SimpleCloudNotifier/flutter/lib/state/app_settings.dart
Mike Schwörer b91ddc172d
Some checks failed
Build Docker and Deploy / Build Docker Container (push) Successful in 51s
Build Docker and Deploy / Run Unit-Tests (push) Failing after 11m17s
Build Docker and Deploy / Deploy to Server (push) Has been skipped
Implement settings
2025-04-19 02:02:37 +02:00

213 lines
8.8 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:intl/intl.dart';
import 'package:shared_preferences/src/shared_preferences_legacy.dart';
import 'package:simplecloudnotifier/state/globals.dart';
enum AppSettingsDateFormat {
ISO(displayStr: 'ISO (yyyy-MM-dd)', key: 'ISO'),
German(displayStr: 'German (dd.MM.yyyy)', key: 'German'),
US(displayStr: 'US (MM/dd/yyyy)', key: 'US');
const AppSettingsDateFormat({required this.displayStr, required this.key});
final String displayStr;
final String key;
@override
toString() => displayStr;
DateFormat dateFormat() {
switch (this) {
case AppSettingsDateFormat.ISO:
return DateFormat('yyyy-MM-dd HH:mm');
case AppSettingsDateFormat.German:
return DateFormat('dd.MM.yyyy HH:mm');
case AppSettingsDateFormat.US:
return DateFormat('MM/dd/yyyy HH:mm');
}
}
static AppSettingsDateFormat? parse(String? string) {
if (string == null) return null;
return values.firstWhere((e) => e.key == string, orElse: null);
}
}
class AppSettings extends ChangeNotifier {
bool groupNotifications = true;
int messagePageSize = 128;
bool devMode = false;
bool showDebugButton = false;
bool backgroundRefreshMessageListOnPop = false;
bool alwaysBackgroundRefreshMessageListOnLifecycleResume = true;
AppSettingsDateFormat dateFormat = AppSettingsDateFormat.ISO;
int messagePreviewLength = 3;
AppNotificationSettings notification0 = AppNotificationSettings();
AppNotificationSettings notification1 = AppNotificationSettings();
AppNotificationSettings notification2 = AppNotificationSettings();
static AppSettings? _singleton = AppSettings._internal();
factory AppSettings() {
return _singleton ?? (_singleton = AppSettings._internal());
}
AppSettings._internal() {
load();
}
void reset() {
groupNotifications = true;
messagePageSize = 128;
devMode = false;
showDebugButton = false;
backgroundRefreshMessageListOnPop = false;
alwaysBackgroundRefreshMessageListOnLifecycleResume = true;
dateFormat = AppSettingsDateFormat.ISO;
messagePreviewLength = 3;
notification0 = AppNotificationSettings();
notification1 = AppNotificationSettings();
notification2 = AppNotificationSettings();
notifyListeners();
}
void load() {
groupNotifications = Globals().sharedPrefs.getBool('settings.groupNotifications') ?? groupNotifications;
messagePageSize = Globals().sharedPrefs.getInt('settings.messagePageSize') ?? messagePageSize;
devMode = Globals().sharedPrefs.getBool('settings.devMode') ?? devMode;
showDebugButton = Globals().sharedPrefs.getBool('settings.showDebugButton') ?? showDebugButton;
backgroundRefreshMessageListOnPop = Globals().sharedPrefs.getBool('settings.backgroundRefreshMessageListOnPop') ?? backgroundRefreshMessageListOnPop;
alwaysBackgroundRefreshMessageListOnLifecycleResume = Globals().sharedPrefs.getBool('settings.alwaysBackgroundRefreshMessageListOnLifecycleResume') ?? alwaysBackgroundRefreshMessageListOnLifecycleResume;
dateFormat = AppSettingsDateFormat.parse(Globals().sharedPrefs.getString('settings.dateFormat')) ?? dateFormat;
messagePreviewLength = Globals().sharedPrefs.getInt('settings.messagePreviewLength') ?? messagePreviewLength;
notification0 = AppNotificationSettings.load(Globals().sharedPrefs, 'settings.notification0');
notification1 = AppNotificationSettings.load(Globals().sharedPrefs, 'settings.notification1');
notification2 = AppNotificationSettings.load(Globals().sharedPrefs, 'settings.notification2');
}
Future<void> save() async {
await Globals().sharedPrefs.setBool('settings.groupNotifications', groupNotifications);
await Globals().sharedPrefs.setInt('settings.messagePageSize', messagePageSize);
await Globals().sharedPrefs.setBool('settings.devMode', devMode);
await Globals().sharedPrefs.setBool('settings.showDebugButton', showDebugButton);
await Globals().sharedPrefs.setBool('settings.backgroundRefreshMessageListOnPop', backgroundRefreshMessageListOnPop);
await Globals().sharedPrefs.setBool('settings.alwaysBackgroundRefreshMessageListOnLifecycleResume', alwaysBackgroundRefreshMessageListOnLifecycleResume);
await Globals().sharedPrefs.setString('settings.dateFormat', dateFormat.key);
await Globals().sharedPrefs.setInt('settings.messagePreviewLength', messagePreviewLength);
await notification0.save(Globals().sharedPrefs, 'settings.notification0');
await notification1.save(Globals().sharedPrefs, 'settings.notification1');
await notification2.save(Globals().sharedPrefs, 'settings.notification2');
}
void update(void Function(AppSettings p) fn) {
fn(this);
save();
notifyListeners();
}
void updateNotification(int prio, AppNotificationSettings Function(AppNotificationSettings p) fn) {
if (prio == 0) {
notification0 = fn(notification0);
} else if (prio == 1) {
notification1 = fn(notification1);
} else if (prio == 2) {
notification2 = fn(notification2);
}
save();
notifyListeners();
}
AppNotificationSettings getNotificationSettings(int? prio) {
if (prio != null && prio == 0) {
return notification0;
} else if (prio != null && prio == 1) {
return notification1;
} else if (prio != null && prio == 2) {
return notification2;
} else {
return AppNotificationSettings();
}
}
}
class AppNotificationSettings {
// Immutable
AppNotificationSettings({
this.enableLights = false,
this.enableVibration = true,
this.playSound = true,
this.sound = null,
this.silent = false,
this.timeoutAfter = null,
});
final bool enableLights;
final bool enableVibration;
final bool playSound;
final String? sound;
final bool silent;
final int? timeoutAfter;
Future<void> save(SharedPreferences sharedPrefs, String prefix) async {
await Globals().sharedPrefs.setBool('${prefix}.enableLights', enableLights);
await Globals().sharedPrefs.setBool('${prefix}.enableVibration', enableVibration);
await Globals().sharedPrefs.setBool('${prefix}.playSound', playSound);
await Globals().sharedPrefs.setString('${prefix}.sound', _encode(sound));
await Globals().sharedPrefs.setBool('${prefix}.silent', silent);
await Globals().sharedPrefs.setString('${prefix}.timeoutAfter', _encode(timeoutAfter));
}
UriAndroidNotificationSound? soundURI() {
return (sound != null) ? UriAndroidNotificationSound(sound!) : null;
}
AppNotificationSettings withEnableLights(bool v) => AppNotificationSettings(enableLights: v, enableVibration: enableVibration, playSound: playSound, sound: sound, silent: silent, timeoutAfter: timeoutAfter);
AppNotificationSettings withEnableVibration(bool v) => AppNotificationSettings(enableLights: enableLights, enableVibration: v, playSound: playSound, sound: sound, silent: silent, timeoutAfter: timeoutAfter);
AppNotificationSettings withPlaySound(bool v) => AppNotificationSettings(enableLights: enableLights, enableVibration: enableVibration, playSound: v, sound: sound, silent: silent, timeoutAfter: timeoutAfter);
AppNotificationSettings withSound(String? v) => AppNotificationSettings(enableLights: enableLights, enableVibration: enableVibration, playSound: playSound, sound: v, silent: silent, timeoutAfter: timeoutAfter);
AppNotificationSettings withSilent(bool v) => AppNotificationSettings(enableLights: enableLights, enableVibration: enableVibration, playSound: playSound, sound: sound, silent: v, timeoutAfter: timeoutAfter);
AppNotificationSettings withTimeoutAfter(int? v) => AppNotificationSettings(enableLights: enableLights, enableVibration: enableVibration, playSound: playSound, sound: sound, silent: silent, timeoutAfter: v);
static AppNotificationSettings load(SharedPreferences prefs, String prefix) {
final def = AppNotificationSettings();
final enableLights = prefs.getBool('${prefix}.enableLights') ?? def.enableLights;
final enableVibration = prefs.getBool('${prefix}.enableVibration') ?? def.enableVibration;
final playSound = prefs.getBool('${prefix}.playSound') ?? def.playSound;
final sound = _decode(prefs.getString('${prefix}.sound'), def.sound);
final silent = prefs.getBool('${prefix}.silent') ?? def.silent;
final timeoutAfter = _decode(prefs.getString('${prefix}.timeoutAfter'), def.timeoutAfter);
return AppNotificationSettings(
enableLights: enableLights,
enableVibration: enableVibration,
playSound: playSound,
sound: sound,
silent: silent,
timeoutAfter: timeoutAfter,
);
}
}
String _encode<T>(T v) {
return JsonEncoder().convert(v);
}
T _decode<T>(String? v, T fallback) {
if (v == null) return fallback;
try {
return JsonDecoder().convert(v) as T;
} catch (_) {
return fallback;
}
}