mobile bluesky app made with flutter lazurite.stormlightlabs.org/
mobile bluesky flutter
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

chore: add bottom nav back

+63 -4
+1 -1
ios/Podfile.lock
··· 114 114 wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556 115 115 workmanager: 01be2de7f184bd15de93a1812936a2b7f42ef07e 116 116 117 - PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e 117 + PODFILE CHECKSUM: eacb6976ee55d09dd7976888367ed4eee5f3a1bd 118 118 119 119 COCOAPODS: 1.16.2
+58
lib/core/router/app_shell.dart
··· 4 4 import 'package:go_router/go_router.dart'; 5 5 import 'package:lazurite/features/auth/bloc/auth_bloc.dart'; 6 6 import 'package:lazurite/features/notifications/cubit/unread_count_cubit.dart'; 7 + import 'package:provider/provider.dart'; 7 8 8 9 class AppShellScope extends InheritedWidget { 9 10 const AppShellScope({super.key, required super.child, required this.openMenu}); ··· 53 54 key: _scaffoldKey, 54 55 drawer: _AppMenu(navigationShell: widget.navigationShell, rootContext: context), 55 56 body: widget.navigationShell, 57 + bottomNavigationBar: NavigationBar( 58 + height: 50, 59 + backgroundColor: Theme.of(context).colorScheme.surfaceContainerHighest, 60 + selectedIndex: widget.navigationShell.currentIndex, 61 + onDestinationSelected: (index) { 62 + widget.navigationShell.goBranch(index, initialLocation: index == widget.navigationShell.currentIndex); 63 + }, 64 + indicatorShape: RoundedSuperellipseBorder(borderRadius: BorderRadius.circular(10)), 65 + labelBehavior: NavigationDestinationLabelBehavior.alwaysHide, 66 + destinations: _destinations, 67 + ), 56 68 ), 69 + ); 70 + } 71 + 72 + List<Widget> get _destinations => [ 73 + const NavigationDestination(icon: Icon(Icons.home_outlined), selectedIcon: Icon(Icons.home), label: 'Home'), 74 + const NavigationDestination(icon: Icon(Icons.search_outlined), selectedIcon: Icon(Icons.search), label: 'Search'), 75 + const NavigationDestination( 76 + icon: _NotificationDestinationIcon(selected: false), 77 + selectedIcon: _NotificationDestinationIcon(selected: true), 78 + label: 'Notifications', 79 + ), 80 + const NavigationDestination(icon: Icon(Icons.person_outline), selectedIcon: Icon(Icons.person), label: 'Profile'), 81 + const NavigationDestination( 82 + icon: Icon(Icons.chat_bubble_outline), 83 + selectedIcon: Icon(Icons.chat_bubble), 84 + label: 'Messages', 85 + ), 86 + const NavigationDestination( 87 + icon: Icon(Icons.settings_outlined), 88 + selectedIcon: Icon(Icons.settings), 89 + label: 'Settings', 90 + ), 91 + ]; 92 + } 93 + 94 + class _NotificationDestinationIcon extends StatelessWidget { 95 + const _NotificationDestinationIcon({required this.selected}); 96 + 97 + final bool selected; 98 + 99 + @override 100 + Widget build(BuildContext context) { 101 + final unreadCountCubit = Provider.of<UnreadCountCubit?>(context, listen: false); 102 + if (unreadCountCubit == null) { 103 + return Icon(selected ? Icons.notifications : Icons.notifications_outlined); 104 + } 105 + 106 + return BlocBuilder<UnreadCountCubit, UnreadCountState>( 107 + bloc: unreadCountCubit, 108 + builder: (context, state) { 109 + return Badge( 110 + isLabelVisible: state.hasUnread, 111 + label: Text(state.count > 99 ? '99+' : state.count.toString(), style: const TextStyle(fontSize: 10)), 112 + child: Icon(selected ? Icons.notifications : Icons.notifications_outlined), 113 + ); 114 + }, 57 115 ); 58 116 } 59 117 }
+1 -1
pubspec.lock
··· 1017 1017 source: hosted 1018 1018 version: "1.5.2" 1019 1019 provider: 1020 - dependency: transitive 1020 + dependency: "direct main" 1021 1021 description: 1022 1022 name: provider 1023 1023 sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
+1
pubspec.yaml
··· 46 46 dio: ^5.9.2 47 47 gal: ^2.3.2 48 48 permission_handler: ^12.0.1 49 + provider: ^6.1.5+1 49 50 50 51 dev_dependencies: 51 52 flutter_test:
+2 -2
test/core/router/app_router_test.dart
··· 156 156 await tester.scrollUntilVisible(find.text('Log Out'), 200, scrollable: find.byType(Scrollable).last); 157 157 expect(find.text('Log Out'), findsOneWidget); 158 158 159 - await tester.tap(find.text('Profile')); 159 + await tester.tap(find.text('Profile').last); 160 160 await tester.pumpAndSettle(); 161 161 162 162 expect(find.text('River Tam'), findsOneWidget); ··· 164 164 await tester.tap(find.byTooltip('Open menu')); 165 165 await tester.pumpAndSettle(); 166 166 167 - await tester.tap(find.text('Settings')); 167 + await tester.tap(find.text('Settings').last); 168 168 await tester.pumpAndSettle(); 169 169 170 170 expect(find.text('APPEARANCE'), findsOneWidget);