docs: add Android nav restructure + projects staleness fix spec
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
# 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:
|
||||
|
||||
1. **Nav restructure** — `lib/app.dart`
|
||||
2. **Staleness fix** — `lib/screens/library/project_tasks_screen.dart`
|
||||
|
||||
---
|
||||
|
||||
## Design Details
|
||||
|
||||
### 1. Nav Restructure (`lib/app.dart`)
|
||||
|
||||
**Route changes:**
|
||||
- Remove `/projects` from the `ShellRoute` routes list.
|
||||
- Add three new top-level `GoRoute` entries (alongside the existing non-shell routes):
|
||||
- `/projects` → `ProjectsScreen()` (moved from shell)
|
||||
- `/news` → stub `Scaffold(body: Center(child: Text('News — coming soon')))`
|
||||
- `/calendar` → stub `Scaffold(body: Center(child: Text('Calendar — coming soon')))`
|
||||
- Add route constants to `lib/core/constants.dart`: `news = '/news'`, `calendar = '/calendar'`
|
||||
|
||||
**Shell tab list:**
|
||||
```dart
|
||||
static const _tabs = [
|
||||
Routes.briefing,
|
||||
Routes.knowledge,
|
||||
Routes.conversations,
|
||||
];
|
||||
```
|
||||
(3 entries — "More" is index 3 but handled specially, not a route)
|
||||
|
||||
**`_tabIndex()` update:**
|
||||
```dart
|
||||
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`):**
|
||||
```dart
|
||||
onDestinationSelected: (i) {
|
||||
if (i == 3) {
|
||||
_showMoreSheet(context);
|
||||
} else {
|
||||
context.go(_tabs[i]);
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
**`_showMoreSheet` method on `_ShellState`:**
|
||||
```dart
|
||||
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):**
|
||||
```dart
|
||||
context.push(Routes.taskEdit.replaceFirst(':id', '${task.id}'));
|
||||
```
|
||||
|
||||
**Fixed:**
|
||||
```dart
|
||||
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
|
||||
Reference in New Issue
Block a user