This commit is contained in:
Henry Hiles 2026-01-22 17:05:59 +00:00
commit 2996074838
No known key found for this signature in database
7 changed files with 179 additions and 22 deletions

View file

@ -1,6 +1,7 @@
analyzer:
errors:
invalid_annotation_target: ignore
avoid_print: ignore
exclude:
- "build/**"
- "**/*.g.dart"

View file

@ -1,3 +0,0 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:

View file

@ -32,6 +32,7 @@
_module.args.pkgs = import nixpkgs {
inherit system;
config = {
permittedInsecurePackages = [ "olm-3.2.16" ];
android_sdk.accept_license = true;
allowUnfree = true;
};
@ -44,7 +45,11 @@
pkgs.mkShell {
packages = with pkgs; [
# jdk17
go
olm
git
cargo
clang
(flutter.override { extraPkgConfigPackages = [ pkgs.libsecret ]; })
# android.platform-tools
@ -56,7 +61,7 @@
pkgs.lib.makeLibraryPath ([
pkgs.sqlite
])
}:./build/linux/x64/debug/plugins/flutter_vodozemac";
}:./.dart_tool/hooks_runner/shared/nexus/build/gomuks";
# ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk";
# ANDROID_SDK_ROOT = ANDROID_HOME;

111
hook/build.dart Normal file
View file

@ -0,0 +1,111 @@
import "dart:io";
import "package:hooks/hooks.dart";
import "package:code_assets/code_assets.dart";
import "package:path/path.dart";
import "package:ffigen/ffigen.dart";
Future<void> main(List<String> args) => build(args, (input, output) async {
final targetOS = input.config.code.targetOS;
final targetArch = input.config.code.targetArchitecture;
String libFileName;
switch (targetOS) {
case OS.linux:
libFileName = "libgomuks.so";
break;
case OS.macOS:
libFileName = "libgomuks.dylib";
break;
case OS.windows:
libFileName = "libgomuks.dll";
break;
default:
throw UnsupportedError("Unsupported OS: $targetOS");
}
// Where we put the Gomuks repo and compiled library
final buildDir = Directory.fromUri(
input.outputDirectoryShared.resolve("gomuks/"),
);
if (!await buildDir.exists()) await buildDir.create(recursive: true);
final repoDir = Directory(join(buildDir.path, "source"));
bool skipBuild = false;
final generatedSourcePath = "src/third_party/gomuks.g.dart";
final generatedLibPath = input.packageRoot.resolve(
join("lib", generatedSourcePath),
);
final bindingsFile = File(generatedLibPath.toFilePath());
if (await bindingsFile.exists() &&
await File(join(buildDir.path, libFileName)).exists() &&
await repoDir.exists()) {
final result = await Process.run("git", [
"fetch",
"--dry-run",
], workingDirectory: repoDir.path);
if ((result.stdout as String).trim().isEmpty) {
skipBuild = true;
}
}
if (skipBuild) {
return print(
"Gomuks build skipped: bindings and library exist and repo is up to date.",
);
}
if (await repoDir.exists()) await repoDir.delete(recursive: true);
print("Cloning Gomuks repository...");
final cloneResult = await Process.run("git", [
"clone",
"--depth",
"1",
"--branch",
"tulir/ffi",
"https://mau.dev/gomuks/gomuks",
repoDir.path,
]);
if (cloneResult.exitCode != 0) {
throw Exception(
"Failed to clone Gomuks repository: \n${cloneResult.stderr}",
);
}
final libFile = File(join(buildDir.path, libFileName));
print("Building Gomuks shared library for $targetOS/$targetArch...");
final result = await Process.run("go", [
"build",
"-o",
libFile.path,
"-buildmode=c-shared",
], workingDirectory: join(repoDir.path, "pkg/ffi"));
if (result.exitCode != 0) {
throw Exception("Failed to build Gomuks shared library\n${result.stderr}");
}
// Add the library as a code asset so Dart can find it
output.assets.code.add(
CodeAsset(
package: "nexus",
name: "src/third_party/gomuks.g.dart",
linkMode: DynamicLoadingBundled(),
file: libFile.uri,
),
);
output.dependencies.add(libFile.uri);
print("Generating FFI Bindings...");
FfiGenerator(
output: Output(dartFile: generatedLibPath),
headers: Headers(
entryPoints: [File(join(buildDir.path, "libgomuks.h")).uri],
),
functions: Functions.includeAll,
).generate();
});

View file

@ -1,15 +1,24 @@
import "dart:convert";
import "dart:ffi";
import "dart:io";
import "package:ffi/ffi.dart";
import "package:flutter/foundation.dart";
import "package:matrix/encryption.dart";
import "package:nexus/controllers/database_controller.dart";
import "package:vodozemac/vodozemac.dart" as vod;
import "package:flutter_vodozemac/flutter_vodozemac.dart" as fl_vod;
import "package:nexus/src/third_party/gomuks.g.dart";
import "package:matrix/matrix.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/secure_storage_controller.dart";
import "package:nexus/models/session_backup.dart";
void gomuksCallback(Pointer<Char> command, int requestId, GomuksBuffer data) {
// Convert the C string to Dart
final cmdStr = command.cast<Utf8>().toDartString();
print("Received event: $cmdStr (requestId=$requestId)");
// Optionally inspect 'data' if you need
}
class ClientController extends AsyncNotifier<Client> {
@override
bool updateShouldNotify(
@ -22,7 +31,15 @@ class ClientController extends AsyncNotifier<Client> {
@override
Future<Client> build() async {
if (!vod.isInitialized()) fl_vod.init();
final handle = GomuksInit();
GomuksStart(
handle,
Pointer.fromFunction<Void Function(Pointer<Char>, Int64, GomuksBuffer)>(
gomuksCallback,
),
);
final client = Client(
"nexus",
logLevel: kReleaseMode ? Level.warning : Level.verbose,
@ -33,10 +50,6 @@ class ClientController extends AsyncNotifier<Client> {
"nexus",
database: await ref.watch(DatabaseController.provider.future),
),
nativeImplementations: NativeImplementationsIsolate(
compute,
vodozemacInit: fl_vod.init,
),
);
final backupJson = await ref

View file

@ -217,6 +217,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.2"
code_assets:
dependency: "direct main"
description:
name: code_assets
sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
code_builder:
dependency: transitive
description:
@ -394,13 +402,21 @@ packages:
source: hosted
version: "11.1.0"
ffi:
dependency: transitive
dependency: "direct main"
description:
name: ffi
sha256: d07d37192dbf97461359c1518788f203b0c9102cfd2c35a716b823741219542c
url: "https://pub.dev"
source: hosted
version: "2.1.5"
ffigen:
dependency: "direct main"
description:
name: ffigen
sha256: b7803707faeec4ce3c1b0c2274906504b796e3b70ad573577e72333bd1c9b3ba
url: "https://pub.dev"
source: hosted
version: "20.1.1"
file:
dependency: transitive
description:
@ -728,6 +744,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.2"
hooks:
dependency: "direct main"
description:
name: hooks
sha256: "5d309c86e7ce34cd8e37aa71cb30cb652d3829b900ab145e4d9da564b31d59f7"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
hooks_riverpod:
dependency: "direct main"
description:
@ -1160,6 +1184,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
quiver:
dependency: transitive
description:
name: quiver
sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2
url: "https://pub.dev"
source: hosted
version: "3.2.2"
random_string:
dependency: transitive
description:
@ -1672,11 +1704,10 @@ packages:
vodozemac:
dependency: "direct main"
description:
path: dart
ref: "krille/use-specced-olm-session-config"
resolved-ref: "8770e0555b1bb692e3e1a43a7726b27eae285b20"
url: "https://github.com/famedly/dart-vodozemac"
source: git
name: vodozemac
sha256: "39144e20740807731871c9248d811ed5a037b21d0aa9ffcfa630954de74139d9"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
watcher:
dependency: transitive

View file

@ -12,11 +12,6 @@ environment:
sdk: "^3.9.2"
dependency_overrides:
vodozemac:
git:
url: https://github.com/famedly/dart-vodozemac
ref: krille/use-specced-olm-session-config
path: dart
analyzer: ^8.4.0
source_gen: ^4.0.2
flutter_hooks: ^0.21.2
@ -74,6 +69,10 @@ dependencies:
dynamic_polls: ^0.0.6
flutter_hooks: ^0.21.3+1
cross_cache: ^1.1.0
ffi: ^2.1.5
hooks: ^1.0.0
code_assets: ^1.0.0
ffigen: ^20.1.1
dev_dependencies:
build_runner: ^2.4.11