feat(journal): replace briefing surface with journal; remove news/RSS
The backend retired /api/briefing/* and the RSS feature entirely. This
Flutter change mirrors what landed web-side: rename the briefing surface
to journal, repoint at /api/journal/*, and drop the news/RSS UI since
its endpoints no longer exist.
New (mirrors briefing structure with adapted shapes):
- lib/data/api/journal_api.dart — getToday, getDay, getDays, triggerPrep
- lib/data/models/journal_day.dart — {day_date, conversation, messages}
- lib/providers/journal_provider.dart — async notifier, sendReply, polling,
silent refresh, regeneratePrep. Mirrors the briefing notifier 1:1
- lib/widgets/journal_prep_card.dart — adapted briefing_digest_card
- lib/screens/journal/journal_screen.dart — adapted briefing_screen,
weather card preserved (rendered from msg_metadata.sections.weather
on the daily-prep assistant message). News cards / RSS reactions /
article-discuss removed
- lib/screens/journal/journal_history_screen.dart — past days picker
pulls /api/journal/days, drills into /api/journal/day/<iso>
Wiring:
- Routes.briefing → Routes.journal (constants.dart)
- Routes.news removed
- briefingApiProvider → journalApiProvider (api_client_provider.dart)
- newsApiProvider removed
- app.dart: shell tab "Briefing" → "Journal"; News destination removed
from nav rail, bottom nav, and the More sheet
- splash_screen.dart and login_screen.dart: redirect Routes.journal
instead of Routes.briefing
- chat_api.dart: drop openArticleInChat (calls deleted /api/chat/from-article)
- settings_provider.dart: drop rssEnabled getter and rssEnabledProvider
Deleted:
- lib/screens/briefing/ (whole directory)
- lib/screens/news/ (whole directory)
- lib/data/api/briefing_api.dart, news_api.dart
- lib/data/models/briefing_conversation.dart, briefing_feed.dart, news_item.dart
- lib/providers/briefing_provider.dart, news_provider.dart
- lib/widgets/briefing_digest_card.dart, news_card.dart
- test cases for NewsItem and BriefingFeed in test/widget_test.dart
flutter analyze: 0 issues.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+28
-55
@@ -11,15 +11,14 @@ import 'providers/auth_provider.dart';
|
||||
import 'core/exceptions.dart';
|
||||
import 'providers/capture_queue_provider.dart';
|
||||
import 'providers/capture_work_queue_provider.dart';
|
||||
import 'providers/briefing_provider.dart';
|
||||
import 'providers/calendar_provider.dart';
|
||||
import 'providers/chat_provider.dart';
|
||||
import 'providers/journal_provider.dart';
|
||||
import 'providers/knowledge_provider.dart';
|
||||
import 'providers/news_provider.dart';
|
||||
import 'providers/settings_provider.dart';
|
||||
import 'providers/update_provider.dart';
|
||||
import 'screens/auth/login_screen.dart';
|
||||
import 'screens/briefing/briefing_screen.dart';
|
||||
import 'screens/journal/journal_screen.dart';
|
||||
import 'screens/knowledge/knowledge_screen.dart';
|
||||
import 'screens/library/project_tasks_screen.dart';
|
||||
import 'screens/chat/chat_screen.dart';
|
||||
@@ -29,7 +28,6 @@ import 'screens/projects/project_edit_screen.dart';
|
||||
import 'screens/projects/projects_screen.dart';
|
||||
import 'screens/notes/note_edit_screen.dart';
|
||||
import 'screens/settings/settings_screen.dart';
|
||||
import 'screens/news/news_screen.dart';
|
||||
import 'screens/setup/setup_screen.dart';
|
||||
import 'screens/splash/splash_screen.dart';
|
||||
import 'screens/tasks/task_edit_screen.dart';
|
||||
@@ -161,8 +159,8 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
builder: (context, state, child) => _Shell(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: Routes.briefing,
|
||||
builder: (_, _) => const BriefingScreen(),
|
||||
path: Routes.journal,
|
||||
builder: (_, _) => const JournalScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: Routes.knowledge,
|
||||
@@ -176,10 +174,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
path: Routes.projects,
|
||||
builder: (_, _) => const ProjectsScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: Routes.news,
|
||||
builder: (_, _) => const NewsScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: Routes.calendar,
|
||||
builder: (_, _) => const CalendarScreen(),
|
||||
@@ -200,15 +194,14 @@ class _Shell extends ConsumerStatefulWidget {
|
||||
|
||||
class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
|
||||
static const _baseTabs = [
|
||||
Routes.briefing,
|
||||
Routes.journal,
|
||||
Routes.knowledge,
|
||||
Routes.conversations,
|
||||
Routes.projects,
|
||||
];
|
||||
|
||||
List<String> _tabs(bool rssEnabled) => [
|
||||
List<String> _tabs() => [
|
||||
..._baseTabs,
|
||||
if (rssEnabled) Routes.news,
|
||||
Routes.calendar,
|
||||
];
|
||||
|
||||
@@ -232,7 +225,7 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
|
||||
ref.read(updateProvider.notifier).check(repoUrl);
|
||||
}
|
||||
}
|
||||
// Sync device timezone to backend so briefing and chat use local time.
|
||||
// Sync device timezone to backend so journal and chat use local time.
|
||||
_syncTimezone();
|
||||
});
|
||||
}
|
||||
@@ -260,24 +253,20 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
|
||||
void _refreshAll() {
|
||||
ref.read(conversationsProvider.notifier).refresh();
|
||||
ref.read(calendarProvider.notifier).refresh();
|
||||
ref.read(newsProvider.notifier).refresh();
|
||||
ref.read(knowledgeProvider.notifier).refresh();
|
||||
// briefingProvider is an AsyncNotifier family; invalidating is safe
|
||||
// even if no conversation is open — it doesn't cause flicker since
|
||||
// the briefing screen isn't a list view.
|
||||
ref.invalidate(briefingProvider);
|
||||
// journalProvider is an AsyncNotifier; invalidating is safe even if
|
||||
// the journal screen isn't currently mounted.
|
||||
ref.invalidate(journalProvider);
|
||||
}
|
||||
|
||||
/// Refresh only the provider backing the given shell tab route.
|
||||
void _refreshTab(String route) {
|
||||
if (route == Routes.briefing) {
|
||||
ref.invalidate(briefingProvider);
|
||||
if (route == Routes.journal) {
|
||||
ref.invalidate(journalProvider);
|
||||
} else if (route == Routes.knowledge) {
|
||||
ref.read(knowledgeProvider.notifier).refresh();
|
||||
} else if (route == Routes.conversations) {
|
||||
ref.read(conversationsProvider.notifier).refresh();
|
||||
} else if (route == Routes.news) {
|
||||
ref.read(newsProvider.notifier).refresh();
|
||||
} else if (route == Routes.calendar) {
|
||||
ref.read(calendarProvider.notifier).refresh();
|
||||
}
|
||||
@@ -314,15 +303,6 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
|
||||
context.push(Routes.projects);
|
||||
},
|
||||
),
|
||||
if (ref.read(rssEnabledProvider))
|
||||
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'),
|
||||
@@ -360,8 +340,7 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
|
||||
.addPostFrameCallback((_) => _showUpdateSnackbar(next));
|
||||
}
|
||||
});
|
||||
final rssEnabled = ref.watch(rssEnabledProvider);
|
||||
final tabs = _tabs(rssEnabled);
|
||||
final tabs = _tabs();
|
||||
final location = GoRouterState.of(context).matchedLocation;
|
||||
final index = _tabIndex(location, tabs);
|
||||
|
||||
@@ -389,34 +368,28 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
|
||||
selectedIndex: index,
|
||||
onDestinationSelected: (i) => context.go(tabs[i]),
|
||||
labelType: NavigationRailLabelType.all,
|
||||
destinations: [
|
||||
const NavigationRailDestination(
|
||||
icon: Icon(Icons.wb_sunny_outlined),
|
||||
selectedIcon: Icon(Icons.wb_sunny),
|
||||
label: Text('Briefing'),
|
||||
),
|
||||
const NavigationRailDestination(
|
||||
destinations: const [
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.menu_book_outlined),
|
||||
selectedIcon: Icon(Icons.menu_book),
|
||||
label: Text('Journal'),
|
||||
),
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.lightbulb_outline),
|
||||
selectedIcon: Icon(Icons.lightbulb),
|
||||
label: Text('Knowledge'),
|
||||
),
|
||||
const NavigationRailDestination(
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.chat_bubble_outline),
|
||||
selectedIcon: Icon(Icons.chat_bubble),
|
||||
label: Text('Chat'),
|
||||
),
|
||||
const NavigationRailDestination(
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.folder_outlined),
|
||||
selectedIcon: Icon(Icons.folder),
|
||||
label: Text('Projects'),
|
||||
),
|
||||
if (ref.watch(rssEnabledProvider))
|
||||
const NavigationRailDestination(
|
||||
icon: Icon(Icons.newspaper_outlined),
|
||||
selectedIcon: Icon(Icons.newspaper),
|
||||
label: Text('News'),
|
||||
),
|
||||
const NavigationRailDestination(
|
||||
NavigationRailDestination(
|
||||
icon: Icon(Icons.calendar_month_outlined),
|
||||
selectedIcon: Icon(Icons.calendar_month),
|
||||
label: Text('Calendar'),
|
||||
@@ -458,14 +431,14 @@ class _ShellState extends ConsumerState<_Shell> with WidgetsBindingObserver {
|
||||
}
|
||||
},
|
||||
destinations: const [
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.wb_sunny_outlined),
|
||||
selectedIcon: Icon(Icons.wb_sunny),
|
||||
label: 'Briefing',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.menu_book_outlined),
|
||||
selectedIcon: Icon(Icons.menu_book),
|
||||
label: 'Journal',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.lightbulb_outline),
|
||||
selectedIcon: Icon(Icons.lightbulb),
|
||||
label: 'Knowledge',
|
||||
),
|
||||
NavigationDestination(
|
||||
|
||||
Reference in New Issue
Block a user