diff --git a/app/lib/features/settings/domain/providers/log_filter.dart b/app/lib/features/settings/domain/providers/log_filter.dart
new file mode 100644
index 00000000..533ef483
--- /dev/null
+++ b/app/lib/features/settings/domain/providers/log_filter.dart
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2024-2025 Fabian Freund.
+ *
+ * This file is part of WebLibre
+ * (see https://weblibre.eu).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+import 'package:logger/logger.dart';
+import 'package:riverpod_annotation/riverpod_annotation.dart';
+
+part 'log_filter.g.dart';
+
+@Riverpod(keepAlive: true)
+class LogFilter extends _$LogFilter {
+ @override
+ Level build() {
+ return Level.all;
+ }
+
+ // ignore: use_setters_to_change_properties
+ void setFilter(Level level) {
+ state = level;
+ }
+}
diff --git a/app/lib/features/settings/domain/providers/log_filter.g.dart b/app/lib/features/settings/domain/providers/log_filter.g.dart
new file mode 100644
index 00000000..8d157a63
--- /dev/null
+++ b/app/lib/features/settings/domain/providers/log_filter.g.dart
@@ -0,0 +1,61 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'log_filter.dart';
+
+// **************************************************************************
+// RiverpodGenerator
+// **************************************************************************
+
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// ignore_for_file: type=lint, type=warning
+
+@ProviderFor(LogFilter)
+final logFilterProvider = LogFilterProvider._();
+
+final class LogFilterProvider extends $NotifierProvider {
+ LogFilterProvider._()
+ : super(
+ from: null,
+ argument: null,
+ retry: null,
+ name: r'logFilterProvider',
+ isAutoDispose: false,
+ dependencies: null,
+ $allTransitiveDependencies: null,
+ );
+
+ @override
+ String debugGetCreateSourceHash() => _$logFilterHash();
+
+ @$internal
+ @override
+ LogFilter create() => LogFilter();
+
+ /// {@macro riverpod.override_with_value}
+ Override overrideWithValue(Level value) {
+ return $ProviderOverride(
+ origin: this,
+ providerOverride: $SyncValueProvider(value),
+ );
+ }
+}
+
+String _$logFilterHash() => r'b2ee125735571998293b0396907938c38a54d0b5';
+
+abstract class _$LogFilter extends $Notifier {
+ Level build();
+ @$mustCallSuper
+ @override
+ void runBuild() {
+ final ref = this.ref as $Ref;
+ final element =
+ ref.element
+ as $ClassProviderElement<
+ AnyNotifier,
+ Level,
+ Object?,
+ Object?
+ >;
+ element.handleCreate(ref, build);
+ }
+}
diff --git a/app/lib/features/settings/presentation/screens/error_logs_screen.dart b/app/lib/features/settings/presentation/screens/error_logs_screen.dart
index 4ab4f3b2..70625a1d 100644
--- a/app/lib/features/settings/presentation/screens/error_logs_screen.dart
+++ b/app/lib/features/settings/presentation/screens/error_logs_screen.dart
@@ -23,10 +23,12 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:google_fonts/google_fonts.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:intl/intl.dart';
import 'package:logger/logger.dart';
import 'package:timeago/timeago.dart' as timeago;
import 'package:weblibre/core/logger.dart';
+import 'package:weblibre/features/settings/domain/providers/log_filter.dart';
import 'package:weblibre/utils/ui_helper.dart';
IconData _levelIcon(Level level) {
@@ -77,7 +79,7 @@ Color _levelBackgroundColor(Level level, BuildContext context) {
};
}
-class ErrorLogsScreen extends HookWidget {
+class ErrorLogsScreen extends HookConsumerWidget {
const ErrorLogsScreen({super.key});
String _logsText() {
@@ -93,13 +95,14 @@ class ErrorLogsScreen extends HookWidget {
}
@override
- Widget build(BuildContext context) {
- final minLogLevel = useState(Level.all);
+ Widget build(BuildContext context, WidgetRef ref) {
+ final minLogLevel = ref.watch(logFilterProvider);
+
final allLogs = useMemoized(() => loggerMemory.buffer.toList());
final sortedLogs = useMemoized(
() => allLogs.reversed
- .where((e) => e.level.value >= minLogLevel.value.value)
+ .where((e) => e.level.value >= minLogLevel.value)
.toList(),
[allLogs, minLogLevel.value],
);
@@ -113,17 +116,22 @@ class ErrorLogsScreen extends HookWidget {
return TextButton.icon(
onPressed: controller.open,
icon: const Icon(Icons.filter_list),
- label: Text(minLogLevel.value.name.toUpperCase()),
+ label: Text(minLogLevel.name.toUpperCase()),
);
},
menuChildren: [
const Divider(height: 0),
- _buildLevelFilterMenuItem(context, minLogLevel, Level.trace),
- _buildLevelFilterMenuItem(context, minLogLevel, Level.debug),
- _buildLevelFilterMenuItem(context, minLogLevel, Level.info),
- _buildLevelFilterMenuItem(context, minLogLevel, Level.warning),
- _buildLevelFilterMenuItem(context, minLogLevel, Level.error),
- _buildLevelFilterMenuItem(context, minLogLevel, Level.fatal),
+ _buildLevelFilterMenuItem(context, ref, minLogLevel, Level.trace),
+ _buildLevelFilterMenuItem(context, ref, minLogLevel, Level.debug),
+ _buildLevelFilterMenuItem(context, ref, minLogLevel, Level.info),
+ _buildLevelFilterMenuItem(
+ context,
+ ref,
+ minLogLevel,
+ Level.warning,
+ ),
+ _buildLevelFilterMenuItem(context, ref, minLogLevel, Level.error),
+ _buildLevelFilterMenuItem(context, ref, minLogLevel, Level.fatal),
],
),
IconButton(
@@ -150,10 +158,11 @@ class ErrorLogsScreen extends HookWidget {
Widget _buildLevelFilterMenuItem(
BuildContext context,
- ValueNotifier minLogLevel,
+ WidgetRef ref,
+ Level minLogLevel,
Level level,
) {
- final isSelected = level.value == minLogLevel.value.value;
+ final isSelected = level.value == minLogLevel.value;
final levelColor = _levelColor(level);
return CheckboxMenuButton(
@@ -161,7 +170,7 @@ class ErrorLogsScreen extends HookWidget {
value: isSelected,
onChanged: (value) {
if (value == true) {
- minLogLevel.value = level;
+ ref.read(logFilterProvider.notifier).setFilter(level);
}
},
child: Text(level.name.toUpperCase()),