From c3fa976b260c817fdfe3cfbec955d764acd8b85a Mon Sep 17 00:00:00 2001 From: My-Responsitories <107370289+My-Responsitories@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:36:43 +0800 Subject: [PATCH] tweaks (#1562) * opt: downloadImg use cache * opt: uin8 cast * non null ext --- .../widgets/image/network_img_layer.dart | 2 +- lib/pages/group_panel/view.dart | 2 +- .../pl_player/widgets/mpv_convert_webp.dart | 6 +- lib/utils/cache_manage.dart | 2 +- lib/utils/extension.dart | 67 ++++++++++--------- lib/utils/image_utils.dart | 64 ++++++++++++------ 6 files changed, 84 insertions(+), 59 deletions(-) diff --git a/lib/common/widgets/image/network_img_layer.dart b/lib/common/widgets/image/network_img_layer.dart index 3111e346..e7b5d8bd 100644 --- a/lib/common/widgets/image/network_img_layer.dart +++ b/lib/common/widgets/image/network_img_layer.dart @@ -80,7 +80,7 @@ class NetworkImgLayer extends StatelessWidget { if (height == null || forceUseCacheWidth || width <= height!) { memCacheWidth = width.cacheSize(context); } else { - memCacheHeight = height.cacheSize(context); + memCacheHeight = height?.cacheSize(context); } return CachedNetworkImage( imageUrl: ImageUtils.thumbnailUrl(src, quality), diff --git a/lib/pages/group_panel/view.dart b/lib/pages/group_panel/view.dart index 19084072..f4d34fa7 100644 --- a/lib/pages/group_panel/view.dart +++ b/lib/pages/group_panel/view.dart @@ -39,7 +39,7 @@ class _GroupPanelState extends State { void _query() { MemberHttp.followUpTags().then((res) { if (mounted) { - loadingState = res..dataOrNull.removeFirstWhere((e) => e.tagid == 0); + loadingState = res..dataOrNull?.removeFirstWhere((e) => e.tagid == 0); showDefaultBtn.value = tags.isEmpty; setState(() {}); } diff --git a/lib/plugin/pl_player/widgets/mpv_convert_webp.dart b/lib/plugin/pl_player/widgets/mpv_convert_webp.dart index 3cdade3d..5f74e4fd 100644 --- a/lib/plugin/pl_player/widgets/mpv_convert_webp.dart +++ b/lib/plugin/pl_player/widgets/mpv_convert_webp.dart @@ -68,7 +68,7 @@ class MpvConvertWebp { _observeProperty('time-pos'); } final level = (kDebugMode ? 'info' : 'error').toNativeUtf8(); - _mpv.mpv_request_log_messages(_ctx, level.cast()); + _mpv.mpv_request_log_messages(_ctx, level); calloc.free(level); } @@ -124,7 +124,7 @@ class MpvConvertWebp { arr[i] = pointers[i]; } - _mpv.mpv_command(_ctx, arr.cast()); + _mpv.mpv_command(_ctx, arr); calloc.free(arr); pointers.forEach(calloc.free); @@ -135,7 +135,7 @@ class MpvConvertWebp { _mpv.mpv_observe_property( _ctx, property.hashCode, - name.cast(), + name, generated.mpv_format.MPV_FORMAT_DOUBLE, ); diff --git a/lib/utils/cache_manage.dart b/lib/utils/cache_manage.dart index 7052e4a5..b244b9f0 100644 --- a/lib/utils/cache_manage.dart +++ b/lib/utils/cache_manage.dart @@ -57,7 +57,7 @@ abstract class CacheManage { value = value / 1024; } String size = value.toStringAsFixed(2); - return size + unitArr.getOrElse(index, orElse: () => ''); + return size + (unitArr.getOrNull(index) ?? ''); } // 清除 Library/Caches 目录及文件缓存 diff --git a/lib/utils/extension.dart b/lib/utils/extension.dart index f7229db3..aa8b4f64 100644 --- a/lib/utils/extension.dart +++ b/lib/utils/extension.dart @@ -14,12 +14,12 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart' hide ContextExtensionss; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; -extension ImageExtension on num? { +extension ImageExtension on num { int? cacheSize(BuildContext context) { - if (this == null || this == 0) { + if (this == 0) { return null; } - return (this! * MediaQuery.devicePixelRatioOf(context)).round(); + return (this * MediaQuery.devicePixelRatioOf(context)).round(); } } @@ -57,13 +57,43 @@ extension IterableExt on Iterable? { bool get isNullOrEmpty => this == null || this!.isEmpty; } +extension NonNullIterableExt on Iterable { + T? reduceOrNull(T Function(T value, T element) combine) { + Iterator iterator = this.iterator; + if (!iterator.moveNext()) { + return null; + } + T value = iterator.current; + while (iterator.moveNext()) { + value = combine(value, iterator.current); + } + return value; + } +} + extension MapExt on Map { Map fromCast() { return Map.from(this); } } -extension NonNullListExt on List { +extension ListExt on List { + T? getOrNull(int index) { + if (index < 0 || index >= length) { + return null; + } + return this[index]; + } + + bool removeFirstWhere(bool Function(T) test) { + final index = indexWhere(test); + if (index != -1) { + removeAt(index); + return true; + } + return false; + } + List fromCast() { return List.from(this); } @@ -72,34 +102,7 @@ extension NonNullListExt on List { bool Function(T) test, T Function(T, T) combine, ) { - final filters = where(test).toList(); - return filters.isNotEmpty ? filters.reduce(combine) : reduce(combine); - } -} - -extension ListExt on List? { - T? getOrNull(int index) { - if (isNullOrEmpty) { - return null; - } - if (index < 0 || index >= this!.length) { - return null; - } - return this![index]; - } - - T getOrElse(int index, {required T Function() orElse}) { - return getOrNull(index) ?? orElse(); - } - - bool removeFirstWhere(bool Function(T) test) { - if (this == null) return false; - final index = this!.indexWhere(test); - if (index != -1) { - this!.removeAt(index); - return true; - } - return false; + return where(test).reduceOrNull(combine) ?? reduce(combine); } } diff --git a/lib/utils/image_utils.dart b/lib/utils/image_utils.dart index e5dd82e0..697160b1 100644 --- a/lib/utils/image_utils.dart +++ b/lib/utils/image_utils.dart @@ -11,6 +11,7 @@ import 'package:PiliPlus/utils/utils.dart'; import 'package:dio/dio.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:intl/intl.dart' show DateFormat; import 'package:live_photo_maker/live_photo_maker.dart'; @@ -164,8 +165,9 @@ abstract class ImageUtils { static Future downloadImg( BuildContext context, - List imgList, - ) async { + List imgList, [ + CacheManager? manager, + ]) async { if (Utils.isMobile && !await checkPermissionDependOnSdkInt(context)) { return false; } @@ -179,41 +181,59 @@ abstract class ImageUtils { ); } try { - final isAndroid = Platform.isAndroid; - final tempPath = await Utils.temporaryDirectory; final futures = imgList.map((url) async { final name = Utils.getFileName(url); - final filePath = '$tempPath/$name'; - final response = await Request().downloadFile( + final file = (await (manager ?? DefaultCacheManager()).getFileFromCache( url.http2https, - filePath, - cancelToken: cancelToken, - ); + ))?.file; - if (isAndroid) { - if (response.statusCode == 200) { + if (file == null) { + final String filePath = '${await Utils.temporaryDirectory}/$name'; + + final response = await Request().downloadFile( + url.http2https, + filePath, + cancelToken: cancelToken, + ); + + if (Utils.isMobile) { + if (response.statusCode == 200) { + await SaverGallery.saveFile( + filePath: filePath, + fileName: name, + androidRelativePath: "Pictures/${Constants.appName}", + skipIfExists: false, + ).whenComplete(File(filePath).tryDel); + } + } + return ( + filePath: filePath, + name: name, + statusCode: response.statusCode, + del: true, + ); + } else { + if (Utils.isMobile) { await SaverGallery.saveFile( - filePath: filePath, + filePath: file.path, fileName: name, androidRelativePath: "Pictures/${Constants.appName}", skipIfExists: false, - ).whenComplete(File(filePath).tryDel); + ); } + + return (filePath: file.path, name: name, statusCode: 200, del: false); } - return ( - filePath: filePath, - name: name, - statusCode: response.statusCode, - ); }); final result = await Future.wait(futures, eagerError: true); - if (!isAndroid) { + if (!Utils.isMobile) { for (var res in result) { if (res.statusCode == 200) { await saveFileImg( filePath: res.filePath, fileName: res.name, + del: res.del, ); } } @@ -305,6 +325,7 @@ abstract class ImageUtils { required String fileName, FileType type = FileType.image, bool needToast = false, + bool del = true, }) async { final file = File(filePath); if (!file.existsSync()) { @@ -318,7 +339,8 @@ abstract class ImageUtils { fileName: fileName, androidRelativePath: "Pictures/${Constants.appName}", skipIfExists: false, - ).whenComplete(file.tryDel); + ); + if (del) file.tryDel(); } else { final savePath = await FilePicker.platform.saveFile( type: type, @@ -329,7 +351,7 @@ abstract class ImageUtils { return; } await file.copy(savePath); - file.tryDel(); + if (del) file.tryDel(); result = SaveResult(true, null); } if (needToast) {