Files
BudgetApp/lib/logic/user/user_cubit.dart
T
Sanders 85daede4a9 Implements authentication flow with user registration
This commit implements a complete authentication flow, including user registration.

- Introduces an `AuthRegisterRequested` event to handle user registration.
- Persists the user ID in settings upon successful authentication.
- Modifies `AuthBloc` to load the user based on the stored ID, improving app launch persistence.
- Refactors `UserCubit` to only manage the user state and removes authentication logic.
- Removes `UserCubit` initialization from `main.dart` and triggers `AuthStarted` to initiate the authentication process.
2025-07-12 22:40:31 +03:00

121 lines
4.8 KiB
Dart

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import '/data/repositories/interfaces/icategory_repository.dart';
import '/data/repositories/interfaces/iglobal_settings_repository.dart';
import '/data/repositories/interfaces/itag_repository.dart';
import '/data/repositories/interfaces/itransaction_repository.dart';
import '/data/repositories/interfaces/iuser_repository.dart';
import '/models/user.dart';
import '/utils/category_utils.dart';
import '/utils/tag_utils.dart';
import '/utils/transaction_utils.dart';
part 'user_state.dart';
/// Cubit для управления состоянием пользователя.
/// Больше не управляет процессом входа, а только хранит состояние пользователя.
class UserCubit extends Cubit<UserState> {
final IGlobalSettingsRepository _settingsRepository;
final IUserRepository _userRepository;
// Эти репозитории теперь могут быть null и устанавливаются после входа пользователя.
ICategoryRepository? _categoryRepository;
ITagRepository? _tagRepository;
ITransactionRepository? _transactionRepository;
final Logger _logger = Logger(
printer: PrettyPrinter(
methodCount: 2, // Number of method calls to be displayed
errorMethodCount: 8, // Number of method calls if stacktrace is provided
lineLength: 120, // Width of the output
colors: true, // Colorful log messages
printEmojis: true, // Print an emoji for each log message
// Should each log print contain a timestamp
dateTimeFormat: DateTimeFormat.onlyTimeAndSinceStart,
),
);
UserCubit({
required IGlobalSettingsRepository settingsRepository,
required IUserRepository userRepository,
// Репозитории сделаны опциональными в конструкторе.
ICategoryRepository? categoryRepository,
ITagRepository? tagRepository,
ITransactionRepository? transactionRepository,
}) : _settingsRepository = settingsRepository,
_userRepository = userRepository,
_categoryRepository = categoryRepository,
_tagRepository = tagRepository,
_transactionRepository = transactionRepository,
super(UserInitial());
// Сеттеры для внедрения зависимостей после аутентификации.
set categoryRepository(ICategoryRepository? repo) => _categoryRepository = repo;
set tagRepository(ITagRepository? repo) => _tagRepository = repo;
set transactionRepository(ITransactionRepository? repo) =>
_transactionRepository = repo;
Future<void> createInitialData(String userId) async {
// Проверяем, что репозитории были установлены, прежде чем их использовать.
if (_categoryRepository == null ||
_tagRepository == null ||
_transactionRepository == null) {
_logger.w('User-specific repositories are not initialized. Skipping initial data creation.');
return;
}
try {
// Разбиваем создание данных на этапы
emit(UserLoading(progress: 0.7, message: 'Создание категорий...'));
// Используем '!', так как мы уже проверили на null.
await _categoryRepository!.addAll(
CategoryUtils.getDefaultCategories(),
);
emit(UserLoading(progress: 0.8, message: 'Создание тегов...'));
await _tagRepository!.addAll(TagUtils.getDefaultTags());
emit(UserLoading(progress: 0.9, message: 'Создание транзакций...'));
await _transactionRepository!.addAll(
TransactionUtils.getSampleTransactions(),
);
} catch (e, stack) {
_logger.e(
'Error creating initial data for user: $userId',
error: e,
stackTrace: stack,
);
}
}
/// Устанавливает текущего пользователя (прямая установка без загрузки)
void setUser(User user) {
emit(UserLoaded(user));
}
/// Выход из системы
Future<void> logout() async {
emit(UserLoading());
try {
await _settingsRepository.setCurrentUserId(null);
emit(UserLoaded(null));
} catch (e, stack) {
_logger.e('Error during logout', error: e, stackTrace: stack);
emit(UserError('Ошибка выхода из системы: ${e.toString()}'));
}
}
/// Возвращает всех пользователей
Future<List<User>> getAllUsers() async {
try {
return await _userRepository.getAll();
} catch (e, stack) {
_logger.e('Error getting all users', error: e, stackTrace: stack);
return [];
}
}
}