use CupertinoClient for iOS

This commit is contained in:
kodjomoustapha 2024-09-05 15:44:33 +01:00
parent 99acfde0ca
commit 3bf1d08e0e
5 changed files with 59 additions and 222 deletions

View file

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

View file

@ -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<Task>();
/// 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 = <Task>{}; // by TaskId
var _readyForEnqueue = Completer();
final _enqueueErrorsStreamController = StreamController<Task>();
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<Task> 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<String> 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 = <Task>[];
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<bool> 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<Task> get enqueueErrors => _enqueueErrorsStreamController.stream;
}

View file

@ -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<String, dynamic>? 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,

View file

@ -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:

View file

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