feat: tablet landscape improvements

Shell: move Projects/News/Calendar into ShellRoute so the NavigationRail
persists across all screens. Show all 6 nav destinations on tablet
instead of 3+More overflow. Phone bottom nav unchanged.

Chat: master-detail layout on tablet — conversations list (320px) with
inline chat panel. Tapping a conversation updates state instead of
pushing a new route.

Knowledge: responsive grid (2 cols portrait, 3 cols landscape) with
card layout showing icon, title, body preview, and tags. Fix snippet
data — read json['snippet'] which the API actually sends. Bump snippet
length from 120 to 200 chars. Tasks now show description as snippet.

News: responsive grid with the same breakpoints. Larger snippet
(5 lines) in grid mode via snippetMaxLines parameter.

Briefing: centered reading column (maxWidth 700) on wide screens,
matching the web UI layout.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-16 01:31:52 -04:00
parent bdaa5210f0
commit 58d4cfab4d
8 changed files with 346 additions and 125 deletions
+35 -29
View File
@@ -159,20 +159,20 @@ final routerProvider = Provider<GoRouter>((ref) {
path: Routes.conversations,
builder: (_, _) => const ConversationsTabScreen(),
),
GoRoute(
path: Routes.projects,
builder: (_, _) => const ProjectsScreen(),
),
GoRoute(
path: Routes.news,
builder: (_, _) => const NewsScreen(),
),
GoRoute(
path: Routes.calendar,
builder: (_, _) => const CalendarScreen(),
),
],
),
GoRoute(
path: Routes.projects,
builder: (_, _) => const ProjectsScreen(),
),
GoRoute(
path: Routes.news,
builder: (_, _) => const NewsScreen(),
),
GoRoute(
path: Routes.calendar,
builder: (_, _) => const CalendarScreen(),
),
],
);
});
@@ -190,6 +190,9 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
Routes.briefing,
Routes.knowledge,
Routes.conversations,
Routes.projects,
Routes.news,
Routes.calendar,
];
// Minimum gap between app-resume refreshes to avoid hammering the server.
@@ -255,6 +258,10 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
ref.read(knowledgeProvider.notifier).refresh();
case 2:
ref.read(conversationsProvider.notifier).refresh();
case 4:
ref.read(newsProvider.notifier).refresh();
case 5:
ref.read(calendarProvider.notifier).refresh();
}
}
@@ -271,11 +278,6 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
for (var i = 0; i < _tabs.length; i++) {
if (location.startsWith(_tabs[i])) return i;
}
if (location.startsWith(Routes.projects) ||
location.startsWith(Routes.news) ||
location.startsWith(Routes.calendar)) {
return 3;
}
return 0;
}
@@ -394,7 +396,7 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
final index = _tabIndex(location);
// Refresh the incoming tab's data when switching between shell tabs.
if (_prevTabIndex != null && _prevTabIndex != index && index < 3) {
if (_prevTabIndex != null && _prevTabIndex != index) {
WidgetsBinding.instance.addPostFrameCallback((_) => _refreshTab(index));
}
_prevTabIndex = index;
@@ -413,13 +415,7 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
children: [
NavigationRail(
selectedIndex: index,
onDestinationSelected: (i) {
if (i == 3) {
_showMoreSheet(context);
} else {
context.go(_tabs[i]);
}
},
onDestinationSelected: (i) => context.go(_tabs[i]),
labelType: NavigationRailLabelType.all,
destinations: const [
NavigationRailDestination(
@@ -438,9 +434,19 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
label: Text('Chat'),
),
NavigationRailDestination(
icon: Icon(Icons.more_horiz_outlined),
selectedIcon: Icon(Icons.more_horiz),
label: Text('More'),
icon: Icon(Icons.folder_outlined),
selectedIcon: Icon(Icons.folder),
label: Text('Projects'),
),
NavigationRailDestination(
icon: Icon(Icons.newspaper_outlined),
selectedIcon: Icon(Icons.newspaper),
label: Text('News'),
),
NavigationRailDestination(
icon: Icon(Icons.calendar_month_outlined),
selectedIcon: Icon(Icons.calendar_month),
label: Text('Calendar'),
),
],
),
@@ -469,7 +475,7 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
],
),
bottomNavigationBar: NavigationBar(
selectedIndex: index,
selectedIndex: index >= 3 ? 3 : index,
onDestinationSelected: (i) {
if (i == 3) {
_showMoreSheet(context);