Implement settings
This commit is contained in:
212
flutter/lib/state/app_settings.dart
Normal file
212
flutter/lib/state/app_settings.dart
Normal file
@@ -0,0 +1,212 @@
|
||||
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;
|
||||
}
|
||||
}
|
@@ -1,16 +1,87 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:simplecloudnotifier/state/globals.dart';
|
||||
|
||||
enum ThemeColor {
|
||||
Pink(displayStr: 'Pink', key: 'PINK', value: Colors.pink),
|
||||
Red(displayStr: 'Red', key: 'RED', value: Colors.red),
|
||||
DeepOrange(displayStr: 'Deep-Orange', key: 'DEEPORANGE', value: Colors.deepOrange),
|
||||
Orange(displayStr: 'Orange', key: 'ORANGE', value: Colors.orange),
|
||||
Amber(displayStr: 'Amber', key: 'AMBER', value: Colors.amber),
|
||||
Yellow(displayStr: 'Yellow', key: 'YELLOW', value: Colors.yellow),
|
||||
Lime(displayStr: 'Lime', key: 'LIME', value: Colors.lime),
|
||||
LightGreen(displayStr: 'Light-Green', key: 'LIGHTGREEN', value: Colors.lightGreen),
|
||||
Green(displayStr: 'Green', key: 'GREEN', value: Colors.green),
|
||||
Teal(displayStr: 'Teal', key: 'TEAL', value: Colors.teal),
|
||||
Cyan(displayStr: 'Cyan', key: 'CYAN', value: Colors.cyan),
|
||||
LightBlue(displayStr: 'Light-Blue', key: 'LIGHTBLUE', value: Colors.lightBlue),
|
||||
Blue(displayStr: 'Blue', key: 'BLUE', value: Colors.blue),
|
||||
Indigo(displayStr: 'Indigo', key: 'INDIGO', value: Colors.indigo),
|
||||
Purple(displayStr: 'Purple', key: 'PURPLE', value: Colors.purple),
|
||||
DeepPurple(displayStr: 'Deep-Purple', key: 'DEEPPURPLE', value: Colors.deepPurple),
|
||||
BlueGrey(displayStr: 'Blue-Grey', key: 'BLUEGREY', value: Colors.blueGrey),
|
||||
Brown(displayStr: 'Brown', key: 'BROWN', value: Colors.brown),
|
||||
Grey(displayStr: 'Grey', key: 'GREY', value: Colors.grey);
|
||||
|
||||
const ThemeColor({required this.displayStr, required this.key, required this.value});
|
||||
|
||||
final String displayStr;
|
||||
final String key;
|
||||
final Color value;
|
||||
|
||||
@override
|
||||
toString() => displayStr;
|
||||
|
||||
static ThemeColor? parse(String? string) {
|
||||
if (string == null) return null;
|
||||
return values.firstWhere((e) => e.key == string, orElse: null);
|
||||
}
|
||||
}
|
||||
|
||||
class AppTheme extends ChangeNotifier {
|
||||
static AppTheme? _singleton = AppTheme._internal();
|
||||
|
||||
factory AppTheme() {
|
||||
return _singleton ?? (_singleton = AppTheme._internal());
|
||||
}
|
||||
|
||||
AppTheme._internal() {}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
bool _darkmode = false;
|
||||
bool get darkMode => _darkmode;
|
||||
|
||||
ThemeColor _color = ThemeColor.Blue;
|
||||
ThemeColor get color => _color;
|
||||
|
||||
void setDarkMode(bool v) {
|
||||
_darkmode = v;
|
||||
notifyListeners();
|
||||
save();
|
||||
}
|
||||
|
||||
void switchDarkMode() {
|
||||
_darkmode = !_darkmode;
|
||||
notifyListeners();
|
||||
save();
|
||||
}
|
||||
|
||||
void setColor(ThemeColor v) {
|
||||
_color = v;
|
||||
notifyListeners();
|
||||
save();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
void load() {
|
||||
_darkmode = Globals().sharedPrefs.getBool('theme.dark') ?? _darkmode;
|
||||
_color = ThemeColor.parse(Globals().sharedPrefs.getString('theme.color')) ?? _color;
|
||||
}
|
||||
|
||||
Future<void> save() async {
|
||||
await Globals().sharedPrefs.setBool('theme.dark', _darkmode);
|
||||
await Globals().sharedPrefs.setString('theme.color', _color.key);
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ import 'package:simplecloudnotifier/api/api_client.dart';
|
||||
import 'package:simplecloudnotifier/models/channel.dart';
|
||||
import 'package:simplecloudnotifier/models/keytoken.dart';
|
||||
import 'package:simplecloudnotifier/models/scn_message.dart';
|
||||
import 'package:simplecloudnotifier/settings/app_settings.dart';
|
||||
import 'package:simplecloudnotifier/state/app_settings.dart';
|
||||
|
||||
class SCNDataCache {
|
||||
SCNDataCache._internal();
|
||||
|
Reference in New Issue
Block a user