342 lines
15 KiB
Dart
342 lines
15 KiB
Dart
|
|
|
|
import 'package:filesize/filesize.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:package_info/package_info.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
import '../../model/accountData.dart';
|
|
import '../../notification/notifyUpdater.dart';
|
|
import '../../storage/base/settingsProvider.dart';
|
|
import '../../theming/appTheme.dart';
|
|
import '../../widget/centeredLeading.dart';
|
|
import '../../widget/confirmDialog.dart';
|
|
import '../../widget/debug/cacheView.dart';
|
|
import '../../widget/debug/jsonViewer.dart';
|
|
import 'privacyInfo.dart';
|
|
|
|
class Settings extends StatefulWidget {
|
|
const Settings({super.key});
|
|
|
|
@override
|
|
State<Settings> createState() => _SettingsState();
|
|
}
|
|
|
|
class _SettingsState extends State<Settings> {
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
}
|
|
|
|
bool developerMode = false;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
|
|
return Consumer<SettingsProvider>(builder: (context, settings, child) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text("Einstellungen"),
|
|
),
|
|
body: ListView(
|
|
children: [
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.logout_outlined)),
|
|
title: const Text("Konto abmelden"),
|
|
subtitle: Text("Angemeldet als ${AccountData().getUsername()}"),
|
|
onTap: () {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => ConfirmDialog(
|
|
title: "Abmelden?",
|
|
content: "Möchtest du dich wirklich abmelden?",
|
|
confirmButton: "Abmelden",
|
|
onConfirm: () {
|
|
SharedPreferences.getInstance().then((value) => {
|
|
value.clear(),
|
|
}).then((value) async {
|
|
PaintingBinding.instance.imageCache.clear();
|
|
Provider.of<SettingsProvider>(context, listen: false).reset();
|
|
const CacheView().clear();
|
|
AccountData().removeData(context: context);
|
|
Navigator.popUntil(context, (route) => !Navigator.canPop(context));
|
|
});
|
|
},
|
|
),
|
|
);
|
|
},
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.dark_mode_outlined),
|
|
title: const Text("Farbgebung"),
|
|
trailing: DropdownButton<ThemeMode>(
|
|
value: settings.val().appTheme,
|
|
icon: const Icon(Icons.arrow_drop_down),
|
|
items: ThemeMode.values.map((e) => DropdownMenuItem<ThemeMode>(
|
|
value: e,
|
|
enabled: e != settings.val().appTheme,
|
|
child: Row(
|
|
children: [
|
|
Icon(AppTheme.getDisplayOptions(e).icon),
|
|
const SizedBox(width: 10),
|
|
Text(AppTheme.getDisplayOptions(e).displayName),
|
|
],
|
|
),
|
|
)).toList(),
|
|
onChanged: (e) {
|
|
settings.val(write: true).appTheme = e!;
|
|
},
|
|
),
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.star_border),
|
|
title: const Text("Favoriten im Talk nach oben sortieren"),
|
|
trailing: Checkbox(
|
|
value: settings.val().talkSettings.sortFavoritesToTop,
|
|
onChanged: (e) {
|
|
settings.val(write: true).talkSettings.sortFavoritesToTop = e!;
|
|
},
|
|
),
|
|
),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.mark_email_unread_outlined),
|
|
title: const Text("Ungelesene Chats nach oben sortieren"),
|
|
trailing: Checkbox(
|
|
value: settings.val().talkSettings.sortUnreadToTop,
|
|
onChanged: (e) {
|
|
settings.val(write: true).talkSettings.sortUnreadToTop = e!;
|
|
},
|
|
),
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.drive_folder_upload_outlined),
|
|
title: const Text("Ordner in Dateien nach oben sortieren"),
|
|
trailing: Checkbox(
|
|
value: settings.val().fileSettings.sortFoldersToTop,
|
|
onChanged: (e) {
|
|
settings.val(write: true).fileSettings.sortFoldersToTop = e!;
|
|
},
|
|
),
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.open_in_new_outlined),
|
|
title: const Text("Dateien immer mit Systemdialog öffnen"),
|
|
trailing: Checkbox(
|
|
value: settings.val().fileViewSettings.alwaysOpenExternally,
|
|
onChanged: (e) {
|
|
settings.val(write: true).fileViewSettings.alwaysOpenExternally = e!;
|
|
},
|
|
),
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.notifications_active_outlined)),
|
|
title: const Text("Push-Benachrichtigungen aktivieren"),
|
|
subtitle: const Text("Lange tippen für mehr Informationen"),
|
|
trailing: Checkbox(
|
|
value: settings.val().notificationSettings.enabled,
|
|
onChanged: (e) {
|
|
if(e!) {
|
|
NotifyUpdater.enableAfterDisclaimer(settings).asDialog(context);
|
|
} else {
|
|
settings.val(write: true).notificationSettings.enabled = e;
|
|
}
|
|
},
|
|
),
|
|
onLongPress: () => showDialog(context: context, builder: (context) => AlertDialog(
|
|
title: const Text("Info über Push"),
|
|
content: const SingleChildScrollView(child: Text(""
|
|
"Aufgrund technischer Limitationen müssen Push-nachrichten über einen externen Server - hier 'mhsl.eu' (Author dieser App) - erfolgen.\n\n"
|
|
"Wenn Push aktiviert wird, werden deine Zugangsdaten und ein Token verschlüsselt an den Betreiber gesendet und von ihm unverschlüsselt gespeichert.\n\n"
|
|
"Der extene Server verwendet die Zugangsdaten um sich maschinell in Nextcloud Talk anzumelden und via Websockets auf neue Nachrichten zu warten.\n\n"
|
|
"Wenn eine neue Nachricht eintrifft wird dein Telefon via FBC-Messaging (Google Firebase Push) vom externen Server benachrichtigt.\n\n"
|
|
"Behalte im Hinterkopf, dass deine Zugangsdaten auf einem externen Server gespeichert werden und dies trots bester Absichten ein Sicherheitsrisiko sein kann!"
|
|
)),
|
|
actions: [
|
|
TextButton(onPressed: () => Navigator.of(context).pop(), child: const Text("Zurück"))
|
|
],
|
|
)),
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.live_help_outlined),
|
|
title: const Text("Informationen und Lizenzen"),
|
|
onTap: () {
|
|
PackageInfo.fromPlatform().then((appInfo) {
|
|
showAboutDialog(
|
|
context: context,
|
|
applicationIcon: const Icon(Icons.apps),
|
|
applicationName: "MarianumMobile",
|
|
applicationVersion: "${appInfo.appName}\n\nPackage: ${appInfo.packageName}\n\nVersion: ${appInfo.version}\nBuild: ${appInfo.buildNumber}",
|
|
applicationLegalese: "Dies ist ein Inoffizieller Nextcloud & Webuntis Client und wird nicht vom Marianum selbst betrieben.\n"
|
|
"Keinerlei Gewähr für Vollständigkeit, Richtigkeit und Aktualität!\n\n"
|
|
"Development build\n"
|
|
"Marianum Fulda 2023 Elias Müller",
|
|
);
|
|
});
|
|
},
|
|
trailing: const Icon(Icons.arrow_right),
|
|
),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.policy_outlined),
|
|
title: const Text("Impressum & Datenschutz"),
|
|
onTap: () {
|
|
showDialog(context: context, builder: (context) {
|
|
return SimpleDialog(
|
|
children: [
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.school_outlined)),
|
|
title: const Text("Infos zum Marianum Fulda"),
|
|
subtitle: const Text("Für Talk-Chats und Dateien"),
|
|
trailing: const Icon(Icons.arrow_right),
|
|
onTap: () => PrivacyInfo(providerText: "Marianum", imprintUrl: "https://www.marianum-fulda.de/impressum", privacyUrl: "https://www.marianum-fulda.de/datenschutz").showPopup(context)
|
|
),
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.date_range_outlined)),
|
|
title: const Text("Infos zu Web-/ Untis"),
|
|
subtitle: const Text("Für den Vertretungsplan"),
|
|
trailing: const Icon(Icons.arrow_right),
|
|
onTap: () => PrivacyInfo(providerText: "Untis", imprintUrl: "https://www.untis.at/impressum", privacyUrl: "https://www.untis.at/datenschutz-wu-apps").showPopup(context)
|
|
),
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.send_time_extension_outlined)),
|
|
title: const Text("Infos zu mhsl"),
|
|
subtitle: const Text("Für Countdowns, Marianum Message und mehr"),
|
|
trailing: const Icon(Icons.arrow_right),
|
|
onTap: () => PrivacyInfo(providerText: "mhsl", imprintUrl: "https://mhsl.eu/id.html", privacyUrl: "https://mhsl.eu/datenschutz.html").showPopup(context),
|
|
),
|
|
],
|
|
);
|
|
});
|
|
},
|
|
trailing: const Icon(Icons.arrow_right),
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.code)),
|
|
title: const Text("Quellcode der App"),
|
|
subtitle: const Text("Open Source GNU GPL v3"),
|
|
onTap: () => ConfirmDialog.openBrowser(context, "https://mhsl.eu/gitea/MarianumMobile/Client"),
|
|
),
|
|
|
|
ListTile(
|
|
leading: const Icon(Icons.developer_mode_outlined),
|
|
title: const Text("Entwickleransicht"),
|
|
trailing: Checkbox(
|
|
value: settings.val().devToolsEnabled,
|
|
onChanged: (state) {
|
|
changeView() => settings.val(write: true).devToolsEnabled = state ?? false;
|
|
|
|
if(!state!) {
|
|
changeView();
|
|
return;
|
|
}
|
|
|
|
ConfirmDialog(
|
|
title: "Entwicklermodus",
|
|
content: ""
|
|
"Die Entwickleransicht bietet erweiterte Funktionen, die für den üblichen Gebrauch nicht benötigt werden.\n\nDie Verwendung der Tools kann darüber hinaus bei falscher Verwendung zu Fehlern führen.\n\n"
|
|
"Aktivieren auf eigene Verantwortung.",
|
|
confirmButton: "Ja, ich verstehe das Risiko",
|
|
cancelButton: "Nein, zurück zur App",
|
|
onConfirm: () {
|
|
changeView();
|
|
},
|
|
).asDialog(context);
|
|
},
|
|
),
|
|
),
|
|
|
|
Visibility(
|
|
visible: settings.val().devToolsEnabled,
|
|
child: Column(
|
|
children: [
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.image_outlined)),
|
|
title: const Text("Cached Thumbnails löschen"),
|
|
subtitle: Text("etwa ${filesize(PaintingBinding.instance.imageCache.currentSizeBytes)}"),
|
|
onTap: () {
|
|
ConfirmDialog(
|
|
title: "Thumbs cache löschen",
|
|
content: "Alle zwischengespeicherten Bilder werden gelöscht.",
|
|
confirmButton: "Unwiederruflich löschen",
|
|
onConfirm: () => PaintingBinding.instance.imageCache.clear(),
|
|
).asDialog(context);
|
|
},
|
|
trailing: const Icon(Icons.arrow_right),
|
|
),
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.settings_applications_outlined)),
|
|
title: const Text("Settings-storage JSON dump"),
|
|
subtitle: Text("etwa ${filesize(settings.val().toJson().toString().length * 8)}\nLange tippen um zu löschen"),
|
|
onTap: () {
|
|
JsonViewer.asDialog(context, settings.val().toJson());
|
|
},
|
|
onLongPress: () {
|
|
ConfirmDialog(
|
|
title: "App-Speicher löschen",
|
|
content: "Alle Einstellungen gehen verloren! Accountdaten sowie App-Daten sind nicht betroffen.",
|
|
confirmButton: "Unwiederruflich Löschen",
|
|
onConfirm: () {
|
|
Provider.of<SettingsProvider>(context, listen: false).reset();
|
|
},
|
|
).asDialog(context);
|
|
},
|
|
trailing: const Icon(Icons.arrow_right),
|
|
),
|
|
ListTile(
|
|
leading: const CenteredLeading(Icon(Icons.data_object)),
|
|
title: const Text("Cache-storage JSON dump"),
|
|
subtitle: FutureBuilder(
|
|
future: const CacheView().totalSize(),
|
|
builder: (context, snapshot) {
|
|
return Text("etwa ${snapshot.hasError ? "?" : snapshot.hasData ? filesize(snapshot.data) : "..."}\nLange tippen um zu löschen");
|
|
},
|
|
),
|
|
onTap: () {
|
|
Navigator.push(context, MaterialPageRoute(builder: (context) {
|
|
return const CacheView();
|
|
}));
|
|
},
|
|
onLongPress: () {
|
|
ConfirmDialog(
|
|
title: "App-Cache löschen",
|
|
content: "Alle cache Einträge werden gelöscht. Der Cache wird bei Nutzung der App automatisch erneut aufgebaut",
|
|
confirmButton: "Unwiederruflich löschen",
|
|
onConfirm: () => const CacheView().clear().then((value) => setState((){})),
|
|
).asDialog(context);
|
|
},
|
|
trailing: const Icon(Icons.arrow_right),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
});
|
|
}
|
|
}
|