* opt: downloadImg use cache

* opt: uin8 cast

* non null ext
This commit is contained in:
My-Responsitories
2025-10-14 19:36:43 +08:00
committed by GitHub
parent 43beb518f4
commit c3fa976b26
6 changed files with 84 additions and 59 deletions

View File

@@ -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),

View File

@@ -39,7 +39,7 @@ class _GroupPanelState extends State<GroupPanel> {
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(() {});
}

View File

@@ -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,
);

View File

@@ -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 目录及文件缓存

View File

@@ -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<T> on Iterable<T>? {
bool get isNullOrEmpty => this == null || this!.isEmpty;
}
extension NonNullIterableExt<T> on Iterable<T> {
T? reduceOrNull(T Function(T value, T element) combine) {
Iterator<T> iterator = this.iterator;
if (!iterator.moveNext()) {
return null;
}
T value = iterator.current;
while (iterator.moveNext()) {
value = combine(value, iterator.current);
}
return value;
}
}
extension MapExt<K, V> on Map<K, V> {
Map<RK, RV> fromCast<RK, RV>() {
return Map<RK, RV>.from(this);
}
}
extension NonNullListExt<T> on List<T> {
extension ListExt<T> on List<T> {
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<R> fromCast<R>() {
return List<R>.from(this);
}
@@ -72,34 +102,7 @@ extension NonNullListExt<T> on List<T> {
bool Function(T) test,
T Function(T, T) combine,
) {
final filters = where(test).toList();
return filters.isNotEmpty ? filters.reduce(combine) : reduce(combine);
}
}
extension ListExt<T> on List<T>? {
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);
}
}

View File

@@ -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<bool> downloadImg(
BuildContext context,
List<String> imgList,
) async {
List<String> 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) {