Skip to content

Commit 213123c

Browse files
committed
refactor(headlines_feed): update bloc to use new decorator services
Refactors `HeadlinesFeedBloc` to align with the new, decoupled decorator architecture. - Replaces the single call to the old monolithic `FeedDecoratorService` with a new two-step process in all major load handlers (`_onHeadlinesFeedRefreshRequested`, `_onHeadlinesFeedFiltersApplied`, `_onHeadlinesFeedFiltersCleared`). - The BLoC now first calls the new, lightweight `FeedDecoratorService` to inject a `DecoratorPlaceholder`. - It then passes the resulting list to the `AdService`'s `injectAdPlaceholders` method to inject ad placeholders. - Removes all logic related to processing the old `FeedDecoratorResult` and its `injectedDecorator` property, as this responsibility is now fully encapsulated within the `FeedDecoratorLoaderWidget`. - Updates comments to accurately describe the new, cleaner decoration process.
1 parent 997e462 commit 213123c

File tree

1 file changed

+15
-19
lines changed

1 file changed

+15
-19
lines changed

lib/headlines-feed/bloc/headlines_feed_bloc.dart

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,22 @@ part 'headlines_feed_state.dart';
2727
/// - Fetching, filtering, and displaying headlines from a `DataRepository`.
2828
/// - Injecting dynamic content placeholders for ads and non-ad decorators
2929
/// using the `AdService` and the new `FeedDecoratorService`.
30-
/// - Implementing a robust, session-based in-memory caching strategy via
31-
/// [FeedCacheService] to provide a highly responsive user experience.
30+
/// - Implementing a session-based in-memory caching strategy via
31+
/// [FeedCacheService] to provide a responsive user experience.
3232
///
3333
/// ### Feed Decoration and Ad Injection:
34-
/// On major feed loads (initial load, refresh, or new filter), this BLoC now
34+
/// On major feed loads (initial load, refresh, or new filter), this BLoC
3535
/// uses a two-step process:
3636
/// 1. The new `FeedDecoratorService` injects a single `DecoratorPlaceholder`.
37-
/// 2. The `AdService` injects multiple `AdPlaceholder` items.
37+
/// 2. The `AdService` then injects multiple `AdPlaceholder` items.
3838
/// The UI is then responsible for rendering loader widgets for these placeholders.
3939
///
4040
/// ### Caching and Data Flow Scenarios:
4141
///
4242
/// 1. **Cache Miss (Initial Load / New Filter):** When a filter is applied for
4343
/// the first time, the BLoC fetches data from the [DataRepository],
4444
/// decorates it using [FeedDecoratorService], and stores the result in the
45-
/// cache before emitting the `success` state.
45+
/// cache before emitting the `success` state with the decorated feed.
4646
///
4747
/// 2. **Cache Hit (Switching Filters):** When switching to a previously viewed
4848
/// filter, the BLoC instantly emits the cached data. If the cached data is
@@ -53,7 +53,7 @@ part 'headlines_feed_state.dart';
5353
/// feed, the BLoC fetches the next page of headlines and **appends** them
5454
/// to the existing cached list, ensuring a seamless infinite scroll.
5555
///
56-
/// 4. **Pull-to-Refresh (Prepending):** On a pull-to-refresh action, the BLoC
56+
/// 4. **Pull-to-Refresh:** On a pull-to-refresh action, the BLoC
5757
/// fetches the latest headlines and intelligently **prepends** only the new
5858
/// items to the top of the cached list, avoiding full reloads.
5959
/// {@endtemplate}
@@ -404,30 +404,28 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
404404
}
405405
}
406406

407-
// Use user content preferences from AppBloc for followed items.
408407
_logger.info(
409408
'Refresh: Performing full decoration for filter "$filterKey".',
410409
);
411-
final userPreferences = _appBloc.state.userContentPreferences;
412410
final settings = _appBloc.state.settings;
413411

414412
// Step 1: Inject the non-ad decorator placeholder.
415-
final feedWithDecorator = _feedDecoratorService.decorateFeed(
413+
final feedWithDecorator = await _feedDecoratorService.decorateFeed(
416414
feedItems: headlineResponse.items,
417415
remoteConfig: appConfig,
418416
);
419417

420418
// Step 2: Inject ad placeholders into the resulting list.
421419
final fullyDecoratedFeed = await _adService.injectAdPlaceholders(
422-
feedItems: feedWithDecorator,
420+
feedItems: feedWithDecorator.decoratedItems,
423421
user: currentUser,
424422
adConfig: appConfig.adConfig,
425423
imageStyle: settings!.feedPreferences.headlineImageStyle,
426424
adThemeStyle: event.adThemeStyle,
427425
);
428426

429427
final newCachedFeed = CachedFeed(
430-
feedItems: fullyDecoratedFeed,
428+
feedItems: fullyDecoratedFeed.decoratedItems,
431429
hasMore: headlineResponse.hasMore,
432430
cursor: headlineResponse.cursor,
433431
lastRefreshedAt: DateTime.now(),
@@ -534,26 +532,25 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
534532
sort: [const SortOption('updatedAt', SortOrder.desc)],
535533
);
536534

537-
final userPreferences = _appBloc.state.userContentPreferences;
538535
final settings = _appBloc.state.settings;
539536

540537
// Step 1: Inject the non-ad decorator placeholder.
541-
final feedWithDecorator = _feedDecoratorService.decorateFeed(
538+
final feedWithDecorator = await _feedDecoratorService.decorateFeed(
542539
feedItems: headlineResponse.items,
543540
remoteConfig: appConfig,
544541
);
545542

546543
// Step 2: Inject ad placeholders into the resulting list.
547544
final fullyDecoratedFeed = await _adService.injectAdPlaceholders(
548-
feedItems: feedWithDecorator,
545+
feedItems: feedWithDecorator.decoratedItems,
549546
user: currentUser,
550547
adConfig: appConfig.adConfig,
551548
imageStyle: settings!.feedPreferences.headlineImageStyle,
552549
adThemeStyle: event.adThemeStyle,
553550
);
554551

555552
final newCachedFeed = CachedFeed(
556-
feedItems: fullyDecoratedFeed,
553+
feedItems: fullyDecoratedFeed.decoratedItems,
557554
hasMore: headlineResponse.hasMore,
558555
cursor: headlineResponse.cursor,
559556
lastRefreshedAt: DateTime.now(),
@@ -631,26 +628,25 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
631628
sort: [const SortOption('updatedAt', SortOrder.desc)],
632629
);
633630

634-
final userPreferences = _appBloc.state.userContentPreferences;
635631
final settings = _appBloc.state.settings;
636632

637633
// Step 1: Inject the non-ad decorator placeholder.
638-
final feedWithDecorator = _feedDecoratorService.decorateFeed(
634+
final feedWithDecorator = await _feedDecoratorService.decorateFeed(
639635
feedItems: headlineResponse.items,
640636
remoteConfig: appConfig,
641637
);
642638

643639
// Step 2: Inject ad placeholders into the resulting list.
644640
final fullyDecoratedFeed = await _adService.injectAdPlaceholders(
645-
feedItems: feedWithDecorator,
641+
feedItems: feedWithDecorator.decoratedItems,
646642
user: currentUser,
647643
adConfig: appConfig.adConfig,
648644
imageStyle: settings!.feedPreferences.headlineImageStyle,
649645
adThemeStyle: event.adThemeStyle,
650646
);
651647

652648
final newCachedFeed = CachedFeed(
653-
feedItems: fullyDecoratedFeed,
649+
feedItems: fullyDecoratedFeed.decoratedItems,
654650
hasMore: headlineResponse.hasMore,
655651
cursor: headlineResponse.cursor,
656652
lastRefreshedAt: DateTime.now(),

0 commit comments

Comments
 (0)