@@ -7,27 +7,22 @@ import 'package:flutter/foundation.dart';
7
7
part 'edit_source_event.dart' ;
8
8
part 'edit_source_state.dart' ;
9
9
10
- final class _FetchNextCountryPage extends EditSourceEvent {
11
- const _FetchNextCountryPage ();
12
- }
13
-
14
- final class _FetchNextLanguagePage extends EditSourceEvent {
15
- const _FetchNextLanguagePage ();
16
- }
17
-
18
10
/// A BLoC to manage the state of editing a single source.
19
11
class EditSourceBloc extends Bloc <EditSourceEvent , EditSourceState > {
20
12
/// {@macro edit_source_bloc}
21
13
EditSourceBloc ({
22
14
required DataRepository <Source > sourcesRepository,
23
- required DataRepository <Country > countriesRepository ,
24
- required DataRepository <Language > languagesRepository ,
15
+ required List <Country > countries ,
16
+ required List <Language > languages ,
25
17
required String sourceId,
26
- }) : _sourcesRepository = sourcesRepository,
27
- _countriesRepository = countriesRepository,
28
- _languagesRepository = languagesRepository,
29
- _sourceId = sourceId,
30
- super (const EditSourceState ()) {
18
+ }) : _sourcesRepository = sourcesRepository,
19
+ _sourceId = sourceId,
20
+ super (
21
+ EditSourceState (
22
+ countries: countries,
23
+ languages: languages,
24
+ ),
25
+ ) {
31
26
on < EditSourceLoaded > (_onLoaded);
32
27
on < EditSourceNameChanged > (_onNameChanged);
33
28
on < EditSourceDescriptionChanged > (_onDescriptionChanged);
@@ -37,13 +32,9 @@ class EditSourceBloc extends Bloc<EditSourceEvent, EditSourceState> {
37
32
on < EditSourceHeadquartersChanged > (_onHeadquartersChanged);
38
33
on < EditSourceStatusChanged > (_onStatusChanged);
39
34
on < EditSourceSubmitted > (_onSubmitted);
40
- on < _FetchNextCountryPage > (_onFetchNextCountryPage);
41
- on < _FetchNextLanguagePage > (_onFetchNextLanguagePage);
42
35
}
43
36
44
37
final DataRepository <Source > _sourcesRepository;
45
- final DataRepository <Country > _countriesRepository;
46
- final DataRepository <Language > _languagesRepository;
47
38
final String _sourceId;
48
39
49
40
Future <void > _onLoaded (
@@ -52,32 +43,7 @@ class EditSourceBloc extends Bloc<EditSourceEvent, EditSourceState> {
52
43
) async {
53
44
emit (state.copyWith (status: EditSourceStatus .loading));
54
45
try {
55
- final responses = await Future .wait <dynamic >([
56
- _sourcesRepository.read (id: _sourceId),
57
- _countriesRepository.readAll (
58
- sort: [const SortOption ('name' , SortOrder .asc)],
59
- filter: {'status' : ContentStatus .active.name},
60
- ),
61
- _languagesRepository.readAll (
62
- sort: [const SortOption ('name' , SortOrder .asc)],
63
- filter: {'status' : ContentStatus .active.name},
64
- ),
65
- ]);
66
-
67
- final source = responses[0 ] as Source ;
68
- final countriesPaginated = responses[1 ] as PaginatedResponse <Country >;
69
- final languagesPaginated = responses[2 ] as PaginatedResponse <Language >;
70
-
71
- Language ? selectedLanguage;
72
- try {
73
- // Find the equivalent language object from the full list.
74
- // This ensures the DropdownButton can identify it by reference.
75
- selectedLanguage = languagesPaginated.items.firstWhere (
76
- (listLanguage) => listLanguage.id == source.language.id,
77
- );
78
- } catch (_) {
79
- selectedLanguage = source.language;
80
- }
46
+ final source = await _sourcesRepository.read (id: _sourceId);
81
47
82
48
emit (
83
49
state.copyWith (
@@ -87,26 +53,11 @@ class EditSourceBloc extends Bloc<EditSourceEvent, EditSourceState> {
87
53
description: source.description,
88
54
url: source.url,
89
55
sourceType: () => source.sourceType,
90
- language: () => selectedLanguage ,
56
+ language: () => source.language ,
91
57
headquarters: () => source.headquarters,
92
58
contentStatus: source.status,
93
- countries: countriesPaginated.items,
94
- countriesCursor: countriesPaginated.cursor,
95
- countriesHasMore: countriesPaginated.hasMore,
96
- languages: languagesPaginated.items,
97
- languagesCursor: languagesPaginated.cursor,
98
- languagesHasMore: languagesPaginated.hasMore,
99
59
),
100
60
);
101
-
102
- // After the initial page is loaded, start background processes to
103
- // fetch all remaining pages for countries and languages.
104
- if (state.countriesHasMore) {
105
- add (const _FetchNextCountryPage ());
106
- }
107
- if (state.languagesHasMore) {
108
- add (const _FetchNextLanguagePage ());
109
- }
110
61
} on HttpException catch (e) {
111
62
emit (state.copyWith (status: EditSourceStatus .failure, exception: e));
112
63
} catch (e) {
@@ -194,84 +145,6 @@ class EditSourceBloc extends Bloc<EditSourceEvent, EditSourceState> {
194
145
}
195
146
196
147
// --- Background Data Fetching for Dropdown ---
197
- // The DropdownButtonFormField widget does not natively support on-scroll
198
- // pagination. To preserve UI consistency across the application, this BLoC
199
- // employs an event-driven background fetching mechanism.
200
- //
201
- // After the first page of items is loaded, a chain of events is initiated
202
- // to progressively fetch all remaining pages. This process is throttled
203
- // and runs in the background, ensuring the UI remains responsive while the
204
- // full list of dropdown options is populated over time.
205
- Future <void > _onFetchNextCountryPage (
206
- _FetchNextCountryPage event,
207
- Emitter <EditSourceState > emit,
208
- ) async {
209
- if (! state.countriesHasMore || state.countriesIsLoadingMore) return ;
210
-
211
- try {
212
- emit (state.copyWith (countriesIsLoadingMore: true ));
213
-
214
- // ignore: inference_failure_on_instance_creation
215
- await Future .delayed (const Duration (milliseconds: 400 ));
216
-
217
- final nextCountries = await _countriesRepository.readAll (
218
- pagination: PaginationOptions (cursor: state.countriesCursor),
219
- sort: [const SortOption ('name' , SortOrder .asc)],
220
- );
221
-
222
- emit (
223
- state.copyWith (
224
- countries: List .of (state.countries)..addAll (nextCountries.items),
225
- countriesCursor: nextCountries.cursor,
226
- countriesHasMore: nextCountries.hasMore,
227
- countriesIsLoadingMore: false ,
228
- ),
229
- );
230
-
231
- if (nextCountries.hasMore) {
232
- add (const _FetchNextCountryPage ());
233
- }
234
- } catch (e) {
235
- emit (state.copyWith (countriesIsLoadingMore: false ));
236
- // Optionally log the error without disrupting the user
237
- }
238
- }
239
-
240
- Future <void > _onFetchNextLanguagePage (
241
- _FetchNextLanguagePage event,
242
- Emitter <EditSourceState > emit,
243
- ) async {
244
- if (! state.languagesHasMore || state.languagesIsLoadingMore) return ;
245
-
246
- try {
247
- emit (state.copyWith (languagesIsLoadingMore: true ));
248
-
249
- // ignore: inference_failure_on_instance_creation
250
- await Future .delayed (const Duration (milliseconds: 400 ));
251
-
252
- final nextLanguages = await _languagesRepository.readAll (
253
- pagination: PaginationOptions (cursor: state.languagesCursor),
254
- sort: [const SortOption ('name' , SortOrder .asc)],
255
- );
256
-
257
- emit (
258
- state.copyWith (
259
- languages: List .of (state.languages)..addAll (nextLanguages.items),
260
- languagesCursor: nextLanguages.cursor,
261
- languagesHasMore: nextLanguages.hasMore,
262
- languagesIsLoadingMore: false ,
263
- ),
264
- );
265
-
266
- if (nextLanguages.hasMore) {
267
- add (const _FetchNextLanguagePage ());
268
- }
269
- } catch (e) {
270
- emit (state.copyWith (languagesIsLoadingMore: false ));
271
- // Optionally log the error without disrupting the user
272
- }
273
- }
274
-
275
148
Future <void > _onSubmitted (
276
149
EditSourceSubmitted event,
277
150
Emitter <EditSourceState > emit,
0 commit comments