use provider to keep logfilter alive

This commit is contained in:
Fabian Freund
2026-01-21 15:18:52 +01:00
parent b573ed5645
commit 9155b9bace
3 changed files with 120 additions and 14 deletions
@@ -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 <http://www.gnu.org/licenses/>.
*/
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;
}
}
@@ -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<LogFilter, Level> {
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<Level>(value),
);
}
}
String _$logFilterHash() => r'b2ee125735571998293b0396907938c38a54d0b5';
abstract class _$LogFilter extends $Notifier<Level> {
Level build();
@$mustCallSuper
@override
void runBuild() {
final ref = this.ref as $Ref<Level, Level>;
final element =
ref.element
as $ClassProviderElement<
AnyNotifier<Level, Level>,
Level,
Object?,
Object?
>;
element.handleCreate(ref, build);
}
}
@@ -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<Level> 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()),