From cb35c400f99b7cc77b157af634b1c5c497208202 Mon Sep 17 00:00:00 2001 From: xkeyC <3334969096@qq.com> Date: Thu, 8 May 2025 23:16:27 +0800 Subject: [PATCH] feat: add listSortReverse option to ToolsLogAnalyze provider --- lib/app.g.dart | 2 +- lib/ui/nav/nav_state.g.dart | 2 +- .../log_analyze_ui/log_analyze_provider.dart | 50 +++++++++++-------- .../log_analyze_provider.g.dart | 31 ++++++++++-- .../tools/log_analyze_ui/log_analyze_ui.dart | 50 +++++++------------ 5 files changed, 75 insertions(+), 60 deletions(-) diff --git a/lib/app.g.dart b/lib/app.g.dart index b097aa9..42b9d9b 100644 --- a/lib/app.g.dart +++ b/lib/app.g.dart @@ -22,7 +22,7 @@ final routerProvider = AutoDisposeProvider.internal( @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element typedef RouterRef = AutoDisposeProviderRef; -String _$appGlobalModelHash() => r'eb06413ab3a70f26712d897cee745ee62e89e75e'; +String _$appGlobalModelHash() => r'4e372bc744903960e4e7b146dbb394ded15e2c18'; /// See also [AppGlobalModel]. @ProviderFor(AppGlobalModel) diff --git a/lib/ui/nav/nav_state.g.dart b/lib/ui/nav/nav_state.g.dart index d6da236..5ae1bc3 100644 --- a/lib/ui/nav/nav_state.g.dart +++ b/lib/ui/nav/nav_state.g.dart @@ -6,7 +6,7 @@ part of 'nav_state.dart'; // RiverpodGenerator // ************************************************************************** -String _$navHash() => r'2019b3f675fbaec4be794049d900bf2dcc8d5e37'; +String _$navHash() => r'00c4da8fdd37214cda179a81ece3676add7aab53'; /// See also [Nav]. @ProviderFor(Nav) diff --git a/lib/ui/tools/log_analyze_ui/log_analyze_provider.dart b/lib/ui/tools/log_analyze_ui/log_analyze_provider.dart index 426397d..9a8a1d2 100644 --- a/lib/ui/tools/log_analyze_ui/log_analyze_provider.dart +++ b/lib/ui/tools/log_analyze_ui/log_analyze_provider.dart @@ -38,11 +38,10 @@ class LogAnalyzeLineData with _$LogAnalyzeLineData { @riverpod class ToolsLogAnalyze extends _$ToolsLogAnalyze { - static const String unknownValue = ""; - + @override - Future> build(String gameInstallPath) async { + Future> build(String gameInstallPath, bool listSortReverse) async { final logFile = File("$gameInstallPath/Game.log"); debugPrint("[ToolsLogAnalyze] logFile: ${logFile.absolute.path}"); if (gameInstallPath.isEmpty || !(await logFile.exists())) { @@ -99,7 +98,7 @@ class ToolsLogAnalyze extends _$ToolsLogAnalyze { } final lastLineDateTime = - _gameStartTime != null ? _getLogLineDateTime(logLines.lastWhere((e) => e.startsWith("<20"))) : null; + _gameStartTime != null ? _getLogLineDateTime(logLines.lastWhere((e) => e.startsWith("<20"))) : null; // 检查${S.current.log_analyzer_filter_game_crash}行号 if (_gameCrashLineNumber > 0) { @@ -173,9 +172,13 @@ class ToolsLogAnalyze extends _$ToolsLogAnalyze { debugPrint("[ToolsLogAnalyze] logFile change: ${change.type}"); switch (change.type) { case ChangeType.MODIFY: - // 移除${S.current.log_analyzer_filter_statistics} + // 移除${S.current.log_analyzer_filter_statistics} final newList = state.value?.where((e) => e.type != "statistics").toList(); - state = AsyncData(newList ?? []); + if (listSortReverse) { + state = AsyncData(newList?.reversed.toList() ?? []); + } else { + state = AsyncData(newList ?? []); + } return _launchLogAnalyze(logFile, startLine: _currentLineNumber); case ChangeType.ADD: case ChangeType.REMOVE: @@ -217,19 +220,19 @@ class ToolsLogAnalyze extends _$ToolsLogAnalyze { if (baseEvent != null) { switch (baseEvent) { case "AccountLoginCharacterStatus_Character": - // 角色登录 + // 角色登录 return _logGetCharacterName(line); case "FatalCollision": - // 载具${S.current.log_analyzer_filter_fatal_collision} + // 载具${S.current.log_analyzer_filter_fatal_collision} return _logGetFatalCollision(line); case "Vehicle Destruction": - // ${S.current.log_analyzer_filter_vehicle_damaged} + // ${S.current.log_analyzer_filter_vehicle_damaged} return _logGetVehicleDestruction(line); case "Actor Death": - // ${S.current.log_analyzer_filter_character_death} + // ${S.current.log_analyzer_filter_character_death} return _logGetActorDeath(line); case "RequestLocationInventory": - // 请求${S.current.log_analyzer_filter_local_inventory} + // 请求${S.current.log_analyzer_filter_local_inventory} return _logGetRequestLocationInventory(line); } } @@ -253,7 +256,12 @@ class ToolsLogAnalyze extends _$ToolsLogAnalyze { // 追加结果到 state final currentState = state.value; if (currentState != null) { - state = AsyncData([...currentState, data]); + if (listSortReverse) { + // 反向排序 + state = AsyncData([data, ...currentState]); + } else { + state = AsyncData([...currentState, data]); + } } else { state = AsyncData([data]); } @@ -272,7 +280,7 @@ class ToolsLogAnalyze extends _$ToolsLogAnalyze { } final _gameLoadingRegExp = - RegExp(r'<[^>]+>\s+Loading screen for\s+(\w+)\s+:\s+SC_Frontend closed after\s+(\d+\.\d+)\s+seconds'); + RegExp(r'<[^>]+>\s+Loading screen for\s+(\w+)\s+:\s+SC_Frontend closed after\s+(\d+\.\d+)\s+seconds'); (String, String)? _logGetGameLoading(String line) { final match = _gameLoadingRegExp.firstMatch(line); @@ -339,10 +347,10 @@ class ToolsLogAnalyze extends _$ToolsLogAnalyze { LogAnalyzeLineData? _logGetVehicleDestruction(String line) { final pattern = RegExp(r"Vehicle\s+'([^']+)'.*?" // 载具型号 - r"in zone\s+'([^']+)'.*?" // Zone - r"destroy level \d+ to (\d+).*?" // 损毁等级 - r"caused by\s+'([^']+)'" // 责任方 - ); + r"in zone\s+'([^']+)'.*?" // Zone + r"destroy level \d+ to (\d+).*?" // 损毁等级 + r"caused by\s+'([^']+)'" // 责任方 + ); final match = pattern.firstMatch(line); if (match != null) { final vehicleModel = match.group(1) ?? unknownValue; @@ -378,10 +386,10 @@ class ToolsLogAnalyze extends _$ToolsLogAnalyze { LogAnalyzeLineData? _logGetActorDeath(String line) { final pattern = RegExp(r"CActor::Kill: '([^']+)'.*?" // 受害者ID - r"in zone '([^']+)'.*?" // 死亡位置区域 - r"killed by '([^']+)'.*?" // 击杀者ID - r"with damage type '([^']+)'" // 伤害类型 - ); + r"in zone '([^']+)'.*?" // 死亡位置区域 + r"killed by '([^']+)'.*?" // 击杀者ID + r"with damage type '([^']+)'" // 伤害类型 + ); final match = pattern.firstMatch(line); if (match != null) { diff --git a/lib/ui/tools/log_analyze_ui/log_analyze_provider.g.dart b/lib/ui/tools/log_analyze_ui/log_analyze_provider.g.dart index 7932242..d71bfd5 100644 --- a/lib/ui/tools/log_analyze_ui/log_analyze_provider.g.dart +++ b/lib/ui/tools/log_analyze_ui/log_analyze_provider.g.dart @@ -6,7 +6,7 @@ part of 'log_analyze_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$toolsLogAnalyzeHash() => r'cc8aed5b4eeb6c8feb35c59ef484dc61c92a5549'; +String _$toolsLogAnalyzeHash() => r'5666c3f882e22e2192593629164bc53f8ce4aabe'; /// Copied from Dart SDK class _SystemHash { @@ -32,9 +32,11 @@ class _SystemHash { abstract class _$ToolsLogAnalyze extends BuildlessAutoDisposeAsyncNotifier> { late final String gameInstallPath; + late final bool listSortReverse; FutureOr> build( String gameInstallPath, + bool listSortReverse, ); } @@ -51,9 +53,11 @@ class ToolsLogAnalyzeFamily /// See also [ToolsLogAnalyze]. ToolsLogAnalyzeProvider call( String gameInstallPath, + bool listSortReverse, ) { return ToolsLogAnalyzeProvider( gameInstallPath, + listSortReverse, ); } @@ -63,6 +67,7 @@ class ToolsLogAnalyzeFamily ) { return call( provider.gameInstallPath, + provider.listSortReverse, ); } @@ -87,8 +92,11 @@ class ToolsLogAnalyzeProvider extends AutoDisposeAsyncNotifierProviderImpl< /// See also [ToolsLogAnalyze]. ToolsLogAnalyzeProvider( String gameInstallPath, + bool listSortReverse, ) : this._internal( - () => ToolsLogAnalyze()..gameInstallPath = gameInstallPath, + () => ToolsLogAnalyze() + ..gameInstallPath = gameInstallPath + ..listSortReverse = listSortReverse, from: toolsLogAnalyzeProvider, name: r'toolsLogAnalyzeProvider', debugGetCreateSourceHash: @@ -99,6 +107,7 @@ class ToolsLogAnalyzeProvider extends AutoDisposeAsyncNotifierProviderImpl< allTransitiveDependencies: ToolsLogAnalyzeFamily._allTransitiveDependencies, gameInstallPath: gameInstallPath, + listSortReverse: listSortReverse, ); ToolsLogAnalyzeProvider._internal( @@ -109,9 +118,11 @@ class ToolsLogAnalyzeProvider extends AutoDisposeAsyncNotifierProviderImpl< required super.debugGetCreateSourceHash, required super.from, required this.gameInstallPath, + required this.listSortReverse, }) : super.internal(); final String gameInstallPath; + final bool listSortReverse; @override FutureOr> runNotifierBuild( @@ -119,6 +130,7 @@ class ToolsLogAnalyzeProvider extends AutoDisposeAsyncNotifierProviderImpl< ) { return notifier.build( gameInstallPath, + listSortReverse, ); } @@ -127,13 +139,16 @@ class ToolsLogAnalyzeProvider extends AutoDisposeAsyncNotifierProviderImpl< return ProviderOverride( origin: this, override: ToolsLogAnalyzeProvider._internal( - () => create()..gameInstallPath = gameInstallPath, + () => create() + ..gameInstallPath = gameInstallPath + ..listSortReverse = listSortReverse, from: from, name: null, dependencies: null, allTransitiveDependencies: null, debugGetCreateSourceHash: null, gameInstallPath: gameInstallPath, + listSortReverse: listSortReverse, ), ); } @@ -147,13 +162,15 @@ class ToolsLogAnalyzeProvider extends AutoDisposeAsyncNotifierProviderImpl< @override bool operator ==(Object other) { return other is ToolsLogAnalyzeProvider && - other.gameInstallPath == gameInstallPath; + other.gameInstallPath == gameInstallPath && + other.listSortReverse == listSortReverse; } @override int get hashCode { var hash = _SystemHash.combine(0, runtimeType.hashCode); hash = _SystemHash.combine(hash, gameInstallPath.hashCode); + hash = _SystemHash.combine(hash, listSortReverse.hashCode); return _SystemHash.finish(hash); } @@ -165,6 +182,9 @@ mixin ToolsLogAnalyzeRef on AutoDisposeAsyncNotifierProviderRef> { /// The parameter `gameInstallPath` of this provider. String get gameInstallPath; + + /// The parameter `listSortReverse` of this provider. + bool get listSortReverse; } class _ToolsLogAnalyzeProviderElement @@ -175,6 +195,9 @@ class _ToolsLogAnalyzeProviderElement @override String get gameInstallPath => (origin as ToolsLogAnalyzeProvider).gameInstallPath; + @override + bool get listSortReverse => + (origin as ToolsLogAnalyzeProvider).listSortReverse; } // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/ui/tools/log_analyze_ui/log_analyze_ui.dart b/lib/ui/tools/log_analyze_ui/log_analyze_ui.dart index 838e557..c983dbc 100644 --- a/lib/ui/tools/log_analyze_ui/log_analyze_ui.dart +++ b/lib/ui/tools/log_analyze_ui/log_analyze_ui.dart @@ -15,14 +15,13 @@ class ToolsLogAnalyzeDialogUI extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final selectedPath = useState(appState.gameInstallPaths.firstOrNull); - final logResp = ref.watch(toolsLogAnalyzeProvider(selectedPath.value ?? "")); + final listSortReverse = useState(false); + final provider = toolsLogAnalyzeProvider(selectedPath.value ?? "", listSortReverse.value); + final logResp = ref.watch(provider); final searchText = useState(""); final searchType = useState(null); - final lastListSize = useState(0); - final listCtrl = useScrollController(); - _diffData(logResp, lastListSize, listCtrl); return ScaffoldPage( content: Column( children: [ @@ -56,7 +55,7 @@ class ToolsLogAnalyzeDialogUI extends HookConsumerWidget { child: const Icon(FluentIcons.refresh), ), onPressed: () { - ref.invalidate(toolsLogAnalyzeProvider(selectedPath.value ?? "")); + ref.invalidate(provider); }, ), ], @@ -81,6 +80,7 @@ class ToolsLogAnalyzeDialogUI extends HookConsumerWidget { }, ), ), + SizedBox(width: 6), // 筛选 ComboBox ComboBox( @@ -97,6 +97,18 @@ class ToolsLogAnalyzeDialogUI extends HookConsumerWidget { searchType.value = value; }, ), + const SizedBox(width: 6), + // 倒序 Icon + Button( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 6), + child: Transform.rotate( + angle: listSortReverse.value ? 3.14 : 0, child: const Icon(FluentIcons.sort_lines)), + ), + onPressed: () { + listSortReverse.value = !listSortReverse.value; + }, + ), ], ), ), @@ -226,32 +238,4 @@ class ToolsLogAnalyzeDialogUI extends HookConsumerWidget { return Colors.white.withValues(alpha: .06); } } - - void _diffData( - AsyncValue> logResp, ValueNotifier lastListSize, ScrollController listCtrl) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (lastListSize.value == 0) { - lastListSize.value = logResp.value?.length ?? 0; - } else { - // 判断当前内容是否大于一页 - if (listCtrl.position.maxScrollExtent > listCtrl.position.viewportDimension) { - // 判断当前列表是否在底部 - if (listCtrl.position.pixels >= listCtrl.position.maxScrollExtent) { - // 如果在底部,判断数据是否有变化 - if ((logResp.value?.length ?? 0) > lastListSize.value) { - Future.delayed(Duration(milliseconds: 100)).then((_) { - listCtrl.jumpTo(listCtrl.position.maxScrollExtent); - }); - lastListSize.value = logResp.value?.length ?? 0; - } else { - // 回顶部 - if (listCtrl.position.pixels > 0) { - listCtrl.jumpTo(0); - } - } - } - } - } - }); - } }