@@ -67,18 +67,18 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
6767 required InlineAdCacheService inlineAdCacheService,
6868 required FeedCacheService feedCacheService,
6969 UserContentPreferences ? initialUserContentPreferences,
70- }) : _headlinesRepository = headlinesRepository,
71- _feedDecoratorService = feedDecoratorService,
72- _appBloc = appBloc,
73- _inlineAdCacheService = inlineAdCacheService,
74- _feedCacheService = feedCacheService,
75- _logger = Logger ('HeadlinesFeedBloc' ),
76- super (
77- HeadlinesFeedState (
78- savedFilters:
79- initialUserContentPreferences? .savedFilters ?? const [],
80- ),
81- ) {
70+ }) : _headlinesRepository = headlinesRepository,
71+ _feedDecoratorService = feedDecoratorService,
72+ _appBloc = appBloc,
73+ _inlineAdCacheService = inlineAdCacheService,
74+ _feedCacheService = feedCacheService,
75+ _logger = Logger ('HeadlinesFeedBloc' ),
76+ super (
77+ HeadlinesFeedState (
78+ savedFilters:
79+ initialUserContentPreferences? .savedFilters ?? const [],
80+ ),
81+ ) {
8282 // Subscribe to AppBloc to react to global state changes, primarily for
8383 // keeping the feed's list of saved filters synchronized with the global
8484 // app state.
@@ -224,7 +224,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
224224 }
225225
226226 _logger.info (
227- 'Pagination: Fetching next page for filter "$filterKey " with cursor "${cachedFeed .cursor }".' ,
227+ 'Pagination: Fetching next page for filter "$filterKey " with cursor '
228+ '"${cachedFeed .cursor }".' ,
228229 );
229230 emit (state.copyWith (status: HeadlinesFeedStatus .loadingMore));
230231
@@ -247,21 +248,21 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
247248 );
248249
249250 // For pagination, only inject ad placeholders, not feed actions.
250- final newProcessedFeedItems = await _feedDecoratorService
251- .injectAdPlaceholders (
252- feedItems: headlineResponse.items,
253- user: currentUser,
254- adConfig: remoteConfig.adConfig,
255- imageStyle:
256- _appBloc.state.settings! .feedPreferences.headlineImageStyle,
257- adThemeStyle: event.adThemeStyle,
258- processedContentItemCount: cachedFeed.feedItems
259- .whereType <Headline >()
260- .length,
261- );
251+ final newProcessedFeedItems =
252+ await _feedDecoratorService.injectAdPlaceholders (
253+ feedItems: headlineResponse.items,
254+ user: currentUser,
255+ adConfig: remoteConfig.adConfig,
256+ imageStyle:
257+ _appBloc.state.settings! .feedPreferences.headlineImageStyle,
258+ adThemeStyle: event.adThemeStyle,
259+ processedContentItemCount:
260+ cachedFeed.feedItems.whereType <Headline >().length,
261+ );
262262
263263 _logger.fine (
264- 'Pagination: Appending ${newProcessedFeedItems .length } new items to the feed.' ,
264+ 'Pagination: Appending ${newProcessedFeedItems .length } new items to '
265+ 'the feed.' ,
265266 );
266267
267268 final updatedFeedItems = List .of (cachedFeed.feedItems)
@@ -275,7 +276,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
275276
276277 _feedCacheService.updateFeed (filterKey, updatedCachedFeed);
277278 _logger.fine (
278- 'Pagination: Cache updated for filter "$filterKey ". New total items: ${updatedFeedItems .length }.' ,
279+ 'Pagination: Cache updated for filter "$filterKey ". New total items: '
280+ '${updatedFeedItems .length }.' ,
279281 );
280282
281283 emit (
@@ -300,9 +302,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
300302
301303 // Apply throttling logic.
302304 if (cachedFeed != null ) {
303- final timeSinceLastRefresh = DateTime .now ().difference (
304- cachedFeed.lastRefreshedAt,
305- );
305+ final timeSinceLastRefresh =
306+ DateTime .now ().difference (cachedFeed.lastRefreshedAt);
306307 if (timeSinceLastRefresh < _refreshThrottleDuration) {
307308 _logger.info (
308309 'Refresh throttled for filter "$filterKey ". '
@@ -312,9 +313,9 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
312313 }
313314 }
314315
315- // On a full refresh, clear the ad cache for the current feed to ensure
316+ // On a full refresh, clear the ad cache for the current context to ensure
316317 // fresh ads are loaded.
317- _inlineAdCacheService.clearAdsForFeed (feedKey : filterKey);
318+ _inlineAdCacheService.clearAdsForContext (contextKey : filterKey);
318319 emit (state.copyWith (status: HeadlinesFeedStatus .loading));
319320 try {
320321 final currentUser = _appBloc.state.user;
@@ -332,7 +333,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
332333 );
333334
334335 _logger.info (
335- 'Refresh: Fetched ${headlineResponse .items .length } latest headlines for filter "$filterKey ".' ,
336+ 'Refresh: Fetched ${headlineResponse .items .length } latest headlines '
337+ 'for filter "$filterKey ".' ,
336338 );
337339 // If there's an existing cache, perform the intelligent prepend.
338340 if (cachedFeed != null ) {
@@ -341,9 +343,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
341343
342344 if (cachedHeadlines.isNotEmpty) {
343345 final firstCachedHeadlineId = cachedHeadlines.first.id;
344- final matchIndex = newHeadlines.indexWhere (
345- (h) => h.id == firstCachedHeadlineId,
346- );
346+ final matchIndex =
347+ newHeadlines.indexWhere ((h) => h.id == firstCachedHeadlineId);
347348
348349 if (matchIndex != - 1 ) {
349350 // Prepend only the new items found before the match.
@@ -355,7 +356,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
355356 final updatedFeedItems = List <FeedItem >.from (itemsToPrepend)
356357 ..addAll (cachedFeed.feedItems);
357358 _logger.info (
358- 'Refresh: Prepending ${itemsToPrepend .length } new items to the feed.' ,
359+ 'Refresh: Prepending ${itemsToPrepend .length } new items to '
360+ 'the feed.' ,
359361 );
360362
361363 // Update cache and state, then return.
@@ -373,7 +375,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
373375 return ;
374376 } else {
375377 _logger.info (
376- 'Refresh: No new items to prepend. Emitting existing cached state.' ,
378+ 'Refresh: No new items to prepend. Emitting existing cached '
379+ 'state.' ,
377380 );
378381 // If there are no new items, just emit the success state with
379382 // the existing cached items to dismiss the loading indicator.
@@ -385,7 +388,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
385388 );
386389 // This early return is critical. It prevents the BLoC from
387390 // proceeding to the full re-decoration step when no new content
388- // is available, which would unnecessarily clear and reload all ads.
391+ // is available, which would unnecessarily clear and reload all
392+ // ads.
389393 return ;
390394 }
391395 } else {
@@ -469,23 +473,25 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
469473 if (event.savedFilter != null ) {
470474 newActiveFilterId = event.savedFilter! .id;
471475 } else {
472- final matchingSavedFilter = state.savedFilters.firstWhereOrNull ((
473- savedFilter,
474- ) {
475- final appliedTopics = event.filter.topics? .toSet () ?? {};
476- final savedTopics = savedFilter.topics.toSet ();
477- final appliedSources = event.filter.sources? .toSet () ?? {};
478- final savedSources = savedFilter.sources.toSet ();
479- final appliedCountries = event.filter.eventCountries? .toSet () ?? {};
480- final savedCountries = savedFilter.countries.toSet ();
481-
482- return const SetEquality <Topic >().equals (appliedTopics, savedTopics) &&
483- const SetEquality <Source >().equals (appliedSources, savedSources) &&
484- const SetEquality <Country >().equals (
485- appliedCountries,
486- savedCountries,
487- );
488- });
476+ final matchingSavedFilter = state.savedFilters.firstWhereOrNull (
477+ (savedFilter) {
478+ final appliedTopics = event.filter.topics? .toSet () ?? {};
479+ final savedTopics = savedFilter.topics.toSet ();
480+ final appliedSources = event.filter.sources? .toSet () ?? {};
481+ final savedSources = savedFilter.sources.toSet ();
482+ final appliedCountries = event.filter.eventCountries? .toSet () ?? {};
483+ final savedCountries = savedFilter.countries.toSet ();
484+
485+ return const SetEquality <Topic >()
486+ .equals (appliedTopics, savedTopics) &&
487+ const SetEquality <Source >()
488+ .equals (appliedSources, savedSources) &&
489+ const SetEquality <Country >().equals (
490+ appliedCountries,
491+ savedCountries,
492+ );
493+ },
494+ );
489495
490496 newActiveFilterId = matchingSavedFilter? .id ?? 'custom' ;
491497 }
@@ -813,7 +819,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
813819
814820 if (cachedFeed != null ) {
815821 _logger.info (
816- 'Saved Filter Selected: Cache HIT for key "$filterKey ". Emitting cached state.' ,
822+ 'Saved Filter Selected: Cache HIT for key "$filterKey ". '
823+ 'Emitting cached state.' ,
817824 );
818825 emit (
819826 state.copyWith (
@@ -835,7 +842,8 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
835842 }
836843
837844 _logger.info (
838- 'Saved Filter Selected: Cache MISS for key "$filterKey ". Delegating to filter application.' ,
845+ 'Saved Filter Selected: Cache MISS for key "$filterKey ". '
846+ 'Delegating to filter application.' ,
839847 );
840848 emit (state.copyWith (activeFilterId: event.filter.id));
841849 add (
0 commit comments