diff --git a/lib/controllers/client.dart b/lib/controllers/client.dart index cd9fb92..28da24e 100644 --- a/lib/controllers/client.dart +++ b/lib/controllers/client.dart @@ -13,7 +13,6 @@ import "package:nexus/models/capabilities.dart"; import "package:nexus/models/content/message.dart"; import "package:nexus/models/event.dart"; import "package:nexus/models/event_context.dart"; -import "package:nexus/models/mentions_response.dart"; import "package:nexus/models/gomuks_config.dart"; import "package:nexus/models/oauth_auth_code_response.dart"; import "package:nexus/models/open_graph_data.dart"; @@ -215,8 +214,11 @@ class ClientController extends AsyncNotifier { return .new(response?.map((event) => .fromJson(event))); } - Future getMentions(GetMentionsRequest request) async => - .fromJson(await _sendCommand("get_mentions", request.toJson())); + Future> getMentions(GetMentionsRequest request) async => .new( + // TODO: Handle `related_events` + ((await _sendCommand("get_mentions", request.toJson()))["events"] as List) + .map((event) => .fromJson(event)), + ); Future getEvent(GetEventRequest request) async { final json = await _sendCommand("get_event", request.toJson()); diff --git a/lib/controllers/notifications.dart b/lib/controllers/notifications.dart index 4140b66..a9bb89f 100644 --- a/lib/controllers/notifications.dart +++ b/lib/controllers/notifications.dart @@ -43,9 +43,9 @@ class NotificationsController(final NotificationsRequest request) ), ); - storeEvents(mentions.events.addAll(mentions.relatedEvents)); + storeEvents(mentions); - return .new(mentions.events.map((event) => (event.rowId, event.roomId))); + return .new(mentions.map((event) => (event.rowId, event.roomId))); } Future loadOlder() async { @@ -76,12 +76,10 @@ class NotificationsController(final NotificationsRequest request) ), ); - storeEvents( - newNotifications.events.addAll(newNotifications.relatedEvents), - ); + storeEvents(newNotifications); return currentNotifications.addAll( - newNotifications.events.map((event) => (event.rowId, event.roomId)), + newNotifications.map((event) => (event.rowId, event.roomId)), ); }); } diff --git a/lib/helpers/extensions/scheme_to_theme.dart b/lib/helpers/extensions/scheme_to_theme.dart index f9a0521..ac50a09 100644 --- a/lib/helpers/extensions/scheme_to_theme.dart +++ b/lib/helpers/extensions/scheme_to_theme.dart @@ -9,7 +9,6 @@ extension SchemeToTheme on ColorScheme { ).textTheme; return .from(colorScheme: this).copyWith( cardTheme: .new(color: primaryContainer), - badgeTheme: .new(backgroundColor: primary, textColor: onPrimary), popupMenuTheme: .new( shape: RoundedRectangleBorder(borderRadius: .circular(16)), color: surfaceContainerHigh, diff --git a/lib/models/mentions_response.dart b/lib/models/mentions_response.dart deleted file mode 100644 index 27b6d10..0000000 --- a/lib/models/mentions_response.dart +++ /dev/null @@ -1,16 +0,0 @@ -import "package:fast_immutable_collections/fast_immutable_collections.dart"; -import "package:freezed_annotation/freezed_annotation.dart"; -import "package:nexus/models/event.dart"; - -part "mentions_response.freezed.dart"; -part "mentions_response.g.dart"; - -@Freezed(toJson: false, fromJson: false) -@JsonSerializable(createToJson: false) -class const MentionsResponse({ - required final IList events, - final IList relatedEvents = const .empty(), -}) with _$MentionsResponse { - factory MentionsResponse.fromJson(Map json) => - _$MentionsResponseFromJson(json); -} diff --git a/lib/models/nav_page.dart b/lib/models/nav_page.dart index 083ead4..a731de2 100644 --- a/lib/models/nav_page.dart +++ b/lib/models/nav_page.dart @@ -5,6 +5,5 @@ abstract class const NavPage({super.key}) extends Widget { String get title; IconData get icon; - /// Null hides the badge, and 0 shows a dot. int? badgeCount(WidgetRef ref) => null; } diff --git a/lib/widgets/count_badge.dart b/lib/widgets/count_badge.dart deleted file mode 100644 index e0912f8..0000000 --- a/lib/widgets/count_badge.dart +++ /dev/null @@ -1,16 +0,0 @@ -import "package:material_ui/material_ui.dart"; - -/// Shows [count] in a badge on [child]: nothing if null, a dot if 0, and the -/// number otherwise. -class const CountBadge( - final int? count, { - required final Widget child, - super.key, -}) extends StatelessWidget { - @override - Widget build(BuildContext context) => switch (count) { - null => child, - 0 => Badge(child: child), - final count => Badge.count(count: count, child: child), - }; -} diff --git a/lib/widgets/room_appbar.dart b/lib/widgets/room_appbar.dart index 6bbe2a3..3b29129 100644 --- a/lib/widgets/room_appbar.dart +++ b/lib/widgets/room_appbar.dart @@ -3,10 +3,8 @@ import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/controllers/rooms.dart"; import "package:nexus/widgets/appbar.dart"; import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/count_badge.dart"; import "package:nexus/widgets/room_menu_button.dart"; import "package:nexus/widgets/room_summary_dialog.dart"; -import "package:nexus/widgets/sidebar.dart"; final class const RoomAppbar({ required final String? roomId, @@ -51,14 +49,7 @@ final class const RoomAppbar({ dimension: 24, fallback: Icon(Icons.numbers), ) - : IconButton( - onPressed: onOpenDrawer, - tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip, - icon: CountBadge( - Sidebar.totalBadgeCount(ref), - child: const DrawerButtonIcon(), - ), - ), + : DrawerButton(onPressed: onOpenDrawer), scrolledUnderElevation: 0, title: room == null ? null diff --git a/lib/widgets/room_list.dart b/lib/widgets/room_list.dart index 05c1219..7cf5e36 100644 --- a/lib/widgets/room_list.dart +++ b/lib/widgets/room_list.dart @@ -13,7 +13,6 @@ import "package:nexus/widgets/pages/settings.dart"; import "package:nexus/widgets/join_dialog.dart"; import "package:nexus/widgets/room_menu_button.dart"; import "package:nexus/controllers/key.dart"; -import "package:nexus/controllers/rooms.dart"; import "package:nexus/controllers/spaces.dart"; import "package:collection/collection.dart"; @@ -27,26 +26,9 @@ class const RoomList({super.key}) extends ConsumerWidget implements NavPage { @override IconData get icon => Icons.list; + // TODO: Show unread badge here and on sidebar hamburger @override - int? badgeCount(WidgetRef ref) { - final (notifications, hasUnread) = ref.watch( - RoomsController.provider.select( - (rooms) => rooms.values.fold( - (0, false), - (total, room) => ( - total.$1 + (room.metadata?.unreadNotifications ?? 0), - total.$2 || (room.metadata?.unreadMessages ?? 0) > 0, - ), - ), - ), - ); - - return notifications > 0 - ? notifications - : hasUnread - ? 0 - : null; - } + int? badgeCount(WidgetRef ref) => null; @override Widget build(BuildContext context, WidgetRef ref) { diff --git a/lib/widgets/sidebar.dart b/lib/widgets/sidebar.dart index 3ed8daa..4c80802 100644 --- a/lib/widgets/sidebar.dart +++ b/lib/widgets/sidebar.dart @@ -1,36 +1,23 @@ -import "package:collection/collection.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:material_ui/material_ui.dart"; import "package:nexus/controllers/sidebar_page.dart"; import "package:nexus/models/nav_page.dart"; import "package:nexus/models/sidebar_page.dart"; -import "package:nexus/widgets/count_badge.dart"; import "package:nexus/widgets/invites_list.dart"; import "package:nexus/widgets/notifications_list.dart"; import "package:nexus/widgets/room_list.dart"; class const Sidebar({super.key}) extends ConsumerWidget { - static NavPage pageFor(SidebarPage page) => switch (page) { - .rooms => const RoomList(), - .notifications => const NotificationsList(), - .invites => const InvitesList(), - }; - - /// The badges of every tab added together, e.g. for the drawer button. - /// - /// Like [NavPage.badgeCount], null means no badges and 0 means only dots. - static int? totalBadgeCount(WidgetRef ref) { - final counts = SidebarPage.values - .map((page) => pageFor(page).badgeCount(ref)) - .nonNulls; - - return counts.isEmpty ? null : counts.sum; - } - @override Widget build(BuildContext context, WidgetRef ref) { final selected = ref.watch(SidebarPageController.provider); - final pages = SidebarPage.values.map(pageFor); + final pages = SidebarPage.values.map( + (page) => switch (page) { + .rooms => const RoomList(), + .notifications => const NotificationsList(), + .invites => const InvitesList(), + }, + ); return Drawer( width: 330, @@ -40,17 +27,18 @@ class const Sidebar({super.key}) extends ConsumerWidget { body: pages.elementAt(selected.index), bottomNavigationBar: NavigationBar( selectedIndex: selected.index, - destinations: pages - .map( - (page) => NavigationDestination( - icon: CountBadge( - page.badgeCount(ref), - child: Icon(page.icon), - ), - label: page.title, - ), - ) - .toList(), + destinations: pages.map((page) { + final badgeCount = page.badgeCount(ref); + + return NavigationDestination( + icon: Badge.count( + count: badgeCount ?? 0, + isLabelVisible: badgeCount != null, + child: Icon(page.icon), + ), + label: page.title, + ); + }).toList(), onDestinationSelected: (index) => ref .read(SidebarPageController.provider.notifier) .set(SidebarPage.values[index]),