Skip to content

Commit b7cc090

Browse files
committed
refactor(headlines-feed): improve code structure and naming
- Rename 'feedKey' to 'contextKey' in ad cache service for clarity - Update 'feedKey' parameter to 'contextKey' in FeedAdLoaderWidget - Adjust line wrapping and formatting for better readability
1 parent 4b8b116 commit b7cc090

File tree

2 files changed

+67
-59
lines changed

2 files changed

+67
-59
lines changed

lib/headlines-feed/bloc/headlines_feed_bloc.dart

Lines changed: 66 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -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(

lib/headlines-feed/view/headlines_feed_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ class _HeadlinesFeedPageState extends State<HeadlinesFeedPage>
309309

310310
return FeedAdLoaderWidget(
311311
key: ValueKey(item.id),
312-
feedKey: state.activeFilterId!,
312+
contextKey: state.activeFilterId!,
313313
adPlaceholder: item,
314314
adThemeStyle: AdThemeStyle.fromTheme(theme),
315315
adConfig: adConfig,

0 commit comments

Comments
 (0)