add onLoadFailed to imageLoadingConfig

This commit is contained in:
nyne
2024-11-11 15:01:31 +08:00
parent d875681c4b
commit 7cf55fcb8e

View File

@@ -1,5 +1,6 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter_qjs/flutter_qjs.dart';
import 'package:venera/foundation/cache_manager.dart'; import 'package:venera/foundation/cache_manager.dart';
import 'package:venera/foundation/comic_source/comic_source.dart'; import 'package:venera/foundation/comic_source/comic_source.dart';
import 'package:venera/foundation/consts.dart'; import 'package:venera/foundation/consts.dart';
@@ -83,61 +84,92 @@ class ImageDownloader {
); );
} }
Future<Map<String, dynamic>?> Function()? onLoadFailed;
var configs = <String, dynamic>{}; var configs = <String, dynamic>{};
if (sourceKey != null) { if (sourceKey != null) {
var comicSource = ComicSource.find(sourceKey); var comicSource = ComicSource.find(sourceKey);
configs = (await comicSource!.getImageLoadingConfig configs = (await comicSource!.getImageLoadingConfig
?.call(imageKey, cid, eid)) ?? {}; ?.call(imageKey, cid, eid)) ??
{};
} }
configs['headers'] ??= { var retryLimit = 5;
'user-agent': webUA, while (true) {
}; try {
configs['headers'] ??= {
'user-agent': webUA,
};
var dio = AppDio(BaseOptions( if (configs['onLoadFailed'] is JSInvokable) {
headers: configs['headers'], onLoadFailed = () async {
method: configs['method'] ?? 'GET', dynamic result = configs['onLoadFailed']();
responseType: ResponseType.stream, if (result is Future) {
)); result = await result;
}
if (result is! Map<String, dynamic>) return null;
return result;
};
}
var req = await dio.request<ResponseBody>(configs['url'] ?? imageKey, var dio = AppDio(BaseOptions(
data: configs['data']); headers: configs['headers'],
var stream = req.data?.stream ?? (throw "Error: Empty response body."); method: configs['method'] ?? 'GET',
int? expectedBytes = req.data!.contentLength; responseType: ResponseType.stream,
if (expectedBytes == -1) { ));
expectedBytes = null;
} var req = await dio.request<ResponseBody>(configs['url'] ?? imageKey,
var buffer = <int>[]; data: configs['data']);
await for (var data in stream) { var stream = req.data?.stream ?? (throw "Error: Empty response body.");
buffer.addAll(data); int? expectedBytes = req.data!.contentLength;
if (expectedBytes != null) { if (expectedBytes == -1) {
expectedBytes = null;
}
var buffer = <int>[];
await for (var data in stream) {
buffer.addAll(data);
if (expectedBytes != null) {
yield ImageDownloadProgress(
currentBytes: buffer.length,
totalBytes: expectedBytes,
);
}
}
if (configs['onResponse'] != null) {
buffer = configs['onResponse'](buffer);
}
var data = Uint8List.fromList(buffer);
buffer.clear();
if (configs['modifyImage'] != null) {
var newData = await modifyImageWithScript(
data,
configs['modifyImage'],
);
data = newData;
}
await CacheManager().writeCache(cacheKey, data);
yield ImageDownloadProgress( yield ImageDownloadProgress(
currentBytes: buffer.length, currentBytes: data.length,
totalBytes: expectedBytes, totalBytes: data.length,
imageBytes: data,
); );
return;
} catch (e) {
if(retryLimit < 0 || onLoadFailed == null) {
rethrow;
}
var newConfig = await onLoadFailed();
onLoadFailed = null;
if(newConfig == null) {
rethrow;
}
configs = newConfig;
retryLimit--;
} }
} }
if (configs['onResponse'] != null) {
buffer = configs['onResponse'](buffer);
}
var data = Uint8List.fromList(buffer);
buffer.clear();
if (configs['modifyImage'] != null) {
var newData = await modifyImageWithScript(
data,
configs['modifyImage'],
);
data = newData;
}
await CacheManager().writeCache(cacheKey, data);
yield ImageDownloadProgress(
currentBytes: data.length,
totalBytes: data.length,
imageBytes: data,
);
} }
} }