1+ import 'package:collection/collection.dart' ;
12import 'package:core/core.dart' ;
23import 'package:flutter/material.dart' ;
34import 'package:flutter_bloc/flutter_bloc.dart' ;
@@ -33,14 +34,26 @@ class _SourceListFilterView extends StatefulWidget {
3334}
3435
3536class _SourceListFilterViewState extends State <_SourceListFilterView > {
37+ late final Set <Country > _initialSelection;
38+ late Set <Country > _currentSelection;
3639 final _scrollController = ScrollController ();
3740
3841 @override
3942 void initState () {
4043 super .initState ();
44+ // Store the initial and current selections locally to track changes.
45+ _initialSelection = context.read <SourceListBloc >().state.selectedCountries;
46+ _currentSelection = Set .from (_initialSelection);
4147 _scrollController.addListener (_onScroll);
4248 }
4349
50+ bool get _hasChanges {
51+ return ! const SetEquality <Country >().equals (
52+ _initialSelection,
53+ _currentSelection,
54+ );
55+ }
56+
4457 @override
4558 void dispose () {
4659 _scrollController
@@ -79,7 +92,20 @@ class _SourceListFilterViewState extends State<_SourceListFilterView> {
7992 IconButton (
8093 icon: const Icon (Icons .check),
8194 tooltip: l10n.headlinesFeedFilterApplyButton,
82- onPressed: () => Navigator .of (context).pop (),
95+ // The button is enabled only if the selection has changed.
96+ onPressed: _hasChanges
97+ ? () {
98+ // When applying, dispatch a single event with the final
99+ // selection and then pop the page.
100+ context.read <SourceListBloc >().add (
101+ SourceListCountryFilterChanged (
102+ selectedCountries: _currentSelection,
103+ ),
104+ );
105+ Navigator .of (context).pop ();
106+ }
107+ // If there are no changes, the button is disabled.
108+ : null ,
83109 ),
84110 ],
85111 ),
@@ -115,7 +141,7 @@ class _SourceListFilterViewState extends State<_SourceListFilterView> {
115141 : const SizedBox .shrink ();
116142 }
117143 final country = state.countries[index];
118- final isSelected = state.selectedCountries .contains (country);
144+ final isSelected = _currentSelection .contains (country);
119145
120146 return CheckboxListTile (
121147 title: Text (country.name, style: textTheme.titleMedium),
@@ -138,19 +164,15 @@ class _SourceListFilterViewState extends State<_SourceListFilterView> {
138164 value: isSelected,
139165 onChanged: (bool ? value) {
140166 if (value == null ) return ;
141- final newSelection = Set <Country >.from (
142- state.selectedCountries,
143- );
144- if (value) {
145- newSelection.add (country);
146- } else {
147- newSelection.remove (country);
148- }
149- context.read <SourceListBloc >().add (
150- SourceListCountryFilterChanged (
151- selectedCountries: newSelection,
152- ),
153- );
167+ // Update the local selection state, which will trigger a
168+ // rebuild and enable/disable the apply button.
169+ setState (() {
170+ if (value) {
171+ _currentSelection.add (country);
172+ } else {
173+ _currentSelection.remove (country);
174+ }
175+ });
154176 },
155177 controlAffinity: ListTileControlAffinity .leading,
156178 );
0 commit comments