Files
Client/lib/view/pages/settings/sections/dev_tools_section.dart
T
2026-05-08 20:12:40 +02:00

173 lines
6.7 KiB
Dart

import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import '../../../../routing/app_routes.dart';
import '../../../../state/app/modules/settings/bloc/settings_cubit.dart';
import '../../../../storage/settings.dart' as model;
import '../../../../widget/centered_leading.dart';
import '../../../../widget/confirm_dialog.dart';
import '../../../../widget/debug/cache_view.dart';
import '../../../../widget/debug/json_viewer.dart';
import '../../../../widget/details_bottom_sheet.dart';
class DevToolsSection extends StatefulWidget {
final SettingsCubit settings;
const DevToolsSection({required this.settings, super.key});
@override
State<DevToolsSection> createState() => _DevToolsSectionState();
}
class _DevToolsSectionState extends State<DevToolsSection> {
@override
Widget build(BuildContext context) => Column(
children: [
ListTile(
leading: const CenteredLeading(Icon(Icons.speed_outlined)),
title: const Text('Performance overlays'),
trailing: const Icon(Icons.arrow_right),
onTap: () {
showDetailsBottomSheet(
context,
children: (sheetCtx) => [
BlocBuilder<SettingsCubit, model.Settings>(
bloc: widget.settings,
builder: (_, _) {
final dev = widget.settings.val().devToolsSettings;
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.auto_graph_outlined),
title: const Text('Performance graph'),
trailing: Checkbox(
value: dev.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: dev.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: dev.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: () {
context.read<SettingsCubit>().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: () => AppRoutes.openCacheView(context),
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'),
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);
},
),
],
);
}