This repository has been archived on 2026-06-02. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
FabledApp/docs/superpowers/specs/2026-04-06-android-nav-restructure-design.md

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:

  1. Nav restructurelib/app.dart
  2. Staleness fixlib/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):
    • /projectsProjectsScreen() (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:

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