From 77d9f9bdc12f96688a0cf90a27effa06cf39a273 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Thu, 22 Jan 2026 17:05:59 +0000 Subject: [PATCH] wip go --- analysis_options.yaml | 1 + devtools_options.yaml | 3 - flake.nix | 7 +- hook/build.dart | 111 +++++++++++++++++++++++++ lib/controllers/client_controller.dart | 27 ++++-- pubspec.lock | 43 ++++++++-- pubspec.yaml | 9 +- 7 files changed, 179 insertions(+), 22 deletions(-) delete mode 100644 devtools_options.yaml create mode 100644 hook/build.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index c2aaaa0..a8b1078 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,6 +1,7 @@ analyzer: errors: invalid_annotation_target: ignore + avoid_print: ignore exclude: - "build/**" - "**/*.g.dart" diff --git a/devtools_options.yaml b/devtools_options.yaml deleted file mode 100644 index fa0b357..0000000 --- a/devtools_options.yaml +++ /dev/null @@ -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: diff --git a/flake.nix b/flake.nix index 027db59..0d380af 100644 --- a/flake.nix +++ b/flake.nix @@ -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; diff --git a/hook/build.dart b/hook/build.dart new file mode 100644 index 0000000..a8f43b3 --- /dev/null +++ b/hook/build.dart @@ -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 main(List 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(); +}); diff --git a/lib/controllers/client_controller.dart b/lib/controllers/client_controller.dart index 9f69e8f..13bc0eb 100644 --- a/lib/controllers/client_controller.dart +++ b/lib/controllers/client_controller.dart @@ -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 command, int requestId, GomuksBuffer data) { + // Convert the C string to Dart + final cmdStr = command.cast().toDartString(); + print("Received event: $cmdStr (requestId=$requestId)"); + + // Optionally inspect 'data' if you need +} + class ClientController extends AsyncNotifier { @override bool updateShouldNotify( @@ -22,7 +31,15 @@ class ClientController extends AsyncNotifier { @override Future build() async { - if (!vod.isInitialized()) fl_vod.init(); + final handle = GomuksInit(); + + GomuksStart( + handle, + Pointer.fromFunction, Int64, GomuksBuffer)>( + gomuksCallback, + ), + ); + final client = Client( "nexus", logLevel: kReleaseMode ? Level.warning : Level.verbose, @@ -33,10 +50,6 @@ class ClientController extends AsyncNotifier { "nexus", database: await ref.watch(DatabaseController.provider.future), ), - nativeImplementations: NativeImplementationsIsolate( - compute, - vodozemacInit: fl_vod.init, - ), ); final backupJson = await ref diff --git a/pubspec.lock b/pubspec.lock index 01d55a5..49a2fc3 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -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 diff --git a/pubspec.yaml b/pubspec.yaml index e733f2e..0e9adce 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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