This commit refactors the data repositories to remove user-specific filtering. It simplifies the data access logic by retrieving all data from the Hive boxes and removing the need to filter by `userId` in the repository methods. This change makes the app function in single-user mode and removes the need to manage multiple user contexts within the data layer. Specifically: - Removes `userId` parameter from repository methods. - Updates the setting repository to use fixed keys. - Removes user ID filtering from queries. - Removes user ID parameters from Cubits and Blocs - Updates initial data creation
181 lines
10 KiB
Dart
181 lines
10 KiB
Dart
import 'package:budget_app/logic/sms/sms_cubit.dart';
|
||
import 'package:budget_app/pages/category/category_list_page.dart';
|
||
import 'package:budget_app/pages/tag/tag_list_page.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||
import '/l10n/app_localizations.dart';
|
||
import '../logic/settings/settings_cubit.dart';
|
||
import '../logic/user/user_cubit.dart';
|
||
|
||
// Комментарий: Мы преобразуем SettingsPage из StatefulWidget в StatelessWidget.
|
||
// Это возможно, потому что теперь состояние управляется SettingsCubit,
|
||
// и виджету не нужно хранить собственное состояние, что делает код проще и эффективнее.
|
||
class SettingsPage extends StatelessWidget {
|
||
const SettingsPage({super.key});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final localizations = AppLocalizations.of(context)!;
|
||
|
||
return Scaffold(
|
||
appBar: AppBar(
|
||
title: Text(localizations.settingsPageTitle),
|
||
),
|
||
body: BlocListener<SettingsCubit, SettingsState>(
|
||
listener: (context, state) {
|
||
// Комментарий: Обрабатываем ошибки и показываем SnackBar пользователю
|
||
if (state is SettingsError) {
|
||
ScaffoldMessenger.of(context).showSnackBar(
|
||
SnackBar(
|
||
content: Text('Ошибка настроек: ${state.message}'),
|
||
backgroundColor: Theme.of(context).colorScheme.error,
|
||
),
|
||
);
|
||
}
|
||
},
|
||
child: BlocBuilder<UserCubit, UserState>(
|
||
builder: (context, userState) {
|
||
if (userState is UserLoaded && userState.user != null) {
|
||
// Комментарий: Как только пользователь загружен, мы загружаем его настройки.
|
||
context.read<SettingsCubit>().loadSettings();
|
||
return BlocBuilder<SettingsCubit, SettingsState>(
|
||
builder: (context, state) {
|
||
if (state is SettingsLoaded) {
|
||
return Padding(
|
||
padding: const EdgeInsets.all(16.0),
|
||
// Комментарий: Обернули 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<SettingsCubit>()` используется для доступа к Cubit без подписки на его изменения.
|
||
// Это хорошо для вызова методов. Также передаем userId из UserService.
|
||
onChanged: (value) {
|
||
// Получаем ID текущего пользователя из UserCubit
|
||
context
|
||
.read<SettingsCubit>()
|
||
.toggleDarkMode(value);
|
||
},
|
||
),
|
||
const Divider(),
|
||
ListTile(
|
||
title: Text(localizations.languageSetting),
|
||
subtitle: Text(localizations.languageDescription),
|
||
trailing: DropdownButton<String>(
|
||
value: state.languageCode,
|
||
// Комментарий: При выборе нового языка вызываем метод `changeLanguage` у Cubit.
|
||
// Также передаем userId из UserService.
|
||
onChanged: (String? newValue) {
|
||
if (newValue != null) {
|
||
context
|
||
.read<SettingsCubit>()
|
||
.changeLanguage(newValue);
|
||
}
|
||
},
|
||
// Комментарий: Формируем список доступных языков.
|
||
items: <String>['en', 'ru']
|
||
.map<DropdownMenuItem<String>>(
|
||
(String value) {
|
||
return DropdownMenuItem<String>(
|
||
value: value,
|
||
// Комментарий: Отображаем локализованное название языка.
|
||
child: Text(value == 'en'
|
||
? localizations.englishLanguage
|
||
: localizations.russianLanguage),
|
||
);
|
||
}).toList(),
|
||
),
|
||
),
|
||
const Divider(),
|
||
ListTile(
|
||
title: Text(localizations.currencySetting),
|
||
subtitle: Text(localizations.currencyDescription),
|
||
trailing: DropdownButton<String>(
|
||
value: state.defaultCurrency,
|
||
// Комментарий: При выборе новой валюты вызываем метод `changeCurrency` у Cubit.
|
||
// Также передаем userId из UserService.
|
||
onChanged: (String? newValue) {
|
||
if (newValue != null) {
|
||
|
||
context
|
||
.read<SettingsCubit>()
|
||
.changeCurrency(newValue);
|
||
}
|
||
},
|
||
// Комментарий: Формируем список доступных валют. Можно расширить этот список.
|
||
items: <String>['RUB', 'USD', 'EUR']
|
||
.map<DropdownMenuItem<String>>(
|
||
(String value) {
|
||
return DropdownMenuItem<String>(
|
||
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<SmsCubit>().loadSmsMessages();
|
||
},
|
||
),
|
||
const Divider(),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
} else {
|
||
return const Center(child: CircularProgressIndicator());
|
||
}
|
||
},
|
||
);
|
||
} else {
|
||
return const Center(child: CircularProgressIndicator());
|
||
}
|
||
},
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|