show badges totaled in more areas
This commit is contained in:
parent
d37ec2878b
commit
66a437094a
6 changed files with 79 additions and 22 deletions
16
lib/widgets/count_badge.dart
Normal file
16
lib/widgets/count_badge.dart
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
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),
|
||||
};
|
||||
}
|
||||
|
|
@ -3,8 +3,10 @@ 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,
|
||||
|
|
@ -49,7 +51,14 @@ final class const RoomAppbar({
|
|||
dimension: 24,
|
||||
fallback: Icon(Icons.numbers),
|
||||
)
|
||||
: DrawerButton(onPressed: onOpenDrawer),
|
||||
: IconButton(
|
||||
onPressed: onOpenDrawer,
|
||||
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
|
||||
icon: CountBadge(
|
||||
Sidebar.totalBadgeCount(ref),
|
||||
child: const DrawerButtonIcon(),
|
||||
),
|
||||
),
|
||||
scrolledUnderElevation: 0,
|
||||
title: room == null
|
||||
? null
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ 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";
|
||||
|
||||
|
|
@ -26,9 +27,26 @@ 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) => null;
|
||||
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;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
|
|
|
|||
|
|
@ -1,23 +1,36 @@
|
|||
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<NavPage>(
|
||||
(page) => switch (page) {
|
||||
.rooms => const RoomList(),
|
||||
.notifications => const NotificationsList(),
|
||||
.invites => const InvitesList(),
|
||||
},
|
||||
);
|
||||
final pages = SidebarPage.values.map(pageFor);
|
||||
|
||||
return Drawer(
|
||||
width: 330,
|
||||
|
|
@ -27,18 +40,17 @@ class const Sidebar({super.key}) extends ConsumerWidget {
|
|||
body: pages.elementAt(selected.index),
|
||||
bottomNavigationBar: NavigationBar(
|
||||
selectedIndex: selected.index,
|
||||
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(),
|
||||
destinations: pages
|
||||
.map(
|
||||
(page) => NavigationDestination(
|
||||
icon: CountBadge(
|
||||
page.badgeCount(ref),
|
||||
child: Icon(page.icon),
|
||||
),
|
||||
label: page.title,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
onDestinationSelected: (index) => ref
|
||||
.read(SidebarPageController.provider.notifier)
|
||||
.set(SidebarPage.values[index]),
|
||||
|
|
|
|||
Loading…
Reference in a new issue