Client/lib/view/settings/devToolsSettings.dart

213 lines
10 KiB
Dart

import 'package:background_fetch/background_fetch.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../background_tasks/scheduledTask.dart';
import '../../storage/base/settingsProvider.dart';
import '../../widget/centeredLeading.dart';
import '../../widget/confirmDialog.dart';
import '../../widget/debug/cacheView.dart';
import '../../widget/debug/jsonViewer.dart';
import '../../widget/infoDialog.dart';
class DevToolsSettings extends StatefulWidget {
final SettingsProvider settings;
const DevToolsSettings({required this.settings, super.key});
@override
State<DevToolsSettings> createState() => _DevToolsSettingsState();
}
class _DevToolsSettingsState extends State<DevToolsSettings> {
@override
Widget build(BuildContext context) => Column(
children: [
ListTile(
leading: const CenteredLeading(Icon(Icons.task_outlined)),
title: const Text('Background app fetch task'),
trailing: const Icon(Icons.arrow_right),
onTap: () {
showDialog(context: context, builder: (context) => AlertDialog(
title: Text('Background fetch task'),
content: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
children: [
FutureBuilder(future: BackgroundFetch.status, builder: (context, snapshot) {
if(snapshot.hasData) {
var fetchStatus = switch(snapshot.data) {
BackgroundFetch.STATUS_AVAILABLE => 'STATUS_AVAILABLE, Background updates are available for the app.',
BackgroundFetch.STATUS_DENIED => 'STATUS_DENIED, The user explicitly disabled background behavior for this app or for the whole system.',
BackgroundFetch.STATUS_RESTRICTED => 'STATUS_RESTRICTED, Background updates are unavailable and the user cannot enable them again. For example, this status can occur when parental controls are in effect for the current user.',
_ => 'UNKNOWN',
};
return Text('(${snapshot.data}): $fetchStatus');
}
return LinearProgressIndicator();
}),
const Divider(),
const Text('There is no indicator if the Fetch-API is currently running or not!'),
const Divider(),
FutureBuilder(
future: SharedPreferences.getInstance(),
builder: (context, snapshot) {
if(!snapshot.hasData) return LinearProgressIndicator();
return Text('Last fetch timestamp: ${snapshot.data?.getStringList(ScheduledTask.fetchApiLastRunTimestampKey)?.last ?? 'No entry'}');
},
)
],
),
actions: [
FutureBuilder(future: SharedPreferences.getInstance(), builder: (context, snapshot) {
if(!snapshot.hasData) return LinearProgressIndicator();
return TextButton(
onPressed: () {
InfoDialog.show(
context,
(snapshot.data!.getStringList(ScheduledTask.fetchApiLastRunTimestampKey) ?? []).reversed.join('\n')
);
},
child: Text('Fetch history')
);
}),
TextButton(
onPressed: () => ConfirmDialog(
title: 'Warning',
content: 'Background Fetch worker will be started! This basically happens on every app startup.',
onConfirm: BackgroundFetch.start
).asDialog(context),
child: Text('Fetch-API Start')
),
TextButton(
onPressed: () => ConfirmDialog(
title: 'Warning',
content: 'Background Fetch worker will be terminated. This will result in outdated Information when App is not in foreground!',
onConfirm: BackgroundFetch.stop
).asDialog(context),
child: Text('Fetch-API Stop')
),
TextButton(
onPressed: () => ConfirmDialog(
title: 'Warning',
content: 'Background fetch will run now! This happens in the application layer and does not interact with the Fetch-API!',
confirmButton: 'Run',
onConfirm: ScheduledTask.backgroundFetch
).asDialog(context),
child: Text('Run task manually')
),
TextButton(onPressed: () => Navigator.of(context).pop(), child: Text('Zurück'))
],
));
},
),
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('Thumb-storage'),
subtitle: Text('etwa ${filesize(PaintingBinding.instance.imageCache.currentSizeBytes)}\nLange tippen um zu löschen'),
onLongPress: () {
ConfirmDialog(
title: 'Thumbs cache löschen',
content: 'Alle zwischengespeicherten Bilder werden gelöscht.',
confirmButton: 'Unwiederruflich löschen',
onConfirm: () => PaintingBinding.instance.imageCache.clear(),
).asDialog(context);
},
),
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: 'Einstellungen 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) => Text("etwa ${snapshot.hasError ? "?" : snapshot.hasData ? filesize(snapshot.data) : "..."}\nLange tippen um zu löschen"),
),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => 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),
),
ListTile(
leading: const CenteredLeading(Icon(Icons.data_object)),
title: const Text('BLOC-storage state cache'),
subtitle: const Text('Lange tippen um zu löschen'),
onTap: () {
// Navigator.push(context, MaterialPageRoute(builder: (context) => const CacheView()));
},
onLongPress: () {
ConfirmDialog(
title: 'BLOC-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: () => HydratedBloc.storage.clear(),
).asDialog(context);
},
),
],
);
}