diff --git a/images/decode_xlog_file.py b/images/decode_xlog_file.py new file mode 100644 index 0000000..ce13fb6 --- /dev/null +++ b/images/decode_xlog_file.py @@ -0,0 +1,169 @@ +#!/usr/bin/python + +import sys +import os +import glob +import zlib +import struct +import binascii +import traceback + + +MAGIC_NO_COMPRESS_START = 0x03 +MAGIC_NO_COMPRESS_START1 = 0x06 +MAGIC_NO_COMPRESS_NO_CRYPT_START = 0x08 +MAGIC_COMPRESS_START = 0x04 +MAGIC_COMPRESS_START1 = 0x05 +MAGIC_COMPRESS_START2 = 0x07 +MAGIC_COMPRESS_NO_CRYPT_START = 0x09 + +MAGIC_END = 0x00 + +lastseq = 0 + + +def IsGoodLogBuffer(_buffer, _offset, count): + + if _offset == len(_buffer): return (True, '') + + magic_start = _buffer[_offset] + if MAGIC_NO_COMPRESS_START==magic_start or MAGIC_COMPRESS_START==magic_start or MAGIC_COMPRESS_START1==magic_start: + crypt_key_len = 4 + elif MAGIC_COMPRESS_START2==magic_start or MAGIC_NO_COMPRESS_START1==magic_start or MAGIC_NO_COMPRESS_NO_CRYPT_START==magic_start or MAGIC_COMPRESS_NO_CRYPT_START==magic_start: + crypt_key_len = 64 + else: + return (False, '_buffer[%d]:%d != MAGIC_NUM_START'%(_offset, _buffer[_offset])) + + headerLen = 1 + 2 + 1 + 1 + 4 + crypt_key_len + + if _offset + headerLen + 1 + 1 > len(_buffer): return (False, 'offset:%d > len(buffer):%d'%(_offset, len(_buffer))) + length = struct.unpack_from("I", _buffer[_offset+headerLen-4-crypt_key_len: _offset+headerLen-4-crypt_key_len+4])[0] + if _offset + headerLen + length + 1 > len(_buffer): return (False, 'log length:%d, end pos %d > len(buffer):%d'%(length, _offset + headerLen + length + 1, len(_buffer))) + if MAGIC_END!=_buffer[_offset + headerLen + length]: return (False, 'log length:%d, buffer[%d]:%d != MAGIC_END'%(length, _offset + headerLen + length, _buffer[_offset + headerLen + length])) + + + if (1>=count): return (True, '') + else: return IsGoodLogBuffer(_buffer, _offset+headerLen+length+1, count-1) + + +def GetLogStartPos(_buffer, _count): + offset = 0 + while True: + if offset >= len(_buffer): break + + if MAGIC_NO_COMPRESS_START==_buffer[offset] or MAGIC_NO_COMPRESS_START1==_buffer[offset] or MAGIC_COMPRESS_START==_buffer[offset] or MAGIC_COMPRESS_START1==_buffer[offset] or MAGIC_COMPRESS_START2==_buffer[offset] or MAGIC_COMPRESS_NO_CRYPT_START==_buffer[offset] or MAGIC_NO_COMPRESS_NO_CRYPT_START==_buffer[offset]: + if IsGoodLogBuffer(_buffer, offset, _count)[0]: return offset + offset+=1 + + return -1 + +def DecodeBuffer(_buffer, _offset, _outbuffer): + + if _offset >= len(_buffer): return -1 + # if _offset + 1 + 4 + 1 + 1 > len(_buffer): return -1 + ret = IsGoodLogBuffer(_buffer, _offset, 1) + if not ret[0]: + fixpos = GetLogStartPos(_buffer[_offset:], 1) + if -1==fixpos: + return -1 + else: + _outbuffer.extend("[F]decode_log_file.py decode error len=%d, result:%s \n"%(fixpos, ret[1])) + _offset += fixpos + + magic_start = _buffer[_offset] + if MAGIC_NO_COMPRESS_START==magic_start or MAGIC_COMPRESS_START==magic_start or MAGIC_COMPRESS_START1==magic_start: + crypt_key_len = 4 + elif MAGIC_COMPRESS_START2==magic_start or MAGIC_NO_COMPRESS_START1==magic_start or MAGIC_NO_COMPRESS_NO_CRYPT_START==magic_start or MAGIC_COMPRESS_NO_CRYPT_START==magic_start: + crypt_key_len = 64 + else: + _outbuffer.extend('in DecodeBuffer _buffer[%d]:%d != MAGIC_NUM_START'%(_offset, magic_start)) + return -1 + + headerLen = 1 + 2 + 1 + 1 + 4 + crypt_key_len + length = struct.unpack_from("I", _buffer[_offset+headerLen-4-crypt_key_len: _offset+headerLen-4-crypt_key_len+4])[0] + tmpbuffer = bytearray(length) + + seq = struct.unpack_from("H", _buffer[_offset+headerLen-4-crypt_key_len-2-2: _offset+headerLen-4-crypt_key_len-2])[0] + begin_hour = struct.unpack_from("c", _buffer[_offset+headerLen-4-crypt_key_len-1-1: _offset+headerLen-4-crypt_key_len-1])[0] + end_hour = struct.unpack_from("c", _buffer[_offset+headerLen-4-crypt_key_len-1: _offset+headerLen-4-crypt_key_len])[0] + + global lastseq + if seq != 0 and seq != 1 and lastseq != 0 and seq != (lastseq+1): + _outbuffer.extend("[F]decode_log_file.py log seq:%d-%d is missing\n" %(lastseq+1, seq-1)) + + if seq != 0: + lastseq = seq + + tmpbuffer[:] = _buffer[_offset+headerLen:_offset+headerLen+length] + + try: + decompressor = zlib.decompressobj(-zlib.MAX_WBITS) + + if MAGIC_NO_COMPRESS_START1==_buffer[_offset] or MAGIC_COMPRESS_START2==_buffer[_offset]: + print("use wrong decode script") + elif MAGIC_COMPRESS_START==_buffer[_offset] or MAGIC_COMPRESS_NO_CRYPT_START==_buffer[_offset]: + tmpbuffer = decompressor.decompress(tmpbuffer) + elif MAGIC_COMPRESS_START1==_buffer[_offset]: + decompress_data = bytearray() + while len(tmpbuffer) > 0: + single_log_len = struct.unpack_from("H", buffer(tmpbuffer, 0, 2))[0] + decompress_data.extend(tmpbuffer[2:single_log_len+2]) + tmpbuffer[:] = tmpbuffer[single_log_len+2:len(tmpbuffer)] + + tmpbuffer = decompressor.decompress(str(decompress_data)) + + else: + pass + + # _outbuffer.extend('seq:%d, hour:%d-%d len:%d decompress:%d\n' %(seq, ord(begin_hour), ord(end_hour), length, len(tmpbuffer))) + except Exception as e: + traceback.print_exc() + _outbuffer.extend("[F]decode_log_file.py decompress err, ".encode() + str(e).encode() + b"\n") + return _offset+headerLen+length+1 + + _outbuffer.extend(tmpbuffer) + + return _offset+headerLen+length+1 + + +def ParseFile(_file, _outfile): + fp = open(_file, "rb") + _buffer = bytearray(os.path.getsize(_file)) + fp.readinto(_buffer) + fp.close() + startpos = GetLogStartPos(_buffer, 2) + if -1==startpos: + return + + outbuffer = bytearray() + + while True: + startpos = DecodeBuffer(_buffer, startpos, outbuffer) + if -1==startpos: break; + + if 0==len(outbuffer): return + + fpout = open(_outfile, "wb") + fpout.write(outbuffer) + fpout.close() + +def main(args): + global lastseq + + if 1==len(args): + if os.path.isdir(args[0]): + filelist = glob.glob(args[0] + "/*.xlog") + for filepath in filelist: + lastseq = 0 + ParseFile(filepath, filepath+".log") + else: ParseFile(args[0], args[0]+".log") + elif 2==len(args): + ParseFile(args[0], args[1]) + else: + filelist = glob.glob("*.xlog") + for filepath in filelist: + lastseq = 0 + ParseFile(filepath, filepath+".log") + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/lib/controller/xlog_info_controller.dart b/lib/controller/xlog_info_controller.dart index c006fa2..668ebe6 100644 --- a/lib/controller/xlog_info_controller.dart +++ b/lib/controller/xlog_info_controller.dart @@ -70,8 +70,10 @@ class XlogInfoController extends GetxController { return; } + final privateKey = this.cryptMd5.value.trim(); + if (this.isEnableCrypt.value == true && - (this.cryptMd5.value.isEmpty || this.cryptMd5.value.length != 64)) { + (privateKey.isEmpty || privateKey.length != 64)) { print("private key is empty"); showToast("Private Key 为空或长度不对(64位)", textPadding: EdgeInsets.all(15)); vm.updateStatus(XlogInfoStatus.fail); @@ -88,44 +90,48 @@ class XlogInfoController extends GetxController { return; } - var execFileName = Platform.isWindows ? "xlog-decoder.exe" : "xlog-decoder"; - var pyPath = path.joinAll([ - _assetsDir.path, - execFileName, - ]); - if (this.isEnableCrypt.value == false) { - pyPath = path.joinAll([_assetsDir.path, execFileName]); - } + final outputPath = path.join( + savePath.value, + "${vm.file.fileName}.log", + ); + + final execFileName = + Platform.isWindows ? "xlog-decoder.exe" : "xlog-decoder"; + final execPath = path.join(_assetsDir.path, execFileName); ProcessResult process; if (this.isEnableCrypt.value == true) { //加密 debugPrint("执行带加密key命令"); - process = await Process.run( - pyPath, - [ - "decode", - "-i", - vm.file.path, - "-p", - this.cryptMd5.value, - "-o", - "${vm.file.path}.log" - ], - ); + process = await Process.run(execPath, [ + "decode", + "-i", + vm.file.path, + "-p", + privateKey.toLowerCase(), + "-o", + outputPath, + ]); } else { //不加密 debugPrint("执行不加密命令"); - process = await Process.run( - pyPath, - [ - "decode", - "-i", - vm.file.path, - "-o", - "${vm.file.path}.log" - ], - ); + process = await Process.run(execPath, [ + "decode", + "-i", + vm.file.path, + "-o", + outputPath, + ]); + } + + final stdoutMsg = process.stdout?.toString().trim() ?? ''; + final stderrMsg = process.stderr?.toString().trim() ?? ''; + debugPrint("xlog-decoder exitCode: ${process.exitCode}"); + if (stdoutMsg.isNotEmpty) { + debugPrint("xlog-decoder stdout: $stdoutMsg"); + } + if (stderrMsg.isNotEmpty) { + debugPrint("xlog-decoder stderr: $stderrMsg"); } if (process.exitCode != 0) { @@ -136,22 +142,25 @@ class XlogInfoController extends GetxController { return; } - var file = File(vm.file.path + ".log"); + var file = File(outputPath); var isExist = await file.exists(); if (isExist) { - Platform.isWindows - ? await Process.run("xcopy", [ - file.path, - savePath.value, - "/y", - ]) - : await Process.run("cp", [ - "-f", - file.path, - savePath.value, - ]); - vm.saveFile = File(path.joinAll([savePath.value, file.fileName])); + final fileLength = await file.length(); + if (fileLength == 0) { + await file.delete().catchError((_) {}); + if (this.isEnableCrypt.value == false && + await _decodeWithPython(vm.file.path, outputPath)) { + file = File(outputPath); + } else { + showToast("Xlog解析失败:输出内容为空,请检查输入文件与私钥", + textPadding: EdgeInsets.all(15)); + vm.updateStatus(XlogInfoStatus.fail); + taskList.refresh(); + return; + } + } + vm.saveFile = file; vm.updateStatus(XlogInfoStatus.success); taskList.refresh(); } else { @@ -209,4 +218,68 @@ class XlogInfoController extends GetxController { return null; } } + + Future _decodeWithPython(String inputPath, String outputPath) async { + final scriptPath = path.join(_assetsDir.path, "decode_xlog_file.py"); + final pythonCandidates = Platform.isWindows + ? ["python", "py"] + : ["python3", "python"]; + debugPrint("尝试使用 Python 脚本解码: $scriptPath"); + + ProcessResult? result; + String? usedCmd; + try { + for (final cmd in pythonCandidates) { + try { + debugPrint("尝试执行 Python 命令: $cmd"); + result = await Process.run( + cmd, + [ + scriptPath, + inputPath, + outputPath, + ], + ); + usedCmd = cmd; + break; + } on ProcessException catch (e) { + debugPrint("Python 命令 $cmd 不可用: $e"); + continue; + } + } + if (result == null) { + if (Platform.isWindows) { + showToast("未找到 Python 环境,请安装 Python 并将其加入 PATH", + textPadding: EdgeInsets.all(15)); + } + return false; + } + final stdoutMsg = result.stdout?.toString().trim() ?? ''; + final stderrMsg = result.stderr?.toString().trim() ?? ''; + debugPrint( + "python decode (${usedCmd ?? 'unknown'}) exitCode: ${result.exitCode}"); + if (stdoutMsg.isNotEmpty) { + debugPrint("python decode stdout: $stdoutMsg"); + } + if (stderrMsg.isNotEmpty) { + debugPrint("python decode stderr: $stderrMsg"); + } + if (result.exitCode != 0) { + return false; + } + final file = File(outputPath); + if (!await file.exists()) { + return false; + } + final length = await file.length(); + if (length == 0) { + await file.delete().catchError((_) {}); + return false; + } + return true; + } catch (e) { + debugPrint("python decode error: $e"); + return false; + } + } } diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart new file mode 100644 index 0000000..0caef73 --- /dev/null +++ b/lib/generated/assets.dart @@ -0,0 +1,13 @@ +///This file is automatically generated. DO NOT EDIT, all your changes would be lost. +class Assets { + Assets._(); + + static const String imagesAppIcon = 'images/app_icon.png'; + static const String imagesDecodeXlogFile = 'images/decode_xlog_file.py'; + static const String imagesError = 'images/error.png'; + static const String imagesFolder = 'images/folder.png'; + static const String imagesSuccess = 'images/success.png'; + static const String imagesXlogDecoder = 'images/xlog-decoder'; + static const String marsXlogDecoderGuiImagesXlogDecoder = 'images/xlog-decoder.exe'; + +} diff --git a/lib/xlog_page/xlog_page.dart b/lib/xlog_page/xlog_page.dart index 739dafe..70f4e08 100644 --- a/lib/xlog_page/xlog_page.dart +++ b/lib/xlog_page/xlog_page.dart @@ -42,13 +42,14 @@ class _XlogPageState extends State { if (savePath == null || savePath.isEmpty) { try { var provider = PathProviderUtil.provider(); - String? path = await provider.getDownloadsPath(); - print("get down path $path"); - if (path == null) return; - final filePath = - path + PathProviderUtil.platformDirectoryLine() + "XlogOutput"; - pre.setString(KXlogSavePathKey, filePath); - controller.savePath.value = filePath; + final downloadsPath = await provider.getDownloadsPath(); + if (downloadsPath != null && downloadsPath.isNotEmpty) { + print("get down path $downloadsPath"); + final separator = PathProviderUtil.platformDirectoryLine(); + final filePath = downloadsPath + separator + "XlogOutput"; + pre.setString(KXlogSavePathKey, filePath); + controller.savePath.value = filePath; + } } catch (e) {} } else { controller.savePath.value = savePath; diff --git a/macos/Podfile b/macos/Podfile index 049abe2..9ec46f8 100644 --- a/macos/Podfile +++ b/macos/Podfile @@ -1,4 +1,4 @@ -platform :osx, '10.14' +platform :osx, '10.15' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/macos/Podfile.lock b/macos/Podfile.lock index e273b70..ec8e5a1 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -17,7 +17,7 @@ DEPENDENCIES: - FlutterMacOS (from `Flutter/ephemeral`) - native_context_menu (from `Flutter/ephemeral/.symlinks/plugins/native_context_menu/macos`) - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) - - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos`) + - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`) - window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`) EXTERNAL SOURCES: @@ -30,18 +30,18 @@ EXTERNAL SOURCES: path_provider_macos: :path: Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos shared_preferences_foundation: - :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/macos + :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin window_manager: :path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos SPEC CHECKSUMS: - desktop_drop: 69eeff437544aa619c8db7f4481b3a65f7696898 - FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - native_context_menu: 8b710e17c5962cf3f005b805eb97cce668b3839a - path_provider_macos: 160cab0d5461f0c0e02995469a98f24bdb9a3f1f - shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c - window_manager: 02776e5a599084cd4576e27a42dd5ec6f49132cf + desktop_drop: e0b672a7d84c0a6cbc378595e82cdb15f2970a43 + FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1 + native_context_menu: bdd0ebd36a94cbb869111d7d057771a1c90c450a + path_provider_macos: 982456d73d6592ced25ed951ae1a32f95a82049f + shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb + window_manager: cca01c8096ad7e5cabeec56d2d987dca79ba658b -PODFILE CHECKSUM: 353c8bcc5d5b0994e508d035b5431cfe18c1dea7 +PODFILE CHECKSUM: 0d3963a09fc94f580682bd88480486da345dc3f0 -COCOAPODS: 1.11.3 +COCOAPODS: 1.16.2 diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 576bbd6..310dfc1 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -202,7 +202,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0920; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 33CC10EC2044A3C60003C045 = { @@ -404,7 +404,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -419,11 +419,12 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Manual; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 4L75765R87; - ENABLE_HARDENED_RUNTIME = YES; + ENABLE_HARDENED_RUNTIME = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -486,7 +487,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -533,7 +534,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -548,11 +549,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 4L75765R87; - ENABLE_HARDENED_RUNTIME = YES; + ENABLE_HARDENED_RUNTIME = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -571,12 +574,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + CODE_SIGN_STYLE = Manual; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = 4L75765R87; - ENABLE_HARDENED_RUNTIME = YES; + ENABLE_HARDENED_RUNTIME = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index d93e9cb..48305b0 100644 --- a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift index d53ef64..b3c1761 100644 --- a/macos/Runner/AppDelegate.swift +++ b/macos/Runner/AppDelegate.swift @@ -1,9 +1,13 @@ import Cocoa import FlutterMacOS -@NSApplicationMain +@main class AppDelegate: FlutterAppDelegate { override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { return true } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } } diff --git a/pubspec.lock b/pubspec.lock index 3441a77..94d8656 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,58 +5,58 @@ packages: dependency: transitive description: name: async - sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" url: "https://pub.flutter-io.cn" source: hosted - version: "2.10.0" + version: "2.13.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: name: characters - sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.flutter-io.cn" source: hosted - version: "1.17.0" + version: "1.19.1" cross_file: dependency: transitive description: name: cross_file - sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9" + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" url: "https://pub.flutter-io.cn" source: hosted - version: "0.3.3+4" + version: "0.3.4+2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.5" + version: "1.0.8" desktop_drop: dependency: "direct main" description: @@ -69,18 +69,18 @@ packages: dependency: "direct main" description: name: event_bus - sha256: "44baa799834f4c803921873e7446a2add0f3efa45e101a054b1f0ab9b95f8edc" + sha256: "1a55e97923769c286d295240048fc180e7b0768902c3c2e869fe059aafa15304" url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.0" + version: "2.0.1" fake_async: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" url: "https://pub.flutter-io.cn" source: hosted - version: "1.3.1" + version: "1.3.3" ffi: dependency: transitive description: @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: file - sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.flutter-io.cn" source: hosted - version: "6.1.4" + version: "7.0.1" file_picker: dependency: "direct main" description: @@ -114,10 +114,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "96af49aa6b57c10a312106ad6f71deed5a754029c24789bbf620ba784f0bd0b0" + sha256: "306f0596590e077338312f38837f595c04f28d6cdeeac392d3d74df2f0003687" url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.14" + version: "2.0.32" flutter_test: dependency: "direct dev" description: flutter @@ -136,14 +136,30 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "4.6.5" - js: + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.flutter-io.cn" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.10" + leak_tracker_testing: dependency: transitive description: - name: js - sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" url: "https://pub.flutter-io.cn" source: hosted - version: "0.6.5" + version: "3.0.2" macos_ui: dependency: "direct main" description: @@ -156,26 +172,26 @@ packages: dependency: transitive description: name: matcher - sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.flutter-io.cn" source: hosted - version: "0.12.13" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.flutter-io.cn" source: hosted - version: "0.2.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.0" + version: "1.16.0" native_context_menu: dependency: transitive description: @@ -196,18 +212,18 @@ packages: dependency: "direct main" description: name: oktoast - sha256: fd5dd5c7dd02c41c56bdbdbc163351bd6cd59cba61c416daf255e35d1a86dce1 + sha256: f1366c5c793ddfb8f55bc6fc3e45db43c45debf173b765fb4c5ec096cbdeb84a url: "https://pub.flutter-io.cn" source: hosted - version: "3.3.1" + version: "3.4.0" path: dependency: transitive description: name: path - sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.flutter-io.cn" source: hosted - version: "1.8.2" + version: "1.9.1" path_provider: dependency: "direct main" description: @@ -219,10 +235,10 @@ packages: dependency: transitive description: name: path_provider_linux - sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.10" + version: "2.2.1" path_provider_macos: dependency: "direct main" description: @@ -234,10 +250,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.6" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -250,151 +266,159 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.flutter-io.cn" source: hosted - version: "3.1.0" + version: "3.1.6" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.4" - process: - dependency: transitive - description: - name: process - sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" - url: "https://pub.flutter-io.cn" - source: hosted - version: "4.2.4" + version: "2.1.8" provider: dependency: "direct main" description: name: provider - sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" url: "https://pub.flutter-io.cn" source: hosted - version: "6.0.5" + version: "6.1.5+1" shared_preferences: dependency: "direct main" description: name: shared_preferences - sha256: "16d3fb6b3692ad244a695c0183fca18cf81fd4b821664394a781de42386bf022" + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.5.3" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "6478c6bbbecfe9aced34c483171e90d7c078f5883558b30ec3163cf18402c749" + sha256: "34266009473bf71d748912da4bf62d439185226c03e01e2d9687bc65bbfcb713" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.4" + version: "2.4.15" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: e014107bb79d6d3297196f4f2d0db54b5d1f85b8ea8ff63b8e8b391a02700feb + sha256: "1c33a907142607c40a7542768ec9badfd16293bac51da3a4482623d15845f88b" url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.2" + version: "2.5.5" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: "9d387433ca65717bbf1be88f4d5bb18f10508917a8fa2fb02e0fd0d7479a9afa" + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.0" + version: "2.4.1" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - sha256: fb5cf25c0235df2d0640ac1b1174f6466bd311f621574997ac59018a6664548d + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.0" + version: "2.4.1" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - sha256: "74083203a8eae241e0de4a0d597dbedab3b8fef5563f33cf3c12d7e93c655ca5" + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.0" + version: "2.4.3" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: "5e588e2efef56916a3b229c3bfe81e6a525665a454519ca51dbcc4236a274173" + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" url: "https://pub.flutter-io.cn" source: hosted - version: "2.2.0" + version: "2.4.1" sky_engine: dependency: transitive description: flutter source: sdk - version: "0.0.99" + version: "0.0.0" source_span: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.flutter-io.cn" source: hosted - version: "1.9.1" + version: "1.10.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.flutter-io.cn" source: hosted - version: "1.11.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.1" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.0" + version: "1.4.1" term_glyph: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.flutter-io.cn" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.flutter-io.cn" source: hosted - version: "0.4.16" + version: "0.7.6" vector_math: dependency: transitive description: name: vector_math - sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.4" + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.flutter-io.cn" + source: hosted + version: "15.0.2" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.1" win32: dependency: transitive description: @@ -415,10 +439,10 @@ packages: dependency: transitive description: name: xdg_directories - sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1 + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.0" + version: "1.1.0" sdks: - dart: ">=2.18.0 <3.0.0" - flutter: ">=3.0.0" + dart: ">=3.9.0 <4.0.0" + flutter: ">=3.35.0"