Keep original bottom nav, navigate search/notifications inside shell with Threads-style top bar

This commit is contained in:
Patrick Britton 2026-02-06 16:00:07 -06:00
parent 8623596903
commit 858d57b5b2
3 changed files with 67 additions and 146 deletions

View file

@ -21,6 +21,7 @@ import '../screens/discover/discover_screen.dart';
import '../screens/secure_chat/secure_chat_full_screen.dart';
import '../screens/secure_chat/secure_chat_loader_screen.dart';
import '../screens/post/threaded_conversation_screen.dart';
import '../screens/notifications/notifications_screen.dart';
/// App routing config (GoRouter).
class AppRoutes {
@ -93,6 +94,16 @@ class AppRoutes {
GoRoute(
path: homeAlias,
builder: (_, __) => const FeedPersonalScreen(),
routes: [
GoRoute(
path: 'notifications',
builder: (_, __) => const NotificationsScreen(),
),
GoRoute(
path: 'discover',
builder: (_, __) => const DiscoverScreen(),
),
],
),
],
),

View file

@ -256,13 +256,7 @@ class _HomeShellState extends ConsumerState<HomeShell> with WidgetsBindingObserv
IconButton(
icon: Icon(Icons.search, color: AppTheme.navyBlue),
tooltip: 'Discover',
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const DiscoverScreen(),
),
);
},
onPressed: () => context.go('/home/discover'),
),
IconButton(
icon: Consumer(
@ -299,13 +293,7 @@ class _HomeShellState extends ConsumerState<HomeShell> with WidgetsBindingObserv
},
),
tooltip: 'Notifications',
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => const NotificationsScreen(),
),
);
},
onPressed: () => context.go('/home/notifications'),
),
const SizedBox(width: 4),
],

View file

@ -6,13 +6,9 @@ import 'package:timeago/timeago.dart' as timeago;
import '../../models/notification.dart';
import '../../providers/api_provider.dart';
import '../../theme/app_theme.dart';
import '../../widgets/app_scaffold.dart';
import '../../widgets/media/signed_media_image.dart';
import '../profile/viewable_profile_screen.dart';
import '../post/post_detail_screen.dart';
import '../search/search_screen.dart';
import '../discover/discover_screen.dart';
import '../secure_chat/secure_chat_full_screen.dart';
import 'package:go_router/go_router.dart';
import '../../services/notification_service.dart';
@ -352,66 +348,68 @@ class _NotificationsScreenState extends ConsumerState<NotificationsScreen> {
}
}
void _navigateHome() {
Navigator.of(context).pop();
}
void _navigateSearch() {
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (_) => const DiscoverScreen()),
);
}
void _navigateChat() {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (_) => const SecureChatFullScreen(),
fullscreenDialog: true,
),
);
}
@override
Widget build(BuildContext context) {
final canArchiveAll = _activeTabIndex == 0 && _notifications.isNotEmpty;
return DefaultTabController(
length: 2,
child: AppScaffold(
title: 'Activity',
leading: const SizedBox.shrink(),
actions: [
if (canArchiveAll)
TextButton(
onPressed: _archiveAllNotifications,
child: Text(
'Archive All',
style: AppTheme.textTheme.labelMedium?.copyWith(
color: AppTheme.egyptianBlue,
fontWeight: FontWeight.w600,
child: Scaffold(
backgroundColor: AppTheme.scaffoldBg,
body: SafeArea(
child: Column(
children: [
// Threads-style top bar
Padding(
padding: const EdgeInsets.only(left: 4, right: 8, top: 4),
child: Row(
children: [
IconButton(
icon: Icon(Icons.arrow_back, color: AppTheme.navyBlue),
onPressed: () => context.go('/home'),
),
Text(
'Activity',
style: AppTheme.textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
const Spacer(),
if (canArchiveAll)
TextButton(
onPressed: _archiveAllNotifications,
child: Text(
'Archive All',
style: AppTheme.textTheme.labelMedium?.copyWith(
color: AppTheme.egyptianBlue,
fontWeight: FontWeight.w600,
),
),
),
],
),
),
),
],
bottom: TabBar(
onTap: (index) {
if (index != _activeTabIndex) {
setState(() {
_activeTabIndex = index;
});
_loadNotifications(refresh: true);
}
},
indicatorColor: AppTheme.egyptianBlue,
labelColor: AppTheme.egyptianBlue,
unselectedLabelColor: AppTheme.egyptianBlue.withOpacity(0.5),
tabs: const [
Tab(text: 'Active'),
Tab(text: 'Archived'),
],
),
bottomNavigationBar: _buildBottomNav(),
body: _error != null
// Filter tabs
TabBar(
onTap: (index) {
if (index != _activeTabIndex) {
setState(() {
_activeTabIndex = index;
});
_loadNotifications(refresh: true);
}
},
indicatorColor: AppTheme.egyptianBlue,
labelColor: AppTheme.egyptianBlue,
unselectedLabelColor: AppTheme.egyptianBlue.withOpacity(0.5),
tabs: const [
Tab(text: 'Active'),
Tab(text: 'Archived'),
],
),
// Content
Expanded(
child: _error != null
? _ErrorState(
message: _error!,
onRetry: () => _loadNotifications(refresh: true),
@ -485,48 +483,6 @@ class _NotificationsScreenState extends ConsumerState<NotificationsScreen> {
},
),
),
),
);
}
Widget _buildBottomNav() {
return Container(
decoration: BoxDecoration(
color: AppTheme.scaffoldBg,
border: Border(
top: BorderSide(
color: AppTheme.egyptianBlue.withOpacity(0.1),
width: 0.5,
),
),
),
child: SafeArea(
top: false,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildNavItem(
icon: Icons.home_outlined,
label: 'Home',
onTap: _navigateHome,
),
_buildNavItem(
icon: Icons.search,
label: 'Discover',
onTap: _navigateSearch,
),
_buildNavItem(
icon: Icons.notifications,
label: 'Activity',
isActive: true,
onTap: () {},
),
_buildNavItem(
icon: Icons.chat_bubble_outline,
label: 'Chat',
onTap: _navigateChat,
),
],
),
@ -534,40 +490,6 @@ class _NotificationsScreenState extends ConsumerState<NotificationsScreen> {
),
);
}
Widget _buildNavItem({
required IconData icon,
required String label,
required VoidCallback onTap,
bool isActive = false,
}) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
icon,
color: isActive ? AppTheme.navyBlue : Colors.grey,
size: 26,
),
const SizedBox(height: 2),
Text(
label,
style: TextStyle(
fontSize: 10,
color: isActive ? AppTheme.navyBlue : Colors.grey,
fontWeight: isActive ? FontWeight.w600 : FontWeight.normal,
),
),
],
),
),
);
}
}
/// Individual notification item widget