@@ -9,6 +9,14 @@ import 'package:uuid/uuid.dart';
99part 'create_source_event.dart' ;
1010part 'create_source_state.dart' ;
1111
12+ final class _FetchNextCountryPage extends CreateSourceEvent {
13+ const _FetchNextCountryPage ();
14+ }
15+
16+ final class _FetchNextLanguagePage extends CreateSourceEvent {
17+ const _FetchNextLanguagePage ();
18+ }
19+
1220const _searchDebounceDuration = Duration (milliseconds: 300 );
1321
1422/// A BLoC to manage the state of creating a new source.
@@ -18,10 +26,10 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
1826 required DataRepository <Source > sourcesRepository,
1927 required DataRepository <Country > countriesRepository,
2028 required DataRepository <Language > languagesRepository,
21- }) : _sourcesRepository = sourcesRepository,
22- _countriesRepository = countriesRepository,
23- _languagesRepository = languagesRepository,
24- super (const CreateSourceState ()) {
29+ }) : _sourcesRepository = sourcesRepository,
30+ _countriesRepository = countriesRepository,
31+ _languagesRepository = languagesRepository,
32+ super (const CreateSourceState ()) {
2533 on < CreateSourceDataLoaded > (_onDataLoaded);
2634 on < CreateSourceNameChanged > (_onNameChanged);
2735 on < CreateSourceDescriptionChanged > (_onDescriptionChanged);
@@ -31,6 +39,8 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
3139 on < CreateSourceHeadquartersChanged > (_onHeadquartersChanged);
3240 on < CreateSourceStatusChanged > (_onStatusChanged);
3341 on < CreateSourceSubmitted > (_onSubmitted);
42+ on < _FetchNextCountryPage > (_onFetchNextCountryPage);
43+ on < _FetchNextLanguagePage > (_onFetchNextLanguagePage);
3444 }
3545
3646 final DataRepository <Source > _sourcesRepository;
@@ -66,34 +76,13 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
6676 ),
6777 );
6878
69- // Start background fetching for all countries
70- while (state.countriesHasMore) {
71- final nextCountries = await _countriesRepository.readAll (
72- pagination: PaginationOptions (cursor: state.countriesCursor),
73- sort: [const SortOption ('name' , SortOrder .asc)],
74- );
75- emit (
76- state.copyWith (
77- countries: List .of (state.countries)..addAll (nextCountries.items),
78- countriesCursor: nextCountries.cursor,
79- countriesHasMore: nextCountries.hasMore,
80- ),
81- );
79+ // After the initial page is loaded, start background processes to
80+ // fetch all remaining pages for countries and languages.
81+ if (state.countriesHasMore) {
82+ add (const _FetchNextCountryPage ());
8283 }
83-
84- // Start background fetching for all languages
85- while (state.languagesHasMore) {
86- final nextLanguages = await _languagesRepository.readAll (
87- pagination: PaginationOptions (cursor: state.languagesCursor),
88- sort: [const SortOption ('name' , SortOrder .asc)],
89- );
90- emit (
91- state.copyWith (
92- languages: List .of (state.languages)..addAll (nextLanguages.items),
93- languagesCursor: nextLanguages.cursor,
94- languagesHasMore: nextLanguages.hasMore,
95- ),
96- );
84+ if (state.languagesHasMore) {
85+ add (const _FetchNextLanguagePage ());
9786 }
9887 } on HttpException catch (e) {
9988 emit (state.copyWith (status: CreateSourceStatus .failure, exception: e));
@@ -161,6 +150,83 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
161150 );
162151 }
163152
153+ // --- Background Data Fetching for Dropdown ---
154+ // The DropdownButtonFormField widget does not natively support on-scroll
155+ // pagination. To preserve UI consistency across the application, this BLoC
156+ // employs an event-driven background fetching mechanism.
157+ //
158+ // After the first page of items is loaded, a chain of events is initiated
159+ // to progressively fetch all remaining pages. This process is throttled
160+ // and runs in the background, ensuring the UI remains responsive while the
161+ // full list of dropdown options is populated over time.
162+ Future <void > _onFetchNextCountryPage (
163+ _FetchNextCountryPage event,
164+ Emitter <CreateSourceState > emit,
165+ ) async {
166+ if (! state.countriesHasMore || state.countriesIsLoadingMore) return ;
167+
168+ try {
169+ emit (state.copyWith (countriesIsLoadingMore: true ));
170+
171+ await Future .delayed (const Duration (milliseconds: 400 ));
172+
173+ final nextCountries = await _countriesRepository.readAll (
174+ pagination: PaginationOptions (cursor: state.countriesCursor),
175+ sort: [const SortOption ('name' , SortOrder .asc)],
176+ );
177+
178+ emit (
179+ state.copyWith (
180+ countries: List .of (state.countries)..addAll (nextCountries.items),
181+ countriesCursor: nextCountries.cursor,
182+ countriesHasMore: nextCountries.hasMore,
183+ countriesIsLoadingMore: false ,
184+ ),
185+ );
186+
187+ if (nextCountries.hasMore) {
188+ add (const _FetchNextCountryPage ());
189+ }
190+ } catch (e) {
191+ emit (state.copyWith (countriesIsLoadingMore: false ));
192+ // Optionally log the error without disrupting the user
193+ }
194+ }
195+
196+ Future <void > _onFetchNextLanguagePage (
197+ _FetchNextLanguagePage event,
198+ Emitter <CreateSourceState > emit,
199+ ) async {
200+ if (! state.languagesHasMore || state.languagesIsLoadingMore) return ;
201+
202+ try {
203+ emit (state.copyWith (languagesIsLoadingMore: true ));
204+
205+ await Future .delayed (const Duration (milliseconds: 400 ));
206+
207+ final nextLanguages = await _languagesRepository.readAll (
208+ pagination: PaginationOptions (cursor: state.languagesCursor),
209+ sort: [const SortOption ('name' , SortOrder .asc)],
210+ );
211+
212+ emit (
213+ state.copyWith (
214+ languages: List .of (state.languages)..addAll (nextLanguages.items),
215+ languagesCursor: nextLanguages.cursor,
216+ languagesHasMore: nextLanguages.hasMore,
217+ languagesIsLoadingMore: false ,
218+ ),
219+ );
220+
221+ if (nextLanguages.hasMore) {
222+ add (const _FetchNextLanguagePage ());
223+ }
224+ } catch (e) {
225+ emit (state.copyWith (languagesIsLoadingMore: false ));
226+ // Optionally log the error without disrupting the user
227+ }
228+ }
229+
164230 Future <void > _onSubmitted (
165231 CreateSourceSubmitted event,
166232 Emitter <CreateSourceState > emit,
0 commit comments