@@ -570,15 +570,15 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
570570 /// Handles the selection of the "Followed" filter from the filter bar.
571571 ///
572572 /// This creates a [HeadlineFilter] from the user's followed items and
573- /// triggers a full feed refresh.
573+ /// triggers a full feed refresh directly within this handler. It no longer
574+ /// delegates to `HeadlinesFeedFiltersApplied` to prevent a bug where the
575+ /// filter would be incorrectly identified as 'custom'.
574576 Future <void > _onFollowedFilterSelected (
575577 FollowedFilterSelected event,
576578 Emitter <HeadlinesFeedState > emit,
577579 ) async {
578580 final userPreferences = _appBloc.state.userContentPreferences;
579581 if (userPreferences == null ) {
580- // This case should ideally not happen if the UI is built correctly,
581- // as the "Followed" button is only shown when preferences are available.
582582 return ;
583583 }
584584
@@ -588,15 +588,77 @@ class HeadlinesFeedBloc extends Bloc<HeadlinesFeedEvent, HeadlinesFeedState> {
588588 eventCountries: userPreferences.followedCountries,
589589 );
590590
591- // Set the active filter ID and then dispatch an event to apply the filter
592- // and refresh the feed.
593- emit (state. copyWith (activeFilterId : 'followed' ));
594- add (
595- HeadlinesFeedFiltersApplied (
591+ // This is a major feed change, so clear the ad cache.
592+ _inlineAdCacheService. clearAllAds ();
593+ emit (
594+ state. copyWith (
595+ status : HeadlinesFeedStatus .loading,
596596 filter: newFilter,
597- adThemeStyle: event.adThemeStyle,
597+ activeFilterId: 'followed' ,
598+ feedItems: [],
599+ clearCursor: true ,
598600 ),
599601 );
602+
603+ try {
604+ final currentUser = _appBloc.state.user;
605+ final appConfig = _appBloc.state.remoteConfig;
606+
607+ if (appConfig == null ) {
608+ emit (state.copyWith (status: HeadlinesFeedStatus .failure));
609+ return ;
610+ }
611+
612+ final headlineResponse = await _headlinesRepository.readAll (
613+ filter: _buildFilter (newFilter),
614+ pagination: const PaginationOptions (limit: _headlinesFetchLimit),
615+ sort: [const SortOption ('updatedAt' , SortOrder .desc)],
616+ );
617+
618+ final decorationResult = await _feedDecoratorService.decorateFeed (
619+ headlines: headlineResponse.items,
620+ user: currentUser,
621+ remoteConfig: appConfig,
622+ followedTopicIds: userPreferences.followedTopics
623+ .map ((t) => t.id)
624+ .toList (),
625+ followedSourceIds: userPreferences.followedSources
626+ .map ((s) => s.id)
627+ .toList (),
628+ imageStyle: _appBloc.state.settings! .feedPreferences.headlineImageStyle,
629+ adThemeStyle: event.adThemeStyle,
630+ );
631+
632+ emit (
633+ state.copyWith (
634+ status: HeadlinesFeedStatus .success,
635+ feedItems: decorationResult.decoratedItems,
636+ hasMore: headlineResponse.hasMore,
637+ cursor: headlineResponse.cursor,
638+ ),
639+ );
640+
641+ final injectedDecorator = decorationResult.injectedDecorator;
642+ if (injectedDecorator != null && currentUser? .id != null ) {
643+ if (injectedDecorator is CallToActionItem ) {
644+ _appBloc.add (
645+ AppUserFeedDecoratorShown (
646+ userId: currentUser! .id,
647+ feedDecoratorType: injectedDecorator.decoratorType,
648+ ),
649+ );
650+ } else if (injectedDecorator is ContentCollectionItem ) {
651+ _appBloc.add (
652+ AppUserFeedDecoratorShown (
653+ userId: currentUser! .id,
654+ feedDecoratorType: injectedDecorator.decoratorType,
655+ ),
656+ );
657+ }
658+ }
659+ } on HttpException catch (e) {
660+ emit (state.copyWith (status: HeadlinesFeedStatus .failure, error: e));
661+ }
600662 }
601663
602664 @override
0 commit comments