diff --git a/lib/data/repositories/hive_category_repository.dart b/lib/data/repositories/hive_category_repository.dart index 37adda6..38a0e09 100644 --- a/lib/data/repositories/hive_category_repository.dart +++ b/lib/data/repositories/hive_category_repository.dart @@ -76,7 +76,7 @@ class HiveCategoryRepository implements ICategoryRepository { @override Future> getAllByUser(String userId) async { try { - return _box.values.where((c) => c.userId == userId).toList(); + return _box.values.toList(); } catch (e) { throw Exception('Ошибка получения категорий пользователя: $e'); } @@ -86,7 +86,7 @@ class HiveCategoryRepository implements ICategoryRepository { Future> getIncomeCategoriesByUser(String userId) async { try { return _box.values - .where((c) => c.userId == userId && c.isIncome) + .where((c) => c.isIncome) .toList(); } catch (e) { throw Exception('Ошибка получения категорий доходов пользователя: $e'); @@ -97,7 +97,7 @@ class HiveCategoryRepository implements ICategoryRepository { Future> getExpenseCategoriesByUser(String userId) async { try { return _box.values - .where((c) => c.userId == userId && !c.isIncome) + .where((c) => !c.isIncome) .toList(); } catch (e) { throw Exception('Ошибка получения категорий расходов пользователя: $e'); diff --git a/lib/data/repositories/hive_settings_repository.dart b/lib/data/repositories/hive_settings_repository.dart index 8a34d65..797311f 100644 --- a/lib/data/repositories/hive_settings_repository.dart +++ b/lib/data/repositories/hive_settings_repository.dart @@ -5,15 +5,26 @@ import 'package:hive_ce/hive.dart'; /// Реализация репозитория настроек с использованием Hive class HiveSettingsRepository implements ISettingsRepository { final Box _box; + + // Фиксированный ключ для хранения настроек приложения + static const String _settingsKey = 'user_settings'; HiveSettingsRepository(this._box); @override - Future getSettings(String userId) async { + Future getSettings() async { try { - // Возвращаем настройки пользователя или создаем новые по умолчанию - final settings = _box.get(userId, defaultValue: AppSettings(userId: userId)); - return settings!; // Гарантируем возврат не-null значения + // Получаем настройки по ключу вместо индекса + final settings = _box.get(_settingsKey); + + // Если настройки не существуют, создаем новые с значениями по умолчанию + if (settings == null) { + final defaultSettings = AppSettings(); + await _box.put(_settingsKey, defaultSettings); + return defaultSettings; + } + + return settings; } catch (e) { throw Exception('Ошибка получения настроек: $e'); } @@ -22,17 +33,18 @@ class HiveSettingsRepository implements ISettingsRepository { @override Future saveSettings(AppSettings settings) async { try { - // Сохраняем настройки с ключом = userId - await _box.put(settings.userId, settings); + // Сохраняем настройки с фиксированным ключом + await _box.put(_settingsKey, settings); } catch (e) { throw Exception('Ошибка сохранения настроек: $e'); } } @override - Future deleteSettings(String userId) async { + Future deleteSettings() async { try { - await _box.delete(userId); + // Удаляем настройки по фиксированному ключу + await _box.delete(_settingsKey); } catch (e) { throw Exception('Ошибка удаления настроек: $e'); } diff --git a/lib/data/repositories/hive_sms_handler_repository.dart b/lib/data/repositories/hive_sms_handler_repository.dart index 47e64e4..e6e7219 100644 --- a/lib/data/repositories/hive_sms_handler_repository.dart +++ b/lib/data/repositories/hive_sms_handler_repository.dart @@ -10,26 +10,25 @@ class HiveSmsHandlerRepository implements ISmsHandlerRepository { HiveSmsHandlerRepository(this._smsHandlerBox); @override - Future getSmsHandlerSettings(String userId) async { + Future getSmsHandlerSettings() async { // В Hive мы будем использовать ID пользователя как ключ для его настроек. - return _smsHandlerBox.get(userId); + return _smsHandlerBox.getAt(1); } @override Future saveSmsHandlerSettings(SmsHandlerSettings settings) async { // Сохраняем объект настроек по ключу, равному ID пользователя. - await _smsHandlerBox.put(settings.userId, settings); + await _smsHandlerBox.put(settings.id, settings); } @override - Future saveRuleForSender(String userId, String sender, SmsProcessingRule rule) async { + Future saveRuleForSender(String sender, SmsProcessingRule rule) async { // 1. Получаем текущие настройки. - SmsHandlerSettings? settings = await getSmsHandlerSettings(userId); + SmsHandlerSettings? settings = await getSmsHandlerSettings(); if (settings == null) { // 2. Если настроек нет, создаем новый объект. settings = SmsHandlerSettings( - userId: userId, rulesBySender: {sender: rule}, // Создаем карту с первым правилом ); } else { @@ -42,9 +41,9 @@ class HiveSmsHandlerRepository implements ISmsHandlerRepository { } @override - Future deleteRuleForSender(String userId, String sender) async { + Future deleteRuleForSender(String sender) async { // 1. Получаем текущие настройки. - final settings = await getSmsHandlerSettings(userId); + final settings = await getSmsHandlerSettings(); if (settings != null) { // 2. Если настройки существуют, удаляем правило для отправителя. diff --git a/lib/data/repositories/hive_transaction_repository.dart b/lib/data/repositories/hive_transaction_repository.dart index 36b0457..bbb4962 100644 --- a/lib/data/repositories/hive_transaction_repository.dart +++ b/lib/data/repositories/hive_transaction_repository.dart @@ -60,40 +60,6 @@ class HiveTransactionRepository implements ITransactionRepository { .toList(); } - // Добавляем новый метод для получения всех транзакций конкретного пользователя - @override - Future> getAllByUser(String userId) async { - // Фильтруем все транзакции в Box по userId - return _box.values.where((t) => t.userId == userId).toList(); - } - - // Добавляем новый метод для получения транзакций пользователя по диапазону дат - @override - Future> getByUserAndDateRange(String userId, DateTime from, DateTime to) async { - // Фильтруем транзакции сначала по userId, затем по диапазону дат - return _box.values - .where((t) => t.userId == userId && t.dateTime.isAfter(from) && t.dateTime.isBefore(to)) - .toList(); - } - - // Добавляем новый метод для получения транзакций пользователя по категории - @override - Future> getByUserAndCategory(String userId, String categoryId) async { - // Фильтруем транзакции сначала по userId, затем по категории - return _box.values - .where((t) => t.userId == userId && t.category.id == categoryId) - .toList(); - } - - // Добавляем новый метод для получения транзакций пользователя по тегу - @override - Future> getByUserAndTag(String userId, String tagId) async { - // Фильтруем транзакции сначала по userId, затем по тегу - return _box.values - .where((t) => t.userId == userId && t.tag?.id == tagId) - .toList(); - } - @override Future addAll(List transactions) async { final Map transactionMap = { diff --git a/lib/data/repositories/interfaces/icategory_repository.dart b/lib/data/repositories/interfaces/icategory_repository.dart index a2eb91c..c43e4ee 100644 --- a/lib/data/repositories/interfaces/icategory_repository.dart +++ b/lib/data/repositories/interfaces/icategory_repository.dart @@ -10,16 +10,6 @@ abstract class ICategoryRepository { Future> getIncomeCategories(); Future> getExpenseCategories(); - // Новые методы для работы с пользователями - /// Получить все категории конкретного пользователя - Future> getAllByUser(String userId); - - /// Получить категории доходов конкретного пользователя - Future> getIncomeCategoriesByUser(String userId); - - /// Получить категории расходов конкретного пользователя - Future> getExpenseCategoriesByUser(String userId); - /// Добавить список категорий Future addAll(List categories); } diff --git a/lib/data/repositories/interfaces/isettings_repository.dart b/lib/data/repositories/interfaces/isettings_repository.dart index a9cf609..76c4b65 100644 --- a/lib/data/repositories/interfaces/isettings_repository.dart +++ b/lib/data/repositories/interfaces/isettings_repository.dart @@ -4,7 +4,7 @@ import 'package:budget_app/models/app_settings.dart'; abstract class ISettingsRepository { /// Получает настройки для указанного пользователя /// [userId] - идентификатор пользователя - Future getSettings(String userId); + Future getSettings(); /// Сохраняет настройки /// [settings] - объект настроек для сохранения @@ -12,5 +12,5 @@ abstract class ISettingsRepository { /// Удаляет настройки для указанного пользователя /// [userId] - идентификатор пользователя - Future deleteSettings(String userId); + Future deleteSettings(); } diff --git a/lib/data/repositories/interfaces/isms_handler_repository.dart b/lib/data/repositories/interfaces/isms_handler_repository.dart index 13e28d8..c2605f8 100644 --- a/lib/data/repositories/interfaces/isms_handler_repository.dart +++ b/lib/data/repositories/interfaces/isms_handler_repository.dart @@ -6,9 +6,7 @@ import '../../../models/sms_handler_settings.dart'; abstract class ISmsHandlerRepository { /// Получает настройки обработки СМС для указанного пользователя. /// - /// [userId] - Уникальный идентификатор пользователя. - /// Возвращает [SmsHandlerSettings] или null, если настроек нет. - Future getSmsHandlerSettings(String userId); + Future getSmsHandlerSettings(); /// Сохраняет или обновляет настройки обработки СМС для пользователя. /// @@ -20,11 +18,11 @@ abstract class ISmsHandlerRepository { /// [userId] - ID пользователя. /// [sender] - Идентификатор отправителя (например, 'SBERBANK'). /// [rule] - Правило обработки. - Future saveRuleForSender(String userId, String sender, SmsProcessingRule rule); + Future saveRuleForSender(String sender, SmsProcessingRule rule); /// Удаляет правило для конкретного отправителя. /// /// [userId] - ID пользователя. /// [sender] - Идентификатор отправителя, чье правило нужно удалить. - Future deleteRuleForSender(String userId, String sender); + Future deleteRuleForSender(String sender); } diff --git a/lib/data/repositories/interfaces/itag_repository.dart b/lib/data/repositories/interfaces/itag_repository.dart index 266e9a3..99f0ec9 100644 --- a/lib/data/repositories/interfaces/itag_repository.dart +++ b/lib/data/repositories/interfaces/itag_repository.dart @@ -7,12 +7,6 @@ abstract class ITagRepository { Future update(Tag tag); Future delete(String id); - // Комментарий: Добавляем новый абстрактный метод в интерфейс. - // Все классы, которые реализуют этот интерфейс, должны будут предоставить - // реализацию этого метода. Это гарантирует, что наш репозиторий - // сможет получать теги для конкретного пользователя. - Future> getAllByUser(String userId); - /// Добавить список тегов Future addAll(List tags); } diff --git a/lib/data/repositories/interfaces/itransaction_repository.dart b/lib/data/repositories/interfaces/itransaction_repository.dart index 876652d..4437e20 100644 --- a/lib/data/repositories/interfaces/itransaction_repository.dart +++ b/lib/data/repositories/interfaces/itransaction_repository.dart @@ -11,13 +11,6 @@ abstract class ITransactionRepository { Future> getByCategory(String categoryId); Future> getByTag(String tagId); - // Добавляем новые методы для работы с транзакциями конкретного пользователя - // Это важно для многопользовательской архитектуры - Future> getAllByUser(String userId); - Future> getByUserAndDateRange(String userId, DateTime from, DateTime to); - Future> getByUserAndCategory(String userId, String categoryId); - Future> getByUserAndTag(String userId, String tagId); - /// Добавить список транзакций Future addAll(List transactions); } diff --git a/lib/hive/hive_adapters.dart b/lib/hive/hive_adapters.dart index 03911cc..8beb5f6 100644 --- a/lib/hive/hive_adapters.dart +++ b/lib/hive/hive_adapters.dart @@ -4,8 +4,6 @@ import 'package:hive_ce/hive.dart'; @GenerateAdapters([ - AdapterSpec(), AdapterSpec(), - AdapterSpec(), ]) part 'hive_adapters.g.dart'; diff --git a/lib/hive/hive_adapters.g.dart b/lib/hive/hive_adapters.g.dart index 9095817..0a774a3 100644 --- a/lib/hive/hive_adapters.g.dart +++ b/lib/hive/hive_adapters.g.dart @@ -6,38 +6,6 @@ part of 'hive_adapters.dart'; // AdaptersGenerator // ************************************************************************** -class ColorAdapter extends TypeAdapter { - @override - final typeId = 0; - - @override - Color read(BinaryReader reader) { - final numOfFields = reader.readByte(); - final fields = { - for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), - }; - return Color((fields[0] as num).toInt()); - } - - @override - void write(BinaryWriter writer, Color obj) { - writer - ..writeByte(1) - ..writeByte(0) - ..write(obj.value); - } - - @override - int get hashCode => typeId.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is ColorAdapter && - runtimeType == other.runtimeType && - typeId == other.typeId; -} - class IconDataAdapter extends TypeAdapter { @override final typeId = 1; @@ -83,58 +51,3 @@ class IconDataAdapter extends TypeAdapter { runtimeType == other.runtimeType && typeId == other.typeId; } - -class DateTimeAdapter extends TypeAdapter { - @override - final typeId = 2; - - @override - DateTime read(BinaryReader reader) { - final numOfFields = reader.readByte(); - final fields = { - for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), - }; - return DateTime( - (fields[0] as num).toInt(), - fields[1] == null ? 1 : (fields[1] as num).toInt(), - fields[2] == null ? 1 : (fields[2] as num).toInt(), - fields[3] == null ? 0 : (fields[3] as num).toInt(), - fields[4] == null ? 0 : (fields[4] as num).toInt(), - fields[5] == null ? 0 : (fields[5] as num).toInt(), - fields[6] == null ? 0 : (fields[6] as num).toInt(), - fields[7] == null ? 0 : (fields[7] as num).toInt(), - ); - } - - @override - void write(BinaryWriter writer, DateTime obj) { - writer - ..writeByte(8) - ..writeByte(0) - ..write(obj.year) - ..writeByte(1) - ..write(obj.month) - ..writeByte(2) - ..write(obj.day) - ..writeByte(3) - ..write(obj.hour) - ..writeByte(4) - ..write(obj.minute) - ..writeByte(5) - ..write(obj.second) - ..writeByte(6) - ..write(obj.millisecond) - ..writeByte(7) - ..write(obj.microsecond); - } - - @override - int get hashCode => typeId.hashCode; - - @override - bool operator ==(Object other) => - identical(this, other) || - other is DateTimeAdapter && - runtimeType == other.runtimeType && - typeId == other.typeId; -} diff --git a/lib/hive/hive_adapters.g.yaml b/lib/hive/hive_adapters.g.yaml index 4b38796..8740adf 100644 --- a/lib/hive/hive_adapters.g.yaml +++ b/lib/hive/hive_adapters.g.yaml @@ -3,12 +3,6 @@ # Check in to version control nextTypeId: 3 types: - Color: - typeId: 0 - nextIndex: 1 - fields: - value: - index: 0 IconData: typeId: 1 nextIndex: 5 @@ -23,23 +17,3 @@ types: index: 3 fontFamilyFallback: index: 4 - DateTime: - typeId: 2 - nextIndex: 8 - fields: - year: - index: 0 - month: - index: 1 - day: - index: 2 - hour: - index: 3 - minute: - index: 4 - second: - index: 5 - millisecond: - index: 6 - microsecond: - index: 7 diff --git a/lib/hive/hive_registrar.g.dart b/lib/hive/hive_registrar.g.dart index 7e3d1e9..710b1ef 100644 --- a/lib/hive/hive_registrar.g.dart +++ b/lib/hive/hive_registrar.g.dart @@ -17,8 +17,6 @@ extension HiveRegistrar on HiveInterface { void registerAdapters() { registerAdapter(AppSettingsAdapter()); registerAdapter(CategoryAdapter()); - registerAdapter(ColorAdapter()); - registerAdapter(DateTimeAdapter()); registerAdapter(GlobalSettingsAdapter()); registerAdapter(IconDataAdapter()); registerAdapter(SmsHandlerSettingsAdapter()); @@ -35,8 +33,6 @@ extension IsolatedHiveRegistrar on IsolatedHiveInterface { void registerAdapters() { registerAdapter(AppSettingsAdapter()); registerAdapter(CategoryAdapter()); - registerAdapter(ColorAdapter()); - registerAdapter(DateTimeAdapter()); registerAdapter(GlobalSettingsAdapter()); registerAdapter(IconDataAdapter()); registerAdapter(SmsHandlerSettingsAdapter()); diff --git a/lib/injection_container.dart b/lib/injection_container.dart index 04e7c6e..021c48e 100644 --- a/lib/injection_container.dart +++ b/lib/injection_container.dart @@ -155,7 +155,7 @@ Future initUserSpecificDependencies(String userId) async { await getIt.unregister(); } getIt.registerFactory( - () => CategoryCubit(getIt(), userId), // Добавляем userId + () => CategoryCubit(getIt()), // Добавляем userId ); // Теги diff --git a/lib/logic/category/category_cubit.dart b/lib/logic/category/category_cubit.dart index ab7f2b4..c2fab28 100644 --- a/lib/logic/category/category_cubit.dart +++ b/lib/logic/category/category_cubit.dart @@ -1,8 +1,10 @@ +import 'package:equatable/equatable.dart'; // equatable для сравнения объектов import 'package:flutter_bloc/flutter_bloc.dart'; import '../../data/repositories/interfaces/icategory_repository.dart'; import '../../models/category.dart'; -import 'category_state.dart'; + +part 'category_state.dart'; // Используем part для разделения файла /// Cubit для управления категориями /// Изменения: @@ -10,15 +12,14 @@ import 'category_state.dart'; /// - Упрощена работа с состояниями по аналогии с TagCubit class CategoryCubit extends Cubit { final ICategoryRepository repository; - final String userId; // Храним userId в cubit - CategoryCubit(this.repository, this.userId) : super(CategoryInitial()); + CategoryCubit(this.repository) : super(CategoryInitial()); /// Загружает категории для текущего пользователя Future loadCategories() async { emit(CategoryLoading()); try { - final categories = await repository.getAllByUser(userId); + final categories = await repository.getAll(); emit(CategoryLoaded(categories)); } catch (e) { emit(CategoryError('Ошибка загрузки категорий: $e')); @@ -29,7 +30,7 @@ class CategoryCubit extends Cubit { Future addCategory(Category category) async { try { // Устанавливаем userId для категории из cubit - final newCategory = category.copyWith(userId: userId); + final newCategory = category.copyWith(); await repository.add(newCategory); // Перезагружаем список категорий await loadCategories(); diff --git a/lib/logic/category/category_state.dart b/lib/logic/category/category_state.dart new file mode 100644 index 0000000..24191ee --- /dev/null +++ b/lib/logic/category/category_state.dart @@ -0,0 +1,30 @@ +part of 'category_cubit.dart'; + +abstract class CategoryState extends Equatable { + const CategoryState(); + + @override + List get props => []; +} + +class CategoryInitial extends CategoryState {} + +class CategoryLoading extends CategoryState {} + +class CategoryLoaded extends CategoryState { + final List categories; + + const CategoryLoaded(this.categories); + + @override + List get props => [categories]; +} + +class CategoryError extends CategoryState { + final String message; + + const CategoryError(this.message); + + @override + List get props => [message]; +} diff --git a/lib/logic/settings/settings_cubit.dart b/lib/logic/settings/settings_cubit.dart index 797f588..f4891b3 100644 --- a/lib/logic/settings/settings_cubit.dart +++ b/lib/logic/settings/settings_cubit.dart @@ -12,10 +12,10 @@ class SettingsCubit extends Cubit { SettingsCubit(this._settingsRepository) : super(SettingsInitial()); - Future loadSettings(String userId) async { + Future loadSettings() async { emit(SettingsLoading()); try { - final settings = await _settingsRepository.getSettings(userId); + final settings = await _settingsRepository.getSettings(); emit(SettingsLoaded( isDarkMode: settings.isDarkMode, languageCode: settings.languageCode, @@ -26,48 +26,47 @@ class SettingsCubit extends Cubit { } } - Future toggleDarkMode(bool value, String userId) async { + Future toggleDarkMode(bool value) async { if (state is SettingsLoaded) { try { final currentState = state as SettingsLoaded; final newState = currentState.copyWith(isDarkMode: value); emit(newState); - await _saveSettings(newState, userId); + await _saveSettings(newState); } catch (e) { emit(SettingsError(e.toString())); } } } - Future changeLanguage(String languageCode, String userId) async { + Future changeLanguage(String languageCode) async { if (state is SettingsLoaded) { try { final currentState = state as SettingsLoaded; final newState = currentState.copyWith(languageCode: languageCode); emit(newState); - await _saveSettings(newState, userId); + await _saveSettings(newState); } catch (e) { emit(SettingsError(e.toString())); } } } - Future changeCurrency(String currency, String userId) async { + Future changeCurrency(String currency) async { if (state is SettingsLoaded) { try { final currentState = state as SettingsLoaded; final newState = currentState.copyWith(defaultCurrency: currency); emit(newState); - await _saveSettings(newState, userId); + await _saveSettings(newState); } catch (e) { emit(SettingsError(e.toString())); } } } - Future _saveSettings(SettingsLoaded settings, String userId) async { + Future _saveSettings(SettingsLoaded settings) async { final appSettings = AppSettings( - userId: userId, isDarkMode: settings.isDarkMode, languageCode: settings.languageCode, defaultCurrency: settings.defaultCurrency, diff --git a/lib/logic/sms/sms_cubit.dart b/lib/logic/sms/sms_cubit.dart index 5cd9844..264d63f 100644 --- a/lib/logic/sms/sms_cubit.dart +++ b/lib/logic/sms/sms_cubit.dart @@ -31,13 +31,8 @@ class SmsCubit extends Cubit { try { final hasPermissions = await _smsService.requestPermissions(); if (hasPermissions) { - final userState = _userCubit.state; - if (userState is UserLoaded) { - final messages = await _smsService.getLastSmsMessages(10, userState.user!.id); - emit(SmsLoaded(messages)); - } else { - emit(SmsError("User not loaded")); - } + final messages = await _smsService.getLastSmsMessages(10); + emit(SmsLoaded(messages)); } else { emit(SmsPermissionDenied()); } @@ -60,7 +55,7 @@ class SmsCubit extends Cubit { final user = userState.user; // Комментарий: Получаем все SMS-сообщения с момента последней синхронизации. - final messages = await _smsService.getSmsMessagesSince(user!.lastSmsSyncTime, user.id); + final messages = await _smsService.getSmsMessagesSince(user!.lastSmsSyncTime); // Комментарий: Сохраняем новые сообщения через репозиторий и создаем транзакции. await _smsRepository.addAll(messages); diff --git a/lib/logic/transaction/transaction_bloc.dart b/lib/logic/transaction/transaction_bloc.dart index 46701e9..e499bd8 100644 --- a/lib/logic/transaction/transaction_bloc.dart +++ b/lib/logic/transaction/transaction_bloc.dart @@ -21,7 +21,7 @@ class TransactionBloc extends Bloc { void _onLoadTransactions(LoadTransactions event, Emitter emit) async { emit(TransactionLoading()); try { - final transactions = await _transactionRepository.getAllByUser(event.userId); + final transactions = await _transactionRepository.getAll(); emit(TransactionLoaded(transactions: transactions)); } catch (e) { emit(TransactionError(message: e.toString())); @@ -31,7 +31,7 @@ class TransactionBloc extends Bloc { void _onAddTransaction(AddTransaction event, Emitter emit) async { try { await _transactionRepository.add(event.transaction); - final transactions = await _transactionRepository.getAllByUser(event.transaction.userId); + final transactions = await _transactionRepository.getAll(); emit(TransactionLoaded(transactions: transactions)); } catch (e) { emit(TransactionError(message: e.toString())); @@ -41,7 +41,7 @@ class TransactionBloc extends Bloc { void _onUpdateTransaction(UpdateTransaction event, Emitter emit) async { try { await _transactionRepository.update(event.transaction); - final transactions = await _transactionRepository.getAllByUser(event.transaction.userId); + final transactions = await _transactionRepository.getAll(); emit(TransactionLoaded(transactions: transactions)); } catch (e) { emit(TransactionError(message: e.toString())); @@ -54,9 +54,8 @@ class TransactionBloc extends Bloc { if (state is TransactionLoaded) { final loadedState = state as TransactionLoaded; if (loadedState.transactions.isNotEmpty) { - final userId = loadedState.transactions.first.userId; await _transactionRepository.delete(event.transactionId); - final transactions = await _transactionRepository.getAllByUser(userId); + final transactions = await _transactionRepository.getAll(); emit(TransactionLoaded(transactions: transactions)); } } diff --git a/lib/logic/user/user_cubit.dart b/lib/logic/user/user_cubit.dart index 06f2cd0..9f08511 100644 --- a/lib/logic/user/user_cubit.dart +++ b/lib/logic/user/user_cubit.dart @@ -87,22 +87,7 @@ class UserCubit extends Cubit { emit(UserError('Ошибка загрузки пользователя: ${e.toString()}')); } } - - Future _createDefaultUser() async { - final user = User( - name: 'Пользователь по умолчанию', - email: 'default@example.com', - ); - await _userRepository.add(user); - - // Создаем начальные данные для нового пользователя - await _createInitialData(user.id); - - await _setCurrentUser(user); - return user; - } - - Future _createInitialData(String userId) async { + Future createInitialData(String userId) async { // Проверяем, что репозитории были установлены, прежде чем их использовать. if (_categoryRepository == null || _tagRepository == null || @@ -115,15 +100,15 @@ class UserCubit extends Cubit { emit(UserLoading(progress: 0.7, message: 'Создание категорий...')); // Используем '!', так как мы уже проверили на null. await _categoryRepository!.addAll( - CategoryUtils.getDefaultCategories(userId), + CategoryUtils.getDefaultCategories(), ); emit(UserLoading(progress: 0.8, message: 'Создание тегов...')); - await _tagRepository!.addAll(TagUtils.getDefaultTags(userId)); + await _tagRepository!.addAll(TagUtils.getDefaultTags()); emit(UserLoading(progress: 0.9, message: 'Создание транзакций...')); await _transactionRepository!.addAll( - TransactionUtils.getSampleTransactions(userId), + TransactionUtils.getSampleTransactions(), ); } catch (e, stack) { @@ -176,7 +161,7 @@ class UserCubit extends Cubit { await _userRepository.add(user); // Создаем начальные данные для нового пользователя - await _createInitialData(user.id); + await createInitialData(user.id); await _setCurrentUser(user); } catch (e, stack) { diff --git a/lib/models/app_settings.dart b/lib/models/app_settings.dart index 9f5a69b..d01c438 100644 --- a/lib/models/app_settings.dart +++ b/lib/models/app_settings.dart @@ -1,13 +1,13 @@ import 'package:equatable/equatable.dart'; import 'package:hive_ce/hive.dart'; +import '../utils/id_generator.dart'; part 'app_settings.g.dart'; @HiveType(typeId: 1005) class AppSettings extends Equatable { - /// Ссылка на ID пользователя, которому принадлежат настройки @HiveField(0) - final String userId; + final String id; /// Код языка интерфейса (например, 'ru', 'en') @HiveField(1) @@ -26,17 +26,17 @@ class AppSettings extends Equatable { final DateTime updatedAt; AppSettings({ - required this.userId, + String? id, this.languageCode = 'ru', this.isDarkMode = false, this.defaultCurrency = 'RUB', DateTime? updatedAt, - }) : updatedAt = updatedAt ?? DateTime.now(); + }) : id = id ?? IdGenerator.generateId(), + updatedAt = updatedAt ?? DateTime.now(); /// Преобразование в Map для сохранения Map toMap() { return { - 'userId': userId, 'languageCode': languageCode, 'isDarkMode': isDarkMode, 'defaultCurrency': defaultCurrency, @@ -47,7 +47,6 @@ class AppSettings extends Equatable { /// Создание из Map factory AppSettings.fromMap(Map map) { return AppSettings( - userId: map['userId'], languageCode: map['languageCode'] ?? 'ru', isDarkMode: map['isDarkMode'] ?? false, defaultCurrency: map['defaultCurrency'] ?? 'RUB', @@ -63,7 +62,6 @@ class AppSettings extends Equatable { String? defaultCurrency, }) { return AppSettings( - userId: userId ?? this.userId, languageCode: languageCode ?? this.languageCode, isDarkMode: isDarkMode ?? this.isDarkMode, defaultCurrency: defaultCurrency ?? this.defaultCurrency, @@ -72,17 +70,11 @@ class AppSettings extends Equatable { } @override - List get props => [ - userId, - languageCode, - isDarkMode, - defaultCurrency, - updatedAt, - ]; + List get props => [id]; @override String toString() { - return 'AppSettings(userId: $userId, languageCode: $languageCode, ' + return 'AppSettings(languageCode: $languageCode, ' 'isDarkMode: $isDarkMode, defaultCurrency: $defaultCurrency)'; } } diff --git a/lib/models/app_settings.g.dart b/lib/models/app_settings.g.dart index 7069a2c..3387a9b 100644 --- a/lib/models/app_settings.g.dart +++ b/lib/models/app_settings.g.dart @@ -17,7 +17,6 @@ class AppSettingsAdapter extends TypeAdapter { for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), }; return AppSettings( - userId: fields[0] as String, languageCode: fields[1] == null ? 'ru' : fields[1] as String, isDarkMode: fields[2] == null ? false : fields[2] as bool, defaultCurrency: fields[3] == null ? 'RUB' : fields[3] as String, @@ -28,9 +27,7 @@ class AppSettingsAdapter extends TypeAdapter { @override void write(BinaryWriter writer, AppSettings obj) { writer - ..writeByte(5) - ..writeByte(0) - ..write(obj.userId) + ..writeByte(4) ..writeByte(1) ..write(obj.languageCode) ..writeByte(2) diff --git a/lib/models/category.dart b/lib/models/category.dart index 99c2817..c4e88bb 100644 --- a/lib/models/category.dart +++ b/lib/models/category.dart @@ -32,11 +32,6 @@ class Category extends Equatable { /// false - расход (например покупки) final bool isIncome; - @HiveField(5) - /// Идентификатор пользователя, которому принадлежит эта категория - /// Это позволяет разделять категории между разными пользователями - final String userId; - @HiveField(6) /// Дата и время последнего обновления объекта final DateTime updatedAt; @@ -48,7 +43,6 @@ class Category extends Equatable { required this.color, required this.icon, required this.isIncome, - required this.userId, // Теперь userId обязательный параметр DateTime? updatedAt, // Добавлено поле updatedAt, теперь необязательное }) : id = id ?? IdGenerator.generateId(), updatedAt = updatedAt ?? DateTime.now(); // Устанавливаем текущее время по умолчанию @@ -61,7 +55,6 @@ class Category extends Equatable { 'color': color.toARGB32(), // Сохраняем только значение цвета 'icon': icon.codePoint, 'isIncome': isIncome, - 'userId': userId, // Добавляем userId в Map 'updatedAt': updatedAt.toIso8601String(), // Добавлено updatedAt в Map }; } @@ -74,7 +67,6 @@ class Category extends Equatable { color: Color(map['color']), icon: IconData(map['icon'], fontFamily: 'MaterialIcons'), isIncome: map['isIncome'], - userId: map['userId'], // Добавляем userId при создании из Map updatedAt: DateTime.parse(map['updatedAt']), // Добавлено updatedAt при создании из Map ); } @@ -94,7 +86,6 @@ class Category extends Equatable { color: color ?? this.color, icon: icon ?? this.icon, isIncome: isIncome ?? this.isIncome, - userId: userId ?? this.userId, updatedAt: DateTime.now(), // Обновляем updatedAt при каждом копировании ); } diff --git a/lib/models/category.g.dart b/lib/models/category.g.dart index 64cd3f3..790cc54 100644 --- a/lib/models/category.g.dart +++ b/lib/models/category.g.dart @@ -22,7 +22,6 @@ class CategoryAdapter extends TypeAdapter { color: fields[2] as Color, icon: fields[3] as IconData, isIncome: fields[4] as bool, - userId: fields[5] as String, updatedAt: fields[6] as DateTime?, ); } @@ -30,7 +29,7 @@ class CategoryAdapter extends TypeAdapter { @override void write(BinaryWriter writer, Category obj) { writer - ..writeByte(7) + ..writeByte(6) ..writeByte(0) ..write(obj.id) ..writeByte(1) @@ -41,8 +40,6 @@ class CategoryAdapter extends TypeAdapter { ..write(obj.icon) ..writeByte(4) ..write(obj.isIncome) - ..writeByte(5) - ..write(obj.userId) ..writeByte(6) ..write(obj.updatedAt); } diff --git a/lib/models/sms_handler_settings.dart b/lib/models/sms_handler_settings.dart index 86efbba..3b4c934 100644 --- a/lib/models/sms_handler_settings.dart +++ b/lib/models/sms_handler_settings.dart @@ -1,6 +1,7 @@ import 'package:hive_ce/hive.dart'; +import '/utils/id_generator.dart'; part 'sms_handler_settings.g.dart'; /// Перечисление для определения типа обработки СМС. @@ -31,7 +32,11 @@ class SmsProcessingRule extends HiveObject { @HiveField(2) final String? customFunctionId; + @HiveField(3) + final String id; + SmsProcessingRule({ + String? id, required this.type, this.pattern, this.customFunctionId, @@ -39,23 +44,22 @@ class SmsProcessingRule extends HiveObject { (type == SmsProcessingType.regexp && pattern != null) || (type == SmsProcessingType.customFunction && customFunctionId != null), 'Pattern must be provided for regexp type, and customFunctionId for customFunction type.', - ); + ), id = id ?? IdGenerator.generateId(); } /// Модель для хранения всех настроек обработки СМС для одного пользователя. @HiveType(typeId: 12) class SmsHandlerSettings extends HiveObject { - /// Уникальный идентификатор пользователя, к которому относятся эти настройки. - @HiveField(0) - final String userId; + @HiveField(0) + final String id; /// Карта правил обработки, где ключ - это идентификатор отправителя (например, 'SBERBANK' или номер телефона), /// а значение - правило обработки для этого отправителя. @HiveField(1) final Map rulesBySender; SmsHandlerSettings({ - required this.userId, + String? id, required this.rulesBySender, - }); + }) : id = id ?? IdGenerator.generateId(); } diff --git a/lib/models/sms_handler_settings.g.dart b/lib/models/sms_handler_settings.g.dart index 78522b0..085c470 100644 --- a/lib/models/sms_handler_settings.g.dart +++ b/lib/models/sms_handler_settings.g.dart @@ -57,7 +57,6 @@ class SmsHandlerSettingsAdapter extends TypeAdapter { for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), }; return SmsHandlerSettings( - userId: fields[0] as String, rulesBySender: (fields[1] as Map).cast(), ); } @@ -65,9 +64,7 @@ class SmsHandlerSettingsAdapter extends TypeAdapter { @override void write(BinaryWriter writer, SmsHandlerSettings obj) { writer - ..writeByte(2) - ..writeByte(0) - ..write(obj.userId) + ..writeByte(1) ..writeByte(1) ..write(obj.rulesBySender); } diff --git a/lib/models/sms_message.dart b/lib/models/sms_message.dart index 3eaf5e6..75b923f 100644 --- a/lib/models/sms_message.dart +++ b/lib/models/sms_message.dart @@ -21,17 +21,12 @@ class SmsMessage extends HiveObject { @HiveField(4) String? transactionId; - // Комментарий: Добавлено поле для связи с пользователем. - @HiveField(5) - final String userId; - SmsMessage({ String? id, this.body, this.sender, this.date, this.transactionId, - required this.userId, }) : id = id ?? IdGenerator.generateId(); // Комментарий: Добавляем метод для обновления transactionId @@ -42,7 +37,6 @@ class SmsMessage extends HiveObject { sender: sender, date: date, transactionId: transactionId ?? this.transactionId, - userId: userId ?? this.userId, ); } } diff --git a/lib/models/sms_message.g.dart b/lib/models/sms_message.g.dart index 9f166ce..4a4d537 100644 --- a/lib/models/sms_message.g.dart +++ b/lib/models/sms_message.g.dart @@ -22,14 +22,13 @@ class SmsMessageAdapter extends TypeAdapter { sender: fields[2] as String?, date: fields[3] as DateTime?, transactionId: fields[4] as String?, - userId: fields[5] as String, ); } @override void write(BinaryWriter writer, SmsMessage obj) { writer - ..writeByte(6) + ..writeByte(5) ..writeByte(0) ..write(obj.id) ..writeByte(1) @@ -39,9 +38,7 @@ class SmsMessageAdapter extends TypeAdapter { ..writeByte(3) ..write(obj.date) ..writeByte(4) - ..write(obj.transactionId) - ..writeByte(5) - ..write(obj.userId); + ..write(obj.transactionId); } @override diff --git a/lib/models/tag.dart b/lib/models/tag.dart index 07eb45b..c584f25 100644 --- a/lib/models/tag.dart +++ b/lib/models/tag.dart @@ -14,12 +14,6 @@ class Tag extends Equatable { /// Название тега (например: "Важное", "Работа") final String name; - // Комментарий: Добавляем новое поле для хранения идентификатора пользователя. - // Это позволит нам связать каждый тег с конкретным пользователем. - // Мы используем аннотацию @HiveField(2), чтобы указать Hive, как сохранять это поле. - @HiveField(2) - final String userId; - @HiveField(3) /// Дата и время последнего обновления объекта final DateTime updatedAt; @@ -30,7 +24,6 @@ class Tag extends Equatable { required this.name, // Комментарий: Добавляем userId в конструктор как обязательный параметр. // Теперь при создании тега необходимо будет указать, какому пользователю он принадлежит. - required this.userId, DateTime? updatedAt, // Добавлено поле updatedAt, теперь необязательное }) : id = id ?? IdGenerator.generateId(), updatedAt = updatedAt ?? DateTime.now(); // Устанавливаем текущее время по умолчанию @@ -42,7 +35,6 @@ class Tag extends Equatable { 'name': name, // Комментарий: Добавляем userId в Map. Это нужно для сохранения // данных в форматах, которые не работают напрямую с объектами Dart (например, при отправке на сервер). - 'userId': userId, 'updatedAt': updatedAt.toIso8601String(), // Добавлено updatedAt в Map }; } @@ -54,7 +46,6 @@ class Tag extends Equatable { name: map['name'], // Комментарий: Извлекаем userId из Map при создании объекта. // Это позволит восстановить полный объект Tag из данных, например, из базы данных. - userId: map['userId'], updatedAt: DateTime.parse(map['updatedAt']), // Добавлено updatedAt при создании из Map ); } @@ -68,7 +59,6 @@ class Tag extends Equatable { return Tag( id: id ?? this.id, name: name ?? this.name, - userId: userId ?? this.userId, updatedAt: DateTime.now(), // Обновляем updatedAt при каждом копировании ); } diff --git a/lib/models/tag.g.dart b/lib/models/tag.g.dart index 30b33c6..98f587a 100644 --- a/lib/models/tag.g.dart +++ b/lib/models/tag.g.dart @@ -19,7 +19,6 @@ class TagAdapter extends TypeAdapter { return Tag( id: fields[0] as String?, name: fields[1] as String, - userId: fields[2] as String, updatedAt: fields[3] as DateTime?, ); } @@ -27,13 +26,11 @@ class TagAdapter extends TypeAdapter { @override void write(BinaryWriter writer, Tag obj) { writer - ..writeByte(4) + ..writeByte(3) ..writeByte(0) ..write(obj.id) ..writeByte(1) ..write(obj.name) - ..writeByte(2) - ..write(obj.userId) ..writeByte(3) ..write(obj.updatedAt); } diff --git a/lib/models/transaction_record.dart b/lib/models/transaction_record.dart index 53f670e..d292451 100644 --- a/lib/models/transaction_record.dart +++ b/lib/models/transaction_record.dart @@ -39,10 +39,6 @@ class TransactionRecord extends Equatable { /// Валюта операции (код валюты, например "RUB", "USD") final String currency; - // Добавляем новое поле для хранения идентификатора пользователя - @HiveField(7) // Используем следующий доступный номер поля Hive - final String userId; - @HiveField(8) /// Дата и время последнего обновления объекта final DateTime updatedAt; @@ -56,7 +52,6 @@ class TransactionRecord extends Equatable { required this.dateTime, required this.vendor, required this.currency, - required this.userId, // Добавляем userId в конструктор DateTime? updatedAt, // Добавлено поле updatedAt, теперь необязательное }) : id = id ?? IdGenerator.generateId(), updatedAt = @@ -73,7 +68,6 @@ class TransactionRecord extends Equatable { 'dateTime': dateTime.toIso8601String(), 'vendor': vendor, 'currency': currency, - 'userId': userId, // Добавляем userId в Map 'updatedAt': updatedAt.toIso8601String(), // Добавлено updatedAt в Map }; } @@ -88,7 +82,6 @@ class TransactionRecord extends Equatable { dateTime: DateTime.parse(map['dateTime']), vendor: map['vendor'], currency: map['currency'], - userId: map['userId'], // Извлекаем userId из Map updatedAt: DateTime.parse( map['updatedAt'], ), // Добавлено updatedAt при создании из Map @@ -118,7 +111,6 @@ class TransactionRecord extends Equatable { dateTime: dateTime ?? this.dateTime, vendor: vendor ?? this.vendor, currency: currency ?? this.currency, - userId: userId ?? this.userId, updatedAt: DateTime.now(), // Обновляем updatedAt при каждом копировании ); } diff --git a/lib/models/transaction_record.g.dart b/lib/models/transaction_record.g.dart index 2a90916..03956e2 100644 --- a/lib/models/transaction_record.g.dart +++ b/lib/models/transaction_record.g.dart @@ -24,7 +24,6 @@ class TransactionRecordAdapter extends TypeAdapter { dateTime: fields[4] as DateTime, vendor: fields[5] as String, currency: fields[6] as String, - userId: fields[7] as String, updatedAt: fields[8] as DateTime?, ); } @@ -32,7 +31,7 @@ class TransactionRecordAdapter extends TypeAdapter { @override void write(BinaryWriter writer, TransactionRecord obj) { writer - ..writeByte(9) + ..writeByte(8) ..writeByte(0) ..write(obj.id) ..writeByte(1) @@ -47,8 +46,6 @@ class TransactionRecordAdapter extends TypeAdapter { ..write(obj.vendor) ..writeByte(6) ..write(obj.currency) - ..writeByte(7) - ..write(obj.userId) ..writeByte(8) ..write(obj.updatedAt); } diff --git a/lib/pages/category/category_list_page.dart b/lib/pages/category/category_list_page.dart index f76b323..5eef059 100644 --- a/lib/pages/category/category_list_page.dart +++ b/lib/pages/category/category_list_page.dart @@ -1,6 +1,5 @@ import 'package:budget_app/l10n/app_localizations.dart'; import 'package:budget_app/logic/category/category_cubit.dart'; -import 'package:budget_app/logic/category/category_state.dart'; import 'package:budget_app/models/category.dart'; import 'package:budget_app/pages/category/category_edit_page.dart'; import 'package:budget_app/pages/category/widgets/add_category_button.dart'; @@ -63,16 +62,11 @@ class _CategoryListPageState extends State { MaterialPageRoute( builder: (_) => CategoryEditPage( onSave: (name, color, icon, isIncome) { - final userState = context.read().state; - if (userState is! UserLoaded || userState.user == null) return; - - final currentUserId = userState.user!.id; final newCategory = Category( name: name, color: color, icon: icon, isIncome: isIncome, - userId: currentUserId, ); context.read().addCategory(newCategory); @@ -89,10 +83,6 @@ class _CategoryListPageState extends State { builder: (_) => CategoryEditPage( category: category, onSave: (name, color, icon, isIncome) { - final userState = context.read().state; - if (userState is! UserLoaded || userState.user == null) return; - - final currentUserId = userState.user!.id; final updatedCategory = category.copyWith( name: name, color: color, @@ -108,10 +98,6 @@ class _CategoryListPageState extends State { } void _deleteCategory(BuildContext context, Category category) { - final userState = context.read().state; - if (userState is! UserLoaded || userState.user == null) return; - - final currentUserId = userState.user!.id; context.read().deleteCategory(category.id); } } diff --git a/lib/pages/home/widgets/add_transaction_dialog.dart b/lib/pages/home/widgets/add_transaction_dialog.dart index c8cf9d9..63df9b6 100644 --- a/lib/pages/home/widgets/add_transaction_dialog.dart +++ b/lib/pages/home/widgets/add_transaction_dialog.dart @@ -122,17 +122,14 @@ class _AddTransactionDialogState extends State { : 'RUB'; // Получаем ID текущего пользователя из UserCubit - final userState = context.read().state; - if (userState is! UserLoaded || userState.user == null) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - AppLocalizations.of(context)!.transactionErrorText('User not found'), - ), + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + AppLocalizations.of(context)!.transactionErrorText('User not found'), ), - ); - return; - } + ), + ); final newTransaction = TransactionRecord( amount: amount, @@ -141,7 +138,6 @@ class _AddTransactionDialogState extends State { dateTime: _selectedDateTime, tag: _selectedTag, currency: currency, - userId: userState.user!.id, ); context.read().add( @@ -154,14 +150,9 @@ class _AddTransactionDialogState extends State { @override Widget build(BuildContext context) { final localizations = AppLocalizations.of(context)!; + - // Получаем ID текущего пользователя из UserCubit - final userState = context.read().state; - final userId = userState is UserLoaded && userState.user != null - ? userState.user!.id - : ''; - - final categories = CategoryUtils.getDefaultCategories(userId) + final categories = CategoryUtils.getDefaultCategories() .where((c) => c.isIncome == _isIncome).toList(); return AlertDialog( @@ -233,7 +224,7 @@ class _AddTransactionDialogState extends State { // Комментарий: Добавляем выпадающий список для выбора тега. // Он будет загружать теги асинхронно для текущего пользователя. FutureBuilder>( - future: GetIt.instance().getAllByUser(userId), + future: GetIt.instance().getAll(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); diff --git a/lib/pages/settings_page.dart b/lib/pages/settings_page.dart index 29d76ca..dbb860d 100644 --- a/lib/pages/settings_page.dart +++ b/lib/pages/settings_page.dart @@ -37,145 +37,131 @@ class SettingsPage extends StatelessWidget { builder: (context, userState) { if (userState is UserLoaded && userState.user != null) { // Комментарий: Как только пользователь загружен, мы загружаем его настройки. - context.read().loadSettings(userState.user!.id); + context.read().loadSettings(); return BlocBuilder( builder: (context, state) { if (state is SettingsLoaded) { return Padding( padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SwitchListTile( - title: Text(localizations.darkModeSetting), - subtitle: Text(localizations.darkModeDescription), - value: state.isDarkMode, - // Комментарий: При изменении положения переключателя (onChanged) мы вызываем метод `toggleDarkMode` у Cubit. - // `context.read()` используется для доступа к Cubit без подписки на его изменения. - // Это хорошо для вызова методов. Также передаем userId из UserService. - onChanged: (value) { - // Получаем ID текущего пользователя из UserCubit - final userState = context.read().state; - if (userState is UserLoaded && - userState.user != null) { - final userId = userState.user!.id; - context - .read() - .toggleDarkMode(value, userId); - } - }, - ), - const Divider(), - ListTile( - title: Text(localizations.languageSetting), - subtitle: Text(localizations.languageDescription), - trailing: DropdownButton( - value: state.languageCode, - // Комментарий: При выборе нового языка вызываем метод `changeLanguage` у Cubit. - // Также передаем userId из UserService. - onChanged: (String? newValue) { - if (newValue != null) { - // Получаем ID текущего пользователя из UserCubit - final userState = - context.read().state; - if (userState is UserLoaded && - userState.user != null) { - final userId = userState.user!.id; - context - .read() - .changeLanguage(newValue, userId); - } - } + // Комментарий: Обернули Column в SingleChildScrollView, чтобы избежать переполнения по вертикали. + // Это позволяет прокручивать содержимое, если оно не помещается на экране. + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SwitchListTile( + title: Text(localizations.darkModeSetting), + subtitle: Text(localizations.darkModeDescription), + value: state.isDarkMode, + // Комментарий: При изменении положения переключателя (onChanged) мы вызываем метод `toggleDarkMode` у Cubit. + // `context.read()` используется для доступа к Cubit без подписки на его изменения. + // Это хорошо для вызова методов. Также передаем userId из UserService. + onChanged: (value) { + // Получаем ID текущего пользователя из UserCubit + context + .read() + .toggleDarkMode(value); }, - // Комментарий: Формируем список доступных языков. - items: ['en', 'ru'] - .map>( - (String value) { - return DropdownMenuItem( - value: value, - // Комментарий: Отображаем локализованное название языка. - child: Text(value == 'en' - ? localizations.englishLanguage - : localizations.russianLanguage), - ); - }).toList(), ), - ), - const Divider(), - ListTile( - title: Text(localizations.currencySetting), - subtitle: Text(localizations.currencyDescription), - trailing: DropdownButton( - value: state.defaultCurrency, - // Комментарий: При выборе новой валюты вызываем метод `changeCurrency` у Cubit. - // Также передаем userId из UserService. - onChanged: (String? newValue) { - if (newValue != null) { - // Получаем ID текущего пользователя из UserCubit - final userState = - context.read().state; - if (userState is UserLoaded && - userState.user != null) { - final userId = userState.user!.id; - context - .read() - .changeCurrency(newValue, userId); + const Divider(), + ListTile( + title: Text(localizations.languageSetting), + subtitle: Text(localizations.languageDescription), + trailing: DropdownButton( + value: state.languageCode, + // Комментарий: При выборе нового языка вызываем метод `changeLanguage` у Cubit. + // Также передаем userId из UserService. + onChanged: (String? newValue) { + if (newValue != null) { + context + .read() + .changeLanguage(newValue); } - } - }, - // Комментарий: Формируем список доступных валют. Можно расширить этот список. - items: ['RUB', 'USD', 'EUR'] - .map>( - (String value) { - return DropdownMenuItem( - value: value, - child: Text(value), - ); - }).toList(), + }, + // Комментарий: Формируем список доступных языков. + items: ['en', 'ru'] + .map>( + (String value) { + return DropdownMenuItem( + value: value, + // Комментарий: Отображаем локализованное название языка. + child: Text(value == 'en' + ? localizations.englishLanguage + : localizations.russianLanguage), + ); + }).toList(), + ), ), - ), - const Divider(), - // Комментарий: ListTile для перехода на страницу редактирования категорий. - ListTile( - title: Text(localizations.editCategories), - subtitle: - Text(localizations.editCategoriesDescription), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const CategoryListPage(), - ), - ); - }, - ), - const Divider(), - ListTile( - title: Text(localizations.editTags), - subtitle: Text(localizations.editTagsDescription), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const TagListPage(), - ), - ); - }, - ), - const Divider(), - // Комментарий: ListTile для запуска процесса загрузки SMS-сообщений. - ListTile( - title: Text(localizations.loadSmsMessages), - subtitle: - Text(localizations.loadSmsMessagesDescription), - onTap: () { - // Комментарий: При нажатии на кнопку мы вызываем метод `loadSmsMessages` у SmsCubit. - // Это инициирует процесс получения и сохранения SMS-сообщений. - context.read().loadSmsMessages(); - }, - ), - const Divider(), - ], + const Divider(), + ListTile( + title: Text(localizations.currencySetting), + subtitle: Text(localizations.currencyDescription), + trailing: DropdownButton( + value: state.defaultCurrency, + // Комментарий: При выборе новой валюты вызываем метод `changeCurrency` у Cubit. + // Также передаем userId из UserService. + onChanged: (String? newValue) { + if (newValue != null) { + + context + .read() + .changeCurrency(newValue); + } + }, + // Комментарий: Формируем список доступных валют. Можно расширить этот список. + items: ['RUB', 'USD', 'EUR'] + .map>( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ), + ), + const Divider(), + // Комментарий: ListTile для перехода на страницу редактирования категорий. + ListTile( + title: Text(localizations.editCategories), + subtitle: + Text(localizations.editCategoriesDescription), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const CategoryListPage(), + ), + ); + }, + ), + const Divider(), + ListTile( + title: Text(localizations.editTags), + subtitle: Text(localizations.editTagsDescription), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const TagListPage(), + ), + ); + }, + ), + const Divider(), + // Комментарий: ListTile для запуска процесса загрузки SMS-сообщений. + ListTile( + title: Text(localizations.loadSmsMessages), + subtitle: + Text(localizations.loadSmsMessagesDescription), + onTap: () { + // Комментарий: При нажатии на кнопку мы вызываем метод `loadSmsMessages` у SmsCubit. + // Это инициирует процесс получения и сохранения SMS-сообщений. + context.read().loadSmsMessages(); + }, + ), + const Divider(), + ], + ), ), ); } else { diff --git a/lib/pages/tag/tag_list_page.dart b/lib/pages/tag/tag_list_page.dart index 4b8ac23..f9c3db1 100644 --- a/lib/pages/tag/tag_list_page.dart +++ b/lib/pages/tag/tag_list_page.dart @@ -69,14 +69,8 @@ class _TagListPageState extends State { MaterialPageRoute( builder: (_) => TagEditPage( onSave: (name) { - final userState = context.read().state; - if (userState is! UserLoaded || userState.user == null) { - return; - } - final currentUserId = userState.user!.id; final newTag = Tag( name: name, - userId: currentUserId, ); context.read().addTag(newTag); _listKey.currentState?.insertItem(0); diff --git a/lib/services/sms_service.dart b/lib/services/sms_service.dart index e3850f8..1235354 100644 --- a/lib/services/sms_service.dart +++ b/lib/services/sms_service.dart @@ -23,7 +23,7 @@ class SmsService { /// /// Возвращает список объектов [SmsMessage]. /// В случае ошибки или отсутствия разрешений, возвращает пустой список. - Future> getLastSmsMessages(int count, String userId) async { + Future> getLastSmsMessages(int count) async { final bool? permissionsGranted = await _telephony.requestPhoneAndSmsPermissions; if (permissionsGranted ?? false) { @@ -36,14 +36,13 @@ class SmsService { body: msg.body, sender: msg.address, date: DateTime.fromMillisecondsSinceEpoch(msg.date ?? 0), - userId: userId, )).toList(); } return []; } // Комментарий: Метод для получения SMS-сообщений с определенной даты. - Future> getSmsMessagesSince(DateTime sinceDate, String userId) async { + Future> getSmsMessagesSince(DateTime sinceDate) async { final bool? permissionsGranted = await _telephony.requestPhoneAndSmsPermissions; if (permissionsGranted ?? false) { final List messages = await _telephony.getInboxSms( @@ -57,7 +56,6 @@ class SmsService { body: msg.body, sender: msg.address, date: DateTime.fromMillisecondsSinceEpoch(msg.date ?? 0), - userId: userId, )) .toList(); } diff --git a/lib/utils/category_utils.dart b/lib/utils/category_utils.dart index 91a183d..4554de1 100644 --- a/lib/utils/category_utils.dart +++ b/lib/utils/category_utils.dart @@ -7,7 +7,7 @@ class CategoryUtils { /// Возвращает список предопределенных категорий для конкретного пользователя /// Включает как категории доходов, так и расходов /// [userId] - идентификатор пользователя, для которого создаются категории - static List getDefaultCategories(String userId) { + static List getDefaultCategories() { return [ // Категории доходов Category( @@ -16,7 +16,6 @@ class CategoryUtils { color: Colors.green, icon: Icons.attach_money, isIncome: true, - userId: userId, // Привязываем к конкретному пользователю ), Category( id: 'income_gift', @@ -24,7 +23,6 @@ class CategoryUtils { color: Colors.blue, icon: Icons.card_giftcard, isIncome: true, - userId: userId, // Привязываем к конкретному пользователю ), Category( id: 'income_freelance', @@ -32,7 +30,6 @@ class CategoryUtils { color: Colors.teal, icon: Icons.computer, isIncome: true, - userId: userId, // Привязываем к конкретному пользователю ), // Категории расходов @@ -42,7 +39,6 @@ class CategoryUtils { color: Colors.red, icon: Icons.fastfood, isIncome: false, - userId: userId, // Привязываем к конкретному пользователю ), Category( id: 'expense_transport', @@ -50,7 +46,6 @@ class CategoryUtils { color: Colors.orange, icon: Icons.directions_car, isIncome: false, - userId: userId, // Привязываем к конкретному пользователю ), Category( id: 'expense_entertainment', @@ -58,7 +53,6 @@ class CategoryUtils { color: Colors.purple, icon: Icons.movie, isIncome: false, - userId: userId, // Привязываем к конкретному пользователю ), Category( id: 'expense_utilities', @@ -66,7 +60,6 @@ class CategoryUtils { color: Colors.blueGrey, icon: Icons.home, isIncome: false, - userId: userId, // Привязываем к конкретному пользователю ), Category( id: 'expense_shopping', @@ -74,7 +67,6 @@ class CategoryUtils { color: Colors.pink, icon: Icons.shopping_bag, isIncome: false, - userId: userId, // Привязываем к конкретному пользователю ), ]; } @@ -82,12 +74,12 @@ class CategoryUtils { /// Возвращает только категории доходов для конкретного пользователя /// [userId] - идентификатор пользователя static List getIncomeCategories(String userId) { - return getDefaultCategories(userId).where((c) => c.isIncome).toList(); + return getDefaultCategories().where((c) => c.isIncome).toList(); } /// Возвращает только категории расходов для конкретного пользователя /// [userId] - идентификатор пользователя static List getExpenseCategories(String userId) { - return getDefaultCategories(userId).where((c) => !c.isIncome).toList(); + return getDefaultCategories().where((c) => !c.isIncome).toList(); } } diff --git a/lib/utils/tag_utils.dart b/lib/utils/tag_utils.dart index b556950..0b80982 100644 --- a/lib/utils/tag_utils.dart +++ b/lib/utils/tag_utils.dart @@ -5,35 +5,28 @@ class TagUtils { // Комментарий: Мы изменили сигнатуру метода, добавив параметр `userId`. // Это необходимо, потому что конструктор `Tag` теперь требует `userId`. /// Возвращает список предопределенных тегов для конкретного пользователя - static List getDefaultTags(String userId) { + static List getDefaultTags() { return [ Tag( id: 'tag_important', name: 'Важное', - // Комментарий: Передаем `userId` при создании каждого тега по умолчанию. - // Таким образом, эти теги будут принадлежать конкретному пользователю. - userId: userId, ), Tag( id: 'tag_work', name: 'Работа', - userId: userId, ), Tag( id: 'tag_family', name: 'Семья', - userId: userId, ), Tag( id: 'tag_friends', name: 'Друзья', - userId: userId, ), Tag( id: 'tag_holiday', name: 'Отпуск', - userId: userId, ), ]; } diff --git a/lib/utils/transaction_utils.dart b/lib/utils/transaction_utils.dart index 20d2e5e..ed277ba 100644 --- a/lib/utils/transaction_utils.dart +++ b/lib/utils/transaction_utils.dart @@ -5,11 +5,10 @@ import 'tag_utils.dart'; /// Утилиты для работы с тестовыми транзакциями class TransactionUtils { /// Возвращает список тестовых транзакций для конкретного пользователя - /// [userId] - идентификатор пользователя, для которого создаются транзакции - static List getSampleTransactions(String userId) { + static List getSampleTransactions() { // Получаем категории и теги для этого пользователя - final categories = CategoryUtils.getDefaultCategories(userId); - final tags = TagUtils.getDefaultTags(userId); + final categories = CategoryUtils.getDefaultCategories(); + final tags = TagUtils.getDefaultTags(); return [ // Доходы @@ -20,7 +19,6 @@ class TransactionUtils { dateTime: DateTime.now().subtract(const Duration(days: 5)), vendor: 'ООО "Рога и копыта"', currency: 'RUB', - userId: userId, // Указываем userId для тестовой транзакции ), TransactionRecord( category: categories.firstWhere((c) => c.id == 'income_freelance'), @@ -29,7 +27,6 @@ class TransactionUtils { dateTime: DateTime.now().subtract(const Duration(days: 2)), vendor: 'Фриланс проект', currency: 'RUB', - userId: userId, // Указываем userId для тестовой транзакции ), // Расходы @@ -40,7 +37,6 @@ class TransactionUtils { dateTime: DateTime.now().subtract(const Duration(days: 1)), vendor: 'Пятерочка', currency: 'RUB', - userId: userId, // Указываем userId для тестовой транзакции ), TransactionRecord( category: categories.firstWhere((c) => c.id == 'expense_transport'), @@ -49,7 +45,6 @@ class TransactionUtils { dateTime: DateTime.now().subtract(const Duration(hours: 12)), vendor: 'Яндекс Такси', currency: 'RUB', - userId: userId, // Указываем userId для тестовой транзакции ), TransactionRecord( category: categories.firstWhere((c) => c.id == 'expense_entertainment'), @@ -58,7 +53,6 @@ class TransactionUtils { dateTime: DateTime.now().subtract(const Duration(hours: 6)), vendor: 'Кинотеатр', currency: 'RUB', - userId: userId, // Указываем userId для тестовой транзакции ), ]; }