import 'dart:typed_data'; import 'package:venera/foundation/cache_manager.dart'; import 'package:venera/foundation/comic_source/comic_source.dart'; import 'package:venera/foundation/consts.dart'; import 'app_dio.dart'; class ImageDownloader { static Stream loadThumbnail( String url, String? sourceKey) async* { final cacheKey = "$url@$sourceKey"; final cache = await CacheManager().findCache(cacheKey); if (cache != null) { var data = await cache.readAsBytes(); yield ImageDownloadProgress( currentBytes: data.length, totalBytes: data.length, imageBytes: data, ); } var configs = {}; if (sourceKey != null) { var comicSource = ComicSource.find(sourceKey); configs = comicSource!.getThumbnailLoadingConfig?.call(url) ?? {}; } configs['headers'] ??= {}; if(configs['headers']['user-agent'] == null && configs['headers']['User-Agent'] == null) { configs['headers']['user-agent'] = webUA; } var dio = AppDio(BaseOptions( headers: Map.from(configs['headers']), method: configs['method'] ?? 'GET', responseType: ResponseType.stream, )); var req = await dio.request(configs['url'] ?? url, data: configs['data']); var stream = req.data?.stream ?? (throw "Error: Empty response body."); int? expectedBytes = req.data!.contentLength; if (expectedBytes == -1) { expectedBytes = null; } var buffer = []; 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); } await CacheManager().writeCache(cacheKey, buffer); yield ImageDownloadProgress( currentBytes: buffer.length, totalBytes: buffer.length, imageBytes: Uint8List.fromList(buffer), ); } static Stream loadComicImage( String imageKey, String? sourceKey, String cid, String eid) async* { final cacheKey = "$imageKey@$sourceKey@$cid@$eid"; final cache = await CacheManager().findCache(cacheKey); if (cache != null) { var data = await cache.readAsBytes(); yield ImageDownloadProgress( currentBytes: data.length, totalBytes: data.length, imageBytes: data, ); } var configs = {}; if (sourceKey != null) { var comicSource = ComicSource.find(sourceKey); configs = (await comicSource!.getImageLoadingConfig ?.call(imageKey, cid, eid)) ?? {}; } configs['headers'] ??= { 'user-agent': webUA, }; var dio = AppDio(BaseOptions( headers: configs['headers'], method: configs['method'] ?? 'GET', responseType: ResponseType.stream, )); var req = await dio.request(configs['url'] ?? imageKey, data: configs['data']); var stream = req.data?.stream ?? (throw "Error: Empty response body."); int? expectedBytes = req.data!.contentLength; if (expectedBytes == -1) { expectedBytes = null; } var buffer = []; 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); } await CacheManager().writeCache(cacheKey, buffer); yield ImageDownloadProgress( currentBytes: buffer.length, totalBytes: buffer.length, imageBytes: Uint8List.fromList(buffer), ); } } class ImageDownloadProgress { final int currentBytes; final int totalBytes; final Uint8List? imageBytes; const ImageDownloadProgress({ required this.currentBytes, required this.totalBytes, this.imageBytes, }); }