Skip to content

Commit 1b081d4

Browse files
authored
Merge pull request #15 from headlines-toolkit/firebase_to_custom_api_migration
Firebase to custom api migration
2 parents 48e48b3 + 8405113 commit 1b081d4

Some content is hidden

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

48 files changed

+1955
-1530
lines changed

analysis_options.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ analyzer:
22
errors:
33
avoid_catches_without_on_clauses: ignore
44
avoid_print: ignore
5+
document_ignores: ignore
56
lines_longer_than_80_chars: ignore
67
use_if_null_to_convert_nulls_to_bools: ignore
78
include: package:very_good_analysis/analysis_options.7.0.0.yaml

firebase.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

lib/account/bloc/account_bloc.dart

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
import 'dart:async';
2+
13
import 'package:bloc/bloc.dart';
24
import 'package:equatable/equatable.dart';
3-
import 'package:ht_authentication_repository/ht_authentication_repository.dart';
5+
import 'package:ht_auth_repository/ht_auth_repository.dart';
6+
import 'package:ht_data_repository/ht_data_repository.dart';
7+
import 'package:ht_shared/ht_shared.dart'
8+
show HtHttpException, User, UserContentPreferences;
49

510
part 'account_event.dart';
611
part 'account_state.dart';
@@ -10,41 +15,77 @@ part 'account_state.dart';
1015
/// {@endtemplate}
1116
class AccountBloc extends Bloc<AccountEvent, AccountState> {
1217
/// {@macro account_bloc}
13-
AccountBloc({required HtAuthenticationRepository authenticationRepository})
14-
: _authenticationRepository = authenticationRepository,
15-
super(const AccountState()) {
16-
on<AccountLogoutRequested>(_onLogoutRequested);
18+
AccountBloc({
19+
required HtAuthRepository authenticationRepository,
20+
required HtDataRepository<UserContentPreferences>
21+
userContentPreferencesRepository,
22+
}) : _authenticationRepository = authenticationRepository,
23+
_userContentPreferencesRepository = userContentPreferencesRepository,
24+
super(const AccountState()) {
25+
// Listen to authentication state changes from the repository
26+
_authenticationRepository.authStateChanges.listen(
27+
(user) => add(_AccountUserChanged(user: user)),
28+
);
29+
30+
on<_AccountUserChanged>(_onAccountUserChanged);
31+
on<AccountLoadContentPreferencesRequested>(
32+
_onAccountLoadContentPreferencesRequested,
33+
);
1734
// Handlers for AccountSettingsNavigationRequested and
1835
// AccountBackupNavigationRequested are typically handled in the UI layer
1936
// (e.g., BlocListener navigating) or could emit specific states if needed.
20-
// For now, we only need the logout logic here.
2137
}
2238

23-
final HtAuthenticationRepository _authenticationRepository;
39+
final HtAuthRepository _authenticationRepository;
40+
final HtDataRepository<UserContentPreferences>
41+
_userContentPreferencesRepository;
42+
43+
/// Handles [_AccountUserChanged] events.
44+
///
45+
/// Updates the state with the current user and triggers loading
46+
/// of user preferences if the user is authenticated.
47+
Future<void> _onAccountUserChanged(
48+
_AccountUserChanged event,
49+
Emitter<AccountState> emit,
50+
) async {
51+
emit(state.copyWith(user: event.user));
52+
if (event.user != null) {
53+
// User is authenticated, load preferences
54+
add(AccountLoadContentPreferencesRequested(userId: event.user!.id));
55+
} else {
56+
// User is unauthenticated, clear preferences
57+
emit(state.copyWith());
58+
}
59+
}
2460

25-
/// Handles the [AccountLogoutRequested] event.
61+
/// Handles [AccountLoadContentPreferencesRequested] events.
2662
///
27-
/// Attempts to sign out the user using the [HtAuthenticationRepository].
28-
/// Emits [AccountStatus.loading] before the operation and updates to
29-
/// [AccountStatus.success] or [AccountStatus.failure] based on the outcome.
30-
Future<void> _onLogoutRequested(
31-
AccountLogoutRequested event,
63+
/// Attempts to load the user's content preferences.
64+
Future<void> _onAccountLoadContentPreferencesRequested(
65+
AccountLoadContentPreferencesRequested event,
3266
Emitter<AccountState> emit,
3367
) async {
3468
emit(state.copyWith(status: AccountStatus.loading));
3569
try {
36-
await _authenticationRepository.signOut();
37-
// No need to emit success here. The AppBloc listening to the
38-
// repository's user stream will handle the global state change
39-
// and trigger the necessary UI updates/redirects.
40-
// We can emit an initial state again if needed for this BLoC's
41-
// local state.
42-
emit(state.copyWith(status: AccountStatus.initial));
70+
final preferences = await _userContentPreferencesRepository.read(
71+
id: event.userId,
72+
userId: event.userId, // Preferences are user-scoped
73+
);
74+
emit(
75+
state.copyWith(status: AccountStatus.success, preferences: preferences),
76+
);
77+
} on HtHttpException catch (e) {
78+
emit(
79+
state.copyWith(
80+
status: AccountStatus.failure,
81+
errorMessage: 'Failed to load preferences: ${e.message}',
82+
),
83+
);
4384
} catch (e) {
4485
emit(
4586
state.copyWith(
4687
status: AccountStatus.failure,
47-
errorMessage: 'Logout failed: $e',
88+
errorMessage: 'An unexpected error occurred: $e',
4889
),
4990
);
5091
}

lib/account/bloc/account_event.dart

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,40 @@
11
part of 'account_bloc.dart';
22

3-
/// Base class for all events related to the Account feature.
4-
abstract class AccountEvent extends Equatable {
3+
/// {@template account_event}
4+
/// Base class for Account events.
5+
/// {@endtemplate}
6+
sealed class AccountEvent extends Equatable {
7+
/// {@macro account_event}
58
const AccountEvent();
69

710
@override
8-
List<Object> get props => [];
11+
List<Object?> get props => [];
912
}
1013

11-
/// Event triggered when the user requests to navigate to the settings page.
12-
class AccountSettingsNavigationRequested extends AccountEvent {
13-
const AccountSettingsNavigationRequested();
14-
}
14+
/// {@template _account_user_changed}
15+
/// Internal event triggered when the authenticated user changes.
16+
/// {@endtemplate}
17+
final class _AccountUserChanged extends AccountEvent {
18+
/// {@macro _account_user_changed}
19+
const _AccountUserChanged({required this.user});
20+
21+
/// The current authenticated user, or null if unauthenticated.
22+
final User? user;
1523

16-
/// Event triggered when the user requests to log out.
17-
class AccountLogoutRequested extends AccountEvent {
18-
const AccountLogoutRequested();
24+
@override
25+
List<Object?> get props => [user];
1926
}
2027

21-
/// Event triggered when the user (anonymous) requests to backup/link account.
22-
class AccountBackupNavigationRequested extends AccountEvent {
23-
const AccountBackupNavigationRequested();
28+
/// {@template account_load_content_preferences_requested}
29+
/// Event triggered when the user's content preferences need to be loaded.
30+
/// {@endtemplate}
31+
final class AccountLoadContentPreferencesRequested extends AccountEvent {
32+
/// {@macro account_load_content_preferences_requested}
33+
const AccountLoadContentPreferencesRequested({required this.userId});
34+
35+
/// The ID of the user whose content preferences should be loaded.
36+
final String userId;
37+
38+
@override
39+
List<Object> get props => [userId];
2440
}

lib/account/bloc/account_state.dart

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,59 @@
11
part of 'account_bloc.dart';
22

3-
/// Enum representing the status of the Account feature.
4-
enum AccountStatus { initial, loading, success, failure }
3+
/// Defines the status of the account state.
4+
enum AccountStatus {
5+
/// The initial state.
6+
initial,
57

6-
/// Represents the state of the Account feature.
7-
class AccountState extends Equatable {
8-
const AccountState({this.status = AccountStatus.initial, this.errorMessage});
8+
/// An operation is in progress.
9+
loading,
910

10-
/// The current status of the account feature operations.
11+
/// An operation was successful.
12+
success,
13+
14+
/// An operation failed.
15+
failure,
16+
}
17+
18+
/// {@template account_state}
19+
/// State for the Account feature.
20+
/// {@endtemplate}
21+
final class AccountState extends Equatable {
22+
/// {@macro account_state}
23+
const AccountState({
24+
this.status = AccountStatus.initial,
25+
this.user,
26+
this.preferences,
27+
this.errorMessage,
28+
});
29+
30+
/// The current status of the account state.
1131
final AccountStatus status;
1232

13-
/// An optional error message if an operation failed.
33+
/// The currently authenticated user.
34+
final User? user;
35+
36+
/// The user's content preferences.
37+
final UserContentPreferences? preferences;
38+
39+
/// An error message if an operation failed.
1440
final String? errorMessage;
1541

16-
/// Creates a copy of the current state with updated values.
17-
AccountState copyWith({AccountStatus? status, String? errorMessage}) {
42+
/// Creates a copy of this [AccountState] with the given fields replaced.
43+
AccountState copyWith({
44+
AccountStatus? status,
45+
User? user,
46+
UserContentPreferences? preferences,
47+
String? errorMessage,
48+
}) {
1849
return AccountState(
1950
status: status ?? this.status,
51+
user: user ?? this.user,
52+
preferences: preferences ?? this.preferences,
2053
errorMessage: errorMessage ?? this.errorMessage,
2154
);
2255
}
2356

2457
@override
25-
List<Object?> get props => [status, errorMessage];
58+
List<Object?> get props => [status, user, preferences, errorMessage];
2659
}

0 commit comments

Comments
 (0)