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
123 lines
5.8 KiB
Dart
123 lines
5.8 KiB
Dart
import 'package:budget_app/logic/sms/sms_state.dart';
|
|
import 'package:budget_app/models/sms_message.dart';
|
|
import 'package:budget_app/models/transaction_record.dart';
|
|
import 'package:budget_app/services/sms_service.dart';
|
|
import 'package:budget_app/logic/user/user_cubit.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:budget_app/data/repositories/interfaces/isms_message_repository.dart';
|
|
|
|
/// Cubit для управления состоянием SMS.
|
|
///
|
|
/// Отвечает за загрузку SMS сообщений и обработку разрешений.
|
|
class SmsCubit extends Cubit<SmsState> {
|
|
final SmsService _smsService;
|
|
final ISmsMessageRepository _smsRepository;
|
|
final UserCubit _userCubit;
|
|
|
|
SmsCubit(
|
|
this._smsService,
|
|
this._smsRepository,
|
|
this._userCubit
|
|
) : super(SmsInitial());
|
|
|
|
/// Загружает последние 10 SMS сообщений.
|
|
///
|
|
/// Перед загрузкой запрашивает необходимые разрешения.
|
|
/// В случае успеха, переходит в состояние [SmsLoaded].
|
|
/// В случае отказа в разрешениях, переходит в состояние [SmsPermissionDenied].
|
|
/// В случае ошибки, переходит в состояние [SmsError].
|
|
Future<void> loadLastMessages() async {
|
|
emit(SmsLoading());
|
|
try {
|
|
final hasPermissions = await _smsService.requestPermissions();
|
|
if (hasPermissions) {
|
|
final messages = await _smsService.getLastSmsMessages(10);
|
|
emit(SmsLoaded(messages));
|
|
} else {
|
|
emit(SmsPermissionDenied());
|
|
}
|
|
} catch (e) {
|
|
emit(SmsError(e.toString()));
|
|
}
|
|
}
|
|
|
|
// Комментарий: Метод для загрузки и сохранения SMS-сообщений.
|
|
Future<void> loadSmsMessages() async {
|
|
// Комментарий: Устанавливаем состояние загрузки, чтобы UI мог отобразить индикатор.
|
|
emit(SmsLoading());
|
|
try {
|
|
// Комментарий: Запрашиваем разрешение на чтение SMS.
|
|
final hasPermissions = await _smsService.requestPermissions();
|
|
if (hasPermissions) {
|
|
// Комментарий: Получаем текущего пользователя из состояния UserCubit.
|
|
final userState = _userCubit.state;
|
|
if (userState is UserLoaded) {
|
|
final user = userState.user;
|
|
|
|
// Комментарий: Получаем все SMS-сообщения с момента последней синхронизации.
|
|
final messages = await _smsService.getSmsMessagesSince(user!.lastSmsSyncTime);
|
|
|
|
// Комментарий: Сохраняем новые сообщения через репозиторий и создаем транзакции.
|
|
await _smsRepository.addAll(messages);
|
|
for (final message in messages) {
|
|
// Комментарий: Пытаемся создать транзакцию из SMS.
|
|
_createTransactionFromSms(message);
|
|
}
|
|
|
|
// Комментарий: Устанавливаем состояние успешной загрузки.
|
|
emit(SmsLoaded(messages));
|
|
} else {
|
|
emit(SmsError("User not loaded"));
|
|
}
|
|
} else {
|
|
// Комментарий: Если разрешение не получено, устанавливаем состояние "в доступе отказано".
|
|
emit(SmsPermissionDenied());
|
|
}
|
|
} catch (e) {
|
|
// Комментарий: В случае ошибки устанавливаем состояние ошибки и передаем сообщение.
|
|
emit(SmsError(e.toString()));
|
|
}
|
|
}
|
|
|
|
// Комментарий: Метод для создания транзакции из SMS-сообщения.
|
|
Future<void> _createTransactionFromSms(SmsMessage sms) async {
|
|
// Комментарий: Здесь будет логика для парсинга SMS и создания транзакции.
|
|
// Пример простой логики парсинга (нужно будет доработать под реальные SMS).
|
|
final body = sms.body?.toLowerCase() ?? '';
|
|
double? amount;
|
|
TransactionRecord? type;
|
|
|
|
// Комментарий: Поиск суммы в сообщении.
|
|
final amountRegex = RegExp(r'(\d+(\.\d{1,2})?)');
|
|
final match = amountRegex.firstMatch(body);
|
|
if (match != null) {
|
|
amount = double.tryParse(match.group(1)!);
|
|
}
|
|
|
|
// TODO
|
|
// Комментарий: Определение типа транзакции (доход/расход).
|
|
// if (body.contains('покупка') || body.contains('списание')) {
|
|
// type = Transaction.expense;
|
|
// } else if (body.contains('зачисление') || body.contains('пополнение')) {
|
|
// type = TransactionType.income;
|
|
// }
|
|
|
|
// if (amount != null && type != null) {
|
|
// // Комментарий: Создаем новую транзакцию.
|
|
// final transaction = TransactionRecord(
|
|
// amount: amount,
|
|
// type: type,
|
|
// date: sms.date ?? DateTime.now(),
|
|
// description: sms.body, // Описание берем из тела SMS
|
|
// // Комментарий: Здесь можно добавить логику для определения категории и тегов.
|
|
// );
|
|
// // Комментарий: Добавляем событие AddTransaction в TransactionBloc.
|
|
// _transactionBloc.add(AddTransaction(transaction));
|
|
// // Комментарий: Сохраняем ID транзакции в SMS-сообщении.
|
|
// await _smsRepository.update(
|
|
// sms.copyWith(transactionId: transaction.id)
|
|
// );
|
|
// }
|
|
}
|
|
}
|