@@ -98,10 +98,15 @@ class _CountryFilterPageState extends State<CountryFilterPage> {
98
98
@override
99
99
Widget build (BuildContext context) {
100
100
final l10n = context.l10n;
101
+ final theme = Theme .of (context); // Get theme
102
+ final textTheme = theme.textTheme; // Get textTheme
101
103
102
104
return Scaffold (
103
105
appBar: AppBar (
104
- title: Text (l10n.headlinesFeedFilterEventCountryLabel),
106
+ title: Text (
107
+ l10n.headlinesFeedFilterEventCountryLabel,
108
+ style: textTheme.titleLarge, // Apply consistent title style
109
+ ),
105
110
actions: [
106
111
IconButton (
107
112
icon: const Icon (Icons .check),
@@ -126,46 +131,45 @@ class _CountryFilterPageState extends State<CountryFilterPage> {
126
131
/// Builds the main content body based on the current [CountriesFilterState] .
127
132
Widget _buildBody (BuildContext context, CountriesFilterState state) {
128
133
final l10n = context.l10n;
134
+ final theme = Theme .of (context); // Get theme
135
+ final textTheme = theme.textTheme; // Get textTheme
136
+ final colorScheme = theme.colorScheme; // Get colorScheme
129
137
130
138
// Handle initial loading state
131
139
if (state.status == CountriesFilterStatus .loading) {
132
140
return LoadingStateWidget (
133
- icon: Icons .public_outlined, // Changed icon
134
- headline: l10n.countryFilterLoadingHeadline, // Assumes this exists
135
- subheadline:
136
- l10n.countryFilterLoadingSubheadline, // Assumes this exists
141
+ icon: Icons .public_outlined,
142
+ headline: l10n.countryFilterLoadingHeadline,
143
+ subheadline: l10n.countryFilterLoadingSubheadline,
137
144
);
138
145
}
139
146
140
147
// Handle failure state (show error and retry button)
141
148
if (state.status == CountriesFilterStatus .failure &&
142
149
state.countries.isEmpty) {
143
150
return FailureStateWidget (
144
- message:
145
- state.error? .toString () ?? l10n.unknownError, // Assumes this exists
146
- onRetry:
147
- () => context.read <CountriesFilterBloc >().add (
148
- CountriesFilterRequested (),
149
- ),
151
+ message: state.error? .toString () ?? l10n.unknownError,
152
+ onRetry: () =>
153
+ context.read <CountriesFilterBloc >().add (CountriesFilterRequested ()),
150
154
);
151
155
}
152
156
153
157
// Handle empty state (after successful load but no countries found)
154
158
if (state.status == CountriesFilterStatus .success &&
155
159
state.countries.isEmpty) {
156
160
return InitialStateWidget (
157
- icon: Icons .search_off,
158
- headline: l10n.countryFilterEmptyHeadline, // Assumes this exists
159
- subheadline: l10n.countryFilterEmptySubheadline, // Assumes this exists
161
+ icon: Icons .flag_circle_outlined, // More relevant icon
162
+ headline: l10n.countryFilterEmptyHeadline,
163
+ subheadline: l10n.countryFilterEmptySubheadline,
160
164
);
161
165
}
162
166
163
167
// Handle loaded state (success or loading more)
164
168
return ListView .builder (
165
169
controller: _scrollController,
166
- padding: const EdgeInsets .only (bottom : AppSpacing .xxl),
167
- itemCount :
168
- state.countries.length +
170
+ padding: const EdgeInsets .symmetric (vertical : AppSpacing .paddingSmall)
171
+ . copyWith (bottom : AppSpacing .xxl), // Consistent vertical padding
172
+ itemCount : state.countries.length +
169
173
((state.status == CountriesFilterStatus .loadingMore ||
170
174
(state.status == CountriesFilterStatus .failure &&
171
175
state.countries.isNotEmpty))
@@ -186,49 +190,63 @@ class _CountryFilterPageState extends State<CountryFilterPage> {
186
190
),
187
191
child: Center (
188
192
child: Text (
189
- l10n.loadMoreError, // Assumes this exists
190
- style: Theme .of (context).textTheme.bodySmall? .copyWith (
191
- color: Theme .of (context).colorScheme.error,
192
- ),
193
+ l10n.loadMoreError,
194
+ style: textTheme.bodySmall
195
+ ? .copyWith (color: colorScheme.error),
193
196
),
194
197
),
195
198
);
196
- } else {
197
- return const SizedBox .shrink ();
198
199
}
200
+ return const SizedBox .shrink ();
199
201
}
200
202
201
203
final country = state.countries[index];
202
204
final isSelected = _pageSelectedCountries.contains (country);
203
205
204
206
return CheckboxListTile (
205
- title: Text (country.name),
207
+ title: Text (country.name, style : textTheme.titleMedium ),
206
208
secondary: SizedBox (
207
- // Use SizedBox for consistent flag size
208
- width: 40 ,
209
- height: 30 , // Adjust height for flag aspect ratio if needed
210
- child: Image .network (
211
- country.flagUrl,
212
- fit: BoxFit .contain,
213
- errorBuilder:
214
- (context, error, stackTrace) =>
215
- const Icon (Icons .flag_outlined), // Placeholder icon
209
+ width: AppSpacing .xl + AppSpacing .xs, // Standardized width (36)
210
+ height: AppSpacing .lg + AppSpacing .sm, // Standardized height (24)
211
+ child: ClipRRect ( // Clip the image for rounded corners if desired
212
+ borderRadius: BorderRadius .circular (AppSpacing .xs / 2 ),
213
+ child: Image .network (
214
+ country.flagUrl,
215
+ fit: BoxFit .cover, // Use cover for better filling
216
+ errorBuilder: (context, error, stackTrace) => Icon (
217
+ Icons .flag_outlined,
218
+ color: colorScheme.onSurfaceVariant,
219
+ size: AppSpacing .lg, // Adjust size as needed
220
+ ),
221
+ loadingBuilder: (context, child, loadingProgress) {
222
+ if (loadingProgress == null ) return child;
223
+ return Center (
224
+ child: CircularProgressIndicator (
225
+ strokeWidth: 2 ,
226
+ value: loadingProgress.expectedTotalBytes != null
227
+ ? loadingProgress.cumulativeBytesLoaded /
228
+ loadingProgress.expectedTotalBytes!
229
+ : null ,
230
+ ),
231
+ );
232
+ },
233
+ ),
216
234
),
217
235
),
218
236
value: isSelected,
219
237
onChanged: (bool ? value) {
220
- // When a checkbox state changes, update the local selection set
221
- // (`_pageSelectedCountries`) for this page.
222
238
setState (() {
223
239
if (value == true ) {
224
- // Add the country if checked.
225
240
_pageSelectedCountries.add (country);
226
241
} else {
227
- // Remove the country if unchecked.
228
242
_pageSelectedCountries.remove (country);
229
243
}
230
244
});
231
245
},
246
+ controlAffinity: ListTileControlAffinity .leading,
247
+ contentPadding: const EdgeInsets .symmetric (
248
+ horizontal: AppSpacing .paddingMedium,
249
+ ),
232
250
);
233
251
},
234
252
);
0 commit comments