4.3 KiB
Android Nav Restructure & Projects Staleness Fix
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Replace the Projects bottom-nav tab with a "More" bottom sheet that houses Projects, News, and Calendar; fix stale task data on the project tasks screen.
Architecture: The shell's 4th nav item becomes a non-routing action — tapping it shows a showModalBottomSheet with the three overflow destinations. _tabIndex() maps /projects, /news, /calendar prefixes to index 3 so the "More" tab highlights correctly. News and Calendar are added as stub push-routes now; their real screens are built in subsequent passes. The staleness fix is a single await + ref.invalidate after returning from task edit.
Tech Stack: Flutter, GoRouter, Riverpod, Material 3 NavigationBar / NavigationRail
Scope
Two independent changes in one pass:
- Nav restructure —
lib/app.dart - Staleness fix —
lib/screens/library/project_tasks_screen.dart
Design Details
1. Nav Restructure (lib/app.dart)
Route changes:
- Remove
/projectsfrom theShellRouteroutes list. - Add three new top-level
GoRouteentries (alongside the existing non-shell routes):/projects→ProjectsScreen()(moved from shell)/news→ stubScaffold(body: Center(child: Text('News — coming soon')))/calendar→ stubScaffold(body: Center(child: Text('Calendar — coming soon')))
- Add route constants to
lib/core/constants.dart:news = '/news',calendar = '/calendar'
Shell tab list:
static const _tabs = [
Routes.briefing,
Routes.knowledge,
Routes.conversations,
];
(3 entries — "More" is index 3 but handled specially, not a route)
_tabIndex() update:
int _tabIndex(String location) {
for (var i = 0; i < _tabs.length; i++) {
if (location.startsWith(_tabs[i])) return i;
}
// Projects, News, Calendar all highlight "More"
if (location.startsWith(Routes.projects) ||
location.startsWith(Routes.news) ||
location.startsWith(Routes.calendar)) return 3;
return 0;
}
onDestinationSelected update (both NavigationBar and NavigationRail):
onDestinationSelected: (i) {
if (i == 3) {
_showMoreSheet(context);
} else {
context.go(_tabs[i]);
}
},
_showMoreSheet method on _ShellState:
void _showMoreSheet(BuildContext context) {
showModalBottomSheet<void>(
context: context,
builder: (_) => SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.folder_outlined),
title: const Text('Projects'),
onTap: () {
Navigator.pop(context);
context.push(Routes.projects);
},
),
ListTile(
leading: const Icon(Icons.newspaper_outlined),
title: const Text('News'),
onTap: () {
Navigator.pop(context);
context.push(Routes.news);
},
),
ListTile(
leading: const Icon(Icons.calendar_month_outlined),
title: const Text('Calendar'),
onTap: () {
Navigator.pop(context);
context.push(Routes.calendar);
},
),
],
),
),
);
}
4th nav destination label: "More" with Icons.more_horiz_outlined / Icons.more_horiz.
NavigationRail note: The wide-layout rail also gets the same 4 destinations and the same intercept on onDestinationSelected.
2. Projects Staleness Fix (lib/screens/library/project_tasks_screen.dart)
Current (line ~321):
context.push(Routes.taskEdit.replaceFirst(':id', '${task.id}'));
Fixed:
await context.push(Routes.taskEdit.replaceFirst(':id', '${task.id}'));
ref.invalidate(projectTasksProvider(widget.projectId));
This re-fetches tasks as soon as the user pops back from the task edit screen, eliminating stale data.
What This Does NOT Include
- Real News screen implementation (separate spec/pass)
- Real Calendar screen implementation (separate spec/pass)
- Any changes to the web frontend