From 9155b9bacefcd5f8cb3178d4fd171bac80e4d85f Mon Sep 17 00:00:00 2001 From: Fabian Freund Date: Wed, 21 Jan 2026 15:18:52 +0100 Subject: [PATCH] use provider to keep logfilter alive --- .../settings/domain/providers/log_filter.dart | 36 +++++++++++ .../domain/providers/log_filter.g.dart | 61 +++++++++++++++++++ .../screens/error_logs_screen.dart | 37 ++++++----- 3 files changed, 120 insertions(+), 14 deletions(-) create mode 100644 app/lib/features/settings/domain/providers/log_filter.dart create mode 100644 app/lib/features/settings/domain/providers/log_filter.g.dart 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()),