diff --git a/lib/main.dart b/lib/main.dart index bdf0f85..aea08d8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -106,7 +106,12 @@ class _MainState extends State<Main> { textDirection: TextDirection.ltr, child: Consumer<SettingsProvider>( builder: (context, settings, child) { + var devToolsSettings = settings.val().devToolsSettings; return MaterialApp( + showPerformanceOverlay: devToolsSettings.showPerformanceOverlay, + checkerboardOffscreenLayers: devToolsSettings.checkerboardOffscreenLayers, + checkerboardRasterCacheImages: devToolsSettings.checkerboardRasterCacheImages, + debugShowCheckedModeBanner: false, localizationsDelegates: const [ ...GlobalMaterialLocalizations.delegates, diff --git a/lib/storage/base/settings.dart b/lib/storage/base/settings.dart index 5f96084..46cd3b8 100644 --- a/lib/storage/base/settings.dart +++ b/lib/storage/base/settings.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:json_annotation/json_annotation.dart'; +import '../devTools/devToolsSettings.dart'; import '../file/fileSettings.dart'; import '../fileView/fileViewSettings.dart'; import '../gradeAverages/gradeAveragesSettings.dart'; @@ -27,6 +28,7 @@ class Settings { HolidaysSettings holidaysSettings; FileViewSettings fileViewSettings; NotificationSettings notificationSettings; + DevToolsSettings devToolsSettings; Settings({ required this.appTheme, @@ -38,6 +40,7 @@ class Settings { required this.holidaysSettings, required this.fileViewSettings, required this.notificationSettings, + required this.devToolsSettings, }); static String _themeToJson(ThemeMode m) => m.name; diff --git a/lib/storage/base/settings.g.dart b/lib/storage/base/settings.g.dart index b8ca058..acfa7ce 100644 --- a/lib/storage/base/settings.g.dart +++ b/lib/storage/base/settings.g.dart @@ -23,6 +23,8 @@ Settings _$SettingsFromJson(Map<String, dynamic> json) => Settings( json['fileViewSettings'] as Map<String, dynamic>), notificationSettings: NotificationSettings.fromJson( json['notificationSettings'] as Map<String, dynamic>), + devToolsSettings: DevToolsSettings.fromJson( + json['devToolsSettings'] as Map<String, dynamic>), ); Map<String, dynamic> _$SettingsToJson(Settings instance) => <String, dynamic>{ @@ -35,4 +37,5 @@ Map<String, dynamic> _$SettingsToJson(Settings instance) => <String, dynamic>{ 'holidaysSettings': instance.holidaysSettings.toJson(), 'fileViewSettings': instance.fileViewSettings.toJson(), 'notificationSettings': instance.notificationSettings.toJson(), + 'devToolsSettings': instance.devToolsSettings.toJson(), }; diff --git a/lib/storage/devTools/devToolsSettings.dart b/lib/storage/devTools/devToolsSettings.dart new file mode 100644 index 0000000..39dfaa5 --- /dev/null +++ b/lib/storage/devTools/devToolsSettings.dart @@ -0,0 +1,15 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'devToolsSettings.g.dart'; + +@JsonSerializable() +class DevToolsSettings { + bool showPerformanceOverlay; + bool checkerboardOffscreenLayers; + bool checkerboardRasterCacheImages; + + DevToolsSettings({required this.showPerformanceOverlay, required this.checkerboardOffscreenLayers, required this.checkerboardRasterCacheImages}); + + factory DevToolsSettings.fromJson(Map<String, dynamic> json) => _$DevToolsSettingsFromJson(json); + Map<String, dynamic> toJson() => _$DevToolsSettingsToJson(this); +} \ No newline at end of file diff --git a/lib/storage/devTools/devToolsSettings.g.dart b/lib/storage/devTools/devToolsSettings.g.dart new file mode 100644 index 0000000..3f480fe --- /dev/null +++ b/lib/storage/devTools/devToolsSettings.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'devToolsSettings.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +DevToolsSettings _$DevToolsSettingsFromJson(Map<String, dynamic> json) => + DevToolsSettings( + showPerformanceOverlay: json['showPerformanceOverlay'] as bool, + checkerboardOffscreenLayers: json['checkerboardOffscreenLayers'] as bool, + checkerboardRasterCacheImages: + json['checkerboardRasterCacheImages'] as bool, + ); + +Map<String, dynamic> _$DevToolsSettingsToJson(DevToolsSettings instance) => + <String, dynamic>{ + 'showPerformanceOverlay': instance.showPerformanceOverlay, + 'checkerboardOffscreenLayers': instance.checkerboardOffscreenLayers, + 'checkerboardRasterCacheImages': instance.checkerboardRasterCacheImages, + }; diff --git a/lib/view/settings/defaultSettings.dart b/lib/view/settings/defaultSettings.dart index 1b99f8d..debfe18 100644 --- a/lib/view/settings/defaultSettings.dart +++ b/lib/view/settings/defaultSettings.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import '../../storage/base/settings.dart'; +import '../../storage/devTools/devToolsSettings.dart'; import '../../storage/file/fileSettings.dart'; import '../../storage/fileView/fileViewSettings.dart'; import '../../storage/gradeAverages/gradeAveragesSettings.dart'; @@ -43,7 +44,12 @@ class DefaultSettings { notificationSettings: NotificationSettings( askUsageDismissed: false, enabled: false, - ) + ), + devToolsSettings: DevToolsSettings( + checkerboardOffscreenLayers: false, + checkerboardRasterCacheImages: false, + showPerformanceOverlay: false, + ), ); } } \ No newline at end of file diff --git a/lib/view/settings/devToolsSettingsDialog.dart b/lib/view/settings/devToolsSettingsDialog.dart new file mode 100644 index 0000000..5ce5861 --- /dev/null +++ b/lib/view/settings/devToolsSettingsDialog.dart @@ -0,0 +1,120 @@ + +import 'package:filesize/filesize.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../storage/base/settingsProvider.dart'; +import '../../widget/centeredLeading.dart'; +import '../../widget/confirmDialog.dart'; +import '../../widget/debug/cacheView.dart'; +import '../../widget/debug/jsonViewer.dart'; + +class DevToolsSettingsDialog extends StatefulWidget { + final SettingsProvider settings; + const DevToolsSettingsDialog({required this.settings, super.key}); + + @override + State<DevToolsSettingsDialog> createState() => _DevToolsSettingsDialogState(); +} + +class _DevToolsSettingsDialogState extends State<DevToolsSettingsDialog> { + @override + Widget build(BuildContext context) { + return Column( + children: [ + ListTile( + leading: const CenteredLeading(Icon(Icons.speed_outlined)), + title: const Text("Performance overlays"), + trailing: const Icon(Icons.arrow_right), + onTap: () { + showDialog(context: context, builder: (context) => SimpleDialog( + children: [ + ListTile( + leading: const Icon(Icons.auto_graph_outlined), + title: const Text("Performance graph"), + trailing: Checkbox( + value: widget.settings.val().devToolsSettings.showPerformanceOverlay, + onChanged: (e) => widget.settings.val(write: true).devToolsSettings.showPerformanceOverlay = e!, + ), + ), + ListTile( + leading: const Icon(Icons.screen_search_desktop_outlined), + title: const Text("Indicate offscreen layers"), + trailing: Checkbox( + value: widget.settings.val().devToolsSettings.checkerboardOffscreenLayers, + onChanged: (e) => widget.settings.val(write: true).devToolsSettings.checkerboardOffscreenLayers = e!, + ), + ), + ListTile( + leading: const Icon(Icons.imagesearch_roller_outlined), + title: const Text("Indicate raster cache images"), + trailing: Checkbox( + value: widget.settings.val().devToolsSettings.checkerboardRasterCacheImages, + onChanged: (e) => widget.settings.val(write: true).devToolsSettings.checkerboardRasterCacheImages = e!, + ), + ), + ], + )); + }, + ), + 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(widget.settings.val().toJson().toString().length * 8)}\nLange tippen um zu löschen"), + onTap: () { + JsonViewer.asDialog(context, widget.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), + ), + ], + ); + } +} diff --git a/lib/view/settings/settings.dart b/lib/view/settings/settings.dart index ecdacd8..7680f95 100644 --- a/lib/view/settings/settings.dart +++ b/lib/view/settings/settings.dart @@ -1,6 +1,5 @@ -import 'package:filesize/filesize.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; @@ -15,7 +14,8 @@ import '../../theming/appTheme.dart'; import '../../widget/centeredLeading.dart'; import '../../widget/confirmDialog.dart'; import '../../widget/debug/cacheView.dart'; -import '../../widget/debug/jsonViewer.dart'; +import 'defaultSettings.dart'; +import 'devToolsSettingsDialog.dart'; import 'privacyInfo.dart'; class Settings extends StatefulWidget { @@ -248,11 +248,15 @@ class _SettingsState extends State<Settings> { ListTile( leading: const Icon(Icons.developer_mode_outlined), - title: const Text("Entwickleransicht"), + title: const Text("Entwicklermodus"), trailing: Checkbox( value: settings.val().devToolsEnabled, onChanged: (state) { - changeView() => settings.val(write: true).devToolsEnabled = state ?? false; + changeView() { + var enabled = state ?? false; + settings.val(write: true).devToolsEnabled = enabled; + if(!enabled) settings.val(write: true).devToolsSettings = DefaultSettings.get().devToolsSettings; + } if(!state!) { changeView(); @@ -276,67 +280,7 @@ class _SettingsState extends State<Settings> { 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), - ), - ], - ), + child: DevToolsSettingsDialog(settings: settings), ), ], ),