diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml deleted file mode 100644 index 8ed63cf..0000000 --- a/.github/workflows/macos.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: "Build MacOS App" - -on: - # TODO: Uncomment this once the MacOS workflow actually works - # push: - # branches: ["main"] - # tags: ["*"] - workflow_dispatch: - -jobs: - build-app: - runs-on: macos-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v6 - with: - submodules: recursive - - - name: Lix GHA Installer Action - uses: samueldr/lix-gha-installer-action@v2026-02-22 - with: - extra_nix_config: experimental-features = nix-command flakes flake-self-attrs - - - name: Build app - run: nix develop --command bash -c "flutter pub get && dart scripts/generate.dart && flutter pub run build_runner build && flutter build macos --release" - - - name: Upload installer artifact - uses: actions/upload-artifact@v6 - with: - name: App - path: build/macos/Build/Products/Release/Nexus.app \ No newline at end of file diff --git a/README.md b/README.md index 57b42d8..d191d6e 100644 --- a/README.md +++ b/README.md @@ -127,16 +127,15 @@ If you want to try out Nexus, grab one of the following artifacts from CI: #### Linux - With Nix: Either use direnv and `direnv allow`, or `nix flake develop` -- Without Nix: Install Flutter, Go, Git, Libclang, Libass, MPV, and Glibc. Do not use any Snap packages, they cause various compilation issues. +- Without Nix: Install Flutter, Go, Git, Libclang, and Glibc. Do not use any Snap packages, they cause various compilation issues. #### Windows You will need: - Flutter +- Android SDK + NDK - Git -- Libass -- MPV - Go - Visual Studio 2022 (Desktop development with C++) - [MSYS2/MinGW-w64 GCC](https://www.msys2.org/) (for CGO) @@ -203,7 +202,7 @@ Development instructions can be found in [DEVELOPMENT.md](./DEVELOPMENT.md). ## Community -Join the [Nexus Client Matrix room](https://matrix.to/#/#nexus:federated.nexus) for questions or help with developing or using Nexus Client. +Join the [Nexus Client Matrix Room](https://matrix.to/#/#nexus:federated.nexus) for questions or help with developing or using Nexus Client. # Credits diff --git a/lib/controllers/attachment.dart b/lib/controllers/attachment.dart index 2a99ee5..e33493e 100644 --- a/lib/controllers/attachment.dart +++ b/lib/controllers/attachment.dart @@ -17,16 +17,18 @@ class AttachmentController extends Notifier<(String, MessageContent?)?> { final filename = basename(file.path); state = (filename, null); - final isEncrypted = ref.read( - RoomsController.provider.select( - (value) => - value[roomId]?.state[EventType.encryption.type]?.isNotEmpty == true, - ), + final room = ref.watch( + RoomsController.provider.select((value) => value[roomId]), ); final content = await ref .watch(ClientController.provider.notifier) - .uploadMedia(.new(path: file.path, encrypt: isEncrypted)); + .uploadMedia( + .new( + path: file.path, + encrypt: room?.state[EventType.encryption.type]?.isNotEmpty == true, + ), + ); state = (filename, content); } diff --git a/lib/controllers/member_list_opened.dart b/lib/controllers/member_list_opened.dart deleted file mode 100644 index e3509f0..0000000 --- a/lib/controllers/member_list_opened.dart +++ /dev/null @@ -1,22 +0,0 @@ -import "package:flutter_riverpod/flutter_riverpod.dart"; -import "package:nexus/controllers/shared_prefs.dart"; - -class MemberListOpenedController extends Notifier { - static const String key = "memberListOpened"; - - @override - bool build() => - ref.watch(SharedPrefsController.provider).requireValue.getBool(key) ?? - true; - - Future set(bool value) async { - final prefs = ref.watch(SharedPrefsController.provider).requireValue; - state = value; - - prefs.setBool(key, value); - } - - static final provider = NotifierProvider( - MemberListOpenedController.new, - ); -} diff --git a/lib/controllers/room_chat.dart b/lib/controllers/room_chat.dart index 3e531bb..558817c 100644 --- a/lib/controllers/room_chat.dart +++ b/lib/controllers/room_chat.dart @@ -125,9 +125,11 @@ class RoomChatController extends AsyncNotifier?> { if (relationType == .edit) { baseContent = relation?.content; } else { - final provider = AttachmentController.provider(roomId); - baseContent = ref.watch(provider)?.$2; - ref.invalidate(provider); + final attachment = ref.watch(AttachmentController.provider(roomId)); + if (attachment != null && attachment.$2 == null) return; + + baseContent = attachment?.$2; + ref.invalidate(AttachmentController.provider(roomId)); } var taggedMessage = text; diff --git a/lib/widgets/composer/composer.dart b/lib/widgets/composer/composer.dart index ca3de8a..c63d939 100644 --- a/lib/widgets/composer/composer.dart +++ b/lib/widgets/composer/composer.dart @@ -59,10 +59,7 @@ class Composer extends HookConsumerWidget { final attachment = ref.watch(AttachmentController.provider(roomId)); void send() { - if (controller.value.text.isEmpty && attachment == null || - attachment != null && attachment.$2 == null) { - return; - } + if (controller.value.text.isEmpty && attachment == null) return; onSend( controller.value.formattedText, shouldMention: shouldMention.value, diff --git a/lib/widgets/renderers/event.dart b/lib/widgets/renderers/event.dart index 2eb8bc3..bcca961 100644 --- a/lib/widgets/renderers/event.dart +++ b/lib/widgets/renderers/event.dart @@ -216,13 +216,10 @@ class EventRenderer extends HookConsumerWidget { if (event.content is! MessageContent) ReactionRow(event), if (event.sendError != null && event.sendError != "not sent") - Padding( - padding: .only(bottom: 4), - child: Text( - event.sendError!, - style: theme.textTheme.labelSmall?.copyWith( - color: theme.colorScheme.error, - ), + Text( + event.sendError!, + style: theme.textTheme.labelSmall?.copyWith( + color: theme.colorScheme.error, ), ), ].map((child) => Padding(padding: .only(left: 4), child: child)), diff --git a/lib/widgets/renderers/message.dart b/lib/widgets/renderers/message.dart index 012dcc9..09ef00b 100644 --- a/lib/widgets/renderers/message.dart +++ b/lib/widgets/renderers/message.dart @@ -286,8 +286,9 @@ class MessageRenderer extends ConsumerWidget { "This message is redacted", style: errorStyle, ) - : Wrap( + : Row( spacing: 8, + mainAxisSize: .min, children: [ Text( "Unknown message type:", diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index b1f29c4..0fdd7c7 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -7,7 +7,6 @@ import "package:measure_size/measure_size.dart"; import "package:nexus/controllers/account_data.dart"; import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client_state.dart"; -import "package:nexus/controllers/member_list_opened.dart"; import "package:nexus/controllers/pinned_ids.dart"; import "package:nexus/controllers/power_level.dart"; import "package:nexus/controllers/rooms.dart"; @@ -47,8 +46,9 @@ class RoomChat extends HookConsumerWidget { final composerSize = useState(64); + final memberListOpened = useState(showMembersByDefault); + final userId = ref.watch(ClientStateController.provider)?.userId; - final memberListOpened = ref.watch(MemberListOpenedController.provider); final theme = Theme.of(context); final nothing = Center( @@ -448,9 +448,7 @@ class RoomChat extends HookConsumerWidget { isDesktop: isDesktop, onOpenDrawer: Scaffold.of(context).openDrawer, onOpenMemberList: (thisContext) { - ref - .watch(MemberListOpenedController.provider.notifier) - .set(!memberListOpened); + memberListOpened.value = !memberListOpened.value; Scaffold.of(thisContext).openEndDrawer(); }, onOpenPinnedMessagesList: () { @@ -555,7 +553,7 @@ class RoomChat extends HookConsumerWidget { ), ), - if (memberListOpened == true && showMembersByDefault) + if (memberListOpened.value == true && showMembersByDefault) MemberList(roomId), ], ), diff --git a/linux/nix/devshell.nix b/linux/nix/devshell.nix index 812082c..ae77467 100644 --- a/linux/nix/devshell.nix +++ b/linux/nix/devshell.nix @@ -18,25 +18,25 @@ let }; in pkgs.mkShell { - packages = - with pkgs; - [ - go - git - jdk17 - libGL - (flutter.override { - extraPkgConfigPackages = [ - mpv-unwrapped - libass - ]; - }) - android.platform-tools - ] - ++ lib.optional pkgs.stdenv.isLinux wayland; + packages = with pkgs; [ + go + git + jdk17 + libGL + wayland + (flutter.override { + extraPkgConfigPackages = [ + mpv-unwrapped + libass + ]; + }) + android.platform-tools + ]; env = rec { LIBCLANG_PATH = lib.makeLibraryPath [ pkgs.libclang ]; + LD_LIBRARY_PATH = "./build/native_assets/linux:${lib.makeLibraryPath [ pkgs.zlib ]}"; + CPATH = lib.makeSearchPath "include" [ pkgs.glibc.dev ]; ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk"; ANDROID_SDK_ROOT = ANDROID_HOME; @@ -44,9 +44,5 @@ pkgs.mkShell { TOOLS = "${ANDROID_HOME}/build-tools/${"36.0.0"}"; GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${TOOLS}/aapt2"; - } - // lib.optionalAttrs pkgs.stdenv.isLinux { - CPATH = lib.makeSearchPath "include" [ pkgs.glibc.dev ]; - LD_LIBRARY_PATH = "./build/native_assets/linux:${lib.makeLibraryPath [ pkgs.zlib ]}"; }; } diff --git a/linux/nix/pkg/default.nix b/linux/nix/pkg/default.nix index c026606..4e00959 100644 --- a/linux/nix/pkg/default.nix +++ b/linux/nix/pkg/default.nix @@ -44,7 +44,7 @@ flutter.buildFlutterApplication { meta = { description = "A simple and user-friendly Matrix client"; mainProgram = "nexus"; - platforms = lib.platforms.unix; + platforms = lib.platforms.linux; maintainers = with lib.maintainers; [ quadradical ]; }; } diff --git a/linux/nix/pkg/gomuks.nix b/linux/nix/pkg/gomuks.nix index 9d7770b..40fe29c 100644 --- a/linux/nix/pkg/gomuks.nix +++ b/linux/nix/pkg/gomuks.nix @@ -1,38 +1,31 @@ { src, - stdenv, buildGoModule, }: -buildGoModule ( - finalAttrs: - let - filename = "libgomuks${stdenv.hostPlatform.extensions.sharedLibrary}"; - in - { - pname = "gomuks-ffi"; - version = "submodule"; +buildGoModule (finalAttrs: { + pname = "gomuks-ffi"; + version = "submodule"; - doCheck = false; + doCheck = false; - src = "${src}/gomuks"; + src = "${src}/gomuks"; - vendorHash = "sha256-4QU51WGiNKYm7z/ajnas2qQaMK5BgyHwPfmNpQvW0qg="; + vendorHash = "sha256-4QU51WGiNKYm7z/ajnas2qQaMK5BgyHwPfmNpQvW0qg="; - buildPhase = '' - runHook preBuild + buildPhase = '' + runHook preBuild - go build -buildmode=c-shared -o ${filename} -tags goolm,noheic,sqlite_fts5 ./pkg/ffi + go build -buildmode=c-shared -o libgomuks.so -tags goolm,noheic,sqlite_fts5 ./pkg/ffi - runHook postBuild - ''; + runHook postBuild + ''; - installPhase = '' - runHook preInstall + installPhase = '' + runHook preInstall - install -Dm0644 ${filename} -t $out/lib + install -Dm0644 libgomuks.so -t $out/lib - runHook postInstall - ''; - } -) + runHook postInstall + ''; +}) diff --git a/scripts/generate.dart b/scripts/generate.dart index c381230..0b0cf7c 100644 --- a/scripts/generate.dart +++ b/scripts/generate.dart @@ -24,18 +24,7 @@ void main(List args) async { ).generate( libclangDylib: libclangPath == null ? null - : Uri.file( - join( - libclangPath, - "libclang.${(Platform.isLinux || Platform.isAndroid) - ? "so" - : Platform.isMacOS - ? "dylib" - : Platform.isWindows - ? "dll" - : throw UnsupportedError("Unsupported Platform")}", - ), - ), + : Uri.file(join(libclangPath, "libclang.so")), ); print("Done!"); }