From 3bf1d08e0e2d136845c852ce0a0646bd23f33a78 Mon Sep 17 00:00:00 2001 From: kodjomoustapha <107993382+kodjodevf@users.noreply.github.com> Date: Thu, 5 Sep 2024 15:44:33 +0100 Subject: [PATCH] use CupertinoClient for iOS --- .../downloader/downloader_http_client.dart | 4 +- .../src/queue/task_queue.dart | 193 ------------------ lib/services/http/m_client.dart | 6 + pubspec.lock | 71 ++++--- pubspec.yaml | 7 +- 5 files changed, 59 insertions(+), 222 deletions(-) diff --git a/lib/services/background_downloader/src/downloader/downloader_http_client.dart b/lib/services/background_downloader/src/downloader/downloader_http_client.dart index 351ede3..f40ec24 100644 --- a/lib/services/background_downloader/src/downloader/downloader_http_client.dart +++ b/lib/services/background_downloader/src/downloader/downloader_http_client.dart @@ -571,7 +571,9 @@ final class DownloaderHttpClient extends BaseDownloader { /// Recreates the [httpClient] used for Requests and isolate downloads/uploads static _recreateClient() async { - await Rhttp.init(); + if (!Platform.isIOS) { + await Rhttp.init(); + } httpClient = MClient.httpClient( settings: const ClientSettings( throwOnStatusCode: false, diff --git a/lib/services/background_downloader/src/queue/task_queue.dart b/lib/services/background_downloader/src/queue/task_queue.dart index eb0f8b4..809f51d 100644 --- a/lib/services/background_downloader/src/queue/task_queue.dart +++ b/lib/services/background_downloader/src/queue/task_queue.dart @@ -1,10 +1,5 @@ // ignore_for_file: depend_on_referenced_packages -import 'dart:async'; - -import 'package:collection/collection.dart'; -import 'package:logging/logging.dart'; - import '../file_downloader.dart'; import '../task.dart'; @@ -14,191 +9,3 @@ abstract interface class TaskQueue { /// Signals that [task] has finished void taskFinished(Task task); } - -/// TaskQueue that holds all information in memory -class MemoryTaskQueue implements TaskQueue { - static final _log = Logger('MemoryTaskQueue'); - static const unlimited = 1 << 20; - - /// Tasks waiting to be enqueued, in priority order - final waiting = PriorityQueue(); - - /// Max number of tasks running concurrently, default is unlimited - int maxConcurrent = unlimited; - - /// Max number of active tasks connecting to the same host concurrently, - /// default is unlimited - int maxConcurrentByHost = unlimited; - - /// Max number of active tasks with the same group concurrently, - /// default is unlimited - int maxConcurrentByGroup = unlimited; - - /// Minimum interval between successive enqueues, set to avoid choking the - /// message loop when adding many tasks - Duration minInterval = const Duration(milliseconds: 20); - - /// Set of tasks that have been enqueued with the FileDownloader - final enqueued = {}; // by TaskId - - var _readyForEnqueue = Completer(); - - final _enqueueErrorsStreamController = StreamController(); - - MemoryTaskQueue() { - _readyForEnqueue.complete(); - } - - /// Add one [task] to the queue and advance the queue if possible - void add(Task task) { - waiting.add(task); - advanceQueue(); - } - - /// Add multiple [tasks] to the queue and advance the queue if possible - void addAll(Iterable tasks) { - waiting.addAll(tasks); - advanceQueue(); - } - - /// Remove all items in the queue. Does not affect tasks already enqueued - /// with the [FileDownloader] - void removeAll() => waiting.removeAll(); - - /// remove all waiting tasks matching [taskIds]. Does not affect tasks already enqueued - /// with the [FileDownloader] - void removeTasksWithIds(List taskIds) { - for (final taskId in taskIds) { - final match = waiting.unorderedElements - .firstWhereOrNull((task) => task.taskId == taskId); - if (match != null) { - waiting.remove(match); - } - } - } - - /// remove all waiting tasks in [group]. Does not affect tasks already enqueued - /// with the [FileDownloader] - void removeTasksWithGroup(String group) { - final tasksToRemove = waiting.unorderedElements - .where((task) => task.group == group) - .toList(growable: false); - for (final task in tasksToRemove) { - waiting.remove(task); - } - } - - /// Remove [task] from the queue. Does not affect tasks already enqueued - /// with the [FileDownloader] - void remove(Task task) => waiting.remove(task); - - /// Reset the state of the [TaskQueue]. - /// - /// Clears the [waiting] queue and resets active tasks to 0 - void reset({String? group}) { - if (group == null) { - removeAll(); - enqueued.clear(); - } else { - removeTasksWithGroup(group); - final tasksToRemove = - enqueued.where((task) => task.group != group).toList(growable: false); - for (final task in tasksToRemove) { - enqueued.remove(task); - } - } - } - - /// Advance the queue if possible and ready, no-op if not - /// - /// After the enqueue, [advanceQueue] is called again to ensure the - /// next item in the queue is enqueued, so the queue keeps going until - /// empty, or until it cannot enqueue another task - void advanceQueue() async { - if (_readyForEnqueue.isCompleted) { - final task = getNextTask(); - if (task == null) { - return; - } - _readyForEnqueue = Completer(); - enqueued.add(task); - enqueue(task).then((success) async { - if (!success) { - _log.warning( - 'TaskId ${task.taskId} did not enqueue successfully and will be ignored'); - if (_enqueueErrorsStreamController.hasListener) { - _enqueueErrorsStreamController.add(task); - } - } - await Future.delayed(minInterval); - _readyForEnqueue.complete(); - }); - _readyForEnqueue.future.then((_) => advanceQueue()); - } - } - - /// Get the next waiting task from the queue, or null if not available - Task? getNextTask() { - if (numActive >= maxConcurrent) { - return null; - } - final tasksThatHaveToWait = []; - while (waiting.isNotEmpty) { - var task = waiting.removeFirst(); - if (numActiveWithHostname(task.hostName) < maxConcurrentByHost && - numActiveWithGroup(task.group) < maxConcurrentByGroup) { - waiting.addAll(tasksThatHaveToWait); // put back in queue - return task; - } - tasksThatHaveToWait.add(task); - } - waiting.addAll(tasksThatHaveToWait); // put back in queue - return null; - } - - /// Enqueue the task to the [FileDownloader] - /// - /// When using a [MemoryTaskQueue], do not use this method directly. Instead, - /// add your tasks to the queue using [add] and [addAll], and - /// let the [MemoryTaskQueue] manage the enqueueing. - Future enqueue(Task task) => FileDownloader().enqueue(task); - - /// Task has finished, so remove from active and advance the queue to the - /// next task if the task was indeed managed by this queue - @override - void taskFinished(Task task) { - if (enqueued.remove(task)) { - advanceQueue(); - } - } - - /// Number of active tasks, i.e. enqueued with the FileDownloader and - /// not yet finished - int get numActive => enqueued.length; - - /// Returns number of tasks active with this host name - int numActiveWithHostname(String hostname) => enqueued.fold( - 0, - (previousValue, task) => - task.hostName == hostname ? previousValue + 1 : previousValue); - - /// Returns number of tasks active with this group - int numActiveWithGroup(String group) => enqueued.fold( - 0, - (previousValue, task) => - task.group == group ? previousValue + 1 : previousValue); - - /// True if queue is empty - bool get isEmpty => waiting.isEmpty; - - /// Number of tasks waiting to be enqueued - int get numWaiting => waiting.length; - - /// Number of tasks waiting to be enqueued in [group] - int numWaitingWithGroup(String group) => waiting.unorderedElements - .where((element) => element.group == group) - .length; - - /// Stream with [Task]s that failed to enqueue correctly - Stream get enqueueErrors => _enqueueErrorsStreamController.stream; -} diff --git a/lib/services/http/m_client.dart b/lib/services/http/m_client.dart index 83cdc00..d676bec 100644 --- a/lib/services/http/m_client.dart +++ b/lib/services/http/m_client.dart @@ -1,3 +1,4 @@ +import 'package:cupertino_http/cupertino_http.dart'; import 'package:http_interceptor/http_interceptor.dart'; import 'package:mangayomi/eval/dart/model/m_bridge.dart'; import 'dart:async'; @@ -16,6 +17,11 @@ class MClient { static Client httpClient( {Map? reqcopyWith, rhttp.ClientSettings? settings}) { if (!(reqcopyWith?["useDartHttpClient"] ?? false)) { + if (Platform.isIOS) { + final config = URLSessionConfiguration.ephemeralSessionConfiguration() + ..cache = URLCache.withCapacity(memoryCapacity: 5 * 1024 * 1024); + return CupertinoClient.fromSessionConfiguration(config); + } try { settings ??= rhttp.ClientSettings( throwOnStatusCode: false, diff --git a/pubspec.lock b/pubspec.lock index 88f5c0e..254cb10 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -138,18 +138,18 @@ packages: dependency: "direct dev" description: name: build_runner - sha256: "644dc98a0f179b872f612d3eb627924b578897c629788e858157fa5e704ca0c7" + sha256: dd09dd4e2b078992f42aac7f1a622f01882a8492fef08486b27ddde929c19f04 url: "https://pub.dev" source: hosted - version: "2.4.11" + version: "2.4.12" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: e3c79f69a64bdfcd8a776a3c28db4eb6e3fb5356d013ae5eb2e52007706d5dbe + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 url: "https://pub.dev" source: hosted - version: "7.3.1" + version: "7.3.2" built_collection: dependency: transitive description: @@ -254,6 +254,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + cupertino_http: + dependency: "direct main" + description: + name: cupertino_http + sha256: "7e75c45a27cc13a886ab0a1e4d8570078397057bd612de9d24fe5df0d9387717" + url: "https://pub.dev" + source: hosted + version: "1.5.1" cupertino_icons: dependency: "direct main" description: @@ -501,10 +509,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "9d98bd47ef9d34e803d438f17fd32b116d31009f534a6fa5ce3a1167f189a6de" + sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda" url: "https://pub.dev" source: hosted - version: "2.0.21" + version: "2.0.22" flutter_qjs: dependency: "direct main" description: @@ -561,7 +569,7 @@ packages: description: path: "." ref: master - resolved-ref: "9e7a954ffd54f38baa77520f47fc63ae80c22f14" + resolved-ref: "8673cc315b569ddba37527d9d5414ea9c5a0954f" url: "https://github.com/wgh136/flutter_windows_webview" source: git version: "0.0.1" @@ -601,10 +609,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "48d03a1e4887b00fe622695139246e3c778ac814eeb32421467b56d23fa64034" + sha256: "2ddb88e9ad56ae15ee144ed10e33886777eb5ca2509a914850a5faa7b52ff459" url: "https://pub.dev" source: hosted - version: "14.2.6" + version: "14.2.7" google_fonts: dependency: "direct main" description: @@ -693,6 +701,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + http_profile: + dependency: transitive + description: + name: http_profile + sha256: "7e679e355b09aaee2ab5010915c932cce3f2d1c11c3b2dc177891687014ffa78" + url: "https://pub.dev" + source: hosted + version: "0.1.0" image: dependency: transitive description: @@ -889,10 +905,10 @@ packages: dependency: "direct main" description: name: media_kit - sha256: "3289062540e3b8b9746e5c50d95bd78a9289826b7227e253dff806d002b9e67a" + sha256: "1f1deee148533d75129a6f38251ff8388e33ee05fc2d20a6a80e57d6051b7b62" url: "https://pub.dev" source: hosted - version: "1.1.10+1" + version: "1.1.11" media_kit_libs_android_video: dependency: transitive description: @@ -929,10 +945,10 @@ packages: dependency: "direct main" description: name: media_kit_libs_video - sha256: "3688e0c31482074578652bf038ce6301a5d21e1eda6b54fc3117ffeb4bdba067" + sha256: "20bb4aefa8fece282b59580e1cd8528117297083a6640c98c2e98cfc96b93288" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" media_kit_libs_windows_video: dependency: "direct overridden" description: @@ -972,10 +988,10 @@ packages: dependency: transitive description: name: mime - sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" + sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" mocktail: dependency: transitive description: @@ -1196,10 +1212,10 @@ packages: dependency: transitive description: name: quiver - sha256: b1c1ac5ce6688d77f65f3375a9abb9319b3cb32486bdc7a1e0fdf004d7ba4e47 + sha256: ea0b925899e64ecdfbf9c7becb60d5b50e706ade44a85b2363be2a22d88117d2 url: "https://pub.dev" source: hosted - version: "3.2.1" + version: "3.2.2" quote_buffer: dependency: transitive description: @@ -1219,10 +1235,11 @@ packages: rhttp: dependency: "direct main" description: - name: rhttp - sha256: b07ed2da1f9ee3a18fd1505428a597e6ed3e3ec08ddd99ff3c6e7597887fc3db - url: "https://pub.dev" - source: hosted + path: rhttp + ref: main + resolved-ref: e2c8dd04320936213c1f6ae66a3768b2b4f3a49a + url: "https://github.com/kodjodevf/rhttp.git" + source: git version: "0.7.0" riverpod: dependency: transitive @@ -1456,10 +1473,10 @@ packages: dependency: transitive description: name: synchronized - sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + sha256: a824e842b8a054f91a728b783c177c1e4731f6b124f9192468457a8913371255 url: "https://pub.dev" source: hosted - version: "3.1.0+1" + version: "3.2.0" term_glyph: dependency: transitive description: @@ -1536,10 +1553,10 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: f0c73347dfcfa5b3db8bc06e1502668265d39c08f310c29bff4e28eea9699f79 + sha256: e35a698ac302dd68e41f73250bd9517fe3ab5fa4f18fe4647a0872db61bacbab url: "https://pub.dev" source: hosted - version: "6.3.9" + version: "6.3.10" url_launcher_ios: dependency: transitive description: @@ -1592,10 +1609,10 @@ packages: dependency: transitive description: name: uuid - sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" + sha256: f33d6bb662f0e4f79dcd7ada2e6170f3b3a2530c28fc41f49a411ddedd576a77 url: "https://pub.dev" source: hosted - version: "4.4.2" + version: "4.5.0" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 6d34bf4..e1286f4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -75,7 +75,12 @@ dependencies: rust_lib_mangayomi: path: rust_builder pseudom: ^1.0.1 - rhttp: ^0.7.0 + rhttp: + git: + url: https://github.com/kodjodevf/rhttp.git + path: rhttp + ref: main + cupertino_http: ^1.5.1 dependency_overrides: http: ^1.2.1