leafittome/lib/core/settings/settings_provider.dart
cschlaefke 52e72c25b1 Push-Erinnerungen: FCM-Registrierung in der App, geplante Function sendDailyReminders
- Function läuft alle 15 Min (europe-west3): prüft Erinnerungszeit pro Nutzer (Zeitzonen-korrekt), berechnet fällige Aufgaben, schickt eine Sammel-Push pro Tag, räumt ungültige Tokens auf
- App registriert Gerät nach Login (Berechtigung, Token, Zeitzone), Erinnerungszeit wird ins Nutzer-Dokument synchronisiert
- Doku Schritt 6 inkl. APNs-Anleitung für iOS (sobald Developer Account da ist)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 13:06:02 +02:00

106 lines
3.4 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../features/notifications/data/push_registration_service.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')}',
);
// Ans Backend synchronisieren die Erinnerungs-Function liest die Zeit
// aus dem Nutzer-Dokument.
ref.read(pushRegistrationServiceProvider).syncReminderTime(time);
}
}
final settingsProvider =
NotifierProvider<SettingsNotifier, AppSettings>(SettingsNotifier.new);