From b91144bee651c3210596280f10e98ccf242c81bb Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 2 Aug 2025 17:32:28 +0100 Subject: [PATCH 1/5] chore: misc --- lib/content_management/view/archived_sources_page.dart | 1 - lib/content_management/view/archived_topics_page.dart | 1 - lib/content_management/view/create_headline_page.dart | 1 - lib/content_management/view/create_source_page.dart | 1 - lib/content_management/view/create_topic_page.dart | 1 - lib/content_management/view/edit_headline_page.dart | 1 - lib/content_management/view/edit_source_page.dart | 1 - lib/content_management/view/edit_topic_page.dart | 1 - pubspec.lock | 2 +- 9 files changed, 1 insertion(+), 9 deletions(-) diff --git a/lib/content_management/view/archived_sources_page.dart b/lib/content_management/view/archived_sources_page.dart index 32f66c19..c8a4f573 100644 --- a/lib/content_management/view/archived_sources_page.dart +++ b/lib/content_management/view/archived_sources_page.dart @@ -45,7 +45,6 @@ class _ArchivedSourcesView extends StatelessWidget { context.read().add( const LoadSourcesRequested(limit: kDefaultRowsPerPage), ); - context.read().add(DashboardSummaryLoaded()); } }, child: BlocBuilder( diff --git a/lib/content_management/view/archived_topics_page.dart b/lib/content_management/view/archived_topics_page.dart index a2f9672f..315ffe03 100644 --- a/lib/content_management/view/archived_topics_page.dart +++ b/lib/content_management/view/archived_topics_page.dart @@ -45,7 +45,6 @@ class _ArchivedTopicsView extends StatelessWidget { context .read() .add(const LoadTopicsRequested(limit: kDefaultRowsPerPage)); - context.read().add( DashboardSummaryLoaded()); } }, child: BlocBuilder( diff --git a/lib/content_management/view/create_headline_page.dart b/lib/content_management/view/create_headline_page.dart index eab8a59b..ecc66f8f 100644 --- a/lib/content_management/view/create_headline_page.dart +++ b/lib/content_management/view/create_headline_page.dart @@ -89,7 +89,6 @@ class _CreateHeadlineViewState extends State<_CreateHeadlineView> { // Refresh the list to show the new headline const LoadHeadlinesRequested(limit: kDefaultRowsPerPage), ); - context.read().add(DashboardSummaryLoaded()); context.pop(); } if (state.status == CreateHeadlineStatus.failure) { diff --git a/lib/content_management/view/create_source_page.dart b/lib/content_management/view/create_source_page.dart index 59c96e4d..2f3ef8c6 100644 --- a/lib/content_management/view/create_source_page.dart +++ b/lib/content_management/view/create_source_page.dart @@ -89,7 +89,6 @@ class _CreateSourceViewState extends State<_CreateSourceView> { // Refresh the list to show the new source const LoadSourcesRequested(limit: kDefaultRowsPerPage), ); - context.read().add(DashboardSummaryLoaded()); context.pop(); } if (state.status == CreateSourceStatus.failure) { diff --git a/lib/content_management/view/create_topic_page.dart b/lib/content_management/view/create_topic_page.dart index 80822d2b..6fdac2a9 100644 --- a/lib/content_management/view/create_topic_page.dart +++ b/lib/content_management/view/create_topic_page.dart @@ -86,7 +86,6 @@ class _CreateTopicViewState extends State<_CreateTopicView> { // Refresh the list to show the new topic const LoadTopicsRequested(limit: kDefaultRowsPerPage), ); - context.read().add(DashboardSummaryLoaded()); context.pop(); } if (state.status == CreateTopicStatus.failure) { diff --git a/lib/content_management/view/edit_headline_page.dart b/lib/content_management/view/edit_headline_page.dart index eb2ada1d..2c7dd21f 100644 --- a/lib/content_management/view/edit_headline_page.dart +++ b/lib/content_management/view/edit_headline_page.dart @@ -117,7 +117,6 @@ class _EditHeadlineViewState extends State<_EditHeadlineView> { context.read().add( const LoadHeadlinesRequested(limit: kDefaultRowsPerPage), ); - context.read().add(DashboardSummaryLoaded()); context.pop(); } if (state.status == EditHeadlineStatus.failure) { diff --git a/lib/content_management/view/edit_source_page.dart b/lib/content_management/view/edit_source_page.dart index 1637aa4d..3ef6abaa 100644 --- a/lib/content_management/view/edit_source_page.dart +++ b/lib/content_management/view/edit_source_page.dart @@ -114,7 +114,6 @@ class _EditSourceViewState extends State<_EditSourceView> { context.read().add( const LoadSourcesRequested(limit: kDefaultRowsPerPage), ); - context.read().add(DashboardSummaryLoaded()); context.pop(); } if (state.status == EditSourceStatus.failure) { diff --git a/lib/content_management/view/edit_topic_page.dart b/lib/content_management/view/edit_topic_page.dart index 6cf89486..04c3008b 100644 --- a/lib/content_management/view/edit_topic_page.dart +++ b/lib/content_management/view/edit_topic_page.dart @@ -111,7 +111,6 @@ class _EditTopicViewState extends State<_EditTopicView> { context.read().add( const LoadTopicsRequested(limit: kDefaultRowsPerPage), ); - context.read().add(DashboardSummaryLoaded()); context.pop(); } if (state.status == EditTopicStatus.failure) { diff --git a/pubspec.lock b/pubspec.lock index f6614564..835d2458 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -134,7 +134,7 @@ packages: description: path: "." ref: HEAD - resolved-ref: "5a7bd9f597e98209bc7f5ac897cf64552306c02f" + resolved-ref: d9fbbf33d8bb53724e2dd29d488a0c8eb9cbf6e8 url: "https://github.com/flutter-news-app-full-source-code/data-repository.git" source: git version: "0.0.0" From dfacc136e59b8a61023cfcca389a3079c38b97ce Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 2 Aug 2025 17:45:39 +0100 Subject: [PATCH 2/5] feat: add internal event for dashboard entity updates --- lib/dashboard/bloc/dashboard_event.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/dashboard/bloc/dashboard_event.dart b/lib/dashboard/bloc/dashboard_event.dart index 9b3d391d..ed35cdb4 100644 --- a/lib/dashboard/bloc/dashboard_event.dart +++ b/lib/dashboard/bloc/dashboard_event.dart @@ -10,3 +10,8 @@ sealed class DashboardEvent extends Equatable { /// Event to load the dashboard summary data. final class DashboardSummaryLoaded extends DashboardEvent {} + +/// Internal event triggered when a listened-to entity is updated. +final class _DashboardEntityUpdated extends DashboardEvent { + const _DashboardEntityUpdated(); +} From 1de546962d30a89bc4e34bffd01dbe8f631a529f Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 2 Aug 2025 17:45:45 +0100 Subject: [PATCH 3/5] feat: enhance DashboardBloc to handle entity updates and manage subscriptions --- lib/dashboard/bloc/dashboard_bloc.dart | 31 +++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/dashboard/bloc/dashboard_bloc.dart b/lib/dashboard/bloc/dashboard_bloc.dart index 6047199e..e3ceb63f 100644 --- a/lib/dashboard/bloc/dashboard_bloc.dart +++ b/lib/dashboard/bloc/dashboard_bloc.dart @@ -1,7 +1,10 @@ +import 'dart:async'; + import 'package:bloc/bloc.dart'; import 'package:core/core.dart'; import 'package:data_repository/data_repository.dart'; import 'package:equatable/equatable.dart'; +import 'package:stream_transform/stream_transform.dart'; part 'dashboard_event.dart'; part 'dashboard_state.dart'; @@ -12,14 +15,36 @@ class DashboardBloc extends Bloc { DashboardBloc({ required DataRepository dashboardSummaryRepository, required DataRepository headlinesRepository, - }) : _dashboardSummaryRepository = dashboardSummaryRepository, - _headlinesRepository = headlinesRepository, - super(const DashboardState()) { + required DataRepository topicsRepository, + required DataRepository sourcesRepository, + }) : _dashboardSummaryRepository = dashboardSummaryRepository, + _headlinesRepository = headlinesRepository, + super(const DashboardState()) { on(_onDashboardSummaryLoaded); + on<_DashboardEntityUpdated>(_onDashboardEntityUpdated); + + _entityUpdatedSubscription = headlinesRepository.entityUpdated + .merge(topicsRepository.entityUpdated) + .merge(sourcesRepository.entityUpdated) + .listen((_) => add(const _DashboardEntityUpdated())); } final DataRepository _dashboardSummaryRepository; final DataRepository _headlinesRepository; + late final StreamSubscription _entityUpdatedSubscription; + + @override + Future close() { + _entityUpdatedSubscription.cancel(); + return super.close(); + } + + void _onDashboardEntityUpdated( + _DashboardEntityUpdated event, + Emitter emit, + ) { + add(DashboardSummaryLoaded()); + } Future _onDashboardSummaryLoaded( DashboardSummaryLoaded event, From f8870b8e926da521b59600d4304a13a9ca5df652 Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 2 Aug 2025 17:45:49 +0100 Subject: [PATCH 4/5] feat: update DashboardBloc initialization to include topics and sources repositories --- lib/app/view/app.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/app/view/app.dart b/lib/app/view/app.dart index 33c261a8..34fdb65f 100644 --- a/lib/app/view/app.dart +++ b/lib/app/view/app.dart @@ -112,9 +112,11 @@ class App extends StatelessWidget { ), BlocProvider( create: (context) => DashboardBloc( - dashboardSummaryRepository: context - .read>(), + dashboardSummaryRepository: + context.read>(), headlinesRepository: context.read>(), + topicsRepository: context.read>(), + sourcesRepository: context.read>(), ), ), ], From a6a49222260a327a8fbf0198f5e18c75d717dd27 Mon Sep 17 00:00:00 2001 From: fulleni Date: Sat, 2 Aug 2025 17:48:55 +0100 Subject: [PATCH 5/5] feat: rename DashboardSummaryLoaded event to DashboardSummaryRequested for clarity --- lib/dashboard/bloc/dashboard_bloc.dart | 14 +++++++------- lib/dashboard/bloc/dashboard_event.dart | 2 +- lib/dashboard/view/dashboard_page.dart | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/dashboard/bloc/dashboard_bloc.dart b/lib/dashboard/bloc/dashboard_bloc.dart index e3ceb63f..cd5a4429 100644 --- a/lib/dashboard/bloc/dashboard_bloc.dart +++ b/lib/dashboard/bloc/dashboard_bloc.dart @@ -17,10 +17,10 @@ class DashboardBloc extends Bloc { required DataRepository headlinesRepository, required DataRepository topicsRepository, required DataRepository sourcesRepository, - }) : _dashboardSummaryRepository = dashboardSummaryRepository, - _headlinesRepository = headlinesRepository, - super(const DashboardState()) { - on(_onDashboardSummaryLoaded); + }) : _dashboardSummaryRepository = dashboardSummaryRepository, + _headlinesRepository = headlinesRepository, + super(const DashboardState()) { + on(_onDashboardSummaryRequested); on<_DashboardEntityUpdated>(_onDashboardEntityUpdated); _entityUpdatedSubscription = headlinesRepository.entityUpdated @@ -43,11 +43,11 @@ class DashboardBloc extends Bloc { _DashboardEntityUpdated event, Emitter emit, ) { - add(DashboardSummaryLoaded()); + add(DashboardSummaryRequested()); } - Future _onDashboardSummaryLoaded( - DashboardSummaryLoaded event, + Future _onDashboardSummaryRequested( + DashboardSummaryRequested event, Emitter emit, ) async { emit(state.copyWith(status: DashboardStatus.loading)); diff --git a/lib/dashboard/bloc/dashboard_event.dart b/lib/dashboard/bloc/dashboard_event.dart index ed35cdb4..e8400958 100644 --- a/lib/dashboard/bloc/dashboard_event.dart +++ b/lib/dashboard/bloc/dashboard_event.dart @@ -9,7 +9,7 @@ sealed class DashboardEvent extends Equatable { } /// Event to load the dashboard summary data. -final class DashboardSummaryLoaded extends DashboardEvent {} +final class DashboardSummaryRequested extends DashboardEvent {} /// Internal event triggered when a listened-to entity is updated. final class _DashboardEntityUpdated extends DashboardEvent { diff --git a/lib/dashboard/view/dashboard_page.dart b/lib/dashboard/view/dashboard_page.dart index 0be4698a..f63f908d 100644 --- a/lib/dashboard/view/dashboard_page.dart +++ b/lib/dashboard/view/dashboard_page.dart @@ -23,7 +23,7 @@ class _DashboardPageState extends State { void initState() { super.initState(); // Dispatch the event to load dashboard data when the page is initialized. - context.read().add(DashboardSummaryLoaded()); + context.read().add(DashboardSummaryRequested()); } @override @@ -44,7 +44,7 @@ class _DashboardPageState extends State { return FailureStateWidget( exception: state.exception!, onRetry: () { - context.read().add(DashboardSummaryLoaded()); + context.read().add(DashboardSummaryRequested()); }, ); }