use CupertinoClient for iOS
This commit is contained in:
parent
99acfde0ca
commit
3bf1d08e0e
5 changed files with 59 additions and 222 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
71
pubspec.lock
71
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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue