193 lines
7.5 KiB
Dart
193 lines
7.5 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;
|
|
final ICategoryRepository _categoryRepository;
|
|
final ITagRepository _tagRepository;
|
|
final ITransactionRepository _transactionRepository;
|
|
final Logger _logger = Logger();
|
|
|
|
UserCubit({
|
|
required IGlobalSettingsRepository settingsRepository,
|
|
required IUserRepository userRepository,
|
|
required ICategoryRepository categoryRepository,
|
|
required ITagRepository tagRepository,
|
|
required ITransactionRepository transactionRepository,
|
|
}) : _settingsRepository = settingsRepository,
|
|
_userRepository = userRepository,
|
|
_categoryRepository = categoryRepository,
|
|
_tagRepository = tagRepository,
|
|
_transactionRepository = transactionRepository,
|
|
super(UserInitial());
|
|
|
|
// Метод для инициализации UserCubit
|
|
Future<void> init() async {
|
|
await _init();
|
|
}
|
|
|
|
Future<void> _init() async {
|
|
emit(UserLoading(progress: 0.1, message: 'Поиск пользователя...'));
|
|
try {
|
|
// Этап 1: Проверка существующего пользователя
|
|
final userId = await _settingsRepository.getCurrentUserId();
|
|
emit(UserLoading(progress: 0.3, message: 'Проверка пользователя...'));
|
|
|
|
User? currentUser;
|
|
if (userId != null) {
|
|
currentUser = await _userRepository.getById(userId);
|
|
if (currentUser == null) {
|
|
_logger.w('User with ID $userId not found. Clearing key.');
|
|
await _settingsRepository.setCurrentUserId(null);
|
|
}
|
|
}
|
|
|
|
// Этап 2: Создание пользователя по умолчанию при необходимости
|
|
if (currentUser == null) {
|
|
emit(UserLoading(progress: 0.5, message: 'Проверка данных...'));
|
|
final allUsers = await _userRepository.getAll();
|
|
if (allUsers.isEmpty) {
|
|
_logger.i('No users found, creating default user');
|
|
emit(UserLoading(progress: 0.6, message: 'Создание пользователя...'));
|
|
// Комментарий: Вызываем создание пользователя по умолчанию.
|
|
// Этот метод сам установит состояние UserLoaded, поэтому после него нужно завершить выполнение _init.
|
|
await _createDefaultUser();
|
|
return;
|
|
} else {
|
|
_logger.i('Setting first user as current');
|
|
currentUser = allUsers.first;
|
|
// Комментарий: Устанавливаем первого пользователя как текущего.
|
|
// Этот метод также устанавливает состояние UserLoaded, поэтому выходим.
|
|
await _setCurrentUser(currentUser);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Этап 3: Завершение инициализации (этот блок теперь выполняется только для уже существующих пользователей)
|
|
emit(UserLoading(progress: 1.0, message: 'Завершение...'));
|
|
await Future.delayed(const Duration(milliseconds: 300));
|
|
emit(UserLoaded(currentUser));
|
|
} catch (e, stack) {
|
|
_logger.e('Error initializing user cubit', error: e, stackTrace: stack);
|
|
emit(UserError('Ошибка загрузки пользователя: ${e.toString()}'));
|
|
}
|
|
}
|
|
|
|
Future<User> _createDefaultUser() async {
|
|
final user = User(
|
|
name: 'Пользователь по умолчанию',
|
|
email: 'default@example.com',
|
|
);
|
|
await _userRepository.add(user);
|
|
|
|
// Создаем начальные данные для нового пользователя
|
|
await _createInitialData(user.id);
|
|
|
|
await _setCurrentUser(user);
|
|
return user;
|
|
}
|
|
|
|
Future<void> _createInitialData(String userId) async {
|
|
try {
|
|
// Разбиваем создание данных на этапы
|
|
emit(UserLoading(progress: 0.7, message: 'Создание категорий...'));
|
|
await _categoryRepository.addAll(
|
|
CategoryUtils.getDefaultCategories(userId),
|
|
);
|
|
|
|
emit(UserLoading(progress: 0.8, message: 'Создание тегов...'));
|
|
await _tagRepository.addAll(TagUtils.getDefaultTags(userId));
|
|
|
|
emit(UserLoading(progress: 0.9, message: 'Создание транзакций...'));
|
|
await _transactionRepository.addAll(
|
|
TransactionUtils.getSampleTransactions(userId),
|
|
);
|
|
|
|
_logger.i('Initial data created for user: $userId');
|
|
} catch (e, stack) {
|
|
_logger.e(
|
|
'Error creating initial data for user: $userId',
|
|
error: e,
|
|
stackTrace: stack,
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> _setCurrentUser(User user) async {
|
|
await _settingsRepository.setCurrentUserId(user.id);
|
|
emit(UserLoaded(user));
|
|
}
|
|
|
|
/// Устанавливает текущего пользователя
|
|
Future<void> setCurrentUser(User user) async {
|
|
emit(UserLoading());
|
|
try {
|
|
await _setCurrentUser(user);
|
|
} catch (e, stack) {
|
|
_logger.e('Error setting current user', error: e, stackTrace: stack);
|
|
emit(UserError('Ошибка установки пользователя: ${e.toString()}'));
|
|
}
|
|
}
|
|
|
|
/// Устанавливает текущего пользователя (прямая установка без загрузки)
|
|
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<void> createAndSetUser(String name, String email) async {
|
|
emit(UserLoading());
|
|
try {
|
|
final user = User(name: name, email: email);
|
|
await _userRepository.add(user);
|
|
|
|
// Создаем начальные данные для нового пользователя
|
|
await _createInitialData(user.id);
|
|
|
|
await _setCurrentUser(user);
|
|
} catch (e, stack) {
|
|
_logger.e('Error creating user', 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 [];
|
|
}
|
|
}
|
|
}
|