Transfer settings to user

This commit is contained in:
2025-06-27 23:31:16 +03:00
parent 0d64d4ca0e
commit 65fe73b396
6 changed files with 98 additions and 73 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ Future<void> initDependencies() async {
await HiveService.init();
// Регистрация сервисов
getIt.registerSingleton<SettingsCubit>(SettingsCubit()); // Регистрируем Cubit
getIt.registerSingleton<SettingsCubit>(SettingsCubit(getIt())); // Регистрируем Cubit и передаем IUserRepository
// Регистрация репозиториев
getIt.registerSingleton<ICategoryRepository>(
+43 -20
View File
@@ -1,42 +1,65 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:hive_ce/hive.dart';
import 'package:budget_app/data/repositories/interfaces/iuser_repository.dart'; // Комментарий: Импортируем интерфейс репозитория пользователя
import 'package:budget_app/models/user.dart'; // Комментарий: Импортируем модель пользователя
part 'settings_state.dart';
class SettingsCubit extends Cubit<SettingsState> {
static const String _darkModeKey = 'darkMode';
static const String _languageCodeKey = 'languageCode';
static const String _defaultCurrencyKey = 'defaultCurrency'; // Комментарий: Новый ключ для хранения валюты по умолчанию
late final Box _settingsBox;
final IUserRepository _userRepository; // Комментарий: Зависимость от репозитория пользователя
SettingsCubit() : super(const SettingsInitial()) {
_settingsBox = Hive.box('settings');
SettingsCubit(this._userRepository) : super(const SettingsInitial()) { // Комментарий: Принимаем репозиторий в конструкторе
_loadSettings();
}
void _loadSettings() {
final isDarkMode = _settingsBox.get(_darkModeKey, defaultValue: false);
final languageCode = _settingsBox.get(_languageCodeKey, defaultValue: 'ru');
// Комментарий: Загружаем валюту по умолчанию из Hive. Если ее нет, используем 'RUB'.
final defaultCurrency = _settingsBox.get(_defaultCurrencyKey, defaultValue: 'RUB');
emit(state.copyWith(isDarkMode: isDarkMode, languageCode: languageCode, defaultCurrency: defaultCurrency));
void _loadSettings() async {
// Комментарий: Получаем всех пользователей. В реальном приложении здесь будет логика получения текущего залогиненного пользователя.
final users = await _userRepository.getAll();
User currentUser;
if (users.isEmpty) {
// Комментарий: Если пользователей нет, создаем нового с дефолтными настройками.
currentUser = User(name: 'Default User', email: 'default@example.com');
await _userRepository.add(currentUser);
} else {
// Комментарий: Используем первого пользователя как текущего.
currentUser = users.first;
}
emit(state.copyWith(
isDarkMode: currentUser.isDarkMode,
languageCode: currentUser.languageCode,
defaultCurrency: currentUser.defaultCurrency,
));
}
Future<void> setDarkMode(bool value) async {
await _settingsBox.put(_darkModeKey, value);
emit(state.copyWith(isDarkMode: value));
final users = await _userRepository.getAll();
if (users.isNotEmpty) {
final currentUser = users.first;
final updatedUser = currentUser.copyWith(isDarkMode: value);
await _userRepository.update(updatedUser);
emit(state.copyWith(isDarkMode: value));
}
}
Future<void> setLanguageCode(String code) async {
await _settingsBox.put(_languageCodeKey, code);
emit(state.copyWith(languageCode: code));
final users = await _userRepository.getAll();
if (users.isNotEmpty) {
final currentUser = users.first;
final updatedUser = currentUser.copyWith(languageCode: code);
await _userRepository.update(updatedUser);
emit(state.copyWith(languageCode: code));
}
}
// Комментарий: Новый метод для установки валюты по умолчанию.
Future<void> setDefaultCurrency(String currencyCode) async {
await _settingsBox.put(_defaultCurrencyKey, currencyCode);
emit(state.copyWith(defaultCurrency: currencyCode));
final users = await _userRepository.getAll();
if (users.isNotEmpty) {
final currentUser = users.first;
final updatedUser = currentUser.copyWith(defaultCurrency: currencyCode);
await _userRepository.update(updatedUser);
emit(state.copyWith(defaultCurrency: currencyCode));
}
}
void toggleTheme() {
+23 -7
View File
@@ -22,20 +22,28 @@ class User {
final String email;
@HiveField(3) // Поле 3 в Hive - язык пользователя
final String language;
final String languageCode; // Переименовано с 'language' на 'languageCode'
@HiveField(4)
/// Дата и время последнего обновления объекта
final DateTime updatedAt;
@HiveField(5) // Новое поле для режима темы (светлая/темная)
final bool isDarkMode;
@HiveField(6) // Новое поле для валюты по умолчанию
final String defaultCurrency;
/// Конструктор пользователя
/// id генерируется автоматически, если не передан
User({
String? id, // Опциональный параметр - если null, сгенерируется автоматически
required this.name, // Обязательный параметр
required this.email, // Обязательный параметр
this.language = 'ru', // Язык по умолчанию - русский
this.languageCode = 'ru', // Язык по умолчанию - русский
DateTime? updatedAt, // Добавлено поле updatedAt, теперь необязательное
this.isDarkMode = false, // По умолчанию светлая тема
this.defaultCurrency = 'RUB', // Валюта по умолчанию - RUB
}) : id = id ?? IdGenerator.generateId(), // Если id не передан, генерируем новый
updatedAt = updatedAt ?? DateTime.now(); // Устанавливаем текущее время по умолчанию
@@ -45,8 +53,10 @@ class User {
'id': id,
'name': name,
'email': email,
'language': language,
'languageCode': languageCode, // Обновлено имя поля
'updatedAt': updatedAt.toIso8601String(), // Добавлено updatedAt в Map
'isDarkMode': isDarkMode,
'defaultCurrency': defaultCurrency,
};
}
@@ -56,15 +66,17 @@ class User {
id: map['id'],
name: map['name'],
email: map['email'],
language: map['language'] ?? 'ru', // Устанавливаем русский по умолчанию, если язык не указан
languageCode: map['languageCode'] ?? 'ru', // Обновлено имя поля
updatedAt: DateTime.parse(map['updatedAt']), // Добавлено updatedAt при создании из Map
isDarkMode: map['isDarkMode'] ?? false,
defaultCurrency: map['defaultCurrency'] ?? 'RUB',
);
}
/// Переопределяем toString для удобного отображения в логах
@override
String toString() {
return 'User(id: $id, name: $name, email: $email)';
return 'User(id: $id, name: $name, email: $email, languageCode: $languageCode, isDarkMode: $isDarkMode, defaultCurrency: $defaultCurrency)';
}
/// Метод для создания копии объекта с возможностью изменения полей
@@ -72,14 +84,18 @@ class User {
String? id,
String? name,
String? email,
String? language,
String? languageCode, // Обновлено имя поля
bool? isDarkMode,
String? defaultCurrency,
}) {
return User(
id: id ?? this.id,
name: name ?? this.name,
email: email ?? this.email,
language: language ?? this.language,
languageCode: languageCode ?? this.languageCode, // Обновлено имя поля
updatedAt: DateTime.now(), // Обновляем updatedAt при каждом копировании
isDarkMode: isDarkMode ?? this.isDarkMode,
defaultCurrency: defaultCurrency ?? this.defaultCurrency,
);
}
}
+10 -4
View File
@@ -20,15 +20,17 @@ class UserAdapter extends TypeAdapter<User> {
id: fields[0] as String?,
name: fields[1] as String,
email: fields[2] as String,
language: fields[3] == null ? 'ru' : fields[3] as String,
languageCode: fields[3] == null ? 'ru' : fields[3] as String,
updatedAt: fields[4] as DateTime?,
isDarkMode: fields[5] == null ? false : fields[5] as bool,
defaultCurrency: fields[6] == null ? 'RUB' : fields[6] as String,
);
}
@override
void write(BinaryWriter writer, User obj) {
writer
..writeByte(5)
..writeByte(7)
..writeByte(0)
..write(obj.id)
..writeByte(1)
@@ -36,9 +38,13 @@ class UserAdapter extends TypeAdapter<User> {
..writeByte(2)
..write(obj.email)
..writeByte(3)
..write(obj.language)
..write(obj.languageCode)
..writeByte(4)
..write(obj.updatedAt);
..write(obj.updatedAt)
..writeByte(5)
..write(obj.isDarkMode)
..writeByte(6)
..write(obj.defaultCurrency);
}
@override
-34
View File
@@ -1,34 +0,0 @@
import 'package:flutter/material.dart';
import 'package:hive_ce/hive.dart';
class SettingsService extends ChangeNotifier {
static const String _darkModeKey = 'darkMode';
static const String _languageCodeKey = 'languageCode'; // Новый ключ для языка
late final Box _settingsBox;
SettingsService() {
_settingsBox = Hive.box('settings');
}
bool get isDarkMode => _settingsBox.get(_darkModeKey, defaultValue: false);
Future<void> setDarkMode(bool value) async {
await _settingsBox.put(_darkModeKey, value);
notifyListeners();
}
Future<void> toggleTheme() async {
await setDarkMode(!isDarkMode);
}
// Новый геттер для получения кода языка
String get languageCode => _settingsBox.get(_languageCodeKey, defaultValue: 'ru');
// Новый метод для установки кода языка
Future<void> setLanguageCode(String code) async {
await _settingsBox.put(_languageCodeKey, code);
notifyListeners();
}
}
+21 -7
View File
@@ -6,21 +6,22 @@ import 'package:budget_app/utils/tag_utils.dart';
import 'package:budget_app/utils/transaction_utils.dart';
import 'package:flutter/foundation.dart';
import 'package:hive_ce/hive.dart';
import '/models/user.dart';
import '/data/repositories/interfaces/iuser_repository.dart';
import '/models/user.dart';
/// Сервис для управления текущим пользователем приложения
/// Использует ChangeNotifier для уведомления UI об изменениях
class UserService extends ChangeNotifier {
// Ключ для сохранения ID текущего пользователя в настройках
static const String _currentUserKey = 'currentUserId';
late final Box _settingsBox; // Box для хранения настроек
final IUserRepository _userRepository;
final ICategoryRepository _categoryRepository;
final ITagRepository _tagRepository;
final ITransactionRepository _transactionRepository;
User? _currentUser; // Текущий активный пользователь
/// Геттер для получения текущего пользователя
@@ -30,7 +31,12 @@ class UserService extends ChangeNotifier {
bool get hasCurrentUser => _currentUser != null;
/// Конструктор сервиса
UserService(this._userRepository, this._categoryRepository, this._tagRepository, this._transactionRepository) {
UserService(
this._userRepository,
this._categoryRepository,
this._tagRepository,
this._transactionRepository,
) {
_settingsBox = Hive.box('settings');
_loadCurrentUser(); // Загружаем сохраненного пользователя при запуске
}
@@ -61,13 +67,21 @@ class UserService extends ChangeNotifier {
/// Создание нового пользователя и установка его как текущего
Future<void> createAndSetUser(String name, String email) async {
final user = User(name: name, email: email, language: 'ru'); // Устанавливаем язык по умолчанию
final user = User(
name: name,
email: email,
languageCode: 'ru',
); // Устанавливаем язык по умолчанию
await _userRepository.add(user);
// Добавляем начальные категории, теги и транзакции для нового пользователя
await _categoryRepository.addAll(CategoryUtils.getDefaultCategories(user.id));
await _categoryRepository.addAll(
CategoryUtils.getDefaultCategories(user.id),
);
await _tagRepository.addAll(TagUtils.getDefaultTags(user.id));
await _transactionRepository.addAll(TransactionUtils.getSampleTransactions(user.id));
await _transactionRepository.addAll(
TransactionUtils.getSampleTransactions(user.id),
);
await setCurrentUser(user);
}