add source test mode , fix m_bridge

This commit is contained in:
kodjomoustapha 2023-10-08 15:48:41 +01:00
parent 129467edfa
commit b51dd3f8aa
16 changed files with 419 additions and 389 deletions

View file

@ -118,13 +118,13 @@ class MBridge {
}
///Returns all descendant nodes matching the given selectors, using a preorder traversal.
static String querySelectorAll(String html, String selector, int typeElement,
String attributes, int typeRegExp, int position, String join) {
static List<String> querySelectorAll(String html, String selector,
int typeElement, String attributes, int typeRegExp) {
try {
var parse = parser.parse(html);
final a = parse.querySelectorAll(selector);
List<dynamic> res = [];
List<String> res = [];
for (var element in a) {
//text
if (typeElement == 0) {
@ -149,21 +149,10 @@ class MBridge {
}
// if (typeRegExp == 0) is the default parameter
if (typeRegExp == 0) {
//join the list
if (position == 0) {
return res.join(join);
}
//return first element of the list
else if (position == 1) {
return res.first;
}
//return last element of the list
return res.last;
return res;
}
List<dynamic> resRegExp = [];
List<String> resRegExp = [];
for (var element in res) {
//get first element of href that match
if (typeRegExp == 1) {
@ -186,19 +175,7 @@ class MBridge {
resRegExp.add(regImgMatcher(element.trim().trimLeft().trimRight()));
}
}
//join the resRegExp list
if (position == 0) {
return resRegExp.join(join);
}
//return first element of the resRegExp list
else if (position == 1) {
return resRegExp.first.trim().trimLeft().trimRight();
}
//return last element of the resRegExp list
return resRegExp.last.trim().trimLeft().trimRight();
return resRegExp;
} catch (e) {
botToast(e.toString());
throw Exception(e);
@ -206,7 +183,7 @@ class MBridge {
}
///Create query by html string
static String xpath(String html, String xpath, String join) {
static List<String> xpath(String html, String xpath) {
try {
List<String?> attrs = [];
var htmlXPath = HtmlXPath.html(html);
@ -217,18 +194,18 @@ class MBridge {
attrs.add(element!.trim().trimLeft().trimRight());
}
//Join the attrs list
return attrs.join(join);
return attrs.map((e) => e!).toList();
}
//Return one attr
else {
String? attr =
String attr =
query.attr != null ? query.attr!.trim().trimLeft().trimRight() : "";
return attr;
return [attr];
}
} catch (e) {
// botToast(e.toString());
return "";
return [];
}
}
@ -296,9 +273,8 @@ class MBridge {
webview
..setApplicationNameForUserAgent(defaultUserAgent)
..launch(url);
await Future.doWhile(() async {
await Future.delayed(const Duration(seconds: 1));
await Future.delayed(const Duration(seconds: 3));
html = await decodeHtml(
webview,
);
@ -309,15 +285,6 @@ class MBridge {
return false;
});
html = await decodeHtml(webview);
isOk = true;
await Future.doWhile(() async {
await Future.delayed(const Duration(seconds: 1));
if (isOk == true) {
return false;
}
return true;
});
html = await decodeHtml(webview);
webview.close();
} else {
HeadlessInAppWebView? headlessWebView;
@ -433,10 +400,10 @@ class MBridge {
}
///GetMapValue
static String getMapValue(String source, String attr, int type) {
static String getMapValue(String source, String attr, bool encode) {
try {
var map = json.decode(source) as Map<String, dynamic>;
if (type == 0) {
if (!encode) {
return map[attr] != null ? map[attr].toString() : "";
}
return map[attr] != null ? jsonEncode(map[attr]) : "";
@ -595,7 +562,7 @@ class MBridge {
: method == 2
? 'PUT'
: 'DELETE',
Uri.parse(jsonDecode(url)["url"]));
Uri.parse(url));
request.fields.addAll(fields);
request.headers.addAll(headers);
@ -618,20 +585,21 @@ class MBridge {
}
//http request and also webview
static Future<String> http(String url, int method) async {
static Future<String> http(String method, String datas) async {
try {
hp.StreamedResponse? res;
String result = "";
//Get headers
final headersMap = jsonDecode(url)["headers"] as Map?;
final headersMap = jsonDecode(datas)["headers"] as Map?;
//Get sourceId
final sourceId = jsonDecode(url)["sourceId"] as int?;
final sourceId = jsonDecode(datas)["sourceId"] as int?;
//Get body
final bodyMap = jsonDecode(url)["body"] as Map?;
final bodyMap = jsonDecode(datas)["body"] as Map?;
final url = jsonDecode(datas)["url"] as String;
//Convert body Map<dynamic,dynamic> to Map<String,String>
Map<String, dynamic> body = {};
if (bodyMap != null) {
@ -649,24 +617,14 @@ class MBridge {
final source = sourceId != null ? isar.sources.getSync(sourceId) : null;
//Check the serie if has cloudflare
if (source != null && source.hasCloudflare!) {
final res = await cloudflareBypass(
url: jsonDecode(url)["url"],
sourceId: source.id.toString(),
method: method);
return res;
}
// if (source != null && source.hasCloudflare!) {
// final res = await cloudflareBypass(
// url: url, sourceId: source.id.toString(), method: method);
// return res;
// }
//Do the http request if the serie hasn't cloudflare
var request = hp.Request(
method == 0
? 'GET'
: method == 1
? 'POST'
: method == 2
? 'PUT'
: 'DELETE',
Uri.parse(jsonDecode(url)["url"]));
var request = hp.Request(method, Uri.parse(url));
if (bodyMap != null) {
request.body = json.encode(body);
@ -676,7 +634,10 @@ class MBridge {
res = await request.send();
if (res.statusCode != 200) {
if (res.statusCode != 200 && source != null && source.hasCloudflare!) {
result = await cloudflareBypass(
url: url, sourceId: source.id.toString(), method: 0);
} else if (res.statusCode != 200) {
result = "400";
} else if (res.statusCode == 200) {
result = await res.stream.bytesToString();
@ -731,16 +692,22 @@ class MBridge {
}
//Utility to use substring
static String subString(String text, String pattern, int type) {
String result = "";
if (type == 0) {
result = text.substringBefore(pattern);
} else if (type == 1) {
result = text.split(pattern).last;
} else if (type == 2) {
result = text.substringAfter(pattern);
}
return result;
static String substringAfter(String text, String pattern) {
return text.substringAfter(pattern);
}
//Utility to use substring
static String substringBefore(String text, String pattern) {
return text.substringBefore(pattern);
}
//Utility to use substring
static String substringBeforeLast(String text, String pattern) {
return text.substringBeforeLast(pattern);
}
static String substringAfterLast(String text, String pattern) {
return text.split(pattern).last;
}
//Parse a chapter date to millisecondsSinceEpoch
@ -1318,7 +1285,7 @@ class $MBridge extends MBridge with $Bridge {
],
namedParams: []),
isStatic: true),
'subString': BridgeMethodDef(
'substringAfter': BridgeMethodDef(
BridgeFunctionDef(
returns: BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
@ -1333,10 +1300,59 @@ class $MBridge extends MBridge with $Bridge {
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
],
namedParams: []),
isStatic: true),
'substringBefore': BridgeMethodDef(
BridgeFunctionDef(
returns: BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
params: [
BridgeParameter(
'type',
'text',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.intType)),
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
BridgeParameter(
'pattern',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
],
namedParams: []),
isStatic: true),
'substringBeforeLast': BridgeMethodDef(
BridgeFunctionDef(
returns: BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
params: [
BridgeParameter(
'text',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
BridgeParameter(
'pattern',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
],
namedParams: []),
isStatic: true),
'substringAfterLast': BridgeMethodDef(
BridgeFunctionDef(
returns: BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
params: [
BridgeParameter(
'text',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
BridgeParameter(
'pattern',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
],
namedParams: []),
@ -1440,13 +1456,15 @@ class $MBridge extends MBridge with $Bridge {
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
BridgeParameter(
'type',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.intType)),
false),
],
namedParams: []),
namedParams: [
BridgeParameter(
'encode',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.boolType),
nullable: true),
true),
]),
isStatic: true),
'jsonPathToList': BridgeMethodDef(
BridgeFunctionDef(
@ -1614,14 +1632,16 @@ class $MBridge extends MBridge with $Bridge {
isStatic: true),
'querySelectorAll': BridgeMethodDef(
BridgeFunctionDef(
returns: BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list,
[BridgeTypeRef.type(RuntimeTypes.stringType)])),
params: [
BridgeParameter(
'html',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
],
namedParams: [
BridgeParameter(
'selector',
BridgeTypeAnnotation(
@ -1642,23 +1662,12 @@ class $MBridge extends MBridge with $Bridge {
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.intType)),
false),
BridgeParameter(
'position',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.intType)),
false),
BridgeParameter(
'join',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
],
namedParams: []),
]),
isStatic: true),
'xpath': BridgeMethodDef(
BridgeFunctionDef(
returns: BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list,
[BridgeTypeRef.type(RuntimeTypes.stringType)])),
params: [
BridgeParameter(
'html',
@ -1670,11 +1679,6 @@ class $MBridge extends MBridge with $Bridge {
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
BridgeParameter(
'join',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
],
namedParams: []),
isStatic: true),
@ -1684,14 +1688,14 @@ class $MBridge extends MBridge with $Bridge {
[BridgeTypeRef.type(RuntimeTypes.stringType)])),
params: [
BridgeParameter(
'url',
'method',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
BridgeParameter(
'method',
'datas',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.intType)),
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
],
namedParams: []),
@ -1943,8 +1947,10 @@ class $MBridge extends MBridge with $Bridge {
Runtime runtime, $Value? target, List<$Value?> args) =>
$MBridge();
static $String $xpath(Runtime runtime, $Value? target, List<$Value?> args) =>
$String(MBridge.xpath(args[0]!.$value, args[1]!.$value, args[2]!.$value));
static $Value $xpath(Runtime runtime, $Value? target, List<$Value?> args) =>
$List.wrap(MBridge.xpath(args[0]!.$value, args[1]!.$value)
.map((e) => $String(e))
.toList());
static $List $listParse(Runtime runtime, $Value? target, List<$Value?> args) {
return $List.wrap(MBridge.listParse(
@ -1985,19 +1991,29 @@ class $MBridge extends MBridge with $Bridge {
static $String $jsonPathToString(
Runtime runtime, $Value? target, List<$Value?> args) {
return $String(MBridge.jsonPathToString(
args[0]!.$value,
args[1]!.$value,
args[2]!.$value,
));
args[0]!.$value, args[1]!.$value, args[2]!.$value));
}
static $String $subString(
static $String $substringAfter(
Runtime runtime, $Value? target, List<$Value?> args) {
return $String(MBridge.subString(
args[0]!.$value,
args[1]!.$value,
args[2]!.$value,
));
return $String(MBridge.substringAfter(args[0]!.$value, args[1]!.$value));
}
static $String $substringAfterLast(
Runtime runtime, $Value? target, List<$Value?> args) {
return $String(
MBridge.substringAfterLast(args[0]!.$value, args[1]!.$value));
}
static $String $substringBefore(
Runtime runtime, $Value? target, List<$Value?> args) {
return $String(MBridge.substringBefore(args[0]!.$value, args[1]!.$value));
}
static $String $substringBeforeLast(
Runtime runtime, $Value? target, List<$Value?> args) {
return $String(
MBridge.substringBeforeLast(args[0]!.$value, args[1]!.$value));
}
static $String $getMapValue(
@ -2005,7 +2021,7 @@ class $MBridge extends MBridge with $Bridge {
return $String(MBridge.getMapValue(
args[0]!.$value,
args[1]!.$value,
args[2]!.$value,
args[2]?.$value ?? false,
));
}
@ -2103,16 +2119,13 @@ class $MBridge extends MBridge with $Bridge {
Runtime runtime, $Value? target, List<$Value?> args) =>
$String(MBridge.deobfuscateJsPassword(args[0]!.$value));
static $String $querySelectorAll(
static $Value $querySelectorAll(
Runtime runtime, $Value? target, List<$Value?> args) =>
$String(MBridge.querySelectorAll(
args[0]!.$value,
args[1]!.$value,
args[2]!.$value,
args[3]!.$value,
args[4]!.$value,
args[5]!.$value,
args[6]!.$value));
$List.wrap(MBridge.querySelectorAll(args[0]!.$value, args[1]!.$value,
args[2]!.$value, args[3]!.$value, args[4]!.$value)
.map((e) => $String(e))
.toList());
static $Future $http(Runtime runtime, $Value? target, List<$Value?> args) =>
$Future.wrap(MBridge.http(args[0]!.$value, args[1]!.$value)
.then((value) => $String(value)));

View file

@ -84,7 +84,13 @@ Runtime runtimeEval(Uint8List bytecode) {
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
'MBridge.stringParse', $MBridge.$stringParse);
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
'MBridge.subString', $MBridge.$subString);
'MBridge.substringAfter', $MBridge.$substringAfter);
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
'MBridge.substringAfterLast', $MBridge.$substringAfterLast);
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
'MBridge.substringBeforeLast', $MBridge.$substringBeforeLast);
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',
'MBridge.substringBefore', $MBridge.$substringBefore);
runtime.registerBridgeFunc(
'package:bridge_lib/bridge_lib.dart', 'MBridge.evalJs', $MBridge.$evalJs);
runtime.registerBridgeFunc('package:bridge_lib/bridge_lib.dart',

View file

@ -433,7 +433,7 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
_playbackSpeed.value = speed;
}
Future<void> _togglePlaybackSpeed() async {
void _togglePlaybackSpeed() {
List<double> allowedSpeeds = [0.25, 0.5, 0.75, 1.0, 1.25, 1.50, 1.75, 2.0];
if (allowedSpeeds.indexOf(_playbackSpeed.value) <
allowedSpeeds.length - 1) {
@ -444,6 +444,26 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
}
}
Future<void> _changeFitLabel(WidgetRef ref) async {
List<BoxFit> fitList = [
BoxFit.contain,
BoxFit.cover,
BoxFit.fill,
BoxFit.fitHeight,
BoxFit.fitWidth,
BoxFit.none
];
ref.read(_showFitLabel.notifier).state = true;
if (fitList.indexOf(ref.watch(_fit)) < fitList.length - 1) {
ref.read(_fit.notifier).state =
fitList[fitList.indexOf(ref.watch(_fit)) + 1];
} else {
ref.read(_fit.notifier).state = fitList[0];
}
await Future.delayed(const Duration(seconds: 1));
ref.read(_showFitLabel.notifier).state = false;
}
List<Widget> _bottomButtonBar(BuildContext context, bool isFullScreen) {
bool hasPrevEpisode = _streamController.getEpisodeIndex() + 1 !=
_streamController.getEpisodesLength();
@ -514,25 +534,14 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
onPressed: () {
_togglePlaybackSpeed();
}),
MaterialButton(
child: const Icon(Icons.fit_screen,
size: 30, color: Colors.white),
onPressed: () async {
ref.read(_showFitLabel.notifier).state = true;
final fit = switch (ref.watch(_fit)) {
BoxFit.contain => BoxFit.cover,
BoxFit.cover => BoxFit.fill,
BoxFit.fill => BoxFit.fitHeight,
BoxFit.fitHeight => BoxFit.fitWidth,
BoxFit.fitWidth => BoxFit.none,
BoxFit.none => BoxFit.scaleDown,
_ => BoxFit.contain,
};
ref.read(_fit.notifier).state = fit;
await Future.delayed(const Duration(seconds: 1));
ref.read(_showFitLabel.notifier).state = false;
},
),
if (!isFullScreen)
MaterialButton(
child: const Icon(Icons.fit_screen,
size: 30, color: Colors.white),
onPressed: () async {
_changeFitLabel(ref);
},
),
if (_isDesktop)
const MaterialDesktopFullscreenButton()
],
@ -673,12 +682,11 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
Video(
subtitleViewConfiguration: const SubtitleViewConfiguration(
style: TextStyle(
height: 2,
fontSize: 40,
fontSize: 50,
fontWeight: FontWeight.bold,
color: Colors.white,
fontFamily: "",
shadows: [Shadow(offset: Offset(0.0, 0.0), blurRadius: 7.0)],
shadows: [Shadow(offset: Offset(0.2, 0.0), blurRadius: 7.0)],
backgroundColor: Colors.transparent),
),
fit: fit,

View file

@ -83,8 +83,7 @@ Future<List<String>> downloadChapter(
await File("${mangaDir!.path}${chapter.name}.cbz").exists() &&
ref.watch(saveAsCBZArchiveStateProvider);
bool mp4FileExist =
await File("${mangaDir.path}${chapter.name}.mp4").exists() &&
ref.watch(saveAsCBZArchiveStateProvider);
await File("${mangaDir.path}${chapter.name}.mp4").exists();
if (!cbzFileExist || !mp4FileExist) {
for (var index = 0; index < pageUrls.length; index++) {
final path2 = Directory("${path1.path}downloads/");

View file

@ -1,6 +1,6 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:image/image.dart';
// import 'package:image/image.dart';
import 'package:mangayomi/modules/manga/reader/reader_view.dart';
import 'package:mangayomi/utils/reg_exp_matcher.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
@ -43,86 +43,87 @@ Future<Uint8List?> autoCropImageBorder(AutoCropImageBorderRef ref,
Future<Uint8List?> cropImageWithThread(
Uint8List? imageBytes,
) async {
Command crop = Command();
crop.decodeImage(imageBytes!);
Command encode = Command();
encode.subCommand = crop;
// Command crop = Command();
// crop.decodeImage(imageBytes!);
// Command encode = Command();
// encode.subCommand = crop;
final image = await encode.getImageThread();
int left = 0;
int top = 0;
int right = image!.width;
int bottom = image.height;
// final image = await encode.getImageThread();
// int left = 0;
// int top = 0;
// int right = image!.width;
// int bottom = image.height;
// Find left coordinate
for (int x = 0; x < image.width; x++) {
bool stop = false;
for (int y = 0; y < image.height; y++) {
if (image.getPixel(x, y).toString() != "(255, 255, 255)") {
stop = true;
break;
}
}
if (stop) {
left = x;
break;
}
}
// // Find left coordinate
// for (int x = 0; x < image.width; x++) {
// bool stop = false;
// for (int y = 0; y < image.height; y++) {
// if (image.getPixel(x, y).toString() != "(255, 255, 255)") {
// stop = true;
// break;
// }
// }
// if (stop) {
// left = x;
// break;
// }
// }
// Find top coordinate
for (int y = 0; y < image.height; y++) {
bool stop = false;
for (int x = 0; x < image.width; x++) {
if (image.getPixel(x, y).toString() != "(255, 255, 255)") {
stop = true;
break;
}
}
if (stop) {
top = y;
break;
}
}
// // Find top coordinate
// for (int y = 0; y < image.height; y++) {
// bool stop = false;
// for (int x = 0; x < image.width; x++) {
// if (image.getPixel(x, y).toString() != "(255, 255, 255)") {
// stop = true;
// break;
// }
// }
// if (stop) {
// top = y;
// break;
// }
// }
// Find right coordinate
for (int x = image.width - 1; x >= 0; x--) {
bool stop = false;
for (int y = 0; y < image.height; y++) {
if (image.getPixel(x, y).toString() != "(255, 255, 255)") {
stop = true;
break;
}
}
if (stop) {
right = x;
break;
}
}
// // Find right coordinate
// for (int x = image.width - 1; x >= 0; x--) {
// bool stop = false;
// for (int y = 0; y < image.height; y++) {
// if (image.getPixel(x, y).toString() != "(255, 255, 255)") {
// stop = true;
// break;
// }
// }
// if (stop) {
// right = x;
// break;
// }
// }
// Find bottom coordinate
for (int y = image.height - 1; y >= 0; y--) {
bool stop = false;
for (int x = 0; x < image.width; x++) {
if (image.getPixel(x, y).toString() != "(255, 255, 255)") {
stop = true;
break;
}
}
if (stop) {
bottom = y;
break;
}
}
// // Find bottom coordinate
// for (int y = image.height - 1; y >= 0; y--) {
// bool stop = false;
// for (int x = 0; x < image.width; x++) {
// if (image.getPixel(x, y).toString() != "(255, 255, 255)") {
// stop = true;
// break;
// }
// }
// if (stop) {
// bottom = y;
// break;
// }
// }
crop.copyCrop(
x: left,
y: top,
width: right - left,
height: bottom - top,
);
// crop.copyCrop(
// x: left,
// y: top,
// width: right - left,
// height: bottom - top,
// );
encode.subCommand = crop;
encode.encodeJpg();
// encode.subCommand = crop;
// encode.encodeJpg();
return encode.getBytesThread();
// return encode.getBytesThread();
return null;
}

View file

@ -389,7 +389,7 @@ class _MangaChapterPageGalleryState
final double _imageDetailY = 0;
void _onBtnTapped(int index, bool isPrev, {bool isSlide = false}) {
if (_isView) {
if (_isView && !isSlide) {
_isViewFunction();
}
final readerMode = ref.watch(_selectedValue);
@ -1151,25 +1151,21 @@ class _MangaChapterPageGalleryState
: _onBtnTapped(_currentIndex! + 1, false),
LogicalKeyboardKey.arrowDown =>
_onBtnTapped(_currentIndex! + 1, true),
LogicalKeyboardKey.pageDown ||
LogicalKeyboardKey.keyN =>
hasNextChapter
? () {
pushReplacementMangaReaderView(
context: context,
chapter: _readerController.getNextChapter(),
);
}
: null,
LogicalKeyboardKey.pageUp ||
LogicalKeyboardKey.keyP =>
hasPrevChapter
? () {
pushReplacementMangaReaderView(
context: context,
chapter: _readerController.getPrevChapter());
}
: null,
LogicalKeyboardKey.keyN || LogicalKeyboardKey.pageDown => switch (
hasNextChapter) {
true => pushReplacementMangaReaderView(
context: context,
chapter: _readerController.getNextChapter(),
),
_ => null
},
LogicalKeyboardKey.keyP || LogicalKeyboardKey.pageUp => switch (
hasPrevChapter) {
true => pushReplacementMangaReaderView(
context: context,
chapter: _readerController.getPrevChapter()),
_ => null
},
_ => null
};
action;
@ -1275,6 +1271,9 @@ class _MangaChapterPageGalleryState
}
if (state.extendedImageLoadState ==
LoadState.completed) {
if (_failedToLoadImage.value == true) {
_failedToLoadImage.value = false;
}
return StreamBuilder(
builder: (context, data) {
return ExtendedImageGesture(
@ -1300,7 +1299,9 @@ class _MangaChapterPageGalleryState
}
if (state.extendedImageLoadState ==
LoadState.failed) {
_failedToLoadImage.value = true;
if (_failedToLoadImage.value == false) {
_failedToLoadImage.value = true;
}
return Container(
color: getBackgroundColor(
backgroundColor),

View file

@ -1,4 +1,3 @@
// ignore_for_file: use_build_context_synchronously
import 'dart:convert';
import 'package:bot_toast/bot_toast.dart';
import 'package:flutter/material.dart';
@ -27,36 +26,38 @@ checkForUpdate(CheckForUpdateRef ref,
BotToast.showText(text: l10n.new_update_available);
await Future.delayed(const Duration(seconds: 1));
}
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(l10n.new_update_available),
content: Text(
"${l10n.app_version(updateAvailable.$1)}\n\n${updateAvailable.$2}"),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(l10n.cancel)),
const SizedBox(
width: 15,
),
ElevatedButton(
onPressed: () {
_launchInBrowser(Uri.parse(updateAvailable.$3));
},
child: Text(l10n.download)),
],
)
],
);
},
);
if (context.mounted) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(l10n.new_update_available),
content: Text(
"${l10n.app_version(updateAvailable.$1)}\n\n${updateAvailable.$2}"),
actions: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(l10n.cancel)),
const SizedBox(
width: 15,
),
ElevatedButton(
onPressed: () {
_launchInBrowser(Uri.parse(updateAvailable.$3));
},
child: Text(l10n.download)),
],
)
],
);
},
);
}
} else if (compareVersions(info.version, updateAvailable.$1) == 0) {
if (manualUpdate) {
BotToast.showText(text: l10n.no_new_updates_available);

View file

@ -9,6 +9,7 @@ import 'package:mangayomi/models/video.dart';
import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/providers/storage_provider.dart';
import 'package:mangayomi/sources/utils/utils.dart';
import 'package:mangayomi/sources/source_test.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_anime_servers.g.dart';
@ -30,9 +31,10 @@ Future<(List<Video>, bool)> getAnimeServers(
return ([Video(path!, episode.name!, path, subtitles: [])], true);
}
final source =
getSource(episode.manga.value!.lang!, episode.manga.value!.source!);
getSource(episode.manga.value!.lang!, episode.manga.value!.source!)!;
final bytecode = compilerEval(source!.sourceCode!);
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
final runtime = runtimeEval(bytecode);
runtime.args = [

View file

@ -16,6 +16,7 @@ import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/sources/utils/utils.dart';
import 'package:mangayomi/utils/reg_exp_matcher.dart';
import 'package:mangayomi/modules/more/providers/incognito_mode_state_provider.dart';
import 'package:mangayomi/sources/source_test.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_chapter_url.g.dart';
@ -56,13 +57,14 @@ Future<GetChapterUrlModel> getChapterUrl(
final isLocalArchive = (chapter.archivePath ?? '').isNotEmpty;
if (!chapter.manga.value!.isLocalArchive!) {
final source =
getSource(chapter.manga.value!.lang!, chapter.manga.value!.source!);
getSource(chapter.manga.value!.lang!, chapter.manga.value!.source!)!;
if (isarPageUrls.isNotEmpty &&
isarPageUrls.first.urls != null &&
isarPageUrls.first.urls!.isNotEmpty) {
pageUrls = isarPageUrls.first.urls!;
} else {
final bytecode = compilerEval(source!.sourceCode!);
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
final runtime = runtimeEval(bytecode);
runtime.args = [

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
import 'package:mangayomi/eval/bridge_class/model.dart';
import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/sources/source_test.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_latest_updates_manga.g.dart';
@ -14,7 +15,8 @@ Future<List<MangaModel?>> getLatestUpdatesManga(
required int page,
}) async {
List<MangaModel?>? latestUpdatesManga = [];
final bytecode = compilerEval(source.sourceCode!);
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
final runtime = runtimeEval(bytecode);
runtime.args = [

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
import 'package:mangayomi/eval/bridge_class/model.dart';
import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/sources/source_test.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_manga_detail.g.dart';
@ -14,7 +15,8 @@ Future<MangaModel> getMangaDetail(
required Source source,
}) async {
MangaModel? mangadetail;
final bytecode = compilerEval(source.sourceCode!);
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
final runtime = runtimeEval(bytecode);
runtime.args = [

View file

@ -4,6 +4,7 @@ import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
import 'package:mangayomi/eval/bridge_class/model.dart';
import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/sources/source_test.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_popular_manga.g.dart';
@ -14,7 +15,8 @@ Future<List<MangaModel?>> getPopularManga(
required int page,
}) async {
List<MangaModel> popularManga = [];
final bytecode = compilerEval(source.sourceCode!);
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
final runtime = runtimeEval(bytecode);
runtime.args = [

View file

@ -3,6 +3,7 @@ import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
import 'package:mangayomi/eval/bridge_class/model.dart';
import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/sources/source_test.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'search_manga.g.dart';
@ -14,7 +15,8 @@ Future<List<MangaModel?>> searchManga(
required int page,
}) async {
List<MangaModel?>? manga = [];
final bytecode = compilerEval(source.sourceCode!);
final bytecode =
compilerEval(useTestSourceCode ? testSourceCode : source.sourceCode!);
final runtime = runtimeEval(bytecode);
runtime.args = [

View file

@ -0,0 +1,2 @@
const useTestSourceCode = false;
const testSourceCode = '''''';

View file

@ -5,34 +5,34 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
url: "https://pub.dev"
source: hosted
version: "61.0.0"
version: "64.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
url: "https://pub.dev"
source: hosted
version: "5.13.0"
version: "6.2.0"
analyzer_plugin:
dependency: transitive
description:
name: analyzer_plugin
sha256: c1d5f167683de03d5ab6c3b53fc9aeefc5d59476e7810ba7bbddff50c6f4392d
sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161"
url: "https://pub.dev"
source: hosted
version: "0.11.2"
version: "0.11.3"
archive:
dependency: "direct main"
description:
name: archive
sha256: e0902a06f0e00414e4e3438a084580161279f137aeb862274710f29ec10cf01e
sha256: "06a96f1249f38a00435b3b0c9a3246d934d7dbc8183fc7c9e56989860edb99d4"
url: "https://pub.dev"
source: hosted
version: "3.3.9"
version: "3.4.4"
args:
dependency: transitive
description:
@ -61,10 +61,10 @@ packages:
dependency: "direct main"
description:
name: background_downloader
sha256: "661bd9bfb12067fb8ccf75073b8fba692d80d97e4d6e0762500c29fa40a787a6"
sha256: "9a00bf2e24fa577ca238698cd658a1e858b9897b6efebe5558ead733b34b32d6"
url: "https://pub.dev"
source: hosted
version: "7.9.4"
version: "7.10.0"
boolean_selector:
dependency: transitive
description:
@ -77,10 +77,10 @@ packages:
dependency: "direct main"
description:
name: bot_toast
sha256: "994c55aa16c4df82726b79a63c1f8d29bd7b89d940a5837728ff51546b630497"
sha256: "6b93030a99a98335b8827ecd83021e92e885ffc61d261d3825ffdecdd17f3bdf"
url: "https://pub.dev"
source: hosted
version: "4.1.1"
version: "4.1.3"
build:
dependency: transitive
description:
@ -109,10 +109,10 @@ packages:
dependency: transitive
description:
name: build_resolvers
sha256: d912852cce27c9e80a93603db721c267716894462e7033165178b91138587972
sha256: "64e12b0521812d1684b1917bc80945625391cb9bdd4312536b1d69dcb6133ed8"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
version: "2.4.1"
build_runner:
dependency: "direct dev"
description:
@ -125,10 +125,10 @@ packages:
dependency: transitive
description:
name: build_runner_core
sha256: "6d6ee4276b1c5f34f21fdf39425202712d2be82019983d52f351c94aafbc2c41"
sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185
url: "https://pub.dev"
source: hosted
version: "7.2.10"
version: "7.2.11"
built_collection:
dependency: transitive
description:
@ -141,34 +141,34 @@ packages:
dependency: transitive
description:
name: built_value
sha256: ff627b645b28fb8bdb69e645f910c2458fd6b65f6585c3a53e0626024897dedf
sha256: a8de5955205b4d1dbbbc267daddf2178bd737e4bab8987c04a500478c9651e74
url: "https://pub.dev"
source: hosted
version: "8.6.2"
version: "8.6.3"
cached_network_image:
dependency: "direct main"
description:
name: cached_network_image
sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15
sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f
url: "https://pub.dev"
source: hosted
version: "3.2.3"
version: "3.3.0"
cached_network_image_platform_interface:
dependency: transitive
description:
name: cached_network_image_platform_interface
sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7
sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613"
url: "https://pub.dev"
source: hosted
version: "2.0.0"
version: "3.0.0"
cached_network_image_web:
dependency: transitive
description:
name: cached_network_image_web
sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0
sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
version: "1.1.0"
characters:
dependency: transitive
description:
@ -213,10 +213,10 @@ packages:
dependency: transitive
description:
name: code_builder
sha256: "315a598c7fbe77f22de1c9da7cfd6fd21816312f16ffa124453b4fc679e540f1"
sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677"
url: "https://pub.dev"
source: hosted
version: "4.6.0"
version: "4.7.0"
collection:
dependency: transitive
description:
@ -285,10 +285,10 @@ packages:
dependency: "direct main"
description:
name: dart_eval
sha256: "9d11db96f2b396d0ad09504182e6e17d05e2fb22e92ec3aa21d4fde744c83171"
sha256: c043685c0ea425c79d324e944a8c3c499f251e118d41103aa3448a4eb95ed7f8
url: "https://pub.dev"
source: hosted
version: "0.6.0"
version: "0.6.3"
dart_style:
dependency: transitive
description:
@ -349,10 +349,10 @@ packages:
dependency: "direct main"
description:
name: encrypt
sha256: c1f224c9a65df6f2cd111baaf31edd2f31d3f094abdb22a3b0bbcc64698ef80d
sha256: "62d9aa4670cc2a8798bab89b39fc71b6dfbacf615de6cf5001fb39f7e4a996a2"
url: "https://pub.dev"
source: hosted
version: "5.0.2"
version: "5.0.3"
exception_templates:
dependency: transitive
description:
@ -454,14 +454,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_blurhash:
dependency: transitive
description:
name: flutter_blurhash
sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
flutter_cache_manager:
dependency: transitive
description:
@ -511,10 +503,10 @@ packages:
dependency: "direct main"
description:
name: flutter_riverpod
sha256: "1bd39b04f1bcd217a969589777ca6bd642d116e3e5de65c3e6a8e8bdd8b178ec"
sha256: fcea39b84b666649280f6f678bc0bb479253bf865abc0387a8b11dac6477bf92
url: "https://pub.dev"
source: hosted
version: "2.4.0"
version: "2.4.1"
flutter_test:
dependency: "direct dev"
description: flutter
@ -577,10 +569,10 @@ packages:
dependency: "direct main"
description:
name: go_router
sha256: "5668e6d3dbcb2d0dfa25f7567554b88c57e1e3f3c440b672b24d4a9477017d5b"
sha256: e1a30a66d734f9e498b1b6522d6a75ded28242bad2359a9158df38a1c30bcf1f
url: "https://pub.dev"
source: hosted
version: "10.1.2"
version: "10.2.0"
google_fonts:
dependency: "direct main"
description:
@ -646,13 +638,13 @@ packages:
source: hosted
version: "4.0.2"
image:
dependency: "direct main"
dependency: transitive
description:
name: image
sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf
sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271"
url: "https://pub.dev"
source: hosted
version: "4.0.17"
version: "4.1.3"
infinite_listview:
dependency: transitive
description:
@ -793,74 +785,74 @@ packages:
dependency: "direct main"
description:
name: media_kit
sha256: "92c7f59e075d74471b31e703f81ccc1d7102739ebcce945b30a6417fa2f751d5"
sha256: "1283b500341d41f033478706204a2b4ae2612e9b331c934bc4fad8c4bb869f6d"
url: "https://pub.dev"
source: hosted
version: "1.1.7"
version: "1.1.8+2"
media_kit_libs_android_video:
dependency: transitive
description:
name: media_kit_libs_android_video
sha256: "498a5062bc5f000bd23ada3be788ea886ab32c52f7a8252dde1264ca019b819b"
sha256: a7ef60926ac528e2fabe9ee7084e648e385422a881ba914c978a7a81e6595dee
url: "https://pub.dev"
source: hosted
version: "1.3.3"
version: "1.3.5"
media_kit_libs_ios_video:
dependency: transitive
description:
name: media_kit_libs_ios_video
sha256: fed403dc9d54462e51ee80e0cb23c12a53fadea9a8fa18aca2de9054176d1159
sha256: b5382994eb37a4564c368386c154ad70ba0cc78dacdd3fb0cd9f30db6d837991
url: "https://pub.dev"
source: hosted
version: "1.1.3"
version: "1.1.4"
media_kit_libs_linux:
dependency: transitive
description:
name: media_kit_libs_linux
sha256: "3b7c272179639a914dc8a50bf8a3f2df0e9a503bd727c88fab499dbdf6cb1eb8"
sha256: e186891c31daa6bedab4d74dcdb4e8adfccc7d786bfed6ad81fe24a3b3010310
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.1.3"
media_kit_libs_macos_video:
dependency: transitive
description:
name: media_kit_libs_macos_video
sha256: c06e831f3c22a45296d375788d9bc07871b448f8e9ec98d77b11e5e118a83fb2
sha256: f26aa1452b665df288e360393758f84b911f70ffb3878032e1aabba23aa1032d
url: "https://pub.dev"
source: hosted
version: "1.1.3"
version: "1.1.4"
media_kit_libs_video:
dependency: "direct main"
description:
name: media_kit_libs_video
sha256: d961c49bc0d454524014b76fd66db1aa06e673f03b616f5fdbc59c405178a878
sha256: f130964bd4c0907d0af645ba03c8080a914776bfd2e23761a5e22ac3c0c0906a
url: "https://pub.dev"
source: hosted
version: "1.0.1"
version: "1.0.3"
media_kit_libs_windows_video:
dependency: transitive
description:
name: media_kit_libs_windows_video
sha256: "923f068344d7d200184e0aaa2597f3de6c05982a3b1f18035d842ab53f2a1350"
sha256: "7bace5f35d9afcc7f9b5cdadb7541d2191a66bb3fc71bfa11c1395b3360f6122"
url: "https://pub.dev"
source: hosted
version: "1.0.8"
version: "1.0.9"
media_kit_native_event_loop:
dependency: transitive
description:
name: media_kit_native_event_loop
sha256: e37ce6fb5fa71b8cf513c6a6cd591367743a342a385e7da621a047dd8ef6f4a4
sha256: a605cf185499d14d58935b8784955a92a4bf0ff4e19a23de3d17a9106303930e
url: "https://pub.dev"
source: hosted
version: "1.0.7"
version: "1.0.8"
media_kit_video:
dependency: "direct main"
description:
name: media_kit_video
sha256: cd3ab78e7626146f115134b82c4029ac5987ba6351719c9067d86789723e0c12
sha256: b1a427f0540c5f052dfab73e4b76a5eb8efa7ebb5d83179cb23fc3932afc315a
url: "https://pub.dev"
source: hosted
version: "1.1.8"
version: "1.2.1"
meta:
dependency: transitive
description:
@ -889,10 +881,10 @@ packages:
dependency: transitive
description:
name: octo_image
sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143"
sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
version: "2.0.0"
package_config:
dependency: transitive
description:
@ -985,10 +977,10 @@ packages:
dependency: transitive
description:
name: permission_handler_android
sha256: f23cfe9af0d49c6b9fd8a8b09f7b3301ca7e346204939b5afef4404d36d2608f
sha256: ace7d15a3d1a4a0b91c041d01e5405df221edb9de9116525efc773c74e6fc790
url: "https://pub.dev"
source: hosted
version: "11.0.1"
version: "11.0.5"
permission_handler_apple:
dependency: transitive
description:
@ -1069,14 +1061,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
pubspec2:
dependency: transitive
description:
name: pubspec2
sha256: "7b1fd81927f1da6d88457c83b51134e1bc8cb07638bd8d9e205b2ce1cd9ec091"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
pubspec_parse:
dependency: transitive
description:
@ -1113,34 +1097,34 @@ packages:
dependency: transitive
description:
name: riverpod
sha256: a600120d6f213a9922860eea1abc32597436edd5b2c4e73b91410f8c2af67d22
sha256: ff676bd8a715c7085692fe4919564f78fb90d33b10a1c5c14e740581857cc914
url: "https://pub.dev"
source: hosted
version: "2.4.0"
version: "2.4.1"
riverpod_analyzer_utils:
dependency: transitive
description:
name: riverpod_analyzer_utils
sha256: aa216069d72f5478126029fa555874b4b38119f17e3f0f6c93fd63365f74502d
sha256: d72d7096964baf288b55619fe48100001fc4564ab7923ed0a7f5c7650e03c0d6
url: "https://pub.dev"
source: hosted
version: "0.3.3"
version: "0.3.4"
riverpod_annotation:
dependency: "direct main"
description:
name: riverpod_annotation
sha256: "6294fe7e7d1875f32bdf04c8fce7620e718070273703097847df8f3bf16995ea"
sha256: aeeb1eb6ccf2d779f2ef730e6d96d560316b677662222316779a8cf0a94ee317
url: "https://pub.dev"
source: hosted
version: "2.1.5"
version: "2.1.6"
riverpod_generator:
dependency: "direct dev"
description:
name: riverpod_generator
sha256: d132b1ccb476e60f99989caa6ba9b1c4d88409806c93d880d1633c60c382454d
sha256: "5b36ad2f2b562cffb37212e8d59390b25499bf045b732276e30a207b16a25f61"
url: "https://pub.dev"
source: hosted
version: "2.3.2"
version: "2.3.3"
rxdart:
dependency: transitive
description:
@ -1518,10 +1502,10 @@ packages:
dependency: transitive
description:
name: win32
sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa"
sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
url: "https://pub.dev"
source: hosted
version: "5.0.7"
version: "5.0.9"
window_to_front:
dependency: transitive
description:
@ -1579,5 +1563,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.1.2 <4.0.0"
dart: ">=3.1.3 <4.0.0"
flutter: ">=3.13.0"

View file

@ -1,10 +1,10 @@
name: mangayomi
description: Free and open source manga reader and anime streaming cross-plateform app inspired by Tachiyomi.
publish_to: 'none'
version: 0.0.45+18
environment:
sdk: '>=3.1.2 <4.0.0'
sdk: '>=3.1.3 <4.0.0'
dependencies:
@ -29,7 +29,7 @@ dependencies:
google_fonts: ^5.1.0
url_launcher: ^6.1.12
package_info_plus: ^4.1.0
background_downloader: ^7.9.4
background_downloader: ^7.10.0
permission_handler: ^11.0.0
flutter_inappwebview: ^5.7.2+3
draggable_menu: ^4.1.3
@ -41,18 +41,21 @@ dependencies:
archive: ^3.3.9
file_picker: ^5.3.3
path_provider: ^2.1.0
image: ^4.0.17
# image: ^4.0.17
scrollable_positioned_list: ^0.3.5
dart_eval: ^0.6.0
dart_eval: ^0.6.3
# git:
# url: https://github.com/kodjodevf/dart_eval.git
# ref: 05c54b2
json_path: ^0.6.2
bot_toast: ^4.0.4
flutter_web_auth_2: ^2.1.5
numberpicker: ^2.1.2
encrypt: ^5.0.1
js_packer: ^0.0.5
media_kit: ^1.1.7
media_kit_video: ^1.1.8
media_kit_libs_video: ^1.0.1
media_kit: ^1.1.8+2
media_kit_video: ^1.2.1
media_kit_libs_video: ^1.0.3
crypto: ^3.0.3