@@ -29,24 +29,32 @@ class HeadlinesFilterPage extends StatefulWidget {
29
29
}
30
30
31
31
class _HeadlinesFilterPageState extends State <HeadlinesFilterPage > {
32
- // Temporary state for filter selections within this modal flow
32
+ /// Temporary state for filter selections within this modal flow.
33
+ /// These hold the selections made by the user *while* this filter page
34
+ /// and its sub-pages (Category, Source, Country) are open.
35
+ /// They are initialized from the main [HeadlinesFeedBloc] 's current filter
36
+ /// and are only applied back to the BLoC when the user taps 'Apply'.
33
37
late List <Category > _tempSelectedCategories;
34
38
late List <Source > _tempSelectedSources;
35
39
late List <Country > _tempSelectedCountries;
36
40
37
41
@override
38
42
void initState () {
39
43
super .initState ();
40
- // Initialize temporary state from the currently active filters in the BLoC
44
+ // Initialize the temporary selection state based on the currently
45
+ // active filters held within the HeadlinesFeedBloc. This ensures that
46
+ // when the filter page opens, it reflects the filters already applied.
41
47
final currentState = BlocProvider .of <HeadlinesFeedBloc >(context).state;
42
48
if (currentState is HeadlinesFeedLoaded ) {
49
+ // Create copies of the lists to avoid modifying the BLoC state directly.
43
50
_tempSelectedCategories = List .from (currentState.filter.categories ?? []);
44
51
_tempSelectedSources = List .from (currentState.filter.sources ?? []);
45
52
_tempSelectedCountries = List .from (
46
53
currentState.filter.eventCountries ?? [],
47
54
);
48
55
} else {
49
- // Default to empty lists if the feed isn't loaded yet (should be rare)
56
+ // Default to empty lists if the feed isn't loaded yet. This might happen
57
+ // if the filter page is accessed before the initial feed load completes.
50
58
_tempSelectedCategories = [];
51
59
_tempSelectedSources = [];
52
60
_tempSelectedCountries = [];
@@ -59,9 +67,11 @@ class _HeadlinesFilterPageState extends State<HeadlinesFilterPage> {
59
67
/// ([selectedCount] ), and navigates to the corresponding selection page
60
68
/// specified by [routeName] when tapped.
61
69
///
62
- /// Uses [currentSelection] to pass the temporary selection state to the
63
- /// criterion page and updates the state via the [onResult] callback when
64
- /// the criterion page pops with a result.
70
+ /// Uses [currentSelection] to pass the current temporary selection state
71
+ /// (e.g., `_tempSelectedSources` ) to the corresponding criterion selection page
72
+ /// (e.g., `SourceFilterPage` ) via the `extra` parameter of `context.pushNamed` .
73
+ /// Updates the temporary state via the [onResult] callback when the
74
+ /// criterion page pops with a result (the user tapped 'Apply' on that page).
65
75
Widget _buildFilterTile ({
66
76
required BuildContext context,
67
77
required String title,
@@ -83,14 +93,21 @@ class _HeadlinesFilterPageState extends State<HeadlinesFilterPage> {
83
93
subtitle: Text (subtitle),
84
94
trailing: const Icon (Icons .chevron_right),
85
95
onTap: () async {
86
- // Use pushNamed to navigate and wait for a result
96
+ // Navigate to the specific filter selection page (e.g., SourceFilterPage).
97
+ // Use pushNamed to wait for a result when the page is popped.
87
98
final result = await context.pushNamed <List <dynamic >>(
88
- routeName,
89
- extra: currentSelection, // Pass current temp selection
99
+ routeName, // The route name for the specific filter page.
100
+ // Pass the current temporary selection for this filter type
101
+ // (e.g., _tempSelectedSources) to the next page. This allows
102
+ // the next page to initialize its UI reflecting the current state.
103
+ extra: currentSelection,
90
104
);
91
- // Update temp state if result is not null (user applied changes)
105
+ // When the filter selection page pops (usually via its 'Apply' button),
106
+ // it returns the potentially modified list of selected items.
107
+ // If the result is not null (meaning the user didn't just cancel/go back),
108
+ // update the corresponding temporary state list on *this* page.
92
109
if (result != null ) {
93
- onResult (result);
110
+ onResult (result); // Calls setState to update the UI here.
94
111
}
95
112
},
96
113
);
@@ -127,24 +144,28 @@ class _HeadlinesFilterPageState extends State<HeadlinesFilterPage> {
127
144
icon: const Icon (Icons .check),
128
145
tooltip: l10n.headlinesFeedFilterApplyButton,
129
146
onPressed: () {
130
- // Apply the temporary filters to the BLoC
147
+ // When the user confirms their filter choices on this page,
148
+ // create a new HeadlineFilter object using the final temporary
149
+ // selections gathered from the sub-pages.
150
+ final newFilter = HeadlineFilter (
151
+ categories:
152
+ _tempSelectedCategories.isNotEmpty
153
+ ? _tempSelectedCategories
154
+ : null , // Use null if empty
155
+ sources:
156
+ _tempSelectedSources.isNotEmpty
157
+ ? _tempSelectedSources
158
+ : null , // Use null if empty
159
+ eventCountries:
160
+ _tempSelectedCountries.isNotEmpty
161
+ ? _tempSelectedCountries
162
+ : null , // Use null if empty
163
+ );
164
+
165
+ // Add an event to the main HeadlinesFeedBloc to apply the
166
+ // newly constructed filter and trigger a data refresh.
131
167
context.read <HeadlinesFeedBloc >().add (
132
- HeadlinesFeedFiltersApplied (
133
- filter: HeadlineFilter (
134
- categories:
135
- _tempSelectedCategories.isNotEmpty
136
- ? _tempSelectedCategories
137
- : null ,
138
- sources:
139
- _tempSelectedSources.isNotEmpty
140
- ? _tempSelectedSources
141
- : null ,
142
- eventCountries:
143
- _tempSelectedCountries.isNotEmpty
144
- ? _tempSelectedCountries
145
- : null ,
146
- ),
147
- ),
168
+ HeadlinesFeedFiltersApplied (filter: newFilter),
148
169
);
149
170
context.pop (); // Close the filter page
150
171
},
0 commit comments