Skip to content

Commit 615e5ba

Browse files
authored
Merge pull request #132 from flutter-news-app-full-source-code/aa
Aa
2 parents b2d3d03 + efe2dda commit 615e5ba

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+2117
-1667
lines changed

lib/app/bloc/app_bloc.dart

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,28 @@ part 'app_state.dart';
1717
class AppBloc extends Bloc<AppEvent, AppState> {
1818
AppBloc({
1919
required AuthRepository authenticationRepository,
20-
required DataRepository<UserAppSettings> userAppSettingsRepository,
20+
required DataRepository<AppSettings> appSettingsRepository,
2121
required DataRepository<RemoteConfig> appConfigRepository,
2222
required local_config.AppEnvironment environment,
2323
Logger? logger,
2424
}) : _authenticationRepository = authenticationRepository,
25-
_userAppSettingsRepository = userAppSettingsRepository,
25+
_appSettingsRepository = appSettingsRepository,
2626
_appConfigRepository = appConfigRepository,
2727
_logger = logger ?? Logger('AppBloc'),
2828
super(AppState(environment: environment)) {
2929
on<AppUserChanged>(_onAppUserChanged);
3030
on<AppLogoutRequested>(_onLogoutRequested);
31-
on<AppUserAppSettingsChanged>(_onAppUserAppSettingsChanged);
31+
on<AppUserAppSettingsChanged>(
32+
_onAppUserAppSettingsChanged,
33+
);
3234

3335
_userSubscription = _authenticationRepository.authStateChanges.listen(
3436
(User? user) => add(AppUserChanged(user)),
3537
);
3638
}
3739

3840
final AuthRepository _authenticationRepository;
39-
final DataRepository<UserAppSettings> _userAppSettingsRepository;
41+
final DataRepository<AppSettings> _appSettingsRepository;
4042
final DataRepository<RemoteConfig> _appConfigRepository;
4143
final Logger _logger;
4244
late final StreamSubscription<User?> _userSubscription;
@@ -68,16 +70,16 @@ class AppBloc extends Bloc<AppEvent, AppState> {
6870
// If user is authenticated, load their app settings
6971
if (status == AppStatus.authenticated && user != null) {
7072
try {
71-
final userAppSettings = await _userAppSettingsRepository.read(
73+
final appSettings = await _appSettingsRepository.read(
7274
id: user.id,
7375
);
74-
emit(state.copyWith(userAppSettings: userAppSettings));
76+
emit(state.copyWith(appSettings: appSettings));
7577
} on NotFoundException {
7678
// If settings not found, create default ones
7779
_logger.info(
7880
'User app settings not found for user ${user.id}. Creating default.',
7981
);
80-
final defaultSettings = UserAppSettings(
82+
final defaultSettings = AppSettings(
8183
id: user.id,
8284
displaySettings: const DisplaySettings(
8385
baseTheme: AppBaseTheme.system,
@@ -92,49 +94,48 @@ class AppBloc extends Bloc<AppEvent, AppState> {
9294
'Default language "en" not found in language fixtures.',
9395
),
9496
),
95-
feedPreferences: const FeedDisplayPreferences(
96-
headlineDensity: HeadlineDensity.standard,
97-
headlineImageStyle: HeadlineImageStyle.largeThumbnail,
98-
showSourceInHeadlineFeed: true,
99-
showPublishDateInHeadlineFeed: true,
97+
feedSettings: const FeedSettings(
98+
feedItemDensity: FeedItemDensity.standard,
99+
feedItemImageStyle: FeedItemImageStyle.largeThumbnail,
100+
feedItemClickBehavior: FeedItemClickBehavior.defaultBehavior,
100101
),
101102
);
102-
await _userAppSettingsRepository.create(item: defaultSettings);
103-
emit(state.copyWith(userAppSettings: defaultSettings));
103+
await _appSettingsRepository.create(item: defaultSettings);
104+
emit(state.copyWith(appSettings: defaultSettings));
104105
} on HttpException catch (e, s) {
105106
// Handle HTTP exceptions during settings load
106107
_logger.severe(
107108
'Error loading user app settings for user ${user.id}: ${e.message}',
108109
e,
109110
s,
110111
);
111-
emit(state.copyWith(clearUserAppSettings: true));
112+
emit(state.copyWith(clearAppSettings: true));
112113
} catch (e, s) {
113114
// Handle any other unexpected errors
114115
_logger.severe(
115116
'Unexpected error loading user app settings for user ${user.id}: $e',
116117
e,
117118
s,
118119
);
119-
emit(state.copyWith(clearUserAppSettings: true));
120+
emit(state.copyWith(clearAppSettings: true));
120121
}
121122
} else {
122123
// If user is unauthenticated or anonymous, clear app settings
123-
emit(state.copyWith(clearUserAppSettings: true));
124+
emit(state.copyWith(clearAppSettings: true));
124125
}
125126
}
126127

127128
void _onAppUserAppSettingsChanged(
128129
AppUserAppSettingsChanged event,
129130
Emitter<AppState> emit,
130131
) {
131-
emit(state.copyWith(userAppSettings: event.userAppSettings));
132+
emit(state.copyWith(appSettings: event.appSettings));
132133
}
133134

134135
void _onLogoutRequested(AppLogoutRequested event, Emitter<AppState> emit) {
135136
unawaited(_authenticationRepository.signOut());
136137
emit(
137-
state.copyWith(clearUserAppSettings: true),
138+
state.copyWith(clearAppSettings: true),
138139
);
139140
}
140141

lib/app/bloc/app_event.dart

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
part of 'app_bloc.dart';
22

3-
abstract class AppEvent extends Equatable {
3+
sealed class AppEvent extends Equatable {
44
const AppEvent();
55

66
@override
77
List<Object?> get props => [];
88
}
99

10-
class AppUserChanged extends AppEvent {
10+
final class AppUserChanged extends AppEvent {
1111
const AppUserChanged(this.user);
1212

1313
final User? user;
@@ -16,24 +16,17 @@ class AppUserChanged extends AppEvent {
1616
List<Object?> get props => [user];
1717
}
1818

19-
/// {@template app_logout_requested}
20-
/// Event to request user logout.
21-
/// {@endtemplate}
22-
class AppLogoutRequested extends AppEvent {
23-
/// {@macro app_logout_requested}
19+
final class AppLogoutRequested extends AppEvent {
2420
const AppLogoutRequested();
2521
}
2622

27-
/// {@template app_user_app_settings_changed}
28-
/// Event to notify that user application settings have changed.
29-
/// {@endtemplate}
23+
/// Event for when the user's app settings are changed.
3024
final class AppUserAppSettingsChanged extends AppEvent {
31-
/// {@macro app_user_app_settings_changed}
32-
const AppUserAppSettingsChanged(this.userAppSettings);
25+
const AppUserAppSettingsChanged(this.appSettings);
3326

34-
/// The updated user application settings.
35-
final UserAppSettings userAppSettings;
27+
/// The new user app settings.
28+
final AppSettings appSettings;
3629

3730
@override
38-
List<Object?> get props => [userAppSettings];
31+
List<Object?> get props => [appSettings];
3932
}

lib/app/bloc/app_state.dart

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,47 @@
11
part of 'app_bloc.dart';
22

3-
/// Represents the application's authentication status.
43
enum AppStatus {
5-
/// The application is initializing and the status is unknown.
4+
/// The app is in its initial state, typically before any authentication
5+
/// checks have been performed.
66
initial,
77

8-
/// The user is authenticated.
8+
/// The user is authenticated and has a valid session.
99
authenticated,
1010

11-
/// The user is unauthenticated.
11+
/// The user is unauthenticated, meaning they are not logged in.
1212
unauthenticated,
1313

14-
/// The user is anonymous (signed in using an anonymous provider).
14+
/// The user is authenticated anonymously.
1515
anonymous,
1616
}
1717

18-
/// {@template app_state}
19-
/// Represents the overall state of the application, including authentication
20-
/// status, current user, environment, and user-specific settings.
21-
/// {@endtemplate}
22-
class AppState extends Equatable {
23-
/// {@macro app_state}
18+
final class AppState extends Equatable {
2419
const AppState({
20+
required this.environment,
2521
this.status = AppStatus.initial,
2622
this.user,
27-
this.environment,
28-
this.userAppSettings,
23+
this.appSettings,
2924
});
3025

31-
/// The current authentication status of the application.
3226
final AppStatus status;
33-
34-
/// The current user details. Null if unauthenticated.
3527
final User? user;
28+
final AppSettings? appSettings;
29+
final local_config.AppEnvironment environment;
3630

37-
/// The current application environment (e.g., production, development, demo).
38-
final local_config.AppEnvironment? environment;
39-
40-
/// The current user application settings. Null if not loaded or unauthenticated.
41-
final UserAppSettings? userAppSettings;
42-
43-
/// Creates a copy of the current state with updated values.
4431
AppState copyWith({
4532
AppStatus? status,
4633
User? user,
47-
local_config.AppEnvironment? environment,
48-
UserAppSettings? userAppSettings,
49-
bool clearEnvironment = false,
50-
bool clearUserAppSettings = false,
34+
AppSettings? appSettings,
35+
bool clearAppSettings = false,
5136
}) {
5237
return AppState(
5338
status: status ?? this.status,
5439
user: user ?? this.user,
55-
environment: clearEnvironment ? null : environment ?? this.environment,
56-
userAppSettings: clearUserAppSettings
57-
? null
58-
: userAppSettings ?? this.userAppSettings,
40+
appSettings: clearAppSettings ? null : appSettings ?? this.appSettings,
41+
environment: environment,
5942
);
6043
}
6144

6245
@override
63-
List<Object?> get props => [
64-
status,
65-
user,
66-
environment,
67-
userAppSettings,
68-
];
46+
List<Object?> get props => [status, user, appSettings, environment];
6947
}

lib/app/config/app_config.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class AppConfig {
3434
/// A factory constructor for the demo environment.
3535
factory AppConfig.demo() => AppConfig(
3636
environment: AppEnvironment.demo,
37-
baseUrl: '', // No API access needed for in-memory demo
37+
baseUrl: '',
3838
);
3939

4040
/// A factory constructor for the development environment.

lib/app/view/app.dart

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// ignore_for_file: deprecated_member_use
33

44
import 'package:auth_repository/auth_repository.dart';
5-
import 'package:core/core.dart' hide AppStatus;
5+
import 'package:core/core.dart';
66
import 'package:data_repository/data_repository.dart';
77
import 'package:flex_color_scheme/flex_color_scheme.dart';
88
import 'package:flutter/material.dart';
@@ -33,7 +33,7 @@ class App extends StatelessWidget {
3333
required DataRepository<Headline> headlinesRepository,
3434
required DataRepository<Topic> topicsRepository,
3535
required DataRepository<Source> sourcesRepository,
36-
required DataRepository<UserAppSettings> userAppSettingsRepository,
36+
required DataRepository<AppSettings> appSettingsRepository,
3737
required DataRepository<UserContentPreferences>
3838
userContentPreferencesRepository,
3939
required DataRepository<RemoteConfig> remoteConfigRepository,
@@ -49,7 +49,7 @@ class App extends StatelessWidget {
4949
_headlinesRepository = headlinesRepository,
5050
_topicsRepository = topicsRepository,
5151
_sourcesRepository = sourcesRepository,
52-
_userAppSettingsRepository = userAppSettingsRepository,
52+
_appSettingsRepository = appSettingsRepository,
5353
_userContentPreferencesRepository = userContentPreferencesRepository,
5454
_remoteConfigRepository = remoteConfigRepository,
5555
_kvStorageService = storageService,
@@ -64,7 +64,7 @@ class App extends StatelessWidget {
6464
final DataRepository<Headline> _headlinesRepository;
6565
final DataRepository<Topic> _topicsRepository;
6666
final DataRepository<Source> _sourcesRepository;
67-
final DataRepository<UserAppSettings> _userAppSettingsRepository;
67+
final DataRepository<AppSettings> _appSettingsRepository;
6868
final DataRepository<UserContentPreferences>
6969
_userContentPreferencesRepository;
7070
final DataRepository<RemoteConfig> _remoteConfigRepository;
@@ -86,7 +86,7 @@ class App extends StatelessWidget {
8686
RepositoryProvider.value(value: _headlinesRepository),
8787
RepositoryProvider.value(value: _topicsRepository),
8888
RepositoryProvider.value(value: _sourcesRepository),
89-
RepositoryProvider.value(value: _userAppSettingsRepository),
89+
RepositoryProvider.value(value: _appSettingsRepository),
9090
RepositoryProvider.value(value: _userContentPreferencesRepository),
9191
RepositoryProvider.value(value: _remoteConfigRepository),
9292
RepositoryProvider.value(value: _dashboardSummaryRepository),
@@ -106,8 +106,8 @@ class App extends StatelessWidget {
106106
BlocProvider(
107107
create: (context) => AppBloc(
108108
authenticationRepository: context.read<AuthRepository>(),
109-
userAppSettingsRepository: context
110-
.read<DataRepository<UserAppSettings>>(),
109+
appSettingsRepository: context
110+
.read<DataRepository<AppSettings>>(),
111111
appConfigRepository: context.read<DataRepository<RemoteConfig>>(),
112112
environment: _environment,
113113
logger: Logger('AppBloc'),
@@ -214,20 +214,19 @@ class _AppViewState extends State<_AppView> {
214214
return BlocListener<AppBloc, AppState>(
215215
listenWhen: (previous, current) =>
216216
previous.status != current.status ||
217-
previous.userAppSettings != current.userAppSettings,
217+
previous.appSettings != current.appSettings,
218218
listener: (context, state) {
219219
_statusNotifier.value = state.status;
220220
},
221221
child: BlocBuilder<AppBloc, AppState>(
222222
builder: (context, state) {
223-
final userAppSettings = state.userAppSettings;
224-
final baseTheme = userAppSettings?.displaySettings.baseTheme;
225-
final accentTheme = userAppSettings?.displaySettings.accentTheme;
226-
final fontFamily = userAppSettings?.displaySettings.fontFamily;
227-
final textScaleFactor =
228-
userAppSettings?.displaySettings.textScaleFactor;
229-
final fontWeight = userAppSettings?.displaySettings.fontWeight;
230-
final language = userAppSettings?.language;
223+
final appSettings = state.appSettings;
224+
final baseTheme = appSettings?.displaySettings.baseTheme;
225+
final accentTheme = appSettings?.displaySettings.accentTheme;
226+
final fontFamily = appSettings?.displaySettings.fontFamily;
227+
final textScaleFactor = appSettings?.displaySettings.textScaleFactor;
228+
final fontWeight = appSettings?.displaySettings.fontWeight;
229+
final language = appSettings?.language;
231230

232231
final lightThemeData = lightTheme(
233232
scheme: accentTheme?.toFlexScheme ?? FlexScheme.materialHc,

0 commit comments

Comments
 (0)