@@ -4,6 +4,9 @@ import 'package:core/core.dart';
44import 'package:flutter/material.dart' ;
55import 'package:flutter_news_app_mobile_client_full_source_code/l10n/app_localizations.dart' ;
66import 'package:flutter_news_app_mobile_client_full_source_code/l10n/l10n.dart' ;
7+ import 'package:flutter_news_app_mobile_client_full_source_code/router/routes.dart' ;
8+ import 'package:flutter_news_app_mobile_client_full_source_code/shared/widgets/multi_select_search_page.dart' ;
9+ import 'package:go_router/go_router.dart' ;
710import 'package:ui_kit/ui_kit.dart' ;
811
912/// {@template source_list_filter_page}
@@ -83,20 +86,51 @@ class _SourceListFilterPageState extends State<SourceListFilterPage> {
8386 padding: const EdgeInsets .symmetric (vertical: AppSpacing .md),
8487 children: [
8588 // Section for filtering by headquarters country.
86- _buildSectionHeader (
87- context,
88- l10n.headlinesFeedFilterSourceCountryLabel,
89+ ListTile (
90+ title: Text (l10n.headlinesFeedFilterSourceCountryLabel),
91+ subtitle: Text (
92+ _selectedHeadquarterCountries.isEmpty
93+ ? l10n.headlinesFeedFilterAllLabel
94+ : l10n.headlinesFeedFilterSelectedCountLabel (
95+ _selectedHeadquarterCountries.length,
96+ ),
97+ ),
98+ trailing: const Icon (Icons .chevron_right),
99+ onTap: () async {
100+ final result = await context.pushNamed <Set <Country >>(
101+ Routes .multiSelectSearchName,
102+ extra: {
103+ 'title' : l10n.headlinesFeedFilterSourceCountryLabel,
104+ 'allItems' : widget.allCountries,
105+ 'initialSelectedItems' : _selectedHeadquarterCountries,
106+ 'itemBuilder' : (Country country) => country.name,
107+ },
108+ );
109+
110+ if (result != null && mounted) {
111+ setState (() => _selectedHeadquarterCountries = result);
112+ }
113+ },
89114 ),
90- _buildCountryCapsules (context, widget.allCountries, l10n, textTheme ),
115+ const Divider (height : 1 ),
91116 const SizedBox (height: AppSpacing .lg),
92117
93118 // Section for filtering by source type.
94119 _buildSectionHeader (context, l10n.headlinesFeedFilterSourceTypeLabel),
95- _buildSourceTypeCapsules (
96- context,
97- widget.allSourceTypes,
98- l10n,
99- textTheme,
120+ ...widget.allSourceTypes.map (
121+ (sourceType) => CheckboxListTile (
122+ title: Text (sourceType.name),
123+ value: _selectedSourceTypes.contains (sourceType),
124+ onChanged: (isSelected) {
125+ setState (() {
126+ if (isSelected == true ) {
127+ _selectedSourceTypes.add (sourceType);
128+ } else {
129+ _selectedSourceTypes.remove (sourceType);
130+ }
131+ });
132+ },
133+ ),
100134 ),
101135 ],
102136 ),
@@ -115,108 +149,4 @@ class _SourceListFilterPageState extends State<SourceListFilterPage> {
115149 ),
116150 );
117151 }
118-
119- /// Builds the horizontal list of [ChoiceChip] widgets for countries.
120- Widget _buildCountryCapsules (
121- BuildContext context,
122- List <Country > allCountries,
123- AppLocalizations l10n,
124- TextTheme textTheme,
125- ) {
126- return SizedBox (
127- height: AppSpacing .xl + AppSpacing .md,
128- child: ListView .builder (
129- scrollDirection: Axis .horizontal,
130- padding: const EdgeInsets .symmetric (
131- horizontal: AppSpacing .paddingMedium,
132- vertical: AppSpacing .sm,
133- ),
134- itemCount: allCountries.length + 1 ,
135- itemBuilder: (context, index) {
136- if (index == 0 ) {
137- // The 'All' chip.
138- return ChoiceChip (
139- label: Text (l10n.headlinesFeedFilterAllLabel),
140- labelStyle: textTheme.labelLarge,
141- selected: _selectedHeadquarterCountries.isEmpty,
142- onSelected: (_) => setState (_selectedHeadquarterCountries.clear),
143- );
144- }
145- final country = allCountries[index - 1 ];
146- return Padding (
147- padding: const EdgeInsets .only (left: AppSpacing .sm),
148- child: ChoiceChip (
149- avatar: country.flagUrl.isNotEmpty
150- ? CircleAvatar (
151- backgroundImage: NetworkImage (country.flagUrl),
152- radius: AppSpacing .sm + AppSpacing .xs,
153- )
154- : null ,
155- label: Text (country.name),
156- labelStyle: textTheme.labelLarge,
157- selected: _selectedHeadquarterCountries.contains (country),
158- onSelected: (isSelected) {
159- setState (() {
160- if (isSelected) {
161- _selectedHeadquarterCountries.add (country);
162- } else {
163- _selectedHeadquarterCountries.remove (country);
164- }
165- });
166- },
167- ),
168- );
169- },
170- ),
171- );
172- }
173-
174- /// Builds the horizontal list of [ChoiceChip] widgets for source types.
175- Widget _buildSourceTypeCapsules (
176- BuildContext context,
177- List <SourceType > allSourceTypes,
178- AppLocalizations l10n,
179- TextTheme textTheme,
180- ) {
181- return SizedBox (
182- height: AppSpacing .xl + AppSpacing .md,
183- child: ListView .builder (
184- scrollDirection: Axis .horizontal,
185- padding: const EdgeInsets .symmetric (
186- horizontal: AppSpacing .paddingMedium,
187- vertical: AppSpacing .sm,
188- ),
189- itemCount: allSourceTypes.length + 1 ,
190- itemBuilder: (context, index) {
191- if (index == 0 ) {
192- // The 'All' chip.
193- return ChoiceChip (
194- label: Text (l10n.headlinesFeedFilterAllLabel),
195- labelStyle: textTheme.labelLarge,
196- selected: _selectedSourceTypes.isEmpty,
197- onSelected: (_) => setState (_selectedSourceTypes.clear),
198- );
199- }
200- final sourceType = allSourceTypes[index - 1 ];
201- return Padding (
202- padding: const EdgeInsets .only (left: AppSpacing .sm),
203- child: ChoiceChip (
204- label: Text (sourceType.name),
205- labelStyle: textTheme.labelLarge,
206- selected: _selectedSourceTypes.contains (sourceType),
207- onSelected: (isSelected) {
208- setState (() {
209- if (isSelected) {
210- _selectedSourceTypes.add (sourceType);
211- } else {
212- _selectedSourceTypes.remove (sourceType);
213- }
214- });
215- },
216- ),
217- );
218- },
219- ),
220- );
221- }
222152}
0 commit comments