- Flutter/Dart (iOS + Android), Riverpod, go_router, i18n via ARB (deutsch) - Feature-Struktur: today, plants, locations, household (V2-Platzhalter), settings - Intervall-Modell: Aufgaben werden aus lastWatered/lastFertilized + Intervall berechnet - In-Memory-Demo-Daten, Firebase-Anbindung folgt im nächsten Block - Doku: Architektur, Firebase-Einrichtung, Forgejo-Git-Hosting Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
101 lines
3.1 KiB
Dart
101 lines
3.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
/// Wird in main.dart mit der echten Instanz überschrieben.
|
|
final sharedPreferencesProvider = Provider<SharedPreferences>(
|
|
(ref) => throw UnimplementedError('sharedPreferencesProvider muss in main.dart überschrieben werden'),
|
|
);
|
|
|
|
/// Schriftgrößen-Stufen, die der Nutzer in den Einstellungen wählen kann.
|
|
/// Der Faktor wird zusätzlich zur System-Schriftgröße angewendet.
|
|
enum AppTextSize {
|
|
normal(1.0),
|
|
large(1.15),
|
|
extraLarge(1.3);
|
|
|
|
const AppTextSize(this.factor);
|
|
final double factor;
|
|
}
|
|
|
|
@immutable
|
|
class AppSettings {
|
|
const AppSettings({
|
|
required this.themeMode,
|
|
required this.textSize,
|
|
required this.highContrast,
|
|
required this.reminderTime,
|
|
});
|
|
|
|
final ThemeMode themeMode;
|
|
final AppTextSize textSize;
|
|
final bool highContrast;
|
|
|
|
/// Uhrzeit der täglichen Sammel-Erinnerung. Wird lokal gespeichert und
|
|
/// später mit dem Firebase-Backend synchronisiert (V1-Push-Block).
|
|
final TimeOfDay reminderTime;
|
|
|
|
AppSettings copyWith({
|
|
ThemeMode? themeMode,
|
|
AppTextSize? textSize,
|
|
bool? highContrast,
|
|
TimeOfDay? reminderTime,
|
|
}) {
|
|
return AppSettings(
|
|
themeMode: themeMode ?? this.themeMode,
|
|
textSize: textSize ?? this.textSize,
|
|
highContrast: highContrast ?? this.highContrast,
|
|
reminderTime: reminderTime ?? this.reminderTime,
|
|
);
|
|
}
|
|
}
|
|
|
|
class SettingsNotifier extends Notifier<AppSettings> {
|
|
static const _keyThemeMode = 'settings.themeMode';
|
|
static const _keyTextSize = 'settings.textSize';
|
|
static const _keyHighContrast = 'settings.highContrast';
|
|
static const _keyReminderTime = 'settings.reminderTime';
|
|
|
|
SharedPreferences get _prefs => ref.read(sharedPreferencesProvider);
|
|
|
|
@override
|
|
AppSettings build() {
|
|
final reminderRaw = _prefs.getString(_keyReminderTime) ?? '09:00';
|
|
final parts = reminderRaw.split(':');
|
|
return AppSettings(
|
|
themeMode: ThemeMode.values.asNameMap()[_prefs.getString(_keyThemeMode)] ?? ThemeMode.system,
|
|
textSize: AppTextSize.values.asNameMap()[_prefs.getString(_keyTextSize)] ?? AppTextSize.normal,
|
|
highContrast: _prefs.getBool(_keyHighContrast) ?? false,
|
|
reminderTime: TimeOfDay(
|
|
hour: int.tryParse(parts[0]) ?? 9,
|
|
minute: int.tryParse(parts.length > 1 ? parts[1] : '0') ?? 0,
|
|
),
|
|
);
|
|
}
|
|
|
|
void setThemeMode(ThemeMode mode) {
|
|
state = state.copyWith(themeMode: mode);
|
|
_prefs.setString(_keyThemeMode, mode.name);
|
|
}
|
|
|
|
void setTextSize(AppTextSize size) {
|
|
state = state.copyWith(textSize: size);
|
|
_prefs.setString(_keyTextSize, size.name);
|
|
}
|
|
|
|
void setHighContrast(bool enabled) {
|
|
state = state.copyWith(highContrast: enabled);
|
|
_prefs.setBool(_keyHighContrast, enabled);
|
|
}
|
|
|
|
void setReminderTime(TimeOfDay time) {
|
|
state = state.copyWith(reminderTime: time);
|
|
_prefs.setString(
|
|
_keyReminderTime,
|
|
'${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}',
|
|
);
|
|
}
|
|
}
|
|
|
|
final settingsProvider =
|
|
NotifierProvider<SettingsNotifier, AppSettings>(SettingsNotifier.new);
|