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 accounts, @Default([]) List recurringTransactions, @Default([]) List transactions, @Default([]) List transactionTemplates, @Default([]) List beneficiaries, @Default([]) List expenseCategories, @Default([]) List budgets, @Default(null) Budget? activeBudget, }) = _CoreState; } class CoreCubit extends Cubit { CoreCubit() : super(CoreState()); StreamSubscription? _recurringTransactionStreamSubscription; StreamSubscription? _transactionTemplatesStreamSubcription; StreamSubscription? _accountsStreamSubscription; StreamSubscription? _transactionsStreamSubscription; StreamSubscription? _beneficiariesStreamSubscription; StreamSubscription? _expenseCategoryStreamSubscription; StreamSubscription? _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 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 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 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!]; }