From 9c165e178b48a3c26eb10ac131c5aec606e33378 Mon Sep 17 00:00:00 2001 From: problematicconsumer Date: Tue, 28 Nov 2023 18:24:31 +0330 Subject: [PATCH] Refactor logs --- lib/bootstrap.dart | 4 +- lib/core/router/app_router.dart | 4 +- lib/core/router/routes.dart | 18 ++--- lib/data/repository/config_options_store.dart | 1 + lib/data/repository/core_facade_impl.dart | 18 ----- lib/domain/singbox/box_log.dart | 62 ---------------- lib/domain/singbox/config_options.dart | 2 +- lib/domain/singbox/singbox.dart | 1 - lib/domain/singbox/singbox_facade.dart | 4 -- lib/features/log/data/log_data_providers.dart | 23 ++++++ lib/features/log/data/log_parser.dart | 33 +++++++++ lib/features/log/data/log_path_resolver.dart | 19 +++++ lib/features/log/data/log_repository.dart | 70 +++++++++++++++++++ lib/features/log/model/log_entity.dart | 13 ++++ lib/features/log/model/log_failure.dart | 25 +++++++ lib/features/log/model/log_level.dart | 25 +++++++ .../overview/logs_overview_notifier.dart} | 31 ++++---- .../overview/logs_overview_page.dart} | 24 +++---- .../log/overview/logs_overview_state.dart | 18 +++++ lib/features/logs/notifier/logs_state.dart | 17 ----- lib/features/logs/notifier/notifier.dart | 2 - lib/features/logs/view/view.dart | 1 - .../settings/view/config_options_page.dart | 1 + .../system_tray/system_tray_controller.dart | 2 +- lib/services/files_editor_service.dart | 17 ----- 25 files changed, 272 insertions(+), 163 deletions(-) delete mode 100644 lib/domain/singbox/box_log.dart create mode 100644 lib/features/log/data/log_data_providers.dart create mode 100644 lib/features/log/data/log_parser.dart create mode 100644 lib/features/log/data/log_path_resolver.dart create mode 100644 lib/features/log/data/log_repository.dart create mode 100644 lib/features/log/model/log_entity.dart create mode 100644 lib/features/log/model/log_failure.dart create mode 100644 lib/features/log/model/log_level.dart rename lib/features/{logs/notifier/logs_notifier.dart => log/overview/logs_overview_notifier.dart} (79%) rename lib/features/{logs/view/logs_page.dart => log/overview/logs_overview_page.dart} (92%) create mode 100644 lib/features/log/overview/logs_overview_state.dart delete mode 100644 lib/features/logs/notifier/logs_state.dart delete mode 100644 lib/features/logs/notifier/notifier.dart delete mode 100644 lib/features/logs/view/view.dart diff --git a/lib/bootstrap.dart b/lib/bootstrap.dart index 465d22d6..3a610431 100644 --- a/lib/bootstrap.dart +++ b/lib/bootstrap.dart @@ -12,6 +12,7 @@ import 'package:hiddify/data/repository/app_repository_impl.dart'; import 'package:hiddify/domain/environment.dart'; import 'package:hiddify/features/common/window/window_controller.dart'; import 'package:hiddify/features/geo_asset/data/geo_asset_data_providers.dart'; +import 'package:hiddify/features/log/data/log_data_providers.dart'; import 'package:hiddify/features/profile/data/profile_data_providers.dart'; import 'package:hiddify/features/profile/notifier/active_profile_notifier.dart'; import 'package:hiddify/features/system_tray/system_tray_controller.dart'; @@ -88,6 +89,7 @@ Future _lazyBootstrap( final filesEditor = container.read(filesEditorServiceProvider); await filesEditor.init(); + await container.read(logRepositoryProvider.future); await container.read(geoAssetRepositoryProvider.future); await container.read(profileRepositoryProvider.future); @@ -145,7 +147,7 @@ void initLoggers( final logToFile = debug || (!Platform.isAndroid && !Platform.isIOS); if (logToFile) { _loggers.addPrinter( - FileLogPrinter(read(filesEditorServiceProvider).appLogsFile.path), + FileLogPrinter(read(logPathResolverProvider).appFile().path), ); } Loggy.initLoggy( diff --git a/lib/core/router/app_router.dart b/lib/core/router/app_router.dart index 74a6587f..1339c2d9 100644 --- a/lib/core/router/app_router.dart +++ b/lib/core/router/app_router.dart @@ -53,7 +53,7 @@ int getCurrentIndex(BuildContext context) { final String location = GoRouterState.of(context).uri.path; if (location == const HomeRoute().location) return 0; if (location.startsWith(const ProxiesRoute().location)) return 1; - if (location.startsWith(const LogsRoute().location)) return 2; + if (location.startsWith(const LogsOverviewRoute().location)) return 2; if (location.startsWith(const SettingsRoute().location)) return 3; if (location.startsWith(const AboutRoute().location)) return 4; return 0; @@ -66,7 +66,7 @@ void switchTab(int index, BuildContext context) { case 1: const ProxiesRoute().go(context); case 2: - const LogsRoute().go(context); + const LogsOverviewRoute().go(context); case 3: const SettingsRoute().go(context); case 4: diff --git a/lib/core/router/routes.dart b/lib/core/router/routes.dart index 44a2089a..06c50e7f 100644 --- a/lib/core/router/routes.dart +++ b/lib/core/router/routes.dart @@ -6,7 +6,7 @@ import 'package:hiddify/features/common/adaptive_root_scaffold.dart'; import 'package:hiddify/features/geo_asset/overview/geo_assets_overview_page.dart'; import 'package:hiddify/features/home/view/view.dart'; import 'package:hiddify/features/intro/intro_page.dart'; -import 'package:hiddify/features/logs/view/logs_page.dart'; +import 'package:hiddify/features/log/overview/logs_overview_page.dart'; import 'package:hiddify/features/profile/add/add_profile_modal.dart'; import 'package:hiddify/features/profile/details/profile_details_page.dart'; import 'package:hiddify/features/profile/overview/profiles_overview_page.dart'; @@ -44,9 +44,9 @@ GlobalKey? _dynamicRootKey = path: "profiles/:id", name: ProfileDetailsRoute.name, ), - TypedGoRoute( + TypedGoRoute( path: "logs", - name: LogsRoute.name, + name: LogsOverviewRoute.name, ), TypedGoRoute( path: "settings", @@ -116,9 +116,9 @@ class MobileWrapperRoute extends ShellRouteData { path: "/proxies", name: ProxiesRoute.name, ), - TypedGoRoute( + TypedGoRoute( path: "/logs", - name: LogsRoute.name, + name: LogsOverviewRoute.name, ), TypedGoRoute( path: "/settings", @@ -260,8 +260,8 @@ class ProfileDetailsRoute extends GoRouteData { } } -class LogsRoute extends GoRouteData { - const LogsRoute(); +class LogsOverviewRoute extends GoRouteData { + const LogsOverviewRoute(); static const name = "Logs"; static final GlobalKey? $parentNavigatorKey = _dynamicRootKey; @@ -272,10 +272,10 @@ class LogsRoute extends GoRouteData { return const MaterialPage( fullscreenDialog: true, name: name, - child: LogsPage(), + child: LogsOverviewPage(), ); } - return const NoTransitionPage(name: name, child: LogsPage()); + return const NoTransitionPage(name: name, child: LogsOverviewPage()); } } diff --git a/lib/data/repository/config_options_store.dart b/lib/data/repository/config_options_store.dart index 0a5169be..55cb31b4 100644 --- a/lib/data/repository/config_options_store.dart +++ b/lib/data/repository/config_options_store.dart @@ -3,6 +3,7 @@ import 'package:flutter/foundation.dart'; import 'package:hiddify/core/prefs/prefs.dart'; import 'package:hiddify/data/data_providers.dart'; import 'package:hiddify/domain/singbox/singbox.dart'; +import 'package:hiddify/features/log/model/log_level.dart'; import 'package:hiddify/utils/pref_notifier.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; diff --git a/lib/data/repository/core_facade_impl.dart b/lib/data/repository/core_facade_impl.dart index 375a1e8b..eea0b4df 100644 --- a/lib/data/repository/core_facade_impl.dart +++ b/lib/data/repository/core_facade_impl.dart @@ -240,24 +240,6 @@ class CoreFacadeImpl with ExceptionHandler, InfraLogger implements CoreFacade { ); } - @override - Stream>> watchLogs() { - return singbox.watchLogs(filesEditor.coreLogsFile.path).handleExceptions( - (error, stackTrace) { - loggy.warning("error watching logs", error, stackTrace); - return CoreServiceFailure.unexpected(error, stackTrace); - }, - ); - } - - @override - TaskEither clearLogs() { - return exceptionHandler( - () => singbox.clearLogs().mapLeft(CoreServiceFailure.other).run(), - CoreServiceFailure.unexpected, - ); - } - @override Stream watchConnectionStatus() => singbox.watchConnectionStatus(); diff --git a/lib/domain/singbox/box_log.dart b/lib/domain/singbox/box_log.dart deleted file mode 100644 index 84ee25c1..00000000 --- a/lib/domain/singbox/box_log.dart +++ /dev/null @@ -1,62 +0,0 @@ -import 'package:dartx/dartx.dart'; -import 'package:flutter/material.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:tint/tint.dart'; - -part 'box_log.freezed.dart'; - -enum LogLevel { - trace, - debug, - info, - warn, - error, - fatal, - panic; - - static List get choices => values.takeFirst(4); - - Color? get color => switch (this) { - trace => Colors.lightBlueAccent, - debug => Colors.grey, - info => Colors.lightGreen, - warn => Colors.orange, - error => Colors.redAccent, - fatal => Colors.red, - panic => Colors.red, - }; -} - -@freezed -class BoxLog with _$BoxLog { - const factory BoxLog({ - LogLevel? level, - DateTime? time, - required String message, - }) = _BoxLog; - - factory BoxLog.parse(String log) { - log = log.strip(); - DateTime? time; - if (log.length > 25) { - time = DateTime.tryParse(log.substring(6, 25)); - } - if (time != null) { - log = log.substring(26); - } - final level = LogLevel.values.firstOrNullWhere( - (e) { - if (log.startsWith(e.name.toUpperCase())) { - log = log.removePrefix(e.name.toUpperCase()); - return true; - } - return false; - }, - ); - return BoxLog( - level: level, - time: time, - message: log.trim(), - ); - } -} diff --git a/lib/domain/singbox/config_options.dart b/lib/domain/singbox/config_options.dart index 6790528a..f350e79e 100644 --- a/lib/domain/singbox/config_options.dart +++ b/lib/domain/singbox/config_options.dart @@ -2,8 +2,8 @@ import 'dart:convert'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:hiddify/core/prefs/prefs.dart'; -import 'package:hiddify/domain/singbox/box_log.dart'; import 'package:hiddify/domain/singbox/rules.dart'; +import 'package:hiddify/features/log/model/log_level.dart'; part 'config_options.freezed.dart'; part 'config_options.g.dart'; diff --git a/lib/domain/singbox/singbox.dart b/lib/domain/singbox/singbox.dart index 0ca7decc..441637cd 100644 --- a/lib/domain/singbox/singbox.dart +++ b/lib/domain/singbox/singbox.dart @@ -1,4 +1,3 @@ -export 'box_log.dart'; export 'config_options.dart'; export 'core_status.dart'; export 'outbounds.dart'; diff --git a/lib/domain/singbox/singbox_facade.dart b/lib/domain/singbox/singbox_facade.dart index dd7a9544..4231afb0 100644 --- a/lib/domain/singbox/singbox_facade.dart +++ b/lib/domain/singbox/singbox_facade.dart @@ -46,8 +46,4 @@ abstract interface class SingboxFacade { Stream watchConnectionStatus(); Stream> watchCoreStatus(); - - Stream>> watchLogs(); - - TaskEither clearLogs(); } diff --git a/lib/features/log/data/log_data_providers.dart b/lib/features/log/data/log_data_providers.dart new file mode 100644 index 00000000..199b7dbc --- /dev/null +++ b/lib/features/log/data/log_data_providers.dart @@ -0,0 +1,23 @@ +import 'package:hiddify/features/log/data/log_path_resolver.dart'; +import 'package:hiddify/features/log/data/log_repository.dart'; +import 'package:hiddify/services/service_providers.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'log_data_providers.g.dart'; + +@Riverpod(keepAlive: true) +Future logRepository(LogRepositoryRef ref) async { + final repo = LogRepositoryImpl( + singbox: ref.watch(singboxServiceProvider), + logPathResolver: ref.watch(logPathResolverProvider), + ); + await repo.init().getOrElse((l) => throw l).run(); + return repo; +} + +@Riverpod(keepAlive: true) +LogPathResolver logPathResolver(LogPathResolverRef ref) { + return LogPathResolver( + ref.watch(filesEditorServiceProvider).dirs.workingDir, + ); +} diff --git a/lib/features/log/data/log_parser.dart b/lib/features/log/data/log_parser.dart new file mode 100644 index 00000000..84b496d1 --- /dev/null +++ b/lib/features/log/data/log_parser.dart @@ -0,0 +1,33 @@ +// ignore_for_file: parameter_assignments + +import 'package:dartx/dartx.dart'; +import 'package:hiddify/features/log/model/log_entity.dart'; +import 'package:hiddify/features/log/model/log_level.dart'; +import 'package:tint/tint.dart'; + +abstract class LogParser { + static LogEntity parseSingbox(String log) { + log = log.strip(); + DateTime? time; + if (log.length > 25) { + time = DateTime.tryParse(log.substring(6, 25)); + } + if (time != null) { + log = log.substring(26); + } + final level = LogLevel.values.firstOrNullWhere( + (e) { + if (log.startsWith(e.name.toUpperCase())) { + log = log.removePrefix(e.name.toUpperCase()); + return true; + } + return false; + }, + ); + return LogEntity( + level: level, + time: time, + message: log.trim(), + ); + } +} diff --git a/lib/features/log/data/log_path_resolver.dart b/lib/features/log/data/log_path_resolver.dart new file mode 100644 index 00000000..08762f28 --- /dev/null +++ b/lib/features/log/data/log_path_resolver.dart @@ -0,0 +1,19 @@ +import 'dart:io'; + +import 'package:path/path.dart' as p; + +class LogPathResolver { + const LogPathResolver(this._workingDir); + + final Directory _workingDir; + + Directory get directory => _workingDir; + + File coreFile() { + return File(p.join(directory.path, "box.log")); + } + + File appFile() { + return File(p.join(directory.path, "app.log")); + } +} diff --git a/lib/features/log/data/log_repository.dart b/lib/features/log/data/log_repository.dart new file mode 100644 index 00000000..bd699d42 --- /dev/null +++ b/lib/features/log/data/log_repository.dart @@ -0,0 +1,70 @@ +import 'package:fpdart/fpdart.dart'; +import 'package:hiddify/data/repository/exception_handlers.dart'; +import 'package:hiddify/features/log/data/log_parser.dart'; +import 'package:hiddify/features/log/data/log_path_resolver.dart'; +import 'package:hiddify/features/log/model/log_entity.dart'; +import 'package:hiddify/features/log/model/log_failure.dart'; +import 'package:hiddify/services/singbox/singbox_service.dart'; +import 'package:hiddify/utils/custom_loggers.dart'; + +abstract interface class LogRepository { + TaskEither init(); + Stream>> watchLogs(); + TaskEither clearLogs(); +} + +class LogRepositoryImpl + with ExceptionHandler, InfraLogger + implements LogRepository { + LogRepositoryImpl({ + required this.singbox, + required this.logPathResolver, + }); + + final SingboxService singbox; + final LogPathResolver logPathResolver; + + @override + TaskEither init() { + return exceptionHandler( + () async { + if (!await logPathResolver.directory.exists()) { + await logPathResolver.directory.create(recursive: true); + } + if (await logPathResolver.coreFile().exists()) { + await logPathResolver.coreFile().writeAsString(""); + } else { + await logPathResolver.coreFile().create(recursive: true); + } + if (await logPathResolver.appFile().exists()) { + await logPathResolver.appFile().writeAsString(""); + } else { + await logPathResolver.appFile().create(recursive: true); + } + return right(unit); + }, + LogUnexpectedFailure.new, + ); + } + + @override + Stream>> watchLogs() { + return singbox + .watchLogs(logPathResolver.coreFile().path) + .map((event) => event.map(LogParser.parseSingbox).toList()) + .handleExceptions( + (error, stackTrace) { + loggy.warning("error watching logs", error, stackTrace); + return LogFailure.unexpected(error, stackTrace); + }, + ); + } + + @override + TaskEither clearLogs() { + return exceptionHandler( + () => singbox.clearLogs().mapLeft(LogFailure.unexpected).run(), + LogFailure.unexpected, + ); + } +} diff --git a/lib/features/log/model/log_entity.dart b/lib/features/log/model/log_entity.dart new file mode 100644 index 00000000..878927a9 --- /dev/null +++ b/lib/features/log/model/log_entity.dart @@ -0,0 +1,13 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:hiddify/features/log/model/log_level.dart'; + +part 'log_entity.freezed.dart'; + +@freezed +class LogEntity with _$LogEntity { + const factory LogEntity({ + LogLevel? level, + DateTime? time, + required String message, + }) = _LogEntity; +} diff --git a/lib/features/log/model/log_failure.dart b/lib/features/log/model/log_failure.dart new file mode 100644 index 00000000..f1a4e8fe --- /dev/null +++ b/lib/features/log/model/log_failure.dart @@ -0,0 +1,25 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:hiddify/core/prefs/locale_prefs.dart'; +import 'package:hiddify/domain/failures.dart'; + +part 'log_failure.freezed.dart'; + +@freezed +sealed class LogFailure with _$LogFailure, Failure { + const LogFailure._(); + + const factory LogFailure.unexpected([ + Object? error, + StackTrace? stackTrace, + ]) = LogUnexpectedFailure; + + @override + ({String type, String? message}) present(TranslationsEn t) { + return switch (this) { + LogUnexpectedFailure() => ( + type: "unexpected", + message: null, + ), + }; + } +} diff --git a/lib/features/log/model/log_level.dart b/lib/features/log/model/log_level.dart new file mode 100644 index 00000000..a81cf47c --- /dev/null +++ b/lib/features/log/model/log_level.dart @@ -0,0 +1,25 @@ +import 'package:dartx/dartx.dart'; +import 'package:flutter/material.dart'; + +enum LogLevel { + trace, + debug, + info, + warn, + error, + fatal, + panic; + + /// [LogLevel] selectable by user as preference + static List get choices => values.takeFirst(4); + + Color? get color => switch (this) { + trace => Colors.lightBlueAccent, + debug => Colors.grey, + info => Colors.lightGreen, + warn => Colors.orange, + error => Colors.redAccent, + fatal => Colors.red, + panic => Colors.red, + }; +} diff --git a/lib/features/logs/notifier/logs_notifier.dart b/lib/features/log/overview/logs_overview_notifier.dart similarity index 79% rename from lib/features/logs/notifier/logs_notifier.dart rename to lib/features/log/overview/logs_overview_notifier.dart index b089840d..8b3c4243 100644 --- a/lib/features/logs/notifier/logs_notifier.dart +++ b/lib/features/log/overview/logs_overview_notifier.dart @@ -1,21 +1,22 @@ import 'dart:async'; -import 'package:hiddify/data/data_providers.dart'; -import 'package:hiddify/domain/singbox/singbox.dart'; -import 'package:hiddify/features/logs/notifier/logs_state.dart'; +import 'package:hiddify/features/log/data/log_data_providers.dart'; +import 'package:hiddify/features/log/model/log_entity.dart'; +import 'package:hiddify/features/log/model/log_level.dart'; +import 'package:hiddify/features/log/overview/logs_overview_state.dart'; import 'package:hiddify/utils/riverpod_utils.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:rxdart/rxdart.dart'; -part 'logs_notifier.g.dart'; +part 'logs_overview_notifier.g.dart'; @riverpod -class LogsNotifier extends _$LogsNotifier with AppLogger { +class LogsOverviewNotifier extends _$LogsOverviewNotifier with AppLogger { @override - LogsState build() { + LogsOverviewState build() { ref.disposeDelay(const Duration(seconds: 20)); - state = const LogsState(); + state = const LogsOverviewState(); ref.onDispose( () { loggy.debug("disposing"); @@ -41,7 +42,7 @@ class LogsNotifier extends _$LogsNotifier with AppLogger { ); _addListeners(); - return const LogsState(); + return const LogsOverviewState(); } StreamSubscription? _listener; @@ -50,7 +51,8 @@ class LogsNotifier extends _$LogsNotifier with AppLogger { loggy.debug("adding listeners"); await _listener?.cancel(); _listener = ref - .read(coreFacadeProvider) + .read(logRepositoryProvider) + .requireValue .watchLogs() .throttle( (_) => Stream.value(_listener?.isPaused ?? false), @@ -78,15 +80,14 @@ class LogsNotifier extends _$LogsNotifier with AppLogger { ).listen((event) {}); } - Iterable _logs = []; + Iterable _logs = []; final _debouncer = CallbackDebouncer(const Duration(milliseconds: 200)); LogLevel? _levelFilter; String _filter = ""; - Future> _computeLogs() async { - final logs = _logs.map(BoxLog.parse); - if (_levelFilter == null && _filter.isEmpty) return logs.toList(); - return logs.where((e) { + Future> _computeLogs() async { + if (_levelFilter == null && _filter.isEmpty) return _logs.toList(); + return _logs.where((e) { return (_filter.isEmpty || e.message.contains(_filter)) && (_levelFilter == null || e.level == null || @@ -108,7 +109,7 @@ class LogsNotifier extends _$LogsNotifier with AppLogger { Future clear() async { loggy.debug("clearing"); - await ref.read(coreFacadeProvider).clearLogs().match( + await ref.read(logRepositoryProvider).requireValue.clearLogs().match( (l) { loggy.warning("error clearing logs", l); }, diff --git a/lib/features/logs/view/logs_page.dart b/lib/features/log/overview/logs_overview_page.dart similarity index 92% rename from lib/features/logs/view/logs_page.dart rename to lib/features/log/overview/logs_overview_page.dart index ace41283..3c8e4f75 100644 --- a/lib/features/logs/view/logs_page.dart +++ b/lib/features/log/overview/logs_overview_page.dart @@ -5,25 +5,25 @@ import 'package:gap/gap.dart'; import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/core/prefs/prefs.dart'; import 'package:hiddify/domain/failures.dart'; -import 'package:hiddify/domain/singbox/singbox.dart'; import 'package:hiddify/features/common/nested_app_bar.dart'; -import 'package:hiddify/features/logs/notifier/notifier.dart'; -import 'package:hiddify/services/service_providers.dart'; +import 'package:hiddify/features/log/data/log_data_providers.dart'; +import 'package:hiddify/features/log/model/log_level.dart'; +import 'package:hiddify/features/log/overview/logs_overview_notifier.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:sliver_tools/sliver_tools.dart'; -class LogsPage extends HookConsumerWidget with PresLogger { - const LogsPage({super.key}); +class LogsOverviewPage extends HookConsumerWidget with PresLogger { + const LogsOverviewPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final t = ref.watch(translationsProvider); - final state = ref.watch(logsNotifierProvider); - final notifier = ref.watch(logsNotifierProvider.notifier); + final state = ref.watch(logsOverviewNotifierProvider); + final notifier = ref.watch(logsOverviewNotifierProvider.notifier); final debug = ref.watch(debugModeNotifierProvider); - final filesEditor = ref.watch(filesEditorServiceProvider); + final pathResolver = ref.watch(logPathResolverProvider); final filterController = useTextEditingController(text: state.filter); @@ -33,8 +33,8 @@ class LogsPage extends HookConsumerWidget with PresLogger { child: Text(t.logs.shareCoreLogs), onTap: () async { await UriUtils.tryShareOrLaunchFile( - Uri.parse(filesEditor.coreLogsFile.path), - fileOrDir: filesEditor.logsDir.uri, + Uri.parse(pathResolver.coreFile().path), + fileOrDir: pathResolver.directory.uri, ); }, ), @@ -42,8 +42,8 @@ class LogsPage extends HookConsumerWidget with PresLogger { child: Text(t.logs.shareAppLogs), onTap: () async { await UriUtils.tryShareOrLaunchFile( - Uri.parse(filesEditor.appLogsFile.path), - fileOrDir: filesEditor.logsDir.uri, + Uri.parse(pathResolver.appFile().path), + fileOrDir: pathResolver.directory.uri, ); }, ), diff --git a/lib/features/log/overview/logs_overview_state.dart b/lib/features/log/overview/logs_overview_state.dart new file mode 100644 index 00000000..abc47ca5 --- /dev/null +++ b/lib/features/log/overview/logs_overview_state.dart @@ -0,0 +1,18 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:hiddify/features/log/model/log_entity.dart'; +import 'package:hiddify/features/log/model/log_level.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'logs_overview_state.freezed.dart'; + +@freezed +class LogsOverviewState with _$LogsOverviewState { + const LogsOverviewState._(); + + const factory LogsOverviewState({ + @Default(AsyncLoading()) AsyncValue> logs, + @Default(false) bool paused, + @Default("") String filter, + LogLevel? levelFilter, + }) = _LogsOverviewState; +} diff --git a/lib/features/logs/notifier/logs_state.dart b/lib/features/logs/notifier/logs_state.dart deleted file mode 100644 index 4318870a..00000000 --- a/lib/features/logs/notifier/logs_state.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:hiddify/domain/singbox/singbox.dart'; -import 'package:riverpod_annotation/riverpod_annotation.dart'; - -part 'logs_state.freezed.dart'; - -@freezed -class LogsState with _$LogsState { - const LogsState._(); - - const factory LogsState({ - @Default(AsyncLoading()) AsyncValue> logs, - @Default(false) bool paused, - @Default("") String filter, - LogLevel? levelFilter, - }) = _LogsState; -} diff --git a/lib/features/logs/notifier/notifier.dart b/lib/features/logs/notifier/notifier.dart deleted file mode 100644 index 69135d86..00000000 --- a/lib/features/logs/notifier/notifier.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'logs_notifier.dart'; -export 'logs_state.dart'; diff --git a/lib/features/logs/view/view.dart b/lib/features/logs/view/view.dart deleted file mode 100644 index 2982c609..00000000 --- a/lib/features/logs/view/view.dart +++ /dev/null @@ -1 +0,0 @@ -export 'logs_page.dart'; diff --git a/lib/features/settings/view/config_options_page.dart b/lib/features/settings/view/config_options_page.dart index a4064fe2..50899b71 100644 --- a/lib/features/settings/view/config_options_page.dart +++ b/lib/features/settings/view/config_options_page.dart @@ -4,6 +4,7 @@ import 'package:gap/gap.dart'; import 'package:hiddify/core/core_providers.dart'; import 'package:hiddify/data/repository/config_options_store.dart'; import 'package:hiddify/domain/singbox/singbox.dart'; +import 'package:hiddify/features/log/model/log_level.dart'; import 'package:hiddify/features/settings/widgets/widgets.dart'; import 'package:hiddify/utils/utils.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; diff --git a/lib/features/system_tray/system_tray_controller.dart b/lib/features/system_tray/system_tray_controller.dart index c230fb9f..04108033 100644 --- a/lib/features/system_tray/system_tray_controller.dart +++ b/lib/features/system_tray/system_tray_controller.dart @@ -41,7 +41,7 @@ class SystemTrayController extends _$SystemTrayController final destinations = <(String label, String location)>[ (t.home.pageTitle, const HomeRoute().location), (t.proxies.pageTitle, const ProxiesRoute().location), - (t.logs.pageTitle, const LogsRoute().location), + (t.logs.pageTitle, const LogsOverviewRoute().location), (t.settings.pageTitle, const SettingsRoute().location), (t.about.pageTitle, const AboutRoute().location), ]; diff --git a/lib/services/files_editor_service.dart b/lib/services/files_editor_service.dart index 9de8515e..86bf47c3 100644 --- a/lib/services/files_editor_service.dart +++ b/lib/services/files_editor_service.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:hiddify/services/platform_services.dart'; import 'package:hiddify/utils/utils.dart'; -import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; typedef Directories = ({ @@ -19,10 +18,6 @@ class FilesEditorService with InfraLogger { late final Directories dirs; Directory get workingDir => dirs.workingDir; - Directory get logsDir => dirs.workingDir; - - File get appLogsFile => File(p.join(logsDir.path, "app.log")); - File get coreLogsFile => File(p.join(logsDir.path, "box.log")); Future init() async { dirs = await platformServices.getPaths().getOrElse( @@ -40,18 +35,6 @@ class FilesEditorService with InfraLogger { if (!await dirs.workingDir.exists()) { await dirs.workingDir.create(recursive: true); } - - if (await appLogsFile.exists()) { - await appLogsFile.writeAsString(""); - } else { - await appLogsFile.create(recursive: true); - } - - if (await coreLogsFile.exists()) { - await coreLogsFile.writeAsString(""); - } else { - await coreLogsFile.create(recursive: true); - } } static Future getDatabaseDirectory() async {