mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-05-15 04:00:51 +00:00
Add IsolateService for improved asynchronous operations and refactor service calls to utilize it
This commit is contained in:
parent
1569c1bcd1
commit
ea50cc91ca
10 changed files with 327 additions and 127 deletions
|
|
@ -32,6 +32,7 @@ import 'package:mangayomi/router/router.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/appearance/providers/theme_mode_state_provider.dart';
|
import 'package:mangayomi/modules/more/settings/appearance/providers/theme_mode_state_provider.dart';
|
||||||
import 'package:mangayomi/l10n/generated/app_localizations.dart';
|
import 'package:mangayomi/l10n/generated/app_localizations.dart';
|
||||||
import 'package:mangayomi/services/http/m_client.dart';
|
import 'package:mangayomi/services/http/m_client.dart';
|
||||||
|
import 'package:mangayomi/services/isolate_service.dart';
|
||||||
import 'package:mangayomi/src/rust/frb_generated.dart';
|
import 'package:mangayomi/src/rust/frb_generated.dart';
|
||||||
import 'package:mangayomi/utils/discord_rpc.dart';
|
import 'package:mangayomi/utils/discord_rpc.dart';
|
||||||
import 'package:mangayomi/utils/log/logger.dart';
|
import 'package:mangayomi/utils/log/logger.dart';
|
||||||
|
|
@ -54,6 +55,7 @@ void main(List<String> args) async {
|
||||||
MediaKit.ensureInitialized();
|
MediaKit.ensureInitialized();
|
||||||
await RustLib.init();
|
await RustLib.init();
|
||||||
await imgCropIsolate.start();
|
await imgCropIsolate.start();
|
||||||
|
await getIsolateService.start();
|
||||||
if (!(Platform.isAndroid || Platform.isIOS)) {
|
if (!(Platform.isAndroid || Platform.isIOS)) {
|
||||||
await windowManager.ensureInitialized();
|
await windowManager.ensureInitialized();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,16 @@ Future<void> fetchItemSourcesList(
|
||||||
if (ref.watch(checkForExtensionsUpdateStateProvider) || reFresh) {
|
if (ref.watch(checkForExtensionsUpdateStateProvider) || reFresh) {
|
||||||
final repos = ref.watch(extensionsRepoStateProvider(itemType));
|
final repos = ref.watch(extensionsRepoStateProvider(itemType));
|
||||||
for (Repo repo in repos) {
|
for (Repo repo in repos) {
|
||||||
await fetchSourcesList(
|
try {
|
||||||
repo: repo,
|
await fetchSourcesList(
|
||||||
refresh: reFresh,
|
repo: repo,
|
||||||
id: id,
|
refresh: reFresh,
|
||||||
ref: ref,
|
id: id,
|
||||||
itemType: itemType,
|
androidProxyServer: ref.watch(androidProxyServerStateProvider),
|
||||||
);
|
autoUpdateExtensions: ref.watch(autoUpdateExtensionsStateProvider),
|
||||||
|
itemType: itemType,
|
||||||
|
);
|
||||||
|
} catch (_) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
||||||
import 'package:http_interceptor/http_interceptor.dart';
|
import 'package:http_interceptor/http_interceptor.dart';
|
||||||
import 'package:isar_community/isar.dart';
|
import 'package:isar_community/isar.dart';
|
||||||
import 'package:mangayomi/eval/lib.dart';
|
import 'package:mangayomi/eval/lib.dart';
|
||||||
|
|
@ -9,14 +8,14 @@ import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/manga.dart';
|
import 'package:mangayomi/models/manga.dart';
|
||||||
import 'package:mangayomi/models/settings.dart';
|
import 'package:mangayomi/models/settings.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
|
||||||
import 'package:mangayomi/services/http/m_client.dart';
|
import 'package:mangayomi/services/http/m_client.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
|
||||||
Future<void> fetchSourcesList({
|
Future<void> fetchSourcesList({
|
||||||
int? id,
|
int? id,
|
||||||
required bool refresh,
|
required bool refresh,
|
||||||
required Ref ref,
|
required String androidProxyServer,
|
||||||
|
required bool autoUpdateExtensions,
|
||||||
required ItemType itemType,
|
required ItemType itemType,
|
||||||
required Repo? repo,
|
required Repo? repo,
|
||||||
}) async {
|
}) async {
|
||||||
|
|
@ -126,21 +125,21 @@ Future<void> fetchSourcesList({
|
||||||
orElse: () => Source(),
|
orElse: () => Source(),
|
||||||
);
|
);
|
||||||
if (matchingSource.id != null && matchingSource.sourceCodeUrl!.isNotEmpty) {
|
if (matchingSource.id != null && matchingSource.sourceCodeUrl!.isNotEmpty) {
|
||||||
await _updateSource(matchingSource, ref, repo, itemType);
|
await _updateSource(matchingSource, androidProxyServer, repo, itemType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (var source in sourceList) {
|
for (var source in sourceList) {
|
||||||
final existingSource = await isar.sources.get(source.id!);
|
final existingSource = await isar.sources.get(source.id!);
|
||||||
if (existingSource == null) {
|
if (existingSource == null) {
|
||||||
await _addNewSource(source, ref, repo, itemType);
|
await _addNewSource(source, repo, itemType);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final shouldUpdate =
|
final shouldUpdate =
|
||||||
existingSource.isAdded! &&
|
existingSource.isAdded! &&
|
||||||
compareVersions(existingSource.version!, source.version!) < 0;
|
compareVersions(existingSource.version!, source.version!) < 0;
|
||||||
if (!shouldUpdate) continue;
|
if (!shouldUpdate) continue;
|
||||||
if (ref.read(autoUpdateExtensionsStateProvider)) {
|
if (autoUpdateExtensions) {
|
||||||
await _updateSource(source, ref, repo, itemType);
|
await _updateSource(source, androidProxyServer, repo, itemType);
|
||||||
} else {
|
} else {
|
||||||
await isar.writeTxn(() async {
|
await isar.writeTxn(() async {
|
||||||
isar.sources.put(existingSource..versionLast = source.version);
|
isar.sources.put(existingSource..versionLast = source.version);
|
||||||
|
|
@ -149,12 +148,12 @@ Future<void> fetchSourcesList({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkIfSourceIsObsolete(sourceList, repo!, itemType, ref);
|
checkIfSourceIsObsolete(sourceList, repo!, itemType);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _updateSource(
|
Future<void> _updateSource(
|
||||||
Source source,
|
Source source,
|
||||||
Ref ref,
|
String androidProxyServer,
|
||||||
Repo? repo,
|
Repo? repo,
|
||||||
ItemType itemType,
|
ItemType itemType,
|
||||||
) async {
|
) async {
|
||||||
|
|
@ -163,7 +162,7 @@ Future<void> _updateSource(
|
||||||
final sourceCode = source.sourceCodeLanguage == SourceCodeLanguage.mihon
|
final sourceCode = source.sourceCodeLanguage == SourceCodeLanguage.mihon
|
||||||
? base64.encode(req.bodyBytes)
|
? base64.encode(req.bodyBytes)
|
||||||
: req.body;
|
: req.body;
|
||||||
final androidProxyServer = ref.read(androidProxyServerStateProvider);
|
|
||||||
Map<String, String> headers = {};
|
Map<String, String> headers = {};
|
||||||
bool? supportLatest;
|
bool? supportLatest;
|
||||||
FilterList? filterList;
|
FilterList? filterList;
|
||||||
|
|
@ -232,12 +231,7 @@ Future<void> _updateSource(
|
||||||
await isar.writeTxn(() async => isar.sources.put(updatedSource));
|
await isar.writeTxn(() async => isar.sources.put(updatedSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _addNewSource(
|
Future<void> _addNewSource(Source source, Repo? repo, ItemType itemType) async {
|
||||||
Source source,
|
|
||||||
Ref ref,
|
|
||||||
Repo? repo,
|
|
||||||
ItemType itemType,
|
|
||||||
) async {
|
|
||||||
final newSource = Source()
|
final newSource = Source()
|
||||||
..sourceCodeUrl = source.sourceCodeUrl
|
..sourceCodeUrl = source.sourceCodeUrl
|
||||||
..id = source.id
|
..id = source.id
|
||||||
|
|
@ -269,7 +263,6 @@ Future<void> checkIfSourceIsObsolete(
|
||||||
List<Source> sourceList,
|
List<Source> sourceList,
|
||||||
Repo repo,
|
Repo repo,
|
||||||
ItemType itemType,
|
ItemType itemType,
|
||||||
Ref ref,
|
|
||||||
) async {
|
) async {
|
||||||
if (sourceList.isEmpty) return;
|
if (sourceList.isEmpty) return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import 'package:mangayomi/eval/lib.dart';
|
import 'dart:async';
|
||||||
import 'package:mangayomi/eval/model/m_manga.dart';
|
import 'package:mangayomi/eval/model/m_manga.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||||
|
import 'package:mangayomi/services/isolate_service.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
part 'get_detail.g.dart';
|
part 'get_detail.g.dart';
|
||||||
|
|
||||||
|
|
@ -11,8 +12,12 @@ Future<MManga> getDetail(
|
||||||
required String url,
|
required String url,
|
||||||
required Source source,
|
required Source source,
|
||||||
}) async {
|
}) async {
|
||||||
return getExtensionService(
|
final proxyServer = ref.read(androidProxyServerStateProvider);
|
||||||
source,
|
|
||||||
ref.read(androidProxyServerStateProvider),
|
return getIsolateService.get<MManga>(
|
||||||
).getDetail(url);
|
url: url,
|
||||||
|
source: source,
|
||||||
|
serviceType: 'getDetail',
|
||||||
|
proxyServer: proxyServer,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:isar_community/isar.dart';
|
import 'package:isar_community/isar.dart';
|
||||||
import 'package:mangayomi/eval/lib.dart';
|
|
||||||
import 'package:mangayomi/eval/model/m_manga.dart';
|
import 'package:mangayomi/eval/model/m_manga.dart';
|
||||||
import 'package:mangayomi/eval/model/m_pages.dart';
|
import 'package:mangayomi/eval/model/m_pages.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/manga.dart';
|
import 'package:mangayomi/models/manga.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||||
|
import 'package:mangayomi/services/isolate_service.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
part 'get_latest_updates.g.dart';
|
part 'get_latest_updates.g.dart';
|
||||||
|
|
||||||
|
|
@ -38,8 +37,10 @@ Future<MPages?> getLatestUpdates(
|
||||||
.toList();
|
.toList();
|
||||||
return MPages(list: result, hasNextPage: true);
|
return MPages(list: result, hasNextPage: true);
|
||||||
}
|
}
|
||||||
return getExtensionService(
|
return getIsolateService.get<MPages?>(
|
||||||
source,
|
page: page,
|
||||||
ref.read(androidProxyServerStateProvider),
|
source: source,
|
||||||
).getLatestUpdates(page);
|
serviceType: 'getLatestUpdates',
|
||||||
|
proxyServer: ref.read(androidProxyServerStateProvider),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:isar_community/isar.dart';
|
import 'package:isar_community/isar.dart';
|
||||||
import 'package:mangayomi/eval/lib.dart';
|
|
||||||
import 'package:mangayomi/eval/model/m_manga.dart';
|
import 'package:mangayomi/eval/model/m_manga.dart';
|
||||||
import 'package:mangayomi/eval/model/m_pages.dart';
|
import 'package:mangayomi/eval/model/m_pages.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/manga.dart';
|
import 'package:mangayomi/models/manga.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||||
|
import 'package:mangayomi/services/isolate_service.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
part 'get_popular.g.dart';
|
part 'get_popular.g.dart';
|
||||||
|
|
||||||
|
|
@ -38,8 +37,11 @@ Future<MPages?> getPopular(
|
||||||
.toList();
|
.toList();
|
||||||
return MPages(list: result, hasNextPage: true);
|
return MPages(list: result, hasNextPage: true);
|
||||||
}
|
}
|
||||||
return getExtensionService(
|
|
||||||
source,
|
return getIsolateService.get<MPages?>(
|
||||||
ref.read(androidProxyServerStateProvider),
|
page: page,
|
||||||
).getPopular(page);
|
source: source,
|
||||||
|
serviceType: 'getPopular',
|
||||||
|
proxyServer: ref.read(androidProxyServerStateProvider),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class MClient {
|
||||||
);
|
);
|
||||||
return InterceptedClient.build(
|
return InterceptedClient.build(
|
||||||
client: httpClient(settings: clientSettings, reqcopyWith: reqcopyWith),
|
client: httpClient(settings: clientSettings, reqcopyWith: reqcopyWith),
|
||||||
retryPolicy: ResolveCloudFlareChallenge(showCloudFlareError),
|
|
||||||
interceptors: [
|
interceptors: [
|
||||||
MCookieManager(reqcopyWith),
|
MCookieManager(reqcopyWith),
|
||||||
LoggerInterceptor(showCloudFlareError),
|
LoggerInterceptor(showCloudFlareError),
|
||||||
|
|
@ -235,11 +235,15 @@ class LoggerInterceptor extends InterceptorContract {
|
||||||
Logger.add(LoggerLevel.info, content);
|
Logger.add(LoggerLevel.info, content);
|
||||||
}
|
}
|
||||||
if (cloudflare) {
|
if (cloudflare) {
|
||||||
botToast(
|
try {
|
||||||
"${response.statusCode} Failed to bypass Cloudflare",
|
botToast(
|
||||||
hasCloudFlare: cloudflare,
|
"${response.statusCode} Failed to bypass Cloudflare",
|
||||||
url: response.request!.url.toString(),
|
hasCloudFlare: cloudflare,
|
||||||
);
|
url: response.request!.url.toString(),
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
throw "${response.statusCode} Failed to bypass Cloudflare";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,78 +256,78 @@ bool isCloudflare(BaseResponse response) {
|
||||||
["cloudflare-nginx", "cloudflare"].contains(response.headers["server"]);
|
["cloudflare-nginx", "cloudflare"].contains(response.headers["server"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ResolveCloudFlareChallenge extends RetryPolicy {
|
// class ResolveCloudFlareChallenge extends RetryPolicy {
|
||||||
bool showCloudFlareError;
|
// bool showCloudFlareError;
|
||||||
ResolveCloudFlareChallenge(this.showCloudFlareError);
|
// ResolveCloudFlareChallenge(this.showCloudFlareError);
|
||||||
@override
|
// @override
|
||||||
int get maxRetryAttempts => 2;
|
// int get maxRetryAttempts => 2;
|
||||||
@override
|
// @override
|
||||||
Future<bool> shouldAttemptRetryOnResponse(BaseResponse response) async {
|
// Future<bool> shouldAttemptRetryOnResponse(BaseResponse response) async {
|
||||||
if (!showCloudFlareError || Platform.isLinux) return false;
|
// if (!showCloudFlareError || Platform.isLinux) return false;
|
||||||
flutter_inappwebview.HeadlessInAppWebView? headlessWebView;
|
// flutter_inappwebview.HeadlessInAppWebView? headlessWebView;
|
||||||
int time = 0;
|
// int time = 0;
|
||||||
bool timeOut = false;
|
// bool timeOut = false;
|
||||||
bool isCloudFlare = isCloudflare(response);
|
// bool isCloudFlare = isCloudflare(response);
|
||||||
if (isCloudFlare) {
|
// if (isCloudFlare) {
|
||||||
headlessWebView = flutter_inappwebview.HeadlessInAppWebView(
|
// headlessWebView = flutter_inappwebview.HeadlessInAppWebView(
|
||||||
webViewEnvironment: webViewEnvironment,
|
// webViewEnvironment: webViewEnvironment,
|
||||||
initialUrlRequest: flutter_inappwebview.URLRequest(
|
// initialUrlRequest: flutter_inappwebview.URLRequest(
|
||||||
url: flutter_inappwebview.WebUri(response.request!.url.toString()),
|
// url: flutter_inappwebview.WebUri(response.request!.url.toString()),
|
||||||
),
|
// ),
|
||||||
onLoadStop: (controller, url) async {
|
// onLoadStop: (controller, url) async {
|
||||||
try {
|
// try {
|
||||||
isCloudFlare = await controller.platform.evaluateJavascript(
|
// isCloudFlare = await controller.platform.evaluateJavascript(
|
||||||
source:
|
// source:
|
||||||
"document.head.innerHTML.includes('#challenge-success-text')",
|
// "document.head.innerHTML.includes('#challenge-success-text')",
|
||||||
);
|
// );
|
||||||
} catch (_) {
|
// } catch (_) {
|
||||||
isCloudFlare = false;
|
// isCloudFlare = false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
await Future.doWhile(() async {
|
// await Future.doWhile(() async {
|
||||||
if (!timeOut && isCloudFlare) {
|
// if (!timeOut && isCloudFlare) {
|
||||||
try {
|
// try {
|
||||||
isCloudFlare = await controller.platform.evaluateJavascript(
|
// isCloudFlare = await controller.platform.evaluateJavascript(
|
||||||
source:
|
// source:
|
||||||
"document.head.innerHTML.includes('#challenge-success-text')",
|
// "document.head.innerHTML.includes('#challenge-success-text')",
|
||||||
);
|
// );
|
||||||
} catch (_) {
|
// } catch (_) {
|
||||||
isCloudFlare = false;
|
// isCloudFlare = false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (isCloudFlare) await Future.delayed(Duration(milliseconds: 300));
|
// if (isCloudFlare) await Future.delayed(Duration(milliseconds: 300));
|
||||||
|
|
||||||
return isCloudFlare;
|
// return isCloudFlare;
|
||||||
});
|
// });
|
||||||
if (!timeOut) {
|
// if (!timeOut) {
|
||||||
final ua =
|
// final ua =
|
||||||
await controller.evaluateJavascript(
|
// await controller.evaluateJavascript(
|
||||||
source: "navigator.userAgent",
|
// source: "navigator.userAgent",
|
||||||
) ??
|
// ) ??
|
||||||
"";
|
// "";
|
||||||
await MClient.setCookie(url.toString(), ua, controller);
|
// await MClient.setCookie(url.toString(), ua, controller);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
);
|
// );
|
||||||
|
|
||||||
headlessWebView.run();
|
// headlessWebView.run();
|
||||||
|
|
||||||
await Future.doWhile(() async {
|
// await Future.doWhile(() async {
|
||||||
timeOut = time == 15;
|
// timeOut = time == 15;
|
||||||
if (!isCloudFlare || timeOut) {
|
// if (!isCloudFlare || timeOut) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
await Future.delayed(const Duration(seconds: 1));
|
// await Future.delayed(const Duration(seconds: 1));
|
||||||
time++;
|
// time++;
|
||||||
return true;
|
// return true;
|
||||||
});
|
// });
|
||||||
try {
|
// try {
|
||||||
headlessWebView.dispose();
|
// headlessWebView.dispose();
|
||||||
} catch (_) {}
|
// } catch (_) {}
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
183
lib/services/isolate_service.dart
Normal file
183
lib/services/isolate_service.dart
Normal file
|
|
@ -0,0 +1,183 @@
|
||||||
|
import 'dart:async';
|
||||||
|
import 'dart:isolate';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
|
import 'package:mangayomi/eval/lib.dart';
|
||||||
|
import 'package:mangayomi/main.dart';
|
||||||
|
import 'package:mangayomi/models/manga.dart';
|
||||||
|
import 'package:mangayomi/models/settings.dart';
|
||||||
|
import 'package:mangayomi/models/source.dart';
|
||||||
|
import 'package:mangayomi/providers/storage_provider.dart';
|
||||||
|
|
||||||
|
class _IsolateData {
|
||||||
|
final SendPort sendPort;
|
||||||
|
final RootIsolateToken rootIsolateToken;
|
||||||
|
|
||||||
|
_IsolateData({required this.sendPort, required this.rootIsolateToken});
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetIsolateService {
|
||||||
|
bool _isRunning = false;
|
||||||
|
Isolate? _getIsolateService;
|
||||||
|
ReceivePort? _receivePort;
|
||||||
|
SendPort? _sendPort;
|
||||||
|
|
||||||
|
Future<void> start() async {
|
||||||
|
if (!_isRunning) {
|
||||||
|
try {
|
||||||
|
await _initGetIsolateService();
|
||||||
|
} catch (_) {
|
||||||
|
await stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _initGetIsolateService() async {
|
||||||
|
_receivePort = ReceivePort();
|
||||||
|
|
||||||
|
final rootToken = RootIsolateToken.instance!;
|
||||||
|
|
||||||
|
_getIsolateService = await Isolate.spawn(
|
||||||
|
_getIsolateServiceEntryPoint,
|
||||||
|
_IsolateData(
|
||||||
|
sendPort: _receivePort!.sendPort,
|
||||||
|
rootIsolateToken: rootToken,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final completer = Completer<SendPort>();
|
||||||
|
_receivePort!.listen((message) {
|
||||||
|
if (message is SendPort) {
|
||||||
|
completer.complete(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_sendPort = await completer.future;
|
||||||
|
_isRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> _getIsolateServiceEntryPoint(
|
||||||
|
_IsolateData isolateData,
|
||||||
|
) async {
|
||||||
|
BackgroundIsolateBinaryMessenger.ensureInitialized(
|
||||||
|
isolateData.rootIsolateToken,
|
||||||
|
);
|
||||||
|
|
||||||
|
await initializeDateFormatting();
|
||||||
|
|
||||||
|
isar = await StorageProvider().initDB(null, inspector: kDebugMode);
|
||||||
|
|
||||||
|
final receivePort = ReceivePort();
|
||||||
|
isolateData.sendPort.send(receivePort.sendPort);
|
||||||
|
|
||||||
|
await for (var message in receivePort) {
|
||||||
|
if (message is Map<String, dynamic>) {
|
||||||
|
try {
|
||||||
|
final url = message['url'] as String?;
|
||||||
|
final page = message['page'] as int?;
|
||||||
|
final query = message['query'] as String?;
|
||||||
|
final filterList = message['filterList'] as List?;
|
||||||
|
final source = message['source'] as Source?;
|
||||||
|
final proxyServer = message['proxyServer'] as String?;
|
||||||
|
final serviceType = message['serviceType'] as String?;
|
||||||
|
final responsePort = message['responsePort'] as SendPort;
|
||||||
|
|
||||||
|
if (serviceType == 'getDetail') {
|
||||||
|
final result = await getExtensionService(
|
||||||
|
source!,
|
||||||
|
proxyServer ?? '',
|
||||||
|
).getDetail(url!);
|
||||||
|
responsePort.send({'success': true, 'data': result});
|
||||||
|
} else if (serviceType == 'getPopular') {
|
||||||
|
final result = await getExtensionService(
|
||||||
|
source!,
|
||||||
|
proxyServer ?? '',
|
||||||
|
).getPopular(page!);
|
||||||
|
responsePort.send({'success': true, 'data': result});
|
||||||
|
} else if (serviceType == 'getLatestUpdates') {
|
||||||
|
final result = await getExtensionService(
|
||||||
|
source!,
|
||||||
|
proxyServer ?? '',
|
||||||
|
).getLatestUpdates(page!);
|
||||||
|
responsePort.send({'success': true, 'data': result});
|
||||||
|
} else if (serviceType == 'search') {
|
||||||
|
final result = await getExtensionService(
|
||||||
|
source!,
|
||||||
|
proxyServer ?? '',
|
||||||
|
).search(query!, page!, filterList!);
|
||||||
|
responsePort.send({'success': true, 'data': result});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
final responsePort = message['responsePort'] as SendPort;
|
||||||
|
responsePort.send({'success': false, 'error': e.toString()});
|
||||||
|
}
|
||||||
|
} else if (message == 'dispose') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<T> get<T>({
|
||||||
|
int? id,
|
||||||
|
bool? refresh,
|
||||||
|
ItemType? itemType,
|
||||||
|
Repo? repo,
|
||||||
|
String? url,
|
||||||
|
int? page,
|
||||||
|
String? query,
|
||||||
|
List<dynamic>? filterList,
|
||||||
|
Source? source,
|
||||||
|
String? serviceType,
|
||||||
|
String? proxyServer,
|
||||||
|
bool? autoUpdateExtensions,
|
||||||
|
String? androidProxyServer,
|
||||||
|
}) async {
|
||||||
|
if (_sendPort == null) {
|
||||||
|
throw Exception('Isolate not running');
|
||||||
|
}
|
||||||
|
|
||||||
|
final responsePort = ReceivePort();
|
||||||
|
final completer = Completer<T>();
|
||||||
|
|
||||||
|
responsePort.listen((response) {
|
||||||
|
responsePort.close();
|
||||||
|
if (response is Map<String, dynamic>) {
|
||||||
|
if (response['success'] == true) {
|
||||||
|
completer.complete(response['data'] as T);
|
||||||
|
} else {
|
||||||
|
completer.completeError(response['error']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_sendPort!.send({
|
||||||
|
'url': url,
|
||||||
|
'page': page,
|
||||||
|
'query': query,
|
||||||
|
'filterList': filterList,
|
||||||
|
'serviceType': serviceType,
|
||||||
|
'source': source,
|
||||||
|
'proxyServer': proxyServer,
|
||||||
|
'responsePort': responsePort.sendPort,
|
||||||
|
});
|
||||||
|
|
||||||
|
return completer.future;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> stop() async {
|
||||||
|
if (!_isRunning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sendPort?.send('dispose');
|
||||||
|
_getIsolateService?.kill(priority: Isolate.immediate);
|
||||||
|
_receivePort?.close();
|
||||||
|
_sendPort = null;
|
||||||
|
_getIsolateService = null;
|
||||||
|
_receivePort = null;
|
||||||
|
_isRunning = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final getIsolateService = GetIsolateService();
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:isar_community/isar.dart';
|
import 'package:isar_community/isar.dart';
|
||||||
import 'package:mangayomi/eval/lib.dart';
|
|
||||||
import 'package:mangayomi/eval/model/m_manga.dart';
|
import 'package:mangayomi/eval/model/m_manga.dart';
|
||||||
import 'package:mangayomi/eval/model/m_pages.dart';
|
import 'package:mangayomi/eval/model/m_pages.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/manga.dart';
|
import 'package:mangayomi/models/manga.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||||
|
import 'package:mangayomi/services/isolate_service.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
part 'search.g.dart';
|
part 'search.g.dart';
|
||||||
|
|
||||||
|
|
@ -40,8 +39,12 @@ Future<MPages?> search(
|
||||||
.toList();
|
.toList();
|
||||||
return MPages(list: result, hasNextPage: true);
|
return MPages(list: result, hasNextPage: true);
|
||||||
}
|
}
|
||||||
return getExtensionService(
|
return getIsolateService.get<MPages?>(
|
||||||
source,
|
query: query,
|
||||||
ref.read(androidProxyServerStateProvider),
|
filterList: filterList,
|
||||||
).search(query, page, filterList);
|
source: source,
|
||||||
|
page: page,
|
||||||
|
serviceType: 'search',
|
||||||
|
proxyServer: ref.read(androidProxyServerStateProvider),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import 'package:isar_community/isar.dart';
|
import 'package:isar_community/isar.dart';
|
||||||
import 'package:mangayomi/eval/lib.dart';
|
|
||||||
import 'package:mangayomi/eval/model/m_manga.dart';
|
import 'package:mangayomi/eval/model/m_manga.dart';
|
||||||
import 'package:mangayomi/eval/model/m_pages.dart';
|
import 'package:mangayomi/eval/model/m_pages.dart';
|
||||||
import 'package:mangayomi/main.dart';
|
import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/manga.dart';
|
import 'package:mangayomi/models/manga.dart';
|
||||||
import 'package:mangayomi/models/source.dart';
|
import 'package:mangayomi/models/source.dart';
|
||||||
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
import 'package:mangayomi/modules/more/settings/browse/providers/browse_state_provider.dart';
|
||||||
|
import 'package:mangayomi/services/isolate_service.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
part 'search_.g.dart';
|
part 'search_.g.dart';
|
||||||
|
|
||||||
|
|
@ -37,8 +37,12 @@ Future<MPages?> search(
|
||||||
.toList();
|
.toList();
|
||||||
return MPages(list: result, hasNextPage: true);
|
return MPages(list: result, hasNextPage: true);
|
||||||
}
|
}
|
||||||
return getExtensionService(
|
return getIsolateService.get<MPages?>(
|
||||||
source,
|
query: query,
|
||||||
ref.read(androidProxyServerStateProvider),
|
filterList: filterList,
|
||||||
).search(query, page, filterList);
|
source: source,
|
||||||
|
page: page,
|
||||||
|
serviceType: 'search',
|
||||||
|
proxyServer: ref.read(androidProxyServerStateProvider),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue