@@ -9,14 +9,14 @@ import 'package:ui_kit/ui_kit.dart';
99/// (e.g., Topics or Sources).
1010///
1111/// This widget presents a title and a horizontal list of [SuggestionItemWidget] s.
12+ /// It now includes a dismiss option in a popup menu.
1213/// {@endtemplate}
1314class ContentCollectionDecoratorWidget extends StatelessWidget {
1415 /// {@macro content_collection_decorator_widget}
1516 const ContentCollectionDecoratorWidget ({
1617 required this .item,
1718 required this .onFollowToggle,
18- required this .followedTopicIds,
19- required this .followedSourceIds,
19+ this .onDismiss,
2020 super .key,
2121 });
2222
@@ -27,19 +27,16 @@ class ContentCollectionDecoratorWidget extends StatelessWidget {
2727 /// is pressed.
2828 final ValueSetter <FeedItem > onFollowToggle;
2929
30- /// List of IDs of topics the user is currently following.
31- final List <String > followedTopicIds;
32-
33- /// List of IDs of sources the user is currently following.
34- final List <String > followedSourceIds;
30+ /// An optional callback that is triggered when the user dismisses the
31+ /// decorator.
32+ final VoidCallback ? onDismiss;
3533
3634 @override
3735 Widget build (BuildContext context) {
3836 return _ContentCollectionView (
3937 item: item,
4038 onFollowToggle: onFollowToggle,
41- followedTopicIds: followedTopicIds,
42- followedSourceIds: followedSourceIds,
39+ onDismiss: onDismiss,
4340 );
4441 }
4542}
@@ -48,14 +45,12 @@ class _ContentCollectionView extends StatefulWidget {
4845 const _ContentCollectionView ({
4946 required this .item,
5047 required this .onFollowToggle,
51- required this .followedTopicIds,
52- required this .followedSourceIds,
48+ this .onDismiss,
5349 });
5450
5551 final ContentCollectionItem item;
5652 final ValueSetter <FeedItem > onFollowToggle;
57- final List <String > followedTopicIds;
58- final List <String > followedSourceIds;
53+ final VoidCallback ? onDismiss;
5954
6055 @override
6156 State <_ContentCollectionView > createState () => _ContentCollectionViewState ();
@@ -115,6 +110,19 @@ class _ContentCollectionViewState extends State<_ContentCollectionView> {
115110 overflow: TextOverflow .ellipsis,
116111 ),
117112 ),
113+ if (widget.onDismiss != null )
114+ PopupMenuButton <void >(
115+ icon: const Icon (Icons .more_vert),
116+ tooltip: l10n.manageFiltersDeleteTooltip,
117+ onSelected: (_) => widget.onDismiss !(),
118+ itemBuilder: (BuildContext context) => [
119+ PopupMenuItem <void >(
120+ value: null ,
121+ // TODO(fulleni): Replace with a localized string.
122+ child: Text (l10n.savedFiltersMenuDelete),
123+ ),
124+ ],
125+ ),
118126 ],
119127 ),
120128 ),
@@ -123,6 +131,20 @@ class _ContentCollectionViewState extends State<_ContentCollectionView> {
123131 height: 180 ,
124132 child: LayoutBuilder (
125133 builder: (context, constraints) {
134+ // Access AppBloc to get the user's content preferences,
135+ // which is the source of truth for followed items.
136+ final appState = context.watch <AppBloc >().state;
137+ final followedTopicIds =
138+ appState.userContentPreferences? .followedTopics
139+ .map ((t) => t.id)
140+ .toList () ??
141+ [];
142+ final followedSourceIds =
143+ appState.userContentPreferences? .followedSources
144+ .map ((s) => s.id)
145+ .toList () ??
146+ [];
147+
126148 final listView = ListView .builder (
127149 controller: _scrollController,
128150 scrollDirection: Axis .horizontal,
@@ -134,12 +156,34 @@ class _ContentCollectionViewState extends State<_ContentCollectionView> {
134156 final suggestion = widget.item.items[index];
135157 final isFollowing =
136158 (suggestion is Topic &&
137- widget. followedTopicIds.contains (suggestion.id)) ||
159+ followedTopicIds.contains (suggestion.id)) ||
138160 (suggestion is Source &&
139- widget. followedSourceIds.contains (suggestion.id));
161+ followedSourceIds.contains (suggestion.id));
140162 return SuggestionItemWidget (
141163 item: suggestion,
142- onFollowToggle: widget.onFollowToggle,
164+ onFollowToggle: (toggledItem) {
165+ final currentUserPreferences =
166+ appState.userContentPreferences;
167+ if (currentUserPreferences == null ) return ;
168+
169+ UserContentPreferences updatedPreferences;
170+
171+ if (toggledItem is Topic ) {
172+ updatedPreferences = currentUserPreferences
173+ .toggleFollowedTopic (toggledItem);
174+ } else if (toggledItem is Source ) {
175+ updatedPreferences = currentUserPreferences
176+ .toggleFollowedSource (toggledItem);
177+ } else {
178+ return ;
179+ }
180+
181+ context.read <AppBloc >().add (
182+ AppUserContentPreferencesChanged (
183+ preferences: updatedPreferences,
184+ ),
185+ );
186+ },
143187 isFollowing: isFollowing,
144188 );
145189 },
0 commit comments