Compare commits
9 Commits
5dc474407c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| f8ff892104 | |||
| 121d0ec236 | |||
| 71993c2686 | |||
| cbe2d5a556 | |||
| c4f7d5745a | |||
| 567f5070e9 | |||
| baf0dfa99d | |||
| facbc16bb2 | |||
| 42b1bbd438 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -11,6 +11,7 @@
|
||||
.svn/
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
.sentry-native/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
@@ -45,4 +46,4 @@ app.*.map.json
|
||||
/android/app/release
|
||||
|
||||
# Build artifacts
|
||||
lib/i18n/*
|
||||
lib/i18n/*
|
||||
|
||||
@@ -26,3 +26,8 @@ linter:
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
analyzer:
|
||||
exclude:
|
||||
- "**/*.g.dart"
|
||||
- build/**
|
||||
- .dart_tool/**
|
||||
@@ -56,9 +56,8 @@ class Budgets extends Table {
|
||||
|
||||
class BudgetsDto {
|
||||
final Budget budget;
|
||||
final List<BudgetItemDto> budgetItems;
|
||||
|
||||
BudgetsDto({required this.budget, required this.budgetItems});
|
||||
BudgetsDto({required this.budget});
|
||||
}
|
||||
|
||||
class Loans extends Table {
|
||||
@@ -76,13 +75,8 @@ class LoanChanges extends Table {
|
||||
class LoanDto {
|
||||
final Loan loan;
|
||||
final Beneficiary beneficiary;
|
||||
final List<LoanChange> changes;
|
||||
|
||||
LoanDto({
|
||||
required this.loan,
|
||||
required this.beneficiary,
|
||||
required this.changes,
|
||||
});
|
||||
LoanDto({required this.loan, required this.beneficiary});
|
||||
}
|
||||
|
||||
class RecurringTransactions extends Table {
|
||||
@@ -185,10 +179,19 @@ class OkaneDatabase extends _$OkaneDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
@DriftAccessor(tables: [Accounts])
|
||||
@DriftAccessor(
|
||||
tables: [
|
||||
Accounts,
|
||||
Transactions,
|
||||
TransactionTemplates,
|
||||
RecurringTransactions,
|
||||
Budgets,
|
||||
Beneficiaries,
|
||||
],
|
||||
)
|
||||
class AccountsDao extends DatabaseAccessor<OkaneDatabase>
|
||||
with _$AccountsDaoMixin {
|
||||
AccountsDao(OkaneDatabase db) : super(db);
|
||||
AccountsDao(super.db);
|
||||
|
||||
Stream<List<Account>> accountsStream() {
|
||||
return select(accounts).watch();
|
||||
@@ -201,6 +204,22 @@ class AccountsDao extends DatabaseAccessor<OkaneDatabase>
|
||||
Future<int> upsertAccount(AccountsCompanion account) {
|
||||
return into(accounts).insertOnConflictUpdate(account);
|
||||
}
|
||||
|
||||
Future<void> removeAccount(Account account) async {
|
||||
// Delete dependent data
|
||||
await (delete(transactions)
|
||||
..where((t) => t.accountId.equals(account.id))).go();
|
||||
await (delete(recurringTransactions)
|
||||
..where((r) => r.accountId.equals(account.id))).go();
|
||||
await (delete(transactionTemplates)
|
||||
..where((t) => t.accountId.equals(account.id))).go();
|
||||
await (delete(budgets)..where((b) => b.accountId.equals(account.id))).go();
|
||||
await (delete(beneficiaries)
|
||||
..where((b) => b.accountId.equals(account.id))).go();
|
||||
|
||||
// Delete the account
|
||||
await (delete(accounts)..where((a) => a.id.equals(account.id))).go();
|
||||
}
|
||||
}
|
||||
|
||||
enum TransactionQueryDateOption { thisMonth }
|
||||
@@ -208,7 +227,7 @@ enum TransactionQueryDateOption { thisMonth }
|
||||
@DriftAccessor(tables: [Transactions, Beneficiaries, ExpenseCategories])
|
||||
class TransactionsDao extends DatabaseAccessor<OkaneDatabase>
|
||||
with _$TransactionsDaoMixin {
|
||||
TransactionsDao(OkaneDatabase db) : super(db);
|
||||
TransactionsDao(super.db);
|
||||
|
||||
JoinedSelectStatement _transactionQuery(Account account) {
|
||||
return (select(transactions)
|
||||
@@ -331,7 +350,7 @@ class TransactionsDao extends DatabaseAccessor<OkaneDatabase>
|
||||
@DriftAccessor(tables: [Beneficiaries])
|
||||
class BeneficiariesDao extends DatabaseAccessor<OkaneDatabase>
|
||||
with _$BeneficiariesDaoMixin {
|
||||
BeneficiariesDao(OkaneDatabase db) : super(db);
|
||||
BeneficiariesDao(super.db);
|
||||
|
||||
Stream<List<Beneficiary>> beneficiariesStream() {
|
||||
return select(beneficiaries).watch();
|
||||
@@ -360,7 +379,7 @@ class BeneficiariesDao extends DatabaseAccessor<OkaneDatabase>
|
||||
@DriftAccessor(tables: [ExpenseCategories])
|
||||
class ExpenseCategoriesDao extends DatabaseAccessor<OkaneDatabase>
|
||||
with _$ExpenseCategoriesDaoMixin {
|
||||
ExpenseCategoriesDao(OkaneDatabase db) : super(db);
|
||||
ExpenseCategoriesDao(super.db);
|
||||
|
||||
Stream<List<ExpenseCategory>> expenseCategoriesStream(Account account) {
|
||||
return select(expenseCategories).watch();
|
||||
@@ -373,31 +392,26 @@ class ExpenseCategoriesDao extends DatabaseAccessor<OkaneDatabase>
|
||||
|
||||
return select(expenseCategories).get();
|
||||
}
|
||||
|
||||
Future<ExpenseCategory> upsertCategory(ExpenseCategoriesCompanion category) {
|
||||
return into(
|
||||
expenseCategories,
|
||||
).insertReturning(category, mode: InsertMode.insertOrReplace);
|
||||
}
|
||||
}
|
||||
|
||||
@DriftAccessor(tables: [Budgets, BudgetItems])
|
||||
class BudgetsDao extends DatabaseAccessor<OkaneDatabase>
|
||||
with _$BudgetsDaoMixin {
|
||||
BudgetsDao(OkaneDatabase db) : super(db);
|
||||
BudgetsDao(super.db);
|
||||
|
||||
Stream<List<BudgetsDto>> budgetsStream(Account account) {
|
||||
return (select(budgets)..where((b) => b.accountId.equals(account.id)))
|
||||
.join([
|
||||
leftOuterJoin(
|
||||
budgetItems,
|
||||
budgetItems.budgetId.equalsExp(budgets.id),
|
||||
),
|
||||
])
|
||||
.watch()
|
||||
.map((rows) {
|
||||
return rows.map((row) {
|
||||
return BudgetsDto(
|
||||
budget: row.readTable(budgets),
|
||||
// TODO
|
||||
budgetItems: List.empty(),
|
||||
);
|
||||
}).toList();
|
||||
});
|
||||
return (select(budgets)
|
||||
..where((b) => b.accountId.equals(account.id))).watch().map((rows) {
|
||||
return rows.map((row) {
|
||||
return BudgetsDto(budget: row);
|
||||
}).toList();
|
||||
});
|
||||
}
|
||||
|
||||
Future<List<BudgetsDto>> getBudgets(Account? account) {
|
||||
@@ -405,20 +419,28 @@ class BudgetsDao extends DatabaseAccessor<OkaneDatabase>
|
||||
return Future.value(List.empty());
|
||||
}
|
||||
|
||||
return (select(budgets)..where((b) => b.accountId.equals(account.id)))
|
||||
return (select(budgets)
|
||||
..where((b) => b.accountId.equals(account.id))).get().then((rows) {
|
||||
return rows.map((row) {
|
||||
return BudgetsDto(budget: row);
|
||||
}).toList();
|
||||
});
|
||||
}
|
||||
|
||||
Stream<List<BudgetItemDto>> watchBudgetItems(Budget budget) {
|
||||
return (select(budgetItems)..where((b) => b.budgetId.equals(budget.id)))
|
||||
.join([
|
||||
leftOuterJoin(
|
||||
budgetItems,
|
||||
budgetItems.budgetId.equalsExp(budgets.id),
|
||||
expenseCategories,
|
||||
expenseCategories.id.equalsExp(budgetItems.expenseCategoryId),
|
||||
),
|
||||
])
|
||||
.get()
|
||||
.then((rows) {
|
||||
.watch()
|
||||
.map((rows) {
|
||||
return rows.map((row) {
|
||||
return BudgetsDto(
|
||||
budget: row.readTable(budgets),
|
||||
// TODO
|
||||
budgetItems: List.empty(),
|
||||
return BudgetItemDto(
|
||||
expenseCategory: row.readTable(expenseCategories),
|
||||
item: row.readTable(budgetItems),
|
||||
);
|
||||
}).toList();
|
||||
});
|
||||
@@ -439,7 +461,7 @@ class BudgetsDao extends DatabaseAccessor<OkaneDatabase>
|
||||
|
||||
@DriftAccessor(tables: [Loans, LoanChanges, Beneficiaries])
|
||||
class LoansDao extends DatabaseAccessor<OkaneDatabase> with _$LoansDaoMixin {
|
||||
LoansDao(OkaneDatabase db) : super(db);
|
||||
LoansDao(super.db);
|
||||
|
||||
Stream<List<LoanDto>> loansStream(Account account) {
|
||||
return select(loans)
|
||||
@@ -452,12 +474,10 @@ class LoansDao extends DatabaseAccessor<OkaneDatabase> with _$LoansDaoMixin {
|
||||
.watch()
|
||||
.map((rows) {
|
||||
return rows.map((row) {
|
||||
return (
|
||||
loan: row.readTable(loans),
|
||||
beneficiary: row.readTable(beneficiaries),
|
||||
changes: List.empty(),
|
||||
)
|
||||
as LoanDto;
|
||||
return LoanDto(
|
||||
loan: row.readTable(loans),
|
||||
beneficiary: row.readTable(beneficiaries),
|
||||
);
|
||||
}).toList();
|
||||
});
|
||||
}
|
||||
@@ -477,12 +497,10 @@ class LoansDao extends DatabaseAccessor<OkaneDatabase> with _$LoansDaoMixin {
|
||||
.get()
|
||||
.then((rows) {
|
||||
return rows.map((row) {
|
||||
return (
|
||||
loan: row.readTable(loans),
|
||||
beneficiary: row.readTable(beneficiaries),
|
||||
changes: List.empty(),
|
||||
)
|
||||
as LoanDto;
|
||||
return LoanDto(
|
||||
loan: row.readTable(loans),
|
||||
beneficiary: row.readTable(beneficiaries),
|
||||
);
|
||||
}).toList();
|
||||
});
|
||||
}
|
||||
@@ -506,6 +524,11 @@ class LoansDao extends DatabaseAccessor<OkaneDatabase> with _$LoansDaoMixin {
|
||||
).insertReturning(loanChange, mode: InsertMode.insertOrReplace);
|
||||
}
|
||||
|
||||
Stream<List<LoanChange>> watchLoanChanges(Loan loan) {
|
||||
return (select(loanChanges)
|
||||
..where((c) => c.loanId.equals(loan.id))).watch();
|
||||
}
|
||||
|
||||
Future<void> deleteLoanChange(int id) {
|
||||
return (delete(loanChanges)..where((c) => c.id.equals(id))).go();
|
||||
}
|
||||
@@ -514,7 +537,7 @@ class LoansDao extends DatabaseAccessor<OkaneDatabase> with _$LoansDaoMixin {
|
||||
@DriftAccessor(tables: [TransactionTemplates, ExpenseCategories, Beneficiaries])
|
||||
class TransactionTemplatesDao extends DatabaseAccessor<OkaneDatabase>
|
||||
with _$TransactionTemplatesDaoMixin {
|
||||
TransactionTemplatesDao(OkaneDatabase db) : super(db);
|
||||
TransactionTemplatesDao(super.db);
|
||||
|
||||
Stream<List<TransactionTemplateDto>> transactionTemplatesStream(
|
||||
Account account,
|
||||
@@ -595,7 +618,7 @@ class TransactionTemplatesDao extends DatabaseAccessor<OkaneDatabase>
|
||||
@DriftAccessor(tables: [TransactionTemplates, RecurringTransactions])
|
||||
class RecurringTransactionsDao extends DatabaseAccessor<OkaneDatabase>
|
||||
with _$RecurringTransactionsDaoMixin {
|
||||
RecurringTransactionsDao(OkaneDatabase db) : super(db);
|
||||
RecurringTransactionsDao(super.db);
|
||||
|
||||
Stream<List<RecurringTransactionDto>> recurringTransactionsStream(
|
||||
Account account,
|
||||
|
||||
@@ -8190,6 +8190,15 @@ class $OkaneDatabaseManager {
|
||||
|
||||
mixin _$AccountsDaoMixin on DatabaseAccessor<OkaneDatabase> {
|
||||
$AccountsTable get accounts => attachedDatabase.accounts;
|
||||
$ExpenseCategoriesTable get expenseCategories =>
|
||||
attachedDatabase.expenseCategories;
|
||||
$BeneficiariesTable get beneficiaries => attachedDatabase.beneficiaries;
|
||||
$TransactionsTable get transactions => attachedDatabase.transactions;
|
||||
$TransactionTemplatesTable get transactionTemplates =>
|
||||
attachedDatabase.transactionTemplates;
|
||||
$RecurringTransactionsTable get recurringTransactions =>
|
||||
attachedDatabase.recurringTransactions;
|
||||
$BudgetsTable get budgets => attachedDatabase.budgets;
|
||||
}
|
||||
mixin _$BeneficiariesDaoMixin on DatabaseAccessor<OkaneDatabase> {
|
||||
$AccountsTable get accounts => attachedDatabase.accounts;
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:okane/ui/pages/budgets/budget_details.dart';
|
||||
import 'package:okane/ui/pages/transaction_details.dart';
|
||||
import 'package:okane/ui/state/core.dart';
|
||||
import 'package:okane/ui/state/settings.dart';
|
||||
import 'package:sentry_flutter/sentry_flutter.dart';
|
||||
|
||||
import 'ui/pages/loans/loan_details.dart';
|
||||
|
||||
@@ -21,11 +22,20 @@ Future<void> main() async {
|
||||
|
||||
final settings = SettingsCubit();
|
||||
await settings.loadSettings();
|
||||
|
||||
GetIt.I.registerSingleton<SettingsCubit>(settings);
|
||||
GetIt.I.registerSingleton<CoreCubit>(CoreCubit());
|
||||
GetIt.I.registerSingleton<OkaneDatabase>(OkaneDatabase());
|
||||
|
||||
runApp(const MyApp());
|
||||
appRunner() => runApp(const MyApp());
|
||||
if (settings.sentryDsn != null) {
|
||||
print("Setting up Sentry!");
|
||||
await SentryFlutter.init((options) {
|
||||
options.dsn = settings.sentryDsn!;
|
||||
}, appRunner: appRunner);
|
||||
} else {
|
||||
appRunner();
|
||||
}
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
|
||||
@@ -44,7 +44,7 @@ class AccountListPageState extends State<AccountListPage> {
|
||||
width: 150,
|
||||
height: 100,
|
||||
child: Card(
|
||||
color: colorHash(state.accounts[index].name!),
|
||||
color: colorHash(state.accounts[index].name),
|
||||
shape:
|
||||
index == state.activeAccountIndex
|
||||
? RoundedRectangleBorder(
|
||||
@@ -61,7 +61,7 @@ class AccountListPageState extends State<AccountListPage> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(state.accounts[index].name!),
|
||||
Text(state.accounts[index].name),
|
||||
FutureBuilder(
|
||||
future: GetIt.I
|
||||
.get<OkaneDatabase>()
|
||||
|
||||
@@ -80,7 +80,6 @@ class AccountBalanceGraphCard extends StatelessWidget {
|
||||
child: FutureBuilder(
|
||||
future: getAccountBalance(),
|
||||
builder: (context, snapshot) {
|
||||
print("SNAPSHOT: ${snapshot.data}");
|
||||
if (!snapshot.hasData) {
|
||||
return CircularProgressIndicator();
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class BreakdownCard extends StatelessWidget {
|
||||
Map<String, double> expenses = {};
|
||||
Map<String, Color> colors = {};
|
||||
double usableMoney = 0;
|
||||
transactions.forEach((t) {
|
||||
for (var t in transactions) {
|
||||
String category;
|
||||
if (t.transaction.amount > 0) {
|
||||
category = CATEGORY_INCOME;
|
||||
@@ -67,7 +67,7 @@ class BreakdownCard extends StatelessWidget {
|
||||
ifAbsent: () => t.transaction.amount.abs().toDouble(),
|
||||
);
|
||||
usableMoney += t.transaction.amount;
|
||||
});
|
||||
}
|
||||
return (expenses: expenses, colors: colors, usable: usableMoney);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,13 @@ import 'package:okane/ui/widgets/add_expense_category.dart';
|
||||
class AddBudgetItemPopup extends StatefulWidget {
|
||||
final VoidCallback onDone;
|
||||
final BudgetsDto budget;
|
||||
final List<BudgetItemDto> items;
|
||||
|
||||
const AddBudgetItemPopup({
|
||||
super.key,
|
||||
required this.onDone,
|
||||
required this.budget,
|
||||
required this.items,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -72,7 +74,7 @@ class AddBudgetItemState extends State<AddBudgetItemPopup> {
|
||||
_expenseCategory == null) {
|
||||
return;
|
||||
}
|
||||
if (widget.budget.budgetItems
|
||||
if (widget.items
|
||||
.where(
|
||||
(i) =>
|
||||
i.expenseCategory.name == _expenseCategory!.name,
|
||||
@@ -84,10 +86,11 @@ class AddBudgetItemState extends State<AddBudgetItemPopup> {
|
||||
|
||||
await GetIt.I.get<OkaneDatabase>().budgetsDao.upsertBudgetItem(
|
||||
BudgetItemsCompanion(
|
||||
expenseCategoryId: Value(_expenseCategory!.id),
|
||||
amount: Value(
|
||||
double.parse(_budgetItemAmountEditController.text),
|
||||
),
|
||||
expenseCategoryId: Value(_expenseCategory!.id),
|
||||
budgetId: Value(widget.budget.budget.id),
|
||||
),
|
||||
);
|
||||
widget.onDone();
|
||||
|
||||
@@ -22,6 +22,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
builder:
|
||||
(_) => AddBudgetItemPopup(
|
||||
budget: state.activeBudget!,
|
||||
items: state.budgetItems,
|
||||
onDone: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
@@ -55,7 +56,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
return Text(t.pages.budgets.details.noBudgetSelected);
|
||||
}
|
||||
|
||||
if (state.activeBudget!.budgetItems.isEmpty) {
|
||||
if (state.budgetItems.isEmpty) {
|
||||
return Row(
|
||||
children: [
|
||||
Text(t.pages.budgets.details.noBudgetItems),
|
||||
@@ -95,10 +96,9 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
),
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: state.activeBudget!.budgetItems.length,
|
||||
itemCount: state.budgetItems.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = state.activeBudget!.budgetItems
|
||||
.elementAt(index);
|
||||
final item = state.budgetItems.elementAt(index);
|
||||
final amount = formatCurrency(item.item.amount);
|
||||
return ListTile(
|
||||
title: Text(
|
||||
@@ -120,7 +120,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
}
|
||||
|
||||
final categories =
|
||||
state.activeBudget!.budgetItems
|
||||
state.budgetItems
|
||||
// TODO
|
||||
//.map((i) => i.expenseCategory.value!.name)
|
||||
.map((i) => "lol")
|
||||
@@ -149,7 +149,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
spending.isEmpty
|
||||
? 0
|
||||
: spending.values.reduce((acc, val) => acc + val);
|
||||
final budgetTotal = state.activeBudget!.budgetItems
|
||||
final budgetTotal = state.budgetItems
|
||||
.map((i) => i.item.amount)
|
||||
.reduce((acc, val) => acc + val);
|
||||
return Column(
|
||||
@@ -271,7 +271,7 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
fallbackText: "",
|
||||
valueConverter: formatCurrency,
|
||||
items:
|
||||
state.activeBudget!.budgetItems
|
||||
state.budgetItems
|
||||
.map(
|
||||
(i) => (
|
||||
title: i.expenseCategory.name,
|
||||
@@ -342,10 +342,9 @@ class BudgetDetailsPage extends StatelessWidget {
|
||||
padding: EdgeInsets.all(8),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: state.activeBudget!.budgetItems.length,
|
||||
itemCount: state.budgetItems.length,
|
||||
itemBuilder: (context, index) {
|
||||
final item = state.activeBudget!.budgetItems
|
||||
.elementAt(index);
|
||||
final item = state.budgetItems.elementAt(index);
|
||||
final amount = formatCurrency(item.item.amount);
|
||||
final spent = spending[item.expenseCategory.name];
|
||||
final left =
|
||||
|
||||
@@ -91,6 +91,7 @@ class AddLoanPopupState extends State<AddLoanChangePopup> {
|
||||
sign * double.parse(_amountController.text).abs(),
|
||||
),
|
||||
date: Value(DateTime.now()),
|
||||
loanId: Value(widget.loan.loan.id),
|
||||
),
|
||||
);
|
||||
widget.onDone();
|
||||
|
||||
@@ -43,10 +43,9 @@ class LoanDetailsPage extends StatelessWidget {
|
||||
return Text("No loan selected");
|
||||
}
|
||||
|
||||
final loanChanges = state.activeLoan!.changes.toList();
|
||||
final loanSum =
|
||||
loanChanges.isNotEmpty
|
||||
? loanChanges
|
||||
state.loanChanges.isNotEmpty
|
||||
? state.loanChanges
|
||||
.map((c) => c.amount)
|
||||
.reduce((acc, val) => acc + val)
|
||||
: 0.0;
|
||||
@@ -94,9 +93,9 @@ class LoanDetailsPage extends StatelessWidget {
|
||||
|
||||
SliverToBoxAdapter(
|
||||
child:
|
||||
loanChanges.isNotEmpty
|
||||
state.loanChanges.isNotEmpty
|
||||
? GroupedListView(
|
||||
elements: loanChanges,
|
||||
elements: state.loanChanges,
|
||||
shrinkWrap: true,
|
||||
reverse: true,
|
||||
groupBy:
|
||||
|
||||
@@ -67,6 +67,74 @@ class SettingsPage extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
BlocBuilder<SettingsCubit, SettingsWrapper>(
|
||||
builder:
|
||||
(context, state) => ListTile(
|
||||
title: Text("Sentry"),
|
||||
subtitle: Text(
|
||||
"When enabled sends errors to the configured Sentry DSN.",
|
||||
),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.clear),
|
||||
onPressed:
|
||||
state.settings.sentryDsn == null
|
||||
? null
|
||||
: () async {
|
||||
final result = await confirm(
|
||||
context,
|
||||
"Clear Sentry DSN",
|
||||
"Are you sure you want to clear the Sentry DSN?",
|
||||
);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
await GetIt.I.get<SettingsCubit>().setSettings(
|
||||
state.settings.copyWith(sentryDsn: null),
|
||||
);
|
||||
},
|
||||
),
|
||||
onTap: () async {
|
||||
final controller = TextEditingController(
|
||||
text: state.settings.sentryDsn ?? '',
|
||||
);
|
||||
final result = await showDialogOrModal<String>(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
controller: controller,
|
||||
decoration: InputDecoration(hintText: "Sentry DSN"),
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
OutlinedButton(
|
||||
child: Text("Apply"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(controller.text);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
if (result == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
await GetIt.I.get<SettingsCubit>().setSettings(
|
||||
state.settings.copyWith(sentryDsn: result),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ class TransactionDetailsPage extends StatelessWidget {
|
||||
GetIt.I
|
||||
.get<CoreCubit>()
|
||||
.activeAccount!
|
||||
.name!,
|
||||
.name,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -20,8 +20,10 @@ abstract class CoreState with _$CoreState {
|
||||
@Default([]) List<Beneficiary> beneficiaries,
|
||||
@Default([]) List<ExpenseCategory> expenseCategories,
|
||||
@Default([]) List<BudgetsDto> budgets,
|
||||
@Default([]) List<BudgetItemDto> budgetItems,
|
||||
@Default(null) BudgetsDto? activeBudget,
|
||||
@Default([]) List<LoanDto> loans,
|
||||
@Default([]) List<LoanChange> loanChanges,
|
||||
@Default(null) LoanDto? activeLoan,
|
||||
@Default(false) bool isDeletingAccount,
|
||||
}) = _CoreState;
|
||||
@@ -37,7 +39,9 @@ class CoreCubit extends Cubit<CoreState> {
|
||||
StreamSubscription<void>? _beneficiariesStreamSubscription;
|
||||
StreamSubscription<void>? _expenseCategoryStreamSubscription;
|
||||
StreamSubscription<void>? _budgetsStreamSubscription;
|
||||
StreamSubscription<void>? _budgetItemsStreamSubscription;
|
||||
StreamSubscription<void>? _loanStreamSubscription;
|
||||
StreamSubscription<void>? _loanChangesSubscription;
|
||||
|
||||
void setupAccountStream() {
|
||||
_accountsStreamSubscription?.cancel();
|
||||
@@ -122,17 +126,6 @@ class CoreCubit extends Cubit<CoreState> {
|
||||
state.copyWith(
|
||||
accounts: accounts,
|
||||
activeAccountIndex: accounts.isEmpty ? null : 0,
|
||||
transactions: await db.transactionsDao.getTransactions(account),
|
||||
beneficiaries: await db.beneficiariesDao.getBeneficiaries(),
|
||||
transactionTemplates: await db.transactionTemplatesDao
|
||||
.getTransactionTemplates(account),
|
||||
recurringTransactions: await db.recurringTransactionsDao
|
||||
.getRecurringTransactions(account),
|
||||
expenseCategories: await db.expenseCategoriesDao.getExpenseCategories(
|
||||
account,
|
||||
),
|
||||
budgets: await db.budgetsDao.getBudgets(account),
|
||||
loans: await db.loansDao.getLoans(account),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -179,7 +172,17 @@ class CoreCubit extends Cubit<CoreState> {
|
||||
}
|
||||
|
||||
void setActiveBudget(BudgetsDto? budget) {
|
||||
emit(state.copyWith(activeBudget: budget));
|
||||
emit(state.copyWith(activeBudget: budget, budgetItems: []));
|
||||
_budgetItemsStreamSubscription?.cancel();
|
||||
if (budget != null) {
|
||||
_budgetItemsStreamSubscription = GetIt.I
|
||||
.get<OkaneDatabase>()
|
||||
.budgetsDao
|
||||
.watchBudgetItems(budget.budget)
|
||||
.listen((items) {
|
||||
emit(state.copyWith(budgetItems: items));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteAccount(Account account) async {
|
||||
@@ -190,16 +193,25 @@ class CoreCubit extends Cubit<CoreState> {
|
||||
|
||||
cancelStreams();
|
||||
try {
|
||||
// TODO
|
||||
//await db.deleteAccount(account);
|
||||
await GetIt.I.get<OkaneDatabase>().accountsDao.removeAccount(account);
|
||||
} finally {
|
||||
emit(state.copyWith(isDeletingAccount: false));
|
||||
}
|
||||
await init();
|
||||
}
|
||||
|
||||
void setActiveLoan(LoanDto loan) {
|
||||
emit(state.copyWith(activeLoan: loan));
|
||||
void setActiveLoan(LoanDto? loan) {
|
||||
emit(state.copyWith(activeLoan: loan, loanChanges: []));
|
||||
_loanChangesSubscription?.cancel();
|
||||
if (loan != null) {
|
||||
_loanChangesSubscription = GetIt.I
|
||||
.get<OkaneDatabase>()
|
||||
.loansDao
|
||||
.watchLoanChanges(loan.loan)
|
||||
.listen((changes) {
|
||||
emit(state.copyWith(loanChanges: changes));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Account? get activeAccount =>
|
||||
|
||||
@@ -30,8 +30,10 @@ mixin _$CoreState {
|
||||
List<ExpenseCategory> get expenseCategories =>
|
||||
throw _privateConstructorUsedError;
|
||||
List<BudgetsDto> get budgets => throw _privateConstructorUsedError;
|
||||
List<BudgetItemDto> get budgetItems => throw _privateConstructorUsedError;
|
||||
BudgetsDto? get activeBudget => throw _privateConstructorUsedError;
|
||||
List<LoanDto> get loans => throw _privateConstructorUsedError;
|
||||
List<LoanChange> get loanChanges => throw _privateConstructorUsedError;
|
||||
LoanDto? get activeLoan => throw _privateConstructorUsedError;
|
||||
bool get isDeletingAccount => throw _privateConstructorUsedError;
|
||||
|
||||
@@ -56,8 +58,10 @@ abstract class $CoreStateCopyWith<$Res> {
|
||||
List<Beneficiary> beneficiaries,
|
||||
List<ExpenseCategory> expenseCategories,
|
||||
List<BudgetsDto> budgets,
|
||||
List<BudgetItemDto> budgetItems,
|
||||
BudgetsDto? activeBudget,
|
||||
List<LoanDto> loans,
|
||||
List<LoanChange> loanChanges,
|
||||
LoanDto? activeLoan,
|
||||
bool isDeletingAccount,
|
||||
});
|
||||
@@ -86,8 +90,10 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
||||
Object? beneficiaries = null,
|
||||
Object? expenseCategories = null,
|
||||
Object? budgets = null,
|
||||
Object? budgetItems = null,
|
||||
Object? activeBudget = freezed,
|
||||
Object? loans = null,
|
||||
Object? loanChanges = null,
|
||||
Object? activeLoan = freezed,
|
||||
Object? isDeletingAccount = null,
|
||||
}) {
|
||||
@@ -143,6 +149,11 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
||||
? _value.budgets
|
||||
: budgets // ignore: cast_nullable_to_non_nullable
|
||||
as List<BudgetsDto>,
|
||||
budgetItems:
|
||||
null == budgetItems
|
||||
? _value.budgetItems
|
||||
: budgetItems // ignore: cast_nullable_to_non_nullable
|
||||
as List<BudgetItemDto>,
|
||||
activeBudget:
|
||||
freezed == activeBudget
|
||||
? _value.activeBudget
|
||||
@@ -153,6 +164,11 @@ class _$CoreStateCopyWithImpl<$Res, $Val extends CoreState>
|
||||
? _value.loans
|
||||
: loans // ignore: cast_nullable_to_non_nullable
|
||||
as List<LoanDto>,
|
||||
loanChanges:
|
||||
null == loanChanges
|
||||
? _value.loanChanges
|
||||
: loanChanges // ignore: cast_nullable_to_non_nullable
|
||||
as List<LoanChange>,
|
||||
activeLoan:
|
||||
freezed == activeLoan
|
||||
? _value.activeLoan
|
||||
@@ -189,8 +205,10 @@ abstract class _$$CoreStateImplCopyWith<$Res>
|
||||
List<Beneficiary> beneficiaries,
|
||||
List<ExpenseCategory> expenseCategories,
|
||||
List<BudgetsDto> budgets,
|
||||
List<BudgetItemDto> budgetItems,
|
||||
BudgetsDto? activeBudget,
|
||||
List<LoanDto> loans,
|
||||
List<LoanChange> loanChanges,
|
||||
LoanDto? activeLoan,
|
||||
bool isDeletingAccount,
|
||||
});
|
||||
@@ -218,8 +236,10 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
||||
Object? beneficiaries = null,
|
||||
Object? expenseCategories = null,
|
||||
Object? budgets = null,
|
||||
Object? budgetItems = null,
|
||||
Object? activeBudget = freezed,
|
||||
Object? loans = null,
|
||||
Object? loanChanges = null,
|
||||
Object? activeLoan = freezed,
|
||||
Object? isDeletingAccount = null,
|
||||
}) {
|
||||
@@ -275,6 +295,11 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
||||
? _value._budgets
|
||||
: budgets // ignore: cast_nullable_to_non_nullable
|
||||
as List<BudgetsDto>,
|
||||
budgetItems:
|
||||
null == budgetItems
|
||||
? _value._budgetItems
|
||||
: budgetItems // ignore: cast_nullable_to_non_nullable
|
||||
as List<BudgetItemDto>,
|
||||
activeBudget:
|
||||
freezed == activeBudget
|
||||
? _value.activeBudget
|
||||
@@ -285,6 +310,11 @@ class __$$CoreStateImplCopyWithImpl<$Res>
|
||||
? _value._loans
|
||||
: loans // ignore: cast_nullable_to_non_nullable
|
||||
as List<LoanDto>,
|
||||
loanChanges:
|
||||
null == loanChanges
|
||||
? _value._loanChanges
|
||||
: loanChanges // ignore: cast_nullable_to_non_nullable
|
||||
as List<LoanChange>,
|
||||
activeLoan:
|
||||
freezed == activeLoan
|
||||
? _value.activeLoan
|
||||
@@ -314,8 +344,10 @@ class _$CoreStateImpl implements _CoreState {
|
||||
final List<Beneficiary> beneficiaries = const [],
|
||||
final List<ExpenseCategory> expenseCategories = const [],
|
||||
final List<BudgetsDto> budgets = const [],
|
||||
final List<BudgetItemDto> budgetItems = const [],
|
||||
this.activeBudget = null,
|
||||
final List<LoanDto> loans = const [],
|
||||
final List<LoanChange> loanChanges = const [],
|
||||
this.activeLoan = null,
|
||||
this.isDeletingAccount = false,
|
||||
}) : _accounts = accounts,
|
||||
@@ -325,7 +357,9 @@ class _$CoreStateImpl implements _CoreState {
|
||||
_beneficiaries = beneficiaries,
|
||||
_expenseCategories = expenseCategories,
|
||||
_budgets = budgets,
|
||||
_loans = loans;
|
||||
_budgetItems = budgetItems,
|
||||
_loans = loans,
|
||||
_loanChanges = loanChanges;
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
@@ -401,6 +435,15 @@ class _$CoreStateImpl implements _CoreState {
|
||||
return EqualUnmodifiableListView(_budgets);
|
||||
}
|
||||
|
||||
final List<BudgetItemDto> _budgetItems;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<BudgetItemDto> get budgetItems {
|
||||
if (_budgetItems is EqualUnmodifiableListView) return _budgetItems;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_budgetItems);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final BudgetsDto? activeBudget;
|
||||
@@ -413,6 +456,15 @@ class _$CoreStateImpl implements _CoreState {
|
||||
return EqualUnmodifiableListView(_loans);
|
||||
}
|
||||
|
||||
final List<LoanChange> _loanChanges;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<LoanChange> get loanChanges {
|
||||
if (_loanChanges is EqualUnmodifiableListView) return _loanChanges;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_loanChanges);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final LoanDto? activeLoan;
|
||||
@@ -422,7 +474,7 @@ class _$CoreStateImpl implements _CoreState {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, activeBudget: $activeBudget, loans: $loans, activeLoan: $activeLoan, isDeletingAccount: $isDeletingAccount)';
|
||||
return 'CoreState(activePage: $activePage, activeAccountIndex: $activeAccountIndex, activeTransaction: $activeTransaction, accounts: $accounts, recurringTransactions: $recurringTransactions, transactions: $transactions, transactionTemplates: $transactionTemplates, beneficiaries: $beneficiaries, expenseCategories: $expenseCategories, budgets: $budgets, budgetItems: $budgetItems, activeBudget: $activeBudget, loans: $loans, loanChanges: $loanChanges, activeLoan: $activeLoan, isDeletingAccount: $isDeletingAccount)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -458,9 +510,17 @@ class _$CoreStateImpl implements _CoreState {
|
||||
_expenseCategories,
|
||||
) &&
|
||||
const DeepCollectionEquality().equals(other._budgets, _budgets) &&
|
||||
const DeepCollectionEquality().equals(
|
||||
other._budgetItems,
|
||||
_budgetItems,
|
||||
) &&
|
||||
(identical(other.activeBudget, activeBudget) ||
|
||||
other.activeBudget == activeBudget) &&
|
||||
const DeepCollectionEquality().equals(other._loans, _loans) &&
|
||||
const DeepCollectionEquality().equals(
|
||||
other._loanChanges,
|
||||
_loanChanges,
|
||||
) &&
|
||||
(identical(other.activeLoan, activeLoan) ||
|
||||
other.activeLoan == activeLoan) &&
|
||||
(identical(other.isDeletingAccount, isDeletingAccount) ||
|
||||
@@ -480,8 +540,10 @@ class _$CoreStateImpl implements _CoreState {
|
||||
const DeepCollectionEquality().hash(_beneficiaries),
|
||||
const DeepCollectionEquality().hash(_expenseCategories),
|
||||
const DeepCollectionEquality().hash(_budgets),
|
||||
const DeepCollectionEquality().hash(_budgetItems),
|
||||
activeBudget,
|
||||
const DeepCollectionEquality().hash(_loans),
|
||||
const DeepCollectionEquality().hash(_loanChanges),
|
||||
activeLoan,
|
||||
isDeletingAccount,
|
||||
);
|
||||
@@ -505,8 +567,10 @@ abstract class _CoreState implements CoreState {
|
||||
final List<Beneficiary> beneficiaries,
|
||||
final List<ExpenseCategory> expenseCategories,
|
||||
final List<BudgetsDto> budgets,
|
||||
final List<BudgetItemDto> budgetItems,
|
||||
final BudgetsDto? activeBudget,
|
||||
final List<LoanDto> loans,
|
||||
final List<LoanChange> loanChanges,
|
||||
final LoanDto? activeLoan,
|
||||
final bool isDeletingAccount,
|
||||
}) = _$CoreStateImpl;
|
||||
@@ -532,10 +596,14 @@ abstract class _CoreState implements CoreState {
|
||||
@override
|
||||
List<BudgetsDto> get budgets;
|
||||
@override
|
||||
List<BudgetItemDto> get budgetItems;
|
||||
@override
|
||||
BudgetsDto? get activeBudget;
|
||||
@override
|
||||
List<LoanDto> get loans;
|
||||
@override
|
||||
List<LoanChange> get loanChanges;
|
||||
@override
|
||||
LoanDto? get activeLoan;
|
||||
@override
|
||||
bool get isDeletingAccount;
|
||||
|
||||
@@ -13,6 +13,7 @@ enum ColorSchemeSettings { light, dark, system }
|
||||
abstract class Settings with _$Settings {
|
||||
const factory Settings({
|
||||
@Default(ColorSchemeSettings.system) ColorSchemeSettings colorScheme,
|
||||
@Default(null) String? sentryDsn,
|
||||
}) = _Settings;
|
||||
|
||||
factory Settings.fromJson(Map<String, Object?> json) =>
|
||||
@@ -45,4 +46,6 @@ class SettingsCubit extends Cubit<SettingsWrapper> {
|
||||
|
||||
await _prefs.setString("settings", jsonEncode(settings.toJson()));
|
||||
}
|
||||
|
||||
String? get sentryDsn => state.settings.sentryDsn;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ Settings _$SettingsFromJson(Map<String, dynamic> json) {
|
||||
/// @nodoc
|
||||
mixin _$Settings {
|
||||
ColorSchemeSettings get colorScheme => throw _privateConstructorUsedError;
|
||||
String? get sentryDsn => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
@@ -34,7 +35,7 @@ abstract class $SettingsCopyWith<$Res> {
|
||||
factory $SettingsCopyWith(Settings value, $Res Function(Settings) then) =
|
||||
_$SettingsCopyWithImpl<$Res, Settings>;
|
||||
@useResult
|
||||
$Res call({ColorSchemeSettings colorScheme});
|
||||
$Res call({ColorSchemeSettings colorScheme, String? sentryDsn});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -49,7 +50,7 @@ class _$SettingsCopyWithImpl<$Res, $Val extends Settings>
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({Object? colorScheme = null}) {
|
||||
$Res call({Object? colorScheme = null, Object? sentryDsn = freezed}) {
|
||||
return _then(
|
||||
_value.copyWith(
|
||||
colorScheme:
|
||||
@@ -57,6 +58,11 @@ class _$SettingsCopyWithImpl<$Res, $Val extends Settings>
|
||||
? _value.colorScheme
|
||||
: colorScheme // ignore: cast_nullable_to_non_nullable
|
||||
as ColorSchemeSettings,
|
||||
sentryDsn:
|
||||
freezed == sentryDsn
|
||||
? _value.sentryDsn
|
||||
: sentryDsn // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
)
|
||||
as $Val,
|
||||
);
|
||||
@@ -72,7 +78,7 @@ abstract class _$$SettingsImplCopyWith<$Res>
|
||||
) = __$$SettingsImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({ColorSchemeSettings colorScheme});
|
||||
$Res call({ColorSchemeSettings colorScheme, String? sentryDsn});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -86,7 +92,7 @@ class __$$SettingsImplCopyWithImpl<$Res>
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({Object? colorScheme = null}) {
|
||||
$Res call({Object? colorScheme = null, Object? sentryDsn = freezed}) {
|
||||
return _then(
|
||||
_$SettingsImpl(
|
||||
colorScheme:
|
||||
@@ -94,6 +100,11 @@ class __$$SettingsImplCopyWithImpl<$Res>
|
||||
? _value.colorScheme
|
||||
: colorScheme // ignore: cast_nullable_to_non_nullable
|
||||
as ColorSchemeSettings,
|
||||
sentryDsn:
|
||||
freezed == sentryDsn
|
||||
? _value.sentryDsn
|
||||
: sentryDsn // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -102,7 +113,10 @@ class __$$SettingsImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$SettingsImpl implements _Settings {
|
||||
const _$SettingsImpl({this.colorScheme = ColorSchemeSettings.system});
|
||||
const _$SettingsImpl({
|
||||
this.colorScheme = ColorSchemeSettings.system,
|
||||
this.sentryDsn = null,
|
||||
});
|
||||
|
||||
factory _$SettingsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$SettingsImplFromJson(json);
|
||||
@@ -110,10 +124,13 @@ class _$SettingsImpl implements _Settings {
|
||||
@override
|
||||
@JsonKey()
|
||||
final ColorSchemeSettings colorScheme;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String? sentryDsn;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Settings(colorScheme: $colorScheme)';
|
||||
return 'Settings(colorScheme: $colorScheme, sentryDsn: $sentryDsn)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -122,12 +139,14 @@ class _$SettingsImpl implements _Settings {
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$SettingsImpl &&
|
||||
(identical(other.colorScheme, colorScheme) ||
|
||||
other.colorScheme == colorScheme));
|
||||
other.colorScheme == colorScheme) &&
|
||||
(identical(other.sentryDsn, sentryDsn) ||
|
||||
other.sentryDsn == sentryDsn));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, colorScheme);
|
||||
int get hashCode => Object.hash(runtimeType, colorScheme, sentryDsn);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@@ -142,8 +161,10 @@ class _$SettingsImpl implements _Settings {
|
||||
}
|
||||
|
||||
abstract class _Settings implements Settings {
|
||||
const factory _Settings({final ColorSchemeSettings colorScheme}) =
|
||||
_$SettingsImpl;
|
||||
const factory _Settings({
|
||||
final ColorSchemeSettings colorScheme,
|
||||
final String? sentryDsn,
|
||||
}) = _$SettingsImpl;
|
||||
|
||||
factory _Settings.fromJson(Map<String, dynamic> json) =
|
||||
_$SettingsImpl.fromJson;
|
||||
@@ -151,6 +172,8 @@ abstract class _Settings implements Settings {
|
||||
@override
|
||||
ColorSchemeSettings get colorScheme;
|
||||
@override
|
||||
String? get sentryDsn;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$SettingsImplCopyWith<_$SettingsImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@@ -14,11 +14,13 @@ _$SettingsImpl _$$SettingsImplFromJson(Map<String, dynamic> json) =>
|
||||
json['colorScheme'],
|
||||
) ??
|
||||
ColorSchemeSettings.system,
|
||||
sentryDsn: json['sentryDsn'] as String? ?? null,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$SettingsImplToJson(_$SettingsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'colorScheme': _$ColorSchemeSettingsEnumMap[instance.colorScheme]!,
|
||||
'sentryDsn': instance.sentryDsn,
|
||||
};
|
||||
|
||||
const _$ColorSchemeSettingsEnumMap = {
|
||||
|
||||
@@ -25,7 +25,7 @@ class AccountSwitcher extends StatelessWidget {
|
||||
itemBuilder: (context, index) {
|
||||
final item = state.accounts[index];
|
||||
return ListTile(
|
||||
title: Text(item.name!),
|
||||
title: Text(item.name),
|
||||
trailing: IconButton(
|
||||
icon: Icon(Icons.delete),
|
||||
color: Colors.red,
|
||||
@@ -65,7 +65,7 @@ class AccountSwitcher extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
bloc.activeAccount!.name!,
|
||||
bloc.activeAccount!.name,
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
Icon(Icons.arrow_drop_down),
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import 'package:drift/drift.dart' show Value;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:okane/database/sqlite.dart';
|
||||
import 'package:okane/i18n/strings.g.dart';
|
||||
import 'package:okane/ui/state/core.dart';
|
||||
|
||||
@@ -48,14 +51,16 @@ class AddExpenseCategoryState extends State<AddExpenseCategory> {
|
||||
Spacer(),
|
||||
OutlinedButton(
|
||||
onPressed: () async {
|
||||
// TODO
|
||||
/*
|
||||
final category =
|
||||
ExpenseCategory()
|
||||
..name = _categoryNameController.text;
|
||||
await upsertExpenseCategory(category);
|
||||
final category = await GetIt.I
|
||||
.get<OkaneDatabase>()
|
||||
.expenseCategoriesDao
|
||||
.upsertCategory(
|
||||
ExpenseCategoriesCompanion(
|
||||
name: Value(_categoryNameController.text),
|
||||
),
|
||||
);
|
||||
_categoryNameController.text = "";
|
||||
Navigator.of(context).pop(category);*/
|
||||
Navigator.of(context).pop(category);
|
||||
},
|
||||
child: Text(t.modals.add),
|
||||
),
|
||||
|
||||
@@ -6,9 +6,13 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <sentry_flutter/sentry_flutter_plugin.h>
|
||||
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) sentry_flutter_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin");
|
||||
sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);
|
||||
g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin");
|
||||
sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
sentry_flutter
|
||||
sqlite3_flutter_libs
|
||||
)
|
||||
|
||||
|
||||
56
pubspec.lock
56
pubspec.lock
@@ -405,6 +405,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -565,6 +573,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
package_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.3.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -685,6 +709,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.9"
|
||||
sentry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sentry
|
||||
sha256: "599701ca0693a74da361bc780b0752e1abc98226cf5095f6b069648116c896bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.14.2"
|
||||
sentry_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry_flutter
|
||||
sha256: "5ba2cf40646a77d113b37a07bd69f61bb3ec8a73cbabe5537b05a7c89d2656f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.14.2"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -810,6 +850,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sprintf
|
||||
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
sqlite3:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -898,6 +946,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -2,7 +2,7 @@ name: okane
|
||||
description: "A cross-platform finance tracker."
|
||||
publish_to: "none"
|
||||
|
||||
version: 1.0.0+3
|
||||
version: 1.0.0+6
|
||||
environment:
|
||||
sdk: ^3.7.0
|
||||
|
||||
@@ -29,6 +29,9 @@ dependencies:
|
||||
drift: ^2.26.1
|
||||
drift_flutter: ^0.2.4
|
||||
|
||||
# For optional error tracking
|
||||
sentry_flutter: ^8.14.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:okane/database/collections/recurrent.dart';
|
||||
|
||||
void main() {
|
||||
group("isDue", () {
|
||||
test("null value", () {
|
||||
final t = RecurringTransaction()..lastExecution = null;
|
||||
expect(t.isDue(DateTime.now()), true);
|
||||
});
|
||||
|
||||
test("Date before", () {
|
||||
final now = DateTime.now();
|
||||
final t =
|
||||
RecurringTransaction()
|
||||
..lastExecution = now
|
||||
..days = 30;
|
||||
expect(t.isDue(now.add(Duration(days: 10))), false);
|
||||
});
|
||||
|
||||
test("Date before warning", () {
|
||||
final now = DateTime.now();
|
||||
final t =
|
||||
RecurringTransaction()
|
||||
..lastExecution = now
|
||||
..days = 30;
|
||||
expect(t.isDue(now.add(Duration(days: 20))), true);
|
||||
});
|
||||
|
||||
test("Expired", () {
|
||||
final now = DateTime.now();
|
||||
final t =
|
||||
RecurringTransaction()
|
||||
..lastExecution = now
|
||||
..days = 30;
|
||||
expect(t.isDue(now.add(Duration(days: 31))), true);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user