Skip to content

Commit 0cd3394

Browse files
authored
Merge pull request #42 from flutter-news-app-full-source-code/migrate-from-country-and-langauge-picker-to-internal-solution
Migrate from country and langauge picker to internal solution
2 parents 91d907a + 8c68568 commit 0cd3394

31 files changed

+399
-440
lines changed

lib/app/view/app.dart

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,29 +32,35 @@ class App extends StatelessWidget {
3232
userContentPreferencesRepository,
3333
required DataRepository<RemoteConfig> remoteConfigRepository,
3434
required DataRepository<DashboardSummary> dashboardSummaryRepository,
35+
required DataRepository<Country> countriesRepository,
36+
required DataRepository<Language> languagesRepository,
3537
required KVStorageService storageService,
3638
required AppEnvironment environment,
3739
super.key,
38-
}) : _authenticationRepository = authenticationRepository,
39-
_headlinesRepository = headlinesRepository,
40-
_topicsRepository = topicsRepository,
41-
_sourcesRepository = sourcesRepository,
42-
_userAppSettingsRepository = userAppSettingsRepository,
43-
_userContentPreferencesRepository = userContentPreferencesRepository,
44-
_remoteConfigRepository = remoteConfigRepository,
45-
_kvStorageService = storageService,
46-
_dashboardSummaryRepository = dashboardSummaryRepository,
47-
_environment = environment;
40+
}) : _authenticationRepository = authenticationRepository,
41+
_headlinesRepository = headlinesRepository,
42+
_topicsRepository = topicsRepository,
43+
_sourcesRepository = sourcesRepository,
44+
_userAppSettingsRepository = userAppSettingsRepository,
45+
_userContentPreferencesRepository = userContentPreferencesRepository,
46+
_remoteConfigRepository = remoteConfigRepository,
47+
_kvStorageService = storageService,
48+
_dashboardSummaryRepository = dashboardSummaryRepository,
49+
_countriesRepository = countriesRepository,
50+
_languagesRepository = languagesRepository,
51+
_environment = environment;
4852

4953
final AuthRepository _authenticationRepository;
5054
final DataRepository<Headline> _headlinesRepository;
5155
final DataRepository<Topic> _topicsRepository;
5256
final DataRepository<Source> _sourcesRepository;
5357
final DataRepository<UserAppSettings> _userAppSettingsRepository;
5458
final DataRepository<UserContentPreferences>
55-
_userContentPreferencesRepository;
59+
_userContentPreferencesRepository;
5660
final DataRepository<RemoteConfig> _remoteConfigRepository;
5761
final DataRepository<DashboardSummary> _dashboardSummaryRepository;
62+
final DataRepository<Country> _countriesRepository;
63+
final DataRepository<Language> _languagesRepository;
5864
final KVStorageService _kvStorageService;
5965
final AppEnvironment _environment;
6066

@@ -70,6 +76,8 @@ class App extends StatelessWidget {
7076
RepositoryProvider.value(value: _userContentPreferencesRepository),
7177
RepositoryProvider.value(value: _remoteConfigRepository),
7278
RepositoryProvider.value(value: _dashboardSummaryRepository),
79+
RepositoryProvider.value(value: _countriesRepository),
80+
RepositoryProvider.value(value: _languagesRepository),
7381
RepositoryProvider.value(value: _kvStorageService),
7482
],
7583
child: MultiBlocProvider(

lib/bootstrap.dart

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ Future<Widget> bootstrap(
6060
DataClient<UserAppSettings> userAppSettingsClient;
6161
DataClient<RemoteConfig> remoteConfigClient;
6262
DataClient<DashboardSummary> dashboardSummaryClient;
63+
DataClient<Country> countriesClient;
64+
DataClient<Language> languagesClient;
6365

6466
if (appConfig.environment == app_config.AppEnvironment.demo) {
6567
headlinesClient = DataInMemory<Headline>(
@@ -102,6 +104,18 @@ Future<Widget> bootstrap(
102104
initialData: dashboardSummaryFixturesData,
103105
logger: Logger('DataInMemory<DashboardSummary>'),
104106
);
107+
countriesClient = DataInMemory<Country>(
108+
toJson: (i) => i.toJson(),
109+
getId: (i) => i.id,
110+
initialData: countriesFixturesData,
111+
logger: Logger('DataInMemory<Country>'),
112+
);
113+
languagesClient = DataInMemory<Language>(
114+
toJson: (i) => i.toJson(),
115+
getId: (i) => i.id,
116+
initialData: languagesFixturesData,
117+
logger: Logger('DataInMemory<Language>'),
118+
);
105119
} else if (appConfig.environment == app_config.AppEnvironment.development) {
106120
headlinesClient = DataApi<Headline>(
107121
httpClient: httpClient!,
@@ -152,6 +166,20 @@ Future<Widget> bootstrap(
152166
toJson: (summary) => summary.toJson(),
153167
logger: Logger('DataApi<DashboardSummary>'),
154168
);
169+
countriesClient = DataApi<Country>(
170+
httpClient: httpClient,
171+
modelName: 'country',
172+
fromJson: Country.fromJson,
173+
toJson: (country) => country.toJson(),
174+
logger: Logger('DataApi<Country>'),
175+
);
176+
languagesClient = DataApi<Language>(
177+
httpClient: httpClient,
178+
modelName: 'language',
179+
fromJson: Language.fromJson,
180+
toJson: (language) => language.toJson(),
181+
logger: Logger('DataApi<Language>'),
182+
);
155183
} else {
156184
headlinesClient = DataApi<Headline>(
157185
httpClient: httpClient!,
@@ -202,6 +230,20 @@ Future<Widget> bootstrap(
202230
toJson: (summary) => summary.toJson(),
203231
logger: Logger('DataApi<DashboardSummary>'),
204232
);
233+
countriesClient = DataApi<Country>(
234+
httpClient: httpClient,
235+
modelName: 'country',
236+
fromJson: Country.fromJson,
237+
toJson: (country) => country.toJson(),
238+
logger: Logger('DataApi<Country>'),
239+
);
240+
languagesClient = DataApi<Language>(
241+
httpClient: httpClient,
242+
modelName: 'language',
243+
fromJson: Language.fromJson,
244+
toJson: (language) => language.toJson(),
245+
logger: Logger('DataApi<Language>'),
246+
);
205247
}
206248

207249
final headlinesRepository = DataRepository<Headline>(
@@ -222,6 +264,10 @@ Future<Widget> bootstrap(
222264
final dashboardSummaryRepository = DataRepository<DashboardSummary>(
223265
dataClient: dashboardSummaryClient,
224266
);
267+
final countriesRepository =
268+
DataRepository<Country>(dataClient: countriesClient);
269+
final languagesRepository =
270+
DataRepository<Language>(dataClient: languagesClient);
225271

226272
return App(
227273
authenticationRepository: authenticationRepository,
@@ -232,6 +278,8 @@ Future<Widget> bootstrap(
232278
userContentPreferencesRepository: userContentPreferencesRepository,
233279
remoteConfigRepository: remoteConfigRepository,
234280
dashboardSummaryRepository: dashboardSummaryRepository,
281+
countriesRepository: countriesRepository,
282+
languagesRepository: languagesRepository,
235283
storageService: kvStorage,
236284
environment: environment,
237285
);

lib/content_management/bloc/create_headline/create_headline_bloc.dart

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import 'package:bloc/bloc.dart';
22
import 'package:core/core.dart';
3-
import 'package:country_picker/country_picker.dart' as picker;
43
import 'package:data_repository/data_repository.dart';
54
import 'package:equatable/equatable.dart';
65
import 'package:flutter/foundation.dart';
7-
import 'package:flutter_news_app_web_dashboard_full_source_code/shared/shared.dart';
86
import 'package:uuid/uuid.dart';
97

108
part 'create_headline_event.dart';
@@ -18,10 +16,12 @@ class CreateHeadlineBloc
1816
required DataRepository<Headline> headlinesRepository,
1917
required DataRepository<Source> sourcesRepository,
2018
required DataRepository<Topic> topicsRepository,
21-
}) : _headlinesRepository = headlinesRepository,
22-
_sourcesRepository = sourcesRepository,
23-
_topicsRepository = topicsRepository,
24-
super(const CreateHeadlineState()) {
19+
required DataRepository<Country> countriesRepository,
20+
}) : _headlinesRepository = headlinesRepository,
21+
_sourcesRepository = sourcesRepository,
22+
_topicsRepository = topicsRepository,
23+
_countriesRepository = countriesRepository,
24+
super(const CreateHeadlineState()) {
2525
on<CreateHeadlineDataLoaded>(_onDataLoaded);
2626
on<CreateHeadlineTitleChanged>(_onTitleChanged);
2727
on<CreateHeadlineExcerptChanged>(_onExcerptChanged);
@@ -37,6 +37,7 @@ class CreateHeadlineBloc
3737
final DataRepository<Headline> _headlinesRepository;
3838
final DataRepository<Source> _sourcesRepository;
3939
final DataRepository<Topic> _topicsRepository;
40+
final DataRepository<Country> _countriesRepository;
4041
final _uuid = const Uuid();
4142

4243
Future<void> _onDataLoaded(
@@ -48,23 +49,30 @@ class CreateHeadlineBloc
4849
final [
4950
sourcesResponse,
5051
topicsResponse,
52+
countriesResponse,
5153
] = await Future.wait([
5254
_sourcesRepository.readAll(
5355
sort: [const SortOption('updatedAt', SortOrder.desc)],
5456
),
5557
_topicsRepository.readAll(
5658
sort: [const SortOption('updatedAt', SortOrder.desc)],
5759
),
60+
_countriesRepository.readAll(
61+
sort: [const SortOption('name', SortOrder.asc)],
62+
),
5863
]);
5964

6065
final sources = (sourcesResponse as PaginatedResponse<Source>).items;
6166
final topics = (topicsResponse as PaginatedResponse<Topic>).items;
67+
final countries =
68+
(countriesResponse as PaginatedResponse<Country>).items;
6269

6370
emit(
6471
state.copyWith(
6572
status: CreateHeadlineStatus.initial,
6673
sources: sources,
6774
topics: topics,
75+
countries: countries,
6876
),
6977
);
7078
} on HttpException catch (e) {
@@ -125,13 +133,7 @@ class CreateHeadlineBloc
125133
CreateHeadlineCountryChanged event,
126134
Emitter<CreateHeadlineState> emit,
127135
) {
128-
final packageCountry = event.country;
129-
if (packageCountry == null) {
130-
emit(state.copyWith(eventCountry: () => null));
131-
} else {
132-
final coreCountry = adaptPackageCountryToCoreCountry(packageCountry);
133-
emit(state.copyWith(eventCountry: () => coreCountry));
134-
}
136+
emit(state.copyWith(eventCountry: () => event.country));
135137
}
136138

137139
void _onStatusChanged(

lib/content_management/bloc/create_headline/create_headline_event.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ final class CreateHeadlineTopicChanged extends CreateHeadlineEvent {
6464
/// Event for when the headline's country is changed.
6565
final class CreateHeadlineCountryChanged extends CreateHeadlineEvent {
6666
const CreateHeadlineCountryChanged(this.country);
67-
final picker.Country? country;
67+
final Country? country;
6868
@override
6969
List<Object?> get props => [country];
7070
}

lib/content_management/bloc/create_headline/create_headline_state.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ final class CreateHeadlineState extends Equatable {
3131
this.eventCountry,
3232
this.sources = const [],
3333
this.topics = const [],
34+
this.countries = const [],
3435
this.contentStatus = ContentStatus.active,
3536
this.exception,
3637
this.createdHeadline,
@@ -46,6 +47,7 @@ final class CreateHeadlineState extends Equatable {
4647
final Country? eventCountry;
4748
final List<Source> sources;
4849
final List<Topic> topics;
50+
final List<Country> countries;
4951
final ContentStatus contentStatus;
5052
final HttpException? exception;
5153
final Headline? createdHeadline;
@@ -71,6 +73,7 @@ final class CreateHeadlineState extends Equatable {
7173
ValueGetter<Country?>? eventCountry,
7274
List<Source>? sources,
7375
List<Topic>? topics,
76+
List<Country>? countries,
7477
ContentStatus? contentStatus,
7578
HttpException? exception,
7679
Headline? createdHeadline,
@@ -86,6 +89,7 @@ final class CreateHeadlineState extends Equatable {
8689
eventCountry: eventCountry != null ? eventCountry() : this.eventCountry,
8790
sources: sources ?? this.sources,
8891
topics: topics ?? this.topics,
92+
countries: countries ?? this.countries,
8993
contentStatus: contentStatus ?? this.contentStatus,
9094
exception: exception,
9195
createdHeadline: createdHeadline ?? this.createdHeadline,
@@ -104,6 +108,7 @@ final class CreateHeadlineState extends Equatable {
104108
eventCountry,
105109
sources,
106110
topics,
111+
countries,
107112
contentStatus,
108113
exception,
109114
createdHeadline,

lib/content_management/bloc/create_source/create_source_bloc.dart

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import 'package:bloc/bloc.dart';
22
import 'package:core/core.dart';
3-
import 'package:country_picker/country_picker.dart' as picker;
43
import 'package:data_repository/data_repository.dart';
54
import 'package:equatable/equatable.dart';
6-
import 'package:flutter/material.dart';
7-
import 'package:flutter_news_app_web_dashboard_full_source_code/shared/shared.dart';
8-
import 'package:language_picker/languages.dart';
5+
import 'package:flutter/foundation.dart';
96
import 'package:uuid/uuid.dart';
107

118
part 'create_source_event.dart';
@@ -16,8 +13,12 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
1613
/// {@macro create_source_bloc}
1714
CreateSourceBloc({
1815
required DataRepository<Source> sourcesRepository,
19-
}) : _sourcesRepository = sourcesRepository,
20-
super(const CreateSourceState()) {
16+
required DataRepository<Country> countriesRepository,
17+
required DataRepository<Language> languagesRepository,
18+
}) : _sourcesRepository = sourcesRepository,
19+
_countriesRepository = countriesRepository,
20+
_languagesRepository = languagesRepository,
21+
super(const CreateSourceState()) {
2122
on<CreateSourceDataLoaded>(_onDataLoaded);
2223
on<CreateSourceNameChanged>(_onNameChanged);
2324
on<CreateSourceDescriptionChanged>(_onDescriptionChanged);
@@ -30,15 +31,38 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
3031
}
3132

3233
final DataRepository<Source> _sourcesRepository;
34+
final DataRepository<Country> _countriesRepository;
35+
final DataRepository<Language> _languagesRepository;
3336
final _uuid = const Uuid();
3437

3538
Future<void> _onDataLoaded(
3639
CreateSourceDataLoaded event,
3740
Emitter<CreateSourceState> emit,
3841
) async {
39-
// This event is now a no-op since we don't need to load countries.
40-
// We just ensure the BLoC is in the initial state.
41-
emit(state.copyWith(status: CreateSourceStatus.initial));
42+
emit(state.copyWith(status: CreateSourceStatus.loading));
43+
try {
44+
final [countriesResponse, languagesResponse] = await Future.wait([
45+
_countriesRepository.readAll(
46+
sort: [const SortOption('name', SortOrder.asc)],
47+
),
48+
_languagesRepository.readAll(
49+
sort: [const SortOption('name', SortOrder.asc)],
50+
),
51+
]);
52+
53+
final countries = (countriesResponse as PaginatedResponse<Country>).items;
54+
final languages = (languagesResponse as PaginatedResponse<Language>).items;
55+
56+
emit(
57+
state.copyWith(
58+
status: CreateSourceStatus.initial,
59+
countries: countries,
60+
languages: languages,
61+
),
62+
);
63+
} catch (e) {
64+
emit(state.copyWith(status: CreateSourceStatus.failure));
65+
}
4266
}
4367

4468
void _onNameChanged(
@@ -80,13 +104,7 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
80104
CreateSourceHeadquartersChanged event,
81105
Emitter<CreateSourceState> emit,
82106
) {
83-
final packageCountry = event.headquarters;
84-
if (packageCountry == null) {
85-
emit(state.copyWith(headquarters: () => null));
86-
} else {
87-
final coreCountry = adaptPackageCountryToCoreCountry(packageCountry);
88-
emit(state.copyWith(headquarters: () => coreCountry));
89-
}
107+
emit(state.copyWith(headquarters: () => event.headquarters));
90108
}
91109

92110
void _onStatusChanged(
@@ -116,7 +134,7 @@ class CreateSourceBloc extends Bloc<CreateSourceEvent, CreateSourceState> {
116134
description: state.description,
117135
url: state.url,
118136
sourceType: state.sourceType!,
119-
language: adaptPackageLanguageToLanguageCode(state.language!),
137+
language: state.language!,
120138
createdAt: now,
121139
updatedAt: now,
122140
headquarters: state.headquarters!,

lib/content_management/bloc/create_source/create_source_event.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ final class CreateSourceLanguageChanged extends CreateSourceEvent {
5656
/// Event for when the source's headquarters is changed.
5757
final class CreateSourceHeadquartersChanged extends CreateSourceEvent {
5858
const CreateSourceHeadquartersChanged(this.headquarters);
59-
final picker.Country? headquarters;
59+
final Country? headquarters;
6060
@override
6161
List<Object?> get props => [headquarters];
6262
}

0 commit comments

Comments
 (0)