okane/lib/ui/state/core.dart

169 lines
5.6 KiB
Dart

import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:okane/database/collections/account.dart';
import 'package:okane/database/collections/beneficiary.dart';
import 'package:okane/database/collections/budget.dart';
import 'package:okane/database/collections/expense_category.dart';
import 'package:okane/database/collections/recurrent.dart';
import 'package:okane/database/collections/template.dart';
import 'package:okane/database/collections/transaction.dart';
import 'package:okane/database/database.dart';
import 'package:okane/ui/navigation.dart';
part 'core.freezed.dart';
@freezed
abstract class CoreState with _$CoreState {
const factory CoreState({
@Default(OkanePage.accounts) OkanePage activePage,
int? activeAccountIndex,
@Default(null) Transaction? activeTransaction,
@Default([]) List<Account> accounts,
@Default([]) List<RecurringTransaction> recurringTransactions,
@Default([]) List<Transaction> transactions,
@Default([]) List<TransactionTemplate> transactionTemplates,
@Default([]) List<Beneficiary> beneficiaries,
@Default([]) List<ExpenseCategory> expenseCategories,
@Default([]) List<Budget> budgets,
@Default(null) Budget? activeBudget,
}) = _CoreState;
}
class CoreCubit extends Cubit<CoreState> {
CoreCubit() : super(CoreState());
StreamSubscription<void>? _recurringTransactionStreamSubscription;
StreamSubscription<void>? _transactionTemplatesStreamSubcription;
StreamSubscription<void>? _accountsStreamSubscription;
StreamSubscription<void>? _transactionsStreamSubscription;
StreamSubscription<void>? _beneficiariesStreamSubscription;
StreamSubscription<void>? _expenseCategoryStreamSubscription;
StreamSubscription<void>? _budgetsStreamSubscription;
void setupAccountStream() {
_accountsStreamSubscription?.cancel();
_accountsStreamSubscription = watchAccounts().listen((_) async {
final resetStreams = state.activeAccountIndex == null;
final accounts = await getAccounts();
emit(
state.copyWith(
accounts: accounts,
activeAccountIndex: state.activeAccountIndex ?? 0,
),
);
if (resetStreams) {
setupStreams(accounts[0]);
}
});
}
void setupStreams(Account account) {
setupAccountStream();
_recurringTransactionStreamSubscription?.cancel();
_recurringTransactionStreamSubscription = watchRecurringTransactions(
activeAccount!,
).listen((_) async {
emit(
state.copyWith(
recurringTransactions: await getRecurringTransactions(activeAccount!),
),
);
});
_transactionTemplatesStreamSubcription?.cancel();
_transactionTemplatesStreamSubcription = watchTransactionTemplates(
activeAccount!,
).listen((_) async {
emit(
state.copyWith(
transactionTemplates: await getTransactionTemplates(activeAccount!),
),
);
});
_transactionsStreamSubscription?.cancel();
_transactionsStreamSubscription = watchTransactions(activeAccount!).listen((
_,
) async {
emit(state.copyWith(transactions: await getTransactions(activeAccount!)));
});
_beneficiariesStreamSubscription?.cancel();
_beneficiariesStreamSubscription = watchBeneficiaries().listen((_) async {
emit(state.copyWith(beneficiaries: await getBeneficiaries()));
});
_expenseCategoryStreamSubscription?.cancel();
_expenseCategoryStreamSubscription = watchExpenseCategory().listen((
_,
) async {
emit(state.copyWith(expenseCategories: await getExpenseCategories()));
});
_budgetsStreamSubscription?.cancel();
_budgetsStreamSubscription = watchBudgets(activeAccount!).listen((_) async {
emit(state.copyWith(budgets: await getBudgets(activeAccount!)));
});
}
Future<void> init() async {
final accounts = await getAccounts();
final account = accounts.isEmpty ? null : accounts[0];
emit(
state.copyWith(
accounts: accounts,
activeAccountIndex: accounts.isEmpty ? null : 0,
transactions: await getTransactions(account),
beneficiaries: await getBeneficiaries(),
transactionTemplates: await getTransactionTemplates(account),
recurringTransactions: await getRecurringTransactions(account),
expenseCategories: await getExpenseCategories(),
budgets: await getBudgets(account),
),
);
if (account != null) {
setupStreams(account);
} else {
setupAccountStream();
}
print("Core init done");
}
void setPage(OkanePage page) {
emit(state.copyWith(activePage: page));
}
Future<void> setActiveAccountIndex(int index) async {
final account = state.accounts[index];
emit(
state.copyWith(
activeAccountIndex: index,
transactions: await getTransactions(account),
beneficiaries: await getBeneficiaries(),
transactionTemplates: await getTransactionTemplates(account),
recurringTransactions: await getRecurringTransactions(account),
budgets: await getBudgets(account),
activeBudget: null,
activeTransaction: null,
),
);
setupStreams(account);
}
void setActiveTransaction(Transaction? item) {
emit(state.copyWith(activeTransaction: item));
}
void setAccounts(List<Account> accounts) {
emit(state.copyWith(accounts: accounts));
}
void setActiveBudget(Budget? budget) {
emit(state.copyWith(activeBudget: budget));
}
Account? get activeAccount =>
state.activeAccountIndex == null
? null
: state.accounts[state.activeAccountIndex!];
}