Riverpod + go_router с auth-guard, NavigationRail на широком экране и bottom bar на узком. Токены в flutter_secure_storage, на web access живёт в памяти. Интерцептор подставляет токен и делает ровно один refresh на 401. Деньги приходят строками и форматируются через Decimal: парсить их в double значило бы терять копейки ровно там, где бэкенд их бережёт.
29 lines
915 B
Dart
29 lines
915 B
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
const _prefsKey = 'theme_mode';
|
|
|
|
final themeModeProvider = NotifierProvider<ThemeModeController, ThemeMode>(ThemeModeController.new);
|
|
|
|
/// Persists the chosen [ThemeMode] to this device via `shared_preferences`.
|
|
class ThemeModeController extends Notifier<ThemeMode> {
|
|
@override
|
|
ThemeMode build() {
|
|
Future.microtask(_restore);
|
|
return ThemeMode.system;
|
|
}
|
|
|
|
Future<void> _restore() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final saved = prefs.getString(_prefsKey);
|
|
state = ThemeMode.values.asNameMap()[saved] ?? ThemeMode.system;
|
|
}
|
|
|
|
Future<void> setMode(ThemeMode mode) async {
|
|
state = mode;
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setString(_prefsKey, mode.name);
|
|
}
|
|
}
|