This commit is contained in:
2026-06-13 22:43:06 +03:00
parent 2682c92f23
commit 8fb785944c
29 changed files with 671 additions and 322 deletions
+128
View File
@@ -0,0 +1,128 @@
# AGENTS.md
## Project Overview
Personal finance Flutter app for Android. Tracks accounts, transactions, categories, budgets with multi-currency support, biometric auth, and haptic feedback.
## Stack
- **Flutter** — UI framework
- **Riverpod** — state management (per-feature `provider.dart` files)
- **Drift** — local database (code generation via `.g.dart`)
- **Feature-first architecture**
## Project Structure
```
lib/
├── app/ # App root, router, theme
├── core/ # Constants, l10n, core services, utils
├── data/ # Database schema, repositories
├── features/ # Feature modules (provider + screen + widgets)
├── shared/ # Cross-feature models, providers, services, widgets
└── main.dart
```
### Layer Responsibilities
**`core/`** — app-wide infrastructure. No business logic.
- `constants.dart` — global constants
- `l10n/` — localization strings and locale provider
- `services/` — biometric, haptic, card color services
- `utils/result.dart``Result<T>` type for error handling
**`data/`** — persistence only. No UI, no Riverpod providers.
- `database/` — Drift tables and generated code. Do not edit `.g.dart` files manually.
- `repositories/``AccountRepository`, `TransactionRepository`. All DB access goes through repositories.
**`features/<name>/`** — self-contained feature modules.
- `provider.dart` — Riverpod providers scoped to this feature
- `screen.dart` — top-level screen widget, minimal logic
- `widgets/` — feature-specific widgets
**`shared/`** — reusable across features.
- `models/``Account`, `Transaction` data classes
- `providers/` — providers used by multiple features
- `services/``ExchangeRateService`, `StorageService`
- `utils/``CurrencyUtils`
- `widgets/``BynSign`, `ErrorSnackbar`
## Architecture Rules
- Widgets never access repositories directly — always through providers
- Providers in `features/<name>/provider.dart` are local to that feature
- Providers in `shared/providers/` are app-wide
- Business logic lives in providers or repositories, not in widgets or screens
- `Result<T>` from `core/utils/result.dart` is used for fallible operations in repositories
- Database queries are in repositories only — no raw Drift queries in providers or widgets
- After any changes to Drift tables or DAOs, run `dart run build_runner build --delete-conflicting-outputs`
## Code Style
**No comments anywhere in the codebase.** No `//`, no `/* */`, no `///` doc comments. Code must be self-explanatory through naming.
- Use descriptive names — no abbreviations unless universally known (`id`, `url`, `db`)
- Prefer named constructors and named parameters
- Extract widgets aggressively — if a build method exceeds ~40 lines, split it
- Widget files: one primary widget per file, name matches filename
- Use `final` everywhere possible
- No `dynamic` types
- Avoid `late` unless genuinely necessary
## Naming Conventions
| Element | Convention | Example |
|---|---|---|
| Files | `snake_case.dart` | `balance_card.dart` |
| Classes | `PascalCase` | `BalanceCard` |
| Providers | `camelCase` + `Provider` suffix | `transactionListProvider` |
| Riverpod notifiers | `PascalCase` + `Notifier` suffix | `AddTransactionNotifier` |
| Private members | `_camelCase` | `_handleSubmit` |
## Feature Structure Template
When adding a new feature, follow this pattern:
```
features/
└── <feature_name>/
├── provider.dart # Riverpod providers for this feature
├── screen.dart # Top-level screen widget
└── widgets/ # Sub-widgets (create only if needed)
```
## Key Patterns
**Error handling** — use `Result<T>`:
```dart
final result = await repository.getAccounts();
result.when(
success: (accounts) => ...,
failure: (error) => ...,
);
```
**Localization** — use `AppStrings` from `core/l10n/app_strings.dart`, never hardcode strings visible to the user.
**Currency formatting** — use `CurrencyUtils` and `amountFormatProvider`, never format amounts manually.
**Haptics** — route all haptic feedback through `HapticService`, never call `HapticFeedback` directly.
**Colors for accounts** — use `CardColorService`, not hardcoded colors.
## Existing Features
- **dashboard** — main screen with account carousel (`BalanceCard`), transaction list, search, filter chips, budget progress, account editor overlay
- **add_transaction** — form screen: amount input, type toggle (income/expense), category picker, currency picker, account selector, date/time pickers, note field
- **categories** — category list management
- **settings** — theme, language, currency, budget, amount format, card text color, haptics, currency conversions
## What NOT to Do
- Do not add comments
- Do not put business logic in screen or widget files
- Do not access `AppDatabase` directly from features — use repositories
- Do not create new providers in `shared/providers/` unless the provider is needed by 2+ features
- Do not use `BuildContext` across async gaps without checking `mounted`
- Do not hardcode user-facing strings — use `AppStrings`
- Do not format currency amounts manually — use `CurrencyUtils`
-5
View File
@@ -3,7 +3,6 @@ import java.io.FileInputStream
plugins { plugins {
id("com.android.application") id("com.android.application")
id("kotlin-android")
id("dev.flutter.flutter-gradle-plugin") id("dev.flutter.flutter-gradle-plugin")
} }
@@ -23,10 +22,6 @@ android {
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17
} }
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
defaultConfig { defaultConfig {
applicationId = "com.kolo.casha" applicationId = "com.kolo.casha"
minSdk = flutter.minSdkVersion minSdk = flutter.minSdkVersion
+4
View File
@@ -1,2 +1,6 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true android.useAndroidX=true
# This builtInKotlin flag was added automatically by Flutter migrator
android.builtInKotlin=false
# This newDsl flag was added automatically by Flutter migrator
android.newDsl=false
-1
View File
@@ -20,7 +20,6 @@ pluginManagement {
plugins { plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.11.1" apply false id("com.android.application") version "8.11.1" apply false
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
} }
include(":app") include(":app")
-4
View File
@@ -25,10 +25,6 @@ class BiometricService {
try { try {
return await _auth.authenticate( return await _auth.authenticate(
localizedReason: 'Confirm your identity to open Casha', localizedReason: 'Confirm your identity to open Casha',
options: const AuthenticationOptions(
biometricOnly: false,
stickyAuth: true,
),
); );
} catch (_) { } catch (_) {
return false; return false;
+16 -11
View File
@@ -80,14 +80,23 @@ class AddTransactionState {
bool get isEditing => editingId != null; bool get isEditing => editingId != null;
} }
class AddTransactionNotifier extends StateNotifier<AddTransactionState> { final addTransactionProvider = NotifierProvider.autoDispose
AddTransactionNotifier(Transaction? initial) .family<AddTransactionNotifier, AddTransactionState, Transaction?>(
: super( (initial) => AddTransactionNotifier(initial),
initial != null
? AddTransactionState.fromTransaction(initial)
: AddTransactionState.empty(),
); );
class AddTransactionNotifier extends Notifier<AddTransactionState> {
AddTransactionNotifier(this._initial);
final Transaction? _initial;
@override
AddTransactionState build() {
return _initial != null
? AddTransactionState.fromTransaction(_initial!)
: AddTransactionState.empty();
}
void setAmount(double? v) => state = state.copyWith(amount: v); void setAmount(double? v) => state = state.copyWith(amount: v);
void setCategory(String v) => state = state.copyWith(category: v); void setCategory(String v) => state = state.copyWith(category: v);
@@ -123,11 +132,6 @@ class AddTransactionNotifier extends StateNotifier<AddTransactionState> {
void reset() => state = AddTransactionState.empty(); void reset() => state = AddTransactionState.empty();
} }
final addTransactionProvider = StateNotifierProvider.autoDispose
.family<AddTransactionNotifier, AddTransactionState, Transaction?>(
(ref, initial) => AddTransactionNotifier(initial),
);
final availableCategoriesProvider = Provider.autoDispose final availableCategoriesProvider = Provider.autoDispose
.family<List<String>, Transaction?>((ref, initial) { .family<List<String>, Transaction?>((ref, initial) {
final type = ref.watch( final type = ref.watch(
@@ -135,3 +139,4 @@ final availableCategoriesProvider = Provider.autoDispose
); );
return AppCategories.forType(type); return AppCategories.forType(type);
}); });
+5 -5
View File
@@ -82,7 +82,7 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
if (widget.initial!.category == 'Transfer') { if (widget.initial!.category == 'Transfer') {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
final allTxs = ref.read(transactionsProvider).valueOrNull ?? []; final allTxs = ref.read(transactionsProvider).value ?? [];
if (widget.initial!.type == TransactionType.expense) { if (widget.initial!.type == TransactionType.expense) {
final counterpart = allTxs.firstWhereOrNull( final counterpart = allTxs.firstWhereOrNull(
@@ -271,7 +271,7 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
currencyCode: currencyCode, currencyCode: currencyCode,
accountId: state.selectedAccountId!, accountId: state.selectedAccountId!,
); );
await ref.read(transactionsProvider.notifier).update(updatedExpense); await ref.read(transactionsProvider.notifier).updateTransaction(updatedExpense);
if (_transferIncomeRecordId != null) { if (_transferIncomeRecordId != null) {
final updatedIncome = Transaction( final updatedIncome = Transaction(
@@ -285,7 +285,7 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
currencyCode: currencyCode, currencyCode: currencyCode,
accountId: state.toAccountId!, accountId: state.toAccountId!,
); );
await ref.read(transactionsProvider.notifier).update(updatedIncome); await ref.read(transactionsProvider.notifier).updateTransaction(updatedIncome);
} }
if (mounted) context.pop(); if (mounted) context.pop();
@@ -349,7 +349,7 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
); );
if (state.isEditing) { if (state.isEditing) {
await ref.read(transactionsProvider.notifier).update(tx); await ref.read(transactionsProvider.notifier).updateTransaction(tx);
} else { } else {
final res = await ref.read(transactionsProvider.notifier).add(tx); final res = await ref.read(transactionsProvider.notifier).add(tx);
@@ -486,7 +486,7 @@ class _AddTransactionScreenState extends ConsumerState<AddTransactionScreen>
.delete(counterpartId); .delete(counterpartId);
} else { } else {
final allTxs = final allTxs =
ref.read(transactionsProvider).valueOrNull ?? ref.read(transactionsProvider).value ??
[]; [];
final oppositeType = final oppositeType =
widget.initial!.type == widget.initial!.type ==
@@ -41,7 +41,7 @@ class AccountRow extends ConsumerWidget {
final s = ref.watch(stringsProvider); final s = ref.watch(stringsProvider);
final state = ref.watch(addTransactionProvider(initial)); final state = ref.watch(addTransactionProvider(initial));
final accountsAsync = ref.watch(accountsProvider); final accountsAsync = ref.watch(accountsProvider);
final accounts = accountsAsync.valueOrNull ?? []; final accounts = accountsAsync.value ?? [];
final isTransfer = state.type == TransactionType.transfer; final isTransfer = state.type == TransactionType.transfer;
if (isTransfer && accounts.length == 2 && state.selectedAccountId != null) { if (isTransfer && accounts.length == 2 && state.selectedAccountId != null) {
@@ -21,7 +21,7 @@ class TypeToggle extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final accountsAsync = ref.watch(accountsProvider); final accountsAsync = ref.watch(accountsProvider);
final accounts = accountsAsync.valueOrNull ?? []; final accounts = accountsAsync.value ?? [];
final transferDisabled = accounts.length <= 1; final transferDisabled = accounts.length <= 1;
return Container( return Container(
+3 -3
View File
@@ -4,7 +4,7 @@ import '../dashboard/provider.dart';
final categoryExpenseProvider = Provider<Map<String, double>>((ref) { final categoryExpenseProvider = Provider<Map<String, double>>((ref) {
final txsAsync = ref.watch(transactionsProvider); final txsAsync = ref.watch(transactionsProvider);
final txs = txsAsync.valueOrNull ?? []; final txs = txsAsync.value ?? [];
final filtered = txs.where((t) => t.type == TransactionType.expense); final filtered = txs.where((t) => t.type == TransactionType.expense);
final map = <String, double>{}; final map = <String, double>{};
@@ -16,7 +16,7 @@ final categoryExpenseProvider = Provider<Map<String, double>>((ref) {
final categoryIncomeProvider = Provider<Map<String, double>>((ref) { final categoryIncomeProvider = Provider<Map<String, double>>((ref) {
final txsAsync = ref.watch(transactionsProvider); final txsAsync = ref.watch(transactionsProvider);
final txs = txsAsync.valueOrNull ?? []; final txs = txsAsync.value ?? [];
final filtered = txs.where((t) => t.type == TransactionType.income); final filtered = txs.where((t) => t.type == TransactionType.income);
final map = <String, double>{}; final map = <String, double>{};
@@ -28,7 +28,7 @@ final categoryIncomeProvider = Provider<Map<String, double>>((ref) {
final monthlyBreakdownProvider = Provider<List<MonthlyData>>((ref) { final monthlyBreakdownProvider = Provider<List<MonthlyData>>((ref) {
final txsAsync = ref.watch(transactionsProvider); final txsAsync = ref.watch(transactionsProvider);
final txs = txsAsync.valueOrNull ?? []; final txs = txsAsync.value ?? [];
final filtered = txs.where((t) => t.type == TransactionType.expense); final filtered = txs.where((t) => t.type == TransactionType.expense);
final now = DateTime.now(); final now = DateTime.now();
+211 -77
View File
@@ -35,77 +35,75 @@ final storageServiceProvider = Provider<StorageService>((ref) {
}); });
final transactionsProvider = final transactionsProvider =
StateNotifierProvider<TransactionsNotifier, AsyncValue<List<Transaction>>>(( AsyncNotifierProvider<TransactionsNotifier, List<Transaction>>(
ref, TransactionsNotifier.new,
) { );
class TransactionsNotifier extends AsyncNotifier<List<Transaction>> {
@override
Future<List<Transaction>> build() async {
final repository = ref.watch(transactionRepositoryProvider); final repository = ref.watch(transactionRepositoryProvider);
return TransactionsNotifier(repository); final result = await repository.getAll();
});
class TransactionsNotifier if (result.isSuccess) {
extends StateNotifier<AsyncValue<List<Transaction>>> { return result.dataOrNull!;
final TransactionRepository _repository; } else {
throw result.errorOrNull!;
TransactionsNotifier(this._repository) : super(const AsyncValue.loading()) {
_load();
} }
Future<void> _load() async {
state = const AsyncValue.loading();
final result = await _repository.getAll();
state = result.isSuccess
? AsyncValue.data(result.dataOrNull!)
: AsyncValue.error(result.errorOrNull!, StackTrace.current);
} }
Future<Result<void>> add(Transaction transaction) async { Future<Result<void>> add(Transaction transaction) async {
final result = await _repository.add(transaction); final repository = ref.read(transactionRepositoryProvider);
final result = await repository.add(transaction);
if (result.isSuccess) { if (result.isSuccess) {
await _load(); ref.invalidateSelf();
} }
return result; return result;
} }
Future<Result<void>> update(Transaction transaction) async { Future<Result<void>> updateTransaction(Transaction transaction) async {
final result = await _repository.update(transaction); final repository = ref.read(transactionRepositoryProvider);
final result = await repository.update(transaction);
if (result.isSuccess) { if (result.isSuccess) {
await _load(); ref.invalidateSelf();
} }
return result; return result;
} }
Future<Result<void>> delete(String id) async { Future<Result<void>> delete(String id) async {
final result = await _repository.delete(id); final repository = ref.read(transactionRepositoryProvider);
final result = await repository.delete(id);
if (result.isSuccess) { if (result.isSuccess) {
await _load(); ref.invalidateSelf();
} }
return result; return result;
} }
Future<void> restore(Transaction transaction) async { Future<void> restore(Transaction transaction) async {
await _repository.add(transaction); final repository = ref.read(transactionRepositoryProvider);
await _load(); await repository.add(transaction);
ref.invalidateSelf();
} }
Future<void> clearAll() async { Future<void> clearAll() async {
await _repository.deleteAll(); final repository = ref.read(transactionRepositoryProvider);
await repository.deleteAll();
state = const AsyncValue.data([]); state = const AsyncValue.data([]);
} }
Future<void> refresh() async { Future<void> refresh() async {
await _load(); ref.invalidateSelf();
} }
} }
final transferPairsProvider = Provider<Map<String, Transaction>>((ref) { final transferPairsProvider = Provider<Map<String, Transaction>>((ref) {
final txs = ref.watch(transactionsProvider).valueOrNull ?? []; final txs = ref.watch(transactionsProvider).value ?? [];
final transfers = txs.where((t) => t.category == 'Transfer').toList(); final transfers = txs.where((t) => t.category == 'Transfer').toList();
final Map<String, Transaction> pairs = {}; final Map<String, Transaction> pairs = {};
@@ -131,23 +129,46 @@ final transferPairsProvider = Provider<Map<String, Transaction>>((ref) {
return pairs; return pairs;
}); });
final searchQueryProvider = StateProvider<String>((ref) => ''); final searchQueryProvider = NotifierProvider<_SearchQueryNotifier, String>(
_SearchQueryNotifier.new,
);
class _SearchQueryNotifier extends Notifier<String> {
@override
String build() => '';
void set(String v) => state = v;
}
enum TransactionFilter { all, income, expense, transfer } enum TransactionFilter { all, income, expense, transfer }
enum TimeFilter { allTime, lastMonth } enum TimeFilter { allTime, lastMonth }
final transactionFilterProvider = StateProvider<TransactionFilter>( final transactionFilterProvider = NotifierProvider<_TransactionFilterNotifier, TransactionFilter>(
(ref) => TransactionFilter.all, _TransactionFilterNotifier.new,
); );
final timeFilterProvider = StateProvider<TimeFilter>( class _TransactionFilterNotifier extends Notifier<TransactionFilter> {
(ref) => TimeFilter.lastMonth, @override
TransactionFilter build() => TransactionFilter.all;
void set(TransactionFilter v) => state = v;
}
final timeFilterProvider = NotifierProvider<_TimeFilterNotifier, TimeFilter>(
_TimeFilterNotifier.new,
); );
class _TimeFilterNotifier extends Notifier<TimeFilter> {
@override
TimeFilter build() => TimeFilter.lastMonth;
void set(TimeFilter v) => state = v;
}
final accountFilteredTransactionsProvider = Provider<List<Transaction>>((ref) { final accountFilteredTransactionsProvider = Provider<List<Transaction>>((ref) {
final txsAsync = ref.watch(transactionsProvider); final txsAsync = ref.watch(transactionsProvider);
final txs = txsAsync.valueOrNull ?? []; final txs = txsAsync.value ?? [];
final activeAccount = ref.watch(activeAccountProvider); final activeAccount = ref.watch(activeAccountProvider);
if (activeAccount == null) { if (activeAccount == null) {
@@ -158,7 +179,7 @@ final accountFilteredTransactionsProvider = Provider<List<Transaction>>((ref) {
}); });
final globalTotalBalanceProvider = Provider<double>((ref) { final globalTotalBalanceProvider = Provider<double>((ref) {
final txs = ref.watch(transactionsProvider).valueOrNull ?? []; final txs = ref.watch(transactionsProvider).value ?? [];
final exchangeService = ref.watch(exchangeRateServiceProvider); final exchangeService = ref.watch(exchangeRateServiceProvider);
final targetCurrency = ref.watch(currencyProvider).code; final targetCurrency = ref.watch(currencyProvider).code;
@@ -181,7 +202,7 @@ final totalBalanceProvider = Provider<double>((ref) {
String targetCurrency = globalCurrency; String targetCurrency = globalCurrency;
if (index > 0) { if (index > 0) {
final accounts = accountsAsync.valueOrNull ?? []; final accounts = accountsAsync.value ?? [];
if (index <= accounts.length) { if (index <= accounts.length) {
targetCurrency = accounts[index - 1].currency; targetCurrency = accounts[index - 1].currency;
} }
@@ -211,7 +232,7 @@ final totalIncomeProvider = Provider<double>((ref) {
String targetCurrency = globalCurrency; String targetCurrency = globalCurrency;
if (index > 0) { if (index > 0) {
final accounts = accountsAsync.valueOrNull ?? []; final accounts = accountsAsync.value ?? [];
if (index <= accounts.length) { if (index <= accounts.length) {
targetCurrency = accounts[index - 1].currency; targetCurrency = accounts[index - 1].currency;
} }
@@ -237,7 +258,7 @@ final totalExpenseProvider = Provider<double>((ref) {
String targetCurrency = globalCurrency; String targetCurrency = globalCurrency;
if (index > 0) { if (index > 0) {
final accounts = accountsAsync.valueOrNull ?? []; final accounts = accountsAsync.value ?? [];
if (index <= accounts.length) { if (index <= accounts.length) {
targetCurrency = accounts[index - 1].currency; targetCurrency = accounts[index - 1].currency;
} }
@@ -267,7 +288,7 @@ final currentMonthExpenseProvider = Provider<double>((ref) {
String targetCurrency = globalCurrency; String targetCurrency = globalCurrency;
if (index > 0) { if (index > 0) {
final accounts = accountsAsync.valueOrNull ?? []; final accounts = accountsAsync.value ?? [];
if (index <= accounts.length) { if (index <= accounts.length) {
targetCurrency = accounts[index - 1].currency; targetCurrency = accounts[index - 1].currency;
} }
@@ -349,7 +370,16 @@ final accountsProvider = StreamProvider<List<Account>>((ref) async* {
} }
}); });
final activeAccountIndexProvider = StateProvider<int>((ref) => 0); final activeAccountIndexProvider = NotifierProvider<_ActiveAccountIndexNotifier, int>(
_ActiveAccountIndexNotifier.new,
);
class _ActiveAccountIndexNotifier extends Notifier<int> {
@override
int build() => 0;
void set(int v) => state = v;
}
final activeAccountProvider = Provider<Account?>((ref) { final activeAccountProvider = Provider<Account?>((ref) {
final index = ref.watch(activeAccountIndexProvider); final index = ref.watch(activeAccountIndexProvider);
@@ -387,52 +417,37 @@ class CardColors {
} }
final cardColorsProvider = final cardColorsProvider =
StateNotifierProvider<CardColorsNotifier, CardColors>((ref) { NotifierProvider<CardColorsNotifier, CardColors>(
final notifier = CardColorsNotifier(); CardColorsNotifier.new,
notifier.setupThemeListener(ref); );
return notifier;
});
final accountCardColorsProvider = final accountCardColorsProvider =
StateNotifierProvider.family<CardColorsNotifier, CardColors, int>(( NotifierProvider.family<AccountCardColorsNotifier, CardColors, int>(
ref, (accountId) => AccountCardColorsNotifier(accountId),
accountId, );
) {
final notifier = CardColorsNotifier(accountId: accountId);
notifier.setupThemeListener(ref);
return notifier;
});
class CardColorsNotifier extends StateNotifier<CardColors> {
final int? accountId;
CardColorsNotifier({this.accountId})
: super(
const CardColors(
CardColorService.defaultPrimary,
CardColorService.defaultSecondary,
CardColorService.defaultGradientLight,
CardColorService.defaultGradientDark,
),
) {
_load();
}
class CardColorsNotifier extends Notifier<CardColors> {
int _loadGeneration = 0; int _loadGeneration = 0;
void setupThemeListener(Ref ref) { @override
CardColors build() {
ref.listen<ThemeMode>(themeProvider, (previous, next) { ref.listen<ThemeMode>(themeProvider, (previous, next) {
if (previous != null) { if (previous != null) {
_onThemeChanged(previous, next); _onThemeChanged(previous, next);
} }
}); });
_load();
return const CardColors(
CardColorService.defaultPrimary,
CardColorService.defaultSecondary,
CardColorService.defaultGradientLight,
CardColorService.defaultGradientDark,
);
} }
Future<void> _load() async { Future<void> _load() async {
final currentGeneration = ++_loadGeneration; final currentGeneration = ++_loadGeneration;
final (c1, c2, lightG, darkG) = await CardColorService.load( final (c1, c2, lightG, darkG) = await CardColorService.load();
accountId: accountId,
);
if (currentGeneration != _loadGeneration) return; if (currentGeneration != _loadGeneration) return;
state = CardColors(c1, c2, lightG, darkG); state = CardColors(c1, c2, lightG, darkG);
} }
@@ -450,7 +465,6 @@ class CardColorsNotifier extends StateNotifier<CardColors> {
secondary, secondary,
lightGradient, lightGradient,
darkGradient, darkGradient,
accountId: accountId,
); );
} }
@@ -473,7 +487,127 @@ class CardColorsNotifier extends StateNotifier<CardColors> {
secondary, secondary,
CardColorService.defaultGradientLight, CardColorService.defaultGradientLight,
CardColorService.defaultGradientDark, CardColorService.defaultGradientDark,
accountId: accountId, );
}
void _onThemeChanged(ThemeMode previous, ThemeMode next) {
final previousBrightness = _resolve(previous);
final nextBrightness = _resolve(next);
if (previousBrightness == nextBrightness) return;
final oldDefaults = _defaultsFor(previousBrightness);
final newDefaults = _defaultsFor(nextBrightness);
final isUsingOldDefaults =
state.primary == oldDefaults.primary &&
state.secondary == oldDefaults.secondary &&
state.gradientTypeForBrightness(previousBrightness) ==
oldDefaults.gradient;
if (isUsingOldDefaults) {
_loadGeneration++;
state = CardColors(
newDefaults.primary,
newDefaults.secondary,
state.lightGradientType,
state.darkGradientType,
);
}
}
Brightness _resolve(ThemeMode mode) {
if (mode == ThemeMode.system) {
return WidgetsBinding.instance.platformDispatcher.platformBrightness;
}
return mode == ThemeMode.dark ? Brightness.dark : Brightness.light;
}
({Color primary, Color secondary, GradientType gradient}) _defaultsFor(
Brightness brightness,
) {
return brightness == Brightness.dark
? (
primary: CardColorService.defaultPrimary,
secondary: CardColorService.defaultSecondary,
gradient: CardColorService.defaultGradientDark,
)
: (
primary: CardColorService.defaultPrimaryLight,
secondary: CardColorService.defaultSecondaryLight,
gradient: CardColorService.defaultGradientLight,
);
}
}
class AccountCardColorsNotifier extends Notifier<CardColors> {
AccountCardColorsNotifier(this._accountId);
final int _accountId;
int _loadGeneration = 0;
@override
CardColors build() {
ref.listen<ThemeMode>(themeProvider, (previous, next) {
if (previous != null) {
_onThemeChanged(previous, next);
}
});
_load(_accountId);
return const CardColors(
CardColorService.defaultPrimary,
CardColorService.defaultSecondary,
CardColorService.defaultGradientLight,
CardColorService.defaultGradientDark,
);
}
Future<void> _load(int accountId) async {
final currentGeneration = ++_loadGeneration;
final (c1, c2, lightG, darkG) = await CardColorService.load(
accountId: accountId,
);
if (currentGeneration != _loadGeneration) return;
state = CardColors(c1, c2, lightG, darkG);
}
Future<void> save(
Color primary,
Color secondary,
GradientType lightGradient,
GradientType darkGradient,
) async {
_loadGeneration++;
state = CardColors(primary, secondary, lightGradient, darkGradient);
await CardColorService.save(
primary,
secondary,
lightGradient,
darkGradient,
accountId: _accountId,
);
}
Future<void> reset(bool isDark) async {
final primary = isDark
? CardColorService.defaultPrimary
: CardColorService.defaultPrimaryLight;
final secondary = isDark
? CardColorService.defaultSecondary
: CardColorService.defaultSecondaryLight;
_loadGeneration++;
state = CardColors(
primary,
secondary,
CardColorService.defaultGradientLight,
CardColorService.defaultGradientDark,
);
await CardColorService.save(
primary,
secondary,
CardColorService.defaultGradientLight,
CardColorService.defaultGradientDark,
accountId: _accountId,
); );
} }
+1 -1
View File
@@ -280,7 +280,7 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
final activeIndex = ref.watch(activeAccountIndexProvider); final activeIndex = ref.watch(activeAccountIndexProvider);
final accountsAsync = ref.watch(accountsProvider); final accountsAsync = ref.watch(accountsProvider);
final accountCount = accountsAsync.valueOrNull?.length ?? 0; final accountCount = accountsAsync.value?.length ?? 0;
final isOnAddAccountPage = final isOnAddAccountPage =
accountCount < 5 && activeIndex == accountCount + 1; accountCount < 5 && activeIndex == accountCount + 1;
@@ -377,7 +377,7 @@ class _AccountEditorOverlayState extends State<AccountEditorOverlay> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (!dash.isAddingAccount && if (!dash.isAddingAccount &&
(ref.watch(accountsProvider).valueOrNull?.length ?? 0) > (ref.watch(accountsProvider).value?.length ?? 0) >
1) ...[ 1) ...[
GestureDetector( GestureDetector(
onTap: () => setState(() => _showDeleteDialog = true), onTap: () => setState(() => _showDeleteDialog = true),
@@ -588,7 +588,7 @@ class AccountColorPanel extends StatelessWidget {
final accounts = final accounts =
ProviderScope.containerOf( ProviderScope.containerOf(
dashboardContext, dashboardContext,
).read(accountsProvider).valueOrNull ?? ).read(accountsProvider).value ??
[]; [];
if (isDuplicateName( if (isDuplicateName(
@@ -56,7 +56,7 @@ class AccountDeleteDialog extends ConsumerWidget {
onConfirm(); onConfirm();
final txs = ref.read(transactionsProvider).valueOrNull ?? []; final txs = ref.read(transactionsProvider).value ?? [];
final accountTxs = txs final accountTxs = txs
.where((t) => t.accountId == accountId) .where((t) => t.accountId == accountId)
.toList(); .toList();
@@ -145,15 +145,12 @@ class BalanceCardState extends ConsumerState<BalanceCard>
.toList(); .toList();
final textColorMode = ref.watch(cardTextColorProvider); final textColorMode = ref.watch(cardTextColorProvider);
final Color onCard; final Color onCard = switch (textColorMode) {
switch (textColorMode) { CardTextColorMode.white => Colors.white,
case CardTextColorMode.white: CardTextColorMode.black => Colors.black,
onCard = Colors.white; CardTextColorMode.adaptive => primary.computeLuminance() > 0.3 ? Colors.black : Colors.white,
case CardTextColorMode.black: _ => Colors.white,
onCard = Colors.black; };
case CardTextColorMode.adaptive:
onCard = primary.computeLuminance() > 0.3 ? Colors.black : Colors.white;
}
return GestureDetector( return GestureDetector(
onLongPress: () { onLongPress: () {
@@ -75,7 +75,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
Clip.none, Clip.none,
itemCount: totalPages, itemCount: totalPages,
onPageChanged: (index) { onPageChanged: (index) {
ref.read(activeAccountIndexProvider.notifier).state = index; ref.read(activeAccountIndexProvider.notifier).set(index);
if (ref.read(hapticEnabledProvider)) { if (ref.read(hapticEnabledProvider)) {
HapticService.light(); HapticService.light();
} }
@@ -103,7 +103,7 @@ class _BalanceCardCarouselState extends ConsumerState<BalanceCardCarousel> {
); );
final txs = final txs =
ref.watch(transactionsProvider).valueOrNull ?? []; ref.watch(transactionsProvider).value ?? [];
final accountTxs = txs final accountTxs = txs
.where((t) => t.accountId == account.id) .where((t) => t.accountId == account.id)
.toList(); .toList();
@@ -23,15 +23,15 @@ class FilterChips extends ConsumerWidget {
_FilterChip( _FilterChip(
label: strings.filterAllTime, label: strings.filterAllTime,
isSelected: timeFilter == TimeFilter.allTime, isSelected: timeFilter == TimeFilter.allTime,
onTap: () => ref.read(timeFilterProvider.notifier).state = onTap: () => ref.read(timeFilterProvider.notifier).set(
TimeFilter.allTime, TimeFilter.allTime),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
_FilterChip( _FilterChip(
label: strings.filterMonth, label: strings.filterMonth,
isSelected: timeFilter == TimeFilter.lastMonth, isSelected: timeFilter == TimeFilter.lastMonth,
onTap: () => ref.read(timeFilterProvider.notifier).state = onTap: () => ref.read(timeFilterProvider.notifier).set(
TimeFilter.lastMonth, TimeFilter.lastMonth),
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
@@ -46,32 +46,32 @@ class FilterChips extends ConsumerWidget {
_FilterChip( _FilterChip(
label: strings.filterAll, label: strings.filterAll,
isSelected: typeFilter == TransactionFilter.all, isSelected: typeFilter == TransactionFilter.all,
onTap: () => ref.read(transactionFilterProvider.notifier).state = onTap: () => ref.read(transactionFilterProvider.notifier).set(
TransactionFilter.all, TransactionFilter.all),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
_FilterChip( _FilterChip(
label: strings.filterIncome, label: strings.filterIncome,
isSelected: typeFilter == TransactionFilter.income, isSelected: typeFilter == TransactionFilter.income,
color: AppColors.income, color: AppColors.income,
onTap: () => ref.read(transactionFilterProvider.notifier).state = onTap: () => ref.read(transactionFilterProvider.notifier).set(
TransactionFilter.income, TransactionFilter.income),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
_FilterChip( _FilterChip(
label: strings.filterExpense, label: strings.filterExpense,
isSelected: typeFilter == TransactionFilter.expense, isSelected: typeFilter == TransactionFilter.expense,
color: AppColors.expense, color: AppColors.expense,
onTap: () => ref.read(transactionFilterProvider.notifier).state = onTap: () => ref.read(transactionFilterProvider.notifier).set(
TransactionFilter.expense, TransactionFilter.expense),
), ),
const SizedBox(width: 6), const SizedBox(width: 6),
_FilterChip( _FilterChip(
label: strings.filterTransfer, label: strings.filterTransfer,
isSelected: typeFilter == TransactionFilter.transfer, isSelected: typeFilter == TransactionFilter.transfer,
color: Colors.blueAccent, color: Colors.blueAccent,
onTap: () => ref.read(transactionFilterProvider.notifier).state = onTap: () => ref.read(transactionFilterProvider.notifier).set(
TransactionFilter.transfer, TransactionFilter.transfer),
), ),
], ],
), ),
@@ -37,7 +37,7 @@ class SearchBar extends StatelessWidget {
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6), color: Theme.of(context).colorScheme.onSurface.withOpacity(0.6),
onPressed: () { onPressed: () {
controller.clear(); controller.clear();
ref.read(searchQueryProvider.notifier).state = ''; ref.read(searchQueryProvider.notifier).set('');
}, },
) )
: null, : null,
@@ -63,7 +63,7 @@ class SearchBar extends StatelessWidget {
vertical: 12, vertical: 12,
), ),
), ),
onChanged: (v) => ref.read(searchQueryProvider.notifier).state = v, onChanged: (v) => ref.read(searchQueryProvider.notifier).set(v),
); );
} }
} }
@@ -56,7 +56,7 @@ class TransactionTile extends ConsumerWidget {
: 0.0; : 0.0;
final displaySymbol = currencyMap[displayCurrency]?.symbol ?? ''; final displaySymbol = currencyMap[displayCurrency]?.symbol ?? '';
final accounts = ref.watch(accountsProvider).valueOrNull ?? []; final accounts = ref.watch(accountsProvider).value ?? [];
final txAccount = accounts.firstWhereOrNull( final txAccount = accounts.firstWhereOrNull(
(a) => a.id == transaction.accountId, (a) => a.id == transaction.accountId,
); );
+61 -67
View File
@@ -11,18 +11,20 @@ import '../../shared/utils/currency_utils.dart';
import '../../shared/providers/amount_format_provider.dart'; import '../../shared/providers/amount_format_provider.dart';
import '../dashboard/provider.dart'; import '../dashboard/provider.dart';
final budgetProvider = StateNotifierProvider<BudgetNotifier, double?>((ref) { final budgetProvider = NotifierProvider<BudgetNotifier, double?>(
BudgetNotifier.new,
);
class BudgetNotifier extends Notifier<double?> {
@override
double? build() {
final storage = ref.watch(storageServiceProvider); final storage = ref.watch(storageServiceProvider);
return BudgetNotifier(storage.loadBudget(), storage); return storage.loadBudget();
}); }
class BudgetNotifier extends StateNotifier<double?> {
final dynamic _storage;
BudgetNotifier(super.initialBudget, this._storage);
Future<void> setBudget(double? budget) async { Future<void> setBudget(double? budget) async {
await _storage.saveBudget(budget); final storage = ref.read(storageServiceProvider);
await storage.saveBudget(budget);
state = budget; state = budget;
} }
@@ -50,70 +52,60 @@ const Map<String, CurrencyInfo> currencyMap = {
'RUB': CurrencyInfo('', 'RUB'), 'RUB': CurrencyInfo('', 'RUB'),
}; };
class CurrencyNotifier extends StateNotifier<CurrencyInfo> { class CurrencyNotifier extends Notifier<CurrencyInfo> {
final SharedPreferences _prefs; @override
CurrencyInfo build() {
CurrencyNotifier(this._prefs) : super(currencyMap['USD']!) { final prefs = ref.watch(sharedPreferencesProvider);
_load(); final code = prefs.getString('currency_code') ?? 'USD';
} return currencyMap[code] ?? currencyMap['USD']!;
void _load() {
final code = _prefs.getString('currency_code') ?? 'USD';
state = currencyMap[code] ?? currencyMap['USD']!;
} }
Future<void> setCurrency(String code) async { Future<void> setCurrency(String code) async {
final prefs = ref.read(sharedPreferencesProvider);
state = currencyMap[code] ?? currencyMap['USD']!; state = currencyMap[code] ?? currencyMap['USD']!;
await _prefs.setString('currency_code', code); await prefs.setString('currency_code', code);
} }
} }
final currencyProvider = StateNotifierProvider<CurrencyNotifier, CurrencyInfo>(( final currencyProvider = NotifierProvider<CurrencyNotifier, CurrencyInfo>(
ref, CurrencyNotifier.new,
) { );
class ThemeModeNotifier extends Notifier<ThemeMode> {
@override
ThemeMode build() {
final prefs = ref.watch(sharedPreferencesProvider); final prefs = ref.watch(sharedPreferencesProvider);
return CurrencyNotifier(prefs); final saved = prefs.getString('theme_mode');
});
class ThemeModeNotifier extends StateNotifier<ThemeMode> {
final SharedPreferences _prefs;
ThemeModeNotifier(this._prefs) : super(ThemeMode.system) {
_load();
}
void _load() {
final saved = _prefs.getString('theme_mode');
if (saved == 'dark') { if (saved == 'dark') {
state = ThemeMode.dark; return ThemeMode.dark;
} else if (saved == 'light') { } else if (saved == 'light') {
state = ThemeMode.light; return ThemeMode.light;
} else { } else {
state = ThemeMode.system; return ThemeMode.system;
} }
} }
Future<void> setThemeMode(ThemeMode mode) async { Future<void> setThemeMode(ThemeMode mode) async {
final prefs = ref.read(sharedPreferencesProvider);
state = mode; state = mode;
await _prefs.setString('theme_mode', mode.name); await prefs.setString('theme_mode', mode.name);
} }
} }
final themeProvider = StateNotifierProvider<ThemeModeNotifier, ThemeMode>(( final themeProvider = NotifierProvider<ThemeModeNotifier, ThemeMode>(
ref, ThemeModeNotifier.new,
) { );
final prefs = ref.watch(sharedPreferencesProvider);
return ThemeModeNotifier(prefs);
});
enum CardTextColorMode { white, adaptive, black } enum CardTextColorMode { white, adaptive, black }
class CardTextColorNotifier extends StateNotifier<CardTextColorMode> { class CardTextColorNotifier extends Notifier<CardTextColorMode> {
static const _key = 'card_text_color'; static const _key = 'card_text_color';
final SharedPreferences _prefs;
CardTextColorNotifier(this._prefs) @override
: super(_fromString(_prefs.getString(_key))); CardTextColorMode build() {
final prefs = ref.watch(sharedPreferencesProvider);
return _fromString(prefs.getString(_key));
}
static CardTextColorMode _fromString(String? value) { static CardTextColorMode _fromString(String? value) {
return CardTextColorMode.values.firstWhere( return CardTextColorMode.values.firstWhere(
@@ -123,16 +115,16 @@ class CardTextColorNotifier extends StateNotifier<CardTextColorMode> {
} }
void set(CardTextColorMode mode) { void set(CardTextColorMode mode) {
final prefs = ref.read(sharedPreferencesProvider);
state = mode; state = mode;
_prefs.setString(_key, mode.name); prefs.setString(_key, mode.name);
} }
} }
final cardTextColorProvider = final cardTextColorProvider =
StateNotifierProvider<CardTextColorNotifier, CardTextColorMode>((ref) { NotifierProvider<CardTextColorNotifier, CardTextColorMode>(
final prefs = ref.watch(sharedPreferencesProvider); CardTextColorNotifier.new,
return CardTextColorNotifier(prefs); );
});
final exchangeRateServiceProvider = Provider<ExchangeRateService>((ref) { final exchangeRateServiceProvider = Provider<ExchangeRateService>((ref) {
final prefs = ref.watch(sharedPreferencesProvider); final prefs = ref.watch(sharedPreferencesProvider);
@@ -143,15 +135,15 @@ final ratesInitProvider = FutureProvider<void>((ref) async {
await ref.read(exchangeRateServiceProvider).fetchRates(); await ref.read(exchangeRateServiceProvider).fetchRates();
}); });
final hapticEnabledProvider = StateNotifierProvider<HapticNotifier, bool>(( final hapticEnabledProvider = NotifierProvider<HapticNotifier, bool>(
ref, HapticNotifier.new,
) { );
return HapticNotifier();
});
class HapticNotifier extends StateNotifier<bool> { class HapticNotifier extends Notifier<bool> {
HapticNotifier() : super(true) { @override
bool build() {
_load(); _load();
return true;
} }
Future<void> _load() async { Future<void> _load() async {
@@ -166,13 +158,15 @@ class HapticNotifier extends StateNotifier<bool> {
} }
final showCurrencyConversionsProvider = final showCurrencyConversionsProvider =
StateNotifierProvider<ShowCurrencyConversionsNotifier, bool>((ref) { NotifierProvider<ShowCurrencyConversionsNotifier, bool>(
return ShowCurrencyConversionsNotifier(); ShowCurrencyConversionsNotifier.new,
}); );
class ShowCurrencyConversionsNotifier extends StateNotifier<bool> { class ShowCurrencyConversionsNotifier extends Notifier<bool> {
ShowCurrencyConversionsNotifier() : super(true) { @override
bool build() {
_load(); _load();
return true;
} }
Future<void> _load() async { Future<void> _load() async {
@@ -198,7 +192,7 @@ class ExportService {
Future<String> exportToCSV() async { Future<String> exportToCSV() async {
final transactionsAsync = _ref.read(transactionsProvider); final transactionsAsync = _ref.read(transactionsProvider);
final transactions = transactionsAsync.valueOrNull ?? []; final transactions = transactionsAsync.value ?? [];
final fmt = _ref.read(amountFormatProvider); final fmt = _ref.read(amountFormatProvider);
final buffer = StringBuffer(); final buffer = StringBuffer();
@@ -2,9 +2,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import '../../core/constants.dart'; import '../../core/constants.dart';
class AmountFormatNotifier extends StateNotifier<AmountFormat> { class AmountFormatNotifier extends Notifier<AmountFormat> {
AmountFormatNotifier() : super(AmountFormat.commasDot) { @override
AmountFormat build() {
_load(); _load();
return AmountFormat.commasDot;
} }
void _load() async { void _load() async {
@@ -20,6 +22,6 @@ class AmountFormatNotifier extends StateNotifier<AmountFormat> {
} }
} }
final amountFormatProvider = StateNotifierProvider<AmountFormatNotifier, AmountFormat>( final amountFormatProvider = NotifierProvider<AmountFormatNotifier, AmountFormat>(
(ref) => AmountFormatNotifier(), AmountFormatNotifier.new,
); );
@@ -6,10 +6,6 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) { void fl_register_plugins(FlPluginRegistry* registry) {
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);
} }
+1 -1
View File
@@ -3,10 +3,10 @@
# #
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
sqlite3_flutter_libs
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)
@@ -7,10 +7,8 @@ import Foundation
import local_auth_darwin import local_auth_darwin
import shared_preferences_foundation import shared_preferences_foundation
import sqlite3_flutter_libs
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin")) LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin"))
} }
+196 -92
View File
@@ -5,18 +5,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d" sha256: a49d6cf99e8d8e7a8e93668d09ced0bbdb954d0b4fccc2f5f9241c6b87fad95c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "93.0.0" version: "99.0.0"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b sha256: "663efa951fb8a45e06f491223a604c93820598f20e6a99c25617a1576065e8b7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.1" version: "12.1.0"
ansicolor: ansicolor:
dependency: transitive dependency: transitive
description: description:
@@ -45,10 +45,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: async name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.13.0" version: "2.13.1"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@@ -61,10 +61,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: aadd943f4f8cc946882c954c187e6115a84c98c81ad1d9c6cbf0895a8c85da9c sha256: a156715e7cd728130c592f30552575908aae5b100005fbc1f0fb16b3c03a3d10
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.5" version: "4.0.6"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
@@ -85,10 +85,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: "521daf8d189deb79ba474e43a696b41c49fb3987818dbacf3308f1e03673a75e" sha256: "1523ce62448ebac2c15a8ba5fbad8acac169788658a7dd2a1c2d9c2a9318b9a6"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.13.1" version: "2.15.0"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@@ -101,10 +101,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: built_value name: built_value
sha256: "6ae8a6435a8c6520c7077b107e77f1fb4ba7009633259a4d49a8afd8e7efc5e9" sha256: "34e4067d30ce212937df995f03b69992eea683539ceeac7f679a1f1eba055b56"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.12.4" version: "8.12.6"
characters: characters:
dependency: transitive dependency: transitive
description: description:
@@ -129,6 +129,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.4" version: "2.0.4"
cli_config:
dependency: transitive
description:
name: cli_config
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
url: "https://pub.dev"
source: hosted
version: "0.2.0"
cli_util: cli_util:
dependency: transitive dependency: transitive
description: description:
@@ -149,18 +157,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: code_assets name: code_assets
sha256: "83ccdaa064c980b5596c35dd64a8d3ecc68620174ab9b90b6343b753aa721687" sha256: bf394f466ba9205f1812a0433b392d6af280f155f56651eda7c18cc32ed493b8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0" version: "1.2.1"
code_builder:
dependency: transitive
description:
name: code_builder
sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d"
url: "https://pub.dev"
source: hosted
version: "4.11.1"
collection: collection:
dependency: transitive dependency: transitive
description: description:
@@ -177,6 +177,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
coverage:
dependency: transitive
description:
name: coverage
sha256: "956a3de0725ca232ad353565a8290d3357592bf4250f6f298a185e2d949c5d3d"
url: "https://pub.dev"
source: hosted
version: "1.15.1"
crypto: crypto:
dependency: transitive dependency: transitive
description: description:
@@ -197,34 +205,34 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: cupertino_icons name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.8" version: "1.0.9"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "29f7ecc274a86d32920b1d9cfc7502fa87220da41ec60b55f329559d5732e2b2" sha256: a4c1ccfee44c7e75ed80484071a5c142a385345e658fd8bd7c4b5c97e7198f98
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.7" version: "3.1.8"
drift: drift:
dependency: "direct main" dependency: "direct main"
description: description:
name: drift name: drift
sha256: "055c249d1f91be5a47fe447f88afc24c4ca6f4cd6c5ed66767b4797d48acc2e5" sha256: "6cc0b623c0e83f7080524d8396e9301b1d78b9c66a4fdceeb0f798211303254c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.32.1" version: "2.34.0"
drift_dev: drift_dev:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: drift_dev name: drift_dev
sha256: "88a9de3af8571518148a6d8a513b57779fd1e60a026d3ab8a481a878fba01d91" sha256: "9cfff1576b49725da0d32c040651a41ae195e8c4af8d8da301593e41d7abc2f7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.32.1" version: "2.34.0"
equatable: equatable:
dependency: transitive dependency: transitive
description: description:
@@ -269,10 +277,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: fl_chart name: fl_chart
sha256: "74959b99b92b9eebeed1a4049426fd67c4abc3c5a0f4d12e2877097d6a11ae08" sha256: b938f77d042cbcd822936a7a359a7235bad8bd72070de1f827efc2cc297ac888
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.69.2" version: "1.2.0"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@@ -306,26 +314,26 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: flutter_native_splash name: flutter_native_splash
sha256: "4fb9f4113350d3a80841ce05ebf1976a36de622af7d19aca0ca9a9911c7ff002" sha256: "9db4b80b044e9af17cc4b1272137fc7ace0054d879ef8210a76adc34aaf4cdff"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.7" version: "2.4.8"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:
name: flutter_plugin_android_lifecycle name: flutter_plugin_android_lifecycle
sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1 sha256: "3854fe5e3bff0b113c658f260b90c95dea17c92db0f2addeac2e343dd9969785"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.33" version: "2.0.35"
flutter_riverpod: flutter_riverpod:
dependency: "direct main" dependency: "direct main"
description: description:
name: flutter_riverpod name: flutter_riverpod
sha256: "9532ee6db4a943a1ed8383072a2e3eeda041db5657cdf6d2acecf3c21ecbe7e1" sha256: "9255e1e3ad6e38906a1b4f8287678f95f378744c5b46b1985588543f3f19046e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.1" version: "3.3.2"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@@ -336,6 +344,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.dev"
source: hosted
version: "4.0.0"
glob: glob:
dependency: transitive dependency: transitive
description: description:
@@ -348,18 +364,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: go_router name: go_router
sha256: f02fd7d2a4dc512fec615529824fdd217fecb3a3d3de68360293a551f21634b3 sha256: "5922b2861e2235a3504896f0d6fa07d84141b480cf52eecd2f42cd25585a9e8a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.8.1" version: "17.3.0"
google_fonts: google_fonts:
dependency: "direct main" dependency: "direct main"
description: description:
name: google_fonts name: google_fonts
sha256: ba03d03bcaa2f6cb7bd920e3b5027181db75ab524f8891c8bc3aa603885b8055 sha256: "4e9391085e524954a51e3625b7c9c7e9851dc3f376603208bb45c24b9a66255d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.3.3" version: "8.1.0"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
@@ -372,10 +388,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: hooks name: hooks
sha256: e79ed1e8e1929bc6ecb6ec85f0cb519c887aa5b423705ded0d0f2d9226def388 sha256: "9a62a50b50b769a737bc0a8ff381f333529df3ab746b2f6b02e83760231455ba"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.2" version: "2.0.2"
html: html:
dependency: transitive dependency: transitive
description: description:
@@ -412,18 +428,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: image name: image
sha256: f9881ff4998044947ec38d098bc7c8316ae1186fa786eddffdb867b9bc94dfce sha256: "6300175e00616bbc832e2fc91bfa4d776af5402c81c7151bee6905bb08473c52"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.8.0" version: "4.9.1"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
name: intl name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.19.0" version: "0.20.2"
io: io:
dependency: transitive dependency: transitive
description: description:
@@ -432,14 +448,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.5" version: "1.0.5"
jni:
dependency: transitive
description:
name: jni
sha256: c2230682d5bc2362c1c9e8d3c7f406d9cbba23ab3f2e203a025dd47e0fb2e68f
url: "https://pub.dev"
source: hosted
version: "1.0.0"
jni_flutter:
dependency: transitive
description:
name: jni_flutter
sha256: "8b59e590786050b1cd866677dddaf76b1ade5e7bc751abe04b86e84d379d3ba6"
url: "https://pub.dev"
source: hosted
version: "1.0.1"
json_annotation: json_annotation:
dependency: transitive dependency: transitive
description: description:
name: json_annotation name: json_annotation
sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 sha256: "2a743920d81b7910627f68ee2c9ac1fc0bfee32b9fc3403587d7c6791ca12f80"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.11.0" version: "4.12.0"
leak_tracker: leak_tracker:
dependency: transitive dependency: transitive
description: description:
@@ -476,26 +508,26 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: local_auth name: local_auth
sha256: "434d854cf478f17f12ab29a76a02b3067f86a63a6d6c4eb8fbfdcfe4879c1b7b" sha256: ae6f382f638108c6becd134318d7c3f0a93875383a54010f61d7c97ac05d5137
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "3.0.1"
local_auth_android: local_auth_android:
dependency: transitive dependency: transitive
description: description:
name: local_auth_android name: local_auth_android
sha256: a0bdfcc0607050a26ef5b31d6b4b254581c3d3ce3c1816ab4d4f4a9173e84467 sha256: fdb936d59ab945c7af297defd67bd1ed87b11b6db1bc16d01e94677a8f1c38ec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.56" version: "2.0.9"
local_auth_darwin: local_auth_darwin:
dependency: transitive dependency: transitive
description: description:
name: local_auth_darwin name: local_auth_darwin
sha256: "699873970067a40ef2f2c09b4c72eb1cfef64224ef041b3df9fdc5c4c1f91f49" sha256: a8c3d4e17454111f7fd31ff72a31222359f6059f7fe956c2dcfe0f88f49826d4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.6.1" version: "2.0.3"
local_auth_platform_interface: local_auth_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -508,10 +540,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: local_auth_windows name: local_auth_windows
sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 sha256: be12c5b8ba5e64896983123655c5f67d2484ecfcc95e367952ad6e3bff94cb16
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.11" version: "2.0.1"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@@ -540,10 +572,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" sha256: "1741988757a65eb6b36abe716829688cf01910bbf91c34354ff7ec1c3de2b349"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.17.0" version: "1.18.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@@ -556,18 +588,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: native_toolchain_c name: native_toolchain_c
sha256: "6ba77bb18063eebe9de401f5e6437e95e1438af0a87a3a39084fbd37c90df572" sha256: f59351d28f49520cd3a74eb1f41c5f19ae15e53c65a3231d14af672e46510a96
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.17.6" version: "0.19.1"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
objective_c: objective_c:
dependency: transitive dependency: transitive
description: description:
name: objective_c name: objective_c
sha256: "100a1c87616ab6ed41ec263b083c0ef3261ee6cd1dc3b0f35f8ddfa4f996fe52" sha256: "6cb691c686fa2838c6deb34980d426145c2a5d537491cb83d463c33cdbc726ed"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "9.3.0" version: "9.4.1"
package_config: package_config:
dependency: transitive dependency: transitive
description: description:
@@ -596,10 +636,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: path_provider_android name: path_provider_android
sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e sha256: "69cbd515a62b94d32a7944f086b2f82b4ac40a1d45bebfc00813a430ab2dabcd"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.22" version: "2.3.1"
path_provider_foundation: path_provider_foundation:
dependency: transitive dependency: transitive
description: description:
@@ -696,22 +736,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.0" version: "4.1.0"
record_use:
dependency: transitive
description:
name: record_use
sha256: "2551bd8eecfe95d14ae75f6021ad0248be5c27f138c2ec12fcb52b500b3ba1ed"
url: "https://pub.dev"
source: hosted
version: "0.6.0"
riverpod: riverpod:
dependency: transitive dependency: transitive
description: description:
name: riverpod name: riverpod
sha256: "59062512288d3056b2321804332a13ffdd1bf16df70dcc8e506e411280a72959" sha256: "17100416c51db7810c71a7bb2c34d1f881faa0074fd452afb0c4db6f8f126c76"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.1" version: "3.3.2"
sensors_plus: sensors_plus:
dependency: "direct main" dependency: "direct main"
description: description:
name: sensors_plus name: sensors_plus
sha256: "89e2bfc3d883743539ce5774a2b93df61effde40ff958ecad78cd66b1a8b8d52" sha256: "56e8cd4260d9ed8e00ecd8da5d9fdc8a1b2ec12345a750dfa51ff83fcf12e3fa"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.1.2" version: "7.0.0"
sensors_plus_platform_interface: sensors_plus_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -724,18 +772,18 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: shared_preferences name: shared_preferences
sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64" sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.4" version: "2.5.5"
shared_preferences_android: shared_preferences_android:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: "8374d6200ab33ac99031a852eba4c8eb2170c4bf20778b3e2c9eccb45384fb41" sha256: "93ae5884a9df5d3bb696825bceb3a17590754548b5d740eba51500afc8d088f5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.21" version: "2.4.26"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:
@@ -756,10 +804,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_platform_interface name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.1" version: "2.4.2"
shared_preferences_web: shared_preferences_web:
dependency: transitive dependency: transitive
description: description:
@@ -784,6 +832,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.2" version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.3"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
@@ -801,10 +865,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_gen name: source_gen
sha256: "732792cfd197d2161a65bb029606a46e0a18ff30ef9e141a7a82172b05ea8ecd" sha256: ec37cc0e6694374cbef59ed79685572c870a54ede6fa30a3e420feb3adffea02
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.2.2" version: "4.2.3"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
url: "https://pub.dev"
source: hosted
version: "0.10.13"
source_span: source_span:
dependency: transitive dependency: transitive
description: description:
@@ -817,26 +897,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: sqlite3 name: sqlite3
sha256: caa693ad15a587a2b4fde093b728131a1827903872171089dedb16f7665d3a91 sha256: "37356bcb56ce0d9404d602c41e4bdb7765e7e9732a3e47adb3d98c556a6abdad"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.2.0" version: "3.3.3"
sqlite3_flutter_libs: sqlite3_flutter_libs:
dependency: "direct main" dependency: "direct main"
description: description:
name: sqlite3_flutter_libs name: sqlite3_flutter_libs
sha256: eeb9e3a45207649076b808f8a5a74d68770d0b7f26ccef6d5f43106eee5375ad sha256: "3ed7553eee7bb368f8950f58ba29f634e06e813c029aff6a0d60862b96de8454"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.42" version: "0.6.0+eol"
sqlparser: sqlparser:
dependency: transitive dependency: transitive
description: description:
name: sqlparser name: sqlparser
sha256: ab2b467425f1d4f3acfa5fd11a08226f7d6c26ff102c06be1807e1dff34e050b sha256: "40bdddb306a727be9ce510bd2d2b9a6c9db6c586d846ef7b22e3990a2b24f02d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.44.3" version: "0.44.5"
stack_trace: stack_trace:
dependency: transitive dependency: transitive
description: description:
@@ -885,14 +965,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.2" version: "1.2.2"
test:
dependency: transitive
description:
name: test
sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20"
url: "https://pub.dev"
source: hosted
version: "1.31.0"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "8161c84903fd860b26bfdefb7963b3f0b68fee7adea0f59ef805ecca346f0c7a" sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.10" version: "0.7.11"
test_core:
dependency: transitive
description:
name: test_core
sha256: "1991d4cfe85d5043241acac92962c3977c8d2f2add1ee73130c7b286417d1d34"
url: "https://pub.dev"
source: hosted
version: "0.6.17"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@@ -929,10 +1025,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: vm_service name: vm_service
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" sha256: "0016aef94fc66495ac78af5859181e3f3bf2026bd8eecc72b9565601e19ab360"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "15.0.2" version: "15.2.0"
watcher: watcher:
dependency: transitive dependency: transitive
description: description:
@@ -965,6 +1061,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.3" version: "3.0.3"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:
@@ -977,10 +1081,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: xml name: xml
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" sha256: "67f0aff7be013d107995e9b75bf4e7f2c3ef2dfdb2c8e68024bba0a7fd5756a4"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.6.1" version: "7.0.1"
yaml: yaml:
dependency: transitive dependency: transitive
description: description:
@@ -990,5 +1094,5 @@ packages:
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.11.1 <4.0.0" dart: ">=3.12.0 <4.0.0"
flutter: ">=3.38.4" flutter: ">=3.44.0"
+8 -8
View File
@@ -10,20 +10,20 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
flutter_riverpod: ^2.6.1 flutter_riverpod: ^3.3.2
go_router: ^14.6.2 go_router: ^17.3.0
shared_preferences: ^2.3.3 shared_preferences: ^2.3.3
fl_chart: ^0.69.0 fl_chart: ^1.2.0
google_fonts: ^6.2.1 google_fonts: ^8.1.0
intl: ^0.19.0 intl: ^0.20.2
uuid: ^4.5.1 uuid: ^4.5.1
path_provider: ^2.1.5 path_provider: ^2.1.5
http: ^1.2.0 http: ^1.2.0
sensors_plus: ^6.1.0 sensors_plus: ^7.0.0
local_auth: ^2.3.0 local_auth: ^3.0.1
flutter_colorpicker: ^1.1.0 flutter_colorpicker: ^1.1.0
drift: ^2.14.1 drift: ^2.14.1
sqlite3_flutter_libs: ^0.5.20 sqlite3_flutter_libs: ^0.6.0+eol
path: ^1.8.3 path: ^1.8.3
flutter_launcher_icons: flutter_launcher_icons:
@@ -7,11 +7,8 @@
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <local_auth_windows/local_auth_plugin.h> #include <local_auth_windows/local_auth_plugin.h>
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) { void RegisterPlugins(flutter::PluginRegistry* registry) {
LocalAuthPluginRegisterWithRegistrar( LocalAuthPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("LocalAuthPlugin")); registry->GetRegistrarForPlugin("LocalAuthPlugin"));
Sqlite3FlutterLibsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("Sqlite3FlutterLibsPlugin"));
} }
+1 -1
View File
@@ -4,10 +4,10 @@
list(APPEND FLUTTER_PLUGIN_LIST list(APPEND FLUTTER_PLUGIN_LIST
local_auth_windows local_auth_windows
sqlite3_flutter_libs
) )
list(APPEND FLUTTER_FFI_PLUGIN_LIST list(APPEND FLUTTER_FFI_PLUGIN_LIST
jni
) )
set(PLUGIN_BUNDLED_LIBRARIES) set(PLUGIN_BUNDLED_LIBRARIES)