From 6e02cce84f899143457e9ba78e382e1234c02ecb Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Fri, 5 Jun 2026 21:23:06 -0400 Subject: [PATCH 1/2] WIP subspace support --- lib/controllers/spaces_controller.dart | 2 + lib/models/space.dart | 2 + lib/models/subspace.dart | 10 +++++ lib/widgets/join_dialog.dart | 12 ++++-- lib/widgets/sidebar.dart | 53 +++++++++++++++----------- 5 files changed, 54 insertions(+), 25 deletions(-) create mode 100644 lib/models/subspace.dart diff --git a/lib/controllers/spaces_controller.dart b/lib/controllers/spaces_controller.dart index 548ff20..5c57d3a 100644 --- a/lib/controllers/spaces_controller.dart +++ b/lib/controllers/spaces_controller.dart @@ -103,12 +103,14 @@ class SpacesController extends Notifier> { title: "Home", icon: Icons.home, children: homeRooms, + subSpaces: .new(), ), .new( id: "dms", title: "Direct Messages", icon: Icons.people, children: dmRooms, + subSpaces: .new(), ), ...topLevelSpacesList, ] diff --git a/lib/models/space.dart b/lib/models/space.dart index 631759a..73fbbc6 100644 --- a/lib/models/space.dart +++ b/lib/models/space.dart @@ -2,6 +2,7 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter/widgets.dart"; import "package:freezed_annotation/freezed_annotation.dart"; import "package:nexus/models/room.dart"; +import "package:nexus/models/subspace.dart"; part "space.freezed.dart"; @freezed @@ -12,5 +13,6 @@ abstract class Space with _$Space { IconData? icon, Room? room, required IList children, + required IList subSpaces, }) = _Space; } diff --git a/lib/models/subspace.dart b/lib/models/subspace.dart new file mode 100644 index 0000000..1a1879c --- /dev/null +++ b/lib/models/subspace.dart @@ -0,0 +1,10 @@ +import "package:fast_immutable_collections/fast_immutable_collections.dart"; +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/room.dart"; +part "subspace.freezed.dart"; + +@freezed +abstract class Subspace with _$Subspace { + const factory Subspace({required Room room, required IList children}) = + _Subspace; +} diff --git a/lib/widgets/join_dialog.dart b/lib/widgets/join_dialog.dart index d265595..d420dea 100644 --- a/lib/widgets/join_dialog.dart +++ b/lib/widgets/join_dialog.dart @@ -84,9 +84,15 @@ class JoinDialog extends HookWidget { space?.id ?? spaces .firstWhere( - (space) => space.children.any( - (child) => child.metadata?.id == id, - ), + (space) => + space.children.any( + (child) => + child.metadata?.id == id, + ) || + space.subSpaces.any( + (child) => + child.room.metadata?.id == id, + ), ) .id, ); diff --git a/lib/widgets/sidebar.dart b/lib/widgets/sidebar.dart index 6fb4780..02cac3d 100644 --- a/lib/widgets/sidebar.dart +++ b/lib/widgets/sidebar.dart @@ -1,9 +1,11 @@ import "package:collection/collection.dart"; +import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter/material.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:navigation_rail_m3e/navigation_rail_m3e.dart"; import "package:nexus/controllers/key_controller.dart"; import "package:nexus/controllers/spaces_controller.dart"; +import "package:nexus/models/room.dart"; import "package:nexus/widgets/avatar_or_hash.dart"; import "package:nexus/widgets/join_dialog.dart"; import "package:nexus/widgets/room_menu.dart"; @@ -43,6 +45,27 @@ class Sidebar extends HookConsumerWidget { ? null : indexOfSelectedRoom; + List roomsToDestinations(IList rooms) => + rooms + .map( + (room) => NavigationRailM3EDestination( + label: room.metadata?.name ?? "Unnamed Room", + badgeCount: switch (room.metadata?.unreadNotifications) { + 0 || null => room.metadata?.unreadMessages == 0 ? null : 0, + int unread => unread, + }, + icon: AvatarOrHash( + room.metadata?.avatar, + room.metadata?.name ?? "Unnamed Room", + fallback: selectedSpaceId == "dms" + ? null + : Icon(Icons.numbers), + // space.client.headers, + ), + ), + ) + .toList(); + return Drawer( width: 340, shape: Border(), @@ -189,29 +212,15 @@ class Sidebar extends HookConsumerWidget { selectedIndex: selectedRoomIndex ?? 0, sections: [ .new( - destinations: selectedSpace.children - .map( - (room) => NavigationRailM3EDestination( - label: room.metadata?.name ?? "Unnamed Room", - badgeCount: switch (room - .metadata - ?.unreadNotifications) { - 0 || null => - room.metadata?.unreadMessages == 0 ? null : 0, - int unread => unread, - }, - icon: AvatarOrHash( - room.metadata?.avatar, - room.metadata?.name ?? "Unnamed Room", - fallback: selectedSpaceId == "dms" - ? null - : Icon(Icons.numbers), - // space.client.headers, - ), - ), - ) - .toList(), + destinations: roomsToDestinations(selectedSpace.children), ), + for (final subSpace in selectedSpace.subSpaces) + .new( + header: Text( + subSpace.room.metadata?.name ?? "Unnamed Room", + ), + destinations: roomsToDestinations(subSpace.children), + ), ], onDestinationSelected: (value) { selectedRoomIdNotifier.set( From 5f9622e1c95147cb09651180f9401dff31e67640 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Fri, 5 Jun 2026 21:39:51 -0400 Subject: [PATCH 2/2] try to fix android build --- lib/controllers/spaces_controller.dart | 1 + lib/main.dart | 2 +- linux/flutter/generated_plugin_registrant.cc | 4 ---- linux/flutter/generated_plugins.cmake | 1 - pubspec.lock | 10 +--------- pubspec.yaml | 2 +- windows/flutter/generated_plugin_registrant.cc | 3 --- windows/flutter/generated_plugins.cmake | 1 - 8 files changed, 4 insertions(+), 20 deletions(-) diff --git a/lib/controllers/spaces_controller.dart b/lib/controllers/spaces_controller.dart index 5c57d3a..26e1487 100644 --- a/lib/controllers/spaces_controller.dart +++ b/lib/controllers/spaces_controller.dart @@ -88,6 +88,7 @@ class SpacesController extends Notifier> { final children = childRoomsBySpaceId[id] ?? .new(); return Space( + subSpaces: const IList.empty(), // TODO id: id, title: room.metadata?.name ?? "Unnamed Room", room: room, diff --git a/lib/main.dart b/lib/main.dart index dab4e16..a8d8499 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,5 @@ import "dart:io"; +import "package:dynamic_color/dynamic_color.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter/foundation.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; @@ -17,7 +18,6 @@ import "package:nexus/widgets/error_dialog.dart"; import "package:nexus/widgets/loading.dart"; import "package:window_manager/window_manager.dart"; import "package:flutter/material.dart"; -import "package:dynamic_system_colors/dynamic_system_colors.dart"; final GlobalKey navigatorKey = GlobalKey(); diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index d126d18..755a54e 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,7 +7,6 @@ #include "generated_plugin_registrant.h" #include -#include #include #include #include @@ -19,9 +18,6 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) dynamic_color_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); - g_autoptr(FlPluginRegistrar) dynamic_system_colors_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); - dynamic_color_plugin_register_with_registrar(dynamic_system_colors_registrar); g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); file_selector_plugin_register_with_registrar(file_selector_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 89af22f..b9ca03c 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,7 +4,6 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color - dynamic_system_colors file_selector_linux media_kit_libs_linux media_kit_video diff --git a/pubspec.lock b/pubspec.lock index 7d2e875..999644a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -282,7 +282,7 @@ packages: source: hosted version: "2.1.2" dynamic_color: - dependency: transitive + dependency: "direct main" description: name: dynamic_color sha256: "43a5a6679649a7731ab860334a5812f2067c2d9ce6452cf069c5e0c25336c17c" @@ -297,14 +297,6 @@ packages: url: "https://pub.dev" source: hosted version: "0.0.7" - dynamic_system_colors: - dependency: "direct main" - description: - name: dynamic_system_colors - sha256: "6cda994363fe362e3c433e068af83feffc2c9a26ba0be7ecdb2b96f676d2dfd8" - url: "https://pub.dev" - source: hosted - version: "1.9.0" emoji_text_field: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 815eea3..7c95a5a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -33,7 +33,7 @@ dependencies: image_picker: 1.2.2 file_picker: 11.0.2 path: 1.9.1 - dynamic_system_colors: 1.9.0 + dynamic_color: 1.8.1 collection: 1.19.1 window_manager: 0.5.1 color_hash: 1.0.1 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index b507c00..7938787 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,7 +7,6 @@ #include "generated_plugin_registrant.h" #include -#include #include #include #include @@ -16,8 +15,6 @@ #include void RegisterPlugins(flutter::PluginRegistry* registry) { - DynamicColorPluginCApiRegisterWithRegistrar( - registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); DynamicColorPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("DynamicColorPluginCApi")); FileSelectorWindowsRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index b26701d..64ef5b5 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,7 +4,6 @@ list(APPEND FLUTTER_PLUGIN_LIST dynamic_color - dynamic_system_colors file_selector_windows media_kit_libs_windows_video media_kit_video