fix & reformat
This commit is contained in:
parent
0c84faa5f8
commit
a41ccaff22
228 changed files with 8642 additions and 3604 deletions
|
|
@ -9,13 +9,15 @@ import 'package:mangayomi/eval/model/element.dart';
|
|||
class $MDocument implements MDocument, $Instance {
|
||||
$MDocument.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MDocument'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MDocument'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('document', BridgeTypeAnnotation($Element.$type, nullable: true), false),
|
||||
BridgeParameter('document',
|
||||
BridgeTypeAnnotation($Element.$type, nullable: true), false),
|
||||
]),
|
||||
)
|
||||
},
|
||||
|
|
@ -36,60 +38,118 @@ class $MDocument implements MDocument, $Instance {
|
|||
returns: BridgeTypeAnnotation($MElement.$type, nullable: true),
|
||||
)),
|
||||
'outerHtml': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'text': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'children': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$MElement.$type]), nullable: true),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$MElement.$type]),
|
||||
nullable: true),
|
||||
)),
|
||||
},
|
||||
methods: {
|
||||
'select': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$MElement.$type]), nullable: true),
|
||||
params: [BridgeParameter('selector', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$MElement.$type]),
|
||||
nullable: true),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'selector',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'selectFirst': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($MElement.$type, nullable: true),
|
||||
params: [BridgeParameter('selector', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'selector',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'getElementsByClassName': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$type]), nullable: true),
|
||||
params: [BridgeParameter('classNames', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$type]),
|
||||
nullable: true),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'classNames',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'getElementsByTagName': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$type]), nullable: true),
|
||||
params: [BridgeParameter('localNames', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$type]),
|
||||
nullable: true),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'localNames',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'getElementById': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($MElement.$type, nullable: true),
|
||||
params: [BridgeParameter('id', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'id',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'xpath': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])),
|
||||
params: [BridgeParameter('xpath', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'xpath',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'xpathFirst': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
params: [BridgeParameter('xpath', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'xpath',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'attr': BridgeMethodDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), params: [
|
||||
BridgeParameter('attr', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true), false)
|
||||
]),
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'attr',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'hasAttr': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
params: [BridgeParameter('attr', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'attr',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
},
|
||||
wrap: true);
|
||||
|
|
@ -125,7 +185,9 @@ class $MDocument implements MDocument, $Instance {
|
|||
return res == null ? const $null() : $String(res);
|
||||
case 'children':
|
||||
final res = $value.children;
|
||||
return res == null ? const $null() : $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
case 'select':
|
||||
return __select;
|
||||
case 'selectFirst':
|
||||
|
|
@ -156,59 +218,79 @@ class $MDocument implements MDocument, $Instance {
|
|||
void $setProperty(Runtime runtime, String identifier, $Value value) {}
|
||||
|
||||
static const $Function __select = $Function(_select);
|
||||
static $Value? _select(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _select(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).select(args[0]?.$value);
|
||||
return res == null ? const $null() : $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
}
|
||||
|
||||
static const $Function __selectFirst = $Function(_selectFirst);
|
||||
static $Value? _selectFirst(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _selectFirst(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).selectFirst(args[0]?.$value);
|
||||
return res == null ? const $null() : $MElement.wrap(res);
|
||||
}
|
||||
|
||||
static $Value? $new(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? $new(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
return $MDocument.wrap(MDocument(args[0]?.$value));
|
||||
}
|
||||
|
||||
static const $Function __getElementsByClassName = $Function(_getElementsByClassName);
|
||||
static $Value? _getElementsByClassName(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).getElementsByClassName(args[0]?.$value);
|
||||
return res == null ? const $null() : $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
static const $Function __getElementsByClassName =
|
||||
$Function(_getElementsByClassName);
|
||||
static $Value? _getElementsByClassName(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res =
|
||||
(target!.$value as MDocument).getElementsByClassName(args[0]?.$value);
|
||||
return res == null
|
||||
? const $null()
|
||||
: $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
}
|
||||
|
||||
static const $Function __getElementsByTagName = $Function(_getElementsByTagName);
|
||||
static $Value? _getElementsByTagName(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).getElementsByTagName(args[0]?.$value);
|
||||
return res == null ? const $null() : $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
static const $Function __getElementsByTagName =
|
||||
$Function(_getElementsByTagName);
|
||||
static $Value? _getElementsByTagName(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res =
|
||||
(target!.$value as MDocument).getElementsByTagName(args[0]?.$value);
|
||||
return res == null
|
||||
? const $null()
|
||||
: $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
}
|
||||
|
||||
static const $Function __getElementById = $Function(_getElementById);
|
||||
static $Value? _getElementById(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _getElementById(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).getElementById(args[0]?.$value);
|
||||
return res == null ? const $null() : $MElement.wrap(res);
|
||||
}
|
||||
|
||||
static const $Function __xpath = $Function(_xpath);
|
||||
static $Value? _xpath(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _xpath(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).xpath(args[0]?.$value);
|
||||
return $List.wrap(res.map((e) => $String(e)).toList());
|
||||
}
|
||||
|
||||
static const $Function __xpathFirst = $Function(_xpathFirst);
|
||||
static $Value? _xpathFirst(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _xpathFirst(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).xpathFirst(args[0]?.$value);
|
||||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
||||
static const $Function __attr = $Function(_attr);
|
||||
static $Value? _attr(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _attr(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).attr(args[0]?.$value ?? "");
|
||||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
||||
static const $Function __hasAttr = $Function(_hasAttr);
|
||||
static $Value? _hasAttr(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _hasAttr(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MDocument).attr(args[0]?.$value ?? "");
|
||||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
|
@ -226,10 +308,12 @@ class $MDocument implements MDocument, $Instance {
|
|||
String? xpathFirst(String xpath) => $value.xpathFirst(xpath);
|
||||
|
||||
@override
|
||||
List<MElement>? getElementsByClassName(String classNames) => $value.getElementsByClassName(classNames);
|
||||
List<MElement>? getElementsByClassName(String classNames) =>
|
||||
$value.getElementsByClassName(classNames);
|
||||
|
||||
@override
|
||||
List<MElement>? getElementsByTagName(String localNames) => $value.getElementsByTagName(localNames);
|
||||
List<MElement>? getElementsByTagName(String localNames) =>
|
||||
$value.getElementsByTagName(localNames);
|
||||
|
||||
@override
|
||||
String? attr(String attr) => $value.attr(attr);
|
||||
|
|
@ -265,11 +349,15 @@ class $MDocument implements MDocument, $Instance {
|
|||
class $Document implements $Instance {
|
||||
$Document.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'Document'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'Document'));
|
||||
|
||||
static const $declaration = BridgeClassDef(
|
||||
BridgeClassType($type),
|
||||
constructors: {'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type, nullable: true)))},
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type, nullable: true)))
|
||||
},
|
||||
wrap: true,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,13 +5,15 @@ import 'package:mangayomi/eval/model/element.dart';
|
|||
|
||||
class $MElement implements MElement, $Instance {
|
||||
$MElement.wrap(this.$value) : _superclass = $Object($value);
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MElement'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MElement'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('element', BridgeTypeAnnotation($Element.$type, nullable: true), false),
|
||||
BridgeParameter('element',
|
||||
BridgeTypeAnnotation($Element.$type, nullable: true), false),
|
||||
]),
|
||||
)
|
||||
},
|
||||
|
|
@ -20,37 +22,48 @@ class $MElement implements MElement, $Instance {
|
|||
},
|
||||
getters: {
|
||||
'outerHtml': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'innerHtml': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'text': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'className': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'localName': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'namespaceUri': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'getSrc': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'getImg': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'getHref': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'getDataSrc': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'children': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$type]), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$type]),
|
||||
nullable: true),
|
||||
)),
|
||||
'parent': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type, nullable: true),
|
||||
|
|
@ -64,48 +77,100 @@ class $MElement implements MElement, $Instance {
|
|||
},
|
||||
methods: {
|
||||
'attr': BridgeMethodDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), params: [
|
||||
BridgeParameter('attr', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true), false)
|
||||
]),
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'attr',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'text': BridgeMethodDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true)),
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true)),
|
||||
),
|
||||
'select': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$type]), nullable: true),
|
||||
params: [BridgeParameter('selector', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$type]),
|
||||
nullable: true),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'selector',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'selectFirst': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type, nullable: true),
|
||||
params: [BridgeParameter('selector', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'selector',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'getElementsByClassName': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$type]), nullable: true),
|
||||
params: [BridgeParameter('classNames', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$type]),
|
||||
nullable: true),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'classNames',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'getElementsByTagName': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$type]), nullable: true),
|
||||
params: [BridgeParameter('localNames', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$type]),
|
||||
nullable: true),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'localNames',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'xpath': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]),
|
||||
nullable: true),
|
||||
params: [BridgeParameter('xpath', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'xpath',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'xpathFirst': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
params: [BridgeParameter('xpath', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'xpath',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
'hasAttr': BridgeMethodDef(
|
||||
BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
params: [BridgeParameter('attr', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false)]),
|
||||
params: [
|
||||
BridgeParameter(
|
||||
'attr',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
false)
|
||||
]),
|
||||
),
|
||||
},
|
||||
wrap: true);
|
||||
|
|
@ -129,28 +194,44 @@ class $MElement implements MElement, $Instance {
|
|||
return res == null ? const $null() : $String(res);
|
||||
case 'text':
|
||||
final res = $value.text;
|
||||
return res == null ? const $null() : $String(res.trim().trimLeft().trimRight());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $String(res.trim().trimLeft().trimRight());
|
||||
case 'className':
|
||||
final res = $value.className;
|
||||
return res == null ? const $null() : $String(res.trim().trimLeft().trimRight());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $String(res.trim().trimLeft().trimRight());
|
||||
case 'localName':
|
||||
final res = $value.localName;
|
||||
return res == null ? const $null() : $String(res.trim().trimLeft().trimRight());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $String(res.trim().trimLeft().trimRight());
|
||||
case 'namespaceUri':
|
||||
final res = $value.namespaceUri;
|
||||
return res == null ? const $null() : $String(res.trim().trimLeft().trimRight());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $String(res.trim().trimLeft().trimRight());
|
||||
case 'getSrc':
|
||||
final res = $value.getSrc;
|
||||
return res == null ? const $null() : $String(res.trim().trimLeft().trimRight());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $String(res.trim().trimLeft().trimRight());
|
||||
case 'getImg':
|
||||
final res = $value.getImg;
|
||||
return res == null ? const $null() : $String(res.trim().trimLeft().trimRight());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $String(res.trim().trimLeft().trimRight());
|
||||
case 'getHref':
|
||||
final res = $value.getHref;
|
||||
return res == null ? const $null() : $String(res.trim().trimLeft().trimRight());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $String(res.trim().trimLeft().trimRight());
|
||||
case 'getDataSrc':
|
||||
final res = $value.getDataSrc;
|
||||
return res == null ? const $null() : $String(res.trim().trimLeft().trimRight());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $String(res.trim().trimLeft().trimRight());
|
||||
case 'parent':
|
||||
final res = $value.parent;
|
||||
return res == null ? const $null() : $MElement.wrap(res);
|
||||
|
|
@ -187,62 +268,83 @@ class $MElement implements MElement, $Instance {
|
|||
@override
|
||||
void $setProperty(Runtime runtime, String identifier, $Value value) {}
|
||||
|
||||
static $Value? $new(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? $new(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
return $MElement.wrap(MElement(args[0]?.$value));
|
||||
}
|
||||
|
||||
static const $Function __attr = $Function(_attr);
|
||||
|
||||
static $Value? _attr(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _attr(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).attr(args[0]?.$value ?? "");
|
||||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
||||
static const $Function __select = $Function(_select);
|
||||
|
||||
static $Value? _select(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _select(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).select(args[0]?.$value);
|
||||
return res == null ? const $null() : $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
}
|
||||
|
||||
static const $Function __selectFirst = $Function(_selectFirst);
|
||||
|
||||
static $Value? _selectFirst(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _selectFirst(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).selectFirst(args[0]?.$value);
|
||||
return res == null ? const $null() : $MElement.wrap(res);
|
||||
}
|
||||
|
||||
static const $Function __getElementsByClassName = $Function(_getElementsByClassName);
|
||||
static const $Function __getElementsByClassName =
|
||||
$Function(_getElementsByClassName);
|
||||
|
||||
static $Value? _getElementsByClassName(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).getElementsByClassName(args[0]?.$value);
|
||||
return res == null ? const $null() : $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
static $Value? _getElementsByClassName(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res =
|
||||
(target!.$value as MElement).getElementsByClassName(args[0]?.$value);
|
||||
return res == null
|
||||
? const $null()
|
||||
: $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
}
|
||||
|
||||
static const $Function __getElementsByTagName = $Function(_getElementsByTagName);
|
||||
static const $Function __getElementsByTagName =
|
||||
$Function(_getElementsByTagName);
|
||||
|
||||
static $Value? _getElementsByTagName(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).getElementsByTagName(args[0]?.$value);
|
||||
return res == null ? const $null() : $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
static $Value? _getElementsByTagName(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res =
|
||||
(target!.$value as MElement).getElementsByTagName(args[0]?.$value);
|
||||
return res == null
|
||||
? const $null()
|
||||
: $List.wrap(res.map((e) => $MElement.wrap(e)).toList());
|
||||
}
|
||||
|
||||
static const $Function __xpath = $Function(_xpath);
|
||||
|
||||
static $Value? _xpath(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _xpath(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).xpath(args[0]?.$value);
|
||||
return res == null ? const $null() : $List.wrap(res.map((e) => $String(e)).toList());
|
||||
return res == null
|
||||
? const $null()
|
||||
: $List.wrap(res.map((e) => $String(e)).toList());
|
||||
}
|
||||
|
||||
static const $Function __xpathFirst = $Function(_xpathFirst);
|
||||
|
||||
static $Value? _xpathFirst(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _xpathFirst(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).xpathFirst(args[0]?.$value);
|
||||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
||||
static const $Function __hasAttr = $Function(_hasAttr);
|
||||
|
||||
static $Value? _hasAttr(final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
static $Value? _hasAttr(
|
||||
final Runtime runtime, final $Value? target, final List<$Value?> args) {
|
||||
final res = (target!.$value as MElement).attr(args[0]?.$value ?? "");
|
||||
return res == null ? const $null() : $String(res);
|
||||
}
|
||||
|
|
@ -266,10 +368,12 @@ class $MElement implements MElement, $Instance {
|
|||
List<MElement>? get children => $value.children;
|
||||
|
||||
@override
|
||||
List<MElement>? getElementsByClassName(String classNames) => $value.getElementsByClassName(classNames);
|
||||
List<MElement>? getElementsByClassName(String classNames) =>
|
||||
$value.getElementsByClassName(classNames);
|
||||
|
||||
@override
|
||||
List<MElement>? getElementsByTagName(String localNames) => $value.getElementsByTagName(localNames);
|
||||
List<MElement>? getElementsByTagName(String localNames) =>
|
||||
$value.getElementsByTagName(localNames);
|
||||
|
||||
@override
|
||||
bool hasAttr(String attr) => $value.hasAttr(attr);
|
||||
|
|
@ -317,11 +421,15 @@ class $MElement implements MElement, $Instance {
|
|||
class $Element implements $Instance {
|
||||
$Element.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'Element'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'Element'));
|
||||
|
||||
static const $declaration = BridgeClassDef(
|
||||
BridgeClassType($type),
|
||||
constructors: {'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type, nullable: true)))},
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type, nullable: true)))
|
||||
},
|
||||
wrap: true,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,18 +5,24 @@ import 'package:mangayomi/eval/model/filter.dart';
|
|||
class $FilterList implements FilterList, $Instance {
|
||||
$FilterList.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'FilterList'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'FilterList'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('filters',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), false),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter(
|
||||
'filters',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'filters': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
),
|
||||
},
|
||||
wrap: true);
|
||||
|
|
@ -51,7 +57,9 @@ class $FilterList implements FilterList, $Instance {
|
|||
void $setProperty(Runtime runtime, String identifier, $Value value) {
|
||||
switch (identifier) {
|
||||
case 'filters':
|
||||
$value.filters = (value.$reified as List).map((e) => e is $Value ? e.$reified : e).toList();
|
||||
$value.filters = (value.$reified as List)
|
||||
.map((e) => e is $Value ? e.$reified : e)
|
||||
.toList();
|
||||
default:
|
||||
_superclass.$setProperty(runtime, identifier, value);
|
||||
}
|
||||
|
|
@ -72,26 +80,37 @@ class $FilterList implements FilterList, $Instance {
|
|||
class $SelectFilter implements SelectFilter, $Instance {
|
||||
$SelectFilter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SelectFilter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SelectFilter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('state', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('state',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false),
|
||||
BridgeParameter(
|
||||
'values', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), false),
|
||||
'values',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'type': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'state': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.int),
|
||||
)),
|
||||
'values': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
),
|
||||
},
|
||||
wrap: true);
|
||||
|
|
@ -109,7 +128,8 @@ class $SelectFilter implements SelectFilter, $Instance {
|
|||
map = value.map((key, value) => MapEntry(key.toString(), value));
|
||||
if (map['type'] == 'SelectOption') {
|
||||
final filter = map['filter'] as Map;
|
||||
return SelectFilterOption.fromJson(filter.map((key, value) => MapEntry(key.toString(), value)));
|
||||
return SelectFilterOption.fromJson(filter
|
||||
.map((key, value) => MapEntry(key.toString(), value)));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
|
|
@ -202,23 +222,30 @@ class $SelectFilter implements SelectFilter, $Instance {
|
|||
class $SelectFilterOption implements SelectFilterOption, $Instance {
|
||||
$SelectFilterOption.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SelectFilterOption'));
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec(
|
||||
'package:mangayomi/bridge_lib.dart', 'SelectFilterOption'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
return $SelectFilterOption.wrap(SelectFilterOption(args[0]!.$value, args[1]!.$value, null));
|
||||
return $SelectFilterOption
|
||||
.wrap(SelectFilterOption(args[0]!.$value, args[1]!.$value, null));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -285,21 +312,26 @@ class $SelectFilterOption implements SelectFilterOption, $Instance {
|
|||
class $SeparatorFilter implements SeparatorFilter, $Instance {
|
||||
$SeparatorFilter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SeparatorFilter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SeparatorFilter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'type': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
return $SeparatorFilter.wrap(SeparatorFilter(null, type: args[0]?.$value ?? ''));
|
||||
return $SeparatorFilter
|
||||
.wrap(SeparatorFilter(null, type: args[0]?.$value ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -355,23 +387,30 @@ class $SeparatorFilter implements SeparatorFilter, $Instance {
|
|||
class $HeaderFilter implements HeaderFilter, $Instance {
|
||||
$HeaderFilter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'HeaderFilter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'HeaderFilter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('type', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('type',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
return $HeaderFilter.wrap(HeaderFilter(args[0]!.$value, null, type: args[1]?.$value ?? ''));
|
||||
return $HeaderFilter
|
||||
.wrap(HeaderFilter(args[0]!.$value, null, type: args[1]?.$value ?? ''));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -438,18 +477,24 @@ class $HeaderFilter implements HeaderFilter, $Instance {
|
|||
class $TextFilter implements TextFilter, $Instance {
|
||||
$TextFilter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'TextFilter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'TextFilter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'type': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -530,24 +575,35 @@ class $TextFilter implements TextFilter, $Instance {
|
|||
class $SortFilter implements SortFilter, $Instance {
|
||||
$SortFilter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SortFilter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SortFilter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('state', BridgeTypeAnnotation($SortState.$type), false),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter(
|
||||
'values', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), false),
|
||||
'state', BridgeTypeAnnotation($SortState.$type), false),
|
||||
BridgeParameter(
|
||||
'values',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'type': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'state': BridgeFieldDef(BridgeTypeAnnotation($SortState.$type)),
|
||||
'values': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
),
|
||||
},
|
||||
wrap: true);
|
||||
|
|
@ -557,7 +613,10 @@ class $SortFilter implements SortFilter, $Instance {
|
|||
args[0]!.$value,
|
||||
args[1]!.$value,
|
||||
args[2]!.$value,
|
||||
(args[3]!.$value as List).map((e) => SelectFilterOption(e.$reified.name, e.$reified.value, null)).toList(),
|
||||
(args[3]!.$value as List)
|
||||
.map((e) =>
|
||||
SelectFilterOption(e.$reified.name, e.$reified.value, null))
|
||||
.toList(),
|
||||
null));
|
||||
}
|
||||
|
||||
|
|
@ -644,13 +703,17 @@ class $SortFilter implements SortFilter, $Instance {
|
|||
class $SortState implements SortState, $Instance {
|
||||
$SortState.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SortState'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SortState'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('index', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false),
|
||||
BridgeParameter('ascending', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), false),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('index',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false),
|
||||
BridgeParameter('ascending',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
|
|
@ -731,22 +794,31 @@ class $SortState implements SortState, $Instance {
|
|||
class $TriStateFilter implements TriStateFilter, $Instance {
|
||||
$TriStateFilter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'TriStateFilter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'TriStateFilter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('type', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('type',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
], namedParams: [
|
||||
BridgeParameter('state', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), true)
|
||||
BridgeParameter(
|
||||
'state', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), true)
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'state': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.int),
|
||||
)),
|
||||
|
|
@ -754,8 +826,9 @@ class $TriStateFilter implements TriStateFilter, $Instance {
|
|||
wrap: true);
|
||||
|
||||
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
return $TriStateFilter.wrap(
|
||||
TriStateFilter(args[2]?.$value ?? '', args[0]!.$value, args[1]!.$value, null, state: args[3]?.$value ?? 0));
|
||||
return $TriStateFilter.wrap(TriStateFilter(
|
||||
args[2]?.$value ?? '', args[0]!.$value, args[1]!.$value, null,
|
||||
state: args[3]?.$value ?? 0));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -842,22 +915,32 @@ class $TriStateFilter implements TriStateFilter, $Instance {
|
|||
class $GroupFilter implements GroupFilter, $Instance {
|
||||
$GroupFilter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'GroupFilter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'GroupFilter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('type',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter(
|
||||
'state', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])), false),
|
||||
'state',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'type': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'state': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.dynamic)])),
|
||||
),
|
||||
},
|
||||
wrap: true);
|
||||
|
|
@ -874,10 +957,12 @@ class $GroupFilter implements GroupFilter, $Instance {
|
|||
map = value.map((key, value) => MapEntry(key.toString(), value));
|
||||
if (map['type'] == 'TriState') {
|
||||
final filter = map['filter'] as Map;
|
||||
return TriStateFilter.fromJson(filter.map((key, value) => MapEntry(key.toString(), value)));
|
||||
return TriStateFilter.fromJson(filter
|
||||
.map((key, value) => MapEntry(key.toString(), value)));
|
||||
} else if (map['type'] == 'CheckBox') {
|
||||
final filter = map['filter'] as Map;
|
||||
return CheckBoxFilter.fromJson(filter.map((key, value) => MapEntry(key.toString(), value)));
|
||||
return CheckBoxFilter.fromJson(filter
|
||||
.map((key, value) => MapEntry(key.toString(), value)));
|
||||
}
|
||||
}
|
||||
return value;
|
||||
|
|
@ -961,22 +1046,31 @@ class $GroupFilter implements GroupFilter, $Instance {
|
|||
class $CheckBoxFilter implements CheckBoxFilter, $Instance {
|
||||
$CheckBoxFilter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'CheckBoxFilter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'CheckBoxFilter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('type', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('type',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
], namedParams: [
|
||||
BridgeParameter('state', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), true),
|
||||
BridgeParameter('state',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), true),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'type': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'state': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.bool),
|
||||
)),
|
||||
|
|
@ -984,8 +1078,9 @@ class $CheckBoxFilter implements CheckBoxFilter, $Instance {
|
|||
wrap: true);
|
||||
|
||||
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
return $CheckBoxFilter.wrap(
|
||||
CheckBoxFilter(args[2]?.$value ?? '', args[0]!.$value, args[1]!.$value, null, state: args[3]?.$value ?? false));
|
||||
return $CheckBoxFilter.wrap(CheckBoxFilter(
|
||||
args[2]?.$value ?? '', args[0]!.$value, args[1]!.$value, null,
|
||||
state: args[3]?.$value ?? false));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -17,104 +17,165 @@ class $Client implements $Instance {
|
|||
late final $Instance _superclass = $Object($value);
|
||||
|
||||
/// Compile-time bridged type reference for [$InterceptedClient]
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'Client'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'Client'));
|
||||
|
||||
/// Compile-time bridged class declaration for [$InterceptedClient]
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('source', BridgeTypeAnnotation($MSource.$type), true),
|
||||
BridgeParameter('reqcopyWith', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
BridgeParameter('reqcopyWith',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
], namedParams: []))
|
||||
},
|
||||
methods: {
|
||||
'get': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
params: [
|
||||
BridgeParameter('url', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
BridgeParameter('url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
],
|
||||
namedParams: [
|
||||
BridgeParameter(
|
||||
'headers',
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
nullable: true),
|
||||
true),
|
||||
])),
|
||||
'post': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
params: [
|
||||
BridgeParameter('url', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
BridgeParameter('url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
],
|
||||
namedParams: [
|
||||
BridgeParameter(
|
||||
'headers',
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
nullable: true),
|
||||
true),
|
||||
BridgeParameter('body', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object), nullable: true), true),
|
||||
BridgeParameter(
|
||||
'encoding', BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.encoding), nullable: true), true),
|
||||
'body',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object),
|
||||
nullable: true),
|
||||
true),
|
||||
BridgeParameter(
|
||||
'encoding',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.encoding),
|
||||
nullable: true),
|
||||
true),
|
||||
])),
|
||||
'put': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
params: [
|
||||
BridgeParameter('url', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
BridgeParameter('url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
],
|
||||
namedParams: [
|
||||
BridgeParameter(
|
||||
'headers',
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
nullable: true),
|
||||
true),
|
||||
BridgeParameter('body', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object), nullable: true), true),
|
||||
BridgeParameter(
|
||||
'encoding', BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.encoding), nullable: true), true),
|
||||
'body',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object),
|
||||
nullable: true),
|
||||
true),
|
||||
BridgeParameter(
|
||||
'encoding',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.encoding),
|
||||
nullable: true),
|
||||
true),
|
||||
])),
|
||||
'delete': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
params: [
|
||||
BridgeParameter('url', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
BridgeParameter('url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
],
|
||||
namedParams: [
|
||||
BridgeParameter(
|
||||
'headers',
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
nullable: true),
|
||||
true),
|
||||
BridgeParameter('body', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object), nullable: true), true),
|
||||
BridgeParameter(
|
||||
'encoding', BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.encoding), nullable: true), true),
|
||||
'body',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object),
|
||||
nullable: true),
|
||||
true),
|
||||
BridgeParameter(
|
||||
'encoding',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.encoding),
|
||||
nullable: true),
|
||||
true),
|
||||
])),
|
||||
'patch': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.future, [$Response.$type])),
|
||||
params: [
|
||||
BridgeParameter('url', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
BridgeParameter('url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
],
|
||||
namedParams: [
|
||||
BridgeParameter(
|
||||
'headers',
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
nullable: true),
|
||||
true),
|
||||
BridgeParameter('body', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object), nullable: true), true),
|
||||
BridgeParameter(
|
||||
'encoding', BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.encoding), nullable: true), true),
|
||||
'body',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.object),
|
||||
nullable: true),
|
||||
true),
|
||||
BridgeParameter(
|
||||
'encoding',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.encoding),
|
||||
nullable: true),
|
||||
true),
|
||||
])),
|
||||
'read': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [BridgeTypeRef(CoreTypes.string)])),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.future, [BridgeTypeRef(CoreTypes.string)])),
|
||||
params: [
|
||||
BridgeParameter('url', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
BridgeParameter('url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
],
|
||||
namedParams: [
|
||||
BridgeParameter(
|
||||
'headers',
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
nullable: true),
|
||||
true),
|
||||
])),
|
||||
|
|
@ -123,20 +184,26 @@ class $Client implements $Instance {
|
|||
BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])
|
||||
])),
|
||||
params: [
|
||||
BridgeParameter('url', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
BridgeParameter('url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), false),
|
||||
],
|
||||
namedParams: [
|
||||
BridgeParameter(
|
||||
'headers',
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
nullable: true),
|
||||
true),
|
||||
])),
|
||||
'send': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.future, [BridgeTypeRef(CoreTypes.list)])),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.future, [BridgeTypeRef(CoreTypes.list)])),
|
||||
params: [
|
||||
BridgeParameter('request', BridgeTypeAnnotation($BaseRequest.$type), false),
|
||||
BridgeParameter(
|
||||
'request', BridgeTypeAnnotation($BaseRequest.$type), false),
|
||||
])),
|
||||
'close': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.voidType)),
|
||||
|
|
@ -147,7 +214,8 @@ class $Client implements $Instance {
|
|||
static $Client $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
final reqcopyWith = args[1]?.$value == null
|
||||
? null
|
||||
: (jsonDecode(args[1]!.$value) as Map).map((key, value) => MapEntry(key.toString(), value));
|
||||
: (jsonDecode(args[1]!.$value) as Map)
|
||||
.map((key, value) => MapEntry(key.toString(), value));
|
||||
return $Client.wrap(
|
||||
MClient.init(source: args[0]?.$value, reqcopyWith: reqcopyWith),
|
||||
);
|
||||
|
|
@ -183,8 +251,10 @@ class $Client implements $Instance {
|
|||
final url = args[0]!.$value as Uri;
|
||||
final headers = _toMapString(args[1]?.$value);
|
||||
|
||||
final request = (target!.$value as InterceptedClient).get(url, headers: headers);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
final request =
|
||||
(target!.$value as InterceptedClient).get(url, headers: headers);
|
||||
return $Future
|
||||
.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __post = $Function(_post);
|
||||
|
|
@ -195,8 +265,10 @@ class $Client implements $Instance {
|
|||
final body = _toBodyObject(args[2]?.$value);
|
||||
final encoding = args[3]?.$value as Encoding?;
|
||||
|
||||
final request = (target!.$value as InterceptedClient).post(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
final request = (target!.$value as InterceptedClient)
|
||||
.post(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future
|
||||
.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __put = $Function(_put);
|
||||
|
|
@ -207,8 +279,10 @@ class $Client implements $Instance {
|
|||
final body = _toBodyObject(args[2]?.$value);
|
||||
final encoding = args[3]?.$value as Encoding?;
|
||||
|
||||
final request = (target!.$value as InterceptedClient).put(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
final request = (target!.$value as InterceptedClient)
|
||||
.put(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future
|
||||
.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __delete = $Function(_delete);
|
||||
|
|
@ -219,8 +293,10 @@ class $Client implements $Instance {
|
|||
final body = _toBodyObject(args[2]?.$value);
|
||||
final encoding = args[3]?.$value as Encoding?;
|
||||
|
||||
final request = (target!.$value as InterceptedClient).delete(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
final request = (target!.$value as InterceptedClient)
|
||||
.delete(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future
|
||||
.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __patch = $Function(_patch);
|
||||
|
|
@ -231,8 +307,10 @@ class $Client implements $Instance {
|
|||
final body = _toBodyObject(args[2]?.$value);
|
||||
final encoding = args[3]?.$value as Encoding?;
|
||||
|
||||
final request = (target!.$value as InterceptedClient).patch(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
final request = (target!.$value as InterceptedClient)
|
||||
.patch(url, headers: headers, body: body, encoding: encoding);
|
||||
return $Future
|
||||
.wrap(request.then((value) => $Response.wrap(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __read = $Function(_read);
|
||||
|
|
@ -241,19 +319,25 @@ class $Client implements $Instance {
|
|||
final url = args[0]!.$value as Uri;
|
||||
final headers = _toMapString(args[1]?.$value);
|
||||
|
||||
final request = (target!.$value as InterceptedClient).read(url, headers: headers);
|
||||
return $Future.wrap(request.then((value) => $String(value)).onErrorMessage());
|
||||
final request =
|
||||
(target!.$value as InterceptedClient).read(url, headers: headers);
|
||||
return $Future
|
||||
.wrap(request.then((value) => $String(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __readBytes = $Function(_readBytes);
|
||||
|
||||
static $Value? _readBytes(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
static $Value? _readBytes(
|
||||
Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
final url = args[0]!.$value as Uri;
|
||||
final headers = (args[1]?.$value as Map<$Value, $Value>?)
|
||||
?.map((key, value) => MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
final headers = (args[1]?.$value as Map<$Value, $Value>?)?.map(
|
||||
(key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
|
||||
final request = (target!.$value as InterceptedClient).readBytes(url, headers: headers);
|
||||
return $Future.wrap(request.then((value) => $List.wrap(value)).onErrorMessage());
|
||||
final request =
|
||||
(target!.$value as InterceptedClient).readBytes(url, headers: headers);
|
||||
return $Future
|
||||
.wrap(request.then((value) => $List.wrap(value)).onErrorMessage());
|
||||
}
|
||||
|
||||
static const $Function __close = $Function(_close);
|
||||
|
|
@ -281,46 +365,52 @@ class $BaseRequest implements $Instance {
|
|||
final BaseRequest $value;
|
||||
|
||||
/// Compile-time bridged type reference for [$BaseRequest]
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'BaseRequest'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'BaseRequest'));
|
||||
|
||||
/// Compile-time bridged class declaration for [$BaseRequest]
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type, isAbstract: true),
|
||||
constructors: {},
|
||||
getters: {
|
||||
'contentLength': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int), nullable: true),
|
||||
)),
|
||||
'finalized': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
)),
|
||||
'followRedirects': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
)),
|
||||
'headers': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
),
|
||||
)),
|
||||
'maxRedirects': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)),
|
||||
)),
|
||||
'method': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
),
|
||||
)),
|
||||
'persistentConnection': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
),
|
||||
)),
|
||||
'url': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.uri),
|
||||
),
|
||||
)),
|
||||
},
|
||||
wrap: true);
|
||||
static const $declaration =
|
||||
BridgeClassDef(BridgeClassType($type, isAbstract: true),
|
||||
constructors: {},
|
||||
getters: {
|
||||
'contentLength': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int),
|
||||
nullable: true),
|
||||
)),
|
||||
'finalized': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
)),
|
||||
'followRedirects': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
)),
|
||||
'headers': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
),
|
||||
)),
|
||||
'maxRedirects': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)),
|
||||
)),
|
||||
'method': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
),
|
||||
)),
|
||||
'persistentConnection': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
),
|
||||
)),
|
||||
'url': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.uri),
|
||||
),
|
||||
)),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
final $Instance _superclass;
|
||||
|
||||
|
|
@ -369,25 +459,34 @@ class $Response implements $Instance {
|
|||
final Response $value;
|
||||
|
||||
/// Compile-time bridged type reference for [$Response]
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'Response'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'Response'));
|
||||
|
||||
/// Compile-time bridged class declaration for [$Response]
|
||||
static const $declaration = BridgeClassDef(
|
||||
BridgeClassType($type),
|
||||
constructors: {'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type)))},
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type)))
|
||||
},
|
||||
getters: {
|
||||
'body': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)),
|
||||
)),
|
||||
'bodyBytes': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])),
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])),
|
||||
)),
|
||||
'contentLength': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int), nullable: true),
|
||||
returns:
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int), nullable: true),
|
||||
)),
|
||||
'headers': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
),
|
||||
)),
|
||||
'isRedirect': BridgeMethodDef(BridgeFunctionDef(
|
||||
|
|
@ -397,7 +496,8 @@ class $Response implements $Instance {
|
|||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
)),
|
||||
'reasonPhrase': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'statusCode': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)),
|
||||
|
|
@ -460,22 +560,30 @@ class $StreamedResponse implements $Instance {
|
|||
final StreamedResponse $value;
|
||||
|
||||
/// Compile-time bridged type reference for [$StreamedResponse]
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'StreamedResponse'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'StreamedResponse'));
|
||||
|
||||
/// Compile-time bridged class declaration for [$StreamedResponse]
|
||||
static const $declaration = BridgeClassDef(
|
||||
BridgeClassType($type),
|
||||
constructors: {'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type)))},
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type)))
|
||||
},
|
||||
getters: {
|
||||
'stream': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($ByteStream.$type),
|
||||
)),
|
||||
'contentLength': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int), nullable: true),
|
||||
returns:
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int), nullable: true),
|
||||
)),
|
||||
'headers': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
),
|
||||
)),
|
||||
'isRedirect': BridgeMethodDef(BridgeFunctionDef(
|
||||
|
|
@ -485,7 +593,8 @@ class $StreamedResponse implements $Instance {
|
|||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)),
|
||||
)),
|
||||
'reasonPhrase': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), nullable: true),
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string),
|
||||
nullable: true),
|
||||
)),
|
||||
'statusCode': BridgeMethodDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)),
|
||||
|
|
@ -546,12 +655,16 @@ class $ByteStream implements $Instance {
|
|||
final ByteStream $value;
|
||||
|
||||
/// Compile-time bridged type reference for [$ByteStream]
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'ByteStream'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'ByteStream'));
|
||||
|
||||
/// Compile-time bridged class declaration for [$ByteStream]
|
||||
static const $declaration = BridgeClassDef(
|
||||
BridgeClassType($type),
|
||||
constructors: {'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type)))},
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type)))
|
||||
},
|
||||
getters: {},
|
||||
wrap: true,
|
||||
);
|
||||
|
|
@ -579,13 +692,15 @@ class $ByteStream implements $Instance {
|
|||
}
|
||||
|
||||
Map<String, String>? _toMapString(Map<$Value, $Value>? value) {
|
||||
return value?.map((key, value) => MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
return value?.map((key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
}
|
||||
|
||||
Object? _toBodyObject(Object? value) {
|
||||
Object? body;
|
||||
if (value is Map<$Value, $Value>) {
|
||||
body = value.map((key, value) => MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
body = value.map((key, value) =>
|
||||
MapEntry((key.$reified).toString(), (value.$reified).toString()));
|
||||
} else if (value is List<$Value>) {
|
||||
body = value.map((e) => e.$reified).toList();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,23 +5,35 @@ import 'package:mangayomi/eval/model/m_chapter.dart';
|
|||
class $MChapter implements MChapter, $Instance {
|
||||
$MChapter.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MChapter'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MChapter'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [], namedParams: [
|
||||
BridgeParameter('name', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('url', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('dateUpload', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('scanlator', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
]))
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type),
|
||||
params: [],
|
||||
namedParams: [
|
||||
BridgeParameter('name',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('url',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('dateUpload',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('scanlator',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), true),
|
||||
]))
|
||||
},
|
||||
// Specify class fields
|
||||
fields: {
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'url': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'dateUpload': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'scanlator': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'url': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'dateUpload': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'scanlator': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -102,5 +114,10 @@ class $MChapter implements MChapter, $Instance {
|
|||
set scanlator(String? scanlator) {}
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() => {'name': name, 'url': url, 'dateUpload': dateUpload, 'scanlator': scanlator};
|
||||
Map<String, dynamic> toJson() => {
|
||||
'name': name,
|
||||
'url': url,
|
||||
'dateUpload': dateUpload,
|
||||
'scanlator': scanlator
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,25 +10,36 @@ import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
|||
class $MManga implements MManga, $Instance {
|
||||
$MManga.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MManga'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MManga'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: []))},
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: []))
|
||||
},
|
||||
// Specify class fields
|
||||
fields: {
|
||||
'author': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'artist': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'author': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'artist': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'status': BridgeFieldDef(BridgeTypeAnnotation($MStatus.$type)),
|
||||
'genre': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]),
|
||||
),
|
||||
),
|
||||
'imageUrl': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'link': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'description': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'chapters': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$MChapter.$type]))),
|
||||
'imageUrl': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'link': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'description': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'chapters': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$MChapter.$type]))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -65,7 +76,8 @@ class $MManga implements MManga, $Instance {
|
|||
case 'description':
|
||||
return $String($value.description!);
|
||||
case 'chapters':
|
||||
return $List.wrap($value.chapters!.map((e) => $MChapter.wrap(e)).toList());
|
||||
return $List
|
||||
.wrap($value.chapters!.map((e) => $MChapter.wrap(e)).toList());
|
||||
|
||||
default:
|
||||
return _superclass.$getProperty(runtime, identifier);
|
||||
|
|
@ -85,7 +97,8 @@ class $MManga implements MManga, $Instance {
|
|||
case 'status':
|
||||
$value.status = value.$reified;
|
||||
case 'genre':
|
||||
$value.genre = (value.$reified as List).map((e) => e.toString()).toList();
|
||||
$value.genre =
|
||||
(value.$reified as List).map((e) => e.toString()).toList();
|
||||
case 'imageUrl':
|
||||
$value.imageUrl = value.$reified;
|
||||
case 'name':
|
||||
|
|
@ -96,7 +109,11 @@ class $MManga implements MManga, $Instance {
|
|||
$value.description = value.$reified;
|
||||
case 'chapters':
|
||||
$value.chapters = (value.$reified as List)
|
||||
.map((e) => MChapter(dateUpload: e.dateUpload, url: e.url, name: e.name, scanlator: e.scanlator))
|
||||
.map((e) => MChapter(
|
||||
dateUpload: e.dateUpload,
|
||||
url: e.url,
|
||||
name: e.name,
|
||||
scanlator: e.scanlator))
|
||||
.toList();
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -7,26 +7,40 @@ import 'package:mangayomi/eval/model/m_pages.dart';
|
|||
class $MPages implements MPages, $Instance {
|
||||
$MPages.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MPages'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MPages'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter('list', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$MManga.$type])), false),
|
||||
BridgeParameter('hasNextPage', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool), nullable: true), true),
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [
|
||||
BridgeParameter(
|
||||
'list',
|
||||
BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$MManga.$type])),
|
||||
false),
|
||||
BridgeParameter(
|
||||
'hasNextPage',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool),
|
||||
nullable: true),
|
||||
true),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'list': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$MManga.$type])),
|
||||
),
|
||||
'hasNextPage': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool), nullable: true)),
|
||||
'hasNextPage': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.bool),
|
||||
nullable: true)),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
List<$Value> list = args[0]!.$value;
|
||||
return $MPages.wrap(MPages(list: list.map((e) => e as MManga).toList(), hasNextPage: args[1]?.$value ?? false));
|
||||
return $MPages.wrap(MPages(
|
||||
list: list.map((e) => e as MManga).toList(),
|
||||
hasNextPage: args[1]?.$value ?? false));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5,21 +5,35 @@ import 'package:mangayomi/eval/model/m_source.dart';
|
|||
class $MSource implements MSource, $Instance {
|
||||
$MSource.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MSource'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MSource'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: []))},
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(
|
||||
BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: []))
|
||||
},
|
||||
fields: {
|
||||
'id': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int))),
|
||||
'name': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'baseUrl': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'lang': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'isFullData': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool))),
|
||||
'hasCloudflare': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool))),
|
||||
'dateFormat': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'dateFormatLocale': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'apiUrl': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'additionalParams': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'id':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int))),
|
||||
'name': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'baseUrl': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'lang': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'isFullData':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool))),
|
||||
'hasCloudflare':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool))),
|
||||
'dateFormat': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'dateFormatLocale': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'apiUrl': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'additionalParams': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,18 @@ import 'package:dart_eval/stdlib/core.dart';
|
|||
import 'package:mangayomi/models/manga.dart';
|
||||
|
||||
class $MStatus implements $Instance {
|
||||
static $MStatus $wrap(Runtime runtime, $Value? target, List<$Value?> args) => $MStatus.wrap(args[0]!.$value);
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MStatus'));
|
||||
static const $declaration = BridgeEnumDef($type,
|
||||
values: ['ongoing', 'completed', 'canceled', 'unknown', 'onHiatus', 'publishingFinished'],
|
||||
methods: {},
|
||||
getters: {},
|
||||
setters: {},
|
||||
fields: {});
|
||||
static $MStatus $wrap(Runtime runtime, $Value? target, List<$Value?> args) =>
|
||||
$MStatus.wrap(args[0]!.$value);
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MStatus'));
|
||||
static const $declaration = BridgeEnumDef($type, values: [
|
||||
'ongoing',
|
||||
'completed',
|
||||
'canceled',
|
||||
'unknown',
|
||||
'onHiatus',
|
||||
'publishingFinished'
|
||||
], methods: {}, getters: {}, setters: {}, fields: {});
|
||||
static final $values = Status.values.asNameMap().map(
|
||||
(key, value) => MapEntry(key, $MStatus.wrap(value)),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import 'package:mangayomi/models/video.dart';
|
|||
class $MTrack implements Track, $Instance {
|
||||
$MTrack.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MTrack'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MTrack'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
|
|
@ -15,8 +16,10 @@ class $MTrack implements Track, $Instance {
|
|||
},
|
||||
// Specify class fields
|
||||
fields: {
|
||||
'file': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'label': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'file': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'label': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import 'package:mangayomi/models/video.dart';
|
|||
class $MVideo implements Video, $Instance {
|
||||
$MVideo.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MVideo'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MVideo'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
|
|
@ -16,14 +17,22 @@ class $MVideo implements Video, $Instance {
|
|||
},
|
||||
// Specify class fields
|
||||
fields: {
|
||||
'url': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'quality': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'originalUrl': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'url': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'quality': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'originalUrl': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'headers': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.map, [BridgeTypeRef(CoreTypes.string), BridgeTypeRef(CoreTypes.string)]),
|
||||
BridgeTypeRef(CoreTypes.map, [
|
||||
BridgeTypeRef(CoreTypes.string),
|
||||
BridgeTypeRef(CoreTypes.string)
|
||||
]),
|
||||
nullable: true)),
|
||||
'subtitles': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$MTrack.$type]))),
|
||||
'audios': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [$MTrack.$type]))),
|
||||
'subtitles': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$MTrack.$type]))),
|
||||
'audios': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [$MTrack.$type]))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -51,9 +60,13 @@ class $MVideo implements Video, $Instance {
|
|||
case 'headers':
|
||||
return $Map.wrap($value.headers ?? {});
|
||||
case 'subtitles':
|
||||
return $List.wrap($value.subtitles!.map((e) => $MTrack.wrap(Track(file: e.file, label: e.label))).toList());
|
||||
return $List.wrap($value.subtitles!
|
||||
.map((e) => $MTrack.wrap(Track(file: e.file, label: e.label)))
|
||||
.toList());
|
||||
case 'audios':
|
||||
return $List.wrap($value.audios!.map((e) => $MTrack.wrap(Track(file: e.file, label: e.label))).toList());
|
||||
return $List.wrap($value.audios!
|
||||
.map((e) => $MTrack.wrap(Track(file: e.file, label: e.label)))
|
||||
.toList());
|
||||
|
||||
default:
|
||||
return _superclass.$getProperty(runtime, identifier);
|
||||
|
|
@ -73,12 +86,17 @@ class $MVideo implements Video, $Instance {
|
|||
case 'originalUrl':
|
||||
$value.originalUrl = value.$reified;
|
||||
case 'headers':
|
||||
$value.headers = (value.$reified as Map).map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||
$value.headers = (value.$reified as Map)
|
||||
.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||
case 'subtitles':
|
||||
$value.subtitles = (value.$reified as List).map((e) => Track(file: e.file, label: e.label)).toList();
|
||||
$value.subtitles = (value.$reified as List)
|
||||
.map((e) => Track(file: e.file, label: e.label))
|
||||
.toList();
|
||||
|
||||
case 'audios':
|
||||
$value.audios = (value.$reified as List).map((e) => Track(file: e.file, label: e.label)).toList();
|
||||
$value.audios = (value.$reified as List)
|
||||
.map((e) => Track(file: e.file, label: e.label))
|
||||
.toList();
|
||||
|
||||
default:
|
||||
_superclass.$setProperty(runtime, identifier, value);
|
||||
|
|
|
|||
|
|
@ -6,30 +6,44 @@ import 'package:mangayomi/eval/model/source_preference.dart';
|
|||
class $CheckBoxPreference implements SourcePreference, $Instance {
|
||||
$CheckBoxPreference.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'CheckBoxPreference'));
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec(
|
||||
'package:mangayomi/bridge_lib.dart', 'CheckBoxPreference'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [], namedParams: [
|
||||
BridgeParameter('key', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), false),
|
||||
]))
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type),
|
||||
params: [],
|
||||
namedParams: [
|
||||
BridgeParameter('key',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'key': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool))),
|
||||
'key': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
return $CheckBoxPreference.wrap(SourcePreference(
|
||||
key: args[0]!.$value,
|
||||
checkBoxPreference:
|
||||
CheckBoxPreference(title: args[1]!.$value, summary: args[2]!.$value, value: args[3]!.$value)));
|
||||
checkBoxPreference: CheckBoxPreference(
|
||||
title: args[1]!.$value,
|
||||
summary: args[2]!.$value,
|
||||
value: args[3]!.$value)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -78,10 +92,12 @@ class $CheckBoxPreference implements SourcePreference, $Instance {
|
|||
ListPreference? get listPreference => $value.listPreference;
|
||||
|
||||
@override
|
||||
MultiSelectListPreference? get multiSelectListPreference => $value.multiSelectListPreference;
|
||||
MultiSelectListPreference? get multiSelectListPreference =>
|
||||
$value.multiSelectListPreference;
|
||||
|
||||
@override
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat => $value.switchPreferenceCompat;
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat =>
|
||||
$value.switchPreferenceCompat;
|
||||
|
||||
@override
|
||||
Id? get id => $value.id;
|
||||
|
|
@ -108,7 +124,8 @@ class $CheckBoxPreference implements SourcePreference, $Instance {
|
|||
set listPreference(ListPreference? listPreference) {}
|
||||
|
||||
@override
|
||||
set multiSelectListPreference(MultiSelectListPreference? multiSelectListPreference) {}
|
||||
set multiSelectListPreference(
|
||||
MultiSelectListPreference? multiSelectListPreference) {}
|
||||
|
||||
@override
|
||||
set sourceId(int? sourceId) {}
|
||||
|
|
@ -125,30 +142,44 @@ class $CheckBoxPreference implements SourcePreference, $Instance {
|
|||
class $SwitchPreferenceCompat implements SourcePreference, $Instance {
|
||||
$SwitchPreferenceCompat.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'SwitchPreferenceCompat'));
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec(
|
||||
'package:mangayomi/bridge_lib.dart', 'SwitchPreferenceCompat'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [], namedParams: [
|
||||
BridgeParameter('key', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), false),
|
||||
]))
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type),
|
||||
params: [],
|
||||
namedParams: [
|
||||
BridgeParameter('key',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'key': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool))),
|
||||
'key': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
static $Value? $new(Runtime runtime, $Value? target, List<$Value?> args) {
|
||||
return $SwitchPreferenceCompat.wrap(SourcePreference(
|
||||
key: args[0]!.$value,
|
||||
switchPreferenceCompat:
|
||||
SwitchPreferenceCompat(title: args[1]!.$value, summary: args[2]!.$value, value: args[3]!.$value)));
|
||||
switchPreferenceCompat: SwitchPreferenceCompat(
|
||||
title: args[1]!.$value,
|
||||
summary: args[2]!.$value,
|
||||
value: args[3]!.$value)));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -197,10 +228,12 @@ class $SwitchPreferenceCompat implements SourcePreference, $Instance {
|
|||
ListPreference? get listPreference => $value.listPreference;
|
||||
|
||||
@override
|
||||
MultiSelectListPreference? get multiSelectListPreference => $value.multiSelectListPreference;
|
||||
MultiSelectListPreference? get multiSelectListPreference =>
|
||||
$value.multiSelectListPreference;
|
||||
|
||||
@override
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat => $value.switchPreferenceCompat;
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat =>
|
||||
$value.switchPreferenceCompat;
|
||||
|
||||
@override
|
||||
Id? get id => $value.id;
|
||||
|
|
@ -227,7 +260,8 @@ class $SwitchPreferenceCompat implements SourcePreference, $Instance {
|
|||
set listPreference(ListPreference? listPreference) {}
|
||||
|
||||
@override
|
||||
set multiSelectListPreference(MultiSelectListPreference? multiSelectListPreference) {}
|
||||
set multiSelectListPreference(
|
||||
MultiSelectListPreference? multiSelectListPreference) {}
|
||||
|
||||
@override
|
||||
set sourceId(int? sourceId) {}
|
||||
|
|
@ -244,30 +278,48 @@ class $SwitchPreferenceCompat implements SourcePreference, $Instance {
|
|||
class $ListPreference implements SourcePreference, $Instance {
|
||||
$ListPreference.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'ListPreference'));
|
||||
static const $type = BridgeTypeRef(
|
||||
BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'ListPreference'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [], namedParams: [
|
||||
BridgeParameter('key', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('valueIndex', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false),
|
||||
BridgeParameter(
|
||||
'entries', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])), false),
|
||||
BridgeParameter('entryValues',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])), false),
|
||||
]))
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type),
|
||||
params: [],
|
||||
namedParams: [
|
||||
BridgeParameter('key',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('valueIndex',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false),
|
||||
BridgeParameter(
|
||||
'entries',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])),
|
||||
false),
|
||||
BridgeParameter(
|
||||
'entryValues',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])),
|
||||
false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'key': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'valueIndex': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int))),
|
||||
'entries':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
'entryValues':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
'key': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'valueIndex':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int))),
|
||||
'entries': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
'entryValues': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -278,8 +330,12 @@ class $ListPreference implements SourcePreference, $Instance {
|
|||
title: args[1]!.$value,
|
||||
summary: args[2]!.$value,
|
||||
valueIndex: args[3]!.$value,
|
||||
entries: (args[4]!.$value as List).map((e) => (e is $Value ? e.$reified : e).toString()).toList(),
|
||||
entryValues: (args[5]!.$value as List).map((e) => (e is $Value ? e.$reified : e).toString()).toList())));
|
||||
entries: (args[4]!.$value as List)
|
||||
.map((e) => (e is $Value ? e.$reified : e).toString())
|
||||
.toList(),
|
||||
entryValues: (args[5]!.$value as List)
|
||||
.map((e) => (e is $Value ? e.$reified : e).toString())
|
||||
.toList())));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -332,10 +388,12 @@ class $ListPreference implements SourcePreference, $Instance {
|
|||
ListPreference? get listPreference => $value.listPreference;
|
||||
|
||||
@override
|
||||
MultiSelectListPreference? get multiSelectListPreference => $value.multiSelectListPreference;
|
||||
MultiSelectListPreference? get multiSelectListPreference =>
|
||||
$value.multiSelectListPreference;
|
||||
|
||||
@override
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat => $value.switchPreferenceCompat;
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat =>
|
||||
$value.switchPreferenceCompat;
|
||||
|
||||
@override
|
||||
Id? get id => $value.id;
|
||||
|
|
@ -362,7 +420,8 @@ class $ListPreference implements SourcePreference, $Instance {
|
|||
set listPreference(ListPreference? listPreference) {}
|
||||
|
||||
@override
|
||||
set multiSelectListPreference(MultiSelectListPreference? multiSelectListPreference) {}
|
||||
set multiSelectListPreference(
|
||||
MultiSelectListPreference? multiSelectListPreference) {}
|
||||
|
||||
@override
|
||||
set sourceId(int? sourceId) {}
|
||||
|
|
@ -379,32 +438,51 @@ class $ListPreference implements SourcePreference, $Instance {
|
|||
class $MultiSelectListPreference implements SourcePreference, $Instance {
|
||||
$MultiSelectListPreference.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'MultiSelectListPreference'));
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec(
|
||||
'package:mangayomi/bridge_lib.dart', 'MultiSelectListPreference'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [], namedParams: [
|
||||
BridgeParameter('key', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter(
|
||||
'entries', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])), false),
|
||||
BridgeParameter('entryValues',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])), false),
|
||||
BridgeParameter(
|
||||
'values', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])), false),
|
||||
]))
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type),
|
||||
params: [],
|
||||
namedParams: [
|
||||
BridgeParameter('key',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter(
|
||||
'entries',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])),
|
||||
false),
|
||||
BridgeParameter(
|
||||
'entryValues',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])),
|
||||
false),
|
||||
BridgeParameter(
|
||||
'values',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(
|
||||
CoreTypes.list, [BridgeTypeRef(CoreTypes.string)])),
|
||||
false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'key': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'entries':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
'entryValues':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
'values':
|
||||
BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
'key': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'entries': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
'entryValues': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
'values': BridgeFieldDef(BridgeTypeAnnotation(
|
||||
BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.string)]))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -414,9 +492,15 @@ class $MultiSelectListPreference implements SourcePreference, $Instance {
|
|||
multiSelectListPreference: MultiSelectListPreference(
|
||||
title: args[1]!.$value,
|
||||
summary: args[2]!.$value,
|
||||
entries: (args[3]!.$value as List).map((e) => (e is $Value ? e.$reified : e).toString()).toList(),
|
||||
entryValues: (args[4]!.$value as List).map((e) => (e is $Value ? e.$reified : e).toString()).toList(),
|
||||
values: (args[5]!.$value as List).map((e) => (e is $Value ? e.$reified : e).toString()).toList())));
|
||||
entries: (args[3]!.$value as List)
|
||||
.map((e) => (e is $Value ? e.$reified : e).toString())
|
||||
.toList(),
|
||||
entryValues: (args[4]!.$value as List)
|
||||
.map((e) => (e is $Value ? e.$reified : e).toString())
|
||||
.toList(),
|
||||
values: (args[5]!.$value as List)
|
||||
.map((e) => (e is $Value ? e.$reified : e).toString())
|
||||
.toList())));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -469,10 +553,12 @@ class $MultiSelectListPreference implements SourcePreference, $Instance {
|
|||
ListPreference? get listPreference => $value.listPreference;
|
||||
|
||||
@override
|
||||
MultiSelectListPreference? get multiSelectListPreference => $value.multiSelectListPreference;
|
||||
MultiSelectListPreference? get multiSelectListPreference =>
|
||||
$value.multiSelectListPreference;
|
||||
|
||||
@override
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat => $value.switchPreferenceCompat;
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat =>
|
||||
$value.switchPreferenceCompat;
|
||||
|
||||
@override
|
||||
Id? get id => $value.id;
|
||||
|
|
@ -499,7 +585,8 @@ class $MultiSelectListPreference implements SourcePreference, $Instance {
|
|||
set listPreference(ListPreference? listPreference) {}
|
||||
|
||||
@override
|
||||
set multiSelectListPreference(MultiSelectListPreference? multiSelectListPreference) {}
|
||||
set multiSelectListPreference(
|
||||
MultiSelectListPreference? multiSelectListPreference) {}
|
||||
|
||||
@override
|
||||
set sourceId(int? sourceId) {}
|
||||
|
|
@ -516,28 +603,46 @@ class $MultiSelectListPreference implements SourcePreference, $Instance {
|
|||
class $EditTextPreference implements SourcePreference, $Instance {
|
||||
$EditTextPreference.wrap(this.$value) : _superclass = $Object($value);
|
||||
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec('package:mangayomi/bridge_lib.dart', 'EditTextPreference'));
|
||||
static const $type = BridgeTypeRef(BridgeTypeSpec(
|
||||
'package:mangayomi/bridge_lib.dart', 'EditTextPreference'));
|
||||
|
||||
static const $declaration = BridgeClassDef(BridgeClassType($type),
|
||||
constructors: {
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(returns: BridgeTypeAnnotation($type), params: [], namedParams: [
|
||||
BridgeParameter('key', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('dialogTitle', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('dialogMessage', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('text', BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
]))
|
||||
'': BridgeConstructorDef(BridgeFunctionDef(
|
||||
returns: BridgeTypeAnnotation($type),
|
||||
params: [],
|
||||
namedParams: [
|
||||
BridgeParameter('key',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('title',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('summary',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('value',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('dialogTitle',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('dialogMessage',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
BridgeParameter('text',
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false),
|
||||
]))
|
||||
},
|
||||
fields: {
|
||||
'key': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'dialogTitle': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'dialogMessage': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'text': BridgeFieldDef(BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'key': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'title': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'summary': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'value': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'dialogTitle': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'dialogMessage': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
'text': BridgeFieldDef(
|
||||
BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string))),
|
||||
},
|
||||
wrap: true);
|
||||
|
||||
|
|
@ -605,10 +710,12 @@ class $EditTextPreference implements SourcePreference, $Instance {
|
|||
ListPreference? get listPreference => $value.listPreference;
|
||||
|
||||
@override
|
||||
MultiSelectListPreference? get multiSelectListPreference => $value.multiSelectListPreference;
|
||||
MultiSelectListPreference? get multiSelectListPreference =>
|
||||
$value.multiSelectListPreference;
|
||||
|
||||
@override
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat => $value.switchPreferenceCompat;
|
||||
SwitchPreferenceCompat? get switchPreferenceCompat =>
|
||||
$value.switchPreferenceCompat;
|
||||
|
||||
@override
|
||||
Id? get id => $value.id;
|
||||
|
|
@ -635,7 +742,8 @@ class $EditTextPreference implements SourcePreference, $Instance {
|
|||
set listPreference(ListPreference? listPreference) {}
|
||||
|
||||
@override
|
||||
set multiSelectListPreference(MultiSelectListPreference? multiSelectListPreference) {}
|
||||
set multiSelectListPreference(
|
||||
MultiSelectListPreference? multiSelectListPreference) {}
|
||||
|
||||
@override
|
||||
set sourceId(int? sourceId) {}
|
||||
|
|
|
|||
|
|
@ -61,39 +61,64 @@ class MEvalPlugin extends EvalPlugin {
|
|||
|
||||
@override
|
||||
void configureForRuntime(Runtime runtime) {
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MProvider.', $MProvider.$construct,
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'MProvider.', $MProvider.$construct,
|
||||
isBridge: true);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MChapter.', $MChapter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MManga.', $MManga.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MPages.', $MPages.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MSource.', $MSource.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MVideo.', $MVideo.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MTrack.', $MTrack.$new);
|
||||
runtime.registerBridgeEnumValues('package:mangayomi/bridge_lib.dart', 'MStatus', $MStatus.$values);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MChapter.', $MChapter.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MManga.', $MManga.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MPages.', $MPages.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MSource.', $MSource.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MVideo.', $MVideo.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MTrack.', $MTrack.$new);
|
||||
runtime.registerBridgeEnumValues(
|
||||
'package:mangayomi/bridge_lib.dart', 'MStatus', $MStatus.$values);
|
||||
//Filter
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'FilterList.', $FilterList.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'SelectFilter.', $SelectFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'SeparatorFilter.', $SeparatorFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'HeaderFilter.', $HeaderFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'TextFilter.', $TextFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'SortFilter.', $SortFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'TriStateFilter.', $TriStateFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'GroupFilter.', $GroupFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'CheckBoxFilter.', $CheckBoxFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'SortState.', $SortState.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'SelectFilterOption.', $SelectFilterOption.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'FilterList.', $FilterList.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'SelectFilter.', $SelectFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'SeparatorFilter.', $SeparatorFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'HeaderFilter.', $HeaderFilter.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'TextFilter.', $TextFilter.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'SortFilter.', $SortFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'TriStateFilter.', $TriStateFilter.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'GroupFilter.', $GroupFilter.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'CheckBoxFilter.', $CheckBoxFilter.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'SortState.', $SortState.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'SelectFilterOption.', $SelectFilterOption.$new);
|
||||
//Sources preferences
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'CheckBoxPreference.', $CheckBoxPreference.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'SwitchPreferenceCompat.', $SwitchPreferenceCompat.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'ListPreference.', $ListPreference.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MultiSelectListPreference.', $MultiSelectListPreference.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'EditTextPreference.', $EditTextPreference.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'CheckBoxPreference.', $CheckBoxPreference.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'SwitchPreferenceCompat.', $SwitchPreferenceCompat.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'ListPreference.', $ListPreference.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'MultiSelectListPreference.', $MultiSelectListPreference.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart',
|
||||
'EditTextPreference.', $EditTextPreference.$new);
|
||||
//DOM HTML
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MElement.', $MElement.$new);
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'MDocument.', $MDocument.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MElement.', $MElement.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'MDocument.', $MDocument.$new);
|
||||
//HTTP CLIENT
|
||||
runtime.registerBridgeFunc('package:mangayomi/bridge_lib.dart', 'Client.', $Client.$new);
|
||||
runtime.registerBridgeFunc(
|
||||
'package:mangayomi/bridge_lib.dart', 'Client.', $Client.$new);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,8 @@ class DartExtensionService implements ExtensionService {
|
|||
|
||||
final runtime = runtimeEval(bytecode);
|
||||
|
||||
return runtime.executeLib('package:mangayomi/main.dart', 'main', [$MSource.wrap(source.toMSource())]) as MProvider;
|
||||
return runtime.executeLib('package:mangayomi/main.dart', 'main',
|
||||
[$MSource.wrap(source.toMSource())]) as MProvider;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -103,7 +104,9 @@ class DartExtensionService implements ExtensionService {
|
|||
@override
|
||||
Future<List<PageUrl>> getPageList(String url) async {
|
||||
return (await _executeLib().getPageList(url))
|
||||
.map((e) => e is String ? PageUrl(e.toString().trim()) : PageUrl.fromJson((e as Map).toMapStringDynamic!))
|
||||
.map((e) => e is String
|
||||
? PageUrl(e.toString().trim())
|
||||
: PageUrl.fromJson((e as Map).toMapStringDynamic!))
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
|
@ -117,7 +120,10 @@ class DartExtensionService implements ExtensionService {
|
|||
List<dynamic> list;
|
||||
|
||||
try {
|
||||
list = _executeLib().getFilterList().map((e) => e is $Value ? e.$reified : e).toList();
|
||||
list = _executeLib()
|
||||
.getFilterList()
|
||||
.map((e) => e is $Value ? e.$reified : e)
|
||||
.toList();
|
||||
} catch (_) {
|
||||
list = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,8 +67,10 @@ class JsDomSelector {
|
|||
final type = args[0];
|
||||
final key = args[1];
|
||||
final ele = _elements[key];
|
||||
final element =
|
||||
switch (type) { 'nextElementSibling' => ele?.nextElementSibling, _ => ele?.previousElementSibling };
|
||||
final element = switch (type) {
|
||||
'nextElementSibling' => ele?.nextElementSibling,
|
||||
_ => ele?.previousElementSibling
|
||||
};
|
||||
_elementKey++;
|
||||
_elements[_elementKey] = element;
|
||||
return _elementKey;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ class JsVideosExtractors {
|
|||
|
||||
void init() {
|
||||
runtime.onMessage('sibnetExtractor', (dynamic args) async {
|
||||
return (await MBridge.sibnetExtractor(args[0], args[1] ?? "")).encodeToJson();
|
||||
return (await MBridge.sibnetExtractor(args[0], args[1] ?? ""))
|
||||
.encodeToJson();
|
||||
});
|
||||
runtime.onMessage('myTvExtractor', (dynamic args) async {
|
||||
return (await MBridge.myTvExtractor(args[0])).encodeToJson();
|
||||
|
|
@ -25,7 +26,8 @@ class JsVideosExtractors {
|
|||
return (await MBridge.vidBomExtractor(args[0])).encodeToJson();
|
||||
});
|
||||
runtime.onMessage('quarkVideosExtractor', (dynamic args) async {
|
||||
return (await MBridge.quarkVideosExtractor(args[0], args[1])).encodeToJson();
|
||||
return (await MBridge.quarkVideosExtractor(args[0], args[1]))
|
||||
.encodeToJson();
|
||||
});
|
||||
runtime.onMessage('ucVideosExtractor', (dynamic args) async {
|
||||
return (await MBridge.ucVideosExtractor(args[0], args[1])).encodeToJson();
|
||||
|
|
@ -39,16 +41,27 @@ class JsVideosExtractors {
|
|||
return (await MBridge.ucFilesExtractor(urls, args[1]));
|
||||
});
|
||||
runtime.onMessage('streamlareExtractor', (dynamic args) async {
|
||||
return (await MBridge.streamlareExtractor(args[0], args[1] ?? "", args[2] ?? "")).encodeToJson();
|
||||
return (await MBridge.streamlareExtractor(
|
||||
args[0], args[1] ?? "", args[2] ?? ""))
|
||||
.encodeToJson();
|
||||
});
|
||||
runtime.onMessage('sendVidExtractor', (dynamic args) async {
|
||||
return (await MBridge.sendVidExtractor(
|
||||
args[0], args[1] != null ? jsonEncode((args[1] as Map?).toMapStringString) : null, args[2] ?? ""))
|
||||
args[0],
|
||||
args[1] != null
|
||||
? jsonEncode((args[1] as Map?).toMapStringString)
|
||||
: null,
|
||||
args[2] ?? ""))
|
||||
.encodeToJson();
|
||||
});
|
||||
runtime.onMessage('yourUploadExtractor', (dynamic args) async {
|
||||
return (await MBridge.yourUploadExtractor(args[0],
|
||||
args[1] != null ? jsonEncode((args[1] as Map?).toMapStringString) : null, args[2], args[3] ?? ""))
|
||||
return (await MBridge.yourUploadExtractor(
|
||||
args[0],
|
||||
args[1] != null
|
||||
? jsonEncode((args[1] as Map?).toMapStringString)
|
||||
: null,
|
||||
args[2],
|
||||
args[3] ?? ""))
|
||||
.encodeToJson();
|
||||
});
|
||||
runtime.onMessage('gogoCdnExtractor', (dynamic args) async {
|
||||
|
|
@ -58,18 +71,27 @@ class JsVideosExtractors {
|
|||
return (await MBridge.doodExtractor(args[0], args[1])).encodeToJson();
|
||||
});
|
||||
runtime.onMessage('streamTapeExtractor', (dynamic args) async {
|
||||
return (await MBridge.streamTapeExtractor(args[0], args[1])).encodeToJson();
|
||||
return (await MBridge.streamTapeExtractor(args[0], args[1]))
|
||||
.encodeToJson();
|
||||
});
|
||||
runtime.onMessage('mp4UploadExtractor', (dynamic args) async {
|
||||
return (await MBridge.mp4UploadExtractor(args[0],
|
||||
args[1] != null ? jsonEncode((args[1] as Map?).toMapStringString) : null, args[2] ?? "", args[3] ?? ""))
|
||||
return (await MBridge.mp4UploadExtractor(
|
||||
args[0],
|
||||
args[1] != null
|
||||
? jsonEncode((args[1] as Map?).toMapStringString)
|
||||
: null,
|
||||
args[2] ?? "",
|
||||
args[3] ?? ""))
|
||||
.encodeToJson();
|
||||
});
|
||||
runtime.onMessage('streamWishExtractor', (dynamic args) async {
|
||||
return (await MBridge.streamWishExtractor(args[0], args[1] ?? "")).encodeToJson();
|
||||
return (await MBridge.streamWishExtractor(args[0], args[1] ?? ""))
|
||||
.encodeToJson();
|
||||
});
|
||||
runtime.onMessage('filemoonExtractor', (dynamic args) async {
|
||||
return (await MBridge.filemoonExtractor(args[0], args[1] ?? "", args[2] ?? "")).encodeToJson();
|
||||
return (await MBridge.filemoonExtractor(
|
||||
args[0], args[1] ?? "", args[2] ?? ""))
|
||||
.encodeToJson();
|
||||
});
|
||||
|
||||
runtime.evaluate('''
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ class JsHttpClient {
|
|||
|
||||
void init() {
|
||||
InterceptedClient client(dynamic reqcopyWith) {
|
||||
return MClient.init(reqcopyWith: (reqcopyWith as Map?)?.toMapStringDynamic);
|
||||
return MClient.init(
|
||||
reqcopyWith: (reqcopyWith as Map?)?.toMapStringDynamic);
|
||||
}
|
||||
|
||||
runtime.onMessage('http_get', (dynamic args) async {
|
||||
|
|
@ -85,7 +86,9 @@ Future<String> _toHttpResponse(Client client, String method, List args) async {
|
|||
final body = args.length >= 5 ? (args[4] as Map?)?.toMapStringDynamic : null;
|
||||
var request = http.Request(method, Uri.parse(url));
|
||||
request.headers.addAll(headers ?? {});
|
||||
if ((request.headers[HttpHeaders.contentTypeHeader]?.contains("application/json")) ?? false) {
|
||||
if ((request.headers[HttpHeaders.contentTypeHeader]
|
||||
?.contains("application/json")) ??
|
||||
false) {
|
||||
request.body = json.encode(body);
|
||||
request.headers.addAll(headers ?? {});
|
||||
http.StreamedResponse response = await client.send(request);
|
||||
|
|
@ -136,6 +139,7 @@ extension ToMapExtension on Map? {
|
|||
}
|
||||
|
||||
Map<String, String>? get toMapStringString {
|
||||
return this?.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||
return this
|
||||
?.map((key, value) => MapEntry(key.toString(), value.toString()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ var extention = new DefaultExtension();
|
|||
|
||||
@override
|
||||
Map<String, String> getHeaders() {
|
||||
return _extensionCall<Map>('getHeaders(`${source.baseUrl ?? ''}`)', {}).toMapStringString!;
|
||||
return _extensionCall<Map>('getHeaders(`${source.baseUrl ?? ''}`)', {})
|
||||
.toMapStringString!;
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -98,13 +99,15 @@ var extention = new DefaultExtension();
|
|||
|
||||
@override
|
||||
Future<MPages> getLatestUpdates(int page) async {
|
||||
return MPages.fromJson(await _extensionCallAsync('getLatestUpdates($page)', {}));
|
||||
return MPages.fromJson(
|
||||
await _extensionCallAsync('getLatestUpdates($page)', {}));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MPages> search(String query, int page, List<dynamic> filters) async {
|
||||
return MPages.fromJson(
|
||||
await _extensionCallAsync('search("$query",$page,${jsonEncode(filterValuesListToJson(filters))})', {}));
|
||||
return MPages.fromJson(await _extensionCallAsync(
|
||||
'search("$query",$page,${jsonEncode(filterValuesListToJson(filters))})',
|
||||
{}));
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -115,14 +118,17 @@ var extention = new DefaultExtension();
|
|||
@override
|
||||
Future<List<PageUrl>> getPageList(String url) async {
|
||||
return (await _extensionCallAsync<List>('getPageList(`$url`)', []))
|
||||
.map((e) => e is String ? PageUrl(e.trim()) : PageUrl.fromJson((e as Map).toMapStringDynamic!))
|
||||
.map((e) => e is String
|
||||
? PageUrl(e.trim())
|
||||
: PageUrl.fromJson((e as Map).toMapStringDynamic!))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Video>> getVideoList(String url) async {
|
||||
return (await _extensionCallAsync<List>('getVideoList(`$url`)', []))
|
||||
.where((element) => element['url'] != null && element['originalUrl'] != null)
|
||||
.where((element) =>
|
||||
element['url'] != null && element['originalUrl'] != null)
|
||||
.map((e) => Video.fromJson(e))
|
||||
.toList()
|
||||
.toSet()
|
||||
|
|
@ -149,12 +155,11 @@ var extention = new DefaultExtension();
|
|||
.toList();
|
||||
}
|
||||
|
||||
|
||||
T _extensionCall<T>(String call, T def) {
|
||||
_init();
|
||||
|
||||
try {
|
||||
final res = runtime.evaluate('JSON.stringify(extention.`$call`)');
|
||||
final res = runtime.evaluate('JSON.stringify(extention.$call)');
|
||||
|
||||
return jsonDecode(res.stringResult) as T;
|
||||
} catch (_) {
|
||||
|
|
@ -170,7 +175,8 @@ var extention = new DefaultExtension();
|
|||
_init();
|
||||
|
||||
try {
|
||||
final promised = await runtime.handlePromise(await runtime.evaluateAsync('jsonStringify(() => extention.$call)'));
|
||||
final promised = await runtime.handlePromise(
|
||||
await runtime.evaluateAsync('jsonStringify(() => extention.$call)'));
|
||||
|
||||
return jsonDecode(promised.stringResult) as T;
|
||||
} catch (_) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ class MDocument {
|
|||
|
||||
String? get text => _document?.text;
|
||||
|
||||
List<MElement>? get children => _document?.children.map((e) => MElement(e)).toList();
|
||||
List<MElement>? get children =>
|
||||
_document?.children.map((e) => MElement(e)).toList();
|
||||
|
||||
List<MElement>? select(String selector) {
|
||||
return _document?.select(selector)?.map((e) => MElement(e)).toList();
|
||||
|
|
@ -34,11 +35,17 @@ class MDocument {
|
|||
}
|
||||
|
||||
List<MElement>? getElementsByClassName(String classNames) {
|
||||
return _document?.getElementsByClassName(classNames).map((e) => MElement(e)).toList();
|
||||
return _document
|
||||
?.getElementsByClassName(classNames)
|
||||
.map((e) => MElement(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<MElement>? getElementsByTagName(String localNames) {
|
||||
return _document?.getElementsByTagName(localNames).map((e) => MElement(e)).toList();
|
||||
return _document
|
||||
?.getElementsByTagName(localNames)
|
||||
.map((e) => MElement(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
MElement? getElementById(String id) {
|
||||
|
|
|
|||
|
|
@ -26,13 +26,15 @@ class MElement {
|
|||
|
||||
String? get getDataSrc => _element?.getDataSrc;
|
||||
|
||||
List<MElement>? get children => _element?.children.map((e) => MElement(e)).toList();
|
||||
List<MElement>? get children =>
|
||||
_element?.children.map((e) => MElement(e)).toList();
|
||||
|
||||
MElement? get parent => MElement(_element?.parent);
|
||||
|
||||
MElement? get nextElementSibling => MElement(_element?.nextElementSibling);
|
||||
|
||||
MElement? get previousElementSibling => MElement(_element?.previousElementSibling);
|
||||
MElement? get previousElementSibling =>
|
||||
MElement(_element?.previousElementSibling);
|
||||
|
||||
String? xpathFirst(String xpath) {
|
||||
return _element?.outerHtml == null ? null : _element?.xpathFirst(xpath);
|
||||
|
|
@ -43,11 +45,17 @@ class MElement {
|
|||
}
|
||||
|
||||
List<MElement>? getElementsByClassName(String classNames) {
|
||||
return _element?.getElementsByClassName(classNames).map((e) => MElement(e)).toList();
|
||||
return _element
|
||||
?.getElementsByClassName(classNames)
|
||||
.map((e) => MElement(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<MElement>? getElementsByTagName(String localNames) {
|
||||
return _element?.getElementsByTagName(localNames).map((e) => MElement(e)).toList();
|
||||
return _element
|
||||
?.getElementsByTagName(localNames)
|
||||
.map((e) => MElement(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<MElement>? select(String selector) {
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ class SelectFilter {
|
|||
|
||||
SelectFilter(this.type, this.name, this.state, this.values, this.typeName);
|
||||
factory SelectFilter.fromJson(Map<String, dynamic> json) {
|
||||
return SelectFilter(
|
||||
json['type'], json['name'], json['state'] ?? 0, fromJsonFilterValuesToList(json['values']), json['type_name']);
|
||||
return SelectFilter(json['type'], json['name'], json['state'] ?? 0,
|
||||
fromJsonFilterValuesToList(json['values']), json['type_name']);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {
|
||||
'type': type,
|
||||
|
|
@ -39,7 +39,8 @@ class SelectFilterOption {
|
|||
factory SelectFilterOption.fromJson(Map<String, dynamic> json) {
|
||||
return SelectFilterOption(json['name'], json['value'], json['type_name']);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {'value': value, 'name': name, 'type_name': "SelectOption"};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'value': value, 'name': name, 'type_name': "SelectOption"};
|
||||
}
|
||||
|
||||
class SeparatorFilter {
|
||||
|
|
@ -49,7 +50,8 @@ class SeparatorFilter {
|
|||
factory SeparatorFilter.fromJson(Map<String, dynamic> json) {
|
||||
return SeparatorFilter(type: json['type'], json['type_name']);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {'type': type, 'type_name': "SeparatorFilter"};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'type': type, 'type_name': "SeparatorFilter"};
|
||||
}
|
||||
|
||||
class HeaderFilter {
|
||||
|
|
@ -60,7 +62,8 @@ class HeaderFilter {
|
|||
factory HeaderFilter.fromJson(Map<String, dynamic> json) {
|
||||
return HeaderFilter(json['name'], json['type_name'], type: json['value']);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {'type': type, 'name': name, 'type_name': "HeaderFilter"};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'type': type, 'name': name, 'type_name': "HeaderFilter"};
|
||||
}
|
||||
|
||||
class TextFilter {
|
||||
|
|
@ -71,9 +74,11 @@ class TextFilter {
|
|||
|
||||
TextFilter(this.type, this.name, this.typeName, {this.state = ""});
|
||||
factory TextFilter.fromJson(Map<String, dynamic> json) {
|
||||
return TextFilter(json['type'], json['name'], json['type_name'], state: json['state'] ?? "");
|
||||
return TextFilter(json['type'], json['name'], json['type_name'],
|
||||
state: json['state'] ?? "");
|
||||
}
|
||||
Map<String, dynamic> toJson() => {'type': type, 'name': name, 'state': state, 'type_name': "TextFilter"};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'type': type, 'name': name, 'state': state, 'type_name': "TextFilter"};
|
||||
}
|
||||
|
||||
class SortFilter {
|
||||
|
|
@ -88,7 +93,9 @@ class SortFilter {
|
|||
return SortFilter(
|
||||
json['type'],
|
||||
json['name'],
|
||||
json['state'] == null ? SortState(0, false, "") : SortState.fromJson(json['state']),
|
||||
json['state'] == null
|
||||
? SortState(0, false, "")
|
||||
: SortState.fromJson(json['state']),
|
||||
fromJsonFilterValuesToList(json['values']),
|
||||
json['type_name']);
|
||||
}
|
||||
|
|
@ -110,7 +117,8 @@ class SortState {
|
|||
factory SortState.fromJson(Map<String, dynamic> json) {
|
||||
return SortState(json['index'], json['ascending'], json['type_name']);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {'index': index, 'ascending': ascending, 'type_name': "SortState"};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'index': index, 'ascending': ascending, 'type_name': "SortState"};
|
||||
}
|
||||
|
||||
class TriStateFilter {
|
||||
|
|
@ -121,11 +129,19 @@ class TriStateFilter {
|
|||
String? typeName;
|
||||
|
||||
factory TriStateFilter.fromJson(Map<String, dynamic> json) {
|
||||
return TriStateFilter(json['type'], json['name'], json['value'], json['type_name'], state: json['state'] ?? 0);
|
||||
return TriStateFilter(
|
||||
json['type'], json['name'], json['value'], json['type_name'],
|
||||
state: json['state'] ?? 0);
|
||||
}
|
||||
TriStateFilter(this.type, this.name, this.value, this.typeName, {this.state = 0});
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'type': type, 'name': name, 'value': value, 'state': state, 'type_name': "TriState"};
|
||||
TriStateFilter(this.type, this.name, this.value, this.typeName,
|
||||
{this.state = 0});
|
||||
Map<String, dynamic> toJson() => {
|
||||
'type': type,
|
||||
'name': name,
|
||||
'value': value,
|
||||
'state': state,
|
||||
'type_name': "TriState"
|
||||
};
|
||||
}
|
||||
|
||||
class GroupFilter {
|
||||
|
|
@ -136,10 +152,15 @@ class GroupFilter {
|
|||
|
||||
GroupFilter(this.type, this.name, this.state, this.typeName);
|
||||
factory GroupFilter.fromJson(Map<String, dynamic> json) {
|
||||
return GroupFilter(json['type'], json['name'], fromJsonFilterValuesToList(json['state']), json['type_name']);
|
||||
return GroupFilter(json['type'], json['name'],
|
||||
fromJsonFilterValuesToList(json['state']), json['type_name']);
|
||||
}
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'type': type, 'name': name, 'state': filterValuesListToJson(state), 'type_name': "GroupFilter"};
|
||||
Map<String, dynamic> toJson() => {
|
||||
'type': type,
|
||||
'name': name,
|
||||
'state': filterValuesListToJson(state),
|
||||
'type_name': "GroupFilter"
|
||||
};
|
||||
}
|
||||
|
||||
class CheckBoxFilter {
|
||||
|
|
@ -149,12 +170,20 @@ class CheckBoxFilter {
|
|||
bool state;
|
||||
String? typeName;
|
||||
|
||||
CheckBoxFilter(this.type, this.name, this.value, this.typeName, {this.state = false});
|
||||
CheckBoxFilter(this.type, this.name, this.value, this.typeName,
|
||||
{this.state = false});
|
||||
factory CheckBoxFilter.fromJson(Map<String, dynamic> json) {
|
||||
return CheckBoxFilter(json['type'], json['name'], json['value'], json['type_name'], state: json['state'] ?? false);
|
||||
return CheckBoxFilter(
|
||||
json['type'], json['name'], json['value'], json['type_name'],
|
||||
state: json['state'] ?? false);
|
||||
}
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'type': type, 'name': name, 'value': value, 'state': state, 'type_name': "CheckBox"};
|
||||
Map<String, dynamic> toJson() => {
|
||||
'type': type,
|
||||
'name': name,
|
||||
'value': value,
|
||||
'state': state,
|
||||
'type_name': "CheckBox"
|
||||
};
|
||||
}
|
||||
|
||||
List<dynamic> fromJsonFilterValuesToList(List list) {
|
||||
|
|
@ -165,9 +194,11 @@ List<dynamic> fromJsonFilterValuesToList(List list) {
|
|||
return switch (map['type_name']) {
|
||||
'TriState' => TriStateFilter.fromJson(map.toMapStringDynamic!),
|
||||
'CheckBox' => CheckBoxFilter.fromJson(map.toMapStringDynamic!),
|
||||
'SelectOption' => SelectFilterOption.fromJson(map.toMapStringDynamic!),
|
||||
'SelectOption' =>
|
||||
SelectFilterOption.fromJson(map.toMapStringDynamic!),
|
||||
'SelectFilter' => SelectFilter.fromJson(map.toMapStringDynamic!),
|
||||
'SeparatorFilter' => SeparatorFilter.fromJson(map.toMapStringDynamic!),
|
||||
'SeparatorFilter' =>
|
||||
SeparatorFilter.fromJson(map.toMapStringDynamic!),
|
||||
'HeaderFilter' => HeaderFilter.fromJson(map.toMapStringDynamic!),
|
||||
'TextFilter' => TextFilter.fromJson(map.toMapStringDynamic!),
|
||||
'SortFilter' => SortFilter.fromJson(map.toMapStringDynamic!),
|
||||
|
|
|
|||
|
|
@ -44,15 +44,18 @@ class WordSet {
|
|||
WordSet(this.words);
|
||||
|
||||
bool anyWordIn(String dateString) {
|
||||
return words.any((word) => dateString.toLowerCase().contains(word.toLowerCase()));
|
||||
return words
|
||||
.any((word) => dateString.toLowerCase().contains(word.toLowerCase()));
|
||||
}
|
||||
|
||||
bool startsWith(String dateString) {
|
||||
return words.any((word) => dateString.toLowerCase().startsWith(word.toLowerCase()));
|
||||
return words
|
||||
.any((word) => dateString.toLowerCase().startsWith(word.toLowerCase()));
|
||||
}
|
||||
|
||||
bool endsWith(String dateString) {
|
||||
return words.any((word) => dateString.toLowerCase().endsWith(word.toLowerCase()));
|
||||
return words
|
||||
.any((word) => dateString.toLowerCase().endsWith(word.toLowerCase()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -79,7 +82,8 @@ class MBridge {
|
|||
|
||||
//Return one attr
|
||||
else if (query.nodes.length == 1) {
|
||||
String attr = query.attr != null ? query.attr!.trim().trimLeft().trimRight() : "";
|
||||
String attr =
|
||||
query.attr != null ? query.attr!.trim().trimLeft().trimRight() : "";
|
||||
if (attr.isNotEmpty) {
|
||||
attrs = [attr];
|
||||
}
|
||||
|
|
@ -102,7 +106,10 @@ class MBridge {
|
|||
statusMap = element;
|
||||
}
|
||||
for (var element in statusMap.entries) {
|
||||
if (element.key.toString().toLowerCase().contains(status.toLowerCase().trim().trimLeft().trimRight())) {
|
||||
if (element.key
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.contains(status.toLowerCase().trim().trimLeft().trimRight())) {
|
||||
return switch (element.value as int) {
|
||||
0 => Status.ongoing,
|
||||
1 => Status.completed,
|
||||
|
|
@ -259,7 +266,8 @@ class MBridge {
|
|||
}
|
||||
|
||||
//Parse a list of dates to millisecondsSinceEpoch
|
||||
static List parseDates(List value, String dateFormat, String dateFormatLocale) {
|
||||
static List parseDates(
|
||||
List value, String dateFormat, String dateFormatLocale) {
|
||||
List<dynamic> val = [];
|
||||
for (var element in value) {
|
||||
if (element is $Value) {
|
||||
|
|
@ -304,7 +312,8 @@ class MBridge {
|
|||
}
|
||||
|
||||
//Utility to use RegExp
|
||||
static String regExp(String expression, String source, String replace, int type, int group) {
|
||||
static String regExp(
|
||||
String expression, String source, String replace, int type, int group) {
|
||||
if (type == 0) {
|
||||
return expression.replaceAll(RegExp(source), replace);
|
||||
}
|
||||
|
|
@ -319,48 +328,58 @@ class MBridge {
|
|||
return await DoodExtractor().videosFromUrl(url, quality: quality);
|
||||
}
|
||||
|
||||
static Future<List<Video>> streamWishExtractor(String url, String prefix) async {
|
||||
static Future<List<Video>> streamWishExtractor(
|
||||
String url, String prefix) async {
|
||||
return await StreamWishExtractor().videosFromUrl(url, prefix);
|
||||
}
|
||||
|
||||
static Future<List<Video>> filemoonExtractor(String url, String prefix, String suffix) async {
|
||||
static Future<List<Video>> filemoonExtractor(
|
||||
String url, String prefix, String suffix) async {
|
||||
return await FilemoonExtractor().videosFromUrl(url, prefix, suffix);
|
||||
}
|
||||
|
||||
static Future<List<Video>> mp4UploadExtractor(String url, String? headers, String prefix, String suffix) async {
|
||||
static Future<List<Video>> mp4UploadExtractor(
|
||||
String url, String? headers, String prefix, String suffix) async {
|
||||
Map<String, String> newHeaders = {};
|
||||
if (headers != null) {
|
||||
newHeaders = (jsonDecode(headers) as Map).toMapStringString!;
|
||||
}
|
||||
return await Mp4uploadExtractor().videosFromUrl(url, newHeaders, prefix: prefix, suffix: suffix);
|
||||
return await Mp4uploadExtractor()
|
||||
.videosFromUrl(url, newHeaders, prefix: prefix, suffix: suffix);
|
||||
}
|
||||
|
||||
static Future<List<Map<String, String>>> quarkFilesExtractor(List<String> url, String cookie) async {
|
||||
static Future<List<Map<String, String>>> quarkFilesExtractor(
|
||||
List<String> url, String cookie) async {
|
||||
QuarkUcExtractor quark = QuarkUcExtractor();
|
||||
await quark.initCloudDrive(cookie, CloudDriveType.quark);
|
||||
return await quark.videoFilesFromUrl(url);
|
||||
}
|
||||
|
||||
static Future<List<Map<String, String>>> ucFilesExtractor(List<String> url, String cookie) async {
|
||||
static Future<List<Map<String, String>>> ucFilesExtractor(
|
||||
List<String> url, String cookie) async {
|
||||
QuarkUcExtractor uc = QuarkUcExtractor();
|
||||
await uc.initCloudDrive(cookie, CloudDriveType.uc);
|
||||
return await uc.videoFilesFromUrl(url);
|
||||
}
|
||||
|
||||
static Future<List<Video>> quarkVideosExtractor(String url, String cookie) async {
|
||||
static Future<List<Video>> quarkVideosExtractor(
|
||||
String url, String cookie) async {
|
||||
QuarkUcExtractor quark = QuarkUcExtractor();
|
||||
await quark.initCloudDrive(cookie, CloudDriveType.quark);
|
||||
return await quark.videosFromUrl(url);
|
||||
}
|
||||
|
||||
static Future<List<Video>> ucVideosExtractor(String url, String cookie) async {
|
||||
static Future<List<Video>> ucVideosExtractor(
|
||||
String url, String cookie) async {
|
||||
QuarkUcExtractor uc = QuarkUcExtractor();
|
||||
await uc.initCloudDrive(cookie, CloudDriveType.uc);
|
||||
return await uc.videosFromUrl(url);
|
||||
}
|
||||
|
||||
static Future<List<Video>> streamTapeExtractor(String url, String? quality) async {
|
||||
return await StreamTapeExtractor().videosFromUrl(url, quality: quality ?? "StreamTape");
|
||||
static Future<List<Video>> streamTapeExtractor(
|
||||
String url, String? quality) async {
|
||||
return await StreamTapeExtractor()
|
||||
.videosFromUrl(url, quality: quality ?? "StreamTape");
|
||||
}
|
||||
|
||||
//Utility to use substring
|
||||
|
|
@ -383,28 +402,55 @@ class MBridge {
|
|||
}
|
||||
|
||||
//Parse a chapter date to millisecondsSinceEpoch
|
||||
static String parseChapterDate(
|
||||
String date, String dateFormat, String dateFormatLocale, Function((String, String, bool)) newLocale) {
|
||||
static String parseChapterDate(String date, String dateFormat,
|
||||
String dateFormatLocale, Function((String, String, bool)) newLocale) {
|
||||
int parseRelativeDate(String date) {
|
||||
final number = int.tryParse(RegExp(r"(\d+)").firstMatch(date)!.group(0)!);
|
||||
if (number == null) return 0;
|
||||
final cal = DateTime.now();
|
||||
|
||||
if (WordSet(["hari", "gün", "jour", "día", "dia", "day", "วัน", "ngày", "giorni", "أيام", "天"]).anyWordIn(date)) {
|
||||
if (WordSet([
|
||||
"hari",
|
||||
"gün",
|
||||
"jour",
|
||||
"día",
|
||||
"dia",
|
||||
"day",
|
||||
"วัน",
|
||||
"ngày",
|
||||
"giorni",
|
||||
"أيام",
|
||||
"天"
|
||||
]).anyWordIn(date)) {
|
||||
return cal.subtract(Duration(days: number)).millisecondsSinceEpoch;
|
||||
} else if (WordSet(["jam", "saat", "heure", "hora", "hour", "ชั่วโมง", "giờ", "ore", "ساعة", "小时"])
|
||||
.anyWordIn(date)) {
|
||||
} else if (WordSet([
|
||||
"jam",
|
||||
"saat",
|
||||
"heure",
|
||||
"hora",
|
||||
"hour",
|
||||
"ชั่วโมง",
|
||||
"giờ",
|
||||
"ore",
|
||||
"ساعة",
|
||||
"小时"
|
||||
]).anyWordIn(date)) {
|
||||
return cal.subtract(Duration(hours: number)).millisecondsSinceEpoch;
|
||||
} else if (WordSet(["menit", "dakika", "min", "minute", "minuto", "นาที", "دقائق"]).anyWordIn(date)) {
|
||||
} else if (WordSet(
|
||||
["menit", "dakika", "min", "minute", "minuto", "นาที", "دقائق"])
|
||||
.anyWordIn(date)) {
|
||||
return cal.subtract(Duration(minutes: number)).millisecondsSinceEpoch;
|
||||
} else if (WordSet(["detik", "segundo", "second", "วินาที", "sec"]).anyWordIn(date)) {
|
||||
} else if (WordSet(["detik", "segundo", "second", "วินาที", "sec"])
|
||||
.anyWordIn(date)) {
|
||||
return cal.subtract(Duration(seconds: number)).millisecondsSinceEpoch;
|
||||
} else if (WordSet(["week", "semana"]).anyWordIn(date)) {
|
||||
return cal.subtract(Duration(days: number * 7)).millisecondsSinceEpoch;
|
||||
} else if (WordSet(["month", "mes"]).anyWordIn(date)) {
|
||||
return cal.subtract(Duration(days: number * 30)).millisecondsSinceEpoch;
|
||||
} else if (WordSet(["year", "año"]).anyWordIn(date)) {
|
||||
return cal.subtract(Duration(days: number * 365)).millisecondsSinceEpoch;
|
||||
return cal
|
||||
.subtract(Duration(days: number * 365))
|
||||
.millisecondsSinceEpoch;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -430,11 +476,19 @@ class MBridge {
|
|||
} else if (date.contains(RegExp(r"\d(st|nd|rd|th)"))) {
|
||||
final cleanedDate = date
|
||||
.split(" ")
|
||||
.map((it) => it.contains(RegExp(r"\d\D\D")) ? it.replaceAll(RegExp(r"\D"), "") : it)
|
||||
.map((it) => it.contains(RegExp(r"\d\D\D"))
|
||||
? it.replaceAll(RegExp(r"\D"), "")
|
||||
: it)
|
||||
.join(" ");
|
||||
return DateFormat(dateFormat, dateFormatLocale).parse(cleanedDate).millisecondsSinceEpoch.toString();
|
||||
return DateFormat(dateFormat, dateFormatLocale)
|
||||
.parse(cleanedDate)
|
||||
.millisecondsSinceEpoch
|
||||
.toString();
|
||||
} else {
|
||||
return DateFormat(dateFormat, dateFormatLocale).parse(date).millisecondsSinceEpoch.toString();
|
||||
return DateFormat(dateFormat, dateFormatLocale)
|
||||
.parse(date)
|
||||
.millisecondsSinceEpoch
|
||||
.toString();
|
||||
}
|
||||
} catch (e) {
|
||||
final supportedLocales = DateFormat.allLocalesWithSymbols();
|
||||
|
|
@ -456,18 +510,27 @@ class MBridge {
|
|||
DateTime cal = DateTime.now().subtract(const Duration(days: 2));
|
||||
cal = DateTime(cal.year, cal.month, cal.day);
|
||||
return cal.millisecondsSinceEpoch.toString();
|
||||
} else if (WordSet(["ago", "atrás", "önce", "قبل"]).endsWith(date)) {
|
||||
} else if (WordSet(["ago", "atrás", "önce", "قبل"])
|
||||
.endsWith(date)) {
|
||||
return parseRelativeDate(date).toString();
|
||||
} else if (WordSet(["hace"]).startsWith(date)) {
|
||||
return parseRelativeDate(date).toString();
|
||||
} else if (date.contains(RegExp(r"\d(st|nd|rd|th)"))) {
|
||||
final cleanedDate = date
|
||||
.split(" ")
|
||||
.map((it) => it.contains(RegExp(r"\d\D\D")) ? it.replaceAll(RegExp(r"\D"), "") : it)
|
||||
.map((it) => it.contains(RegExp(r"\d\D\D"))
|
||||
? it.replaceAll(RegExp(r"\D"), "")
|
||||
: it)
|
||||
.join(" ");
|
||||
return DateFormat(dateFormat, locale).parse(cleanedDate).millisecondsSinceEpoch.toString();
|
||||
return DateFormat(dateFormat, locale)
|
||||
.parse(cleanedDate)
|
||||
.millisecondsSinceEpoch
|
||||
.toString();
|
||||
} else {
|
||||
return DateFormat(dateFormat, locale).parse(date).millisecondsSinceEpoch.toString();
|
||||
return DateFormat(dateFormat, locale)
|
||||
.parse(date)
|
||||
.millisecondsSinceEpoch
|
||||
.toString();
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
|
@ -485,13 +548,15 @@ class MBridge {
|
|||
return await SibnetExtractor().videosFromUrl(url, prefix: prefix);
|
||||
}
|
||||
|
||||
static Future<List<Video>> sendVidExtractor(String url, String? headers, String prefix) async {
|
||||
static Future<List<Video>> sendVidExtractor(
|
||||
String url, String? headers, String prefix) async {
|
||||
Map<String, String> newHeaders = {};
|
||||
if (headers != null) {
|
||||
newHeaders = (jsonDecode(headers) as Map).toMapStringString!;
|
||||
}
|
||||
|
||||
return await SendvidExtractor(newHeaders).videosFromUrl(url, prefix: prefix);
|
||||
return await SendvidExtractor(newHeaders)
|
||||
.videosFromUrl(url, prefix: prefix);
|
||||
}
|
||||
|
||||
static Future<List<Video>> myTvExtractor(String url) async {
|
||||
|
|
@ -502,12 +567,14 @@ class MBridge {
|
|||
return await OkruExtractor().videosFromUrl(url);
|
||||
}
|
||||
|
||||
static Future<List<Video>> yourUploadExtractor(String url, String? headers, String? name, String prefix) async {
|
||||
static Future<List<Video>> yourUploadExtractor(
|
||||
String url, String? headers, String? name, String prefix) async {
|
||||
Map<String, String> newHeaders = {};
|
||||
if (headers != null) {
|
||||
newHeaders = (jsonDecode(headers) as Map).toMapStringString!;
|
||||
}
|
||||
return await YourUploadExtractor().videosFromUrl(url, newHeaders, prefix: prefix, name: name ?? "YourUpload");
|
||||
return await YourUploadExtractor().videosFromUrl(url, newHeaders,
|
||||
prefix: prefix, name: name ?? "YourUpload");
|
||||
}
|
||||
|
||||
static Future<List<Video>> voeExtractor(String url, String? quality) async {
|
||||
|
|
@ -518,8 +585,10 @@ class MBridge {
|
|||
return await VidBomExtractor().videosFromUrl(url);
|
||||
}
|
||||
|
||||
static Future<List<Video>> streamlareExtractor(String url, String prefix, String suffix) async {
|
||||
return await StreamlareExtractor().videosFromUrl(url, prefix: prefix, suffix: suffix);
|
||||
static Future<List<Video>> streamlareExtractor(
|
||||
String url, String prefix, String suffix) async {
|
||||
return await StreamlareExtractor()
|
||||
.videosFromUrl(url, prefix: prefix, suffix: suffix);
|
||||
}
|
||||
|
||||
static String encryptAESCryptoJS(String plainText, String passphrase) {
|
||||
|
|
@ -530,16 +599,18 @@ class MBridge {
|
|||
return CryptoAES.decryptAESCryptoJS(encrypted, passphrase);
|
||||
}
|
||||
|
||||
static Video toVideo(
|
||||
String url, String quality, String originalUrl, String? headers, List<Track>? subtitles, List<Track>? audios) {
|
||||
static Video toVideo(String url, String quality, String originalUrl,
|
||||
String? headers, List<Track>? subtitles, List<Track>? audios) {
|
||||
Map<String, String> newHeaders = {};
|
||||
if (headers != null) {
|
||||
newHeaders = (jsonDecode(headers) as Map).toMapStringString!;
|
||||
}
|
||||
return Video(url, quality, originalUrl, headers: newHeaders, subtitles: subtitles ?? [], audios: audios ?? []);
|
||||
return Video(url, quality, originalUrl,
|
||||
headers: newHeaders, subtitles: subtitles ?? [], audios: audios ?? []);
|
||||
}
|
||||
|
||||
static String cryptoHandler(String text, String iv, String secretKeyString, bool encrypt) {
|
||||
static String cryptoHandler(
|
||||
String text, String iv, String secretKeyString, bool encrypt) {
|
||||
try {
|
||||
if (encrypt) {
|
||||
final encryptt = _encrypt(secretKeyString, iv);
|
||||
|
|
@ -603,7 +674,10 @@ void botToast(String title,
|
|||
bool hasCloudFlare = false,
|
||||
String? url}) {
|
||||
final context = navigatorKey.currentState?.context;
|
||||
final assets = ['assets/app_icons/icon-black.png', 'assets/app_icons/icon-red.png'];
|
||||
final assets = [
|
||||
'assets/app_icons/icon-black.png',
|
||||
'assets/app_icons/icon-red.png'
|
||||
];
|
||||
BotToast.showNotification(
|
||||
onlyOne: true,
|
||||
dismissDirections: [DismissDirection.horizontal, DismissDirection.down],
|
||||
|
|
@ -617,9 +691,11 @@ void botToast(String title,
|
|||
? (_) => OutlinedButton.icon(
|
||||
style: OutlinedButton.styleFrom(elevation: 10),
|
||||
onPressed: () {
|
||||
context?.push("/mangawebview", extra: {'url': url, 'title': ''});
|
||||
context
|
||||
?.push("/mangawebview", extra: {'url': url, 'title': ''});
|
||||
},
|
||||
label: Text("Resolve Cloudflare challenge", style: TextStyle(color: context?.secondaryColor)),
|
||||
label: Text("Resolve Cloudflare challenge",
|
||||
style: TextStyle(color: context?.secondaryColor)),
|
||||
icon: const Icon(Icons.public),
|
||||
)
|
||||
: null,
|
||||
|
|
@ -629,6 +705,7 @@ void botToast(String title,
|
|||
(encrypt.Encrypter, encrypt.IV) _encrypt(String keyy, String ivv) {
|
||||
final key = encrypt.Key.fromUtf8(keyy);
|
||||
final iv = encrypt.IV.fromUtf8(ivv);
|
||||
final encrypter = encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: 'PKCS7'));
|
||||
final encrypter = encrypt.Encrypter(
|
||||
encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: 'PKCS7'));
|
||||
return (encrypter, iv);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,16 @@ class MChapter {
|
|||
String? scanlator;
|
||||
MChapter({this.name, this.url, this.dateUpload, this.scanlator});
|
||||
factory MChapter.fromJson(Map<String, dynamic> json) {
|
||||
return MChapter(name: json['name'], url: json['url'], dateUpload: json['dateUpload'], scanlator: json['scanlator']);
|
||||
return MChapter(
|
||||
name: json['name'],
|
||||
url: json['url'],
|
||||
dateUpload: json['dateUpload'],
|
||||
scanlator: json['scanlator']);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {'name': name, 'url': url, 'dateUpload': dateUpload, 'scanlator': scanlator};
|
||||
Map<String, dynamic> toJson() => {
|
||||
'name': name,
|
||||
'url': url,
|
||||
'dateUpload': dateUpload,
|
||||
'scanlator': scanlator
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,11 +48,16 @@ class MManga {
|
|||
4 => Status.publishingFinished,
|
||||
_ => Status.unknown,
|
||||
},
|
||||
genre: (json['genre'] as List?)?.map((e) => e.toString()).toList() ?? [],
|
||||
genre:
|
||||
(json['genre'] as List?)?.map((e) => e.toString()).toList() ?? [],
|
||||
chapters: json['chapters'] != null
|
||||
? (json['chapters'] as List).map((e) => MChapter.fromJson(e)).toList()
|
||||
? (json['chapters'] as List)
|
||||
.map((e) => MChapter.fromJson(e))
|
||||
.toList()
|
||||
: json['episodes'] != null
|
||||
? (json['episodes'] as List).map((e) => MChapter.fromJson(e)).toList()
|
||||
? (json['episodes'] as List)
|
||||
.map((e) => MChapter.fromJson(e))
|
||||
.toList()
|
||||
: []);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@ class MPages {
|
|||
|
||||
factory MPages.fromJson(Map<String, dynamic> json) {
|
||||
return MPages(
|
||||
list: json['list'] != null ? (json['list'] as List).map((e) => MManga.fromJson(e)).toList() : [],
|
||||
list: json['list'] != null
|
||||
? (json['list'] as List).map((e) => MManga.fromJson(e)).toList()
|
||||
: [],
|
||||
hasNextPage: json['hasNextPage']);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ class MVideo {
|
|||
List<MTrack>? subtitles;
|
||||
List<MTrack>? audios;
|
||||
|
||||
MVideo(this.url, this.quality, this.originalUrl, {this.headers, this.subtitles, this.audios});
|
||||
MVideo(this.url, this.quality, this.originalUrl,
|
||||
{this.headers, this.subtitles, this.audios});
|
||||
}
|
||||
|
||||
class MTrack {
|
||||
|
|
|
|||
|
|
@ -27,11 +27,15 @@ class SourcePreference {
|
|||
'id': id,
|
||||
'sourceId': sourceId,
|
||||
'key': key,
|
||||
if (checkBoxPreference != null) 'checkBoxPreference': checkBoxPreference!.toJson(),
|
||||
if (switchPreferenceCompat != null) 'switchPreferenceCompat': switchPreferenceCompat!.toJson(),
|
||||
if (checkBoxPreference != null)
|
||||
'checkBoxPreference': checkBoxPreference!.toJson(),
|
||||
if (switchPreferenceCompat != null)
|
||||
'switchPreferenceCompat': switchPreferenceCompat!.toJson(),
|
||||
if (listPreference != null) 'listPreference': listPreference!.toJson(),
|
||||
if (multiSelectListPreference != null) 'multiSelectListPreference': multiSelectListPreference!.toJson(),
|
||||
if (editTextPreference != null) 'editTextPreference': editTextPreference!.toJson()
|
||||
if (multiSelectListPreference != null)
|
||||
'multiSelectListPreference': multiSelectListPreference!.toJson(),
|
||||
if (editTextPreference != null)
|
||||
'editTextPreference': editTextPreference!.toJson()
|
||||
};
|
||||
|
||||
factory SourcePreference.fromJson(Map<String, dynamic> json) {
|
||||
|
|
@ -39,17 +43,22 @@ class SourcePreference {
|
|||
id: json['id'] ?? Isar.autoIncrement,
|
||||
sourceId: json['sourceId'],
|
||||
key: json['key'],
|
||||
checkBoxPreference:
|
||||
json['checkBoxPreference'] != null ? CheckBoxPreference.fromJson(json['checkBoxPreference']) : null,
|
||||
checkBoxPreference: json['checkBoxPreference'] != null
|
||||
? CheckBoxPreference.fromJson(json['checkBoxPreference'])
|
||||
: null,
|
||||
switchPreferenceCompat: json['switchPreferenceCompat'] != null
|
||||
? SwitchPreferenceCompat.fromJson(json['switchPreferenceCompat'])
|
||||
: null,
|
||||
listPreference: json['listPreference'] != null ? ListPreference.fromJson(json['listPreference']) : null,
|
||||
multiSelectListPreference: json['multiSelectListPreference'] != null
|
||||
? MultiSelectListPreference.fromJson(json['multiSelectListPreference'])
|
||||
listPreference: json['listPreference'] != null
|
||||
? ListPreference.fromJson(json['listPreference'])
|
||||
: null,
|
||||
editTextPreference:
|
||||
json['editTextPreference'] != null ? EditTextPreference.fromJson(json['editTextPreference']) : null);
|
||||
multiSelectListPreference: json['multiSelectListPreference'] != null
|
||||
? MultiSelectListPreference.fromJson(
|
||||
json['multiSelectListPreference'])
|
||||
: null,
|
||||
editTextPreference: json['editTextPreference'] != null
|
||||
? EditTextPreference.fromJson(json['editTextPreference'])
|
||||
: null);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,10 +70,12 @@ class CheckBoxPreference {
|
|||
|
||||
CheckBoxPreference({this.title, this.summary, this.value});
|
||||
|
||||
Map<String, dynamic> toJson() => {'title': title, 'summary': summary, 'value': value};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'title': title, 'summary': summary, 'value': value};
|
||||
|
||||
factory CheckBoxPreference.fromJson(Map<String, dynamic> json) {
|
||||
return CheckBoxPreference(title: json['title'], summary: json['summary'], value: json['value']);
|
||||
return CheckBoxPreference(
|
||||
title: json['title'], summary: json['summary'], value: json['value']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -76,10 +87,12 @@ class SwitchPreferenceCompat {
|
|||
|
||||
SwitchPreferenceCompat({this.title, this.summary, this.value});
|
||||
|
||||
Map<String, dynamic> toJson() => {'title': title, 'summary': summary, 'value': value};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'title': title, 'summary': summary, 'value': value};
|
||||
|
||||
factory SwitchPreferenceCompat.fromJson(Map<String, dynamic> json) {
|
||||
return SwitchPreferenceCompat(title: json['title'], summary: json['summary'], value: json['value']);
|
||||
return SwitchPreferenceCompat(
|
||||
title: json['title'], summary: json['summary'], value: json['value']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,10 +104,20 @@ class ListPreference {
|
|||
List<String>? entries;
|
||||
List<String>? entryValues;
|
||||
|
||||
ListPreference({this.title, this.summary, this.valueIndex, this.entries, this.entryValues});
|
||||
ListPreference(
|
||||
{this.title,
|
||||
this.summary,
|
||||
this.valueIndex,
|
||||
this.entries,
|
||||
this.entryValues});
|
||||
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'title': title, 'summary': summary, 'valueIndex': valueIndex, 'entries': entries, 'entryValues': entryValues};
|
||||
Map<String, dynamic> toJson() => {
|
||||
'title': title,
|
||||
'summary': summary,
|
||||
'valueIndex': valueIndex,
|
||||
'entries': entries,
|
||||
'entryValues': entryValues
|
||||
};
|
||||
|
||||
factory ListPreference.fromJson(Map<String, dynamic> json) {
|
||||
return ListPreference(
|
||||
|
|
@ -114,7 +137,8 @@ class MultiSelectListPreference {
|
|||
List<String>? entryValues;
|
||||
List<String>? values;
|
||||
|
||||
MultiSelectListPreference({this.title, this.summary, this.entries, this.entryValues, this.values});
|
||||
MultiSelectListPreference(
|
||||
{this.title, this.summary, this.entries, this.entryValues, this.values});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'title': title,
|
||||
|
|
@ -143,7 +167,13 @@ class EditTextPreference {
|
|||
String? dialogMessage;
|
||||
String? text;
|
||||
|
||||
EditTextPreference({this.title, this.summary, this.value, this.dialogTitle, this.dialogMessage, this.text});
|
||||
EditTextPreference(
|
||||
{this.title,
|
||||
this.summary,
|
||||
this.value,
|
||||
this.dialogTitle,
|
||||
this.dialogMessage,
|
||||
this.text});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'title': title,
|
||||
|
|
@ -173,5 +203,6 @@ class SourcePreferenceStringValue {
|
|||
String? key;
|
||||
String? value;
|
||||
|
||||
SourcePreferenceStringValue({this.id = Isar.autoIncrement, this.sourceId, this.key, this.value});
|
||||
SourcePreferenceStringValue(
|
||||
{this.id = Isar.autoIncrement, this.sourceId, this.key, this.value});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,17 @@ import 'dart:ffi' as ffi;
|
|||
/// Bindings to `lib/ffi/libmtorrentserver.h`.
|
||||
class TorrentLibrary {
|
||||
/// Holds the symbol lookup function.
|
||||
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) _lookup;
|
||||
final ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||
_lookup;
|
||||
|
||||
/// The symbols are looked up in [dynamicLibrary].
|
||||
TorrentLibrary(ffi.DynamicLibrary dynamicLibrary) : _lookup = dynamicLibrary.lookup;
|
||||
TorrentLibrary(ffi.DynamicLibrary dynamicLibrary)
|
||||
: _lookup = dynamicLibrary.lookup;
|
||||
|
||||
/// The symbols are looked up with [lookup].
|
||||
TorrentLibrary.fromLookup(ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName) lookup)
|
||||
TorrentLibrary.fromLookup(
|
||||
ffi.Pointer<T> Function<T extends ffi.NativeType>(String symbolName)
|
||||
lookup)
|
||||
: _lookup = lookup;
|
||||
|
||||
void __va_start(
|
||||
|
|
@ -30,15 +34,21 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final ___va_startPtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<va_list>)>>('__va_start');
|
||||
late final ___va_start = ___va_startPtr.asFunction<void Function(ffi.Pointer<va_list>)>();
|
||||
late final ___va_startPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<va_list>)>>(
|
||||
'__va_start');
|
||||
late final ___va_start =
|
||||
___va_startPtr.asFunction<void Function(ffi.Pointer<va_list>)>();
|
||||
|
||||
void __security_init_cookie() {
|
||||
return ___security_init_cookie();
|
||||
}
|
||||
|
||||
late final ___security_init_cookiePtr = _lookup<ffi.NativeFunction<ffi.Void Function()>>('__security_init_cookie');
|
||||
late final ___security_init_cookie = ___security_init_cookiePtr.asFunction<void Function()>();
|
||||
late final ___security_init_cookiePtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function()>>(
|
||||
'__security_init_cookie');
|
||||
late final ___security_init_cookie =
|
||||
___security_init_cookiePtr.asFunction<void Function()>();
|
||||
|
||||
void __security_check_cookie(
|
||||
int _StackCookie,
|
||||
|
|
@ -49,8 +59,10 @@ class TorrentLibrary {
|
|||
}
|
||||
|
||||
late final ___security_check_cookiePtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.UintPtr)>>('__security_check_cookie');
|
||||
late final ___security_check_cookie = ___security_check_cookiePtr.asFunction<void Function(int)>();
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.UintPtr)>>(
|
||||
'__security_check_cookie');
|
||||
late final ___security_check_cookie =
|
||||
___security_check_cookiePtr.asFunction<void Function(int)>();
|
||||
|
||||
void __report_gsfailure(
|
||||
int _StackCookie,
|
||||
|
|
@ -60,10 +72,14 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final ___report_gsfailurePtr = _lookup<ffi.NativeFunction<ffi.Void Function(ffi.UintPtr)>>('__report_gsfailure');
|
||||
late final ___report_gsfailure = ___report_gsfailurePtr.asFunction<void Function(int)>();
|
||||
late final ___report_gsfailurePtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.UintPtr)>>(
|
||||
'__report_gsfailure');
|
||||
late final ___report_gsfailure =
|
||||
___report_gsfailurePtr.asFunction<void Function(int)>();
|
||||
|
||||
late final ffi.Pointer<ffi.UintPtr> ___security_cookie = _lookup<ffi.UintPtr>('__security_cookie');
|
||||
late final ffi.Pointer<ffi.UintPtr> ___security_cookie =
|
||||
_lookup<ffi.UintPtr>('__security_cookie');
|
||||
|
||||
int get __security_cookie => ___security_cookie.value;
|
||||
|
||||
|
|
@ -74,16 +90,20 @@ class TorrentLibrary {
|
|||
}
|
||||
|
||||
late final __invalid_parameter_noinfoPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function()>>('_invalid_parameter_noinfo');
|
||||
late final __invalid_parameter_noinfo = __invalid_parameter_noinfoPtr.asFunction<void Function()>();
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function()>>(
|
||||
'_invalid_parameter_noinfo');
|
||||
late final __invalid_parameter_noinfo =
|
||||
__invalid_parameter_noinfoPtr.asFunction<void Function()>();
|
||||
|
||||
void _invalid_parameter_noinfo_noreturn() {
|
||||
return __invalid_parameter_noinfo_noreturn();
|
||||
}
|
||||
|
||||
late final __invalid_parameter_noinfo_noreturnPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function()>>('_invalid_parameter_noinfo_noreturn');
|
||||
late final __invalid_parameter_noinfo_noreturn = __invalid_parameter_noinfo_noreturnPtr.asFunction<void Function()>();
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function()>>(
|
||||
'_invalid_parameter_noinfo_noreturn');
|
||||
late final __invalid_parameter_noinfo_noreturn =
|
||||
__invalid_parameter_noinfo_noreturnPtr.asFunction<void Function()>();
|
||||
|
||||
void _invoke_watson(
|
||||
ffi.Pointer<ffi.WChar> _Expression,
|
||||
|
|
@ -103,16 +123,22 @@ class TorrentLibrary {
|
|||
|
||||
late final __invoke_watsonPtr = _lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.WChar>, ffi.UnsignedInt,
|
||||
ffi.Void Function(
|
||||
ffi.Pointer<ffi.WChar>,
|
||||
ffi.Pointer<ffi.WChar>,
|
||||
ffi.Pointer<ffi.WChar>,
|
||||
ffi.UnsignedInt,
|
||||
ffi.UintPtr)>>('_invoke_watson');
|
||||
late final __invoke_watson = __invoke_watsonPtr
|
||||
.asFunction<void Function(ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.WChar>, int, int)>();
|
||||
late final __invoke_watson = __invoke_watsonPtr.asFunction<
|
||||
void Function(ffi.Pointer<ffi.WChar>, ffi.Pointer<ffi.WChar>,
|
||||
ffi.Pointer<ffi.WChar>, int, int)>();
|
||||
|
||||
ffi.Pointer<ffi.Int> _errno() {
|
||||
return __errno();
|
||||
}
|
||||
|
||||
late final __errnoPtr = _lookup<ffi.NativeFunction<ffi.Pointer<ffi.Int> Function()>>('_errno');
|
||||
late final __errnoPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Int> Function()>>('_errno');
|
||||
late final __errno = __errnoPtr.asFunction<ffi.Pointer<ffi.Int> Function()>();
|
||||
|
||||
int _set_errno(
|
||||
|
|
@ -123,7 +149,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final __set_errnoPtr = _lookup<ffi.NativeFunction<errno_t Function(ffi.Int)>>('_set_errno');
|
||||
late final __set_errnoPtr =
|
||||
_lookup<ffi.NativeFunction<errno_t Function(ffi.Int)>>('_set_errno');
|
||||
late final __set_errno = __set_errnoPtr.asFunction<int Function(int)>();
|
||||
|
||||
int _get_errno(
|
||||
|
|
@ -134,21 +161,26 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final __get_errnoPtr = _lookup<ffi.NativeFunction<errno_t Function(ffi.Pointer<ffi.Int>)>>('_get_errno');
|
||||
late final __get_errno = __get_errnoPtr.asFunction<int Function(ffi.Pointer<ffi.Int>)>();
|
||||
late final __get_errnoPtr =
|
||||
_lookup<ffi.NativeFunction<errno_t Function(ffi.Pointer<ffi.Int>)>>(
|
||||
'_get_errno');
|
||||
late final __get_errno =
|
||||
__get_errnoPtr.asFunction<int Function(ffi.Pointer<ffi.Int>)>();
|
||||
|
||||
int __threadid() {
|
||||
return ___threadid();
|
||||
}
|
||||
|
||||
late final ___threadidPtr = _lookup<ffi.NativeFunction<ffi.UnsignedLong Function()>>('__threadid');
|
||||
late final ___threadidPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.UnsignedLong Function()>>('__threadid');
|
||||
late final ___threadid = ___threadidPtr.asFunction<int Function()>();
|
||||
|
||||
int __threadhandle() {
|
||||
return ___threadhandle();
|
||||
}
|
||||
|
||||
late final ___threadhandlePtr = _lookup<ffi.NativeFunction<ffi.UintPtr Function()>>('__threadhandle');
|
||||
late final ___threadhandlePtr =
|
||||
_lookup<ffi.NativeFunction<ffi.UintPtr Function()>>('__threadhandle');
|
||||
late final ___threadhandle = ___threadhandlePtr.asFunction<int Function()>();
|
||||
|
||||
double cabs(
|
||||
|
|
@ -159,7 +191,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cabsPtr = _lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('cabs');
|
||||
late final _cabsPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('cabs');
|
||||
late final _cabs = _cabsPtr.asFunction<double Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex cacos(
|
||||
|
|
@ -170,7 +203,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cacosPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('cacos');
|
||||
late final _cacosPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('cacos');
|
||||
late final _cacos = _cacosPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex cacosh(
|
||||
|
|
@ -181,7 +215,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cacoshPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('cacosh');
|
||||
late final _cacoshPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('cacosh');
|
||||
late final _cacosh = _cacoshPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
double carg(
|
||||
|
|
@ -192,7 +227,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cargPtr = _lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('carg');
|
||||
late final _cargPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('carg');
|
||||
late final _carg = _cargPtr.asFunction<double Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex casin(
|
||||
|
|
@ -203,7 +239,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _casinPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('casin');
|
||||
late final _casinPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('casin');
|
||||
late final _casin = _casinPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex casinh(
|
||||
|
|
@ -214,7 +251,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _casinhPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('casinh');
|
||||
late final _casinhPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('casinh');
|
||||
late final _casinh = _casinhPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex catan(
|
||||
|
|
@ -225,7 +263,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _catanPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('catan');
|
||||
late final _catanPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('catan');
|
||||
late final _catan = _catanPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex catanh(
|
||||
|
|
@ -236,7 +275,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _catanhPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('catanh');
|
||||
late final _catanhPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('catanh');
|
||||
late final _catanh = _catanhPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex ccos(
|
||||
|
|
@ -247,7 +287,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _ccosPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('ccos');
|
||||
late final _ccosPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('ccos');
|
||||
late final _ccos = _ccosPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex ccosh(
|
||||
|
|
@ -258,7 +299,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _ccoshPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('ccosh');
|
||||
late final _ccoshPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('ccosh');
|
||||
late final _ccosh = _ccoshPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex cexp(
|
||||
|
|
@ -269,7 +311,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cexpPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('cexp');
|
||||
late final _cexpPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('cexp');
|
||||
late final _cexp = _cexpPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
double cimag(
|
||||
|
|
@ -280,7 +323,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cimagPtr = _lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('cimag');
|
||||
late final _cimagPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('cimag');
|
||||
late final _cimag = _cimagPtr.asFunction<double Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex clog(
|
||||
|
|
@ -291,7 +335,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _clogPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('clog');
|
||||
late final _clogPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('clog');
|
||||
late final _clog = _clogPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex clog10(
|
||||
|
|
@ -302,7 +347,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _clog10Ptr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('clog10');
|
||||
late final _clog10Ptr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('clog10');
|
||||
late final _clog10 = _clog10Ptr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex conj(
|
||||
|
|
@ -313,7 +359,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _conjPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('conj');
|
||||
late final _conjPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('conj');
|
||||
late final _conj = _conjPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex cpow(
|
||||
|
|
@ -326,8 +373,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cpowPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex, _Dcomplex)>>('cpow');
|
||||
late final _cpow = _cpowPtr.asFunction<_Dcomplex Function(_Dcomplex, _Dcomplex)>();
|
||||
late final _cpowPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex, _Dcomplex)>>(
|
||||
'cpow');
|
||||
late final _cpow =
|
||||
_cpowPtr.asFunction<_Dcomplex Function(_Dcomplex, _Dcomplex)>();
|
||||
|
||||
_Dcomplex cproj(
|
||||
_Dcomplex _Z,
|
||||
|
|
@ -337,7 +387,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cprojPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('cproj');
|
||||
late final _cprojPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('cproj');
|
||||
late final _cproj = _cprojPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
double creal(
|
||||
|
|
@ -348,7 +399,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _crealPtr = _lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('creal');
|
||||
late final _crealPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('creal');
|
||||
late final _creal = _crealPtr.asFunction<double Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex csin(
|
||||
|
|
@ -359,7 +411,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _csinPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('csin');
|
||||
late final _csinPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('csin');
|
||||
late final _csin = _csinPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex csinh(
|
||||
|
|
@ -370,7 +423,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _csinhPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('csinh');
|
||||
late final _csinhPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('csinh');
|
||||
late final _csinh = _csinhPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex csqrt(
|
||||
|
|
@ -381,7 +435,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _csqrtPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('csqrt');
|
||||
late final _csqrtPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('csqrt');
|
||||
late final _csqrt = _csqrtPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex ctan(
|
||||
|
|
@ -392,7 +447,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _ctanPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('ctan');
|
||||
late final _ctanPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('ctan');
|
||||
late final _ctan = _ctanPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
_Dcomplex ctanh(
|
||||
|
|
@ -403,7 +459,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _ctanhPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('ctanh');
|
||||
late final _ctanhPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex)>>('ctanh');
|
||||
late final _ctanh = _ctanhPtr.asFunction<_Dcomplex Function(_Dcomplex)>();
|
||||
|
||||
double norm(
|
||||
|
|
@ -414,7 +471,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _normPtr = _lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('norm');
|
||||
late final _normPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Double Function(_Dcomplex)>>('norm');
|
||||
late final _norm = _normPtr.asFunction<double Function(_Dcomplex)>();
|
||||
|
||||
double cabsf(
|
||||
|
|
@ -425,7 +483,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cabsfPtr = _lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('cabsf');
|
||||
late final _cabsfPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('cabsf');
|
||||
late final _cabsf = _cabsfPtr.asFunction<double Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex cacosf(
|
||||
|
|
@ -436,7 +495,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cacosfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('cacosf');
|
||||
late final _cacosfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('cacosf');
|
||||
late final _cacosf = _cacosfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex cacoshf(
|
||||
|
|
@ -447,7 +507,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cacoshfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('cacoshf');
|
||||
late final _cacoshfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('cacoshf');
|
||||
late final _cacoshf = _cacoshfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
double cargf(
|
||||
|
|
@ -458,7 +519,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cargfPtr = _lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('cargf');
|
||||
late final _cargfPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('cargf');
|
||||
late final _cargf = _cargfPtr.asFunction<double Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex casinf(
|
||||
|
|
@ -469,7 +531,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _casinfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('casinf');
|
||||
late final _casinfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('casinf');
|
||||
late final _casinf = _casinfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex casinhf(
|
||||
|
|
@ -480,7 +543,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _casinhfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('casinhf');
|
||||
late final _casinhfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('casinhf');
|
||||
late final _casinhf = _casinhfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex catanf(
|
||||
|
|
@ -491,7 +555,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _catanfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('catanf');
|
||||
late final _catanfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('catanf');
|
||||
late final _catanf = _catanfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex catanhf(
|
||||
|
|
@ -502,7 +567,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _catanhfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('catanhf');
|
||||
late final _catanhfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('catanhf');
|
||||
late final _catanhf = _catanhfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex ccosf(
|
||||
|
|
@ -513,7 +579,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _ccosfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('ccosf');
|
||||
late final _ccosfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('ccosf');
|
||||
late final _ccosf = _ccosfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex ccoshf(
|
||||
|
|
@ -524,7 +591,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _ccoshfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('ccoshf');
|
||||
late final _ccoshfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('ccoshf');
|
||||
late final _ccoshf = _ccoshfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex cexpf(
|
||||
|
|
@ -535,7 +603,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cexpfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('cexpf');
|
||||
late final _cexpfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('cexpf');
|
||||
late final _cexpf = _cexpfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
double cimagf(
|
||||
|
|
@ -546,7 +615,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cimagfPtr = _lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('cimagf');
|
||||
late final _cimagfPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('cimagf');
|
||||
late final _cimagf = _cimagfPtr.asFunction<double Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex clogf(
|
||||
|
|
@ -557,7 +627,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _clogfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('clogf');
|
||||
late final _clogfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('clogf');
|
||||
late final _clogf = _clogfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex clog10f(
|
||||
|
|
@ -568,7 +639,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _clog10fPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('clog10f');
|
||||
late final _clog10fPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('clog10f');
|
||||
late final _clog10f = _clog10fPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex conjf(
|
||||
|
|
@ -579,7 +651,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _conjfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('conjf');
|
||||
late final _conjfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('conjf');
|
||||
late final _conjf = _conjfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex cpowf(
|
||||
|
|
@ -592,8 +665,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cpowfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex, _Fcomplex)>>('cpowf');
|
||||
late final _cpowf = _cpowfPtr.asFunction<_Fcomplex Function(_Fcomplex, _Fcomplex)>();
|
||||
late final _cpowfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex, _Fcomplex)>>(
|
||||
'cpowf');
|
||||
late final _cpowf =
|
||||
_cpowfPtr.asFunction<_Fcomplex Function(_Fcomplex, _Fcomplex)>();
|
||||
|
||||
_Fcomplex cprojf(
|
||||
_Fcomplex _Z,
|
||||
|
|
@ -603,7 +679,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _cprojfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('cprojf');
|
||||
late final _cprojfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('cprojf');
|
||||
late final _cprojf = _cprojfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
double crealf(
|
||||
|
|
@ -614,7 +691,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _crealfPtr = _lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('crealf');
|
||||
late final _crealfPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('crealf');
|
||||
late final _crealf = _crealfPtr.asFunction<double Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex csinf(
|
||||
|
|
@ -625,7 +703,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _csinfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('csinf');
|
||||
late final _csinfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('csinf');
|
||||
late final _csinf = _csinfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex csinhf(
|
||||
|
|
@ -636,7 +715,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _csinhfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('csinhf');
|
||||
late final _csinhfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('csinhf');
|
||||
late final _csinhf = _csinhfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex csqrtf(
|
||||
|
|
@ -647,7 +727,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _csqrtfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('csqrtf');
|
||||
late final _csqrtfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('csqrtf');
|
||||
late final _csqrtf = _csqrtfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex ctanf(
|
||||
|
|
@ -658,7 +739,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _ctanfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('ctanf');
|
||||
late final _ctanfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('ctanf');
|
||||
late final _ctanf = _ctanfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
_Fcomplex ctanhf(
|
||||
|
|
@ -669,7 +751,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _ctanhfPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('ctanhf');
|
||||
late final _ctanhfPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex)>>('ctanhf');
|
||||
late final _ctanhf = _ctanhfPtr.asFunction<_Fcomplex Function(_Fcomplex)>();
|
||||
|
||||
double normf(
|
||||
|
|
@ -680,7 +763,8 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _normfPtr = _lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('normf');
|
||||
late final _normfPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Float Function(_Fcomplex)>>('normf');
|
||||
late final _normf = _normfPtr.asFunction<double Function(_Fcomplex)>();
|
||||
|
||||
_Dcomplex _Cbuild(
|
||||
|
|
@ -693,8 +777,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final __CbuildPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(ffi.Double, ffi.Double)>>('_Cbuild');
|
||||
late final __Cbuild = __CbuildPtr.asFunction<_Dcomplex Function(double, double)>();
|
||||
late final __CbuildPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(ffi.Double, ffi.Double)>>(
|
||||
'_Cbuild');
|
||||
late final __Cbuild =
|
||||
__CbuildPtr.asFunction<_Dcomplex Function(double, double)>();
|
||||
|
||||
_Dcomplex _Cmulcc(
|
||||
_Dcomplex _X,
|
||||
|
|
@ -706,8 +793,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final __CmulccPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex, _Dcomplex)>>('_Cmulcc');
|
||||
late final __Cmulcc = __CmulccPtr.asFunction<_Dcomplex Function(_Dcomplex, _Dcomplex)>();
|
||||
late final __CmulccPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex, _Dcomplex)>>(
|
||||
'_Cmulcc');
|
||||
late final __Cmulcc =
|
||||
__CmulccPtr.asFunction<_Dcomplex Function(_Dcomplex, _Dcomplex)>();
|
||||
|
||||
_Dcomplex _Cmulcr(
|
||||
_Dcomplex _X,
|
||||
|
|
@ -719,8 +809,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final __CmulcrPtr = _lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex, ffi.Double)>>('_Cmulcr');
|
||||
late final __Cmulcr = __CmulcrPtr.asFunction<_Dcomplex Function(_Dcomplex, double)>();
|
||||
late final __CmulcrPtr =
|
||||
_lookup<ffi.NativeFunction<_Dcomplex Function(_Dcomplex, ffi.Double)>>(
|
||||
'_Cmulcr');
|
||||
late final __Cmulcr =
|
||||
__CmulcrPtr.asFunction<_Dcomplex Function(_Dcomplex, double)>();
|
||||
|
||||
_Fcomplex _FCbuild(
|
||||
double _Re,
|
||||
|
|
@ -732,8 +825,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final __FCbuildPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(ffi.Float, ffi.Float)>>('_FCbuild');
|
||||
late final __FCbuild = __FCbuildPtr.asFunction<_Fcomplex Function(double, double)>();
|
||||
late final __FCbuildPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(ffi.Float, ffi.Float)>>(
|
||||
'_FCbuild');
|
||||
late final __FCbuild =
|
||||
__FCbuildPtr.asFunction<_Fcomplex Function(double, double)>();
|
||||
|
||||
_Fcomplex _FCmulcc(
|
||||
_Fcomplex _X,
|
||||
|
|
@ -745,8 +841,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final __FCmulccPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex, _Fcomplex)>>('_FCmulcc');
|
||||
late final __FCmulcc = __FCmulccPtr.asFunction<_Fcomplex Function(_Fcomplex, _Fcomplex)>();
|
||||
late final __FCmulccPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex, _Fcomplex)>>(
|
||||
'_FCmulcc');
|
||||
late final __FCmulcc =
|
||||
__FCmulccPtr.asFunction<_Fcomplex Function(_Fcomplex, _Fcomplex)>();
|
||||
|
||||
_Fcomplex _FCmulcr(
|
||||
_Fcomplex _X,
|
||||
|
|
@ -758,8 +857,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final __FCmulcrPtr = _lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex, ffi.Float)>>('_FCmulcr');
|
||||
late final __FCmulcr = __FCmulcrPtr.asFunction<_Fcomplex Function(_Fcomplex, double)>();
|
||||
late final __FCmulcrPtr =
|
||||
_lookup<ffi.NativeFunction<_Fcomplex Function(_Fcomplex, ffi.Float)>>(
|
||||
'_FCmulcr');
|
||||
late final __FCmulcr =
|
||||
__FCmulcrPtr.asFunction<_Fcomplex Function(_Fcomplex, double)>();
|
||||
|
||||
Start_return Start(
|
||||
ffi.Pointer<ffi.Char> mcfg,
|
||||
|
|
@ -769,8 +871,11 @@ class TorrentLibrary {
|
|||
);
|
||||
}
|
||||
|
||||
late final _StartPtr = _lookup<ffi.NativeFunction<Start_return Function(ffi.Pointer<ffi.Char>)>>('Start');
|
||||
late final _Start = _StartPtr.asFunction<Start_return Function(ffi.Pointer<ffi.Char>)>();
|
||||
late final _StartPtr =
|
||||
_lookup<ffi.NativeFunction<Start_return Function(ffi.Pointer<ffi.Char>)>>(
|
||||
'Start');
|
||||
late final _Start =
|
||||
_StartPtr.asFunction<Start_return Function(ffi.Pointer<ffi.Char>)>();
|
||||
}
|
||||
|
||||
typedef va_list = ffi.Pointer<ffi.Char>;
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ void main(List<String> args) async {
|
|||
'Failed to find an installed WebView2 runtime or non-stable Microsoft Edge installation.');
|
||||
final document = await getApplicationDocumentsDirectory();
|
||||
webViewEnvironment = await WebViewEnvironment.create(
|
||||
settings: WebViewEnvironmentSettings(userDataFolder: p.join(document.path, 'flutter_inappwebview')));
|
||||
settings: WebViewEnvironmentSettings(
|
||||
userDataFolder: p.join(document.path, 'flutter_inappwebview')));
|
||||
}
|
||||
isar = await StorageProvider().initDB(null, inspector: kDebugMode);
|
||||
await StorageProvider().requestPermission();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@ class Category {
|
|||
Id? id;
|
||||
String? name;
|
||||
bool? forManga;
|
||||
Category({this.id = Isar.autoIncrement, required this.name, required this.forManga});
|
||||
Category(
|
||||
{this.id = Isar.autoIncrement,
|
||||
required this.name,
|
||||
required this.forManga});
|
||||
|
||||
Category.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
|
|
@ -15,5 +18,6 @@ class Category {
|
|||
forManga = json['forManga'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'id': id, 'name': name, 'forManga': forManga};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'id': id, 'name': name, 'forManga': forManga};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,13 @@ class UpdatedChapter {
|
|||
bool? isRead;
|
||||
String? lastPageRead;
|
||||
bool? deleted;
|
||||
UpdatedChapter({this.chapterId, this.mangaId, this.isBookmarked, this.isRead, this.lastPageRead, this.deleted});
|
||||
UpdatedChapter(
|
||||
{this.chapterId,
|
||||
this.mangaId,
|
||||
this.isBookmarked,
|
||||
this.isRead,
|
||||
this.lastPageRead,
|
||||
this.deleted});
|
||||
UpdatedChapter.fromJson(Map<String, dynamic> json) {
|
||||
chapterId = json['chapterId'];
|
||||
mangaId = json['mangaId'];
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ class History {
|
|||
mangaId = json['mangaId'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'chapterId': chapterId, 'date': date, 'id': id, 'isManga': isManga, 'mangaId': mangaId};
|
||||
Map<String, dynamic> toJson() => {
|
||||
'chapterId': chapterId,
|
||||
'date': date,
|
||||
'id': id,
|
||||
'isManga': isManga,
|
||||
'mangaId': mangaId
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,4 +118,11 @@ class Manga {
|
|||
};
|
||||
}
|
||||
|
||||
enum Status { ongoing, completed, canceled, unknown, onHiatus, publishingFinished }
|
||||
enum Status {
|
||||
ongoing,
|
||||
completed,
|
||||
canceled,
|
||||
unknown,
|
||||
onHiatus,
|
||||
publishingFinished
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,45 +280,62 @@ class Settings {
|
|||
|
||||
Settings.fromJson(Map<String, dynamic> json) {
|
||||
animatePageTransitions = json['animatePageTransitions'];
|
||||
animeDisplayType = DisplayType.values[json['animeDisplayType'] ?? DisplayType.compactGrid.index];
|
||||
animeDisplayType = DisplayType
|
||||
.values[json['animeDisplayType'] ?? DisplayType.compactGrid.index];
|
||||
animeLibraryDownloadedChapters = json['animeLibraryDownloadedChapters'];
|
||||
animeLibraryLocalSource = json['animeLibraryLocalSource'];
|
||||
animeLibraryShowCategoryTabs = json['animeLibraryShowCategoryTabs'];
|
||||
animeLibraryShowContinueReadingButton = json['animeLibraryShowContinueReadingButton'];
|
||||
animeLibraryShowContinueReadingButton =
|
||||
json['animeLibraryShowContinueReadingButton'];
|
||||
animeLibraryShowLanguage = json['animeLibraryShowLanguage'];
|
||||
animeLibraryShowNumbersOfItems = json['animeLibraryShowNumbersOfItems'];
|
||||
autoExtensionsUpdates = json['autoExtensionsUpdates'];
|
||||
backgroundColor = BackgroundColor.values[json['backgroundColor'] ?? BackgroundColor.black.index];
|
||||
backgroundColor = BackgroundColor
|
||||
.values[json['backgroundColor'] ?? BackgroundColor.black.index];
|
||||
if (json['chapterFilterBookmarkedList'] != null) {
|
||||
chapterFilterBookmarkedList =
|
||||
(json['chapterFilterBookmarkedList'] as List).map((e) => ChapterFilterBookmarked.fromJson(e)).toList();
|
||||
(json['chapterFilterBookmarkedList'] as List)
|
||||
.map((e) => ChapterFilterBookmarked.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
if (json['chapterFilterDownloadedList'] != null) {
|
||||
chapterFilterDownloadedList =
|
||||
(json['chapterFilterDownloadedList'] as List).map((e) => ChapterFilterDownloaded.fromJson(e)).toList();
|
||||
(json['chapterFilterDownloadedList'] as List)
|
||||
.map((e) => ChapterFilterDownloaded.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
if (json['chapterFilterUnreadList'] != null) {
|
||||
chapterFilterUnreadList =
|
||||
(json['chapterFilterUnreadList'] as List).map((e) => ChapterFilterUnread.fromJson(e)).toList();
|
||||
chapterFilterUnreadList = (json['chapterFilterUnreadList'] as List)
|
||||
.map((e) => ChapterFilterUnread.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
if (json['chapterPageIndexList'] != null) {
|
||||
chapterPageIndexList = (json['chapterPageIndexList'] as List).map((e) => ChapterPageIndex.fromJson(e)).toList();
|
||||
chapterPageIndexList = (json['chapterPageIndexList'] as List)
|
||||
.map((e) => ChapterPageIndex.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
if (json['chapterPageUrlsList'] != null) {
|
||||
chapterPageUrlsList = (json['chapterPageUrlsList'] as List).map((e) => ChapterPageurls.fromJson(e)).toList();
|
||||
chapterPageUrlsList = (json['chapterPageUrlsList'] as List)
|
||||
.map((e) => ChapterPageurls.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
checkForExtensionUpdates = json['checkForExtensionUpdates'];
|
||||
if (json['cookiesList'] != null) {
|
||||
cookiesList = (json['cookiesList'] as List).map((e) => MCookie.fromJson(e)).toList();
|
||||
cookiesList = (json['cookiesList'] as List)
|
||||
.map((e) => MCookie.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
cropBorders = json['cropBorders'];
|
||||
dateFormat = json['dateFormat'];
|
||||
defaultReaderMode = ReaderMode.values[json['defaultReaderMode'] ?? ReaderMode.vertical.index];
|
||||
defaultReaderMode = ReaderMode
|
||||
.values[json['defaultReaderMode'] ?? ReaderMode.vertical.index];
|
||||
displayType = DisplayType.values[json['displayType']];
|
||||
doubleTapAnimationSpeed = json['doubleTapAnimationSpeed'];
|
||||
downloadLocation = json['downloadLocation'];
|
||||
downloadOnlyOnWifi = json['downloadOnlyOnWifi'];
|
||||
filterScanlatorList = (json['filterScanlatorList'] as List?)?.map((e) => FilterScanlator.fromJson(e)).toList();
|
||||
filterScanlatorList = (json['filterScanlatorList'] as List?)
|
||||
?.map((e) => FilterScanlator.fromJson(e))
|
||||
.toList();
|
||||
flexColorSchemeBlendLevel = json['flexColorSchemeBlendLevel'] is double
|
||||
? json['flexColorSchemeBlendLevel']
|
||||
: (json['flexColorSchemeBlendLevel'] as int).toDouble();
|
||||
|
|
@ -330,7 +347,8 @@ class Settings {
|
|||
libraryFilterAnimeDownloadType = json['libraryFilterAnimeDownloadType'];
|
||||
libraryFilterAnimeStartedType = json['libraryFilterAnimeStartedType'];
|
||||
libraryFilterAnimeUnreadType = json['libraryFilterAnimeUnreadType'];
|
||||
libraryFilterMangasBookMarkedType = json['libraryFilterMangasBookMarkedType'];
|
||||
libraryFilterMangasBookMarkedType =
|
||||
json['libraryFilterMangasBookMarkedType'];
|
||||
libraryFilterMangasDownloadType = json['libraryFilterMangasDownloadType'];
|
||||
libraryFilterMangasStartedType = json['libraryFilterMangasStartedType'];
|
||||
libraryFilterMangasUnreadType = json['libraryFilterMangasUnreadType'];
|
||||
|
|
@ -339,28 +357,41 @@ class Settings {
|
|||
libraryShowContinueReadingButton = json['libraryShowContinueReadingButton'];
|
||||
libraryShowLanguage = json['libraryShowLanguage'];
|
||||
libraryShowNumbersOfItems = json['libraryShowNumbersOfItems'];
|
||||
locale = json['locale'] != null ? L10nLocale.fromJson(json['locale']) : null;
|
||||
locale =
|
||||
json['locale'] != null ? L10nLocale.fromJson(json['locale']) : null;
|
||||
onlyIncludePinnedSources = json['onlyIncludePinnedSources'];
|
||||
pagePreloadAmount = json['pagePreloadAmount'];
|
||||
if (json['personalPageModeList'] != null) {
|
||||
personalPageModeList = (json['personalPageModeList'] as List).map((e) => PersonalPageMode.fromJson(e)).toList();
|
||||
personalPageModeList = (json['personalPageModeList'] as List)
|
||||
.map((e) => PersonalPageMode.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
if (json['personalReaderModeList'] != null) {
|
||||
personalReaderModeList =
|
||||
(json['personalReaderModeList'] as List).map((e) => PersonalReaderMode.fromJson(e)).toList();
|
||||
personalReaderModeList = (json['personalReaderModeList'] as List)
|
||||
.map((e) => PersonalReaderMode.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
pureBlackDarkMode = json['pureBlackDarkMode'];
|
||||
relativeTimesTamps = json['relativeTimesTamps'];
|
||||
saveAsCBZArchive = json['saveAsCBZArchive'];
|
||||
scaleType = ScaleType.values[json['scaleType'] ?? ScaleType.fitScreen.index];
|
||||
scaleType =
|
||||
ScaleType.values[json['scaleType'] ?? ScaleType.fitScreen.index];
|
||||
showPagesNumber = json['showPagesNumber'];
|
||||
if (json['sortChapterList'] != null) {
|
||||
sortChapterList = (json['sortChapterList'] as List).map((e) => SortChapter.fromJson(e)).toList();
|
||||
sortChapterList = (json['sortChapterList'] as List)
|
||||
.map((e) => SortChapter.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
sortLibraryAnime = json['sortLibraryAnime'] != null ? SortLibraryManga.fromJson(json['sortLibraryAnime']) : null;
|
||||
sortLibraryManga = json['sortLibraryManga'] != null ? SortLibraryManga.fromJson(json['sortLibraryManga']) : null;
|
||||
sortLibraryAnime = json['sortLibraryAnime'] != null
|
||||
? SortLibraryManga.fromJson(json['sortLibraryAnime'])
|
||||
: null;
|
||||
sortLibraryManga = json['sortLibraryManga'] != null
|
||||
? SortLibraryManga.fromJson(json['sortLibraryManga'])
|
||||
: null;
|
||||
if (json['autoScrollPages'] != null) {
|
||||
autoScrollPages = (json['autoScrollPages'] as List).map((e) => AutoScrollPages.fromJson(e)).toList();
|
||||
autoScrollPages = (json['autoScrollPages'] as List)
|
||||
.map((e) => AutoScrollPages.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
themeIsDark = json['themeIsDark'];
|
||||
userAgent = json['userAgent'];
|
||||
|
|
@ -384,17 +415,22 @@ class Settings {
|
|||
aniSkipTimeoutLength = json['aniSkipTimeoutLength'];
|
||||
btServerAddress = json['btServerAddress'];
|
||||
btServerPort = json['btServerPort'];
|
||||
customColorFilter =
|
||||
json['customColorFilter'] != null ? CustomColorFilter.fromJson(json['customColorFilter']) : null;
|
||||
customColorFilter = json['customColorFilter'] != null
|
||||
? CustomColorFilter.fromJson(json['customColorFilter'])
|
||||
: null;
|
||||
enableCustomColorFilter = json['enableCustomColorFilter'];
|
||||
colorFilterBlendMode = ColorFilterBlendMode.values[json['colorFilterBlendMode'] ?? ColorFilterBlendMode.none];
|
||||
playerSubtitleSettings =
|
||||
json['playerSubtitleSettings'] != null ? PlayerSubtitleSettings.fromJson(json['playerSubtitleSettings']) : null;
|
||||
mangaHomeDisplayType = DisplayType.values[json['mangaHomeDisplayType'] ?? DisplayType.comfortableGrid.index];
|
||||
colorFilterBlendMode = ColorFilterBlendMode
|
||||
.values[json['colorFilterBlendMode'] ?? ColorFilterBlendMode.none];
|
||||
playerSubtitleSettings = json['playerSubtitleSettings'] != null
|
||||
? PlayerSubtitleSettings.fromJson(json['playerSubtitleSettings'])
|
||||
: null;
|
||||
mangaHomeDisplayType = DisplayType.values[
|
||||
json['mangaHomeDisplayType'] ?? DisplayType.comfortableGrid.index];
|
||||
appFontFamily = json['appFontFamily'];
|
||||
mangaGridSize = json['mangaGridSize'];
|
||||
animeGridSize = json['animeGridSize'];
|
||||
disableSectionType = SectionType.values[json['disableSectionType'] ?? SectionType.all];
|
||||
disableSectionType =
|
||||
SectionType.values[json['disableSectionType'] ?? SectionType.all];
|
||||
useLibass = json['useLibass'];
|
||||
}
|
||||
|
||||
|
|
@ -404,16 +440,22 @@ class Settings {
|
|||
'animeLibraryDownloadedChapters': animeLibraryDownloadedChapters,
|
||||
'animeLibraryLocalSource': animeLibraryLocalSource,
|
||||
'animeLibraryShowCategoryTabs': animeLibraryShowCategoryTabs,
|
||||
'animeLibraryShowContinueReadingButton': animeLibraryShowContinueReadingButton,
|
||||
'animeLibraryShowContinueReadingButton':
|
||||
animeLibraryShowContinueReadingButton,
|
||||
'animeLibraryShowLanguage': animeLibraryShowLanguage,
|
||||
'animeLibraryShowNumbersOfItems': animeLibraryShowNumbersOfItems,
|
||||
'autoExtensionsUpdates': autoExtensionsUpdates,
|
||||
'backgroundColor': backgroundColor.index,
|
||||
'chapterFilterBookmarkedList': chapterFilterBookmarkedList?.map((v) => v.toJson()).toList(),
|
||||
'chapterFilterDownloadedList': chapterFilterDownloadedList?.map((v) => v.toJson()).toList(),
|
||||
'chapterFilterUnreadList': chapterFilterUnreadList?.map((v) => v.toJson()).toList(),
|
||||
'chapterPageIndexList': chapterPageIndexList?.map((v) => v.toJson()).toList(),
|
||||
'chapterPageUrlsList': chapterPageUrlsList?.map((v) => v.toJson()).toList(),
|
||||
'chapterFilterBookmarkedList':
|
||||
chapterFilterBookmarkedList?.map((v) => v.toJson()).toList(),
|
||||
'chapterFilterDownloadedList':
|
||||
chapterFilterDownloadedList?.map((v) => v.toJson()).toList(),
|
||||
'chapterFilterUnreadList':
|
||||
chapterFilterUnreadList?.map((v) => v.toJson()).toList(),
|
||||
'chapterPageIndexList':
|
||||
chapterPageIndexList?.map((v) => v.toJson()).toList(),
|
||||
'chapterPageUrlsList':
|
||||
chapterPageUrlsList?.map((v) => v.toJson()).toList(),
|
||||
'checkForExtensionUpdates': checkForExtensionUpdates,
|
||||
'cookiesList': cookiesList,
|
||||
'cropBorders': cropBorders,
|
||||
|
|
@ -445,8 +487,10 @@ class Settings {
|
|||
'locale': locale?.toJson(),
|
||||
'onlyIncludePinnedSources': onlyIncludePinnedSources,
|
||||
'pagePreloadAmount': pagePreloadAmount,
|
||||
'personalPageModeList': personalPageModeList?.map((v) => v.toJson()).toList(),
|
||||
'personalReaderModeList': personalReaderModeList?.map((v) => v.toJson()).toList(),
|
||||
'personalPageModeList':
|
||||
personalPageModeList?.map((v) => v.toJson()).toList(),
|
||||
'personalReaderModeList':
|
||||
personalReaderModeList?.map((v) => v.toJson()).toList(),
|
||||
'pureBlackDarkMode': pureBlackDarkMode,
|
||||
'relativeTimesTamps': relativeTimesTamps,
|
||||
'saveAsCBZArchive': saveAsCBZArchive,
|
||||
|
|
@ -477,10 +521,12 @@ class Settings {
|
|||
'btServerAddress': btServerAddress,
|
||||
'btServerPort': btServerPort,
|
||||
'fullScreenReader': fullScreenReader,
|
||||
if (customColorFilter != null) 'customColorFilter': customColorFilter!.toJson(),
|
||||
if (customColorFilter != null)
|
||||
'customColorFilter': customColorFilter!.toJson(),
|
||||
'enableCustomColorFilter': enableCustomColorFilter,
|
||||
'colorFilterBlendMode': colorFilterBlendMode.index,
|
||||
if (playerSubtitleSettings != null) 'playerSubtitleSettings': playerSubtitleSettings!.toJson(),
|
||||
if (playerSubtitleSettings != null)
|
||||
'playerSubtitleSettings': playerSubtitleSettings!.toJson(),
|
||||
'mangaHomeDisplayType': mangaHomeDisplayType.index,
|
||||
'appFontFamily': appFontFamily,
|
||||
'mangaGridSize': mangaGridSize,
|
||||
|
|
@ -549,7 +595,8 @@ class SortChapter {
|
|||
reverse = json['reverse'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'index': index, 'mangaId': mangaId, 'reverse': reverse};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'index': index, 'mangaId': mangaId, 'reverse': reverse};
|
||||
}
|
||||
|
||||
@embedded
|
||||
|
|
@ -604,7 +651,8 @@ class ChapterPageurls {
|
|||
urls = json['headers']?.cast<String>();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'chapterId': chapterId, 'urls': urls, 'headers': headers};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'chapterId': chapterId, 'urls': urls, 'headers': headers};
|
||||
}
|
||||
|
||||
@embedded
|
||||
|
|
@ -634,7 +682,8 @@ class PersonalReaderMode {
|
|||
readerMode = ReaderMode.values[json['readerMode']];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'mangaId': mangaId, 'readerMode': readerMode.index};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'mangaId': mangaId, 'readerMode': readerMode.index};
|
||||
}
|
||||
|
||||
@embedded
|
||||
|
|
@ -642,7 +691,8 @@ class AutoScrollPages {
|
|||
int? mangaId;
|
||||
double? pageOffset;
|
||||
bool? autoScroll;
|
||||
AutoScrollPages({this.mangaId, this.pageOffset = 10, this.autoScroll = false});
|
||||
AutoScrollPages(
|
||||
{this.mangaId, this.pageOffset = 10, this.autoScroll = false});
|
||||
|
||||
AutoScrollPages.fromJson(Map<String, dynamic> json) {
|
||||
mangaId = json['mangaId'];
|
||||
|
|
@ -650,7 +700,8 @@ class AutoScrollPages {
|
|||
autoScroll = json['autoScroll'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'mangaId': mangaId, 'pageOffset': pageOffset, 'autoScroll': autoScroll};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'mangaId': mangaId, 'pageOffset': pageOffset, 'autoScroll': autoScroll};
|
||||
}
|
||||
|
||||
@embedded
|
||||
|
|
@ -666,10 +717,18 @@ class PersonalPageMode {
|
|||
pageMode = PageMode.values[json['pageMode']];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'mangaId': mangaId, 'pageMode': pageMode.index};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'mangaId': mangaId, 'pageMode': pageMode.index};
|
||||
}
|
||||
|
||||
enum ReaderMode { vertical, ltr, rtl, verticalContinuous, webtoon, horizontalContinuous }
|
||||
enum ReaderMode {
|
||||
vertical,
|
||||
ltr,
|
||||
rtl,
|
||||
verticalContinuous,
|
||||
webtoon,
|
||||
horizontalContinuous
|
||||
}
|
||||
|
||||
enum PageMode { onePage, doublePage }
|
||||
|
||||
|
|
@ -684,7 +743,8 @@ class FilterScanlator {
|
|||
scanlators = json['scanlators']?.cast<String>();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'mangaId': mangaId, 'scanlators': scanlators};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'mangaId': mangaId, 'scanlators': scanlators};
|
||||
}
|
||||
|
||||
@embedded
|
||||
|
|
@ -698,7 +758,8 @@ class L10nLocale {
|
|||
languageCode = json['languageCode'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'countryCode': countryCode, 'languageCode': languageCode};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'countryCode': countryCode, 'languageCode': languageCode};
|
||||
}
|
||||
|
||||
@embedded
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ class Source {
|
|||
additionalParams = json['additionalParams'] ?? "";
|
||||
isObsolete = json['isObsolete'];
|
||||
isLocal = json['isLocal'];
|
||||
sourceCodeLanguage = SourceCodeLanguage.values[json['sourceCodeLanguage'] ?? 0];
|
||||
sourceCodeLanguage =
|
||||
SourceCodeLanguage.values[json['sourceCodeLanguage'] ?? 0];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
|
|
|||
|
|
@ -83,4 +83,14 @@ class Track {
|
|||
};
|
||||
}
|
||||
|
||||
enum TrackStatus { reading, completed, onHold, dropped, planToRead, rereading, watching, planToWatch, reWatching }
|
||||
enum TrackStatus {
|
||||
reading,
|
||||
completed,
|
||||
onHold,
|
||||
dropped,
|
||||
planToRead,
|
||||
rereading,
|
||||
watching,
|
||||
planToWatch,
|
||||
reWatching
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,5 +26,6 @@ class TrackPreference {
|
|||
prefs = json['prefs'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {'syncId': syncId, 'username': username, 'oAuth': oAuth, 'prefs': prefs};
|
||||
Map<String, dynamic> toJson() =>
|
||||
{'syncId': syncId, 'username': username, 'oAuth': oAuth, 'prefs': prefs};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,13 +8,20 @@ class Video {
|
|||
List<Track>? subtitles;
|
||||
List<Track>? audios;
|
||||
|
||||
Video(this.url, this.quality, this.originalUrl, {this.headers, this.subtitles, this.audios});
|
||||
Video(this.url, this.quality, this.originalUrl,
|
||||
{this.headers, this.subtitles, this.audios});
|
||||
factory Video.fromJson(Map<String, dynamic> json) {
|
||||
return Video(
|
||||
json['url'].toString().trim(), json['quality'].toString().trim(), json['originalUrl'].toString().trim(),
|
||||
json['url'].toString().trim(),
|
||||
json['quality'].toString().trim(),
|
||||
json['originalUrl'].toString().trim(),
|
||||
headers: (json['headers'] as Map?)?.toMapStringString,
|
||||
subtitles: json['subtitles'] != null ? (json['subtitles'] as List).map((e) => Track.fromJson(e)).toList() : [],
|
||||
audios: json['audios'] != null ? (json['audios'] as List).map((e) => Track.fromJson(e)).toList() : []);
|
||||
subtitles: json['subtitles'] != null
|
||||
? (json['subtitles'] as List).map((e) => Track.fromJson(e)).toList()
|
||||
: [],
|
||||
audios: json['audios'] != null
|
||||
? (json['audios'] as List).map((e) => Track.fromJson(e)).toList()
|
||||
: []);
|
||||
}
|
||||
Map<String, dynamic> toJson() => {
|
||||
'url': url,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
|
|||
for (var infoHash in _infoHashList) {
|
||||
MTorrentServer().removeTorrent(infoHash);
|
||||
}
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||
overlays: SystemUiOverlay.values);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -64,13 +65,15 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final serversData = ref.watch(getVideoListProvider(episode: widget.episode));
|
||||
final serversData =
|
||||
ref.watch(getVideoListProvider(episode: widget.episode));
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
|
||||
return serversData.when(
|
||||
data: (data) {
|
||||
final (videos, isLocal, infoHashList) = data;
|
||||
_infoHashList = infoHashList;
|
||||
if (videos.isEmpty && !(widget.episode.manga.value!.isLocalArchive ?? false)) {
|
||||
if (videos.isEmpty &&
|
||||
!(widget.episode.manga.value!.isLocalArchive ?? false)) {
|
||||
return Scaffold(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
appBar: AppBar(
|
||||
|
|
@ -102,7 +105,8 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
|
|||
title: const Text(''),
|
||||
leading: BackButton(
|
||||
onPressed: () {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||
overlays: SystemUiOverlay.values);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
|
|
@ -120,7 +124,8 @@ class _AnimePlayerViewState extends riv.ConsumerState<AnimePlayerView> {
|
|||
leading: BackButton(
|
||||
color: Colors.white,
|
||||
onPressed: () {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||
overlays: SystemUiOverlay.values);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
|
|
@ -150,18 +155,24 @@ class AnimeStreamPage extends riv.ConsumerStatefulWidget {
|
|||
riv.ConsumerState<AnimeStreamPage> createState() => _AnimeStreamPageState();
|
||||
}
|
||||
|
||||
class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with TickerProviderStateMixin {
|
||||
class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
||||
with TickerProviderStateMixin {
|
||||
late final GlobalKey<VideoState> _key = GlobalKey<VideoState>();
|
||||
late final useLibass = ref.read(useLibassStateProvider);
|
||||
late final Player _player = Player(configuration: PlayerConfiguration(libass: useLibass));
|
||||
late final Player _player =
|
||||
Player(configuration: PlayerConfiguration(libass: useLibass));
|
||||
late final VideoController _controller = VideoController(_player);
|
||||
late final _streamController = ref.read(animeStreamControllerProvider(episode: widget.episode).notifier);
|
||||
late final _streamController =
|
||||
ref.read(animeStreamControllerProvider(episode: widget.episode).notifier);
|
||||
late final _firstVid = widget.videos.first;
|
||||
late final ValueNotifier<VideoPrefs?> _video = ValueNotifier(VideoPrefs(
|
||||
videoTrack: VideoTrack(_firstVid.originalUrl, _firstVid.quality, _firstVid.quality), headers: _firstVid.headers));
|
||||
videoTrack: VideoTrack(
|
||||
_firstVid.originalUrl, _firstVid.quality, _firstVid.quality),
|
||||
headers: _firstVid.headers));
|
||||
final ValueNotifier<double> _playbackSpeed = ValueNotifier(1.0);
|
||||
final ValueNotifier<bool> _enterFullScreen = ValueNotifier(false);
|
||||
late final ValueNotifier<Duration> _currentPosition = ValueNotifier(_streamController.geTCurrentPosition());
|
||||
late final ValueNotifier<Duration> _currentPosition =
|
||||
ValueNotifier(_streamController.geTCurrentPosition());
|
||||
final ValueNotifier<Duration?> _currentTotalDuration = ValueNotifier(null);
|
||||
final ValueNotifier<bool> _showFitLabel = ValueNotifier(false);
|
||||
final ValueNotifier<bool> _isCompleted = ValueNotifier(false);
|
||||
|
|
@ -175,9 +186,12 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
bool _hasEndingSkip = false;
|
||||
bool _initSubtitleAndAudio = true;
|
||||
|
||||
late final StreamSubscription<Duration> _currentPositionSub = _player.stream.position.listen(
|
||||
late final StreamSubscription<Duration> _currentPositionSub =
|
||||
_player.stream.position.listen(
|
||||
(position) async {
|
||||
_isCompleted.value = _player.state.duration.inSeconds - _currentPosition.value.inSeconds <= 10;
|
||||
_isCompleted.value =
|
||||
_player.state.duration.inSeconds - _currentPosition.value.inSeconds <=
|
||||
10;
|
||||
_currentPosition.value = position;
|
||||
|
||||
if (_firstVid.subtitles?.isNotEmpty ?? false) {
|
||||
|
|
@ -191,8 +205,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
} catch (_) {}
|
||||
try {
|
||||
if (_firstVid.audios?.isNotEmpty ?? false) {
|
||||
_player.setAudioTrack(AudioTrack.uri(_firstVid.audios!.first.file ?? "",
|
||||
title: _firstVid.audios!.first.label, language: _firstVid.audios!.first.label));
|
||||
_player.setAudioTrack(AudioTrack.uri(
|
||||
_firstVid.audios!.first.file ?? "",
|
||||
title: _firstVid.audios!.first.label,
|
||||
language: _firstVid.audios!.first.label));
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
|
|
@ -201,13 +217,15 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
},
|
||||
);
|
||||
|
||||
late final StreamSubscription<Duration> _currentTotalDurationSub = _player.stream.duration.listen(
|
||||
late final StreamSubscription<Duration> _currentTotalDurationSub =
|
||||
_player.stream.duration.listen(
|
||||
(duration) {
|
||||
_currentTotalDuration.value = duration;
|
||||
},
|
||||
);
|
||||
|
||||
late final StreamSubscription<bool> _completed = _player.stream.completed.listen((val) {
|
||||
late final StreamSubscription<bool> _completed =
|
||||
_player.stream.completed.listen((val) {
|
||||
if (_streamController.getEpisodeIndex().$1 != 0 && val == true) {
|
||||
if (mounted) {
|
||||
pushToNewEpisode(context, _streamController.getNextEpisode());
|
||||
|
|
@ -231,12 +249,14 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
_loadAndroidFont().then(
|
||||
(_) {
|
||||
_player.open(Media(_video.value!.videoTrack!.id,
|
||||
httpHeaders: _video.value!.headers, start: _streamController.geTCurrentPosition()));
|
||||
httpHeaders: _video.value!.headers,
|
||||
start: _streamController.geTCurrentPosition()));
|
||||
if (widget.isTorrent) {
|
||||
Future.delayed(const Duration(seconds: 10)).then((_) {
|
||||
if (mounted) {
|
||||
_player.open(Media(_video.value!.videoTrack!.id,
|
||||
httpHeaders: _video.value!.headers, start: _streamController.geTCurrentPosition()));
|
||||
httpHeaders: _video.value!.headers,
|
||||
start: _streamController.geTCurrentPosition()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -253,11 +273,14 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
final subDir = await getApplicationDocumentsDirectory();
|
||||
final fontPath = path.join(subDir.path, 'subfont.ttf');
|
||||
final data = await rootBundle.load('assets/fonts/subfont.ttf');
|
||||
final bytes = data.buffer.asInt8List(data.offsetInBytes, data.lengthInBytes);
|
||||
final bytes =
|
||||
data.buffer.asInt8List(data.offsetInBytes, data.lengthInBytes);
|
||||
final fontFile = await File(fontPath).create(recursive: true);
|
||||
await fontFile.writeAsBytes(bytes);
|
||||
await (_player.platform as NativePlayer).setProperty('sub-fonts-dir', subDir.path);
|
||||
await (_player.platform as NativePlayer).setProperty('sub-font', 'Droid Sans Fallback');
|
||||
await (_player.platform as NativePlayer)
|
||||
.setProperty('sub-fonts-dir', subDir.path);
|
||||
await (_player.platform as NativePlayer)
|
||||
.setProperty('sub-font', 'Droid Sans Fallback');
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -265,12 +288,14 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
void _initAniSkip() async {
|
||||
await _player.stream.buffer.first;
|
||||
_streamController.getAniSkipResults((result) {
|
||||
final openingRes = result.where((element) => element.skipType == "op").toList();
|
||||
final openingRes =
|
||||
result.where((element) => element.skipType == "op").toList();
|
||||
_hasOpeningSkip = openingRes.isNotEmpty;
|
||||
if (_hasOpeningSkip) {
|
||||
_openingResult = openingRes.first;
|
||||
}
|
||||
final endingRes = result.where((element) => element.skipType == "ed").toList();
|
||||
final endingRes =
|
||||
result.where((element) => element.skipType == "ed").toList();
|
||||
_hasEndingSkip = endingRes.isNotEmpty;
|
||||
if (_hasEndingSkip) {
|
||||
_endingResult = endingRes.first;
|
||||
|
|
@ -295,14 +320,17 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
}
|
||||
|
||||
void _setCurrentPosition(bool save) {
|
||||
_streamController.setCurrentPosition(_currentPosition.value, _currentTotalDuration.value, save: save);
|
||||
_streamController.setCurrentPosition(
|
||||
_currentPosition.value, _currentTotalDuration.value,
|
||||
save: save);
|
||||
_streamController.setAnimeHistoryUpdate();
|
||||
_streamController.checkAndSyncProgress();
|
||||
}
|
||||
|
||||
void _setLandscapeMode(bool state) {
|
||||
if (state) {
|
||||
SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
|
||||
SystemChrome.setPreferredOrientations(
|
||||
[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]);
|
||||
} else {
|
||||
SystemChrome.setPreferredOrientations([
|
||||
DeviceOrientation.portraitUp,
|
||||
|
|
@ -317,7 +345,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
children: [
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: MediaQuery.of(context).padding.top),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: MediaQuery.of(context).padding.top),
|
||||
child: Text(text,
|
||||
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
|
||||
fontSize: 16,
|
||||
|
|
@ -331,7 +360,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
|
||||
Widget _videoQualityWidget(BuildContext context) {
|
||||
List<VideoPrefs> videoQuality = _player.state.tracks.video
|
||||
.where((element) => element.w != null && element.h != null && widget.isLocal)
|
||||
.where((element) =>
|
||||
element.w != null && element.h != null && widget.isLocal)
|
||||
.toList()
|
||||
.map((e) => VideoPrefs(videoTrack: e, isLocal: true))
|
||||
.toList();
|
||||
|
|
@ -339,7 +369,9 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
if (widget.videos.isNotEmpty && !widget.isLocal) {
|
||||
for (var video in widget.videos) {
|
||||
videoQuality.add(VideoPrefs(
|
||||
videoTrack: VideoTrack(video.url, video.quality, video.quality), headers: video.headers, isLocal: false));
|
||||
videoTrack: VideoTrack(video.url, video.quality, video.quality),
|
||||
headers: video.headers,
|
||||
isLocal: false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -347,21 +379,27 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 12),
|
||||
child: Column(
|
||||
children: videoQuality.map((quality) {
|
||||
final selected = _video.value!.videoTrack!.title == quality.videoTrack!.title || widget.isLocal;
|
||||
final selected =
|
||||
_video.value!.videoTrack!.title == quality.videoTrack!.title ||
|
||||
widget.isLocal;
|
||||
return GestureDetector(
|
||||
child: textWidget(widget.isLocal ? _firstVid.quality : quality.videoTrack!.title!, selected),
|
||||
child: textWidget(
|
||||
widget.isLocal ? _firstVid.quality : quality.videoTrack!.title!,
|
||||
selected),
|
||||
onTap: () async {
|
||||
_video.value = quality;
|
||||
if (quality.isLocal) {
|
||||
if (widget.isLocal) {
|
||||
_player.setVideoTrack(quality.videoTrack!);
|
||||
} else {
|
||||
_player
|
||||
.open(Media(quality.videoTrack!.id, httpHeaders: quality.headers, start: _currentPosition.value));
|
||||
_player.open(Media(quality.videoTrack!.id,
|
||||
httpHeaders: quality.headers,
|
||||
start: _currentPosition.value));
|
||||
}
|
||||
} else {
|
||||
_player
|
||||
.open(Media(quality.videoTrack!.id, httpHeaders: quality.headers, start: _currentPosition.value));
|
||||
_player.open(Media(quality.videoTrack!.id,
|
||||
httpHeaders: quality.headers,
|
||||
start: _currentPosition.value));
|
||||
}
|
||||
Navigator.pop(context);
|
||||
},
|
||||
|
|
@ -419,8 +457,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
}
|
||||
|
||||
Widget _videoSubtitle(BuildContext context, Function(bool) hasSubtitleTrack) {
|
||||
List<VideoPrefs> videoSubtitle =
|
||||
_player.state.tracks.subtitle.toList().map((e) => VideoPrefs(isLocal: true, subtitle: e)).toList();
|
||||
List<VideoPrefs> videoSubtitle = _player.state.tracks.subtitle
|
||||
.toList()
|
||||
.map((e) => VideoPrefs(isLocal: true, subtitle: e))
|
||||
.toList();
|
||||
|
||||
List<String> subs = [];
|
||||
if (widget.videos.isNotEmpty && !widget.isLocal) {
|
||||
|
|
@ -443,7 +483,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
videoSubtitle = videoSubtitle
|
||||
.map((e) {
|
||||
VideoPrefs vid = e;
|
||||
vid.title = vid.subtitle?.title ?? vid.subtitle?.language ?? vid.subtitle?.channels ?? "";
|
||||
vid.title = vid.subtitle?.title ??
|
||||
vid.subtitle?.language ??
|
||||
vid.subtitle?.channels ??
|
||||
"";
|
||||
return vid;
|
||||
})
|
||||
.toList()
|
||||
|
|
@ -451,11 +494,16 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
.toList();
|
||||
videoSubtitle.sort((a, b) => a.title!.compareTo(b.title!));
|
||||
hasSubtitleTrack.call(videoSubtitle.isNotEmpty);
|
||||
videoSubtitle.insert(0, VideoPrefs(isLocal: false, subtitle: SubtitleTrack.no()));
|
||||
videoSubtitle.insert(
|
||||
0, VideoPrefs(isLocal: false, subtitle: SubtitleTrack.no()));
|
||||
List<VideoPrefs> videoSubtitleLast = [];
|
||||
for (var element in videoSubtitle) {
|
||||
final contains = videoSubtitleLast.any((sub) {
|
||||
return (sub.title ?? sub.subtitle?.title ?? sub.subtitle?.language ?? sub.subtitle?.channels ?? "None") ==
|
||||
return (sub.title ??
|
||||
sub.subtitle?.title ??
|
||||
sub.subtitle?.language ??
|
||||
sub.subtitle?.channels ??
|
||||
"None") ==
|
||||
(element.title ??
|
||||
element.subtitle?.title ??
|
||||
element.subtitle?.language ??
|
||||
|
|
@ -470,9 +518,17 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 12),
|
||||
child: Column(
|
||||
children: videoSubtitleLast.toSet().toList().map((sub) {
|
||||
final title = sub.title ?? sub.subtitle?.title ?? sub.subtitle?.language ?? sub.subtitle?.channels ?? "None";
|
||||
final title = sub.title ??
|
||||
sub.subtitle?.title ??
|
||||
sub.subtitle?.language ??
|
||||
sub.subtitle?.channels ??
|
||||
"None";
|
||||
|
||||
final selected = (title == (subtitle.title ?? subtitle.language ?? subtitle.channels ?? "None")) ||
|
||||
final selected = (title ==
|
||||
(subtitle.title ??
|
||||
subtitle.language ??
|
||||
subtitle.channels ??
|
||||
"None")) ||
|
||||
(subtitle.id == "no" && title == "None");
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
|
|
@ -489,8 +545,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
}
|
||||
|
||||
Widget _videoAudios(BuildContext context) {
|
||||
List<VideoPrefs> videoAudio =
|
||||
_player.state.tracks.audio.toList().map((e) => VideoPrefs(isLocal: true, audio: e)).toList();
|
||||
List<VideoPrefs> videoAudio = _player.state.tracks.audio
|
||||
.toList()
|
||||
.map((e) => VideoPrefs(isLocal: true, audio: e))
|
||||
.toList();
|
||||
|
||||
List<String> audios = [];
|
||||
if (widget.videos.isNotEmpty && !widget.isLocal) {
|
||||
|
|
@ -498,7 +556,9 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
for (var audio in video.audios ?? []) {
|
||||
if (!audios.contains(audio.file)) {
|
||||
videoAudio.add(VideoPrefs(
|
||||
isLocal: false, audio: AudioTrack.uri(audio.file!, title: audio.label, language: audio.label)));
|
||||
isLocal: false,
|
||||
audio: AudioTrack.uri(audio.file!,
|
||||
title: audio.label, language: audio.label)));
|
||||
audios.add(audio.file!);
|
||||
}
|
||||
}
|
||||
|
|
@ -508,7 +568,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
videoAudio = videoAudio
|
||||
.map((e) {
|
||||
VideoPrefs vid = e;
|
||||
vid.title = vid.audio?.title ?? vid.audio?.language ?? vid.audio?.channels ?? "";
|
||||
vid.title = vid.audio?.title ??
|
||||
vid.audio?.language ??
|
||||
vid.audio?.channels ??
|
||||
"";
|
||||
return vid;
|
||||
})
|
||||
.toList()
|
||||
|
|
@ -520,8 +583,13 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
padding: const EdgeInsets.symmetric(vertical: 15, horizontal: 12),
|
||||
child: Column(
|
||||
children: videoAudio.toSet().toList().map((aud) {
|
||||
final title = aud.title ?? aud.audio?.title ?? aud.audio?.language ?? aud.audio?.channels ?? "None";
|
||||
final selected = (aud.audio == audio) || (audio.id == "no" && title == "None");
|
||||
final title = aud.title ??
|
||||
aud.audio?.title ??
|
||||
aud.audio?.language ??
|
||||
aud.audio?.channels ??
|
||||
"None";
|
||||
final selected =
|
||||
(aud.audio == audio) || (audio.id == "no" && title == "None");
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
|
|
@ -542,8 +610,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
|
||||
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) {
|
||||
_setPlaybackSpeed(allowedSpeeds[allowedSpeeds.indexOf(_playbackSpeed.value) + 1]);
|
||||
if (allowedSpeeds.indexOf(_playbackSpeed.value) <
|
||||
allowedSpeeds.length - 1) {
|
||||
_setPlaybackSpeed(
|
||||
allowedSpeeds[allowedSpeeds.indexOf(_playbackSpeed.value) + 1]);
|
||||
} else {
|
||||
_setPlaybackSpeed(allowedSpeeds[0]);
|
||||
}
|
||||
|
|
@ -576,20 +646,26 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
}
|
||||
|
||||
Widget _seekToWidget() {
|
||||
final defaultSkipIntroLength = ref.watch(defaultSkipIntroLengthStateProvider);
|
||||
final defaultSkipIntroLength =
|
||||
ref.watch(defaultSkipIntroLengthStateProvider);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
child: SizedBox(
|
||||
height: 35,
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
_tempPosition.value = Duration(seconds: defaultSkipIntroLength + _currentPosition.value.inSeconds);
|
||||
await _player.seek(Duration(seconds: _currentPosition.value.inSeconds + defaultSkipIntroLength));
|
||||
_tempPosition.value = Duration(
|
||||
seconds: defaultSkipIntroLength +
|
||||
_currentPosition.value.inSeconds);
|
||||
await _player.seek(Duration(
|
||||
seconds: _currentPosition.value.inSeconds +
|
||||
defaultSkipIntroLength));
|
||||
_tempPosition.value = null;
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text("+$defaultSkipIntroLength", style: const TextStyle(fontWeight: FontWeight.w100)),
|
||||
child: Text("+$defaultSkipIntroLength",
|
||||
style: const TextStyle(fontWeight: FontWeight.w100)),
|
||||
)),
|
||||
),
|
||||
);
|
||||
|
|
@ -631,7 +707,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
_togglePlaybackSpeed();
|
||||
}),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.fit_screen_outlined, color: Colors.white),
|
||||
icon: const Icon(Icons.fit_screen_outlined,
|
||||
color: Colors.white),
|
||||
onPressed: () async {
|
||||
_changeFitLabel(ref);
|
||||
},
|
||||
|
|
@ -644,7 +721,9 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
_setLandscapeMode(!snapshot);
|
||||
_enterFullScreen.value = !snapshot;
|
||||
},
|
||||
icon: Icon(snapshot ? Icons.fullscreen_exit : Icons.fullscreen),
|
||||
icon: Icon(snapshot
|
||||
? Icons.fullscreen_exit
|
||||
: Icons.fullscreen),
|
||||
iconSize: 25,
|
||||
color: Colors.white,
|
||||
);
|
||||
|
|
@ -661,7 +740,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
|
||||
Widget _desktopBottomButtonBar(BuildContext context) {
|
||||
bool hasPrevEpisode = _streamController.getEpisodeIndex().$1 + 1 !=
|
||||
_streamController.getEpisodesLength(_streamController.getEpisodeIndex().$2);
|
||||
_streamController
|
||||
.getEpisodesLength(_streamController.getEpisodeIndex().$2);
|
||||
bool hasNextEpisode = _streamController.getEpisodeIndex().$1 != 0;
|
||||
final skipDuration = ref.watch(defaultDoubleTapToSkipLengthStateProvider);
|
||||
return Column(
|
||||
|
|
@ -675,7 +755,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
if (hasPrevEpisode)
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
pushToNewEpisode(context, _streamController.getPrevEpisode());
|
||||
pushToNewEpisode(
|
||||
context, _streamController.getPrevEpisode());
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.skip_previous,
|
||||
|
|
@ -688,7 +769,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
if (hasNextEpisode)
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
pushToNewEpisode(context, _streamController.getNextEpisode());
|
||||
pushToNewEpisode(
|
||||
context, _streamController.getNextEpisode());
|
||||
},
|
||||
icon: const Icon(Icons.skip_next, color: Colors.white),
|
||||
),
|
||||
|
|
@ -697,8 +779,12 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
width: 50,
|
||||
child: IconButton(
|
||||
onPressed: () async {
|
||||
_tempPosition.value = Duration(seconds: skipDuration - _currentPosition.value.inSeconds);
|
||||
await _player.seek(Duration(seconds: _currentPosition.value.inSeconds - skipDuration));
|
||||
_tempPosition.value = Duration(
|
||||
seconds:
|
||||
skipDuration - _currentPosition.value.inSeconds);
|
||||
await _player.seek(Duration(
|
||||
seconds:
|
||||
_currentPosition.value.inSeconds - skipDuration));
|
||||
_tempPosition.value = null;
|
||||
},
|
||||
icon: Stack(
|
||||
|
|
@ -716,7 +802,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
padding: const EdgeInsets.only(top: 2),
|
||||
child: Text(
|
||||
skipDuration.toString(),
|
||||
style: const TextStyle(fontSize: 9, color: Colors.white),
|
||||
style: const TextStyle(
|
||||
fontSize: 9, color: Colors.white),
|
||||
),
|
||||
)),
|
||||
),
|
||||
|
|
@ -729,8 +816,12 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
width: 50,
|
||||
child: IconButton(
|
||||
onPressed: () async {
|
||||
_tempPosition.value = Duration(seconds: skipDuration + _currentPosition.value.inSeconds);
|
||||
await _player.seek(Duration(seconds: _currentPosition.value.inSeconds + skipDuration));
|
||||
_tempPosition.value = Duration(
|
||||
seconds:
|
||||
skipDuration + _currentPosition.value.inSeconds);
|
||||
await _player.seek(Duration(
|
||||
seconds:
|
||||
_currentPosition.value.inSeconds + skipDuration));
|
||||
_tempPosition.value = null;
|
||||
},
|
||||
icon: Stack(
|
||||
|
|
@ -748,7 +839,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
padding: const EdgeInsets.only(top: 2),
|
||||
child: Text(
|
||||
skipDuration.toString(),
|
||||
style: const TextStyle(fontSize: 9, color: Colors.white),
|
||||
style: const TextStyle(
|
||||
fontSize: 9, color: Colors.white),
|
||||
),
|
||||
)),
|
||||
),
|
||||
|
|
@ -762,7 +854,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
ValueListenableBuilder(
|
||||
valueListenable: _tempPosition,
|
||||
builder: (context, value, child) =>
|
||||
CustomMaterialDesktopPositionIndicator(delta: value, controller: _controller),
|
||||
CustomMaterialDesktopPositionIndicator(
|
||||
delta: value, controller: _controller),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -789,7 +882,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
_togglePlaybackSpeed();
|
||||
}),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.fit_screen_outlined, color: Colors.white),
|
||||
icon: const Icon(Icons.fit_screen_outlined,
|
||||
color: Colors.white),
|
||||
onPressed: () async {
|
||||
_changeFitLabel(ref);
|
||||
},
|
||||
|
|
@ -810,7 +904,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
valueListenable: _enterFullScreen,
|
||||
builder: (context, fullScreen, _) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: !_isDesktop && !fullScreen ? MediaQuery.of(context).padding.top : 0),
|
||||
padding: EdgeInsets.only(
|
||||
top: !_isDesktop && !fullScreen
|
||||
? MediaQuery.of(context).padding.top
|
||||
: 0),
|
||||
child: Row(
|
||||
children: [
|
||||
BackButton(
|
||||
|
|
@ -825,7 +922,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
}
|
||||
}
|
||||
} else {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: SystemUiOverlay.values);
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
|
||||
overlays: SystemUiOverlay.values);
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
|
@ -839,7 +937,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
width: context.width(0.8),
|
||||
child: Text(
|
||||
widget.episode.manga.value!.name!,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, color: Colors.white),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
|
|
@ -848,7 +947,9 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
child: Text(
|
||||
widget.episode.name!,
|
||||
style: TextStyle(
|
||||
fontSize: 12, fontWeight: FontWeight.w400, color: Colors.white.withValues(alpha: 0.7)),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.white.withValues(alpha: 0.7)),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
|
|
@ -924,7 +1025,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
void _resize(BoxFit fit) async {
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
if (mounted) {
|
||||
_key.currentState?.update(fit: fit, width: context.width(1), height: context.height(1));
|
||||
_key.currentState?.update(
|
||||
fit: fit, width: context.width(1), height: context.height(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -934,7 +1036,8 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
return Stack(
|
||||
children: [
|
||||
Video(
|
||||
subtitleViewConfiguration: SubtitleViewConfiguration(visible: false, style: subtileTextStyle(ref)),
|
||||
subtitleViewConfiguration: SubtitleViewConfiguration(
|
||||
visible: false, style: subtileTextStyle(ref)),
|
||||
fit: fit,
|
||||
key: _key,
|
||||
controls: (state) => _isDesktop
|
||||
|
|
@ -976,8 +1079,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
builder: (context, value, child) {
|
||||
if (_hasOpeningSkip || _hasEndingSkip) {
|
||||
if (_hasOpeningSkip) {
|
||||
if (_openingResult!.interval!.startTime!.ceil() <= value.inSeconds &&
|
||||
_openingResult!.interval!.endTime!.toInt() > value.inSeconds) {
|
||||
if (_openingResult!.interval!.startTime!.ceil() <=
|
||||
value.inSeconds &&
|
||||
_openingResult!.interval!.endTime!.toInt() >
|
||||
value.inSeconds) {
|
||||
_showAniSkipOpeningButton.value = true;
|
||||
_showAniSkipEndingButton.value = false;
|
||||
} else {
|
||||
|
|
@ -985,8 +1090,10 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
}
|
||||
}
|
||||
if (_hasEndingSkip) {
|
||||
if (_endingResult!.interval!.startTime!.ceil() <= value.inSeconds &&
|
||||
_endingResult!.interval!.endTime!.toInt() > value.inSeconds) {
|
||||
if (_endingResult!.interval!.startTime!.ceil() <=
|
||||
value.inSeconds &&
|
||||
_endingResult!.interval!.endTime!.toInt() >
|
||||
value.inSeconds) {
|
||||
_showAniSkipEndingButton.value = true;
|
||||
_showAniSkipOpeningButton.value = false;
|
||||
}
|
||||
|
|
@ -995,9 +1102,12 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> with Tick
|
|||
}
|
||||
}
|
||||
return Consumer(builder: (context, ref, _) {
|
||||
late final enableAniSkip = ref.watch(enableAniSkipStateProvider);
|
||||
late final enableAutoSkip = ref.watch(enableAutoSkipStateProvider);
|
||||
late final aniSkipTimeoutLength = ref.watch(aniSkipTimeoutLengthStateProvider);
|
||||
late final enableAniSkip =
|
||||
ref.watch(enableAniSkipStateProvider);
|
||||
late final enableAutoSkip =
|
||||
ref.watch(enableAutoSkipStateProvider);
|
||||
late final aniSkipTimeoutLength =
|
||||
ref.watch(aniSkipTimeoutLengthStateProvider);
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: _showAniSkipOpeningButton,
|
||||
builder: (context, showAniSkipOpENINGButton, child) {
|
||||
|
|
@ -1055,11 +1165,13 @@ Widget seekIndicatorTextWidget(Duration duration, Duration currentPosition) {
|
|||
children: [
|
||||
Text(
|
||||
Duration(seconds: value).label(),
|
||||
style: const TextStyle(fontSize: 65.0, fontWeight: FontWeight.bold, color: Colors.white),
|
||||
style: const TextStyle(
|
||||
fontSize: 65.0, fontWeight: FontWeight.bold, color: Colors.white),
|
||||
),
|
||||
Text(
|
||||
"[${swipeDuration > 0 ? "+${Duration(seconds: swipeDuration).label()}" : "-${Duration(seconds: swipeDuration).label()}"}]",
|
||||
style: const TextStyle(fontSize: 40.0, color: Colors.white, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontSize: 40.0, color: Colors.white, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
@ -1072,5 +1184,11 @@ class VideoPrefs {
|
|||
AudioTrack? audio;
|
||||
bool isLocal;
|
||||
final Map<String, String>? headers;
|
||||
VideoPrefs({this.videoTrack, this.isLocal = true, this.headers, this.subtitle, this.audio, this.title});
|
||||
VideoPrefs(
|
||||
{this.videoTrack,
|
||||
this.isLocal = true,
|
||||
this.headers,
|
||||
this.subtitle,
|
||||
this.audio,
|
||||
this.title});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,13 +104,17 @@ class AnimeStreamController extends _$AnimeStreamController {
|
|||
}
|
||||
|
||||
int getEpisodesLength(bool isInFilterList) {
|
||||
return isInFilterList ? getAnime().getFilteredChapterList().length : getAnime().chapters.length;
|
||||
return isInFilterList
|
||||
? getAnime().getFilteredChapterList().length
|
||||
: getAnime().chapters.length;
|
||||
}
|
||||
|
||||
Duration geTCurrentPosition() {
|
||||
if (incognitoMode) return Duration.zero;
|
||||
String position = episode.lastPageRead ?? "0";
|
||||
return Duration(milliseconds: episode.isRead! ? 0 : int.parse(position.isEmpty ? "0" : position));
|
||||
return Duration(
|
||||
milliseconds:
|
||||
episode.isRead! ? 0 : int.parse(position.isEmpty ? "0" : position));
|
||||
}
|
||||
|
||||
void setAnimeHistoryUpdate() {
|
||||
|
|
@ -122,7 +126,8 @@ class AnimeStreamController extends _$AnimeStreamController {
|
|||
});
|
||||
History? history;
|
||||
|
||||
final empty = isar.historys.filter().mangaIdEqualTo(getAnime().id).isEmptySync();
|
||||
final empty =
|
||||
isar.historys.filter().mangaIdEqualTo(getAnime().id).isEmptySync();
|
||||
|
||||
if (empty) {
|
||||
history = History(
|
||||
|
|
@ -132,7 +137,10 @@ class AnimeStreamController extends _$AnimeStreamController {
|
|||
chapterId: episode.id)
|
||||
..chapter.value = episode;
|
||||
} else {
|
||||
history = (isar.historys.filter().mangaIdEqualTo(getAnime().id).findFirstSync())!
|
||||
history = (isar.historys
|
||||
.filter()
|
||||
.mangaIdEqualTo(getAnime().id)
|
||||
.findFirstSync())!
|
||||
..chapterId = episode.id
|
||||
..chapter.value = episode
|
||||
..date = DateTime.now().millisecondsSinceEpoch.toString();
|
||||
|
|
@ -150,19 +158,25 @@ class AnimeStreamController extends _$AnimeStreamController {
|
|||
}
|
||||
}
|
||||
|
||||
void setCurrentPosition(Duration duration, Duration? totalDuration, {bool save = false}) {
|
||||
void setCurrentPosition(Duration duration, Duration? totalDuration,
|
||||
{bool save = false}) {
|
||||
if (episode.isRead!) return;
|
||||
if (incognitoMode) return;
|
||||
final markEpisodeAsSeenType = ref.watch(markEpisodeAsSeenTypeStateProvider);
|
||||
final isWatch = totalDuration != null && totalDuration != Duration.zero && duration != Duration.zero
|
||||
? duration.inSeconds >= ((totalDuration.inSeconds * markEpisodeAsSeenType) / 100).ceil()
|
||||
final isWatch = totalDuration != null &&
|
||||
totalDuration != Duration.zero &&
|
||||
duration != Duration.zero
|
||||
? duration.inSeconds >=
|
||||
((totalDuration.inSeconds * markEpisodeAsSeenType) / 100).ceil()
|
||||
: false;
|
||||
if (isWatch || save) {
|
||||
final ep = episode;
|
||||
isar.writeTxnSync(() {
|
||||
ep.isRead = isWatch;
|
||||
ep.lastPageRead = (duration.inMilliseconds).toString();
|
||||
ref.read(changedItemsManagerProvider(managerId: 1).notifier).addUpdatedChapter(ep, false, false);
|
||||
ref
|
||||
.read(changedItemsManagerProvider(managerId: 1).notifier)
|
||||
.addUpdatedChapter(ep, false, false);
|
||||
isar.chapters.putSync(ep);
|
||||
});
|
||||
if (isWatch) {
|
||||
|
|
@ -172,10 +186,18 @@ class AnimeStreamController extends _$AnimeStreamController {
|
|||
}
|
||||
|
||||
(int, int)? _getTrackId() {
|
||||
final malId =
|
||||
isar.tracks.filter().syncIdEqualTo(1).mangaIdEqualTo(episode.manga.value!.id!).findFirstSync()?.mediaId;
|
||||
final aniId =
|
||||
isar.tracks.filter().syncIdEqualTo(2).mangaIdEqualTo(episode.manga.value!.id!).findFirstSync()?.mediaId;
|
||||
final malId = isar.tracks
|
||||
.filter()
|
||||
.syncIdEqualTo(1)
|
||||
.mangaIdEqualTo(episode.manga.value!.id!)
|
||||
.findFirstSync()
|
||||
?.mediaId;
|
||||
final aniId = isar.tracks
|
||||
.filter()
|
||||
.syncIdEqualTo(2)
|
||||
.mangaIdEqualTo(episode.manga.value!.id!)
|
||||
.findFirstSync()
|
||||
?.mediaId;
|
||||
return switch (malId) {
|
||||
!= null => (malId, 1),
|
||||
== null => switch (aniId) { != null => (aniId, 2), _ => null },
|
||||
|
|
@ -183,14 +205,17 @@ class AnimeStreamController extends _$AnimeStreamController {
|
|||
};
|
||||
}
|
||||
|
||||
Future<List<Results>?> getAniSkipResults(Function(List<Results>) result) async {
|
||||
Future<List<Results>?> getAniSkipResults(
|
||||
Function(List<Results>) result) async {
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
if (ref.watch(enableAniSkipStateProvider)) {
|
||||
final id = _getTrackId();
|
||||
if (id != null) {
|
||||
final res = await ref
|
||||
.read(aniSkipProvider.notifier)
|
||||
.getResult(id, ChapterRecognition().parseChapterNumber(episode.manga.value!.name!, episode.name!), 0);
|
||||
final res = await ref.read(aniSkipProvider.notifier).getResult(
|
||||
id,
|
||||
ChapterRecognition()
|
||||
.parseChapterNumber(episode.manga.value!.name!, episode.name!),
|
||||
0);
|
||||
result.call(res ?? []);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,21 @@ class SubtitleSettingsState extends _$SubtitleSettingsState {
|
|||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
if (end) {
|
||||
isar.writeTxnSync(() => isar.settings.putSync(settings!..playerSubtitleSettings = value));
|
||||
isar.writeTxnSync(() =>
|
||||
isar.settings.putSync(settings!..playerSubtitleSettings = value));
|
||||
}
|
||||
}
|
||||
|
||||
void resetColor() {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = PlayerSubtitleSettings(fontSize: state.fontSize, useBold: state.useBold, useItalic: state.useItalic);
|
||||
state = PlayerSubtitleSettings(
|
||||
fontSize: state.fontSize,
|
||||
useBold: state.useBold,
|
||||
useItalic: state.useItalic);
|
||||
isar.writeTxnSync(() => isar.settings.putSync(settings!
|
||||
..playerSubtitleSettings =
|
||||
PlayerSubtitleSettings(fontSize: state.fontSize, useBold: state.useBold, useItalic: state.useItalic)));
|
||||
..playerSubtitleSettings = PlayerSubtitleSettings(
|
||||
fontSize: state.fontSize,
|
||||
useBold: state.useBold,
|
||||
useItalic: state.useItalic)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,14 +20,18 @@ class AniSkipCountDownButton extends ConsumerStatefulWidget {
|
|||
required this.timeoutLength});
|
||||
|
||||
@override
|
||||
ConsumerState<AniSkipCountDownButton> createState() => _AniSkipCountDownButtonState();
|
||||
ConsumerState<AniSkipCountDownButton> createState() =>
|
||||
_AniSkipCountDownButtonState();
|
||||
}
|
||||
|
||||
class _AniSkipCountDownButtonState extends ConsumerState<AniSkipCountDownButton> with TickerProviderStateMixin {
|
||||
class _AniSkipCountDownButtonState extends ConsumerState<AniSkipCountDownButton>
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
@override
|
||||
void initState() {
|
||||
_controller = AnimationController(vsync: this, duration: Duration(seconds: widget.timeoutLength))..forward();
|
||||
_controller = AnimationController(
|
||||
vsync: this, duration: Duration(seconds: widget.timeoutLength))
|
||||
..forward();
|
||||
super.initState();
|
||||
if (widget.active) {
|
||||
if (widget.autoSkip) {
|
||||
|
|
@ -50,7 +54,8 @@ class _AniSkipCountDownButtonState extends ConsumerState<AniSkipCountDownButton>
|
|||
_isCompleted = true;
|
||||
});
|
||||
_controller.reset();
|
||||
widget.player.seek(Duration(seconds: widget.aniSkipResult!.interval!.endTime!.ceil()));
|
||||
widget.player.seek(
|
||||
Duration(seconds: widget.aniSkipResult!.interval!.endTime!.ceil()));
|
||||
}
|
||||
|
||||
bool _isCompleted = false;
|
||||
|
|
@ -72,7 +77,8 @@ class _AniSkipCountDownButtonState extends ConsumerState<AniSkipCountDownButton>
|
|||
padding: const EdgeInsets.symmetric(horizontal: 40),
|
||||
child: MaterialButton(
|
||||
padding: const EdgeInsets.all(0),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
onPressed: () {
|
||||
_seekTo();
|
||||
},
|
||||
|
|
@ -103,15 +109,21 @@ class _AniSkipCountDownButtonState extends ConsumerState<AniSkipCountDownButton>
|
|||
),
|
||||
Positioned.fill(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text(
|
||||
widget.skipTypeText.toUpperCase(),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text((widget.timeoutLength - (_controller.duration! * _controller.value).inSeconds)
|
||||
Text((widget.timeoutLength -
|
||||
(_controller.duration! *
|
||||
_controller.value)
|
||||
.inSeconds)
|
||||
.toString()),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -10,7 +10,12 @@ class CustomSeekBar extends StatefulWidget {
|
|||
final Function(Duration)? onSeekStart;
|
||||
final Function(Duration)? onSeekEnd;
|
||||
|
||||
const CustomSeekBar({super.key, this.onSeekStart, this.onSeekEnd, required this.player, this.delta});
|
||||
const CustomSeekBar(
|
||||
{super.key,
|
||||
this.onSeekStart,
|
||||
this.onSeekEnd,
|
||||
required this.player,
|
||||
this.delta});
|
||||
|
||||
@override
|
||||
CustomSeekBarState createState() => CustomSeekBarState();
|
||||
|
|
@ -64,7 +69,8 @@ class CustomSeekBarState extends State<CustomSeekBar> {
|
|||
width: 70,
|
||||
child: Center(
|
||||
child: Text(
|
||||
(widget.delta ?? tempPosition ?? position).label(reference: duration),
|
||||
(widget.delta ?? tempPosition ?? position)
|
||||
.label(reference: duration),
|
||||
style: const TextStyle(
|
||||
height: 1.0,
|
||||
fontSize: 12.0,
|
||||
|
|
@ -79,10 +85,15 @@ class CustomSeekBarState extends State<CustomSeekBar> {
|
|||
),
|
||||
child: Slider(
|
||||
max: max(duration.inMilliseconds.toDouble(), 0),
|
||||
value: max((widget.delta ?? tempPosition ?? position).inMilliseconds.toDouble(), 0),
|
||||
value: max(
|
||||
(widget.delta ?? tempPosition ?? position)
|
||||
.inMilliseconds
|
||||
.toDouble(),
|
||||
0),
|
||||
secondaryTrackValue: max(buffer.inMilliseconds.toDouble(), 0),
|
||||
onChanged: (value) {
|
||||
widget.onSeekStart?.call(Duration(milliseconds: value.toInt() - position.inMilliseconds));
|
||||
widget.onSeekStart?.call(Duration(
|
||||
milliseconds: value.toInt() - position.inMilliseconds));
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
tempPosition = Duration(milliseconds: value.toInt());
|
||||
|
|
@ -90,7 +101,8 @@ class CustomSeekBarState extends State<CustomSeekBar> {
|
|||
}
|
||||
},
|
||||
onChangeEnd: (value) async {
|
||||
widget.onSeekEnd?.call(Duration(milliseconds: value.toInt() - position.inMilliseconds));
|
||||
widget.onSeekEnd?.call(Duration(
|
||||
milliseconds: value.toInt() - position.inMilliseconds));
|
||||
widget.player.seek(Duration(milliseconds: value.toInt()));
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ class DesktopControllerWidget extends StatefulWidget {
|
|||
required this.tempDuration});
|
||||
|
||||
@override
|
||||
State<DesktopControllerWidget> createState() => _DesktopControllerWidgetState();
|
||||
State<DesktopControllerWidget> createState() =>
|
||||
_DesktopControllerWidgetState();
|
||||
}
|
||||
|
||||
class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
||||
|
|
@ -151,26 +152,36 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
bindings: {
|
||||
// Default key-board shortcuts.
|
||||
// https://support.google.com/youtube/answer/7631406
|
||||
const SingleActivator(LogicalKeyboardKey.mediaPlay): () => widget.videoController.player.play(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaPause): () => widget.videoController.player.pause(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaPlayPause): () => widget.videoController.player.playOrPause(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaTrackNext): () => widget.videoController.player.next(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaTrackPrevious): () => widget.videoController.player.previous(),
|
||||
const SingleActivator(LogicalKeyboardKey.space): () => widget.videoController.player.playOrPause(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaPlay): () =>
|
||||
widget.videoController.player.play(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaPause): () =>
|
||||
widget.videoController.player.pause(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaPlayPause): () =>
|
||||
widget.videoController.player.playOrPause(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaTrackNext): () =>
|
||||
widget.videoController.player.next(),
|
||||
const SingleActivator(LogicalKeyboardKey.mediaTrackPrevious): () =>
|
||||
widget.videoController.player.previous(),
|
||||
const SingleActivator(LogicalKeyboardKey.space): () =>
|
||||
widget.videoController.player.playOrPause(),
|
||||
const SingleActivator(LogicalKeyboardKey.keyJ): () {
|
||||
final rate = widget.videoController.player.state.position - const Duration(seconds: 10);
|
||||
final rate = widget.videoController.player.state.position -
|
||||
const Duration(seconds: 10);
|
||||
widget.videoController.player.seek(rate);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.keyL): () {
|
||||
final rate = widget.videoController.player.state.position + const Duration(seconds: 10);
|
||||
final rate = widget.videoController.player.state.position +
|
||||
const Duration(seconds: 10);
|
||||
widget.videoController.player.seek(rate);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.arrowLeft): () {
|
||||
final rate = widget.videoController.player.state.position - const Duration(seconds: 5);
|
||||
final rate = widget.videoController.player.state.position -
|
||||
const Duration(seconds: 5);
|
||||
widget.videoController.player.seek(rate);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.arrowRight): () {
|
||||
final rate = widget.videoController.player.state.position + const Duration(seconds: 5);
|
||||
final rate = widget.videoController.player.state.position +
|
||||
const Duration(seconds: 5);
|
||||
widget.videoController.player.seek(rate);
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.arrowUp): () {
|
||||
|
|
@ -182,7 +193,8 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
widget.videoController.player.setVolume(volume.clamp(0.0, 100.0));
|
||||
},
|
||||
const SingleActivator(LogicalKeyboardKey.keyF): () => setFullScreen(),
|
||||
const SingleActivator(LogicalKeyboardKey.escape): () => setFullScreen(value: false),
|
||||
const SingleActivator(LogicalKeyboardKey.escape): () =>
|
||||
setFullScreen(value: false),
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
|
|
@ -192,7 +204,8 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
: Positioned(
|
||||
child: CustomSubtitleView(
|
||||
controller: widget.videoController,
|
||||
configuration: SubtitleViewConfiguration(style: subtileTextStyle(ref)),
|
||||
configuration:
|
||||
SubtitleViewConfiguration(style: subtileTextStyle(ref)),
|
||||
)),
|
||||
),
|
||||
Focus(
|
||||
|
|
@ -202,12 +215,16 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
? (e) {
|
||||
if (e is PointerScrollEvent) {
|
||||
if (e.delta.dy > 0) {
|
||||
final volume = widget.videoController.player.state.volume - 5.0;
|
||||
widget.videoController.player.setVolume(volume.clamp(0.0, 100.0));
|
||||
final volume =
|
||||
widget.videoController.player.state.volume - 5.0;
|
||||
widget.videoController.player
|
||||
.setVolume(volume.clamp(0.0, 100.0));
|
||||
}
|
||||
if (e.delta.dy < 0) {
|
||||
final volume = widget.videoController.player.state.volume + 5.0;
|
||||
widget.videoController.player.setVolume(volume.clamp(0.0, 100.0));
|
||||
final volume =
|
||||
widget.videoController.player.state.volume + 5.0;
|
||||
widget.videoController.player
|
||||
.setVolume(volume.clamp(0.0, 100.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -226,12 +243,16 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
onPanUpdate: modifyVolumeOnScroll
|
||||
? (e) {
|
||||
if (e.delta.dy > 0) {
|
||||
final volume = widget.videoController.player.state.volume - 5.0;
|
||||
widget.videoController.player.setVolume(volume.clamp(0.0, 100.0));
|
||||
final volume =
|
||||
widget.videoController.player.state.volume - 5.0;
|
||||
widget.videoController.player
|
||||
.setVolume(volume.clamp(0.0, 100.0));
|
||||
}
|
||||
if (e.delta.dy < 0) {
|
||||
final volume = widget.videoController.player.state.volume + 5.0;
|
||||
widget.videoController.player.setVolume(volume.clamp(0.0, 100.0));
|
||||
final volume =
|
||||
widget.videoController.player.state.volume + 5.0;
|
||||
widget.videoController.player
|
||||
.setVolume(volume.clamp(0.0, 100.0));
|
||||
}
|
||||
}
|
||||
: null,
|
||||
|
|
@ -239,7 +260,9 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
onHover: (_) => onHover(),
|
||||
onEnter: (_) => onEnter(),
|
||||
onExit: (_) => onExit(),
|
||||
cursor: cursorVisible ? SystemMouseCursors.basic : SystemMouseCursors.none,
|
||||
cursor: cursorVisible
|
||||
? SystemMouseCursors.basic
|
||||
: SystemMouseCursors.none,
|
||||
child: Stack(
|
||||
children: [
|
||||
AnimatedOpacity(
|
||||
|
|
@ -297,7 +320,9 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
Padding(
|
||||
padding: (
|
||||
// Add padding in fullscreen!
|
||||
isFullscreen(context) ? MediaQuery.of(context).padding : EdgeInsets.zero),
|
||||
isFullscreen(context)
|
||||
? MediaQuery.of(context).padding
|
||||
: EdgeInsets.zero),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
|
|
@ -315,20 +340,29 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
: 1.0,
|
||||
duration: controlsTransitionDuration,
|
||||
child: Center(
|
||||
child: seekIndicatorTextWidget(Duration(seconds: swipeDuration),
|
||||
widget.videoController.player.state.position))),
|
||||
child: seekIndicatorTextWidget(
|
||||
Duration(
|
||||
seconds: swipeDuration),
|
||||
widget.videoController.player
|
||||
.state.position))),
|
||||
),
|
||||
widget.seekToWidget,
|
||||
Transform.translate(
|
||||
offset: Offset.zero,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 5),
|
||||
child: CustomSeekBar(
|
||||
onSeekStart: (value) {
|
||||
setState(() {
|
||||
swipeDuration = value.inSeconds;
|
||||
showSwipeDuration = true;
|
||||
widget.tempDuration(widget.videoController.player.state.position + value);
|
||||
widget.tempDuration(widget
|
||||
.videoController
|
||||
.player
|
||||
.state
|
||||
.position +
|
||||
value);
|
||||
});
|
||||
_timer?.cancel();
|
||||
},
|
||||
|
|
@ -364,7 +398,9 @@ class _DesktopControllerWidgetState extends State<DesktopControllerWidget> {
|
|||
child: Padding(
|
||||
padding: (
|
||||
// Add padding in fullscreen!
|
||||
isFullscreen(context) ? MediaQuery.of(context).padding : EdgeInsets.zero),
|
||||
isFullscreen(context)
|
||||
? MediaQuery.of(context).padding
|
||||
: EdgeInsets.zero),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
|
|
@ -430,10 +466,12 @@ class CustomeMaterialDesktopPlayOrPauseButton extends StatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
CustomeMaterialDesktopPlayOrPauseButtonState createState() => CustomeMaterialDesktopPlayOrPauseButtonState();
|
||||
CustomeMaterialDesktopPlayOrPauseButtonState createState() =>
|
||||
CustomeMaterialDesktopPlayOrPauseButtonState();
|
||||
}
|
||||
|
||||
class CustomeMaterialDesktopPlayOrPauseButtonState extends State<CustomeMaterialDesktopPlayOrPauseButton>
|
||||
class CustomeMaterialDesktopPlayOrPauseButtonState
|
||||
extends State<CustomeMaterialDesktopPlayOrPauseButton>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final animation = AnimationController(
|
||||
vsync: this,
|
||||
|
|
@ -497,10 +535,12 @@ class CustomMaterialDesktopVolumeButton extends StatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
CustomMaterialDesktopVolumeButtonState createState() => CustomMaterialDesktopVolumeButtonState();
|
||||
CustomMaterialDesktopVolumeButtonState createState() =>
|
||||
CustomMaterialDesktopVolumeButtonState();
|
||||
}
|
||||
|
||||
class CustomMaterialDesktopVolumeButtonState extends State<CustomMaterialDesktopVolumeButton>
|
||||
class CustomMaterialDesktopVolumeButtonState
|
||||
extends State<CustomMaterialDesktopVolumeButton>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late double volume = widget.controller.player.state.volume;
|
||||
|
||||
|
|
@ -663,13 +703,16 @@ class CustomMaterialDesktopPositionIndicator extends StatefulWidget {
|
|||
final VideoController controller;
|
||||
final Duration? delta;
|
||||
|
||||
const CustomMaterialDesktopPositionIndicator({super.key, required this.controller, this.delta});
|
||||
const CustomMaterialDesktopPositionIndicator(
|
||||
{super.key, required this.controller, this.delta});
|
||||
|
||||
@override
|
||||
CustomMaterialDesktopPositionIndicatorState createState() => CustomMaterialDesktopPositionIndicatorState();
|
||||
CustomMaterialDesktopPositionIndicatorState createState() =>
|
||||
CustomMaterialDesktopPositionIndicatorState();
|
||||
}
|
||||
|
||||
class CustomMaterialDesktopPositionIndicatorState extends State<CustomMaterialDesktopPositionIndicator> {
|
||||
class CustomMaterialDesktopPositionIndicatorState
|
||||
extends State<CustomMaterialDesktopPositionIndicator> {
|
||||
late Duration position = widget.controller.player.state.position;
|
||||
late Duration duration = widget.controller.player.state.duration;
|
||||
|
||||
|
|
@ -755,10 +798,12 @@ class CustomMaterialDesktopFullscreenButton extends StatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
State<CustomMaterialDesktopFullscreenButton> createState() => _CustomMaterialDesktopFullscreenButtonState();
|
||||
State<CustomMaterialDesktopFullscreenButton> createState() =>
|
||||
_CustomMaterialDesktopFullscreenButtonState();
|
||||
}
|
||||
|
||||
class _CustomMaterialDesktopFullscreenButtonState extends State<CustomMaterialDesktopFullscreenButton> {
|
||||
class _CustomMaterialDesktopFullscreenButtonState
|
||||
extends State<CustomMaterialDesktopFullscreenButton> {
|
||||
bool _isFullscreen = false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -769,7 +814,9 @@ class _CustomMaterialDesktopFullscreenButtonState extends State<CustomMaterialDe
|
|||
_isFullscreen = isFullScreen;
|
||||
});
|
||||
},
|
||||
icon: _isFullscreen ? const Icon(Icons.fullscreen_exit) : const Icon(Icons.fullscreen),
|
||||
icon: _isFullscreen
|
||||
? const Icon(Icons.fullscreen_exit)
|
||||
: const Icon(Icons.fullscreen),
|
||||
iconSize: 25,
|
||||
color: Colors.white,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import 'package:flutter/material.dart';
|
|||
class MediaIndicatorBuilder extends StatelessWidget {
|
||||
final bool isVolumeIndicator;
|
||||
final ValueNotifier<double> value;
|
||||
const MediaIndicatorBuilder({super.key, required this.value, required this.isVolumeIndicator});
|
||||
const MediaIndicatorBuilder(
|
||||
{super.key, required this.value, required this.isVolumeIndicator});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -12,7 +13,9 @@ class MediaIndicatorBuilder extends StatelessWidget {
|
|||
builder: (context, value, child) => Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 40),
|
||||
child: Row(
|
||||
mainAxisAlignment: isVolumeIndicator ? MainAxisAlignment.start : MainAxisAlignment.end,
|
||||
mainAxisAlignment: isVolumeIndicator
|
||||
? MainAxisAlignment.start
|
||||
: MainAxisAlignment.end,
|
||||
children: [
|
||||
Container(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
|
|
@ -42,8 +45,9 @@ class MediaIndicatorBuilder extends StatelessWidget {
|
|||
),
|
||||
child: SizedBox.fromSize(
|
||||
size: const Size(130, 20),
|
||||
child:
|
||||
LinearProgressIndicator(value: value, backgroundColor: Colors.transparent)),
|
||||
child: LinearProgressIndicator(
|
||||
value: value,
|
||||
backgroundColor: Colors.transparent)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -30,16 +30,19 @@ class MobileControllerWidget extends ConsumerStatefulWidget {
|
|||
required this.videoStatekey});
|
||||
|
||||
@override
|
||||
ConsumerState<MobileControllerWidget> createState() => _MobileControllerWidgetState();
|
||||
ConsumerState<MobileControllerWidget> createState() =>
|
||||
_MobileControllerWidgetState();
|
||||
}
|
||||
|
||||
class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget> {
|
||||
class _MobileControllerWidgetState
|
||||
extends ConsumerState<MobileControllerWidget> {
|
||||
bool mount = true;
|
||||
bool visible = true;
|
||||
Duration controlsTransitionDuration = const Duration(milliseconds: 300);
|
||||
Color backdropColor = const Color(0x66000000);
|
||||
Timer? _timer;
|
||||
late final skipDuration = ref.watch(defaultDoubleTapToSkipLengthStateProvider);
|
||||
late final skipDuration =
|
||||
ref.watch(defaultDoubleTapToSkipLengthStateProvider);
|
||||
final ValueNotifier<double> _brightnessValue = ValueNotifier(0.0);
|
||||
final ValueNotifier<bool> _brightnessIndicator = ValueNotifier(false);
|
||||
Timer? _brightnessTimer;
|
||||
|
|
@ -50,7 +53,8 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
// The default event stream in package:volume_controller is buggy.
|
||||
bool _volumeInterceptEventStream = false;
|
||||
|
||||
Offset _dragInitialDelta = Offset.zero; // Initial position for horizontal drag
|
||||
Offset _dragInitialDelta =
|
||||
Offset.zero; // Initial position for horizontal drag
|
||||
int swipeDuration = 0; // Duration to seek in video
|
||||
bool showSwipeDuration = false; // Whether to show the seek duration overlay
|
||||
|
||||
|
|
@ -188,15 +192,17 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
setState(() {
|
||||
swipeDuration = seconds;
|
||||
showSwipeDuration = true;
|
||||
_seekBarDeltaValueNotifier =
|
||||
Duration(seconds: widget.videoController.player.state.position.inSeconds + seconds);
|
||||
_seekBarDeltaValueNotifier = Duration(
|
||||
seconds: widget.videoController.player.state.position.inSeconds +
|
||||
seconds);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void onHorizontalDragEnd() {
|
||||
if (swipeDuration != 0) {
|
||||
Duration newPosition = widget.videoController.player.state.position + Duration(seconds: swipeDuration);
|
||||
Duration newPosition = widget.videoController.player.state.position +
|
||||
Duration(seconds: swipeDuration);
|
||||
newPosition = newPosition.clamp(
|
||||
Duration.zero,
|
||||
widget.videoController.player.state.duration,
|
||||
|
|
@ -233,7 +239,8 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
Future.microtask(() async {
|
||||
try {
|
||||
_brightnessValue.value = await ScreenBrightness.instance.application;
|
||||
ScreenBrightness.instance.onApplicationScreenBrightnessChanged.listen((value) {
|
||||
ScreenBrightness.instance.onApplicationScreenBrightnessChanged
|
||||
.listen((value) {
|
||||
if (mounted) {
|
||||
_brightnessValue.value = value;
|
||||
}
|
||||
|
|
@ -288,7 +295,8 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
: Positioned(
|
||||
child: CustomSubtitleView(
|
||||
controller: widget.videoController,
|
||||
configuration: SubtitleViewConfiguration(style: subtileTextStyle(ref)),
|
||||
configuration:
|
||||
SubtitleViewConfiguration(style: subtileTextStyle(ref)),
|
||||
)),
|
||||
),
|
||||
Focus(
|
||||
|
|
@ -329,7 +337,9 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
onTap: onTap,
|
||||
onDoubleTapDown: _handleTapDown,
|
||||
onDoubleTap: () {
|
||||
if (_tapPosition != null && _tapPosition!.dx > MediaQuery.of(context).size.width / 2) {
|
||||
if (_tapPosition != null &&
|
||||
_tapPosition!.dx >
|
||||
MediaQuery.of(context).size.width / 2) {
|
||||
onDoubleTapSeekForward();
|
||||
} else {
|
||||
onDoubleTapSeekBackward();
|
||||
|
|
@ -345,16 +355,19 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
final delta = e.delta.dy;
|
||||
final Offset position = e.localPosition;
|
||||
|
||||
if (position.dx <= MediaQuery.of(context).size.width / 2) {
|
||||
if (position.dx <=
|
||||
MediaQuery.of(context).size.width / 2) {
|
||||
// Left side of screen swiped
|
||||
|
||||
final brightness = _brightnessValue.value - delta / verticalGestureSensitivity;
|
||||
final brightness = _brightnessValue.value -
|
||||
delta / verticalGestureSensitivity;
|
||||
final result = brightness.clamp(0.0, 1.0);
|
||||
setBrightness(result);
|
||||
} else {
|
||||
// Right side of screen swiped
|
||||
|
||||
final volume = _volumeValue.value - delta / verticalGestureSensitivity;
|
||||
final volume = _volumeValue.value -
|
||||
delta / verticalGestureSensitivity;
|
||||
final result = volume.clamp(0.0, 1.0);
|
||||
setVolume(result);
|
||||
}
|
||||
|
|
@ -368,7 +381,9 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
Padding(
|
||||
padding: (
|
||||
// Add padding in fullscreen!
|
||||
isFullscreen(context) ? MediaQuery.of(context).padding : EdgeInsets.zero),
|
||||
isFullscreen(context)
|
||||
? MediaQuery.of(context).padding
|
||||
: EdgeInsets.zero),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
|
|
@ -387,8 +402,11 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
duration: controlsTransitionDuration,
|
||||
child: Center(
|
||||
child: Row(
|
||||
children: mobilePrimaryButtonBar(context, widget.videoStatekey,
|
||||
widget.streamController, widget.videoController)),
|
||||
children: mobilePrimaryButtonBar(
|
||||
context,
|
||||
widget.videoStatekey,
|
||||
widget.streamController,
|
||||
widget.videoController)),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -434,7 +452,9 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
),
|
||||
// // Double-Tap Seek Seek-Bar:
|
||||
if (!mount)
|
||||
if (_mountSeekBackwardButton || _mountSeekForwardButton || showSwipeDuration)
|
||||
if (_mountSeekBackwardButton ||
|
||||
_mountSeekForwardButton ||
|
||||
showSwipeDuration)
|
||||
Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
|
|
@ -443,8 +463,9 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child:
|
||||
CustomSeekBar(delta: _seekBarDeltaValueNotifier, player: widget.videoController.player),
|
||||
child: CustomSeekBar(
|
||||
delta: _seekBarDeltaValueNotifier,
|
||||
player: widget.videoController.player),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -455,7 +476,9 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
child: Padding(
|
||||
padding: (
|
||||
// Add padding in fullscreen!
|
||||
isFullscreen(context) ? MediaQuery.of(context).padding : EdgeInsets.zero),
|
||||
isFullscreen(context)
|
||||
? MediaQuery.of(context).padding
|
||||
: EdgeInsets.zero),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
|
|
@ -503,7 +526,8 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
curve: Curves.easeInOut,
|
||||
opacity: value ? 1.0 : 0.0,
|
||||
duration: controlsTransitionDuration,
|
||||
child: MediaIndicatorBuilder(value: _volumeValue, isVolumeIndicator: true)),
|
||||
child: MediaIndicatorBuilder(
|
||||
value: _volumeValue, isVolumeIndicator: true)),
|
||||
),
|
||||
),
|
||||
// // Brightness Indicator.
|
||||
|
|
@ -514,7 +538,8 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
curve: Curves.easeInOut,
|
||||
opacity: value ? 1.0 : 0.0,
|
||||
duration: controlsTransitionDuration,
|
||||
child: MediaIndicatorBuilder(value: _brightnessValue, isVolumeIndicator: false)),
|
||||
child: MediaIndicatorBuilder(
|
||||
value: _brightnessValue, isVolumeIndicator: false)),
|
||||
),
|
||||
),
|
||||
// Seek Indicator.
|
||||
|
|
@ -523,7 +548,8 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
duration: controlsTransitionDuration,
|
||||
opacity: showSwipeDuration ? 1 : 0,
|
||||
child: seekIndicatorTextWidget(
|
||||
Duration(seconds: swipeDuration), widget.videoController.player.state.position)),
|
||||
Duration(seconds: swipeDuration),
|
||||
widget.videoController.player.state.position)),
|
||||
),
|
||||
|
||||
// Double-Tap Seek Button(s):
|
||||
|
|
@ -554,20 +580,28 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
child: _BackwardSeekIndicator(
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_seekBarDeltaValueNotifier =
|
||||
widget.videoController.player.state.position - value;
|
||||
_seekBarDeltaValueNotifier = widget
|
||||
.videoController
|
||||
.player
|
||||
.state
|
||||
.position -
|
||||
value;
|
||||
});
|
||||
},
|
||||
onSubmitted: (value) {
|
||||
setState(() {
|
||||
_hideSeekBackwardButton = true;
|
||||
});
|
||||
var result = widget.videoController.player.state.position - value;
|
||||
var result = widget.videoController.player
|
||||
.state.position -
|
||||
value;
|
||||
result = result.clamp(
|
||||
Duration.zero,
|
||||
widget.videoController.player.state.duration,
|
||||
widget.videoController.player.state
|
||||
.duration,
|
||||
);
|
||||
widget.videoController.player.seek(result);
|
||||
widget.videoController.player
|
||||
.seek(result);
|
||||
},
|
||||
skipDuration: skipDuration),
|
||||
)
|
||||
|
|
@ -596,20 +630,28 @@ class _MobileControllerWidgetState extends ConsumerState<MobileControllerWidget>
|
|||
child: _ForwardSeekIndicator(
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_seekBarDeltaValueNotifier =
|
||||
widget.videoController.player.state.position + value;
|
||||
_seekBarDeltaValueNotifier = widget
|
||||
.videoController
|
||||
.player
|
||||
.state
|
||||
.position +
|
||||
value;
|
||||
});
|
||||
},
|
||||
onSubmitted: (value) {
|
||||
setState(() {
|
||||
_hideSeekForwardButton = true;
|
||||
});
|
||||
var result = widget.videoController.player.state.position + value;
|
||||
var result = widget.videoController.player
|
||||
.state.position +
|
||||
value;
|
||||
result = result.clamp(
|
||||
Duration.zero,
|
||||
widget.videoController.player.state.duration,
|
||||
widget.videoController.player.state
|
||||
.duration,
|
||||
);
|
||||
widget.videoController.player.seek(result);
|
||||
widget.videoController.player
|
||||
.seek(result);
|
||||
},
|
||||
skipDuration: skipDuration),
|
||||
)
|
||||
|
|
@ -814,10 +856,12 @@ class CustomMaterialPlayOrPauseButton extends StatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
CustomMaterialPlayOrPauseButtonState createState() => CustomMaterialPlayOrPauseButtonState();
|
||||
CustomMaterialPlayOrPauseButtonState createState() =>
|
||||
CustomMaterialPlayOrPauseButtonState();
|
||||
}
|
||||
|
||||
class CustomMaterialPlayOrPauseButtonState extends State<CustomMaterialPlayOrPauseButton>
|
||||
class CustomMaterialPlayOrPauseButtonState
|
||||
extends State<CustomMaterialPlayOrPauseButton>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final animation = AnimationController(
|
||||
vsync: this,
|
||||
|
|
@ -871,8 +915,11 @@ class CustomMaterialPlayOrPauseButtonState extends State<CustomMaterialPlayOrPau
|
|||
}
|
||||
}
|
||||
|
||||
List<Widget> mobilePrimaryButtonBar(BuildContext context, GlobalKey<VideoState> key,
|
||||
AnimeStreamController streamController, VideoController controller) {
|
||||
List<Widget> mobilePrimaryButtonBar(
|
||||
BuildContext context,
|
||||
GlobalKey<VideoState> key,
|
||||
AnimeStreamController streamController,
|
||||
VideoController controller) {
|
||||
bool hasPrevEpisode = streamController.getEpisodeIndex().$1 + 1 !=
|
||||
streamController.getEpisodesLength(streamController.getEpisodeIndex().$2);
|
||||
bool hasNextEpisode = streamController.getEpisodeIndex().$1 != 0;
|
||||
|
|
@ -885,7 +932,8 @@ List<Widget> mobilePrimaryButtonBar(BuildContext context, GlobalKey<VideoState>
|
|||
if (isFullScreen) {
|
||||
key.currentState?.exitFullscreen();
|
||||
}
|
||||
pushReplacementMangaReaderView(context: context, chapter: streamController.getPrevEpisode());
|
||||
pushReplacementMangaReaderView(
|
||||
context: context, chapter: streamController.getPrevEpisode());
|
||||
}
|
||||
: null,
|
||||
icon: Icon(
|
||||
|
|
@ -909,7 +957,8 @@ List<Widget> mobilePrimaryButtonBar(BuildContext context, GlobalKey<VideoState>
|
|||
);
|
||||
}
|
||||
: null,
|
||||
icon: Icon(Icons.skip_next, size: 35, color: hasPrevEpisode ? Colors.white : Colors.grey),
|
||||
icon: Icon(Icons.skip_next,
|
||||
size: 35, color: hasPrevEpisode ? Colors.white : Colors.grey),
|
||||
),
|
||||
const Spacer(flex: 3)
|
||||
];
|
||||
|
|
|
|||
|
|
@ -43,9 +43,9 @@ class _FontSettingWidgetState extends ConsumerState<FontSettingWidget> {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
iconButton(Icons.remove, () {
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subtitleSettings..fontSize = subtitleSettings.fontSize! - 1, true);
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(
|
||||
subtitleSettings..fontSize = subtitleSettings.fontSize! - 1,
|
||||
true);
|
||||
setState(() {});
|
||||
},
|
||||
backgroundColor: context.dynamicWhiteBlackColor,
|
||||
|
|
@ -54,12 +54,15 @@ class _FontSettingWidgetState extends ConsumerState<FontSettingWidget> {
|
|||
SizedBox(
|
||||
width: 200,
|
||||
child: TextFormField(
|
||||
controller: TextEditingController(text: subtitleSettings.fontSize.toString()),
|
||||
controller: TextEditingController(
|
||||
text: subtitleSettings.fontSize.toString()),
|
||||
keyboardType: TextInputType.number,
|
||||
onChanged: (v) {
|
||||
final val = int.tryParse(v);
|
||||
if (val != null) {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subtitleSettings..fontSize = val, true);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subtitleSettings..fontSize = val, true);
|
||||
}
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
|
|
@ -67,40 +70,51 @@ class _FontSettingWidgetState extends ConsumerState<FontSettingWidget> {
|
|||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: Colors.transparent,
|
||||
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: context.dynamicThemeColor)),
|
||||
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: context.dynamicThemeColor)),
|
||||
border: OutlineInputBorder(borderSide: BorderSide(color: context.dynamicThemeColor))),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: context.dynamicThemeColor)),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: context.dynamicThemeColor)),
|
||||
border: OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: context.dynamicThemeColor))),
|
||||
),
|
||||
),
|
||||
iconButton(Icons.add, () {
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subtitleSettings..fontSize = subtitleSettings.fontSize! + 1, true);
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(
|
||||
subtitleSettings..fontSize = subtitleSettings.fontSize! + 1,
|
||||
true);
|
||||
setState(() {});
|
||||
},
|
||||
backgroundColor: context.dynamicWhiteBlackColor,
|
||||
iconColors: context.isLight ? Colors.white : Colors.black,
|
||||
size: 25),
|
||||
iconButton(Icons.format_bold, () {
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subtitleSettings..useBold = !subtitleSettings.useBold!, true);
|
||||
setState(() {});
|
||||
}, iconColors: subtitleSettings.useBold! ? null : context.dynamicWhiteBlackColor.withValues(alpha: 0.5)),
|
||||
iconButton(Icons.format_italic, () {
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subtitleSettings..useItalic = !subtitleSettings.useItalic!, true);
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(
|
||||
subtitleSettings..useBold = !subtitleSettings.useBold!,
|
||||
true);
|
||||
setState(() {});
|
||||
},
|
||||
iconColors:
|
||||
subtitleSettings.useItalic! ? null : context.dynamicWhiteBlackColor.withValues(alpha: 0.5)),
|
||||
iconColors: subtitleSettings.useBold!
|
||||
? null
|
||||
: context.dynamicWhiteBlackColor.withValues(alpha: 0.5)),
|
||||
iconButton(Icons.format_italic, () {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(
|
||||
subtitleSettings..useItalic = !subtitleSettings.useItalic!,
|
||||
true);
|
||||
setState(() {});
|
||||
},
|
||||
iconColors: subtitleSettings.useItalic!
|
||||
? null
|
||||
: context.dynamicWhiteBlackColor.withValues(alpha: 0.5)),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text("Lorem ipsum dolor sit amet",
|
||||
style: subtileTextStyle(ref).copyWith(fontSize: 22), textAlign: TextAlign.center),
|
||||
style: subtileTextStyle(ref).copyWith(fontSize: 22),
|
||||
textAlign: TextAlign.center),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
|
|
@ -154,7 +168,8 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
|
|||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: color,
|
||||
border: Border.all(width: 2, color: context.dynamicWhiteBlackColor)),
|
||||
border: Border.all(
|
||||
width: 2, color: context.dynamicWhiteBlackColor)),
|
||||
),
|
||||
),
|
||||
Text("#${color.hexCode}", style: TextStyle(color: context.textColor)),
|
||||
|
|
@ -170,12 +185,15 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final subSets = ref.watch(subtitleSettingsStateProvider);
|
||||
final textColor =
|
||||
Color.fromARGB(subSets.textColorA!, subSets.textColorR!, subSets.textColorG!, subSets.textColorB!);
|
||||
final borderColor =
|
||||
Color.fromARGB(subSets.borderColorA!, subSets.borderColorR!, subSets.borderColorG!, subSets.borderColorB!);
|
||||
final textColor = Color.fromARGB(subSets.textColorA!, subSets.textColorR!,
|
||||
subSets.textColorG!, subSets.textColorB!);
|
||||
final borderColor = Color.fromARGB(subSets.borderColorA!,
|
||||
subSets.borderColorR!, subSets.borderColorG!, subSets.borderColorB!);
|
||||
final backgroundColor = Color.fromARGB(
|
||||
subSets.backgroundColorA!, subSets.backgroundColorR!, subSets.backgroundColorG!, subSets.backgroundColorB!);
|
||||
subSets.backgroundColorA!,
|
||||
subSets.backgroundColorR!,
|
||||
subSets.backgroundColorG!,
|
||||
subSets.backgroundColorB!);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
|
|
@ -198,45 +216,72 @@ class _ColorSettingWidgetState extends ConsumerState<ColorSettingWidget> {
|
|||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(flex: 3, child: button(context.l10n.text, "text", textColor)),
|
||||
Expanded(flex: 3, child: button(context.l10n.border, "border", borderColor)),
|
||||
Expanded(flex: 3, child: button(context.l10n.background, "backgroud", backgroundColor)),
|
||||
Expanded(
|
||||
flex: 3, child: button(context.l10n.text, "text", textColor)),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: button(context.l10n.border, "border", borderColor)),
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: button(
|
||||
context.l10n.background, "backgroud", backgroundColor)),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text("Lorem ipsum dolor sit amet",
|
||||
style: subtileTextStyle(ref).copyWith(fontSize: 22), textAlign: TextAlign.center),
|
||||
style: subtileTextStyle(ref).copyWith(fontSize: 22),
|
||||
textAlign: TextAlign.center),
|
||||
),
|
||||
if (selector == "text") ...[
|
||||
rgbaFilterWidget(subSets.textColorA!, subSets.textColorR!, subSets.textColorG!, subSets.textColorB!, (val) {
|
||||
rgbaFilterWidget(subSets.textColorA!, subSets.textColorR!,
|
||||
subSets.textColorG!, subSets.textColorB!, (val) {
|
||||
if (val.$3 == "r") {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subSets..textColorR = val.$1.toInt(), val.$2);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subSets..textColorR = val.$1.toInt(), val.$2);
|
||||
} else if (val.$3 == "g") {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subSets..textColorG = val.$1.toInt(), val.$2);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subSets..textColorG = val.$1.toInt(), val.$2);
|
||||
} else if (val.$3 == "b") {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subSets..textColorB = val.$1.toInt(), val.$2);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subSets..textColorB = val.$1.toInt(), val.$2);
|
||||
} else {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subSets..textColorA = val.$1.toInt(), val.$2);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subSets..textColorA = val.$1.toInt(), val.$2);
|
||||
}
|
||||
setState(() {});
|
||||
}, context),
|
||||
] else if (selector == "border") ...[
|
||||
rgbaFilterWidget(subSets.borderColorA!, subSets.borderColorR!, subSets.borderColorG!, subSets.borderColorB!,
|
||||
(val) {
|
||||
rgbaFilterWidget(subSets.borderColorA!, subSets.borderColorR!,
|
||||
subSets.borderColorG!, subSets.borderColorB!, (val) {
|
||||
if (val.$3 == "r") {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subSets..borderColorR = val.$1.toInt(), val.$2);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subSets..borderColorR = val.$1.toInt(), val.$2);
|
||||
} else if (val.$3 == "g") {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subSets..borderColorG = val.$1.toInt(), val.$2);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subSets..borderColorG = val.$1.toInt(), val.$2);
|
||||
} else if (val.$3 == "b") {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subSets..borderColorB = val.$1.toInt(), val.$2);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subSets..borderColorB = val.$1.toInt(), val.$2);
|
||||
} else {
|
||||
ref.read(subtitleSettingsStateProvider.notifier).set(subSets..borderColorA = val.$1.toInt(), val.$2);
|
||||
ref
|
||||
.read(subtitleSettingsStateProvider.notifier)
|
||||
.set(subSets..borderColorA = val.$1.toInt(), val.$2);
|
||||
}
|
||||
setState(() {});
|
||||
}, context),
|
||||
] else ...[
|
||||
rgbaFilterWidget(subSets.backgroundColorA!, subSets.backgroundColorR!, subSets.backgroundColorG!,
|
||||
rgbaFilterWidget(
|
||||
subSets.backgroundColorA!,
|
||||
subSets.backgroundColorR!,
|
||||
subSets.backgroundColorG!,
|
||||
subSets.backgroundColorB!, (val) {
|
||||
if (val.$3 == "r") {
|
||||
ref
|
||||
|
|
@ -279,7 +324,8 @@ Widget iconButton(IconData icon, void Function()? onPressed,
|
|||
width: size,
|
||||
child: IconButton(
|
||||
iconSize: size * 0.9,
|
||||
style: ButtonStyle(backgroundColor: WidgetStatePropertyAll(backgroundColor)),
|
||||
style: ButtonStyle(
|
||||
backgroundColor: WidgetStatePropertyAll(backgroundColor)),
|
||||
padding: const EdgeInsets.all(1),
|
||||
onPressed: onPressed,
|
||||
icon: Icon(icon, color: iconColors)),
|
||||
|
|
|
|||
|
|
@ -77,10 +77,12 @@ class _CustomSubtitleViewState extends ConsumerState<CustomSubtitleView> {
|
|||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final nr = (constraints.maxWidth * constraints.maxHeight);
|
||||
const dr = kTextScaleFactorReferenceWidth * kTextScaleFactorReferenceHeight;
|
||||
const dr =
|
||||
kTextScaleFactorReferenceWidth * kTextScaleFactorReferenceHeight;
|
||||
final textScaleFactor = sqrt((nr / dr).clamp(0.0, 1.0));
|
||||
|
||||
final textScaler = widget.configuration.textScaler ?? TextScaler.linear(textScaleFactor);
|
||||
final textScaler = widget.configuration.textScaler ??
|
||||
TextScaler.linear(textScaleFactor);
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: AnimatedContainer(
|
||||
|
|
@ -105,19 +107,35 @@ class _CustomSubtitleViewState extends ConsumerState<CustomSubtitleView> {
|
|||
|
||||
TextStyle subtileTextStyle(WidgetRef ref) {
|
||||
final subSets = ref.watch(subtitleSettingsStateProvider);
|
||||
final borderColor =
|
||||
Color.fromARGB(subSets.borderColorA!, subSets.borderColorR!, subSets.borderColorG!, subSets.borderColorB!);
|
||||
final borderColor = Color.fromARGB(subSets.borderColorA!,
|
||||
subSets.borderColorR!, subSets.borderColorG!, subSets.borderColorB!);
|
||||
return TextStyle(
|
||||
fontSize: subSets.fontSize!.toDouble(),
|
||||
fontWeight: subSets.useBold! ? FontWeight.bold : null,
|
||||
fontStyle: subSets.useItalic! ? FontStyle.italic : null,
|
||||
color: Color.fromARGB(subSets.textColorA!, subSets.textColorR!, subSets.textColorG!, subSets.textColorB!),
|
||||
color: Color.fromARGB(subSets.textColorA!, subSets.textColorR!,
|
||||
subSets.textColorG!, subSets.textColorB!),
|
||||
shadows: [
|
||||
Shadow(offset: const Offset(-1.5, -1.5), color: borderColor, blurRadius: 1.4),
|
||||
Shadow(offset: const Offset(1.5, -1.5), color: borderColor, blurRadius: 1.4),
|
||||
Shadow(offset: const Offset(1.5, 1.5), color: borderColor, blurRadius: 1.4),
|
||||
Shadow(offset: const Offset(-1.5, 1.5), color: borderColor, blurRadius: 1.4)
|
||||
Shadow(
|
||||
offset: const Offset(-1.5, -1.5),
|
||||
color: borderColor,
|
||||
blurRadius: 1.4),
|
||||
Shadow(
|
||||
offset: const Offset(1.5, -1.5),
|
||||
color: borderColor,
|
||||
blurRadius: 1.4),
|
||||
Shadow(
|
||||
offset: const Offset(1.5, 1.5),
|
||||
color: borderColor,
|
||||
blurRadius: 1.4),
|
||||
Shadow(
|
||||
offset: const Offset(-1.5, 1.5),
|
||||
color: borderColor,
|
||||
blurRadius: 1.4)
|
||||
],
|
||||
backgroundColor: Color.fromARGB(
|
||||
subSets.backgroundColorA!, subSets.backgroundColorR!, subSets.backgroundColorG!, subSets.backgroundColorB!));
|
||||
subSets.backgroundColorA!,
|
||||
subSets.backgroundColorR!,
|
||||
subSets.backgroundColorG!,
|
||||
subSets.backgroundColorB!));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@ class BrowseScreen extends ConsumerStatefulWidget {
|
|||
ConsumerState<BrowseScreen> createState() => _BrowseScreenState();
|
||||
}
|
||||
|
||||
class _BrowseScreenState extends ConsumerState<BrowseScreen> with TickerProviderStateMixin {
|
||||
class _BrowseScreenState extends ConsumerState<BrowseScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late TabController _tabBarController;
|
||||
|
||||
@override
|
||||
|
|
@ -74,26 +75,33 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen> with TickerProvider
|
|||
)
|
||||
: Row(
|
||||
children: [
|
||||
if (_tabBarController.index == 2 || _tabBarController.index == 3)
|
||||
if (_tabBarController.index == 2 ||
|
||||
_tabBarController.index == 3)
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
context.push('/createExtension');
|
||||
},
|
||||
icon: Icon(Icons.add_outlined, color: Theme.of(context).hintColor)),
|
||||
icon: Icon(Icons.add_outlined,
|
||||
color: Theme.of(context).hintColor)),
|
||||
_tabBarController.index != 4
|
||||
? IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
if (_tabBarController.index != 1 && _tabBarController.index != 0) {
|
||||
if (_tabBarController.index != 1 &&
|
||||
_tabBarController.index != 0) {
|
||||
setState(() {
|
||||
_isSearch = true;
|
||||
});
|
||||
} else {
|
||||
context.push('/globalSearch', extra: _tabBarController.index == 0 ? true : false);
|
||||
context.push('/globalSearch',
|
||||
extra: _tabBarController.index == 0
|
||||
? true
|
||||
: false);
|
||||
}
|
||||
},
|
||||
icon: Icon(
|
||||
_tabBarController.index == 0 || _tabBarController.index == 1
|
||||
_tabBarController.index == 0 ||
|
||||
_tabBarController.index == 1
|
||||
? Icons.travel_explore_rounded
|
||||
: Icons.search_rounded,
|
||||
color: Theme.of(context).hintColor))
|
||||
|
|
@ -118,7 +126,8 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen> with TickerProvider
|
|||
icon: Icon(
|
||||
_tabBarController.index == 0 || _tabBarController.index == 1
|
||||
? Icons.filter_list_sharp
|
||||
: _tabBarController.index == 2 || _tabBarController.index == 3
|
||||
: _tabBarController.index == 2 ||
|
||||
_tabBarController.index == 3
|
||||
? Icons.translate_rounded
|
||||
: Icons.help_outline_outlined,
|
||||
color: Theme.of(context).hintColor)),
|
||||
|
|
@ -132,7 +141,11 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen> with TickerProvider
|
|||
Tab(text: l10n.anime_sources),
|
||||
Tab(
|
||||
child: Row(
|
||||
children: [Text(l10n.manga_extensions), const SizedBox(width: 8), _extensionUpdateNumbers(ref, true)],
|
||||
children: [
|
||||
Text(l10n.manga_extensions),
|
||||
const SizedBox(width: 8),
|
||||
_extensionUpdateNumbers(ref, true)
|
||||
],
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
|
|
@ -187,18 +200,23 @@ Widget _extensionUpdateNumbers(WidgetRef ref, bool isManga) {
|
|||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
final entries =
|
||||
snapshot.data!.where((element) => compareVersions(element.version!, element.versionLast!) < 0).toList();
|
||||
final entries = snapshot.data!
|
||||
.where((element) =>
|
||||
compareVersions(element.version!, element.versionLast!) < 0)
|
||||
.toList();
|
||||
return entries.isEmpty
|
||||
? Container()
|
||||
: Container(
|
||||
decoration:
|
||||
BoxDecoration(borderRadius: BorderRadius.circular(20), color: Theme.of(context).focusColor),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Theme.of(context).focusColor),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Text(
|
||||
entries.length.toString(),
|
||||
style: TextStyle(fontSize: 12, color: Theme.of(context).textTheme.bodySmall!.color),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).textTheme.bodySmall!.color),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ Mode getSourceMode(Source? source) {
|
|||
|
||||
class _CodeEditorState extends ConsumerState<CodeEditor> {
|
||||
dynamic result;
|
||||
late final source = widget.sourceId == null ? null : isar.sources.getSync(widget.sourceId!);
|
||||
late final source =
|
||||
widget.sourceId == null ? null : isar.sources.getSync(widget.sourceId!);
|
||||
late final controller = CodeController(
|
||||
text: source?.sourceCode ?? "",
|
||||
language: getSourceMode(source),
|
||||
|
|
@ -59,7 +60,8 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
bool _isLoading = false;
|
||||
String _errorText = "";
|
||||
bool _error = false;
|
||||
final _logsNotifier = ValueNotifier<List<(LoggerLevel, String, DateTime)>>([]);
|
||||
final _logsNotifier =
|
||||
ValueNotifier<List<(LoggerLevel, String, DateTime)>>([]);
|
||||
late final _logStreamController = Logger.logStreamController;
|
||||
final _scrollController = ScrollController();
|
||||
@override
|
||||
|
|
@ -96,13 +98,15 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(backgroundColor: context.primaryColor),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: context.primaryColor),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'filter');
|
||||
},
|
||||
child: Text(
|
||||
context.l10n.filter,
|
||||
style: TextStyle(color: Theme.of(context).scaffoldBackgroundColor),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).scaffoldBackgroundColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -156,7 +160,8 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
gutterStyle: const GutterStyle(
|
||||
textStyle: TextStyle(
|
||||
color: Colors.grey,
|
||||
height: 1.5, // Issue #307 fix, found in package: flutter-code-editor issue #270
|
||||
height:
|
||||
1.5, // Issue #307 fix, found in package: flutter-code-editor issue #270
|
||||
),
|
||||
showLineNumbers: true,
|
||||
),
|
||||
|
|
@ -165,7 +170,8 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
source?.sourceCode = a;
|
||||
});
|
||||
if (source != null && mounted) {
|
||||
isar.writeTxnSync(() => isar.sources.putSync(source!));
|
||||
isar.writeTxnSync(
|
||||
() => isar.sources.putSync(source!));
|
||||
}
|
||||
},
|
||||
),
|
||||
|
|
@ -182,11 +188,13 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
isExpanded: true,
|
||||
value: _serviceIndex,
|
||||
hint: Text(_getServices(context)[_serviceIndex].$1, style: const TextStyle(fontSize: 13)),
|
||||
hint: Text(_getServices(context)[_serviceIndex].$1,
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
items: _getServices(context)
|
||||
.map((e) => DropdownMenuItem(
|
||||
value: e.$2,
|
||||
child: Text(e.$1, style: const TextStyle(fontSize: 13)),
|
||||
child: Text(e.$1,
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (v) {
|
||||
|
|
@ -196,7 +204,9 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
},
|
||||
),
|
||||
),
|
||||
if (_serviceIndex == 0 || _serviceIndex == 1 || _serviceIndex == 2)
|
||||
if (_serviceIndex == 0 ||
|
||||
_serviceIndex == 1 ||
|
||||
_serviceIndex == 2)
|
||||
_textEditing("Page", context, "ex: 1", (v) {
|
||||
_page = int.tryParse(v) ?? 1;
|
||||
}),
|
||||
|
|
@ -204,8 +214,11 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
_textEditing("Query", context, "ex: one piece", (v) {
|
||||
_query = v;
|
||||
}),
|
||||
if (_serviceIndex == 3 || _serviceIndex == 4 || _serviceIndex == 5)
|
||||
_textEditing("Url", context, "ex: url of the entry", (v) {
|
||||
if (_serviceIndex == 3 ||
|
||||
_serviceIndex == 4 ||
|
||||
_serviceIndex == 5)
|
||||
_textEditing("Url", context, "ex: url of the entry",
|
||||
(v) {
|
||||
_url = v;
|
||||
}),
|
||||
Padding(
|
||||
|
|
@ -219,7 +232,8 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
source?.sourceCode = controller.text;
|
||||
});
|
||||
if (source != null && mounted) {
|
||||
isar.writeTxnSync(() => isar.sources.putSync(source!));
|
||||
isar.writeTxnSync(
|
||||
() => isar.sources.putSync(source!));
|
||||
}
|
||||
setState(() {
|
||||
result = null;
|
||||
|
|
@ -228,36 +242,52 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
_errorText = "";
|
||||
});
|
||||
if (source != null) {
|
||||
final service = getExtensionService(source!);
|
||||
final service =
|
||||
getExtensionService(source!);
|
||||
|
||||
try {
|
||||
if (_serviceIndex == 0) {
|
||||
final getManga =
|
||||
await ref.watch(getPopularProvider(source: source!, page: _page).future);
|
||||
final getManga = await ref.watch(
|
||||
getPopularProvider(
|
||||
source: source!,
|
||||
page: _page)
|
||||
.future);
|
||||
result = getManga!.toJson();
|
||||
} else if (_serviceIndex == 1) {
|
||||
final getManga = await ref
|
||||
.watch(getLatestUpdatesProvider(source: source!, page: _page).future);
|
||||
final getManga = await ref.watch(
|
||||
getLatestUpdatesProvider(
|
||||
source: source!,
|
||||
page: _page)
|
||||
.future);
|
||||
result = getManga!.toJson();
|
||||
} else if (_serviceIndex == 2) {
|
||||
final getManga = await ref.watch(searchProvider(
|
||||
source: source!, query: _query, page: _page, filterList: filterList)
|
||||
.future);
|
||||
final getManga = await ref.watch(
|
||||
searchProvider(
|
||||
source: source!,
|
||||
query: _query,
|
||||
page: _page,
|
||||
filterList: filterList)
|
||||
.future);
|
||||
result = getManga!.toJson();
|
||||
} else if (_serviceIndex == 3) {
|
||||
final getManga =
|
||||
await ref.watch(getDetailProvider(source: source!, url: _url).future);
|
||||
final getManga = await ref.watch(
|
||||
getDetailProvider(
|
||||
source: source!,
|
||||
url: _url)
|
||||
.future);
|
||||
result = getManga.toJson();
|
||||
} else if (_serviceIndex == 4) {
|
||||
result = {
|
||||
"pages": (await service.getPageList(_url))
|
||||
"pages": (await service
|
||||
.getPageList(_url))
|
||||
.map((e) => e.toJson())
|
||||
.toList(),
|
||||
};
|
||||
} else {
|
||||
result = (await service.getVideoList(_url))
|
||||
.map((e) => e.toJson())
|
||||
.toList();
|
||||
result =
|
||||
(await service.getVideoList(_url))
|
||||
.map((e) => e.toJson())
|
||||
.toList();
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
|
|
@ -298,7 +328,8 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
if (filters.isEmpty) {
|
||||
filters = filterList;
|
||||
}
|
||||
final res = await filterDialog(context);
|
||||
final res =
|
||||
await filterDialog(context);
|
||||
if (res == 'filter' && mounted) {
|
||||
setState(() {
|
||||
result = null;
|
||||
|
|
@ -306,9 +337,13 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
_error = false;
|
||||
_errorText = "";
|
||||
});
|
||||
final getManga = await ref.watch(searchProvider(
|
||||
source: source!, query: _query, page: _page, filterList: filters)
|
||||
.future);
|
||||
final getManga = await ref.watch(
|
||||
searchProvider(
|
||||
source: source!,
|
||||
query: _query,
|
||||
page: _page,
|
||||
filterList: filters)
|
||||
.future);
|
||||
result = getManga!.toJson();
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
|
@ -331,22 +366,26 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
child: _error
|
||||
? SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(_errorText),
|
||||
],
|
||||
),
|
||||
)
|
||||
: _isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
? const Center(
|
||||
child: CircularProgressIndicator())
|
||||
: result != null
|
||||
? JsonConfig(
|
||||
data: JsonConfigData(
|
||||
gap: 100,
|
||||
style: const JsonStyleScheme(
|
||||
quotation: JsonQuotation.same('"'),
|
||||
quotation:
|
||||
JsonQuotation.same('"'),
|
||||
openAtStart: false,
|
||||
arrow: Icon(Icons.arrow_forward),
|
||||
arrow:
|
||||
Icon(Icons.arrow_forward),
|
||||
depth: 4,
|
||||
),
|
||||
color: const JsonColorScheme(),
|
||||
|
|
@ -379,7 +418,10 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
itemBuilder: (context, index) {
|
||||
final value = logs[index];
|
||||
return SelectableText(value.$2,
|
||||
style: TextStyle(color: value.$1 == LoggerLevel.info ? Colors.yellow : Colors.blueAccent));
|
||||
style: TextStyle(
|
||||
color: value.$1 == LoggerLevel.info
|
||||
? Colors.yellow
|
||||
: Colors.blueAccent));
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
@ -390,7 +432,8 @@ class _CodeEditorState extends ConsumerState<CodeEditor> {
|
|||
}
|
||||
}
|
||||
|
||||
Widget _textEditing(String label, BuildContext context, String hintText, void Function(String)? onChanged) {
|
||||
Widget _textEditing(String label, BuildContext context, String hintText,
|
||||
void Function(String)? onChanged) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: TextFormField(
|
||||
|
|
@ -402,9 +445,12 @@ Widget _textEditing(String label, BuildContext context, String hintText, void Fu
|
|||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: Colors.transparent,
|
||||
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: context.dynamicThemeColor)),
|
||||
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: context.dynamicThemeColor)),
|
||||
border: OutlineInputBorder(borderSide: BorderSide(color: context.dynamicThemeColor))),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: context.dynamicThemeColor)),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: context.dynamicThemeColor)),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: context.dynamicThemeColor))),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,14 +26,17 @@ class ExtensionDetail extends ConsumerStatefulWidget {
|
|||
class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
||||
late Source source = widget.source;
|
||||
late List<SourcePreference> sourcePreference =
|
||||
getSourcePreference(source: source).map((e) => getSourcePreferenceEntry(e.key!, source.id!)).toList();
|
||||
getSourcePreference(source: source)
|
||||
.map((e) => getSourcePreferenceEntry(e.key!, source.id!))
|
||||
.toList();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(l10n.extension_detail), leading: BackButton(onPressed: () => Navigator.pop(context, source))),
|
||||
title: Text(l10n.extension_detail),
|
||||
leading: BackButton(onPressed: () => Navigator.pop(context, source))),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
@ -41,7 +44,9 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
padding: const EdgeInsets.only(top: 20),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).secondaryHeaderColor.withValues(alpha: 0.5),
|
||||
color: Theme.of(context)
|
||||
.secondaryHeaderColor
|
||||
.withValues(alpha: 0.5),
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
child: widget.source.iconUrl!.isEmpty
|
||||
? const Icon(Icons.source_outlined, size: 140)
|
||||
|
|
@ -65,7 +70,8 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
padding: const EdgeInsets.all(12),
|
||||
child: Text(
|
||||
widget.source.name!,
|
||||
style: const TextStyle(fontSize: 23, fontWeight: FontWeight.bold),
|
||||
style:
|
||||
const TextStyle(fontSize: 23, fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
|
@ -73,7 +79,8 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
padding: const EdgeInsets.all(8.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor.withValues(alpha: 0.2), borderRadius: BorderRadius.circular(10)),
|
||||
color: context.primaryColor.withValues(alpha: 0.2),
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(
|
||||
|
|
@ -83,7 +90,8 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
children: [
|
||||
Text(
|
||||
widget.source.version!,
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
l10n.version,
|
||||
|
|
@ -95,7 +103,8 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
children: [
|
||||
Text(
|
||||
completeLanguageName(widget.source.lang!),
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
l10n.language,
|
||||
|
|
@ -116,16 +125,19 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent),
|
||||
onPressed: () async {
|
||||
final res = await context.push('/codeEditor', extra: source.id);
|
||||
final res =
|
||||
await context.push('/codeEditor', extra: source.id);
|
||||
if (res != null && mounted) {
|
||||
setState(() {
|
||||
source = res as Source;
|
||||
sourcePreference = getSourcePreference(source: source)
|
||||
.map((e) => getSourcePreferenceEntry(e.key!, source.id!))
|
||||
.map((e) =>
|
||||
getSourcePreferenceEntry(e.key!, source.id!))
|
||||
.toList();
|
||||
});
|
||||
}
|
||||
|
|
@ -137,7 +149,8 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Text(
|
||||
l10n.edit_code,
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const Icon(Icons.code)
|
||||
|
|
@ -153,7 +166,8 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent),
|
||||
onPressed: () async {
|
||||
|
|
@ -164,7 +178,8 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Text(
|
||||
"Delete all cookies",
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
style: TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
)),
|
||||
),
|
||||
|
|
@ -176,9 +191,11 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
side: BorderSide(color: context.primaryColor, width: 0.3),
|
||||
side:
|
||||
BorderSide(color: context.primaryColor, width: 0.3),
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
|
|
@ -189,7 +206,8 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
title: Text(
|
||||
widget.source.name!,
|
||||
),
|
||||
content: Text(l10n.uninstall_extension(widget.source.name!)),
|
||||
content: Text(l10n
|
||||
.uninstall_extension(widget.source.name!)),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
|
|
@ -204,13 +222,15 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final sourcePrefsIds = isar.sourcePreferences
|
||||
final sourcePrefsIds = isar
|
||||
.sourcePreferences
|
||||
.filter()
|
||||
.sourceIdEqualTo(source.id!)
|
||||
.findAllSync()
|
||||
.map((e) => e.id!)
|
||||
.toList();
|
||||
final sourcePrefsStringIds = isar.sourcePreferenceStringValues
|
||||
final sourcePrefsStringIds = isar
|
||||
.sourcePreferenceStringValues
|
||||
.filter()
|
||||
.sourceIdEqualTo(source.id!)
|
||||
.findAllSync()
|
||||
|
|
@ -218,15 +238,19 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
.toList();
|
||||
isar.writeTxnSync(() {
|
||||
if (source.isObsolete ?? false) {
|
||||
isar.sources.deleteSync(widget.source.id!);
|
||||
isar.sources.deleteSync(
|
||||
widget.source.id!);
|
||||
} else {
|
||||
isar.sources.putSync(widget.source
|
||||
..sourceCode = ""
|
||||
..isAdded = false
|
||||
..isPinned = false);
|
||||
}
|
||||
isar.sourcePreferences.deleteAllSync(sourcePrefsIds);
|
||||
isar.sourcePreferenceStringValues.deleteAllSync(sourcePrefsStringIds);
|
||||
isar.sourcePreferences
|
||||
.deleteAllSync(sourcePrefsIds);
|
||||
isar.sourcePreferenceStringValues
|
||||
.deleteAllSync(
|
||||
sourcePrefsStringIds);
|
||||
});
|
||||
|
||||
Navigator.pop(ctx);
|
||||
|
|
@ -241,11 +265,13 @@ class _ExtensionDetailState extends ConsumerState<ExtensionDetail> {
|
|||
},
|
||||
child: Text(
|
||||
l10n.uninstall,
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold),
|
||||
)),
|
||||
),
|
||||
),
|
||||
SourcePreferenceWidget(sourcePreference: sourcePreference, source: source)
|
||||
SourcePreferenceWidget(
|
||||
sourcePreference: sourcePreference, source: source)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -39,7 +39,12 @@ class ExtensionsLang extends ConsumerWidget {
|
|||
} else if (value == 1) {
|
||||
enable = false;
|
||||
}
|
||||
final sources = isar.sources.filter().idIsNotNull().and().isMangaEqualTo(isManga).findAllSync();
|
||||
final sources = isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.and()
|
||||
.isMangaEqualTo(isManga)
|
||||
.findAllSync();
|
||||
for (var source in sources) {
|
||||
isar.sources.putSync(source..isActive = enable);
|
||||
}
|
||||
|
|
@ -48,7 +53,12 @@ class ExtensionsLang extends ConsumerWidget {
|
|||
],
|
||||
),
|
||||
body: StreamBuilder(
|
||||
stream: isar.sources.filter().idIsNotNull().and().isMangaEqualTo(isManga).watch(fireImmediately: true),
|
||||
stream: isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.and()
|
||||
.isMangaEqualTo(isManga)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
List<Source>? entries = snapshot.hasData ? snapshot.data : [];
|
||||
final languages = entries!.map((e) => e.lang!).toSet().toList();
|
||||
|
|
@ -70,7 +80,9 @@ class ExtensionsLang extends ConsumerWidget {
|
|||
});
|
||||
},
|
||||
value: entries
|
||||
.where((element) => element.lang!.toLowerCase() == lang.toLowerCase() && element.isActive!)
|
||||
.where((element) =>
|
||||
element.lang!.toLowerCase() == lang.toLowerCase() &&
|
||||
element.isActive!)
|
||||
.isNotEmpty,
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@ import 'package:mangayomi/modules/browse/extension/widgets/extension_list_tile_w
|
|||
class ExtensionScreen extends ConsumerStatefulWidget {
|
||||
final bool isManga;
|
||||
final String query;
|
||||
const ExtensionScreen({required this.query, required this.isManga, super.key});
|
||||
const ExtensionScreen(
|
||||
{required this.query, required this.isManga, super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<ExtensionScreen> createState() => _ExtensionScreenState();
|
||||
|
|
@ -24,7 +25,8 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
final controller = ScrollController();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final streamExtensions = ref.watch(getExtensionsStreamProvider(widget.isManga));
|
||||
final streamExtensions =
|
||||
ref.watch(getExtensionsStreamProvider(widget.isManga));
|
||||
if (widget.isManga) {
|
||||
ref.watch(fetchMangaSourcesListProvider(id: null, reFresh: false));
|
||||
} else {
|
||||
|
|
@ -33,15 +35,21 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
final l10n = l10nLocalizations(context)!;
|
||||
return RefreshIndicator(
|
||||
onRefresh: () => widget.isManga
|
||||
? ref.refresh(fetchMangaSourcesListProvider(id: null, reFresh: true).future)
|
||||
: ref.refresh(fetchAnimeSourcesListProvider(id: null, reFresh: true).future),
|
||||
? ref.refresh(
|
||||
fetchMangaSourcesListProvider(id: null, reFresh: true).future)
|
||||
: ref.refresh(
|
||||
fetchAnimeSourcesListProvider(id: null, reFresh: true).future),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: streamExtensions.when(
|
||||
data: (data) {
|
||||
data = widget.query.isEmpty
|
||||
? data
|
||||
: data.where((element) => element.name!.toLowerCase().contains(widget.query.toLowerCase())).toList();
|
||||
: data
|
||||
.where((element) => element.name!
|
||||
.toLowerCase()
|
||||
.contains(widget.query.toLowerCase()))
|
||||
.toList();
|
||||
|
||||
final notInstalledEntries = data
|
||||
.where((element) => element.version == element.versionLast!)
|
||||
|
|
@ -51,8 +59,10 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
.where((element) => element.version == element.versionLast!)
|
||||
.where((element) => element.isAdded!)
|
||||
.toList();
|
||||
final updateEntries =
|
||||
data.where((element) => compareVersions(element.version!, element.versionLast!) < 0).toList();
|
||||
final updateEntries = data
|
||||
.where((element) =>
|
||||
compareVersions(element.version!, element.versionLast!) < 0)
|
||||
.toList();
|
||||
return Scrollbar(
|
||||
interactive: true,
|
||||
controller: controller,
|
||||
|
|
@ -71,16 +81,21 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
children: [
|
||||
Text(
|
||||
l10n.update_pending,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
for (var source in updateEntries) {
|
||||
source.isManga!
|
||||
? await ref
|
||||
.watch(fetchMangaSourcesListProvider(id: source.id, reFresh: true).future)
|
||||
: await ref
|
||||
.watch(fetchAnimeSourcesListProvider(id: source.id, reFresh: true).future);
|
||||
? await ref.watch(
|
||||
fetchMangaSourcesListProvider(
|
||||
id: source.id, reFresh: true)
|
||||
.future)
|
||||
: await ref.watch(
|
||||
fetchAnimeSourcesListProvider(
|
||||
id: source.id, reFresh: true)
|
||||
.future);
|
||||
}
|
||||
},
|
||||
child: Text(l10n.update_all))
|
||||
|
|
@ -92,8 +107,10 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
source: element,
|
||||
);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) => item1.name!.compareTo(item2.name!),
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
),
|
||||
SliverGroupedListView<Source, String>(
|
||||
|
|
@ -103,26 +120,31 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Text(
|
||||
l10n.installed,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, Source element) {
|
||||
return ExtensionListTileWidget(source: element);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) => item1.name!.compareTo(item2.name!),
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
),
|
||||
SliverGroupedListView<Source, String>(
|
||||
elements: notInstalledEntries,
|
||||
groupBy: (element) => completeLanguageName(element.lang!.toLowerCase()),
|
||||
groupBy: (element) =>
|
||||
completeLanguageName(element.lang!.toLowerCase()),
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
groupByValue,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -132,8 +154,10 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
source: element,
|
||||
);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) => item1.name!.compareTo(item2.name!),
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
),
|
||||
],
|
||||
|
|
@ -144,9 +168,11 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
if (widget.isManga) {
|
||||
ref.invalidate(fetchMangaSourcesListProvider(id: null, reFresh: true));
|
||||
ref.invalidate(
|
||||
fetchMangaSourcesListProvider(id: null, reFresh: true));
|
||||
} else {
|
||||
ref.invalidate(fetchAnimeSourcesListProvider(id: null, reFresh: true));
|
||||
ref.invalidate(
|
||||
fetchAnimeSourcesListProvider(id: null, reFresh: true));
|
||||
}
|
||||
},
|
||||
child: Text(context.l10n.refresh)),
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@ import 'package:mangayomi/models/source.dart';
|
|||
import 'package:mangayomi/services/get_source_preference.dart';
|
||||
|
||||
void setPreferenceSetting(SourcePreference sourcePreference, Source source) {
|
||||
final sourcePref =
|
||||
isar.sourcePreferences.filter().sourceIdEqualTo(source.id).keyEqualTo(sourcePreference.key).findFirstSync();
|
||||
final sourcePref = isar.sourcePreferences
|
||||
.filter()
|
||||
.sourceIdEqualTo(source.id)
|
||||
.keyEqualTo(sourcePreference.key)
|
||||
.findFirstSync();
|
||||
isar.writeTxnSync(() {
|
||||
if (sourcePref != null) {
|
||||
isar.sourcePreferences.putSync(sourcePreference);
|
||||
|
|
@ -33,21 +36,30 @@ getPreferenceValue(int sourceId, String key) {
|
|||
}
|
||||
|
||||
SourcePreference getSourcePreferenceEntry(String key, int sourceId) {
|
||||
SourcePreference? sourcePreference =
|
||||
isar.sourcePreferences.filter().sourceIdEqualTo(sourceId).keyEqualTo(key).findFirstSync();
|
||||
SourcePreference? sourcePreference = isar.sourcePreferences
|
||||
.filter()
|
||||
.sourceIdEqualTo(sourceId)
|
||||
.keyEqualTo(key)
|
||||
.findFirstSync();
|
||||
if (sourcePreference == null) {
|
||||
final source = isar.sources.getSync(sourceId)!;
|
||||
sourcePreference = getSourcePreference(source: source)
|
||||
.firstWhere((element) => element.key == key, orElse: () => throw "Error when getting source preference");
|
||||
sourcePreference = getSourcePreference(source: source).firstWhere(
|
||||
(element) => element.key == key,
|
||||
orElse: () => throw "Error when getting source preference");
|
||||
setPreferenceSetting(sourcePreference, source);
|
||||
}
|
||||
|
||||
return sourcePreference;
|
||||
}
|
||||
|
||||
String getSourcePreferenceStringValue(int sourceId, String key, String defaultValue) {
|
||||
SourcePreferenceStringValue? sourcePreferenceStringValue =
|
||||
isar.sourcePreferenceStringValues.filter().sourceIdEqualTo(sourceId).keyEqualTo(key).findFirstSync();
|
||||
String getSourcePreferenceStringValue(
|
||||
int sourceId, String key, String defaultValue) {
|
||||
SourcePreferenceStringValue? sourcePreferenceStringValue = isar
|
||||
.sourcePreferenceStringValues
|
||||
.filter()
|
||||
.sourceIdEqualTo(sourceId)
|
||||
.keyEqualTo(key)
|
||||
.findFirstSync();
|
||||
if (sourcePreferenceStringValue == null) {
|
||||
setSourcePreferenceStringValue(sourceId, key, defaultValue);
|
||||
return defaultValue;
|
||||
|
|
@ -57,8 +69,11 @@ String getSourcePreferenceStringValue(int sourceId, String key, String defaultVa
|
|||
}
|
||||
|
||||
void setSourcePreferenceStringValue(int sourceId, String key, String value) {
|
||||
final sourcePref =
|
||||
isar.sourcePreferenceStringValues.filter().sourceIdEqualTo(sourceId).keyEqualTo(key).findFirstSync();
|
||||
final sourcePref = isar.sourcePreferenceStringValues
|
||||
.filter()
|
||||
.sourceIdEqualTo(sourceId)
|
||||
.keyEqualTo(key)
|
||||
.findFirstSync();
|
||||
isar.writeTxnSync(() {
|
||||
if (sourcePref != null) {
|
||||
isar.sourcePreferenceStringValues.putSync(sourcePref..value = value);
|
||||
|
|
|
|||
|
|
@ -46,11 +46,13 @@ class _CreateExtensionState extends State<CreateExtension> {
|
|||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
isExpanded: true,
|
||||
value: _languageIndex,
|
||||
hint: Text(_languages[_languageIndex], style: const TextStyle(fontSize: 13)),
|
||||
hint: Text(_languages[_languageIndex],
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
items: _languages
|
||||
.map((e) => DropdownMenuItem(
|
||||
value: _languages.indexOf(e),
|
||||
child: Text(e, style: const TextStyle(fontSize: 13)),
|
||||
child: Text(e,
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (v) {
|
||||
|
|
@ -58,7 +60,8 @@ class _CreateExtensionState extends State<CreateExtension> {
|
|||
if (v == 0) {
|
||||
_sourceCodeLanguage = SourceCodeLanguage.dart;
|
||||
} else {
|
||||
_sourceCodeLanguage = SourceCodeLanguage.javascript;
|
||||
_sourceCodeLanguage =
|
||||
SourceCodeLanguage.javascript;
|
||||
}
|
||||
_languageIndex = v!;
|
||||
});
|
||||
|
|
@ -78,12 +81,15 @@ class _CreateExtensionState extends State<CreateExtension> {
|
|||
_lang = v;
|
||||
});
|
||||
}),
|
||||
_textEditing("BaseUrl", context, "ex: https://example.com", (v) {
|
||||
_textEditing("BaseUrl", context, "ex: https://example.com",
|
||||
(v) {
|
||||
setState(() {
|
||||
_baseUrl = v;
|
||||
});
|
||||
}),
|
||||
_textEditing("ApiUrl (optional)", context, "ex: https://api.example.com", (v) {
|
||||
_textEditing(
|
||||
"ApiUrl (optional)", context, "ex: https://api.example.com",
|
||||
(v) {
|
||||
setState(() {
|
||||
_apiUrl = v;
|
||||
});
|
||||
|
|
@ -104,11 +110,13 @@ class _CreateExtensionState extends State<CreateExtension> {
|
|||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
isExpanded: true,
|
||||
value: _sourceTypeIndex,
|
||||
hint: Text(_sourceTypes[_sourceTypeIndex], style: const TextStyle(fontSize: 13)),
|
||||
hint: Text(_sourceTypes[_sourceTypeIndex],
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
items: _sourceTypes
|
||||
.map((e) => DropdownMenuItem(
|
||||
value: _sourceTypes.indexOf(e),
|
||||
child: Text(e, style: const TextStyle(fontSize: 13)),
|
||||
child: Text(e,
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (v) {
|
||||
|
|
@ -132,11 +140,15 @@ class _CreateExtensionState extends State<CreateExtension> {
|
|||
padding: const EdgeInsets.all(8.0),
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
if (_name.isNotEmpty && _lang.isNotEmpty && _baseUrl.isNotEmpty && _iconUrl.isNotEmpty) {
|
||||
if (_name.isNotEmpty &&
|
||||
_lang.isNotEmpty &&
|
||||
_baseUrl.isNotEmpty &&
|
||||
_iconUrl.isNotEmpty) {
|
||||
try {
|
||||
final id = _sourceCodeLanguage == SourceCodeLanguage.dart
|
||||
? 'mangayomi-$_lang.$_name'.hashCode
|
||||
: 'mangayomi-js-$_lang.$_name'.hashCode;
|
||||
final id =
|
||||
_sourceCodeLanguage == SourceCodeLanguage.dart
|
||||
? 'mangayomi-$_lang.$_name'.hashCode
|
||||
: 'mangayomi-js-$_lang.$_name'.hashCode;
|
||||
final checkIfExist = isar.sources.getSync(id);
|
||||
if (checkIfExist == null) {
|
||||
Source source = Source(
|
||||
|
|
@ -155,9 +167,12 @@ class _CreateExtensionState extends State<CreateExtension> {
|
|||
..sourceCodeLanguage = _sourceCodeLanguage;
|
||||
source = source
|
||||
..isLocal = true
|
||||
..sourceCode =
|
||||
_sourceCodeLanguage == SourceCodeLanguage.dart ? _dartTemplate : _jsSample(source);
|
||||
isar.writeTxnSync(() => isar.sources.putSync(source));
|
||||
..sourceCode = _sourceCodeLanguage ==
|
||||
SourceCodeLanguage.dart
|
||||
? _dartTemplate
|
||||
: _jsSample(source);
|
||||
isar.writeTxnSync(
|
||||
() => isar.sources.putSync(source));
|
||||
Navigator.pop(context);
|
||||
botToast("Source created successfully");
|
||||
} else {
|
||||
|
|
@ -177,7 +192,8 @@ class _CreateExtensionState extends State<CreateExtension> {
|
|||
}
|
||||
}
|
||||
|
||||
Widget _textEditing(String label, BuildContext context, String hintText, void Function(String)? onChanged) {
|
||||
Widget _textEditing(String label, BuildContext context, String hintText,
|
||||
void Function(String)? onChanged) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 5),
|
||||
child: TextFormField(
|
||||
|
|
@ -189,9 +205,12 @@ Widget _textEditing(String label, BuildContext context, String hintText, void Fu
|
|||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: Colors.transparent,
|
||||
enabledBorder: OutlineInputBorder(borderSide: BorderSide(color: context.secondaryColor)),
|
||||
focusedBorder: OutlineInputBorder(borderSide: BorderSide(color: context.secondaryColor)),
|
||||
border: OutlineInputBorder(borderSide: BorderSide(color: context.secondaryColor))),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: context.secondaryColor)),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: context.secondaryColor)),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: context.secondaryColor))),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ class ExtensionLangListTileWidget extends StatelessWidget {
|
|||
final String lang;
|
||||
final bool value;
|
||||
final Function(bool) onChanged;
|
||||
const ExtensionLangListTileWidget({super.key, required this.lang, required this.value, required this.onChanged});
|
||||
const ExtensionLangListTileWidget(
|
||||
{super.key,
|
||||
required this.lang,
|
||||
required this.value,
|
||||
required this.onChanged});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -14,22 +14,28 @@ import 'package:mangayomi/utils/language.dart';
|
|||
class ExtensionListTileWidget extends ConsumerStatefulWidget {
|
||||
final Source source;
|
||||
final bool isTestSource;
|
||||
const ExtensionListTileWidget({super.key, required this.source, this.isTestSource = false});
|
||||
const ExtensionListTileWidget(
|
||||
{super.key, required this.source, this.isTestSource = false});
|
||||
|
||||
@override
|
||||
ConsumerState<ExtensionListTileWidget> createState() => _ExtensionListTileWidgetState();
|
||||
ConsumerState<ExtensionListTileWidget> createState() =>
|
||||
_ExtensionListTileWidgetState();
|
||||
}
|
||||
|
||||
class _ExtensionListTileWidgetState extends ConsumerState<ExtensionListTileWidget> {
|
||||
class _ExtensionListTileWidgetState
|
||||
extends ConsumerState<ExtensionListTileWidget> {
|
||||
bool _isLoading = false;
|
||||
@override
|
||||
Widget build(
|
||||
BuildContext context,
|
||||
) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
final updateAivalable =
|
||||
widget.isTestSource ? false : compareVersions(widget.source.version!, widget.source.versionLast!) < 0;
|
||||
final sourceNotEmpty = widget.source.sourceCode != null && widget.source.sourceCode!.isNotEmpty;
|
||||
final updateAivalable = widget.isTestSource
|
||||
? false
|
||||
: compareVersions(widget.source.version!, widget.source.versionLast!) <
|
||||
0;
|
||||
final sourceNotEmpty = widget.source.sourceCode != null &&
|
||||
widget.source.sourceCode!.isNotEmpty;
|
||||
|
||||
return ListTile(
|
||||
onTap: () async {
|
||||
|
|
@ -43,8 +49,12 @@ class _ExtensionListTileWidgetState extends ConsumerState<ExtensionListTileWidge
|
|||
_isLoading = true;
|
||||
});
|
||||
widget.source.isManga!
|
||||
? await ref.watch(fetchMangaSourcesListProvider(id: widget.source.id, reFresh: true).future)
|
||||
: await ref.watch(fetchAnimeSourcesListProvider(id: widget.source.id, reFresh: true).future);
|
||||
? await ref.watch(fetchMangaSourcesListProvider(
|
||||
id: widget.source.id, reFresh: true)
|
||||
.future)
|
||||
: await ref.watch(fetchAnimeSourcesListProvider(
|
||||
id: widget.source.id, reFresh: true)
|
||||
.future);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
|
@ -56,7 +66,8 @@ class _ExtensionListTileWidgetState extends ConsumerState<ExtensionListTileWidge
|
|||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).secondaryHeaderColor.withValues(alpha: 0.5),
|
||||
color:
|
||||
Theme.of(context).secondaryHeaderColor.withValues(alpha: 0.5),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: widget.source.iconUrl!.isEmpty
|
||||
? const Icon(Icons.extension_rounded)
|
||||
|
|
@ -79,14 +90,20 @@ class _ExtensionListTileWidgetState extends ConsumerState<ExtensionListTileWidge
|
|||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(completeLanguageName(widget.source.lang!.toLowerCase()),
|
||||
style: const TextStyle(fontWeight: FontWeight.w300, fontSize: 12)),
|
||||
style:
|
||||
const TextStyle(fontWeight: FontWeight.w300, fontSize: 12)),
|
||||
const SizedBox(width: 4),
|
||||
Text(widget.source.version!, style: const TextStyle(fontWeight: FontWeight.w300, fontSize: 12)),
|
||||
Text(widget.source.version!,
|
||||
style:
|
||||
const TextStyle(fontWeight: FontWeight.w300, fontSize: 12)),
|
||||
if (widget.source.isObsolete ?? false)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Text("OBSOLETE",
|
||||
style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 12)),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12)),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
|
@ -100,8 +117,12 @@ class _ExtensionListTileWidgetState extends ConsumerState<ExtensionListTileWidge
|
|||
_isLoading = true;
|
||||
});
|
||||
widget.source.isManga!
|
||||
? await ref.watch(fetchMangaSourcesListProvider(id: widget.source.id, reFresh: true).future)
|
||||
: await ref.watch(fetchAnimeSourcesListProvider(id: widget.source.id, reFresh: true).future);
|
||||
? await ref.watch(fetchMangaSourcesListProvider(
|
||||
id: widget.source.id, reFresh: true)
|
||||
.future)
|
||||
: await ref.watch(fetchAnimeSourcesListProvider(
|
||||
id: widget.source.id, reFresh: true)
|
||||
.future);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
|||
class SourcePreferenceWidget extends StatefulWidget {
|
||||
final List<SourcePreference> sourcePreference;
|
||||
final Source source;
|
||||
const SourcePreferenceWidget({super.key, required this.sourcePreference, required this.source});
|
||||
const SourcePreferenceWidget(
|
||||
{super.key, required this.sourcePreference, required this.source});
|
||||
|
||||
@override
|
||||
State<SourcePreferenceWidget> createState() => _SourcePreferenceWidgetState();
|
||||
|
|
@ -29,7 +30,9 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
final pref = preference.editTextPreference!;
|
||||
w = ListTile(
|
||||
title: Text(pref.title!),
|
||||
subtitle: Text(pref.summary!, style: TextStyle(fontSize: 11, color: context.secondaryColor)),
|
||||
subtitle: Text(pref.summary!,
|
||||
style: TextStyle(
|
||||
fontSize: 11, color: context.secondaryColor)),
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
|
|
@ -49,7 +52,9 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
final pref = preference.checkBoxPreference!;
|
||||
w = CheckboxListTile(
|
||||
title: Text(pref.title!),
|
||||
subtitle: Text(pref.summary!, style: TextStyle(fontSize: 11, color: context.secondaryColor)),
|
||||
subtitle: Text(pref.summary!,
|
||||
style: TextStyle(
|
||||
fontSize: 11, color: context.secondaryColor)),
|
||||
value: pref.value,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
|
|
@ -63,7 +68,9 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
final pref = preference.switchPreferenceCompat!;
|
||||
w = SwitchListTile(
|
||||
title: Text(pref.title!),
|
||||
subtitle: Text(pref.summary!, style: TextStyle(fontSize: 11, color: context.secondaryColor)),
|
||||
subtitle: Text(pref.summary!,
|
||||
style: TextStyle(
|
||||
fontSize: 11, color: context.secondaryColor)),
|
||||
value: pref.value!,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
|
|
@ -78,7 +85,8 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
w = ListTile(
|
||||
title: Text(pref.title!),
|
||||
subtitle: Text(pref.entries![pref.valueIndex!],
|
||||
style: TextStyle(fontSize: 11, color: context.secondaryColor)),
|
||||
style: TextStyle(
|
||||
fontSize: 11, color: context.secondaryColor)),
|
||||
onTap: () async {
|
||||
final res = await showDialog(
|
||||
context: context,
|
||||
|
|
@ -114,7 +122,8 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
},
|
||||
child: Text(
|
||||
context.l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -132,7 +141,9 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
final pref = preference.multiSelectListPreference!;
|
||||
w = ListTile(
|
||||
title: Text(pref.title!),
|
||||
subtitle: Text(pref.summary!, style: TextStyle(fontSize: 11, color: context.secondaryColor)),
|
||||
subtitle: Text(pref.summary!,
|
||||
style: TextStyle(
|
||||
fontSize: 11, color: context.secondaryColor)),
|
||||
onTap: () {
|
||||
List<String> indexList = [];
|
||||
indexList.addAll(pref.values!);
|
||||
|
|
@ -151,20 +162,27 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
itemBuilder: (context, index) {
|
||||
return ListTileChapterFilter(
|
||||
label: pref.entries![index],
|
||||
type: indexList.contains(pref.entryValues![index]) ? 1 : 0,
|
||||
type: indexList.contains(
|
||||
pref.entryValues![index])
|
||||
? 1
|
||||
: 0,
|
||||
onTap: () {
|
||||
if (indexList.contains(pref.entryValues![index])) {
|
||||
if (indexList.contains(
|
||||
pref.entryValues![index])) {
|
||||
setState(() {
|
||||
indexList.remove(pref.entryValues![index]);
|
||||
indexList.remove(pref
|
||||
.entryValues![index]);
|
||||
pref.values = indexList;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
indexList.add(pref.entryValues![index]);
|
||||
indexList.add(pref
|
||||
.entryValues![index]);
|
||||
pref.values = indexList;
|
||||
});
|
||||
}
|
||||
setPreferenceSetting(preference, widget.source);
|
||||
setPreferenceSetting(
|
||||
preference, widget.source);
|
||||
});
|
||||
},
|
||||
)),
|
||||
|
|
@ -178,7 +196,8 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
},
|
||||
child: Text(
|
||||
context.l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
|
|
@ -186,7 +205,8 @@ class _SourcePreferenceWidgetState extends State<SourcePreferenceWidget> {
|
|||
},
|
||||
child: Text(
|
||||
context.l10n.ok,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -211,7 +231,11 @@ class EditTextDialogWidget extends StatefulWidget {
|
|||
final String dialogMessage;
|
||||
final Function(String) onChanged;
|
||||
const EditTextDialogWidget(
|
||||
{super.key, required this.text, required this.onChanged, required this.dialogTitle, required this.dialogMessage});
|
||||
{super.key,
|
||||
required this.text,
|
||||
required this.onChanged,
|
||||
required this.dialogTitle,
|
||||
required this.dialogMessage});
|
||||
|
||||
@override
|
||||
State<EditTextDialogWidget> createState() => _EditTextDialogWidgetState();
|
||||
|
|
@ -224,7 +248,10 @@ class _EditTextDialogWidgetState extends State<EditTextDialogWidget> {
|
|||
return AlertDialog(
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [Text(widget.dialogTitle), Text(widget.dialogMessage, style: const TextStyle(fontSize: 13))],
|
||||
children: [
|
||||
Text(widget.dialogTitle),
|
||||
Text(widget.dialogMessage, style: const TextStyle(fontSize: 13))
|
||||
],
|
||||
),
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.only(top: 20),
|
||||
|
|
|
|||
|
|
@ -38,7 +38,12 @@ class _GlobalSearchScreenState extends ConsumerState<GlobalSearchScreen> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Source> sourceList = ref.watch(onlyIncludePinnedSourceStateProvider)
|
||||
? isar.sources.filter().isPinnedEqualTo(true).and().isMangaEqualTo(widget.isManga).findAllSync()
|
||||
? isar.sources
|
||||
.filter()
|
||||
.isPinnedEqualTo(true)
|
||||
.and()
|
||||
.isMangaEqualTo(widget.isManga)
|
||||
.findAllSync()
|
||||
: isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
|
|
@ -123,7 +128,8 @@ class _SourceSearchScreenState extends State<SourceSearchScreen> {
|
|||
_init() async {
|
||||
try {
|
||||
_errorMessage = "";
|
||||
pages = await search(source: widget.source, page: 1, query: widget.query, filterList: []);
|
||||
pages = await search(
|
||||
source: widget.source, page: 1, query: widget.query, filterList: []);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
|
@ -214,7 +220,8 @@ class MangaGlobalImageCard extends ConsumerStatefulWidget {
|
|||
});
|
||||
|
||||
@override
|
||||
ConsumerState<MangaGlobalImageCard> createState() => _MangaGlobalImageCardState();
|
||||
ConsumerState<MangaGlobalImageCard> createState() =>
|
||||
_MangaGlobalImageCardState();
|
||||
}
|
||||
|
||||
class _MangaGlobalImageCardState extends ConsumerState<MangaGlobalImageCard>
|
||||
|
|
@ -251,16 +258,20 @@ class _MangaGlobalImageCardState extends ConsumerState<MangaGlobalImageCard>
|
|||
child: Column(children: [
|
||||
Builder(
|
||||
builder: (context) {
|
||||
if (hasData && snapshot.data!.first.customCoverImage != null) {
|
||||
return Image.memory(snapshot.data!.first.customCoverImage as Uint8List);
|
||||
if (hasData &&
|
||||
snapshot.data!.first.customCoverImage != null) {
|
||||
return Image.memory(snapshot
|
||||
.data!.first.customCoverImage as Uint8List);
|
||||
}
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
child: cachedNetworkImage(
|
||||
headers: ref
|
||||
.watch(headersProvider(source: widget.source.name!, lang: widget.source.lang!)),
|
||||
headers: ref.watch(headersProvider(
|
||||
source: widget.source.name!,
|
||||
lang: widget.source.lang!)),
|
||||
imageUrl: toImgUrl(hasData
|
||||
? snapshot.data!.first.customCoverFromTracker ??
|
||||
? snapshot.data!.first
|
||||
.customCoverFromTracker ??
|
||||
snapshot.data!.first.imageUrl ??
|
||||
""
|
||||
: getMangaDetail.imageUrl ?? ""),
|
||||
|
|
@ -281,7 +292,9 @@ class _MangaGlobalImageCardState extends ConsumerState<MangaGlobalImageCard>
|
|||
Container(
|
||||
width: 110,
|
||||
height: 150,
|
||||
color: hasData && snapshot.data!.first.favorite! ? Colors.black.withValues(alpha: 0.7) : null,
|
||||
color: hasData && snapshot.data!.first.favorite!
|
||||
? Colors.black.withValues(alpha: 0.7)
|
||||
: null,
|
||||
),
|
||||
if (hasData && snapshot.data!.first.favorite!)
|
||||
Positioned(
|
||||
|
|
@ -289,7 +302,8 @@ class _MangaGlobalImageCardState extends ConsumerState<MangaGlobalImageCard>
|
|||
left: 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Icon(Icons.collections_bookmark, color: context.primaryColor),
|
||||
child: Icon(Icons.collections_bookmark,
|
||||
color: context.primaryColor),
|
||||
))
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ class SourcesFilterScreen extends ConsumerWidget {
|
|||
SliverGroupedListView<Source, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => element.lang!,
|
||||
groupSeparatorBuilder: (String groupByValue) => SwitchListTile(
|
||||
groupSeparatorBuilder: (String groupByValue) =>
|
||||
SwitchListTile(
|
||||
value: entries
|
||||
.where((element) =>
|
||||
element.lang!.toLowerCase() == groupByValue &&
|
||||
|
|
@ -49,19 +50,24 @@ class SourcesFilterScreen extends ConsumerWidget {
|
|||
isar.writeTxnSync(() {
|
||||
for (var source in entries) {
|
||||
if (source.lang!.toLowerCase() == groupByValue) {
|
||||
isar.sources.putSync(source..isActive = val == true);
|
||||
isar.sources
|
||||
.putSync(source..isActive = val == true);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
completeLanguageName(groupByValue),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, Source element) {
|
||||
if (entries
|
||||
.where((s) => s.lang!.toLowerCase() == element.lang && s.isActive! && s.isManga == isManga)
|
||||
.where((s) =>
|
||||
s.lang!.toLowerCase() == element.lang &&
|
||||
s.isActive! &&
|
||||
s.isManga == isManga)
|
||||
.isEmpty) {
|
||||
return Container();
|
||||
}
|
||||
|
|
@ -70,7 +76,9 @@ class SourcesFilterScreen extends ConsumerWidget {
|
|||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).secondaryHeaderColor.withValues(alpha: 0.5),
|
||||
color: Theme.of(context)
|
||||
.secondaryHeaderColor
|
||||
.withValues(alpha: 0.5),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: element.iconUrl!.isEmpty
|
||||
? const Icon(Icons.source_outlined)
|
||||
|
|
@ -97,8 +105,10 @@ class SourcesFilterScreen extends ConsumerWidget {
|
|||
title: Text(element.name!),
|
||||
);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) => item1.name!.compareTo(item2.name!),
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import 'package:mangayomi/utils/language.dart';
|
|||
class SourcesScreen extends ConsumerStatefulWidget {
|
||||
final Function(int) tabIndex;
|
||||
final bool isManga;
|
||||
const SourcesScreen({required this.tabIndex, required this.isManga, super.key});
|
||||
const SourcesScreen(
|
||||
{required this.tabIndex, required this.isManga, super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<SourcesScreen> createState() => _SourcesScreenState();
|
||||
|
|
@ -50,16 +51,20 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () => widget.tabIndex(widget.isManga ? 2 : 3),
|
||||
onPressed: () =>
|
||||
widget.tabIndex(widget.isManga ? 2 : 3),
|
||||
icon: const Icon(Icons.extension_rounded),
|
||||
label: Text(context.l10n.show_extensions)),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
final lastUsedEntries = sources.where((element) => element.lastUsed!).toList();
|
||||
final isPinnedEntries = sources.where((element) => element.isPinned!).toList();
|
||||
final allEntriesWithoutIspinned = sources.where((element) => !element.isPinned!).toList();
|
||||
final lastUsedEntries =
|
||||
sources.where((element) => element.lastUsed!).toList();
|
||||
final isPinnedEntries =
|
||||
sources.where((element) => element.isPinned!).toList();
|
||||
final allEntriesWithoutIspinned =
|
||||
sources.where((element) => !element.isPinned!).toList();
|
||||
return Scrollbar(
|
||||
interactive: true,
|
||||
controller: controller,
|
||||
|
|
@ -77,7 +82,8 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
|
|||
children: [
|
||||
Text(
|
||||
l10n.last_used,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -88,8 +94,10 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
|
|||
isManga: widget.isManga,
|
||||
);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) => item1.name!.compareTo(item2.name!),
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
),
|
||||
SliverGroupedListView<Source, String>(
|
||||
|
|
@ -101,7 +109,8 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
|
|||
children: [
|
||||
Text(
|
||||
l10n.pinned,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -112,20 +121,24 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
|
|||
isManga: widget.isManga,
|
||||
);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) => item1.name!.compareTo(item2.name!),
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
),
|
||||
SliverGroupedListView<Source, String>(
|
||||
elements: allEntriesWithoutIspinned,
|
||||
groupBy: (element) => completeLanguageName(element.lang!.toLowerCase()),
|
||||
groupBy: (element) =>
|
||||
completeLanguageName(element.lang!.toLowerCase()),
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(left: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
groupByValue,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 13),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -136,8 +149,10 @@ class _SourcesScreenState extends ConsumerState<SourcesScreen> {
|
|||
isManga: widget.isManga,
|
||||
);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) => item1.name!.compareTo(item2.name!),
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -12,16 +12,23 @@ import 'package:mangayomi/utils/language.dart';
|
|||
class SourceListTile extends StatelessWidget {
|
||||
final bool isManga;
|
||||
final Source source;
|
||||
const SourceListTile({super.key, required this.source, required this.isManga});
|
||||
const SourceListTile(
|
||||
{super.key, required this.source, required this.isManga});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
final sources = isar.sources.filter().idIsNotNull().and().isMangaEqualTo(isManga).findAllSync();
|
||||
final sources = isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.and()
|
||||
.isMangaEqualTo(isManga)
|
||||
.findAllSync();
|
||||
isar.writeTxnSync(() {
|
||||
for (var src in sources) {
|
||||
isar.sources.putSync(src..lastUsed = src.id == source.id ? true : false);
|
||||
isar.sources
|
||||
.putSync(src..lastUsed = src.id == source.id ? true : false);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -31,7 +38,8 @@ class SourceListTile extends StatelessWidget {
|
|||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).secondaryHeaderColor.withValues(alpha: 0.5),
|
||||
color:
|
||||
Theme.of(context).secondaryHeaderColor.withValues(alpha: 0.5),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: source.iconUrl!.isEmpty
|
||||
? const Icon(Icons.extension_rounded)
|
||||
|
|
@ -68,8 +76,10 @@ class SourceListTile extends StatelessWidget {
|
|||
// final supportsLatest = ref.watch(supportsLatestProvider(source: source));
|
||||
// if (supportsLatest) {
|
||||
return TextButton(
|
||||
style: const ButtonStyle(padding: WidgetStatePropertyAll(EdgeInsets.all(10))),
|
||||
onPressed: () => context.push('/mangaHome', extra: (source, true)),
|
||||
style: const ButtonStyle(
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.all(10))),
|
||||
onPressed: () =>
|
||||
context.push('/mangaHome', extra: (source, true)),
|
||||
child: Text(context.l10n.latest));
|
||||
// }
|
||||
// return const SizedBox.shrink();
|
||||
|
|
@ -79,7 +89,8 @@ class SourceListTile extends StatelessWidget {
|
|||
IconButton(
|
||||
padding: const EdgeInsets.all(0),
|
||||
onPressed: () {
|
||||
isar.writeTxnSync(() => isar.sources.putSync(source..isPinned = !source.isPinned!));
|
||||
isar.writeTxnSync(() => isar.sources
|
||||
.putSync(source..isPinned = !source.isPinned!));
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.push_pin_outlined,
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ class HistoryScreen extends ConsumerStatefulWidget {
|
|||
ConsumerState<HistoryScreen> createState() => _HistoryScreenState();
|
||||
}
|
||||
|
||||
class _HistoryScreenState extends ConsumerState<HistoryScreen> with TickerProviderStateMixin {
|
||||
class _HistoryScreenState extends ConsumerState<HistoryScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late TabController _tabBarController;
|
||||
|
||||
@override
|
||||
|
|
@ -88,7 +89,8 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen> with TickerProvid
|
|||
_isSearch = true;
|
||||
});
|
||||
},
|
||||
icon: Icon(Icons.search, color: Theme.of(context).hintColor)),
|
||||
icon:
|
||||
Icon(Icons.search, color: Theme.of(context).hintColor)),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
|
|
@ -117,8 +119,10 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen> with TickerProvid
|
|||
List<History> histories = isar.historys
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.chapter(
|
||||
(q) => q.manga((q) => q.isMangaEqualTo(_tabBarController.index == 0)))
|
||||
.chapter((q) => q.manga((q) =>
|
||||
q.isMangaEqualTo(
|
||||
_tabBarController.index ==
|
||||
0)))
|
||||
.findAllSync()
|
||||
.toList();
|
||||
isar.writeTxnSync(() {
|
||||
|
|
@ -137,7 +141,8 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen> with TickerProvid
|
|||
);
|
||||
});
|
||||
},
|
||||
icon: Icon(Icons.delete_sweep_outlined, color: Theme.of(context).hintColor)),
|
||||
icon: Icon(Icons.delete_sweep_outlined,
|
||||
color: Theme.of(context).hintColor)),
|
||||
],
|
||||
bottom: TabBar(
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
|
|
@ -179,13 +184,16 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
final history = ref.watch(getAllHistoryStreamProvider(isManga: widget.isManga));
|
||||
final history =
|
||||
ref.watch(getAllHistoryStreamProvider(isManga: widget.isManga));
|
||||
return Scaffold(
|
||||
body: history.when(
|
||||
data: (data) {
|
||||
final entries = data
|
||||
.where((element) => widget.query.isNotEmpty
|
||||
? element.chapter.value!.manga.value!.name!.toLowerCase().contains(widget.query.toLowerCase())
|
||||
? element.chapter.value!.manga.value!.name!
|
||||
.toLowerCase()
|
||||
.contains(widget.query.toLowerCase())
|
||||
: true)
|
||||
.toList();
|
||||
|
||||
|
|
@ -195,7 +203,10 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
SliverGroupedListView<History, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => dateFormat(element.date!,
|
||||
context: context, ref: ref, forHistoryValue: true, useRelativeTimesTamps: false),
|
||||
context: context,
|
||||
ref: ref,
|
||||
forHistoryValue: true,
|
||||
useRelativeTimesTamps: false),
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8, left: 12),
|
||||
child: Row(
|
||||
|
|
@ -216,7 +227,8 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(0)),
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
|
|
@ -235,18 +247,26 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(7)),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(7)),
|
||||
),
|
||||
onPressed: () {
|
||||
context.push('/manga-reader/detail', extra: manga.id);
|
||||
context.push('/manga-reader/detail',
|
||||
extra: manga.id);
|
||||
},
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
child: manga.customCoverImage != null
|
||||
? Image.memory(manga.customCoverImage as Uint8List)
|
||||
? Image.memory(
|
||||
manga.customCoverImage as Uint8List)
|
||||
: cachedNetworkImage(
|
||||
headers: ref.watch(headersProvider(source: manga.source!, lang: manga.lang!)),
|
||||
imageUrl: toImgUrl(manga.customCoverFromTracker ?? manga.imageUrl ?? ""),
|
||||
headers: ref.watch(headersProvider(
|
||||
source: manga.source!,
|
||||
lang: manga.lang!)),
|
||||
imageUrl: toImgUrl(
|
||||
manga.customCoverFromTracker ??
|
||||
manga.imageUrl ??
|
||||
""),
|
||||
width: 60,
|
||||
height: 90,
|
||||
fit: BoxFit.cover),
|
||||
|
|
@ -262,33 +282,46 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
manga.name!,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context).textTheme.bodyLarge!.color,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.end,
|
||||
crossAxisAlignment:
|
||||
WrapCrossAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
chapter.name!,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Theme.of(context).textTheme.bodyLarge!.color,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
" - ${dateFormatHour(element.date!, context)}",
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Theme.of(context).textTheme.bodyLarge!.color,
|
||||
fontWeight: FontWeight.w400),
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
fontWeight:
|
||||
FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -306,43 +339,73 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
title: Text(
|
||||
l10n.remove,
|
||||
),
|
||||
content: Text(l10n.remove_history_msg),
|
||||
content: Text(
|
||||
l10n.remove_history_msg),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(
|
||||
context);
|
||||
},
|
||||
child: Text(l10n.cancel)),
|
||||
child: Text(
|
||||
l10n.cancel)),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await manga.chapters.load();
|
||||
final chapters = manga.chapters;
|
||||
await isar.writeTxn(() async {
|
||||
await isar.historys.delete(element.id!);
|
||||
for (var chapter in chapters) {
|
||||
await manga.chapters
|
||||
.load();
|
||||
final chapters =
|
||||
manga.chapters;
|
||||
await isar.writeTxn(
|
||||
() async {
|
||||
await isar
|
||||
.historys
|
||||
.delete(
|
||||
element
|
||||
.id!);
|
||||
for (var chapter
|
||||
in chapters) {
|
||||
await ref
|
||||
.read(changedItemsManagerProvider(managerId: 1)
|
||||
.read(changedItemsManagerProvider(
|
||||
managerId:
|
||||
1)
|
||||
.notifier)
|
||||
.addUpdatedChapterAsync(chapter, true, false);
|
||||
await isar.chapters.delete(chapter.id!);
|
||||
.addUpdatedChapterAsync(
|
||||
chapter,
|
||||
true,
|
||||
false);
|
||||
await isar
|
||||
.chapters
|
||||
.delete(
|
||||
chapter
|
||||
.id!);
|
||||
}
|
||||
await ref
|
||||
.read(changedItemsManagerProvider(managerId: 1)
|
||||
.read(changedItemsManagerProvider(
|
||||
managerId:
|
||||
1)
|
||||
.notifier)
|
||||
.addDeletedMangaAsync(manga, false);
|
||||
await isar.mangas.delete(manga.id!);
|
||||
.addDeletedMangaAsync(
|
||||
manga,
|
||||
false);
|
||||
await isar.mangas
|
||||
.delete(manga
|
||||
.id!);
|
||||
});
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context);
|
||||
if (context
|
||||
.mounted) {
|
||||
Navigator.pop(
|
||||
context);
|
||||
}
|
||||
},
|
||||
child: Text(l10n.remove)),
|
||||
child: Text(
|
||||
l10n.remove)),
|
||||
],
|
||||
)
|
||||
],
|
||||
|
|
@ -352,7 +415,10 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
icon: Icon(
|
||||
Icons.delete_outline,
|
||||
size: 25,
|
||||
color: Theme.of(context).textTheme.bodyLarge!.color,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
)),
|
||||
],
|
||||
),
|
||||
|
|
@ -363,7 +429,8 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
),
|
||||
);
|
||||
},
|
||||
itemComparator: (item1, item2) => item1.date!.compareTo(item2.date!),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.date!.compareTo(item2.date!),
|
||||
order: GroupedListOrder.DESC,
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
part 'isar_providers.g.dart';
|
||||
|
||||
@riverpod
|
||||
Stream<List<History>> getAllHistoryStream(Ref ref, {required bool isManga}) async* {
|
||||
Stream<List<History>> getAllHistoryStream(Ref ref,
|
||||
{required bool isManga}) async* {
|
||||
yield* isar.historys
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
|
|
@ -19,7 +20,8 @@ Stream<List<History>> getAllHistoryStream(Ref ref, {required bool isManga}) asyn
|
|||
}
|
||||
|
||||
@riverpod
|
||||
Stream<List<Update>> getAllUpdateStream(Ref ref, {required bool isManga}) async* {
|
||||
Stream<List<Update>> getAllUpdateStream(Ref ref,
|
||||
{required bool isManga}) async* {
|
||||
yield* isar.updates
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import 'package:flutter/services.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/eval/dart/model/m_bridge.dart';
|
||||
import 'package:mangayomi/eval/model/m_bridge.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/category.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
|
|
@ -1115,7 +1115,9 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
type: fromLibList.isNotEmpty ? 1 : 0,
|
||||
),
|
||||
ListTileChapterFilter(
|
||||
label: widget.isManga ? l10n.downloaded_chapters : l10n.downloaded_episodes,
|
||||
label: widget.isManga
|
||||
? l10n.downloaded_chapters
|
||||
: l10n.downloaded_episodes,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (downloadedChapsList == mangaIdsList) {
|
||||
|
|
@ -1516,7 +1518,9 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
child: Column(
|
||||
children: [
|
||||
ListTileChapterFilter(
|
||||
label: widget.isManga ? l10n.downloaded_chapters : l10n.downloaded_episodes,
|
||||
label: widget.isManga
|
||||
? l10n.downloaded_chapters
|
||||
: l10n.downloaded_episodes,
|
||||
type: downloadedChapter ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
|
|
@ -1549,7 +1553,9 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
.set(!localSource);
|
||||
}),
|
||||
ListTileChapterFilter(
|
||||
label: widget.isManga ? l10n.show_continue_reading_buttons : l10n.show_continue_watching_buttons,
|
||||
label: widget.isManga
|
||||
? l10n.show_continue_reading_buttons
|
||||
: l10n.show_continue_watching_buttons,
|
||||
type: continueReaderBtn ? 1 : 0,
|
||||
onTap: () {
|
||||
ref
|
||||
|
|
@ -1648,7 +1654,8 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
child: AppBar(
|
||||
title: Text(mangaIdsList.length.toString()),
|
||||
backgroundColor: context.primaryColor.withValues(alpha: 0.2),
|
||||
backgroundColor:
|
||||
context.primaryColor.withValues(alpha: 0.2),
|
||||
leading: IconButton(
|
||||
onPressed: () {
|
||||
ref.read(mangasListStateProvider.notifier).clear();
|
||||
|
|
|
|||
|
|
@ -8,17 +8,23 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
part 'add_torrent.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future addTorrentFromUrlOrFromFile(Ref ref, Manga? mManga, {required bool init, String? url}) async {
|
||||
Future addTorrentFromUrlOrFromFile(Ref ref, Manga? mManga,
|
||||
{required bool init, String? url}) async {
|
||||
FilePickerResult? result;
|
||||
if (url == null) {
|
||||
result =
|
||||
await FilePicker.platform.pickFiles(allowMultiple: true, type: FileType.custom, allowedExtensions: ['torrent']);
|
||||
result = await FilePicker.platform.pickFiles(
|
||||
allowMultiple: true,
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ['torrent']);
|
||||
}
|
||||
|
||||
if (result != null || url != null) {
|
||||
String torrentName = "";
|
||||
if (url != null) {
|
||||
torrentName = (await MTorrentServer().getTorrentPlaylist(url, null)).$1.first.quality;
|
||||
torrentName = (await MTorrentServer().getTorrentPlaylist(url, null))
|
||||
.$1
|
||||
.first
|
||||
.quality;
|
||||
}
|
||||
final dateNow = DateTime.now().millisecondsSinceEpoch;
|
||||
final manga = mManga ??
|
||||
|
|
@ -43,7 +49,8 @@ Future addTorrentFromUrlOrFromFile(Ref ref, Manga? mManga, {required bool init,
|
|||
manga.customCoverImage = null;
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.putSync(manga);
|
||||
final chapters = Chapter(name: torrentName, url: url, mangaId: manga.id)..manga.value = manga;
|
||||
final chapters = Chapter(name: torrentName, url: url, mangaId: manga.id)
|
||||
..manga.value = manga;
|
||||
isar.chapters.putSync(chapters);
|
||||
chapters.manga.saveSync();
|
||||
});
|
||||
|
|
@ -57,7 +64,9 @@ Future addTorrentFromUrlOrFromFile(Ref ref, Manga? mManga, {required bool init,
|
|||
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.putSync(manga);
|
||||
final chapters = Chapter(name: name, archivePath: file.path, mangaId: manga.id)..manga.value = manga;
|
||||
final chapters =
|
||||
Chapter(name: name, archivePath: file.path, mangaId: manga.id)
|
||||
..manga.value = manga;
|
||||
isar.chapters.putSync(chapters);
|
||||
chapters.manga.saveSync();
|
||||
});
|
||||
|
|
@ -68,10 +77,6 @@ Future addTorrentFromUrlOrFromFile(Ref ref, Manga? mManga, {required bool init,
|
|||
}
|
||||
|
||||
String _getName(String path) {
|
||||
return path
|
||||
.split('/')
|
||||
.last
|
||||
.split("\\")
|
||||
.last
|
||||
.replaceAll(RegExp(r'\.(mp4|mov|avi|flv|wmv|mpeg|mkv|cbz|zip|cbt|tar|torrent)'), '');
|
||||
return path.split('/').last.split("\\").last.replaceAll(
|
||||
RegExp(r'\.(mp4|mov|avi|flv|wmv|mpeg|mkv|cbz|zip|cbt|tar|torrent)'), '');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
part 'isar_providers.g.dart';
|
||||
|
||||
@riverpod
|
||||
Stream<List<Manga>> getAllMangaStream(Ref ref, {required int? categoryId, required bool? isManga}) async* {
|
||||
Stream<List<Manga>> getAllMangaStream(Ref ref,
|
||||
{required int? categoryId, required bool? isManga}) async* {
|
||||
yield* categoryId == null
|
||||
? isar.mangas
|
||||
.filter()
|
||||
|
|
@ -28,7 +29,8 @@ Stream<List<Manga>> getAllMangaStream(Ref ref, {required int? categoryId, requir
|
|||
}
|
||||
|
||||
@riverpod
|
||||
Stream<List<Manga>> getAllMangaWithoutCategoriesStream(Ref ref, {required bool? isManga}) async* {
|
||||
Stream<List<Manga>> getAllMangaWithoutCategoriesStream(Ref ref,
|
||||
{required bool? isManga}) async* {
|
||||
yield* isar.mangas
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
|
|
@ -47,5 +49,10 @@ Stream<List<Manga>> getAllMangaWithoutCategoriesStream(Ref ref, {required bool?
|
|||
|
||||
@riverpod
|
||||
Stream<List<Settings>> getSettingsStream(Ref ref) async* {
|
||||
yield* isar.settings.filter().idIsNotNull().and().idEqualTo(227).watch(fireImmediately: true);
|
||||
yield* isar.settings
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.and()
|
||||
.idEqualTo(227)
|
||||
.watch(fireImmediately: true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ class LibraryDisplayTypeState extends _$LibraryDisplayTypeState {
|
|||
return isManga ? settings.displayType : settings.animeDisplayType;
|
||||
}
|
||||
|
||||
String getLibraryDisplayTypeName(DisplayType displayType, BuildContext context) {
|
||||
String getLibraryDisplayTypeName(
|
||||
DisplayType displayType, BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
return switch (displayType) {
|
||||
DisplayType.compactGrid => l10n.compact_grid,
|
||||
|
|
@ -74,13 +75,18 @@ class LibraryGridSizeState extends _$LibraryGridSizeState {
|
|||
@riverpod
|
||||
class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
||||
@override
|
||||
int build({required List<Manga> mangaList, required bool isManga, required Settings settings}) {
|
||||
int build(
|
||||
{required List<Manga> mangaList,
|
||||
required bool isManga,
|
||||
required Settings settings}) {
|
||||
state = getType();
|
||||
return getType();
|
||||
}
|
||||
|
||||
int getType() {
|
||||
return isManga ? settings.libraryFilterMangasDownloadType! : settings.libraryFilterAnimeDownloadType ?? 0;
|
||||
return isManga
|
||||
? settings.libraryFilterMangasDownloadType!
|
||||
: settings.libraryFilterAnimeDownloadType ?? 0;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
|
|
@ -110,13 +116,18 @@ class MangaFilterDownloadedState extends _$MangaFilterDownloadedState {
|
|||
@riverpod
|
||||
class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
||||
@override
|
||||
int build({required List<Manga> mangaList, required bool isManga, required Settings settings}) {
|
||||
int build(
|
||||
{required List<Manga> mangaList,
|
||||
required bool isManga,
|
||||
required Settings settings}) {
|
||||
state = getType();
|
||||
return getType();
|
||||
}
|
||||
|
||||
int getType() {
|
||||
return isManga ? settings.libraryFilterMangasUnreadType! : settings.libraryFilterAnimeUnreadType ?? 0;
|
||||
return isManga
|
||||
? settings.libraryFilterMangasUnreadType!
|
||||
: settings.libraryFilterAnimeUnreadType ?? 0;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
|
|
@ -195,13 +206,18 @@ class MangaFilterUnreadState extends _$MangaFilterUnreadState {
|
|||
@riverpod
|
||||
class MangaFilterStartedState extends _$MangaFilterStartedState {
|
||||
@override
|
||||
int build({required List<Manga> mangaList, required bool isManga, required Settings settings}) {
|
||||
int build(
|
||||
{required List<Manga> mangaList,
|
||||
required bool isManga,
|
||||
required Settings settings}) {
|
||||
state = getType();
|
||||
return getType();
|
||||
}
|
||||
|
||||
int getType() {
|
||||
return isManga ? settings.libraryFilterMangasStartedType! : settings.libraryFilterAnimeStartedType ?? 0;
|
||||
return isManga
|
||||
? settings.libraryFilterMangasStartedType!
|
||||
: settings.libraryFilterAnimeStartedType ?? 0;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
|
|
@ -280,13 +296,18 @@ class MangaFilterStartedState extends _$MangaFilterStartedState {
|
|||
@riverpod
|
||||
class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
||||
@override
|
||||
int build({required List<Manga> mangaList, required bool isManga, required Settings settings}) {
|
||||
int build(
|
||||
{required List<Manga> mangaList,
|
||||
required bool isManga,
|
||||
required Settings settings}) {
|
||||
state = getType();
|
||||
return getType();
|
||||
}
|
||||
|
||||
int getType() {
|
||||
return isManga ? settings.libraryFilterMangasBookMarkedType! : settings.libraryFilterAnimeBookMarkedType ?? 0;
|
||||
return isManga
|
||||
? settings.libraryFilterMangasBookMarkedType!
|
||||
: settings.libraryFilterAnimeBookMarkedType ?? 0;
|
||||
}
|
||||
|
||||
void setType(int type) {
|
||||
|
|
@ -365,16 +386,22 @@ class MangaFilterBookmarkedState extends _$MangaFilterBookmarkedState {
|
|||
@riverpod
|
||||
class MangasFilterResultState extends _$MangasFilterResultState {
|
||||
@override
|
||||
bool build({required List<Manga> mangaList, required bool isManga, required Settings settings}) {
|
||||
final downloadFilterType =
|
||||
ref.watch(mangaFilterDownloadedStateProvider(mangaList: mangaList, isManga: isManga, settings: settings));
|
||||
final unreadFilterType =
|
||||
ref.watch(mangaFilterUnreadStateProvider(mangaList: mangaList, isManga: isManga, settings: settings));
|
||||
final startedFilterType =
|
||||
ref.watch(mangaFilterStartedStateProvider(mangaList: mangaList, isManga: isManga, settings: settings));
|
||||
final bookmarkedFilterType =
|
||||
ref.watch(mangaFilterBookmarkedStateProvider(mangaList: mangaList, isManga: isManga, settings: settings));
|
||||
return downloadFilterType == 0 && unreadFilterType == 0 && startedFilterType == 0 && bookmarkedFilterType == 0;
|
||||
bool build(
|
||||
{required List<Manga> mangaList,
|
||||
required bool isManga,
|
||||
required Settings settings}) {
|
||||
final downloadFilterType = ref.watch(mangaFilterDownloadedStateProvider(
|
||||
mangaList: mangaList, isManga: isManga, settings: settings));
|
||||
final unreadFilterType = ref.watch(mangaFilterUnreadStateProvider(
|
||||
mangaList: mangaList, isManga: isManga, settings: settings));
|
||||
final startedFilterType = ref.watch(mangaFilterStartedStateProvider(
|
||||
mangaList: mangaList, isManga: isManga, settings: settings));
|
||||
final bookmarkedFilterType = ref.watch(mangaFilterBookmarkedStateProvider(
|
||||
mangaList: mangaList, isManga: isManga, settings: settings));
|
||||
return downloadFilterType == 0 &&
|
||||
unreadFilterType == 0 &&
|
||||
startedFilterType == 0 &&
|
||||
bookmarkedFilterType == 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +409,9 @@ class MangasFilterResultState extends _$MangasFilterResultState {
|
|||
class LibraryShowCategoryTabsState extends _$LibraryShowCategoryTabsState {
|
||||
@override
|
||||
bool build({required bool isManga, required Settings settings}) {
|
||||
return isManga ? settings.libraryShowCategoryTabs! : settings.animeLibraryShowCategoryTabs ?? false;
|
||||
return isManga
|
||||
? settings.libraryShowCategoryTabs!
|
||||
: settings.animeLibraryShowCategoryTabs ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
|
|
@ -403,7 +432,9 @@ class LibraryShowCategoryTabsState extends _$LibraryShowCategoryTabsState {
|
|||
class LibraryDownloadedChaptersState extends _$LibraryDownloadedChaptersState {
|
||||
@override
|
||||
bool build({required bool isManga, required Settings settings}) {
|
||||
return isManga ? settings.libraryDownloadedChapters! : settings.animeLibraryDownloadedChapters ?? false;
|
||||
return isManga
|
||||
? settings.libraryDownloadedChapters!
|
||||
: settings.animeLibraryDownloadedChapters ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
|
|
@ -424,7 +455,9 @@ class LibraryDownloadedChaptersState extends _$LibraryDownloadedChaptersState {
|
|||
class LibraryLanguageState extends _$LibraryLanguageState {
|
||||
@override
|
||||
bool build({required bool isManga, required Settings settings}) {
|
||||
return isManga ? settings.libraryShowLanguage! : settings.animeLibraryShowLanguage ?? false;
|
||||
return isManga
|
||||
? settings.libraryShowLanguage!
|
||||
: settings.animeLibraryShowLanguage ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
|
|
@ -445,7 +478,9 @@ class LibraryLanguageState extends _$LibraryLanguageState {
|
|||
class LibraryLocalSourceState extends _$LibraryLocalSourceState {
|
||||
@override
|
||||
bool build({required bool isManga, required Settings settings}) {
|
||||
return isManga ? settings.libraryLocalSource ?? false : settings.animeLibraryLocalSource ?? false;
|
||||
return isManga
|
||||
? settings.libraryLocalSource ?? false
|
||||
: settings.animeLibraryLocalSource ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
|
|
@ -466,7 +501,9 @@ class LibraryLocalSourceState extends _$LibraryLocalSourceState {
|
|||
class LibraryShowNumbersOfItemsState extends _$LibraryShowNumbersOfItemsState {
|
||||
@override
|
||||
bool build({required bool isManga, required Settings settings}) {
|
||||
return isManga ? settings.libraryShowNumbersOfItems! : settings.animeLibraryShowNumbersOfItems ?? false;
|
||||
return isManga
|
||||
? settings.libraryShowNumbersOfItems!
|
||||
: settings.animeLibraryShowNumbersOfItems ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
|
|
@ -484,7 +521,8 @@ class LibraryShowNumbersOfItemsState extends _$LibraryShowNumbersOfItemsState {
|
|||
}
|
||||
|
||||
@riverpod
|
||||
class LibraryShowContinueReadingButtonState extends _$LibraryShowContinueReadingButtonState {
|
||||
class LibraryShowContinueReadingButtonState
|
||||
extends _$LibraryShowContinueReadingButtonState {
|
||||
@override
|
||||
bool build({required bool isManga, required Settings settings}) {
|
||||
return isManga
|
||||
|
|
@ -510,7 +548,9 @@ class LibraryShowContinueReadingButtonState extends _$LibraryShowContinueReading
|
|||
class SortLibraryMangaState extends _$SortLibraryMangaState {
|
||||
@override
|
||||
SortLibraryManga build({required bool isManga, required Settings settings}) {
|
||||
return isManga ? settings.sortLibraryManga ?? SortLibraryManga() : settings.sortLibraryAnime ?? SortLibraryManga();
|
||||
return isManga
|
||||
? settings.sortLibraryManga ?? SortLibraryManga()
|
||||
: settings.sortLibraryAnime ?? SortLibraryManga();
|
||||
}
|
||||
|
||||
void update(bool reverse, int index) {
|
||||
|
|
@ -611,7 +651,9 @@ class MangasSetIsReadState extends _$MangasSetIsReadState {
|
|||
for (var chapter in chapters) {
|
||||
chapter.isRead = true;
|
||||
chapter.lastPageRead = "1";
|
||||
ref.read(changedItemsManagerProvider(managerId: 1).notifier).addUpdatedChapter(chapter, false, false);
|
||||
ref
|
||||
.read(changedItemsManagerProvider(managerId: 1).notifier)
|
||||
.addUpdatedChapter(chapter, false, false);
|
||||
isar.chapters.putSync(chapter..manga.value = manga);
|
||||
chapter.manga.saveSync();
|
||||
}
|
||||
|
|
@ -636,7 +678,9 @@ class MangasSetUnReadState extends _$MangasSetUnReadState {
|
|||
isar.writeTxnSync(() {
|
||||
for (var chapter in chapters) {
|
||||
chapter.isRead = false;
|
||||
ref.read(changedItemsManagerProvider(managerId: 1).notifier).addUpdatedChapter(chapter, false, false);
|
||||
ref
|
||||
.read(changedItemsManagerProvider(managerId: 1).notifier)
|
||||
.addUpdatedChapter(chapter, false, false);
|
||||
isar.chapters.putSync(chapter..manga.value = manga);
|
||||
chapter.manga.saveSync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,14 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
part 'local_archive.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future importArchivesFromFile(Ref ref, Manga? mManga, {required bool isManga, required bool init}) async {
|
||||
Future importArchivesFromFile(Ref ref, Manga? mManga,
|
||||
{required bool isManga, required bool init}) async {
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
allowMultiple: true,
|
||||
type: FileType.custom,
|
||||
allowedExtensions: isManga ? ['cbz', 'zip'] : ['mp4', 'mov', 'avi', 'flv', 'wmv', 'mpeg', 'mkv']);
|
||||
allowedExtensions: isManga
|
||||
? ['cbz', 'zip']
|
||||
: ['mp4', 'mov', 'avi', 'flv', 'wmv', 'mpeg', 'mkv']);
|
||||
if (result != null) {
|
||||
final dateNow = DateTime.now().millisecondsSinceEpoch;
|
||||
final manga = mManga ??
|
||||
|
|
@ -36,8 +39,9 @@ Future importArchivesFromFile(Ref ref, Manga? mManga, {required bool isManga, re
|
|||
artist: '',
|
||||
);
|
||||
for (var file in result.files.reversed.toList()) {
|
||||
(String, LocalExtensionType, Uint8List, String)? data =
|
||||
isManga ? await ref.watch(getArchivesDataFromFileProvider(file.path!).future) : null;
|
||||
(String, LocalExtensionType, Uint8List, String)? data = isManga
|
||||
? await ref.watch(getArchivesDataFromFileProvider(file.path!).future)
|
||||
: null;
|
||||
String name = _getName(file.path!);
|
||||
|
||||
if (init) {
|
||||
|
|
@ -46,9 +50,11 @@ Future importArchivesFromFile(Ref ref, Manga? mManga, {required bool isManga, re
|
|||
|
||||
isar.writeTxnSync(() {
|
||||
isar.mangas.putSync(manga);
|
||||
final chapters =
|
||||
Chapter(name: isManga ? data!.$1 : name, archivePath: isManga ? data!.$4 : file.path, mangaId: manga.id)
|
||||
..manga.value = manga;
|
||||
final chapters = Chapter(
|
||||
name: isManga ? data!.$1 : name,
|
||||
archivePath: isManga ? data!.$4 : file.path,
|
||||
mangaId: manga.id)
|
||||
..manga.value = manga;
|
||||
isar.chapters.putSync(chapters);
|
||||
chapters.manga.saveSync();
|
||||
});
|
||||
|
|
@ -58,10 +64,6 @@ Future importArchivesFromFile(Ref ref, Manga? mManga, {required bool isManga, re
|
|||
}
|
||||
|
||||
String _getName(String path) {
|
||||
return path
|
||||
.split('/')
|
||||
.last
|
||||
.split("\\")
|
||||
.last
|
||||
.replaceAll(RegExp(r'\.(mp4|mov|avi|flv|wmv|mpeg|mkv|cbz|zip|cbt|tar)'), '');
|
||||
return path.split('/').last.split("\\").last.replaceAll(
|
||||
RegExp(r'\.(mp4|mov|avi|flv|wmv|mpeg|mkv|cbz|zip|cbt|tar)'), '');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||
final isManga = widget.isManga;
|
||||
|
||||
final gridSize = ref.watch(libraryGridSizeStateProvider(isManga: isManga));
|
||||
final gridSize =
|
||||
ref.watch(libraryGridSizeStateProvider(isManga: isManga));
|
||||
return GridViewWidget(
|
||||
gridSize: gridSize,
|
||||
childAspectRatio: widget.isComfortableGrid ? 0.642 : 0.69,
|
||||
|
|
@ -74,12 +75,16 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
),
|
||||
isComfortableGrid: widget.isComfortableGrid,
|
||||
image: entry.customCoverImage != null
|
||||
? MemoryImage(entry.customCoverImage as Uint8List) as ImageProvider
|
||||
? MemoryImage(entry.customCoverImage as Uint8List)
|
||||
as ImageProvider
|
||||
: CustomExtendedNetworkImageProvider(
|
||||
toImgUrl(entry.customCoverFromTracker ?? entry.imageUrl ?? ""),
|
||||
toImgUrl(entry.customCoverFromTracker ??
|
||||
entry.imageUrl ??
|
||||
""),
|
||||
headers: entry.isLocalArchive!
|
||||
? null
|
||||
: ref.watch(headersProvider(source: entry.source!, lang: entry.lang!)),
|
||||
: ref.watch(headersProvider(
|
||||
source: entry.source!, lang: entry.lang!)),
|
||||
),
|
||||
onTap: () async {
|
||||
if (isLongPressed) {
|
||||
|
|
@ -91,15 +96,19 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
lang: entry.lang!,
|
||||
mangaM: entry,
|
||||
source: entry.source!);
|
||||
ref.invalidate(getAllMangaWithoutCategoriesStreamProvider(isManga: widget.isManga));
|
||||
ref.invalidate(getAllMangaStreamProvider(categoryId: null, isManga: widget.isManga));
|
||||
ref.invalidate(getAllMangaWithoutCategoriesStreamProvider(
|
||||
isManga: widget.isManga));
|
||||
ref.invalidate(getAllMangaStreamProvider(
|
||||
categoryId: null, isManga: widget.isManga));
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
if (!isLongPressed) {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
|
||||
ref.read(isLongPressedMangaStateProvider.notifier).update(!isLongPressed);
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
} else {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
}
|
||||
|
|
@ -108,7 +117,9 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
if (!isLongPressed) {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
|
||||
ref.read(isLongPressedMangaStateProvider.notifier).update(!isLongPressed);
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
} else {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
}
|
||||
|
|
@ -132,14 +143,18 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)),
|
||||
topLeft: Radius.circular(3),
|
||||
bottomLeft: Radius.circular(3)),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 3, right: 3),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 3, right: 3),
|
||||
child: Text(
|
||||
"Local",
|
||||
style: TextStyle(color: context.dynamicBlackWhiteColor),
|
||||
style: TextStyle(
|
||||
color: context
|
||||
.dynamicBlackWhiteColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -150,14 +165,20 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
List nbrDown = [];
|
||||
if (widget.downloadedChapter) {
|
||||
isar.txnSync(() {
|
||||
for (var i = 0; i < entry.chapters.length; i++) {
|
||||
for (var i = 0;
|
||||
i < entry.chapters.length;
|
||||
i++) {
|
||||
final entries = isar.downloads
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.chapterIdEqualTo(entry.chapters.toList()[i].id)
|
||||
.chapterIdEqualTo(entry
|
||||
.chapters
|
||||
.toList()[i]
|
||||
.id)
|
||||
.findAllSync();
|
||||
|
||||
if (entries.isNotEmpty && entries.first.isDownload!) {
|
||||
if (entries.isNotEmpty &&
|
||||
entries.first.isDownload!) {
|
||||
nbrDown.add(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -166,25 +187,42 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
|
||||
return Row(
|
||||
children: [
|
||||
if (nbrDown.isNotEmpty && widget.downloadedChapter)
|
||||
if (nbrDown.isNotEmpty &&
|
||||
widget.downloadedChapter)
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)),
|
||||
color: Theme.of(context).secondaryHeaderColor,
|
||||
borderRadius:
|
||||
const BorderRadius.only(
|
||||
topLeft:
|
||||
Radius.circular(
|
||||
3),
|
||||
bottomLeft:
|
||||
Radius.circular(
|
||||
3)),
|
||||
color: Theme.of(context)
|
||||
.secondaryHeaderColor,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 3, right: 3),
|
||||
padding:
|
||||
const EdgeInsets.only(
|
||||
left: 3, right: 3),
|
||||
child: Text(
|
||||
nbrDown.length.toString(),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 3),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 3),
|
||||
child: Text(
|
||||
entry.chapters.where((element) => !element.isRead!).length.toString(),
|
||||
style: TextStyle(color: context.dynamicBlackWhiteColor),
|
||||
entry.chapters
|
||||
.where((element) =>
|
||||
!element.isRead!)
|
||||
.length
|
||||
.toString(),
|
||||
style: TextStyle(
|
||||
color: context
|
||||
.dynamicBlackWhiteColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -207,14 +245,17 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)),
|
||||
topLeft: Radius.circular(3),
|
||||
bottomLeft: Radius.circular(3)),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 3, right: 3),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 3, right: 3),
|
||||
child: Text(
|
||||
entry.lang!.toUpperCase(),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
style:
|
||||
const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -222,7 +263,8 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
)),
|
||||
],
|
||||
),
|
||||
if (!widget.isComfortableGrid && !widget.isCoverOnlyGrid) BottomTextWidget(text: entry.name!),
|
||||
if (!widget.isComfortableGrid && !widget.isCoverOnlyGrid)
|
||||
BottomTextWidget(text: entry.name!),
|
||||
if (widget.continueReaderBtn)
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
|
|
@ -236,22 +278,31 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
.filter()
|
||||
.idIsNotNull()
|
||||
.and()
|
||||
.chapter((q) => q.manga((q) => q.isMangaEqualTo(entry.isManga!)))
|
||||
.chapter((q) => q.manga((q) =>
|
||||
q.isMangaEqualTo(entry.isManga!)))
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
final entries =
|
||||
snapshot.data!.where((element) => element.mangaId == entry.id).toList();
|
||||
if (entries.isNotEmpty && !incognitoMode) {
|
||||
if (snapshot.hasData &&
|
||||
snapshot.data!.isNotEmpty) {
|
||||
final incognitoMode =
|
||||
ref.watch(incognitoModeStateProvider);
|
||||
final entries = snapshot.data!
|
||||
.where((element) =>
|
||||
element.mangaId == entry.id)
|
||||
.toList();
|
||||
if (entries.isNotEmpty &&
|
||||
!incognitoMode) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
entries.first.chapter.value!.pushToReaderView(context);
|
||||
entries.first.chapter.value!
|
||||
.pushToReaderView(context);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: context.primaryColor.withValues(alpha: 0.9),
|
||||
borderRadius:
|
||||
BorderRadius.circular(5),
|
||||
color: context.primaryColor
|
||||
.withValues(alpha: 0.9),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(7),
|
||||
|
|
@ -265,12 +316,19 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
}
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
entry.chapters.toList().reversed.toList().last.pushToReaderView(context);
|
||||
entry.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()
|
||||
.last
|
||||
.pushToReaderView(context);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: context.primaryColor.withValues(alpha: 0.9),
|
||||
borderRadius:
|
||||
BorderRadius.circular(5),
|
||||
color: context.primaryColor
|
||||
.withValues(alpha: 0.9),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(7),
|
||||
|
|
@ -284,12 +342,19 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
}
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
entry.chapters.toList().reversed.toList().last.pushToReaderView(context);
|
||||
entry.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()
|
||||
.last
|
||||
.pushToReaderView(context);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: context.primaryColor.withValues(alpha: 0.9),
|
||||
borderRadius:
|
||||
BorderRadius.circular(5),
|
||||
color: context.primaryColor
|
||||
.withValues(alpha: 0.9),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(7),
|
||||
|
|
|
|||
|
|
@ -58,15 +58,19 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
lang: entry.lang!,
|
||||
mangaM: entry,
|
||||
source: entry.source!);
|
||||
ref.invalidate(getAllMangaWithoutCategoriesStreamProvider(isManga: entry.isManga));
|
||||
ref.invalidate(getAllMangaStreamProvider(categoryId: null, isManga: entry.isManga));
|
||||
ref.invalidate(getAllMangaWithoutCategoriesStreamProvider(
|
||||
isManga: entry.isManga));
|
||||
ref.invalidate(getAllMangaStreamProvider(
|
||||
categoryId: null, isManga: entry.isManga));
|
||||
}
|
||||
},
|
||||
onLongPress: () {
|
||||
if (!isLongPressed) {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
|
||||
ref.read(isLongPressedMangaStateProvider.notifier).update(!isLongPressed);
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
} else {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
}
|
||||
|
|
@ -75,19 +79,24 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
if (!isLongPressed) {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
|
||||
ref.read(isLongPressedMangaStateProvider.notifier).update(!isLongPressed);
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
} else {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
color:
|
||||
mangaIdsList.contains(entry.id) ? context.primaryColor.withValues(alpha: 0.4) : Colors.transparent,
|
||||
color: mangaIdsList.contains(entry.id)
|
||||
? context.primaryColor.withValues(alpha: 0.4)
|
||||
: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
|
||||
child: Container(
|
||||
height: 45,
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5)),
|
||||
decoration:
|
||||
BoxDecoration(borderRadius: BorderRadius.circular(5)),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
|
@ -102,16 +111,21 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
width: 40,
|
||||
height: 45,
|
||||
image: entry.customCoverImage != null
|
||||
? MemoryImage(entry.customCoverImage as Uint8List) as ImageProvider
|
||||
? MemoryImage(entry.customCoverImage
|
||||
as Uint8List) as ImageProvider
|
||||
: CustomExtendedNetworkImageProvider(
|
||||
toImgUrl(entry.customCoverFromTracker ?? entry.imageUrl!),
|
||||
headers:
|
||||
ref.watch(headersProvider(source: entry.source!, lang: entry.lang!)),
|
||||
toImgUrl(
|
||||
entry.customCoverFromTracker ??
|
||||
entry.imageUrl!),
|
||||
headers: ref.watch(headersProvider(
|
||||
source: entry.source!,
|
||||
lang: entry.lang!)),
|
||||
),
|
||||
child: InkWell(
|
||||
child: Container(
|
||||
color: mangaIdsList.contains(entry.id)
|
||||
? context.primaryColor.withValues(alpha: 0.4)
|
||||
? context.primaryColor
|
||||
.withValues(alpha: 0.4)
|
||||
: Colors.transparent,
|
||||
)),
|
||||
),
|
||||
|
|
@ -119,7 +133,8 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10),
|
||||
child: Text(entry.name!),
|
||||
),
|
||||
)
|
||||
|
|
@ -129,8 +144,9 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Container(
|
||||
decoration:
|
||||
BoxDecoration(borderRadius: BorderRadius.circular(3), color: context.primaryColor),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
color: context.primaryColor),
|
||||
child: SizedBox(
|
||||
height: 22,
|
||||
child: Row(
|
||||
|
|
@ -139,11 +155,13 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)),
|
||||
topLeft: Radius.circular(3),
|
||||
bottomLeft: Radius.circular(3)),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.only(left: 3, right: 3),
|
||||
padding:
|
||||
EdgeInsets.only(left: 3, right: 3),
|
||||
child: Text(
|
||||
"Local",
|
||||
style: TextStyle(color: Colors.white),
|
||||
|
|
@ -157,14 +175,20 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
builder: (context, ref, child) {
|
||||
List nbrDown = [];
|
||||
isar.txnSync(() {
|
||||
for (var i = 0; i < entry.chapters.length; i++) {
|
||||
for (var i = 0;
|
||||
i < entry.chapters.length;
|
||||
i++) {
|
||||
final entries = isar.downloads
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.chapterIdEqualTo(entry.chapters.toList()[i].id)
|
||||
.chapterIdEqualTo(entry
|
||||
.chapters
|
||||
.toList()[i]
|
||||
.id)
|
||||
.findAllSync();
|
||||
|
||||
if (entries.isNotEmpty && entries.first.isDownload!) {
|
||||
if (entries.isNotEmpty &&
|
||||
entries.first.isDownload!) {
|
||||
nbrDown.add(entries.first);
|
||||
}
|
||||
}
|
||||
|
|
@ -172,15 +196,22 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
if (nbrDown.isNotEmpty) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(3), bottomLeft: Radius.circular(3)),
|
||||
color: Theme.of(context).hintColor,
|
||||
borderRadius:
|
||||
const BorderRadius.only(
|
||||
topLeft:
|
||||
Radius.circular(3),
|
||||
bottomLeft:
|
||||
Radius.circular(3)),
|
||||
color:
|
||||
Theme.of(context).hintColor,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 3, right: 3),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 3, right: 3),
|
||||
child: Text(
|
||||
nbrDown.length.toString(),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
style: const TextStyle(
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -194,7 +225,8 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
padding: const EdgeInsets.only(right: 3),
|
||||
child: Text(
|
||||
entry.chapters.length.toString(),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
style:
|
||||
const TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
if (language && entry.lang!.isNotEmpty)
|
||||
|
|
@ -203,14 +235,17 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(3), bottomRight: Radius.circular(3)),
|
||||
topRight: Radius.circular(3),
|
||||
bottomRight: Radius.circular(3)),
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 3, right: 3),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 3, right: 3),
|
||||
child: Text(
|
||||
entry.lang!.toUpperCase(),
|
||||
style: const TextStyle(color: Colors.white),
|
||||
style: const TextStyle(
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -228,13 +263,18 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
.filter()
|
||||
.idIsNotNull()
|
||||
.and()
|
||||
.chapter((q) => q.manga((q) => q.isMangaEqualTo(entry.isManga!)))
|
||||
.chapter((q) => q.manga((q) =>
|
||||
q.isMangaEqualTo(entry.isManga!)))
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
final entries =
|
||||
snapshot.data!.where((element) => element.mangaId == entry.id).toList();
|
||||
if (snapshot.hasData &&
|
||||
snapshot.data!.isNotEmpty) {
|
||||
final incognitoMode =
|
||||
ref.watch(incognitoModeStateProvider);
|
||||
final entries = snapshot.data!
|
||||
.where((element) =>
|
||||
element.mangaId == entry.id)
|
||||
.toList();
|
||||
if (entries.isNotEmpty && !incognitoMode) {
|
||||
final chap = entries.first.chapter.value!;
|
||||
return GestureDetector(
|
||||
|
|
@ -243,8 +283,10 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: context.primaryColor.withValues(alpha: 0.9),
|
||||
borderRadius:
|
||||
BorderRadius.circular(5),
|
||||
color: context.primaryColor
|
||||
.withValues(alpha: 0.9),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(7),
|
||||
|
|
@ -258,12 +300,19 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
}
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
entry.chapters.toList().reversed.toList().last.pushToReaderView(context);
|
||||
entry.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()
|
||||
.last
|
||||
.pushToReaderView(context);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: context.primaryColor.withValues(alpha: 0.9),
|
||||
borderRadius:
|
||||
BorderRadius.circular(5),
|
||||
color: context.primaryColor
|
||||
.withValues(alpha: 0.9),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(7),
|
||||
|
|
@ -277,12 +326,18 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
}
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
entry.chapters.toList().reversed.toList().last.pushToReaderView(context);
|
||||
entry.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()
|
||||
.last
|
||||
.pushToReaderView(context);
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: context.primaryColor.withValues(alpha: 0.9),
|
||||
color: context.primaryColor
|
||||
.withValues(alpha: 0.9),
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(7),
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ class _ListTileMangaCategoryState extends State<ListTileMangaCategory> {
|
|||
void initState() {
|
||||
final res = widget.mangasList.where(
|
||||
(element) {
|
||||
return element.categories == null ? false : element.categories!.contains(widget.category.id);
|
||||
return element.categories == null
|
||||
? false
|
||||
: element.categories!.contains(widget.category.id);
|
||||
},
|
||||
).toList();
|
||||
widget.res(res);
|
||||
|
|
|
|||
|
|
@ -35,8 +35,10 @@ class SeachFormTextField extends StatelessWidget {
|
|||
icon: const Icon(
|
||||
Icons.arrow_back,
|
||||
)),
|
||||
suffixIcon:
|
||||
controller.text.isEmpty ? null : IconButton(onPressed: onSuffixPressed, icon: const Icon(Icons.clear)),
|
||||
suffixIcon: controller.text.isEmpty
|
||||
? null
|
||||
: IconButton(
|
||||
onPressed: onSuffixPressed, icon: const Icon(Icons.clear)),
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ class MainScreen extends ConsumerWidget {
|
|||
final location = ref.watch(
|
||||
routerCurrentLocationStateProvider(context),
|
||||
);
|
||||
bool isReadingScreen = location == '/mangareaderview' || location == '/animePlayerView';
|
||||
bool isReadingScreen =
|
||||
location == '/mangareaderview' || location == '/animePlayerView';
|
||||
int currentIndex = switch (location) {
|
||||
null || '/MangaLibrary' => 0,
|
||||
'/AnimeLibrary' => 1,
|
||||
|
|
@ -122,7 +123,9 @@ class MainScreen extends ConsumerWidget {
|
|||
children: [
|
||||
NavigationRailTheme(
|
||||
data: NavigationRailThemeData(
|
||||
indicatorShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
|
||||
indicatorShape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(30)),
|
||||
),
|
||||
child: Builder(builder: (context) {
|
||||
return NavigationRail(
|
||||
|
|
@ -130,46 +133,73 @@ class MainScreen extends ConsumerWidget {
|
|||
useIndicator: true,
|
||||
destinations: [
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(Icons.collections_bookmark),
|
||||
icon: const Icon(Icons.collections_bookmark_outlined),
|
||||
selectedIcon: const Icon(
|
||||
Icons.collections_bookmark),
|
||||
icon: const Icon(Icons
|
||||
.collections_bookmark_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(top: 5), child: Text(l10n.manga))),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.manga))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(Icons.video_collection),
|
||||
icon: const Icon(Icons.video_collection_outlined),
|
||||
selectedIcon: const Icon(
|
||||
Icons.video_collection),
|
||||
icon: const Icon(Icons
|
||||
.video_collection_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(top: 5), child: Text(l10n.anime))),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.anime))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(Icons.new_releases),
|
||||
icon: const Icon(Icons.new_releases_outlined),
|
||||
selectedIcon:
|
||||
const Icon(Icons.new_releases),
|
||||
icon: const Icon(
|
||||
Icons.new_releases_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Stack(
|
||||
children: [
|
||||
Text(
|
||||
getHyphenatedUpdatesLabel(
|
||||
ref.watch(l10nLocaleStateProvider).languageCode,
|
||||
ref
|
||||
.watch(
|
||||
l10nLocaleStateProvider)
|
||||
.languageCode,
|
||||
l10n.updates,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
textAlign:
|
||||
TextAlign.center,
|
||||
),
|
||||
],
|
||||
))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(Icons.history),
|
||||
icon: const Icon(Icons.history_outlined),
|
||||
selectedIcon:
|
||||
const Icon(Icons.history),
|
||||
icon: const Icon(
|
||||
Icons.history_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(top: 5), child: Text(l10n.history))),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.history))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(Icons.explore),
|
||||
icon: const Icon(Icons.explore_outlined),
|
||||
selectedIcon:
|
||||
const Icon(Icons.explore),
|
||||
icon: const Icon(
|
||||
Icons.explore_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(top: 5), child: Text(l10n.browse))),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.browse))),
|
||||
NavigationRailDestination(
|
||||
selectedIcon: const Icon(Icons.more_horiz),
|
||||
icon: const Icon(Icons.more_horiz_outlined),
|
||||
selectedIcon:
|
||||
const Icon(Icons.more_horiz),
|
||||
icon: const Icon(
|
||||
Icons.more_horiz_outlined),
|
||||
label: Padding(
|
||||
padding: const EdgeInsets.only(top: 5), child: Text(l10n.more))),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 5),
|
||||
child: Text(l10n.more))),
|
||||
],
|
||||
selectedIndex: currentIndex,
|
||||
onDestinationSelected: (newIndex) {
|
||||
|
|
@ -186,8 +216,14 @@ class MainScreen extends ConsumerWidget {
|
|||
);
|
||||
}),
|
||||
),
|
||||
Positioned(right: 18, top: 140, child: _updatesTotalNumbers(ref)),
|
||||
Positioned(right: 18, top: 275, child: _extensionUpdateTotalNumbers(ref)),
|
||||
Positioned(
|
||||
right: 18,
|
||||
top: 140,
|
||||
child: _updatesTotalNumbers(ref)),
|
||||
Positioned(
|
||||
right: 18,
|
||||
top: 275,
|
||||
child: _extensionUpdateTotalNumbers(ref)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -216,27 +252,38 @@ class MainScreen extends ConsumerWidget {
|
|||
},
|
||||
child: NavigationBarTheme(
|
||||
data: NavigationBarThemeData(
|
||||
indicatorShape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
|
||||
indicatorShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(30)),
|
||||
),
|
||||
child: NavigationBar(
|
||||
animationDuration: const Duration(milliseconds: 500),
|
||||
animationDuration:
|
||||
const Duration(milliseconds: 500),
|
||||
selectedIndex: currentIndex,
|
||||
destinations: [
|
||||
NavigationDestination(
|
||||
selectedIcon: const Icon(Icons.collections_bookmark),
|
||||
icon: const Icon(Icons.collections_bookmark_outlined),
|
||||
selectedIcon:
|
||||
const Icon(Icons.collections_bookmark),
|
||||
icon: const Icon(
|
||||
Icons.collections_bookmark_outlined),
|
||||
label: l10n.manga),
|
||||
NavigationDestination(
|
||||
selectedIcon: const Icon(Icons.video_collection),
|
||||
icon: const Icon(Icons.video_collection_outlined),
|
||||
selectedIcon:
|
||||
const Icon(Icons.video_collection),
|
||||
icon: const Icon(
|
||||
Icons.video_collection_outlined),
|
||||
label: l10n.anime),
|
||||
Stack(
|
||||
children: [
|
||||
NavigationDestination(
|
||||
selectedIcon: const Icon(Icons.new_releases),
|
||||
icon: const Icon(Icons.new_releases_outlined),
|
||||
selectedIcon:
|
||||
const Icon(Icons.new_releases),
|
||||
icon: const Icon(
|
||||
Icons.new_releases_outlined),
|
||||
label: l10n.updates),
|
||||
Positioned(right: 14, top: 3, child: _updatesTotalNumbers(ref)),
|
||||
Positioned(
|
||||
right: 14,
|
||||
top: 3,
|
||||
child: _updatesTotalNumbers(ref)),
|
||||
],
|
||||
),
|
||||
NavigationDestination(
|
||||
|
|
@ -249,7 +296,10 @@ class MainScreen extends ConsumerWidget {
|
|||
selectedIcon: const Icon(Icons.explore),
|
||||
icon: const Icon(Icons.explore_outlined),
|
||||
label: l10n.browse),
|
||||
Positioned(right: 14, top: 3, child: _extensionUpdateTotalNumbers(ref)),
|
||||
Positioned(
|
||||
right: 14,
|
||||
top: 3,
|
||||
child: _extensionUpdateTotalNumbers(ref)),
|
||||
],
|
||||
),
|
||||
NavigationDestination(
|
||||
|
|
@ -286,21 +336,32 @@ class MainScreen extends ConsumerWidget {
|
|||
|
||||
Widget _extensionUpdateTotalNumbers(WidgetRef ref) {
|
||||
return StreamBuilder(
|
||||
stream: isar.sources.filter().idIsNotNull().and().isActiveEqualTo(true).watch(fireImmediately: true),
|
||||
stream: isar.sources
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.and()
|
||||
.isActiveEqualTo(true)
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
final entries =
|
||||
snapshot.data!.where((element) => compareVersions(element.version!, element.versionLast!) < 0).toList();
|
||||
final entries = snapshot.data!
|
||||
.where((element) =>
|
||||
compareVersions(element.version!, element.versionLast!) < 0)
|
||||
.toList();
|
||||
return entries.isEmpty
|
||||
? Container()
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10), color: const Color.fromARGB(255, 176, 46, 37)),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: const Color.fromARGB(255, 176, 46, 37)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 3),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 5, vertical: 3),
|
||||
child: Text(
|
||||
entries.length.toString(),
|
||||
style: TextStyle(fontSize: 10, color: Theme.of(context).textTheme.bodySmall!.color),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Theme.of(context).textTheme.bodySmall!.color),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -324,12 +385,16 @@ Widget _updatesTotalNumbers(WidgetRef ref) {
|
|||
? Container()
|
||||
: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10), color: const Color.fromARGB(255, 176, 46, 37)),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: const Color.fromARGB(255, 176, 46, 37)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 3),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 5, vertical: 3),
|
||||
child: Text(
|
||||
entries.length.toString(),
|
||||
style: TextStyle(fontSize: 10, color: Theme.of(context).textTheme.bodySmall!.color),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Theme.of(context).textTheme.bodySmall!.color),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -11,11 +11,20 @@ part 'migration.g.dart';
|
|||
|
||||
@riverpod
|
||||
Future<void> migration(Ref ref) async {
|
||||
final chapters = isar.chapters.filter().idIsNotNull().mangaIdIsNull().findAllSync();
|
||||
final downloads = isar.downloads.filter().idIsNotNull().mangaIdIsNull().findAllSync();
|
||||
final histories =
|
||||
isar.historys.filter().idIsNotNull().chapterIdIsNull().or().idIsNotNull().isMangaIsNull().findAllSync();
|
||||
final tracks = isar.tracks.filter().idIsNotNull().isMangaIsNull().findAllSync();
|
||||
final chapters =
|
||||
isar.chapters.filter().idIsNotNull().mangaIdIsNull().findAllSync();
|
||||
final downloads =
|
||||
isar.downloads.filter().idIsNotNull().mangaIdIsNull().findAllSync();
|
||||
final histories = isar.historys
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.chapterIdIsNull()
|
||||
.or()
|
||||
.idIsNotNull()
|
||||
.isMangaIsNull()
|
||||
.findAllSync();
|
||||
final tracks =
|
||||
isar.tracks.filter().idIsNotNull().isMangaIsNull().findAllSync();
|
||||
|
||||
isar.writeTxnSync(() {
|
||||
//mangaId in chapter
|
||||
|
|
|
|||
|
|
@ -8,17 +8,20 @@ import 'package:path/path.dart' as p;
|
|||
part 'archive_reader_providers.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<(String, LocalExtensionType, Uint8List, String)>> getArchivesDataFromDirectory(Ref ref, String path) async {
|
||||
Future<List<(String, LocalExtensionType, Uint8List, String)>>
|
||||
getArchivesDataFromDirectory(Ref ref, String path) async {
|
||||
return compute(_extractOnly, path);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
Future<List<LocalArchive>> getArchiveDataFromDirectory(Ref ref, String path) async {
|
||||
Future<List<LocalArchive>> getArchiveDataFromDirectory(
|
||||
Ref ref, String path) async {
|
||||
return compute(_extract, path);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
Future<(String, LocalExtensionType, Uint8List, String)> getArchivesDataFromFile(Ref ref, String path) async {
|
||||
Future<(String, LocalExtensionType, Uint8List, String)> getArchivesDataFromFile(
|
||||
Ref ref, String path) async {
|
||||
return compute(_extractArchiveOnly, path);
|
||||
}
|
||||
|
||||
|
|
@ -31,7 +34,8 @@ Future<List<LocalArchive>> _extract(String data) async {
|
|||
return await _searchForArchive(Directory(data));
|
||||
}
|
||||
|
||||
Future<List<(String, LocalExtensionType, Uint8List, String)>> _extractOnly(String data) async {
|
||||
Future<List<(String, LocalExtensionType, Uint8List, String)>> _extractOnly(
|
||||
String data) async {
|
||||
return await _searchForArchiveOnly(Directory(data));
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +57,8 @@ Future<List<LocalArchive>> _searchForArchive(Directory dir) async {
|
|||
return _list;
|
||||
}
|
||||
|
||||
Future<List<(String, LocalExtensionType, Uint8List, String)>> _searchForArchiveOnly(Directory dir) async {
|
||||
Future<List<(String, LocalExtensionType, Uint8List, String)>>
|
||||
_searchForArchiveOnly(Directory dir) async {
|
||||
List<FileSystemEntity> entities = dir.listSync();
|
||||
for (FileSystemEntity entity in entities) {
|
||||
if (entity is Directory) {
|
||||
|
|
@ -99,7 +104,8 @@ LocalArchive _extractArchive(String path) {
|
|||
Archive? archive;
|
||||
final inputStream = InputFileStream(path);
|
||||
final extensionType = localArchive.extensionType;
|
||||
if (extensionType == LocalExtensionType.cbt || extensionType == LocalExtensionType.tar) {
|
||||
if (extensionType == LocalExtensionType.cbt ||
|
||||
extensionType == LocalExtensionType.tar) {
|
||||
archive = TarDecoder().decodeStream(inputStream);
|
||||
} else {
|
||||
archive = ZipDecoder().decodeStream(inputStream);
|
||||
|
|
@ -125,27 +131,35 @@ LocalArchive _extractArchive(String path) {
|
|||
return localArchive;
|
||||
}
|
||||
|
||||
(String, LocalExtensionType, Uint8List, String) _extractArchiveOnly(String path) {
|
||||
final extensionType = setTypeExtension(p.extension(path).replaceFirst('.', ''));
|
||||
(String, LocalExtensionType, Uint8List, String) _extractArchiveOnly(
|
||||
String path) {
|
||||
final extensionType =
|
||||
setTypeExtension(p.extension(path).replaceFirst('.', ''));
|
||||
final name = p.basenameWithoutExtension(path);
|
||||
Uint8List? coverImage;
|
||||
|
||||
Archive? archive;
|
||||
final inputStream = InputFileStream(path);
|
||||
|
||||
if (extensionType == LocalExtensionType.cbt || extensionType == LocalExtensionType.tar) {
|
||||
if (extensionType == LocalExtensionType.cbt ||
|
||||
extensionType == LocalExtensionType.tar) {
|
||||
archive = TarDecoder().decodeStream(inputStream);
|
||||
} else {
|
||||
archive = ZipDecoder().decodeStream(inputStream);
|
||||
}
|
||||
|
||||
final cover = archive.files.where((file) => file.isFile && _isImageFile(file.name) && file.name.contains("cover"));
|
||||
final cover = archive.files.where((file) =>
|
||||
file.isFile && _isImageFile(file.name) && file.name.contains("cover"));
|
||||
|
||||
if (cover.isNotEmpty) {
|
||||
coverImage = cover.first.content;
|
||||
} else {
|
||||
List<ArchiveFile> lArchive =
|
||||
archive.files.where((file) => file.isFile && _isImageFile(file.name) && !file.name.contains("cover")).toList();
|
||||
List<ArchiveFile> lArchive = archive.files
|
||||
.where((file) =>
|
||||
file.isFile &&
|
||||
_isImageFile(file.name) &&
|
||||
!file.name.contains("cover"))
|
||||
.toList();
|
||||
lArchive.sort(
|
||||
(a, b) => a.name.compareTo(b.name),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ class _MangaReaderDetailState extends ConsumerState<MangaReaderDetail> {
|
|||
|
||||
_init() async {
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
await ref.read(updateMangaDetailProvider(mangaId: widget.mangaId, isInit: true).future);
|
||||
await ref.read(
|
||||
updateMangaDetailProvider(mangaId: widget.mangaId, isInit: true)
|
||||
.future);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
|
@ -37,7 +39,8 @@ class _MangaReaderDetailState extends ConsumerState<MangaReaderDetail> {
|
|||
bool _isLoading = true;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final manga = ref.watch(getMangaDetailStreamProvider(mangaId: widget.mangaId));
|
||||
final manga =
|
||||
ref.watch(getMangaDetailStreamProvider(mangaId: widget.mangaId));
|
||||
return Scaffold(
|
||||
body: manga.when(
|
||||
data: (manga) {
|
||||
|
|
@ -59,7 +62,9 @@ class _MangaReaderDetailState extends ConsumerState<MangaReaderDetail> {
|
|||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
if (sourceExist && !_isLoading) {
|
||||
await ref.read(updateMangaDetailProvider(mangaId: manga.id, isInit: false).future);
|
||||
await ref.read(updateMangaDetailProvider(
|
||||
mangaId: manga.id, isInit: false)
|
||||
.future);
|
||||
}
|
||||
},
|
||||
child: Stack(
|
||||
|
|
@ -73,7 +78,9 @@ class _MangaReaderDetailState extends ConsumerState<MangaReaderDetail> {
|
|||
_isLoading = true;
|
||||
});
|
||||
if (sourceExist) {
|
||||
await ref.read(updateMangaDetailProvider(mangaId: manga.id, isInit: false).future);
|
||||
await ref.read(updateMangaDetailProvider(
|
||||
mangaId: manga.id, isInit: false)
|
||||
.future);
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import 'package:flutter/rendering.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/eval/dart/model/m_bridge.dart';
|
||||
import 'package:mangayomi/eval/model/m_bridge.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/download.dart';
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
return textPainter.size;
|
||||
}
|
||||
|
||||
double calculateDynamicButtonWidth(String text, TextStyle textStyle, double padding) {
|
||||
double calculateDynamicButtonWidth(
|
||||
String text, TextStyle textStyle, double padding) {
|
||||
final textSize = measureText(text, textStyle);
|
||||
return textSize.width + padding;
|
||||
}
|
||||
|
|
@ -57,20 +58,28 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
final isExtended = ref.watch(isExtendedStateProvider);
|
||||
return ref.watch(isLongPressedStateProvider) == true
|
||||
? Container()
|
||||
: chaptersList.isNotEmpty && chaptersList.where((element) => !element.isRead!).toList().isNotEmpty
|
||||
: chaptersList.isNotEmpty &&
|
||||
chaptersList
|
||||
.where((element) => !element.isRead!)
|
||||
.toList()
|
||||
.isNotEmpty
|
||||
? StreamBuilder(
|
||||
stream: isar.historys
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.and()
|
||||
.chapter((q) => q.manga((q) => q.isMangaEqualTo(widget.manga.isManga!)))
|
||||
.chapter((q) => q.manga(
|
||||
(q) => q.isMangaEqualTo(widget.manga.isManga!)))
|
||||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
String buttonLabel = widget.manga.isManga! ? l10n.read : l10n.watch;
|
||||
String buttonLabel =
|
||||
widget.manga.isManga! ? l10n.read : l10n.watch;
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
final incognitoMode =
|
||||
ref.watch(incognitoModeStateProvider);
|
||||
final entries = snapshot.data!
|
||||
.where((element) => element.mangaId == widget.manga.id)
|
||||
.where((element) =>
|
||||
element.mangaId == widget.manga.id)
|
||||
.toList()
|
||||
.reversed
|
||||
.toList();
|
||||
|
|
@ -83,8 +92,12 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
onPressed: () {
|
||||
chap.pushToReaderView(context);
|
||||
},
|
||||
textWidth: measureText(l10n.resume, Theme.of(context).textTheme.labelLarge!).width,
|
||||
width: calculateDynamicButtonWidth(l10n.resume, Theme.of(context).textTheme.labelLarge!,
|
||||
textWidth: measureText(l10n.resume,
|
||||
Theme.of(context).textTheme.labelLarge!)
|
||||
.width,
|
||||
width: calculateDynamicButtonWidth(
|
||||
l10n.resume,
|
||||
Theme.of(context).textTheme.labelLarge!,
|
||||
50), // 50 Padding, else RenderFlex overflow Exception
|
||||
);
|
||||
}
|
||||
|
|
@ -92,10 +105,19 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
isExtended: !isExtended,
|
||||
label: buttonLabel,
|
||||
onPressed: () {
|
||||
widget.manga.chapters.toList().reversed.toList().last.pushToReaderView(context);
|
||||
widget.manga.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()
|
||||
.last
|
||||
.pushToReaderView(context);
|
||||
},
|
||||
textWidth: measureText(buttonLabel, Theme.of(context).textTheme.labelLarge!).width,
|
||||
width: calculateDynamicButtonWidth(buttonLabel, Theme.of(context).textTheme.labelLarge!,
|
||||
textWidth: measureText(buttonLabel,
|
||||
Theme.of(context).textTheme.labelLarge!)
|
||||
.width,
|
||||
width: calculateDynamicButtonWidth(
|
||||
buttonLabel,
|
||||
Theme.of(context).textTheme.labelLarge!,
|
||||
50), // 50 Padding, else RenderFlex overflow Exception
|
||||
);
|
||||
}
|
||||
|
|
@ -103,10 +125,19 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
isExtended: !isExtended,
|
||||
label: buttonLabel,
|
||||
onPressed: () {
|
||||
widget.manga.chapters.toList().reversed.toList().last.pushToReaderView(context);
|
||||
widget.manga.chapters
|
||||
.toList()
|
||||
.reversed
|
||||
.toList()
|
||||
.last
|
||||
.pushToReaderView(context);
|
||||
},
|
||||
textWidth: measureText(buttonLabel, Theme.of(context).textTheme.labelLarge!).width,
|
||||
width: calculateDynamicButtonWidth(buttonLabel, Theme.of(context).textTheme.labelLarge!,
|
||||
textWidth: measureText(buttonLabel,
|
||||
Theme.of(context).textTheme.labelLarge!)
|
||||
.width,
|
||||
width: calculateDynamicButtonWidth(
|
||||
buttonLabel,
|
||||
Theme.of(context).textTheme.labelLarge!,
|
||||
50), // 50 Padding, else RenderFlex overflow Exception
|
||||
);
|
||||
},
|
||||
|
|
@ -155,7 +186,9 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
? SizedBox(
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor, elevation: 0),
|
||||
backgroundColor:
|
||||
Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 0),
|
||||
onPressed: () {
|
||||
final model = widget.manga;
|
||||
isar.writeTxnSync(() {
|
||||
|
|
@ -183,8 +216,9 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
),
|
||||
)
|
||||
: ElevatedButton(
|
||||
style:
|
||||
ElevatedButton.styleFrom(backgroundColor: Theme.of(context).scaffoldBackgroundColor, elevation: 0),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 0),
|
||||
onPressed: () {
|
||||
final checkCategoryList = isar.categorys
|
||||
.filter()
|
||||
|
|
@ -215,7 +249,8 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
),
|
||||
Text(
|
||||
l10n.add_to_library,
|
||||
style: TextStyle(color: context.secondaryColor, fontSize: 11),
|
||||
style: TextStyle(
|
||||
color: context.secondaryColor, fontSize: 11),
|
||||
textAlign: TextAlign.center,
|
||||
)
|
||||
],
|
||||
|
|
@ -264,14 +299,17 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
label: entries[index].name!,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
if (categoryIds.contains(entries[index].id)) {
|
||||
if (categoryIds
|
||||
.contains(entries[index].id)) {
|
||||
categoryIds.remove(entries[index].id);
|
||||
} else {
|
||||
categoryIds.add(entries[index].id!);
|
||||
}
|
||||
});
|
||||
},
|
||||
type: categoryIds.contains(entries[index].id) ? 1 : 0,
|
||||
type: categoryIds.contains(entries[index].id)
|
||||
? 1
|
||||
: 0,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
@ -285,7 +323,8 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.push("/categories", extra: (true, widget.manga.isManga! ? 0 : 1));
|
||||
context.push("/categories",
|
||||
extra: (true, widget.manga.isManga! ? 0 : 1));
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(l10n.edit)),
|
||||
|
|
@ -305,7 +344,8 @@ class _MangaDetailsViewState extends ConsumerState<MangaDetailsView> {
|
|||
isar.writeTxnSync(() {
|
||||
model.favorite = true;
|
||||
model.categories = categoryIds;
|
||||
model.dateAdded = DateTime.now().millisecondsSinceEpoch;
|
||||
model.dateAdded =
|
||||
DateTime.now().millisecondsSinceEpoch;
|
||||
isar.mangas.putSync(model);
|
||||
});
|
||||
if (mounted) {
|
||||
|
|
|
|||
|
|
@ -16,5 +16,8 @@ Stream<List<Chapter>> getChaptersStream(
|
|||
Ref ref, {
|
||||
required int mangaId,
|
||||
}) async* {
|
||||
yield* isar.chapters.filter().manga((q) => q.idEqualTo(mangaId)).watch(fireImmediately: true);
|
||||
yield* isar.chapters
|
||||
.filter()
|
||||
.manga((q) => q.idEqualTo(mangaId))
|
||||
.watch(fireImmediately: true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,8 @@ class ChapterFilterDownloadedState extends _$ChapterFilterDownloadedState {
|
|||
}
|
||||
chapterFilterDownloadedList.add(value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..chapterFilterDownloadedList = chapterFilterDownloadedList);
|
||||
isar.settings.putSync(
|
||||
settings..chapterFilterDownloadedList = chapterFilterDownloadedList);
|
||||
});
|
||||
|
||||
state = type;
|
||||
|
|
@ -211,7 +212,8 @@ class ChapterFilterUnreadState extends _$ChapterFilterUnreadState {
|
|||
}
|
||||
chapterFilterUnreadList.add(value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..chapterFilterUnreadList = chapterFilterUnreadList);
|
||||
isar.settings
|
||||
.putSync(settings..chapterFilterUnreadList = chapterFilterUnreadList);
|
||||
});
|
||||
state = type;
|
||||
}
|
||||
|
|
@ -262,7 +264,8 @@ class ChapterFilterBookmarkedState extends _$ChapterFilterBookmarkedState {
|
|||
}
|
||||
chapterFilterBookmarkedList.add(value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..chapterFilterBookmarkedList = chapterFilterBookmarkedList);
|
||||
isar.settings.putSync(
|
||||
settings..chapterFilterBookmarkedList = chapterFilterBookmarkedList);
|
||||
});
|
||||
state = type;
|
||||
}
|
||||
|
|
@ -282,12 +285,18 @@ class ChapterFilterBookmarkedState extends _$ChapterFilterBookmarkedState {
|
|||
class ChapterFilterResultState extends _$ChapterFilterResultState {
|
||||
@override
|
||||
bool build({required Manga manga}) {
|
||||
final downloadFilterType = ref.watch(chapterFilterDownloadedStateProvider(mangaId: manga.id!));
|
||||
final unreadFilterType = ref.watch(chapterFilterUnreadStateProvider(mangaId: manga.id!));
|
||||
final downloadFilterType =
|
||||
ref.watch(chapterFilterDownloadedStateProvider(mangaId: manga.id!));
|
||||
final unreadFilterType =
|
||||
ref.watch(chapterFilterUnreadStateProvider(mangaId: manga.id!));
|
||||
|
||||
final bookmarkedFilterType = ref.watch(chapterFilterBookmarkedStateProvider(mangaId: manga.id!));
|
||||
final bookmarkedFilterType =
|
||||
ref.watch(chapterFilterBookmarkedStateProvider(mangaId: manga.id!));
|
||||
final scanlators = ref.watch(scanlatorsFilterStateProvider(manga));
|
||||
return downloadFilterType == 0 && unreadFilterType == 0 && bookmarkedFilterType == 0 && scanlators.$2.isEmpty;
|
||||
return downloadFilterType == 0 &&
|
||||
unreadFilterType == 0 &&
|
||||
bookmarkedFilterType == 0 &&
|
||||
scanlators.$2.isEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -301,7 +310,9 @@ class ChapterSetIsBookmarkState extends _$ChapterSetIsBookmarkState {
|
|||
isar.writeTxnSync(() {
|
||||
for (var chapter in chapters) {
|
||||
chapter.isBookmarked = !chapter.isBookmarked!;
|
||||
ref.read(changedItemsManagerProvider(managerId: 1).notifier).addUpdatedChapter(chapter, false, false);
|
||||
ref
|
||||
.read(changedItemsManagerProvider(managerId: 1).notifier)
|
||||
.addUpdatedChapter(chapter, false, false);
|
||||
isar.chapters.putSync(chapter..manga.value = manga);
|
||||
chapter.manga.saveSync();
|
||||
}
|
||||
|
|
@ -321,7 +332,9 @@ class ChapterSetIsReadState extends _$ChapterSetIsReadState {
|
|||
isar.writeTxnSync(() {
|
||||
for (var chapter in chapters) {
|
||||
chapter.isRead = !chapter.isRead!;
|
||||
ref.read(changedItemsManagerProvider(managerId: 1).notifier).addUpdatedChapter(chapter, false, false);
|
||||
ref
|
||||
.read(changedItemsManagerProvider(managerId: 1).notifier)
|
||||
.addUpdatedChapter(chapter, false, false);
|
||||
isar.chapters.putSync(chapter..manga.value = manga);
|
||||
chapter.manga.saveSync();
|
||||
}
|
||||
|
|
@ -340,7 +353,11 @@ class ChapterSetDownloadState extends _$ChapterSetDownloadState {
|
|||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
isar.txnSync(() {
|
||||
for (var chapter in ref.watch(chaptersListStateProvider)) {
|
||||
final entries = isar.downloads.filter().idIsNotNull().chapterIdEqualTo(chapter.id).findAllSync();
|
||||
final entries = isar.downloads
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.chapterIdEqualTo(chapter.id)
|
||||
.findAllSync();
|
||||
if (entries.isEmpty || !entries.first.isDownload!) {
|
||||
ref.watch(downloadChapterProvider(chapter: chapter));
|
||||
}
|
||||
|
|
@ -378,7 +395,8 @@ class ScanlatorsFilterState extends _$ScanlatorsFilterState {
|
|||
List<String> _getScanlators() {
|
||||
List<String> scanlators = [];
|
||||
for (var a in manga.chapters.toList()) {
|
||||
if ((a.scanlator?.isNotEmpty ?? false) && !scanlators.contains(a.scanlator)) {
|
||||
if ((a.scanlator?.isNotEmpty ?? false) &&
|
||||
!scanlators.contains(a.scanlator)) {
|
||||
scanlators.add(a.scanlator!);
|
||||
}
|
||||
}
|
||||
|
|
@ -399,14 +417,16 @@ class ScanlatorsFilterState extends _$ScanlatorsFilterState {
|
|||
}
|
||||
filterScanlatorList.add(value);
|
||||
isar.writeTxnSync(() {
|
||||
isar.settings.putSync(settings..filterScanlatorList = filterScanlatorList);
|
||||
isar.settings
|
||||
.putSync(settings..filterScanlatorList = filterScanlatorList);
|
||||
});
|
||||
state = (_getScanlators(), _getFilterScanlator()!, filterScanlators);
|
||||
}
|
||||
|
||||
List<String>? _getFilterScanlator() {
|
||||
final scanlators = isar.settings.getSync(227)!.filterScanlatorList ?? [];
|
||||
final filter = scanlators.where((element) => element.mangaId == manga.id).toList();
|
||||
final filter =
|
||||
scanlators.where((element) => element.mangaId == manga.id).toList();
|
||||
return filter.isEmpty ? null : filter.first.scanlators;
|
||||
}
|
||||
|
||||
|
|
@ -421,6 +441,7 @@ class ScanlatorsFilterState extends _$ScanlatorsFilterState {
|
|||
} else {
|
||||
scanlatorFilteredList.add(scanlator);
|
||||
}
|
||||
state = (_getScanlators(), _getFilterScanlator() ?? [], scanlatorFilteredList);
|
||||
state =
|
||||
(_getScanlators(), _getFilterScanlator() ?? [], scanlatorFilteredList);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,19 +18,41 @@ class TrackState extends _$TrackState {
|
|||
Track? updateTrack;
|
||||
if (track!.syncId == 1) {
|
||||
updateTrack = isManga!
|
||||
? await ref.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga).notifier).updateManga(track!)
|
||||
: await ref.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga).notifier).updateAnime(track!);
|
||||
? await ref
|
||||
.read(
|
||||
myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.updateManga(track!)
|
||||
: await ref
|
||||
.read(
|
||||
myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.updateAnime(track!);
|
||||
} else if (track!.syncId == 2) {
|
||||
updateTrack = isManga!
|
||||
? await ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).updateLibManga(track!)
|
||||
: await ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).updateLibAnime(track!);
|
||||
? await ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.updateLibManga(track!)
|
||||
: await ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.updateLibAnime(track!);
|
||||
} else if (track!.syncId == 3) {
|
||||
updateTrack = isManga!
|
||||
? await ref.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga).notifier).updateLibManga(track!)
|
||||
: await ref.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga).notifier).updateLibAnime(track!);
|
||||
? await ref
|
||||
.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.updateLibManga(track!)
|
||||
: await ref
|
||||
.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.updateLibAnime(track!);
|
||||
}
|
||||
|
||||
ref.read(tracksProvider(syncId: track!.syncId!).notifier).updateTrackManga(updateTrack!, isManga);
|
||||
ref
|
||||
.read(tracksProvider(syncId: track!.syncId!).notifier)
|
||||
.updateTrackManga(updateTrack!, isManga);
|
||||
}
|
||||
|
||||
int getScoreMaxValue() {
|
||||
|
|
@ -38,7 +60,11 @@ class TrackState extends _$TrackState {
|
|||
if (track!.syncId == 1 || track!.syncId == 3) {
|
||||
maxValue = 10;
|
||||
} else if (track!.syncId == 2) {
|
||||
maxValue = ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).getScoreValue().$1;
|
||||
maxValue = ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.getScoreValue()
|
||||
.$1;
|
||||
}
|
||||
return maxValue!;
|
||||
}
|
||||
|
|
@ -46,7 +72,9 @@ class TrackState extends _$TrackState {
|
|||
String getTextMapper(String numberText) {
|
||||
if (track!.syncId == 1 || track!.syncId == 3) {
|
||||
} else if (track!.syncId == 2) {
|
||||
numberText = ref.read(anilistProvider(syncId: 2, isManga: isManga).notifier).displayScore(int.parse(numberText));
|
||||
numberText = ref
|
||||
.read(anilistProvider(syncId: 2, isManga: isManga).notifier)
|
||||
.displayScore(int.parse(numberText));
|
||||
}
|
||||
return numberText;
|
||||
}
|
||||
|
|
@ -56,7 +84,11 @@ class TrackState extends _$TrackState {
|
|||
if (track!.syncId == 1 || track!.syncId == 3) {
|
||||
step = 1;
|
||||
} else if (track!.syncId == 2) {
|
||||
step = ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).getScoreValue().$2;
|
||||
step = ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.getScoreValue()
|
||||
.$2;
|
||||
}
|
||||
return step!;
|
||||
}
|
||||
|
|
@ -66,12 +98,15 @@ class TrackState extends _$TrackState {
|
|||
if (track!.syncId == 1 || track!.syncId == 3) {
|
||||
result = score.toString();
|
||||
} else if (track!.syncId == 2) {
|
||||
result = ref.read(anilistProvider(syncId: 2, isManga: isManga).notifier).displayScore(score);
|
||||
result = ref
|
||||
.read(anilistProvider(syncId: 2, isManga: isManga).notifier)
|
||||
.displayScore(score);
|
||||
}
|
||||
return result!;
|
||||
}
|
||||
|
||||
Future setTrackSearch(TrackSearch trackSearch, int mangaId, int syncId) async {
|
||||
Future setTrackSearch(
|
||||
TrackSearch trackSearch, int mangaId, int syncId) async {
|
||||
Track? findManga;
|
||||
final track = Track(
|
||||
mangaId: mangaId,
|
||||
|
|
@ -86,20 +121,36 @@ class TrackState extends _$TrackState {
|
|||
startedReadingDate: 0,
|
||||
finishedReadingDate: 0);
|
||||
if (syncId == 1) {
|
||||
findManga = await ref.read(myAnimeListProvider(syncId: syncId, isManga: isManga).notifier).findManga(track);
|
||||
findManga = await ref
|
||||
.read(myAnimeListProvider(syncId: syncId, isManga: isManga).notifier)
|
||||
.findManga(track);
|
||||
} else if (syncId == 2) {
|
||||
findManga = isManga!
|
||||
? await ref.read(anilistProvider(syncId: syncId, isManga: isManga).notifier).findLibManga(track)
|
||||
: await ref.read(anilistProvider(syncId: syncId, isManga: isManga).notifier).findLibAnime(track);
|
||||
? await ref
|
||||
.read(anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||
.findLibManga(track)
|
||||
: await ref
|
||||
.read(anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||
.findLibAnime(track);
|
||||
findManga ??= isManga!
|
||||
? await ref.read(anilistProvider(syncId: syncId, isManga: isManga).notifier).addLibManga(track)
|
||||
: await ref.read(anilistProvider(syncId: syncId, isManga: isManga).notifier).addLibAnime(track);
|
||||
? await ref
|
||||
.read(anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||
.addLibManga(track)
|
||||
: await ref
|
||||
.read(anilistProvider(syncId: syncId, isManga: isManga).notifier)
|
||||
.addLibAnime(track);
|
||||
} else if (syncId == 3) {
|
||||
findManga = isManga!
|
||||
? await ref.read(kitsuProvider(syncId: syncId, isManga: isManga).notifier).addLibManga(track)
|
||||
: await ref.read(kitsuProvider(syncId: syncId, isManga: isManga).notifier).addLibAnime(track);
|
||||
? await ref
|
||||
.read(kitsuProvider(syncId: syncId, isManga: isManga).notifier)
|
||||
.addLibManga(track)
|
||||
: await ref
|
||||
.read(kitsuProvider(syncId: syncId, isManga: isManga).notifier)
|
||||
.addLibAnime(track);
|
||||
}
|
||||
ref.read(tracksProvider(syncId: syncId).notifier).updateTrackManga(findManga!, isManga);
|
||||
ref
|
||||
.read(tracksProvider(syncId: syncId).notifier)
|
||||
.updateTrackManga(findManga!, isManga);
|
||||
}
|
||||
|
||||
List<TrackStatus> getStatusList() {
|
||||
|
|
@ -107,16 +158,36 @@ class TrackState extends _$TrackState {
|
|||
List<TrackStatus> list = [];
|
||||
if (track!.syncId == 1) {
|
||||
statusList = isManga!
|
||||
? ref.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga).notifier).myAnimeListStatusListManga
|
||||
: ref.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga).notifier).myAnimeListStatusListAnime;
|
||||
? ref
|
||||
.read(
|
||||
myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.myAnimeListStatusListManga
|
||||
: ref
|
||||
.read(
|
||||
myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.myAnimeListStatusListAnime;
|
||||
} else if (track!.syncId == 2) {
|
||||
statusList = isManga!
|
||||
? ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).aniListStatusListManga
|
||||
: ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).aniListStatusListAnime;
|
||||
? ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.aniListStatusListManga
|
||||
: ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.aniListStatusListAnime;
|
||||
} else if (track!.syncId == 3) {
|
||||
statusList = isManga!
|
||||
? ref.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga).notifier).kitsuStatusListManga
|
||||
: ref.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga).notifier).kitsuStatusListAnime;
|
||||
? ref
|
||||
.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.kitsuStatusListManga
|
||||
: ref
|
||||
.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.kitsuStatusListAnime;
|
||||
}
|
||||
for (var element in TrackStatus.values) {
|
||||
if (statusList.contains(element)) {
|
||||
|
|
@ -129,16 +200,30 @@ class TrackState extends _$TrackState {
|
|||
Future<Track?> findManga() async {
|
||||
Track? findManga;
|
||||
if (track!.syncId == 1) {
|
||||
findManga =
|
||||
await ref.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga).notifier).findManga(track!);
|
||||
findManga = await ref
|
||||
.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.findManga(track!);
|
||||
} else if (track!.syncId == 2) {
|
||||
findManga = isManga!
|
||||
? await ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).findLibManga(track!)
|
||||
: await ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).findLibAnime(track!);
|
||||
? await ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.findLibManga(track!)
|
||||
: await ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.findLibAnime(track!);
|
||||
} else if (track!.syncId == 3) {
|
||||
findManga = isManga!
|
||||
? await ref.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga).notifier).findLibManga(track!)
|
||||
: await ref.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga).notifier).findLibAnime(track!);
|
||||
? await ref
|
||||
.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.findLibManga(track!)
|
||||
: await ref
|
||||
.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.findLibAnime(track!);
|
||||
}
|
||||
return findManga;
|
||||
}
|
||||
|
|
@ -146,15 +231,30 @@ class TrackState extends _$TrackState {
|
|||
Future<List<TrackSearch>?> search(String query) async {
|
||||
List<TrackSearch>? tracks;
|
||||
if (track!.syncId == 1) {
|
||||
tracks = await ref.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga).notifier).search(query);
|
||||
tracks = await ref
|
||||
.read(myAnimeListProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.search(query);
|
||||
} else if (track!.syncId == 2) {
|
||||
tracks = isManga!
|
||||
? await ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).search(query)
|
||||
: await ref.read(anilistProvider(syncId: track!.syncId!, isManga: isManga).notifier).searchAnime(query);
|
||||
? await ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.search(query)
|
||||
: await ref
|
||||
.read(anilistProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.searchAnime(query);
|
||||
} else if (track!.syncId == 3) {
|
||||
tracks = isManga!
|
||||
? await ref.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga).notifier).search(query)
|
||||
: await ref.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga).notifier).searchAnime(query);
|
||||
? await ref
|
||||
.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.search(query)
|
||||
: await ref
|
||||
.read(kitsuProvider(syncId: track!.syncId!, isManga: isManga)
|
||||
.notifier)
|
||||
.searchAnime(query);
|
||||
}
|
||||
return tracks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
part 'update_manga_detail_providers.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<dynamic> updateMangaDetail(Ref ref, {required int? mangaId, required bool isInit}) async {
|
||||
Future<dynamic> updateMangaDetail(Ref ref,
|
||||
{required int? mangaId, required bool isInit}) async {
|
||||
final manga = isar.mangas.getSync(mangaId!);
|
||||
if (manga!.chapters.isNotEmpty && isInit) {
|
||||
return;
|
||||
|
|
@ -20,20 +21,31 @@ Future<dynamic> updateMangaDetail(Ref ref, {required int? mangaId, required bool
|
|||
final source = getSource(manga.lang!, manga.source!);
|
||||
MManga getManga;
|
||||
try {
|
||||
getManga = await ref.watch(getDetailProvider(url: manga.link!, source: source!).future);
|
||||
getManga = await ref
|
||||
.watch(getDetailProvider(url: manga.link!, source: source!).future);
|
||||
} catch (e) {
|
||||
botToast(e.toString());
|
||||
return;
|
||||
}
|
||||
final genre = getManga.genre?.map((e) => e.toString().trim().trimLeft().trimRight()).toList().toSet().toList() ?? [];
|
||||
final genre = getManga.genre
|
||||
?.map((e) => e.toString().trim().trimLeft().trimRight())
|
||||
.toList()
|
||||
.toSet()
|
||||
.toList() ??
|
||||
[];
|
||||
manga
|
||||
..imageUrl = getManga.imageUrl ?? manga.imageUrl
|
||||
..name = getManga.name?.trim().trimLeft().trimRight() ?? manga.name
|
||||
..genre = (genre.isEmpty ? null : genre) ?? manga.genre ?? []
|
||||
..author = getManga.author?.trim().trimLeft().trimRight() ?? manga.author ?? ""
|
||||
..artist = getManga.artist?.trim().trimLeft().trimRight() ?? manga.artist ?? ""
|
||||
..status = getManga.status == Status.unknown ? manga.status : getManga.status!
|
||||
..description = getManga.description?.trim().trimLeft().trimRight() ?? manga.description ?? ""
|
||||
..author =
|
||||
getManga.author?.trim().trimLeft().trimRight() ?? manga.author ?? ""
|
||||
..artist =
|
||||
getManga.artist?.trim().trimLeft().trimRight() ?? manga.artist ?? ""
|
||||
..status =
|
||||
getManga.status == Status.unknown ? manga.status : getManga.status!
|
||||
..description = getManga.description?.trim().trimLeft().trimRight() ??
|
||||
manga.description ??
|
||||
""
|
||||
..link = getManga.link?.trim().trimLeft().trimRight() ?? manga.link
|
||||
..source = manga.source
|
||||
..lang = manga.lang
|
||||
|
|
@ -68,19 +80,24 @@ Future<dynamic> updateMangaDetail(Ref ref, {required int? mangaId, required bool
|
|||
}
|
||||
if (chapters.isNotEmpty) {
|
||||
for (var chap in chapters.reversed.toList()) {
|
||||
ref.read(changedItemsManagerProvider(managerId: 1).notifier).addUpdatedChapter(chap, false, false);
|
||||
ref
|
||||
.read(changedItemsManagerProvider(managerId: 1).notifier)
|
||||
.addUpdatedChapter(chap, false, false);
|
||||
isar.chapters.putSync(chap);
|
||||
chap.manga.saveSync();
|
||||
if (manga.chapters.isNotEmpty) {
|
||||
final update =
|
||||
Update(mangaId: mangaId, chapterName: chap.name, date: DateTime.now().millisecondsSinceEpoch.toString())
|
||||
..chapter.value = chap;
|
||||
final update = Update(
|
||||
mangaId: mangaId,
|
||||
chapterName: chap.name,
|
||||
date: DateTime.now().millisecondsSinceEpoch.toString())
|
||||
..chapter.value = chap;
|
||||
isar.updates.putSync(update);
|
||||
update.chapter.saveSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
final oldChapers = isar.mangas.getSync(mangaId)!.chapters.toList().reversed.toList();
|
||||
final oldChapers =
|
||||
isar.mangas.getSync(mangaId)!.chapters.toList().reversed.toList();
|
||||
if (oldChapers.length == chaps.length) {
|
||||
for (var i = 0; i < oldChapers.length; i++) {
|
||||
final oldChap = oldChapers[i];
|
||||
|
|
@ -91,7 +108,9 @@ Future<dynamic> updateMangaDetail(Ref ref, {required int? mangaId, required bool
|
|||
newChap.name == oldChap.name) {
|
||||
oldChap.url = newChap.url;
|
||||
oldChap.scanlator = newChap.scanlator;
|
||||
ref.read(changedItemsManagerProvider(managerId: 1).notifier).addUpdatedChapter(oldChap, false, false);
|
||||
ref
|
||||
.read(changedItemsManagerProvider(managerId: 1).notifier)
|
||||
.addUpdatedChapter(oldChap, false, false);
|
||||
isar.chapters.putSync(oldChap);
|
||||
oldChap.manga.saveSync();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,11 @@ class ListTileChapterFilter extends StatelessWidget {
|
|||
final String label;
|
||||
final int type;
|
||||
final VoidCallback onTap;
|
||||
const ListTileChapterFilter({super.key, required this.label, required this.type, required this.onTap});
|
||||
const ListTileChapterFilter(
|
||||
{super.key,
|
||||
required this.label,
|
||||
required this.type,
|
||||
required this.onTap});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -25,19 +25,25 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return Container(
|
||||
color: chapterList.contains(chapter) ? context.primaryColor.withValues(alpha: 0.4) : null,
|
||||
color: chapterList.contains(chapter)
|
||||
? context.primaryColor.withValues(alpha: 0.4)
|
||||
: null,
|
||||
child: ListTile(
|
||||
textColor: chapter.isRead!
|
||||
? context.isLight
|
||||
? Colors.black.withValues(alpha: 0.4)
|
||||
: Colors.white.withValues(alpha: 0.3)
|
||||
: null,
|
||||
selectedColor: chapter.isRead! ? Colors.white.withValues(alpha: 0.3) : Colors.white,
|
||||
selectedColor: chapter.isRead!
|
||||
? Colors.white.withValues(alpha: 0.3)
|
||||
: Colors.white,
|
||||
onLongPress: () {
|
||||
if (!isLongPressed) {
|
||||
ref.read(chaptersListStateProvider.notifier).update(chapter);
|
||||
|
||||
ref.read(isLongPressedStateProvider.notifier).update(!isLongPressed);
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
} else {
|
||||
ref.read(chaptersListStateProvider.notifier).update(chapter);
|
||||
}
|
||||
|
|
@ -73,18 +79,23 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
Text(
|
||||
chapter.dateUpload == null || chapter.dateUpload!.isEmpty
|
||||
? ""
|
||||
: dateFormat(chapter.dateUpload!, ref: ref, context: context),
|
||||
: dateFormat(chapter.dateUpload!,
|
||||
ref: ref, context: context),
|
||||
style: const TextStyle(fontSize: 11),
|
||||
),
|
||||
if (!chapter.isRead!)
|
||||
if (chapter.lastPageRead!.isNotEmpty && chapter.lastPageRead != "1")
|
||||
if (chapter.lastPageRead!.isNotEmpty &&
|
||||
chapter.lastPageRead != "1")
|
||||
Row(
|
||||
children: [
|
||||
const Text(' • '),
|
||||
Text(
|
||||
!chapter.manga.value!.isManga!
|
||||
? l10n.episode_progress(
|
||||
Duration(milliseconds: int.parse(chapter.lastPageRead!)).toString().substringBefore("."))
|
||||
? l10n.episode_progress(Duration(
|
||||
milliseconds:
|
||||
int.parse(chapter.lastPageRead!))
|
||||
.toString()
|
||||
.substringBefore("."))
|
||||
: l10n.page(chapter.lastPageRead!),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
|
|
|
|||
|
|
@ -6,15 +6,22 @@ class ListTileChapterSort extends StatelessWidget {
|
|||
final VoidCallback onTap;
|
||||
final bool showLeading;
|
||||
const ListTileChapterSort(
|
||||
{super.key, required this.label, required this.reverse, required this.onTap, required this.showLeading});
|
||||
{super.key,
|
||||
required this.label,
|
||||
required this.reverse,
|
||||
required this.onTap,
|
||||
required this.showLeading});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
iconColor: Theme.of(context).primaryColor,
|
||||
dense: true,
|
||||
leading: Icon(reverse ? Icons.arrow_downward_sharp : Icons.arrow_upward_sharp,
|
||||
color: showLeading ? Theme.of(context).primaryColor : Colors.transparent),
|
||||
leading: Icon(
|
||||
reverse ? Icons.arrow_downward_sharp : Icons.arrow_upward_sharp,
|
||||
color: showLeading
|
||||
? Theme.of(context).primaryColor
|
||||
: Colors.transparent),
|
||||
title: Text(
|
||||
label,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import 'package:mangayomi/providers/l10n_providers.dart';
|
|||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
|
||||
class ReadMoreWidget extends StatefulWidget {
|
||||
const ReadMoreWidget({super.key, required this.text, required this.onChanged});
|
||||
const ReadMoreWidget(
|
||||
{super.key, required this.text, required this.onChanged});
|
||||
final Function(bool) onChanged;
|
||||
final String text;
|
||||
|
||||
|
|
@ -12,7 +13,8 @@ class ReadMoreWidget extends StatefulWidget {
|
|||
ReadMoreWidgetState createState() => ReadMoreWidgetState();
|
||||
}
|
||||
|
||||
class ReadMoreWidgetState extends State<ReadMoreWidget> with TickerProviderStateMixin {
|
||||
class ReadMoreWidgetState extends State<ReadMoreWidget>
|
||||
with TickerProviderStateMixin {
|
||||
late bool expanded = true;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -61,7 +63,9 @@ class ReadMoreWidgetState extends State<ReadMoreWidget> with TickerProviderState
|
|||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
Theme.of(context).scaffoldBackgroundColor.withValues(alpha: 0.2),
|
||||
Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
.withValues(alpha: 0.2),
|
||||
Theme.of(context).scaffoldBackgroundColor
|
||||
],
|
||||
stops: const [0, .9],
|
||||
|
|
|
|||
|
|
@ -11,10 +11,12 @@ import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
|||
class TrackerWidgetSearch extends ConsumerStatefulWidget {
|
||||
final bool isManga;
|
||||
final Track track;
|
||||
const TrackerWidgetSearch({required this.isManga, required this.track, super.key});
|
||||
const TrackerWidgetSearch(
|
||||
{required this.isManga, required this.track, super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<TrackerWidgetSearch> createState() => _TrackerWidgetSearchState();
|
||||
ConsumerState<TrackerWidgetSearch> createState() =>
|
||||
_TrackerWidgetSearchState();
|
||||
}
|
||||
|
||||
class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
||||
|
|
@ -28,7 +30,10 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
|||
late List<TrackSearch>? tracks = [];
|
||||
_init() async {
|
||||
await Future.delayed(const Duration(microseconds: 100));
|
||||
tracks = await ref.read(trackStateProvider(track: widget.track, isManga: widget.isManga).notifier).search(query);
|
||||
tracks = await ref
|
||||
.read(trackStateProvider(track: widget.track, isManga: widget.isManga)
|
||||
.notifier)
|
||||
.search(query);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
|
@ -42,7 +47,8 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
|||
Widget build(BuildContext context) {
|
||||
return Material(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
child: _isLoading
|
||||
? const ProgressCenter()
|
||||
|
|
@ -66,41 +72,50 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
|||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Material(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: Colors.transparent,
|
||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||
clipBehavior:
|
||||
Clip.antiAliasWithSaveLayer,
|
||||
child: Ink.image(
|
||||
height: 120,
|
||||
width: 80,
|
||||
fit: BoxFit.cover,
|
||||
image: CustomExtendedNetworkImageProvider(tracks![index].coverUrl!),
|
||||
image:
|
||||
CustomExtendedNetworkImageProvider(
|
||||
tracks![index].coverUrl!),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: context.width(0.6),
|
||||
child: Text(
|
||||
tracks![index].title!,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
const Text(
|
||||
"Type : ",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12),
|
||||
),
|
||||
Text(
|
||||
tracks![index].publishingType!,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
style: const TextStyle(
|
||||
fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -108,11 +123,15 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
|||
children: [
|
||||
const Text(
|
||||
"Status : ",
|
||||
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12),
|
||||
),
|
||||
Text(
|
||||
tracks![index].publishingStatus!,
|
||||
style: const TextStyle(fontSize: 12),
|
||||
tracks![index]
|
||||
.publishingStatus!,
|
||||
style: const TextStyle(
|
||||
fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -153,7 +172,10 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
|||
_isLoading = true;
|
||||
});
|
||||
tracks = await ref
|
||||
.read(trackStateProvider(track: widget.track, isManga: widget.isManga).notifier)
|
||||
.read(trackStateProvider(
|
||||
track: widget.track,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.search(d.trim());
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
|
|
@ -173,12 +195,16 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
|||
},
|
||||
icon: const Icon(Icons.clear)),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: context.primaryColor),
|
||||
borderSide:
|
||||
BorderSide(color: context.primaryColor),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: context.primaryColor),
|
||||
borderSide:
|
||||
BorderSide(color: context.primaryColor),
|
||||
),
|
||||
border: OutlineInputBorder(borderSide: BorderSide(color: context.primaryColor))),
|
||||
border: OutlineInputBorder(
|
||||
borderSide:
|
||||
BorderSide(color: context.primaryColor))),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -189,7 +215,8 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
|||
}
|
||||
}
|
||||
|
||||
trackersSearchraggableMenu(BuildContext context, {required Track track, required bool isManga}) async {
|
||||
trackersSearchraggableMenu(BuildContext context,
|
||||
{required Track track, required bool isManga}) async {
|
||||
return await DraggableMenu.open(
|
||||
context,
|
||||
DraggableMenu(
|
||||
|
|
@ -199,7 +226,9 @@ trackersSearchraggableMenu(BuildContext context, {required Track track, required
|
|||
barItem: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).scaffoldBackgroundColor,
|
||||
borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), topRight: Radius.circular(20))),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20))),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
|
|
|
|||
|
|
@ -38,10 +38,15 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
|
||||
_init() async {
|
||||
await Future.delayed(const Duration(microseconds: 100));
|
||||
final findManga =
|
||||
await ref.read(trackStateProvider(track: widget.trackRes, isManga: widget.isManga).notifier).findManga();
|
||||
final findManga = await ref
|
||||
.read(
|
||||
trackStateProvider(track: widget.trackRes, isManga: widget.isManga)
|
||||
.notifier)
|
||||
.findManga();
|
||||
if (mounted) {
|
||||
ref.read(tracksProvider(syncId: widget.syncId).notifier).updateTrackManga(findManga!, widget.isManga);
|
||||
ref
|
||||
.read(tracksProvider(syncId: widget.syncId).notifier)
|
||||
.updateTrackManga(findManga!, widget.isManga);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +56,9 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
final l10nLocale = ref.watch(l10nLocaleStateProvider);
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.isLight ? Theme.of(context).scaffoldBackgroundColor : Colors.black,
|
||||
color: context.isLight
|
||||
? Theme.of(context).scaffoldBackgroundColor
|
||||
: Colors.black,
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
@ -59,10 +66,12 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
children: [
|
||||
if (!widget.hide)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
|
||||
child: Container(
|
||||
decoration:
|
||||
BoxDecoration(borderRadius: BorderRadius.circular(10), color: trackInfos(widget.syncId).$3),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: trackInfos(widget.syncId).$3),
|
||||
width: 50,
|
||||
height: 45,
|
||||
child: Image.asset(
|
||||
|
|
@ -74,16 +83,22 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
Expanded(
|
||||
child: _elevatedButton(
|
||||
context,
|
||||
borderRadius: const BorderRadius.only(topRight: Radius.circular(20), topLeft: Radius.circular(20)),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topRight: Radius.circular(20),
|
||||
topLeft: Radius.circular(20)),
|
||||
onPressed: !widget.hide
|
||||
? () async {
|
||||
final trackSearch =
|
||||
await trackersSearchraggableMenu(context, isManga: widget.isManga, track: widget.trackRes)
|
||||
as TrackSearch?;
|
||||
final trackSearch = await trackersSearchraggableMenu(
|
||||
context,
|
||||
isManga: widget.isManga,
|
||||
track: widget.trackRes) as TrackSearch?;
|
||||
if (trackSearch != null) {
|
||||
await ref
|
||||
.read(trackStateProvider(track: null, isManga: widget.isManga).notifier)
|
||||
.setTrackSearch(trackSearch, widget.mangaId, widget.syncId);
|
||||
.read(trackStateProvider(
|
||||
track: null, isManga: widget.isManga)
|
||||
.notifier)
|
||||
.setTrackSearch(
|
||||
trackSearch, widget.mangaId, widget.syncId);
|
||||
}
|
||||
}
|
||||
: null,
|
||||
|
|
@ -95,7 +110,10 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
child: Text(
|
||||
widget.trackRes.title!,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).textTheme.bodyMedium!.color,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.color,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold),
|
||||
|
|
@ -105,7 +123,10 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
ref.read(tracksProvider(syncId: widget.syncId).notifier).deleteTrackManga(widget.trackRes);
|
||||
ref
|
||||
.read(tracksProvider(syncId: widget.syncId)
|
||||
.notifier)
|
||||
.deleteTrackManga(widget.trackRes);
|
||||
},
|
||||
icon: const Icon(Icons.cancel_outlined))
|
||||
],
|
||||
|
|
@ -130,29 +151,39 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: ref
|
||||
.read(trackStateProvider(track: widget.trackRes, isManga: widget.isManga).notifier)
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.getStatusList()
|
||||
.length,
|
||||
itemBuilder: (context, index) {
|
||||
final status = ref
|
||||
.read(
|
||||
trackStateProvider(track: widget.trackRes, isManga: widget.isManga).notifier)
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.getStatusList()[index];
|
||||
return RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: status,
|
||||
groupValue:
|
||||
toTrackStatus(widget.trackRes.status, widget.isManga, widget.trackRes.syncId!),
|
||||
groupValue: toTrackStatus(
|
||||
widget.trackRes.status,
|
||||
widget.isManga,
|
||||
widget.trackRes.syncId!),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes..status = status, isManga: widget.isManga)
|
||||
track: widget.trackRes
|
||||
..status = status,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.updateManga();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: Text(getTrackStatus(status, context)),
|
||||
title:
|
||||
Text(getTrackStatus(status, context)),
|
||||
);
|
||||
},
|
||||
)),
|
||||
|
|
@ -166,7 +197,8 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -175,7 +207,9 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
});
|
||||
},
|
||||
text: getTrackStatus(
|
||||
toTrackStatus(widget.trackRes.status, widget.isManga, widget.trackRes.syncId!), context)),
|
||||
toTrackStatus(widget.trackRes.status, widget.isManga,
|
||||
widget.trackRes.syncId!),
|
||||
context)),
|
||||
),
|
||||
Expanded(
|
||||
child: _elevatedButton(context, onPressed: () {
|
||||
|
|
@ -196,10 +230,13 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
NumberPicker(
|
||||
value: currentIntValue,
|
||||
minValue: 0,
|
||||
maxValue: widget.trackRes.totalChapter != 0 ? widget.trackRes.totalChapter! : 10000,
|
||||
maxValue: widget.trackRes.totalChapter != 0
|
||||
? widget.trackRes.totalChapter!
|
||||
: 10000,
|
||||
step: 1,
|
||||
haptics: true,
|
||||
onChanged: (value) => setState(() => currentIntValue = value),
|
||||
onChanged: (value) =>
|
||||
setState(() => currentIntValue = value),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -215,13 +252,16 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
ref
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes..lastChapterRead = currentIntValue,
|
||||
track: widget.trackRes
|
||||
..lastChapterRead =
|
||||
currentIntValue,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.updateManga();
|
||||
|
|
@ -229,7 +269,8 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
},
|
||||
child: Text(
|
||||
l10n.ok,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -261,21 +302,28 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
value: currentIntValue,
|
||||
minValue: 0,
|
||||
maxValue: ref
|
||||
.read(trackStateProvider(track: widget.trackRes, isManga: widget.isManga)
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.getScoreMaxValue(),
|
||||
textMapper: (numberText) {
|
||||
return ref
|
||||
.read(trackStateProvider(track: widget.trackRes, isManga: widget.isManga)
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.getTextMapper(numberText);
|
||||
},
|
||||
step: ref
|
||||
.read(trackStateProvider(track: widget.trackRes, isManga: widget.isManga)
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.getScoreStep(),
|
||||
haptics: true,
|
||||
onChanged: (value) => setState(() => currentIntValue = value),
|
||||
onChanged: (value) =>
|
||||
setState(() => currentIntValue = value),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -291,13 +339,15 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
},
|
||||
child: Text(
|
||||
l10n.cancel,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
ref
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes..score = currentIntValue,
|
||||
track: widget.trackRes
|
||||
..score = currentIntValue,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.updateManga();
|
||||
|
|
@ -305,7 +355,8 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
},
|
||||
child: Text(
|
||||
l10n.ok,
|
||||
style: TextStyle(color: context.primaryColor),
|
||||
style: TextStyle(
|
||||
color: context.primaryColor),
|
||||
)),
|
||||
],
|
||||
)
|
||||
|
|
@ -315,7 +366,10 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
},
|
||||
text: widget.trackRes.score != 0
|
||||
? ref
|
||||
.read(trackStateProvider(track: widget.trackRes, isManga: widget.isManga).notifier)
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.displayScore(widget.trackRes.score!)
|
||||
: l10n!.score),
|
||||
)
|
||||
|
|
@ -324,8 +378,9 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _elevatedButton(context, borderRadius: const BorderRadius.only(bottomLeft: Radius.circular(20)),
|
||||
onPressed: () async {
|
||||
child: _elevatedButton(context,
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomLeft: Radius.circular(20)), onPressed: () async {
|
||||
DateTime? newDate = await showDatePicker(
|
||||
helpText: l10n!.start_date,
|
||||
locale: l10nLocale,
|
||||
|
|
@ -336,20 +391,27 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
if (newDate == null) return;
|
||||
ref
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes..startedReadingDate = newDate.millisecondsSinceEpoch,
|
||||
track: widget.trackRes
|
||||
..startedReadingDate =
|
||||
newDate.millisecondsSinceEpoch,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.updateManga();
|
||||
},
|
||||
text: widget.trackRes.startedReadingDate != null &&
|
||||
widget.trackRes.startedReadingDate! > DateTime(1970).millisecondsSinceEpoch
|
||||
? dateFormat(widget.trackRes.startedReadingDate.toString(),
|
||||
ref: ref, useRelativeTimesTamps: false, context: context)
|
||||
widget.trackRes.startedReadingDate! >
|
||||
DateTime(1970).millisecondsSinceEpoch
|
||||
? dateFormat(
|
||||
widget.trackRes.startedReadingDate.toString(),
|
||||
ref: ref,
|
||||
useRelativeTimesTamps: false,
|
||||
context: context)
|
||||
: l10n!.start_date),
|
||||
),
|
||||
Expanded(
|
||||
child: _elevatedButton(context, borderRadius: const BorderRadius.only(bottomRight: Radius.circular(20)),
|
||||
onPressed: () async {
|
||||
child: _elevatedButton(context,
|
||||
borderRadius: const BorderRadius.only(
|
||||
bottomRight: Radius.circular(20)), onPressed: () async {
|
||||
DateTime? newDate = await showDatePicker(
|
||||
helpText: l10n!.finish_date,
|
||||
locale: l10nLocale,
|
||||
|
|
@ -360,15 +422,21 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
if (newDate == null) return;
|
||||
ref
|
||||
.read(trackStateProvider(
|
||||
track: widget.trackRes..finishedReadingDate = newDate.millisecondsSinceEpoch,
|
||||
track: widget.trackRes
|
||||
..finishedReadingDate =
|
||||
newDate.millisecondsSinceEpoch,
|
||||
isManga: widget.isManga)
|
||||
.notifier)
|
||||
.updateManga();
|
||||
},
|
||||
text: widget.trackRes.finishedReadingDate != null &&
|
||||
widget.trackRes.finishedReadingDate! > DateTime(1970).millisecondsSinceEpoch
|
||||
? dateFormat(widget.trackRes.finishedReadingDate.toString(),
|
||||
ref: ref, useRelativeTimesTamps: false, context: context)
|
||||
widget.trackRes.finishedReadingDate! >
|
||||
DateTime(1970).millisecondsSinceEpoch
|
||||
? dateFormat(
|
||||
widget.trackRes.finishedReadingDate.toString(),
|
||||
ref: ref,
|
||||
useRelativeTimesTamps: false,
|
||||
context: context)
|
||||
: l10n!.finish_date),
|
||||
)
|
||||
],
|
||||
|
|
@ -380,20 +448,32 @@ class _TrackerWidgetState extends ConsumerState<TrackerWidget> {
|
|||
}
|
||||
|
||||
Widget _elevatedButton(BuildContext context,
|
||||
{required Function()? onPressed, String text = "", Widget? child, BorderRadiusGeometry? borderRadius}) {
|
||||
{required Function()? onPressed,
|
||||
String text = "",
|
||||
Widget? child,
|
||||
BorderRadiusGeometry? borderRadius}) {
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
backgroundColor: context.isLight ? Theme.of(context).scaffoldBackgroundColor : Colors.black,
|
||||
backgroundColor: context.isLight
|
||||
? Theme.of(context).scaffoldBackgroundColor
|
||||
: Colors.black,
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(width: 0, color: context.secondaryColor.withValues(alpha: 0.1)),
|
||||
side: BorderSide(
|
||||
width: 0,
|
||||
color: context.secondaryColor.withValues(alpha: 0.1)),
|
||||
borderRadius: borderRadius ?? BorderRadius.circular(0))),
|
||||
onPressed: onPressed,
|
||||
child: child ??
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(color: Theme.of(context).textTheme.bodyMedium!.color!.withValues(alpha: 0.9)),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium!
|
||||
.color!
|
||||
.withValues(alpha: 0.9)),
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,19 +35,24 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
final StorageProvider _storageProvider = StorageProvider();
|
||||
|
||||
void _startDownload(bool? useWifi) async {
|
||||
await ref.watch(downloadChapterProvider(chapter: widget.chapter, useWifi: useWifi).future);
|
||||
await ref.watch(
|
||||
downloadChapterProvider(chapter: widget.chapter, useWifi: useWifi)
|
||||
.future);
|
||||
}
|
||||
|
||||
late final manga = widget.chapter.manga.value!;
|
||||
|
||||
void _sendFile() async {
|
||||
final mangaDir = await _storageProvider.getMangaMainDirectory(widget.chapter);
|
||||
final path = await _storageProvider.getMangaChapterDirectory(widget.chapter);
|
||||
final mangaDir =
|
||||
await _storageProvider.getMangaMainDirectory(widget.chapter);
|
||||
final path =
|
||||
await _storageProvider.getMangaChapterDirectory(widget.chapter);
|
||||
|
||||
List<XFile> files = [];
|
||||
|
||||
final cbzFile = File(p.join(mangaDir!.path, "${widget.chapter.name}.cbz"));
|
||||
final mp4File = File(p.join(mangaDir.path, "${widget.chapter.name!.replaceForbiddenCharacters(' ')}.mp4"));
|
||||
final mp4File = File(p.join(mangaDir.path,
|
||||
"${widget.chapter.name!.replaceForbiddenCharacters(' ')}.mp4"));
|
||||
if (cbzFile.existsSync()) {
|
||||
files = [XFile(cbzFile.path)];
|
||||
} else if (mp4File.existsSync()) {
|
||||
|
|
@ -61,18 +66,22 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
}
|
||||
|
||||
void _deleteFile() async {
|
||||
final mangaDir = await _storageProvider.getMangaMainDirectory(widget.chapter);
|
||||
final path = await _storageProvider.getMangaChapterDirectory(widget.chapter);
|
||||
final mangaDir =
|
||||
await _storageProvider.getMangaMainDirectory(widget.chapter);
|
||||
final path =
|
||||
await _storageProvider.getMangaChapterDirectory(widget.chapter);
|
||||
|
||||
try {
|
||||
try {
|
||||
final cbzFile = File(p.join(mangaDir!.path, "${widget.chapter.name}.cbz"));
|
||||
final cbzFile =
|
||||
File(p.join(mangaDir!.path, "${widget.chapter.name}.cbz"));
|
||||
if (cbzFile.existsSync()) {
|
||||
cbzFile.deleteSync();
|
||||
}
|
||||
} catch (_) {}
|
||||
try {
|
||||
final mp4File = File(p.join(mangaDir!.path, "${widget.chapter.name!.replaceForbiddenCharacters(' ')}.mp4"));
|
||||
final mp4File = File(p.join(mangaDir!.path,
|
||||
"${widget.chapter.name!.replaceForbiddenCharacters(' ')}.mp4"));
|
||||
if (mp4File.existsSync()) {
|
||||
mp4File.deleteSync();
|
||||
}
|
||||
|
|
@ -80,7 +89,11 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
path!.deleteSync(recursive: true);
|
||||
} catch (_) {}
|
||||
isar.writeTxnSync(() {
|
||||
int id = isar.downloads.filter().chapterIdEqualTo(widget.chapter.id!).findFirstSync()!.id!;
|
||||
int id = isar.downloads
|
||||
.filter()
|
||||
.chapterIdEqualTo(widget.chapter.id!)
|
||||
.findFirstSync()!
|
||||
.id!;
|
||||
isar.downloads.deleteSync(id);
|
||||
});
|
||||
}
|
||||
|
|
@ -111,7 +124,10 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
child: Icon(
|
||||
size: 25,
|
||||
Icons.check_circle,
|
||||
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.7),
|
||||
color: Theme.of(context)
|
||||
.iconTheme
|
||||
.color!
|
||||
.withValues(alpha: 0.7),
|
||||
),
|
||||
onSelected: (value) {
|
||||
if (value == 0) {
|
||||
|
|
@ -125,7 +141,8 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
PopupMenuItem(value: 1, child: Text(l10n.delete)),
|
||||
],
|
||||
)
|
||||
: entries.first.isStartDownload! && entries.first.succeeded == 0
|
||||
: entries.first.isStartDownload! &&
|
||||
entries.first.succeeded == 0
|
||||
? SizedBox(
|
||||
height: 41,
|
||||
width: 35,
|
||||
|
|
@ -144,7 +161,9 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(value: 1, child: Text(l10n.start_downloading)),
|
||||
PopupMenuItem(
|
||||
value: 1,
|
||||
child: Text(l10n.start_downloading)),
|
||||
PopupMenuItem(value: 0, child: Text(l10n.cancel)),
|
||||
],
|
||||
))
|
||||
|
|
@ -159,19 +178,25 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: TweenAnimationBuilder<double>(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
duration:
|
||||
const Duration(milliseconds: 250),
|
||||
curve: Curves.easeInOut,
|
||||
tween: Tween<double>(
|
||||
begin: 0,
|
||||
end: (entries.first.succeeded! / entries.first.total!),
|
||||
end: (entries.first.succeeded! /
|
||||
entries.first.total!),
|
||||
),
|
||||
builder: (context, value, _) => SizedBox(
|
||||
builder: (context, value, _) =>
|
||||
SizedBox(
|
||||
height: 2,
|
||||
width: 2,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 19,
|
||||
value: value,
|
||||
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.7),
|
||||
color: Theme.of(context)
|
||||
.iconTheme
|
||||
.color!
|
||||
.withValues(alpha: 0.7),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -180,9 +205,15 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
alignment: Alignment.center,
|
||||
child: Icon(
|
||||
Icons.arrow_downward_sharp,
|
||||
color: (entries.first.succeeded! / entries.first.total!) > 0.5
|
||||
? Theme.of(context).scaffoldBackgroundColor
|
||||
: Theme.of(context).iconTheme.color!.withValues(alpha: 0.7),
|
||||
color: (entries.first.succeeded! /
|
||||
entries.first.total!) >
|
||||
0.5
|
||||
? Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
: Theme.of(context)
|
||||
.iconTheme
|
||||
.color!
|
||||
.withValues(alpha: 0.7),
|
||||
)),
|
||||
],
|
||||
),
|
||||
|
|
@ -198,8 +229,11 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(value: 1, child: Text(l10n.start_downloading)),
|
||||
PopupMenuItem(value: 0, child: Text(l10n.cancel)),
|
||||
PopupMenuItem(
|
||||
value: 1,
|
||||
child: Text(l10n.start_downloading)),
|
||||
PopupMenuItem(
|
||||
value: 0, child: Text(l10n.cancel)),
|
||||
],
|
||||
))
|
||||
: entries.first.succeeded == 0
|
||||
|
|
@ -212,7 +246,10 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
},
|
||||
icon: Icon(
|
||||
FontAwesomeIcons.circleDown,
|
||||
color: Theme.of(context).iconTheme.color!.withValues(alpha: 0.7),
|
||||
color: Theme.of(context)
|
||||
.iconTheme
|
||||
.color!
|
||||
.withValues(alpha: 0.7),
|
||||
size: 25,
|
||||
))
|
||||
: SizedBox(
|
||||
|
|
@ -235,7 +272,8 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(value: 0, child: Text(l10n.retry)),
|
||||
PopupMenuItem(
|
||||
value: 0, child: Text(l10n.retry)),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
|
@ -255,7 +293,8 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(value: 1, child: Text(l10n.start_downloading)),
|
||||
PopupMenuItem(
|
||||
value: 1, child: Text(l10n.start_downloading)),
|
||||
PopupMenuItem(value: 0, child: Text(l10n.cancel)),
|
||||
],
|
||||
))
|
||||
|
|
@ -287,7 +326,10 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
[];
|
||||
await FileDownloader().cancelTasksWithIds(_pageUrls);
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
final chapterD = isar.downloads.filter().chapterIdEqualTo(widget.chapter.id!).findFirstSync();
|
||||
final chapterD = isar.downloads
|
||||
.filter()
|
||||
.chapterIdEqualTo(widget.chapter.id!)
|
||||
.findFirstSync();
|
||||
if (chapterD != null) {
|
||||
final verifyId = isar.downloads.getSync(chapterD.id!);
|
||||
isar.writeTxnSync(() {
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import 'package:path/path.dart' as path;
|
|||
part 'convert_to_cbz.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<String>> convertToCBZ(
|
||||
Ref ref, String chapterDir, String mangaDir, String chapterName, List<String> pageList) async {
|
||||
Future<List<String>> convertToCBZ(Ref ref, String chapterDir, String mangaDir,
|
||||
String chapterName, List<String> pageList) async {
|
||||
return compute(_convertToCBZ, (chapterDir, mangaDir, chapterName, pageList));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,9 @@ Future<List<PageUrl>> downloadChapter(
|
|||
bool isOk = false;
|
||||
final manga = chapter.manga.value!;
|
||||
final path1 = await storageProvider.getDirectory();
|
||||
String scanlator =
|
||||
(chapter.scanlator?.isNotEmpty ?? false) ? "${chapter.scanlator!.replaceForbiddenCharacters('_')}_" : "";
|
||||
String scanlator = (chapter.scanlator?.isNotEmpty ?? false)
|
||||
? "${chapter.scanlator!.replaceForbiddenCharacters('_')}_"
|
||||
: "";
|
||||
final chapterName = chapter.name!.replaceForbiddenCharacters(' ');
|
||||
|
||||
final isManga = manga.isManga!;
|
||||
|
|
@ -68,12 +69,13 @@ Future<List<PageUrl>> downloadChapter(
|
|||
|
||||
Future<void> processConvert() async {
|
||||
if (hasM3U8File) {
|
||||
await m3u8Downloader?.mergeTsToMp4(p.join(path!.path, "$chapterName.mp4"), p.join(path.path, chapterName));
|
||||
await m3u8Downloader?.mergeTsToMp4(p.join(path!.path, "$chapterName.mp4"),
|
||||
p.join(path.path, chapterName));
|
||||
} else {
|
||||
if (ref.watch(saveAsCBZArchiveStateProvider)) {
|
||||
await ref.watch(
|
||||
convertToCBZProvider(path!.path, mangaDir!.path, chapter.name!, pageUrls.map((e) => e.url).toList())
|
||||
.future);
|
||||
await ref.watch(convertToCBZProvider(path!.path, mangaDir!.path,
|
||||
chapter.name!, pageUrls.map((e) => e.url).toList())
|
||||
.future);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -86,12 +88,17 @@ Future<List<PageUrl>> downloadChapter(
|
|||
chapterPageUrls.add(chapterPageUrl);
|
||||
}
|
||||
}
|
||||
final chapterPageHeaders = pageUrls.map((e) => e.headers == null ? null : jsonEncode(e.headers)).toList();
|
||||
final chapterPageHeaders = pageUrls
|
||||
.map((e) => e.headers == null ? null : jsonEncode(e.headers))
|
||||
.toList();
|
||||
chapterPageUrls.add(ChapterPageurls()
|
||||
..chapterId = chapter.id
|
||||
..urls = pageUrls.map((e) => e.url).toList()
|
||||
..headers = chapterPageHeaders.first != null ? chapterPageHeaders.map((e) => e.toString()).toList() : null);
|
||||
isar.writeTxnSync(() => isar.settings.putSync(settings..chapterPageUrlsList = chapterPageUrls));
|
||||
..headers = chapterPageHeaders.first != null
|
||||
? chapterPageHeaders.map((e) => e.toString()).toList()
|
||||
: null);
|
||||
isar.writeTxnSync(() =>
|
||||
isar.settings.putSync(settings..chapterPageUrlsList = chapterPageUrls));
|
||||
}
|
||||
|
||||
if (isManga) {
|
||||
|
|
@ -108,9 +115,13 @@ Future<List<PageUrl>> downloadChapter(
|
|||
} else {
|
||||
ref.read(getVideoListProvider(episode: chapter).future).then((value) async {
|
||||
final m3u8Urls = value.$1
|
||||
.where((element) => element.originalUrl.endsWith(".m3u8") || element.originalUrl.endsWith(".m3u"))
|
||||
.where((element) =>
|
||||
element.originalUrl.endsWith(".m3u8") ||
|
||||
element.originalUrl.endsWith(".m3u"))
|
||||
.toList();
|
||||
final nonM3u8Urls = value.$1
|
||||
.where((element) => element.originalUrl.isMediaVideo())
|
||||
.toList();
|
||||
final nonM3u8Urls = value.$1.where((element) => element.originalUrl.isMediaVideo()).toList();
|
||||
nonM3U8File = nonM3u8Urls.isNotEmpty;
|
||||
hasM3U8File = nonM3U8File ? false : m3u8Urls.isNotEmpty;
|
||||
final videosUrls = nonM3U8File ? nonM3u8Urls : m3u8Urls;
|
||||
|
|
@ -121,9 +132,12 @@ Future<List<PageUrl>> downloadChapter(
|
|||
m3u8Url: videosUrls.first.url,
|
||||
downloadDir: p.join(path!.path, chapterName),
|
||||
headers: videosUrls.first.headers ?? {});
|
||||
(tsList, tsKey, tsIv, m3u8MediaSequence) = await m3u8Downloader!.getTsList();
|
||||
(tsList, tsKey, tsIv, m3u8MediaSequence) =
|
||||
await m3u8Downloader!.getTsList();
|
||||
}
|
||||
pageUrls = hasM3U8File ? [...tsList.map((e) => PageUrl(e.url))] : [PageUrl(videosUrls.first.url)];
|
||||
pageUrls = hasM3U8File
|
||||
? [...tsList.map((e) => PageUrl(e.url))]
|
||||
: [PageUrl(videosUrls.first.url)];
|
||||
videoHeader.addAll(videosUrls.first.headers ?? {});
|
||||
isOk = true;
|
||||
}
|
||||
|
|
@ -140,12 +154,18 @@ Future<List<PageUrl>> downloadChapter(
|
|||
|
||||
if (pageUrls.isNotEmpty) {
|
||||
bool cbzFileExist =
|
||||
await File(p.join(mangaDir!.path, "${chapter.name}.cbz")).exists() && ref.watch(saveAsCBZArchiveStateProvider);
|
||||
bool mp4FileExist = await File(p.join(mangaDir.path, "$chapterName.mp4")).exists();
|
||||
await File(p.join(mangaDir!.path, "${chapter.name}.cbz")).exists() &&
|
||||
ref.watch(saveAsCBZArchiveStateProvider);
|
||||
bool mp4FileExist =
|
||||
await File(p.join(mangaDir.path, "$chapterName.mp4")).exists();
|
||||
if (!cbzFileExist && isManga || !mp4FileExist && !isManga) {
|
||||
for (var index = 0; index < pageUrls.length; index++) {
|
||||
final path2 = Directory(p.join(path1.path, "downloads", isManga ? "Manga" : "Anime",
|
||||
"${manga.source} (${manga.lang!.toUpperCase()})", manga.name!.replaceForbiddenCharacters('_')));
|
||||
final path2 = Directory(p.join(
|
||||
path1.path,
|
||||
"downloads",
|
||||
isManga ? "Manga" : "Anime",
|
||||
"${manga.source} (${manga.lang!.toUpperCase()})",
|
||||
manga.name!.replaceForbiddenCharacters('_')));
|
||||
if (!(await path2.exists())) {
|
||||
await path2.create(recursive: true);
|
||||
}
|
||||
|
|
@ -156,7 +176,10 @@ Future<List<PageUrl>> downloadChapter(
|
|||
}
|
||||
final page = pageUrls[index];
|
||||
final cookie = MClient.getCookiesPref(page.url);
|
||||
final headers = isManga ? ref.watch(headersProvider(source: manga.source!, lang: manga.lang!)) : videoHeader;
|
||||
final headers = isManga
|
||||
? ref.watch(
|
||||
headersProvider(source: manga.source!, lang: manga.lang!))
|
||||
: videoHeader;
|
||||
if (cookie.isNotEmpty) {
|
||||
final userAgent = isar.settings.getSync(227)!.userAgent!;
|
||||
headers.addAll(cookie);
|
||||
|
|
@ -166,7 +189,8 @@ Future<List<PageUrl>> downloadChapter(
|
|||
pageHeaders.addAll(page.headers ?? {});
|
||||
|
||||
if (isManga) {
|
||||
final file = File(p.join(tempDir.path, "Mangayomi", finalPath, "${padIndex(index + 1)}.jpg"));
|
||||
final file = File(p.join(tempDir.path, "Mangayomi", finalPath,
|
||||
"${padIndex(index + 1)}.jpg"));
|
||||
if (file.existsSync()) {
|
||||
Directory(path.path).createSync(recursive: true);
|
||||
await file.copy(p.join(path.path, "${padIndex(index + 1)}.jpg"));
|
||||
|
|
@ -175,7 +199,8 @@ Future<List<PageUrl>> downloadChapter(
|
|||
if (!(await path.exists())) {
|
||||
await path.create();
|
||||
}
|
||||
if (!(await File(p.join(path.path, "${padIndex(index + 1)}.jpg")).exists())) {
|
||||
if (!(await File(p.join(path.path, "${padIndex(index + 1)}.jpg"))
|
||||
.exists())) {
|
||||
tasks.add(DownloadTask(
|
||||
taskId: page.url,
|
||||
headers: pageHeaders,
|
||||
|
|
@ -190,16 +215,21 @@ Future<List<PageUrl>> downloadChapter(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
final file = File(p.join(tempDir.path, "Mangayomi", finalPath, "$chapterName.mp4"));
|
||||
final file = File(
|
||||
p.join(tempDir.path, "Mangayomi", finalPath, "$chapterName.mp4"));
|
||||
if (file.existsSync()) {
|
||||
await file.copy(p.join(path.path, "$chapterName.mp4"));
|
||||
await file.delete();
|
||||
} else if (hasM3U8File) {
|
||||
final tempFile = File(p.join(tempDir.path, "Mangayomi", finalPath, chapterName, "TS_${index + 1}.ts"));
|
||||
final file = File(p.join(path.path, chapterName, "TS_${index + 1}.ts"));
|
||||
final tempFile = File(p.join(tempDir.path, "Mangayomi", finalPath,
|
||||
chapterName, "TS_${index + 1}.ts"));
|
||||
final file =
|
||||
File(p.join(path.path, chapterName, "TS_${index + 1}.ts"));
|
||||
if (tempFile.existsSync()) {
|
||||
Directory(p.join(path.path, chapterName)).createSync(recursive: true);
|
||||
await tempFile.copy(p.join(path.path, chapterName, "TS_${index + 1}.ts"));
|
||||
Directory(p.join(path.path, chapterName))
|
||||
.createSync(recursive: true);
|
||||
await tempFile
|
||||
.copy(p.join(path.path, chapterName, "TS_${index + 1}.ts"));
|
||||
await tempFile.delete();
|
||||
} else if (!(file.existsSync())) {
|
||||
tasks.add(DownloadTask(
|
||||
|
|
@ -264,7 +294,10 @@ Future<List<PageUrl>> downloadChapter(
|
|||
if (succeeded == tasks.length) {
|
||||
await processConvert();
|
||||
}
|
||||
bool isEmpty = isar.downloads.filter().chapterIdEqualTo(chapter.id!).isEmptySync();
|
||||
bool isEmpty = isar.downloads
|
||||
.filter()
|
||||
.chapterIdEqualTo(chapter.id!)
|
||||
.isEmptySync();
|
||||
if (isEmpty) {
|
||||
final download = Download(
|
||||
succeeded: succeeded,
|
||||
|
|
@ -279,7 +312,10 @@ Future<List<PageUrl>> downloadChapter(
|
|||
isar.downloads.putSync(download..chapter.value = chapter);
|
||||
});
|
||||
} else {
|
||||
final download = isar.downloads.filter().chapterIdEqualTo(chapter.id!).findFirstSync()!;
|
||||
final download = isar.downloads
|
||||
.filter()
|
||||
.chapterIdEqualTo(chapter.id!)
|
||||
.findFirstSync()!;
|
||||
isar.writeTxnSync(() {
|
||||
isar.downloads.putSync(download
|
||||
..succeeded = succeeded
|
||||
|
|
@ -292,7 +328,10 @@ Future<List<PageUrl>> downloadChapter(
|
|||
taskProgressCallback: (taskProgress) async {
|
||||
final progress = taskProgress.progress;
|
||||
if (!isManga && !hasM3U8File) {
|
||||
bool isEmpty = isar.downloads.filter().chapterIdEqualTo(chapter.id!).isEmptySync();
|
||||
bool isEmpty = isar.downloads
|
||||
.filter()
|
||||
.chapterIdEqualTo(chapter.id!)
|
||||
.isEmptySync();
|
||||
if (isEmpty) {
|
||||
final download = Download(
|
||||
succeeded: (progress * 100).toInt(),
|
||||
|
|
@ -307,7 +346,10 @@ Future<List<PageUrl>> downloadChapter(
|
|||
isar.downloads.putSync(download..chapter.value = chapter);
|
||||
});
|
||||
} else {
|
||||
final download = isar.downloads.filter().chapterIdEqualTo(chapter.id!).findFirstSync()!;
|
||||
final download = isar.downloads
|
||||
.filter()
|
||||
.chapterIdEqualTo(chapter.id!)
|
||||
.findFirstSync()!;
|
||||
isar.writeTxnSync(() {
|
||||
isar.downloads.putSync(download
|
||||
..succeeded = (progress * 100).toInt()
|
||||
|
|
@ -317,11 +359,14 @@ Future<List<PageUrl>> downloadChapter(
|
|||
}
|
||||
}
|
||||
if (progress == 1.0) {
|
||||
final file = File(p.join(tempDir.path, taskProgress.task.directory, taskProgress.task.filename));
|
||||
final file = File(p.join(tempDir.path, taskProgress.task.directory,
|
||||
taskProgress.task.filename));
|
||||
if (hasM3U8File) {
|
||||
final newFile = await file.copy(p.join(path!.path, chapterName, taskProgress.task.filename));
|
||||
final newFile = await file.copy(
|
||||
p.join(path!.path, chapterName, taskProgress.task.filename));
|
||||
await file.delete();
|
||||
await m3u8Downloader?.processBytes(newFile, tsKey, tsIv, m3u8MediaSequence);
|
||||
await m3u8Downloader?.processBytes(
|
||||
newFile, tsKey, tsIv, m3u8MediaSequence);
|
||||
} else {
|
||||
await file.copy(p.join(path!.path, taskProgress.task.filename));
|
||||
await file.delete();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,11 @@ class MangaHomeScreen extends ConsumerStatefulWidget {
|
|||
final bool isLatest;
|
||||
final String query;
|
||||
const MangaHomeScreen(
|
||||
{required this.source, this.query = "", this.isSearch = false, this.isLatest = false, super.key});
|
||||
{required this.source,
|
||||
this.query = "",
|
||||
this.isSearch = false,
|
||||
this.isLatest = false,
|
||||
super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<MangaHomeScreen> createState() => _MangaHomeScreenState();
|
||||
|
|
@ -86,9 +90,14 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
source: source,
|
||||
page: _page + 1,
|
||||
).future);
|
||||
} else if (_selectedIndex == 2 && (_isSearch && _query.isNotEmpty) || _isFiltering) {
|
||||
mangaRes = await ref
|
||||
.watch(searchProvider(source: source, query: _query, page: _page + 1, filterList: filters).future);
|
||||
} else if (_selectedIndex == 2 && (_isSearch && _query.isNotEmpty) ||
|
||||
_isFiltering) {
|
||||
mangaRes = await ref.watch(searchProvider(
|
||||
source: source,
|
||||
query: _query,
|
||||
page: _page + 1,
|
||||
filterList: filters)
|
||||
.future);
|
||||
}
|
||||
}
|
||||
if (mangaRes!.list.isNotEmpty) {
|
||||
|
|
@ -115,8 +124,10 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
Widget build(BuildContext context) {
|
||||
final supportsLatest = ref.watch(supportsLatestProvider(source: source));
|
||||
final filterList = getFilterList(source: source);
|
||||
if (_selectedIndex == 2 && (_isSearch && _query.isNotEmpty) || _isFiltering) {
|
||||
_getManga = ref.watch(searchProvider(source: source, query: _query, page: 1, filterList: filters));
|
||||
if (_selectedIndex == 2 && (_isSearch && _query.isNotEmpty) ||
|
||||
_isFiltering) {
|
||||
_getManga = ref.watch(searchProvider(
|
||||
source: source, query: _query, page: 1, filterList: filters));
|
||||
} else if (_selectedIndex == 1 && !_isSearch && _query.isEmpty) {
|
||||
_getManga = ref.watch(getLatestUpdatesProvider(source: source, page: 1));
|
||||
} else if (_selectedIndex == 0 && !_isSearch && _query.isEmpty) {
|
||||
|
|
@ -125,7 +136,9 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
final l10n = context.l10n;
|
||||
final displayType = ref.watch(mangaHomeDisplayTypeStateProvider);
|
||||
final displayTypeIcon = switch (displayType) {
|
||||
DisplayType.comfortableGrid || DisplayType.compactGrid => Icons.view_module,
|
||||
DisplayType.comfortableGrid ||
|
||||
DisplayType.compactGrid =>
|
||||
Icons.view_module,
|
||||
_ => Icons.view_list,
|
||||
};
|
||||
return Scaffold(
|
||||
|
|
@ -179,13 +192,16 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
_isSearch = true;
|
||||
});
|
||||
},
|
||||
icon: Icon(Icons.search, color: Theme.of(context).hintColor)),
|
||||
icon:
|
||||
Icon(Icons.search, color: Theme.of(context).hintColor)),
|
||||
PopupMenuButton(
|
||||
popUpAnimationStyle: popupAnimationStyle,
|
||||
icon: Icon(displayTypeIcon),
|
||||
itemBuilder: (context) {
|
||||
final displayType = ref.watch(mangaHomeDisplayTypeStateProvider);
|
||||
final displayTypeNotifier = ref.read(mangaHomeDisplayTypeStateProvider.notifier);
|
||||
final displayType =
|
||||
ref.watch(mangaHomeDisplayTypeStateProvider);
|
||||
final displayTypeNotifier =
|
||||
ref.read(mangaHomeDisplayTypeStateProvider.notifier);
|
||||
return [
|
||||
PopupMenuItem<int>(
|
||||
value: 0,
|
||||
|
|
@ -242,11 +258,17 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
},
|
||||
onSelected: (value) async {
|
||||
if (value == 0) {
|
||||
final baseUrl = ref.watch(sourceBaseUrlProvider(source: source));
|
||||
Map<String, dynamic> data = {'url': baseUrl, 'sourceId': source.id.toString(), 'title': ''};
|
||||
final baseUrl =
|
||||
ref.watch(sourceBaseUrlProvider(source: source));
|
||||
Map<String, dynamic> data = {
|
||||
'url': baseUrl,
|
||||
'sourceId': source.id.toString(),
|
||||
'title': ''
|
||||
};
|
||||
context.push("/mangawebview", extra: data);
|
||||
} else {
|
||||
final res = await context.push('/extension_detail', extra: source);
|
||||
final res =
|
||||
await context.push('/extension_detail', extra: source);
|
||||
if (res != null && mounted) {
|
||||
setState(() {
|
||||
source = res as Source;
|
||||
|
|
@ -284,7 +306,8 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
if (index == 2) {
|
||||
final result = await showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => StatefulBuilder(builder: (context, setState) {
|
||||
builder: (context) =>
|
||||
StatefulBuilder(builder: (context, setState) {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
|
|
@ -294,20 +317,25 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
TextButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
filters = getFilterList(source: source);
|
||||
filters = getFilterList(
|
||||
source: source);
|
||||
});
|
||||
},
|
||||
child: Text(l10n.reset),
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(backgroundColor: context.primaryColor),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor:
|
||||
context.primaryColor),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, 'filter');
|
||||
},
|
||||
child: Text(
|
||||
l10n.filter,
|
||||
style: TextStyle(color: Theme.of(context).scaffoldBackgroundColor),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context)
|
||||
.scaffoldBackgroundColor),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -339,8 +367,11 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
});
|
||||
}
|
||||
|
||||
_getManga = ref
|
||||
.refresh(searchProvider(source: source, query: _query, page: 1, filterList: filters));
|
||||
_getManga = ref.refresh(searchProvider(
|
||||
source: source,
|
||||
query: _query,
|
||||
page: 1,
|
||||
filterList: filters));
|
||||
}
|
||||
} else {
|
||||
_mangaList.clear();
|
||||
|
|
@ -385,7 +416,8 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
_mangaList.addAll(data.list);
|
||||
}
|
||||
Widget buildProgressIndicator() {
|
||||
return !(data!.list.isNotEmpty && (data.hasNextPage || _hasNextPage))
|
||||
return !(data!.list.isNotEmpty &&
|
||||
(data.hasNextPage || _hasNextPage))
|
||||
? Container()
|
||||
: _isLoading
|
||||
? const Center(
|
||||
|
|
@ -401,7 +433,9 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
padding: const EdgeInsets.all(4),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(5))),
|
||||
onPressed: () {
|
||||
if (!_getManga!.isLoading) {
|
||||
if (mounted) {
|
||||
|
|
@ -420,15 +454,19 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
}
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
l10n.load_more,
|
||||
style: const TextStyle(overflow: TextOverflow.ellipsis),
|
||||
style: const TextStyle(
|
||||
overflow: TextOverflow.ellipsis),
|
||||
maxLines: 2,
|
||||
),
|
||||
const Icon(Icons.arrow_forward_outlined),
|
||||
const Icon(
|
||||
Icons.arrow_forward_outlined),
|
||||
],
|
||||
)),
|
||||
);
|
||||
|
|
@ -438,8 +476,12 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
return Center(child: Text(l10n.no_result));
|
||||
}
|
||||
_scrollController.addListener(() {
|
||||
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
|
||||
if (_mangaList.isNotEmpty && (_hasNextPage) && !_isLoading && !_getManga!.isLoading) {
|
||||
if (_scrollController.position.pixels ==
|
||||
_scrollController.position.maxScrollExtent) {
|
||||
if (_mangaList.isNotEmpty &&
|
||||
(_hasNextPage) &&
|
||||
!_isLoading &&
|
||||
!_getManga!.isLoading) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
|
|
@ -457,9 +499,13 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
}
|
||||
});
|
||||
|
||||
_length = source.isFullData! ? _fullDataLength : _mangaList.length;
|
||||
_length = (_mangaList.length < _length ? _mangaList.length : _length);
|
||||
final isComfortableGrid = displayType == DisplayType.comfortableGrid;
|
||||
_length =
|
||||
source.isFullData! ? _fullDataLength : _mangaList.length;
|
||||
_length = (_mangaList.length < _length
|
||||
? _mangaList.length
|
||||
: _length);
|
||||
final isComfortableGrid =
|
||||
displayType == DisplayType.comfortableGrid;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
|
|
@ -474,16 +520,21 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
return buildProgressIndicator();
|
||||
}
|
||||
return MangaHomeImageCardListTile(
|
||||
isManga: source.isManga ?? true, manga: _mangaList[index], source: source);
|
||||
isManga: source.isManga ?? true,
|
||||
manga: _mangaList[index],
|
||||
source: source);
|
||||
})
|
||||
: Consumer(builder: (context, ref, child) {
|
||||
final gridSize = ref.watch(libraryGridSizeStateProvider(isManga: source.isManga!));
|
||||
final gridSize = ref.watch(
|
||||
libraryGridSizeStateProvider(
|
||||
isManga: source.isManga!));
|
||||
|
||||
return GridViewWidget(
|
||||
gridSize: gridSize,
|
||||
controller: _scrollController,
|
||||
itemCount: _length + 1,
|
||||
childAspectRatio: isComfortableGrid ? 0.642 : 0.69,
|
||||
childAspectRatio:
|
||||
isComfortableGrid ? 0.642 : 0.69,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == _length) {
|
||||
return buildProgressIndicator();
|
||||
|
|
@ -514,12 +565,22 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
if (_selectedIndex == 2 && (_isSearch && _query.isNotEmpty) || _isFiltering) {
|
||||
ref.invalidate(
|
||||
searchProvider(source: source, query: _query, page: 1, filterList: filters));
|
||||
} else if (_selectedIndex == 1 && !_isSearch && _query.isEmpty) {
|
||||
ref.invalidate(getLatestUpdatesProvider(source: source, page: 1));
|
||||
} else if (_selectedIndex == 0 && !_isSearch && _query.isEmpty) {
|
||||
if (_selectedIndex == 2 &&
|
||||
(_isSearch && _query.isNotEmpty) ||
|
||||
_isFiltering) {
|
||||
ref.invalidate(searchProvider(
|
||||
source: source,
|
||||
query: _query,
|
||||
page: 1,
|
||||
filterList: filters));
|
||||
} else if (_selectedIndex == 1 &&
|
||||
!_isSearch &&
|
||||
_query.isEmpty) {
|
||||
ref.invalidate(getLatestUpdatesProvider(
|
||||
source: source, page: 1));
|
||||
} else if (_selectedIndex == 0 &&
|
||||
!_isSearch &&
|
||||
_query.isEmpty) {
|
||||
ref.invalidate(getPopularProvider(
|
||||
source: source,
|
||||
page: 1,
|
||||
|
|
@ -537,12 +598,14 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
children: [
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
final baseUrl = ref.watch(sourceBaseUrlProvider(source: source));
|
||||
final baseUrl = ref.watch(
|
||||
sourceBaseUrlProvider(source: source));
|
||||
Map<String, dynamic> data = {
|
||||
'url': baseUrl,
|
||||
'sourceId': source.id.toString(),
|
||||
'title': '',
|
||||
"hasCloudFlare": source.hasCloudflare ?? false
|
||||
"hasCloudFlare":
|
||||
source.hasCloudflare ?? false
|
||||
};
|
||||
context.push("/mangawebview", extra: data);
|
||||
},
|
||||
|
|
@ -580,7 +643,11 @@ class MangaHomeImageCard extends ConsumerStatefulWidget {
|
|||
final Source source;
|
||||
final bool isComfortableGrid;
|
||||
const MangaHomeImageCard(
|
||||
{super.key, required this.manga, required this.source, required this.isManga, required this.isComfortableGrid});
|
||||
{super.key,
|
||||
required this.manga,
|
||||
required this.source,
|
||||
required this.isManga,
|
||||
required this.isComfortableGrid});
|
||||
|
||||
@override
|
||||
ConsumerState<MangaHomeImageCard> createState() => _MangaHomeImageCardState();
|
||||
|
|
@ -607,19 +674,28 @@ class MangaHomeImageCardListTile extends ConsumerStatefulWidget {
|
|||
final MManga manga;
|
||||
final bool isManga;
|
||||
final Source source;
|
||||
const MangaHomeImageCardListTile({super.key, required this.manga, required this.source, required this.isManga});
|
||||
const MangaHomeImageCardListTile(
|
||||
{super.key,
|
||||
required this.manga,
|
||||
required this.source,
|
||||
required this.isManga});
|
||||
|
||||
@override
|
||||
ConsumerState<MangaHomeImageCardListTile> createState() => _MangaHomeImageCardListTileState();
|
||||
ConsumerState<MangaHomeImageCardListTile> createState() =>
|
||||
_MangaHomeImageCardListTileState();
|
||||
}
|
||||
|
||||
class _MangaHomeImageCardListTileState extends ConsumerState<MangaHomeImageCardListTile>
|
||||
class _MangaHomeImageCardListTileState
|
||||
extends ConsumerState<MangaHomeImageCardListTile>
|
||||
with AutomaticKeepAliveClientMixin<MangaHomeImageCardListTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context);
|
||||
|
||||
return MangaImageCardListTileWidget(getMangaDetail: widget.manga, source: widget.source, isManga: widget.isManga);
|
||||
return MangaImageCardListTileWidget(
|
||||
getMangaDetail: widget.manga,
|
||||
source: widget.source,
|
||||
isManga: widget.isManga);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
|||
class FilterWidget extends StatelessWidget {
|
||||
final List<dynamic> filterList;
|
||||
final Function(List<dynamic>) onChanged;
|
||||
const FilterWidget({super.key, required this.onChanged, required this.filterList});
|
||||
const FilterWidget(
|
||||
{super.key, required this.onChanged, required this.filterList});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -83,14 +84,18 @@ class FilterWidget extends StatelessWidget {
|
|||
final selected = filterState.values[filterState.state.index] == e;
|
||||
return ListTile(
|
||||
dense: true,
|
||||
leading: Icon(ascending ? Icons.arrow_upward_rounded : Icons.arrow_downward_rounded,
|
||||
leading: Icon(
|
||||
ascending
|
||||
? Icons.arrow_upward_rounded
|
||||
: Icons.arrow_downward_rounded,
|
||||
color: selected ? null : Colors.transparent),
|
||||
title: Text(e.name),
|
||||
onTap: () {
|
||||
if (selected) {
|
||||
filterState.state.ascending = !ascending;
|
||||
} else {
|
||||
filterState.state.index = filterState.values.indexWhere((element) => element == e);
|
||||
filterState.state.index = filterState.values
|
||||
.indexWhere((element) => element == e);
|
||||
}
|
||||
filterList[idx] = filterState;
|
||||
onChanged(filterList);
|
||||
|
|
@ -113,20 +118,24 @@ class FilterWidget extends StatelessWidget {
|
|||
Expanded(
|
||||
child: DropdownButtonHideUnderline(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 25),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8, horizontal: 25),
|
||||
child: DropdownButton(
|
||||
icon: const Icon(Icons.keyboard_arrow_down),
|
||||
isExpanded: true,
|
||||
value: filterState.values[filterState.state],
|
||||
hint: Text(filterState.name, style: const TextStyle(fontSize: 13)),
|
||||
hint: Text(filterState.name,
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
items: filterState.values
|
||||
.map((e) => DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(e.name, style: const TextStyle(fontSize: 13)),
|
||||
child: Text(e.name,
|
||||
style: const TextStyle(fontSize: 13)),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (value) {
|
||||
filterState.state = filterState.values.indexWhere((element) => element == value);
|
||||
filterState.state = filterState.values
|
||||
.indexWhere((element) => element == value);
|
||||
onChanged(filterList);
|
||||
},
|
||||
),
|
||||
|
|
@ -147,10 +156,15 @@ class SeachFormTextFieldWidget extends StatefulWidget {
|
|||
final String labelText;
|
||||
final String text;
|
||||
final Function(String) onChanged;
|
||||
const SeachFormTextFieldWidget({super.key, required this.text, required this.onChanged, required this.labelText});
|
||||
const SeachFormTextFieldWidget(
|
||||
{super.key,
|
||||
required this.text,
|
||||
required this.onChanged,
|
||||
required this.labelText});
|
||||
|
||||
@override
|
||||
State<SeachFormTextFieldWidget> createState() => _SeachFormTextFieldWidgetState();
|
||||
State<SeachFormTextFieldWidget> createState() =>
|
||||
_SeachFormTextFieldWidgetState();
|
||||
}
|
||||
|
||||
class _SeachFormTextFieldWidgetState extends State<SeachFormTextFieldWidget> {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ class MangasCardSelector extends StatelessWidget {
|
|||
final bool selected;
|
||||
final VoidCallback onPressed;
|
||||
const MangasCardSelector(
|
||||
{super.key, required this.text, required this.icon, required this.selected, required this.onPressed});
|
||||
{super.key,
|
||||
required this.text,
|
||||
required this.icon,
|
||||
required this.selected,
|
||||
required this.onPressed});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -18,7 +22,8 @@ class MangasCardSelector extends StatelessWidget {
|
|||
padding: const EdgeInsets.all(0),
|
||||
side: BorderSide(width: 0.6, color: context.primaryColor),
|
||||
backgroundColor: selected ? context.primaryColor : null,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(7)),
|
||||
shape:
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(7)),
|
||||
),
|
||||
onPressed: onPressed,
|
||||
child: Padding(
|
||||
|
|
|
|||
|
|
@ -27,14 +27,17 @@ class DoubleColummView extends StatefulWidget {
|
|||
State<DoubleColummView> createState() => _DoubleColummViewState();
|
||||
}
|
||||
|
||||
class _DoubleColummViewState extends State<DoubleColummView> with TickerProviderStateMixin {
|
||||
class _DoubleColummViewState extends State<DoubleColummView>
|
||||
with TickerProviderStateMixin {
|
||||
late AnimationController _scaleAnimationController;
|
||||
late Animation<double> _animation;
|
||||
Alignment _scalePosition = Alignment.center;
|
||||
final PhotoViewController _photoViewController = PhotoViewController();
|
||||
final PhotoViewScaleStateController _photoViewScaleStateController = PhotoViewScaleStateController();
|
||||
final PhotoViewScaleStateController _photoViewScaleStateController =
|
||||
PhotoViewScaleStateController();
|
||||
Duration? _doubleTapAnimationDuration() {
|
||||
int doubleTapAnimationValue = isar.settings.getSync(227)!.doubleTapAnimationSpeed!;
|
||||
int doubleTapAnimationValue =
|
||||
isar.settings.getSync(227)!.doubleTapAnimationSpeed!;
|
||||
if (doubleTapAnimationValue == 0) {
|
||||
return const Duration(milliseconds: 10);
|
||||
} else if (doubleTapAnimationValue == 1) {
|
||||
|
|
@ -43,7 +46,8 @@ class _DoubleColummViewState extends State<DoubleColummView> with TickerProvider
|
|||
return const Duration(milliseconds: 200);
|
||||
}
|
||||
|
||||
void _onScaleEnd(BuildContext context, ScaleEndDetails details, PhotoViewControllerValue controllerValue) {
|
||||
void _onScaleEnd(BuildContext context, ScaleEndDetails details,
|
||||
PhotoViewControllerValue controllerValue) {
|
||||
if (controllerValue.scale! < 1) {
|
||||
_photoViewScaleStateController.reset();
|
||||
}
|
||||
|
|
@ -52,15 +56,16 @@ class _DoubleColummViewState extends State<DoubleColummView> with TickerProvider
|
|||
double get pixelRatio => View.of(context).devicePixelRatio;
|
||||
Size get size => View.of(context).physicalSize / pixelRatio;
|
||||
Alignment _computeAlignmentByTapOffset(Offset offset) {
|
||||
return Alignment(
|
||||
(offset.dx - size.width / 2) / (size.width / 2), (offset.dy - size.height / 2) / (size.height / 2));
|
||||
return Alignment((offset.dx - size.width / 2) / (size.width / 2),
|
||||
(offset.dy - size.height / 2) / (size.height / 2));
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_scaleAnimationController = AnimationController(duration: _doubleTapAnimationDuration(), vsync: this);
|
||||
_animation =
|
||||
Tween(begin: 1.0, end: 2.0).animate(CurvedAnimation(curve: Curves.ease, parent: _scaleAnimationController));
|
||||
_scaleAnimationController = AnimationController(
|
||||
duration: _doubleTapAnimationDuration(), vsync: this);
|
||||
_animation = Tween(begin: 1.0, end: 2.0).animate(
|
||||
CurvedAnimation(curve: Curves.ease, parent: _scaleAnimationController));
|
||||
_animation.addListener(() {
|
||||
_photoViewController.scale = _animation.value;
|
||||
});
|
||||
|
|
@ -122,32 +127,42 @@ class _DoubleColummViewState extends State<DoubleColummView> with TickerProvider
|
|||
child: ImageViewPaged(
|
||||
data: widget.datas[0]!,
|
||||
loadStateChanged: (state) {
|
||||
if (state.extendedImageLoadState == LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress = state.loadingProgress;
|
||||
final double progress = loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress =
|
||||
state.loadingProgress;
|
||||
final double progress =
|
||||
loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
return Container(
|
||||
color: getBackgroundColor(widget.backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child: CircularProgressIndicatorAnimateRotate(progress: progress),
|
||||
child: CircularProgressIndicatorAnimateRotate(
|
||||
progress: progress),
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState == LoadState.completed) {
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.completed) {
|
||||
widget.isFailedToLoadImage(false);
|
||||
return Image(image: state.imageProvider);
|
||||
}
|
||||
if (state.extendedImageLoadState == LoadState.failed) {
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.failed) {
|
||||
widget.isFailedToLoadImage(true);
|
||||
return Container(
|
||||
color: getBackgroundColor(widget.backgroundColor),
|
||||
color:
|
||||
getBackgroundColor(widget.backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
l10n.image_loading_error,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: 0.7)),
|
||||
style: TextStyle(
|
||||
color: Colors.white
|
||||
.withValues(alpha: 0.7)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
|
|
@ -162,9 +177,14 @@ class _DoubleColummViewState extends State<DoubleColummView> with TickerProvider
|
|||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor, borderRadius: BorderRadius.circular(30)),
|
||||
color: context.primaryColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(30)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 16),
|
||||
child: Text(
|
||||
l10n.retry,
|
||||
),
|
||||
|
|
@ -176,7 +196,8 @@ class _DoubleColummViewState extends State<DoubleColummView> with TickerProvider
|
|||
}
|
||||
return null;
|
||||
},
|
||||
onLongPressData: (datas) => widget.onLongPressData.call(datas),
|
||||
onLongPressData: (datas) =>
|
||||
widget.onLongPressData.call(datas),
|
||||
),
|
||||
),
|
||||
// if (widget.datas[1] != null) const SizedBox(width: 10),
|
||||
|
|
@ -185,32 +206,42 @@ class _DoubleColummViewState extends State<DoubleColummView> with TickerProvider
|
|||
child: ImageViewPaged(
|
||||
data: widget.datas[1]!,
|
||||
loadStateChanged: (state) {
|
||||
if (state.extendedImageLoadState == LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress = state.loadingProgress;
|
||||
final double progress = loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress =
|
||||
state.loadingProgress;
|
||||
final double progress =
|
||||
loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
return Container(
|
||||
color: getBackgroundColor(widget.backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child: CircularProgressIndicatorAnimateRotate(progress: progress),
|
||||
child: CircularProgressIndicatorAnimateRotate(
|
||||
progress: progress),
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState == LoadState.completed) {
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.completed) {
|
||||
widget.isFailedToLoadImage(false);
|
||||
return Image(image: state.imageProvider);
|
||||
}
|
||||
if (state.extendedImageLoadState == LoadState.failed) {
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.failed) {
|
||||
widget.isFailedToLoadImage(true);
|
||||
return Container(
|
||||
color: getBackgroundColor(widget.backgroundColor),
|
||||
color:
|
||||
getBackgroundColor(widget.backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
l10n.image_loading_error,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: 0.7)),
|
||||
style: TextStyle(
|
||||
color: Colors.white
|
||||
.withValues(alpha: 0.7)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
|
|
@ -225,9 +256,14 @@ class _DoubleColummViewState extends State<DoubleColummView> with TickerProvider
|
|||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor, borderRadius: BorderRadius.circular(30)),
|
||||
color: context.primaryColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(30)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
horizontal: 16),
|
||||
child: Text(
|
||||
l10n.retry,
|
||||
),
|
||||
|
|
@ -239,7 +275,8 @@ class _DoubleColummViewState extends State<DoubleColummView> with TickerProvider
|
|||
}
|
||||
return null;
|
||||
},
|
||||
onLongPressData: (datas) => widget.onLongPressData.call(datas),
|
||||
onLongPressData: (datas) =>
|
||||
widget.onLongPressData.call(datas),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -39,14 +39,18 @@ class DoubleColummVerticalView extends StatelessWidget {
|
|||
data: datas[0]!,
|
||||
loadStateChanged: (state) {
|
||||
if (state.extendedImageLoadState == LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress = state.loadingProgress;
|
||||
final double progress = loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
final ImageChunkEvent? loadingProgress =
|
||||
state.loadingProgress;
|
||||
final double progress =
|
||||
loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
return Container(
|
||||
color: getBackgroundColor(backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child: CircularProgressIndicatorAnimateRotate(progress: progress),
|
||||
child: CircularProgressIndicatorAnimateRotate(
|
||||
progress: progress),
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState == LoadState.completed) {
|
||||
|
|
@ -63,7 +67,8 @@ class DoubleColummVerticalView extends StatelessWidget {
|
|||
children: [
|
||||
Text(
|
||||
l10n.image_loading_error,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: 0.7)),
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.7)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
|
|
@ -78,9 +83,12 @@ class DoubleColummVerticalView extends StatelessWidget {
|
|||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor, borderRadius: BorderRadius.circular(30)),
|
||||
color: context.primaryColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(30)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8, horizontal: 16),
|
||||
child: Text(
|
||||
l10n.retry,
|
||||
),
|
||||
|
|
@ -102,14 +110,18 @@ class DoubleColummVerticalView extends StatelessWidget {
|
|||
data: datas[1]!,
|
||||
loadStateChanged: (state) {
|
||||
if (state.extendedImageLoadState == LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress = state.loadingProgress;
|
||||
final double progress = loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
final ImageChunkEvent? loadingProgress =
|
||||
state.loadingProgress;
|
||||
final double progress =
|
||||
loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
return Container(
|
||||
color: getBackgroundColor(backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child: CircularProgressIndicatorAnimateRotate(progress: progress),
|
||||
child: CircularProgressIndicatorAnimateRotate(
|
||||
progress: progress),
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState == LoadState.completed) {
|
||||
|
|
@ -126,7 +138,8 @@ class DoubleColummVerticalView extends StatelessWidget {
|
|||
children: [
|
||||
Text(
|
||||
l10n.image_loading_error,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: 0.7)),
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.7)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
|
|
@ -141,9 +154,12 @@ class DoubleColummVerticalView extends StatelessWidget {
|
|||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor, borderRadius: BorderRadius.circular(30)),
|
||||
color: context.primaryColor,
|
||||
borderRadius:
|
||||
BorderRadius.circular(30)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8, horizontal: 16),
|
||||
child: Text(
|
||||
l10n.retry,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ class ImageViewPaged extends ConsumerWidget {
|
|||
final Function(UChapDataPreload data) onLongPressData;
|
||||
final Widget? Function(ExtendedImageState state) loadStateChanged;
|
||||
final Function(ExtendedImageGestureState state)? onDoubleTap;
|
||||
final GestureConfig Function(ExtendedImageState state)? initGestureConfigHandler;
|
||||
final GestureConfig Function(ExtendedImageState state)?
|
||||
initGestureConfigHandler;
|
||||
const ImageViewPaged({
|
||||
super.key,
|
||||
required this.data,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ class ImageViewVertical extends ConsumerWidget {
|
|||
if (state.extendedImageLoadState == LoadState.loading) {
|
||||
final ImageChunkEvent? loadingProgress = state.loadingProgress;
|
||||
final double progress = loadingProgress?.expectedTotalBytes != null
|
||||
? loadingProgress!.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
|
||||
? loadingProgress!.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: 0;
|
||||
return Container(
|
||||
color: Colors.black,
|
||||
|
|
@ -59,7 +60,8 @@ class ImageViewVertical extends ConsumerWidget {
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(context.l10n.image_loading_error,
|
||||
style: TextStyle(color: Colors.white.withValues(alpha: 0.7))),
|
||||
style: TextStyle(
|
||||
color: Colors.white.withValues(alpha: 0.7))),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GestureDetector(
|
||||
|
|
@ -72,10 +74,12 @@ class ImageViewVertical extends ConsumerWidget {
|
|||
failedToLoadImage(false);
|
||||
},
|
||||
child: Container(
|
||||
decoration:
|
||||
BoxDecoration(color: context.primaryColor, borderRadius: BorderRadius.circular(30)),
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor,
|
||||
borderRadius: BorderRadius.circular(30)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8, horizontal: 16),
|
||||
child: Text(
|
||||
context.l10n.retry,
|
||||
),
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue