From 67dee18776e5afdce68a81f747f5530a960606e6 Mon Sep 17 00:00:00 2001 From: NBA2K1 <78034913+NBA2K1@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:43:23 +0100 Subject: [PATCH 1/5] remove redundant import --- lib/modules/anime/anime_player_view.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/modules/anime/anime_player_view.dart b/lib/modules/anime/anime_player_view.dart index 1d132873..618e34a6 100644 --- a/lib/modules/anime/anime_player_view.dart +++ b/lib/modules/anime/anime_player_view.dart @@ -48,7 +48,6 @@ import 'package:media_kit/generated/libmpv/bindings.dart' as generated; import 'package:media_kit_video/media_kit_video.dart'; import 'package:media_kit_video/media_kit_video_controls/src/controls/extensions/duration.dart'; import 'package:numberpicker/numberpicker.dart'; -import 'package:path/path.dart' as p; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; @@ -930,7 +929,7 @@ mp.register_script_message('call_button_${button.id}_long', button${button.id}lo if (Platform.isAndroid && useLibass) { try { final subDir = await getApplicationDocumentsDirectory(); - final fontPath = p.join(subDir.path, 'subfont.ttf'); + final fontPath = path.join(subDir.path, 'subfont.ttf'); final data = await rootBundle.load('assets/fonts/subfont.ttf'); final bytes = data.buffer.asInt8List( data.offsetInBytes, @@ -2310,7 +2309,9 @@ mp.register_script_message('call_button_${button.id}_long', button${button.id}lo ); final dir = await StorageProvider() .getGalleryDirectory(); - final file = File(p.join(dir!.path, "$name.png")); + final file = File( + path.join(dir!.path, "$name.png"), + ); file.writeAsBytesSync(imageBytes!); if (context.mounted) { botToast(context.l10n.picture_saved, second: 3); From 0ed8ee2cd28fb9c135a2081ab0ceec3435097ab0 Mon Sep 17 00:00:00 2001 From: NBA2K1 <78034913+NBA2K1@users.noreply.github.com> Date: Wed, 17 Dec 2025 20:55:41 +0100 Subject: [PATCH 2/5] Move cacheDir creation to storage_provider - Move the cacheDir creation to storage_provider from `others.dart`, `custom_extended_image_provider.dart` and `storage_usage.dart`. - Use the correct directory, `getApplicationCacheDirectory()` instead of the `getTemporaryDirectory()` (which is being deleted by the OS regularly) for cache files. - remove the `_cacheDownloadPath` from `storage_usage.dart` as the path is never being created in the first place, so using that path in `clearCache()` and `_getTotalDiskSpace()` is unnecessary. --- .../providers/storage_usage.dart | 25 ++++--------------- .../custom_extended_image_provider.dart | 13 +++------- lib/providers/storage_provider.dart | 14 +++++++++++ lib/utils/extensions/others.dart | 12 +++------ 4 files changed, 25 insertions(+), 39 deletions(-) diff --git a/lib/modules/more/data_and_storage/providers/storage_usage.dart b/lib/modules/more/data_and_storage/providers/storage_usage.dart index fa8fc1eb..a19b4efe 100644 --- a/lib/modules/more/data_and_storage/providers/storage_usage.dart +++ b/lib/modules/more/data_and_storage/providers/storage_usage.dart @@ -5,8 +5,6 @@ import 'package:mangayomi/models/settings.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; import 'package:mangayomi/providers/storage_provider.dart'; import 'package:mangayomi/router/router.dart'; -import 'package:path/path.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'storage_usage.g.dart'; @@ -21,28 +19,19 @@ class TotalChapterCacheSizeState extends _$TotalChapterCacheSizeState { return "0.00 B"; } - final String _cacheImageMangaPath = join('Mangayomi', 'cacheimagemanga'); - final String _cacheDownloadPath = join('Mangayomi', 'downloads'); + final _storage = StorageProvider(); Future clearCache({bool showToast = true}) async { - final tempPath = (await getTemporaryDirectory()).path; String? msg; try { - final dir = Directory(join(tempPath, _cacheImageMangaPath)); + final dir = await _storage.getCacheDirectory('cacheimagemanga'); if (dir.existsSync()) { await dir.delete(recursive: true); } msg = "0.00 B"; } catch (_) {} try { - final dir = Directory(join(tempPath, _cacheDownloadPath)); - if (dir.existsSync()) { - await dir.delete(recursive: true); - } - msg = "0.00 B"; - } catch (_) {} - try { - await StorageProvider().deleteTmpDirectory(); + await _storage.deleteTmpDirectory(); } catch (_) {} if (msg != null && showToast) { state = msg; @@ -53,14 +42,10 @@ class TotalChapterCacheSizeState extends _$TotalChapterCacheSizeState { } Future _getTotalDiskSpace() async { - final tempPath = (await getTemporaryDirectory()).path; try { return await _getdirectorySize( - Directory(join(tempPath, _cacheImageMangaPath)), - ) + - await _getdirectorySize( - Directory(join(tempPath, _cacheDownloadPath)), - ); + await _storage.getCacheDirectory('cacheimagemanga'), + ); } catch (_) {} return 0; } diff --git a/lib/modules/widgets/custom_extended_image_provider.dart b/lib/modules/widgets/custom_extended_image_provider.dart index 43c96938..f47bd838 100644 --- a/lib/modules/widgets/custom_extended_image_provider.dart +++ b/lib/modules/widgets/custom_extended_image_provider.dart @@ -10,7 +10,6 @@ import 'package:http_client_helper/http_client_helper.dart'; import 'package:mangayomi/providers/storage_provider.dart'; import 'package:mangayomi/services/http/m_client.dart'; import 'package:path/path.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:extended_image_library/src/network/extended_network_image_provider.dart' as image_provider; @@ -214,7 +213,7 @@ class CustomExtendedNetworkImageProvider @override final bool printError; - /// The max duration to cahce image. + /// The max duration to cache image. /// After this time the cache is expired and the image is reloaded. @override final Duration? cacheMaxAge; @@ -317,15 +316,9 @@ class CustomExtendedNetworkImageProvider return cachedData; } - final Directory cacheImagesDirectory = Directory( - join( - (await getTemporaryDirectory()).path, - 'Mangayomi', - imageCacheFolderName ?? 'cacheimagecover', - ), - ); + final Directory cacheImagesDirectory = await StorageProvider() + .createCacheDirectory(imageCacheFolderName); Uint8List? data; - await StorageProvider().createDirectorySafely(cacheImagesDirectory.path); final File cacheFile = File(join(cacheImagesDirectory.path, md5Key)); // exist, try to find cache image file diff --git a/lib/providers/storage_provider.dart b/lib/providers/storage_provider.dart index 9c6aac07..45e626db 100644 --- a/lib/providers/storage_provider.dart +++ b/lib/providers/storage_provider.dart @@ -86,6 +86,20 @@ class StorageProvider { return Directory(tmpPath); } + Future getCacheDirectory(String? imageCacheFolderName) async { + final cacheImagesDirectory = path.join( + (await getApplicationCacheDirectory()).path, + imageCacheFolderName ?? 'cacheimagecover', + ); + return Directory(cacheImagesDirectory); + } + + Future createCacheDirectory(String? imageCacheFolderName) async { + final cachePath = await getCacheDirectory(imageCacheFolderName); + await createDirectorySafely(cachePath.path); + return cachePath; + } + Future _tempDirectoryPath() async { final defaultDirectory = await getDirectory(); return path.join(defaultDirectory!.path, 'tmp'); diff --git a/lib/utils/extensions/others.dart b/lib/utils/extensions/others.dart index 85242453..e57a5638 100644 --- a/lib/utils/extensions/others.dart +++ b/lib/utils/extensions/others.dart @@ -10,10 +10,9 @@ import 'package:intl/intl.dart'; import 'package:mangayomi/modules/manga/reader/u_chap_data_preload.dart'; import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart'; import 'package:mangayomi/modules/widgets/custom_extended_image_provider.dart'; +import 'package:mangayomi/providers/storage_provider.dart'; import 'package:mangayomi/utils/headers.dart'; import 'package:mangayomi/utils/reg_exp_matcher.dart'; -import 'package:path/path.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:path/path.dart' as p; extension FileFormatter on num { @@ -144,13 +143,8 @@ extension UChapDataPreloadExtensions on UChapDataPreload { Future _getCachedImageFile(String url, {String? cacheKey}) async { try { final String key = cacheKey ?? keyToMd5(url); - final Directory cacheImagesDirectory = Directory( - join( - (await getTemporaryDirectory()).path, - 'Mangayomi', - 'cacheimagemanga', - ), - ); + final Directory cacheImagesDirectory = await StorageProvider() + .getCacheDirectory('cacheimagemanga'); if (cacheImagesDirectory.existsSync()) { await for (final FileSystemEntity file in cacheImagesDirectory.list()) { if (file.path.endsWith(key)) { From a078b59678edb7aef4071470b59c22421a06d540 Mon Sep 17 00:00:00 2001 From: NBA2K1 <78034913+NBA2K1@users.noreply.github.com> Date: Wed, 17 Dec 2025 21:24:26 +0100 Subject: [PATCH 3/5] Use floor() instead of round() - Using round() will push values up too early. Example: log(999) / log(1024) = 0.999 .round() = 1. Result: 0.98 kB instead of 999 B - Use correct units, as base1024 = KiB, MiB, etc. and base1000 = kB, MB, GB, ... --- lib/utils/extensions/others.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/utils/extensions/others.dart b/lib/utils/extensions/others.dart index e57a5638..c281c731 100644 --- a/lib/utils/extensions/others.dart +++ b/lib/utils/extensions/others.dart @@ -17,10 +17,15 @@ import 'package:path/path.dart' as p; extension FileFormatter on num { String formattedFileSize({bool base1024 = true}) { + if (this <= 0) return "0.00 B"; final base = base1024 ? 1024 : 1000; - if (this <= 0) return "0"; - final units = ["B", "kB", "MB", "GB", "TB"]; - int digitGroups = (log(this) / log(base)).round(); + final units = base1024 + ? ["B", "KiB", "MiB", "GiB", "TiB"] + : ["B", "kB", "MB", "GB", "TB"]; + int digitGroups = (log(this) / log(base)).floor().clamp( + 0, + units.length - 1, + ); return "${NumberFormat("#,##0.#").format(this / pow(base, digitGroups))} ${units[digitGroups]}"; } } From 0f83899bac724fe8806021eb64bc1121365a1793 Mon Sep 17 00:00:00 2001 From: NBA2K1 <78034913+NBA2K1@users.noreply.github.com> Date: Wed, 17 Dec 2025 21:34:45 +0100 Subject: [PATCH 4/5] remove unnecessary calls .trimLeft().trimRight() after trim() is unnecessary. --- lib/eval/model/m_bridge.dart | 8 +++----- .../manga/download/providers/download_provider.dart | 4 ++-- lib/modules/widgets/manga_image_card_widget.dart | 2 +- lib/utils/extensions/dom_extensions.dart | 4 ++-- lib/utils/extensions/others.dart | 2 +- lib/utils/html_to_xml_doc.dart | 2 +- 6 files changed, 10 insertions(+), 12 deletions(-) diff --git a/lib/eval/model/m_bridge.dart b/lib/eval/model/m_bridge.dart index c942940a..1bd98ede 100644 --- a/lib/eval/model/m_bridge.dart +++ b/lib/eval/model/m_bridge.dart @@ -75,14 +75,12 @@ class MBridge { var query = htmlXPath.query(xpath); if (query.nodes.length > 1) { for (var element in query.attrs) { - attrs.add(element!.trim().trimLeft().trimRight()); + attrs.add(element!.trim()); } } //Return one attr else if (query.nodes.length == 1) { - String attr = query.attr != null - ? query.attr!.trim().trimLeft().trimRight() - : ""; + String attr = query.attr != null ? query.attr!.trim() : ""; if (attr.isNotEmpty) { attrs = [attr]; } @@ -102,7 +100,7 @@ class MBridge { statusMap = element; for (var element in statusMap.entries) { if (element.key.toString().toLowerCase().contains( - status.toLowerCase().trim().trimLeft().trimRight(), + status.toLowerCase().trim(), )) { return switch (element.value as int) { 0 => Status.ongoing, diff --git a/lib/modules/manga/download/providers/download_provider.dart b/lib/modules/manga/download/providers/download_provider.dart index 84779510..66e4037b 100644 --- a/lib/modules/manga/download/providers/download_provider.dart +++ b/lib/modules/manga/download/providers/download_provider.dart @@ -309,7 +309,7 @@ Future downloadChapter( if (!file.existsSync()) { pages.add( PageUrl( - page.url.trim().trimLeft().trimRight(), + page.url.trim(), headers: pageHeaders, fileName: p.join( chapterDirectory.path, @@ -325,7 +325,7 @@ Future downloadChapter( if (!file.existsSync()) { pages.add( PageUrl( - page.url.trim().trimLeft().trimRight(), + page.url.trim(), headers: pageHeaders, fileName: p.join(mangaMainDirectory.path, "$chapterName.mp4"), ), diff --git a/lib/modules/widgets/manga_image_card_widget.dart b/lib/modules/widgets/manga_image_card_widget.dart index 0f34f4dc..cfd11afe 100644 --- a/lib/modules/widgets/manga_image_card_widget.dart +++ b/lib/modules/widgets/manga_image_card_widget.dart @@ -342,7 +342,7 @@ Future pushToMangaReaderDetail({ mangaM ?? Manga( imageUrl: getManga!.imageUrl, - name: getManga.name!.trim().trimLeft().trimRight(), + name: getManga.name!.trim(), genre: getManga.genre?.map((e) => e.toString()).toList() ?? [], author: getManga.author ?? "", status: getManga.status ?? Status.unknown, diff --git a/lib/utils/extensions/dom_extensions.dart b/lib/utils/extensions/dom_extensions.dart index b7d3b3ba..6a8da35e 100644 --- a/lib/utils/extensions/dom_extensions.dart +++ b/lib/utils/extensions/dom_extensions.dart @@ -326,7 +326,7 @@ extension DocumentExtension on Document? { var htmlXPath = HtmlXPath.node(dom); var query = htmlXPath.query(xpath); if (query.nodes.length > 1) { - return query.attrs.map((e) => e!.trim().trimLeft().trimRight()).toList(); + return query.attrs.map((e) => e!.trim()).toList(); } return []; } @@ -365,7 +365,7 @@ extension ElementtExtension on Element { var htmlXPath = HtmlXPath.node(this); var query = htmlXPath.query(xpath); if (query.nodes.length > 1) { - return query.attrs.map((e) => e!.trim().trimLeft().trimRight()).toList(); + return query.attrs.map((e) => e!.trim()).toList(); } return []; } diff --git a/lib/utils/extensions/others.dart b/lib/utils/extensions/others.dart index c281c731..b10123fe 100644 --- a/lib/utils/extensions/others.dart +++ b/lib/utils/extensions/others.dart @@ -125,7 +125,7 @@ extension UChapDataPreloadExtensions on UChapDataPreload { ), ) : CustomExtendedNetworkImageProvider( - data.pageUrl!.url.trim().trimLeft().trimRight(), + data.pageUrl!.url.trim(), cache: true, cacheMaxAge: const Duration(days: 7), showCloudFlareError: showCloudFlareError, diff --git a/lib/utils/html_to_xml_doc.dart b/lib/utils/html_to_xml_doc.dart index 3199c03a..18c1c52f 100644 --- a/lib/utils/html_to_xml_doc.dart +++ b/lib/utils/html_to_xml_doc.dart @@ -61,7 +61,7 @@ // var query = xpath(expression); // if (query.isNotEmpty) { // return query -// .map((e) => (e.value ?? "").trim().trimLeft().trimRight()) +// .map((e) => (e.value ?? "").trim()) // .toList(); // } // } catch (_) {} From 5f7ea7fcf4f978bd69168efdd6faaedb479d292d Mon Sep 17 00:00:00 2001 From: NBA2K1 <78034913+NBA2K1@users.noreply.github.com> Date: Wed, 17 Dec 2025 22:25:45 +0100 Subject: [PATCH 5/5] reduce code duplication Use the `formattedFileSize()` function instead of `_formatBytes()` --- .../providers/storage_usage.dart | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/lib/modules/more/data_and_storage/providers/storage_usage.dart b/lib/modules/more/data_and_storage/providers/storage_usage.dart index a19b4efe..2b416f01 100644 --- a/lib/modules/more/data_and_storage/providers/storage_usage.dart +++ b/lib/modules/more/data_and_storage/providers/storage_usage.dart @@ -5,6 +5,7 @@ import 'package:mangayomi/models/settings.dart'; import 'package:mangayomi/providers/l10n_providers.dart'; import 'package:mangayomi/providers/storage_provider.dart'; import 'package:mangayomi/router/router.dart'; +import 'package:mangayomi/utils/extensions/others.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'storage_usage.g.dart'; @@ -14,7 +15,7 @@ class TotalChapterCacheSizeState extends _$TotalChapterCacheSizeState { String build() { _getTotalDiskSpace().then((value) { if (!ref.mounted) return; - state = _formatBytes(value); + state = value.formattedFileSize(); }); return "0.00 B"; } @@ -64,19 +65,6 @@ class TotalChapterCacheSizeState extends _$TotalChapterCacheSizeState { } catch (_) {} return 0; } - - String _formatBytes(int bytes) { - const units = ['B', 'KB', 'MB', 'GB']; - int unitIndex = 0; - double size = bytes.toDouble(); - - while (size >= 1024 && unitIndex < units.length - 1) { - size /= 1024; - unitIndex++; - } - - return '${size.toStringAsFixed(2)} ${units[unitIndex]}'; - } } @riverpod