mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-21 11:51:57 +00:00
Refactor dependencies and remove unused packages; update Flutter HTML package; add novel reader settings UI
This commit is contained in:
parent
430e062a06
commit
af20e084b0
21 changed files with 2927 additions and 946 deletions
|
|
@ -244,6 +244,22 @@ class Settings {
|
|||
@enumerated
|
||||
late NovelTextAlign novelTextAlign;
|
||||
|
||||
String? novelReaderTheme;
|
||||
|
||||
String? novelReaderTextColor;
|
||||
|
||||
int? novelReaderPadding;
|
||||
|
||||
double? novelReaderLineHeight;
|
||||
|
||||
bool? novelShowScrollPercentage;
|
||||
|
||||
bool? novelAutoScroll;
|
||||
|
||||
bool? novelRemoveExtraParagraphSpacing;
|
||||
|
||||
bool? novelTapToScroll;
|
||||
|
||||
List<String>? navigationOrder;
|
||||
|
||||
List<String>? hideItems;
|
||||
|
|
@ -392,6 +408,14 @@ class Settings {
|
|||
this.novelDisplayType = DisplayType.comfortableGrid,
|
||||
this.novelFontSize = 14,
|
||||
this.novelTextAlign = NovelTextAlign.left,
|
||||
this.novelReaderTheme = '#292832',
|
||||
this.novelReaderTextColor = '#CCCCCC',
|
||||
this.novelReaderPadding = 16,
|
||||
this.novelReaderLineHeight = 1.5,
|
||||
this.novelShowScrollPercentage = true,
|
||||
this.novelAutoScroll = false,
|
||||
this.novelRemoveExtraParagraphSpacing = false,
|
||||
this.novelTapToScroll = false,
|
||||
this.navigationOrder,
|
||||
this.hideItems,
|
||||
this.clearChapterCacheOnAppLaunch = false,
|
||||
|
|
@ -605,6 +629,22 @@ class Settings {
|
|||
}
|
||||
novelTextAlign = NovelTextAlign
|
||||
.values[json['novelTextAlign'] ?? NovelTextAlign.left.index];
|
||||
if (json['novelReaderTheme'] != null) {
|
||||
novelReaderTheme = json['novelReaderTheme'];
|
||||
}
|
||||
if (json['novelReaderTextColor'] != null) {
|
||||
novelReaderTextColor = json['novelReaderTextColor'];
|
||||
}
|
||||
if (json['novelReaderPadding'] != null) {
|
||||
novelReaderPadding = json['novelReaderPadding'];
|
||||
}
|
||||
if (json['novelReaderLineHeight'] != null) {
|
||||
novelReaderLineHeight = json['novelReaderLineHeight'];
|
||||
}
|
||||
novelShowScrollPercentage = json['novelShowScrollPercentage'];
|
||||
novelAutoScroll = json['novelAutoScroll'];
|
||||
novelRemoveExtraParagraphSpacing = json['novelRemoveExtraParagraphSpacing'];
|
||||
novelTapToScroll = json['novelTapToScroll'];
|
||||
if (json['navigationOrder'] != null) {
|
||||
navigationOrder = (json['navigationOrder'] as List).cast<String>();
|
||||
}
|
||||
|
|
@ -783,6 +823,14 @@ class Settings {
|
|||
'novelDisplayType': novelDisplayType.index,
|
||||
'novelFontSize': novelFontSize,
|
||||
'novelTextAlign': novelTextAlign.index,
|
||||
'novelReaderTheme': novelReaderTheme,
|
||||
'novelReaderTextColor': novelReaderTextColor,
|
||||
'novelReaderPadding': novelReaderPadding,
|
||||
'novelReaderLineHeight': novelReaderLineHeight,
|
||||
'novelShowScrollPercentage': novelShowScrollPercentage,
|
||||
'novelAutoScroll': novelAutoScroll,
|
||||
'novelRemoveExtraParagraphSpacing': novelRemoveExtraParagraphSpacing,
|
||||
'novelTapToScroll': novelTapToScroll,
|
||||
'navigationOrder': navigationOrder,
|
||||
'hideItems': hideItems,
|
||||
'clearChapterCacheOnAppLaunch': clearChapterCacheOnAppLaunch,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -40,4 +40,4 @@ final class MigrationProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$migrationHash() => r'2a82120544e693a3162da887a3ca1b3066f3799f';
|
||||
String _$migrationHash() => r'43d62ddf79798d616ac7d11ce50a47551ef42c98';
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ final class CropBordersProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$cropBordersHash() => r'04b24357737d6cc75caa38feca77bb5d41f00aa6';
|
||||
String _$cropBordersHash() => r'f60987c3f38afd5e10263f3d6935e6007ff942f0';
|
||||
|
||||
final class CropBordersFamily extends $Family
|
||||
with
|
||||
|
|
|
|||
|
|
@ -302,3 +302,165 @@ class NovelTextAlignState extends _$NovelTextAlignState {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class NovelReaderThemeState extends _$NovelReaderThemeState {
|
||||
@override
|
||||
String build() {
|
||||
return isar.settings.getSync(227)!.novelReaderTheme ?? '#292832';
|
||||
}
|
||||
|
||||
void set(String value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!
|
||||
..novelReaderTheme = value
|
||||
..updatedAt = DateTime.now().millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class NovelReaderTextColorState extends _$NovelReaderTextColorState {
|
||||
@override
|
||||
String build() {
|
||||
return isar.settings.getSync(227)!.novelReaderTextColor ?? '#CCCCCC';
|
||||
}
|
||||
|
||||
void set(String value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!
|
||||
..novelReaderTextColor = value
|
||||
..updatedAt = DateTime.now().millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class NovelReaderPaddingState extends _$NovelReaderPaddingState {
|
||||
@override
|
||||
int build() {
|
||||
return isar.settings.getSync(227)!.novelReaderPadding ?? 16;
|
||||
}
|
||||
|
||||
void set(int value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!
|
||||
..novelReaderPadding = value
|
||||
..updatedAt = DateTime.now().millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class NovelReaderLineHeightState extends _$NovelReaderLineHeightState {
|
||||
@override
|
||||
double build() {
|
||||
return isar.settings.getSync(227)!.novelReaderLineHeight ?? 1.5;
|
||||
}
|
||||
|
||||
void set(double value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!
|
||||
..novelReaderLineHeight = value
|
||||
..updatedAt = DateTime.now().millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class NovelShowScrollPercentageState extends _$NovelShowScrollPercentageState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.novelShowScrollPercentage ?? true;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!
|
||||
..novelShowScrollPercentage = value
|
||||
..updatedAt = DateTime.now().millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class NovelAutoScrollState extends _$NovelAutoScrollState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.novelAutoScroll ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!
|
||||
..novelAutoScroll = value
|
||||
..updatedAt = DateTime.now().millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class NovelRemoveExtraParagraphSpacingState
|
||||
extends _$NovelRemoveExtraParagraphSpacingState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.novelRemoveExtraParagraphSpacing ??
|
||||
false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!
|
||||
..novelRemoveExtraParagraphSpacing = value
|
||||
..updatedAt = DateTime.now().millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class NovelTapToScrollState extends _$NovelTapToScrollState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.novelTapToScroll ?? false;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(
|
||||
settings!
|
||||
..novelTapToScroll = value
|
||||
..updatedAt = DateTime.now().millisecondsSinceEpoch,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -764,3 +764,440 @@ abstract class _$NovelTextAlignState extends $Notifier<NovelTextAlign> {
|
|||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(NovelReaderThemeState)
|
||||
const novelReaderThemeStateProvider = NovelReaderThemeStateProvider._();
|
||||
|
||||
final class NovelReaderThemeStateProvider
|
||||
extends $NotifierProvider<NovelReaderThemeState, String> {
|
||||
const NovelReaderThemeStateProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'novelReaderThemeStateProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$novelReaderThemeStateHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
NovelReaderThemeState create() => NovelReaderThemeState();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(String value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<String>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$novelReaderThemeStateHash() =>
|
||||
r'3149f8ea16353f770b57cce9f27f3e63d062ee7b';
|
||||
|
||||
abstract class _$NovelReaderThemeState extends $Notifier<String> {
|
||||
String build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<String, String>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<String, String>,
|
||||
String,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(NovelReaderTextColorState)
|
||||
const novelReaderTextColorStateProvider = NovelReaderTextColorStateProvider._();
|
||||
|
||||
final class NovelReaderTextColorStateProvider
|
||||
extends $NotifierProvider<NovelReaderTextColorState, String> {
|
||||
const NovelReaderTextColorStateProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'novelReaderTextColorStateProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$novelReaderTextColorStateHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
NovelReaderTextColorState create() => NovelReaderTextColorState();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(String value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<String>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$novelReaderTextColorStateHash() =>
|
||||
r'28a1987b49a9b0a209c4848dfa4c8c730432c75d';
|
||||
|
||||
abstract class _$NovelReaderTextColorState extends $Notifier<String> {
|
||||
String build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<String, String>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<String, String>,
|
||||
String,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(NovelReaderPaddingState)
|
||||
const novelReaderPaddingStateProvider = NovelReaderPaddingStateProvider._();
|
||||
|
||||
final class NovelReaderPaddingStateProvider
|
||||
extends $NotifierProvider<NovelReaderPaddingState, int> {
|
||||
const NovelReaderPaddingStateProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'novelReaderPaddingStateProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$novelReaderPaddingStateHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
NovelReaderPaddingState create() => NovelReaderPaddingState();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(int value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<int>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$novelReaderPaddingStateHash() =>
|
||||
r'572f1a7134c499a9a5107d29552beca9a5fd55ea';
|
||||
|
||||
abstract class _$NovelReaderPaddingState extends $Notifier<int> {
|
||||
int build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<int, int>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<int, int>,
|
||||
int,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(NovelReaderLineHeightState)
|
||||
const novelReaderLineHeightStateProvider =
|
||||
NovelReaderLineHeightStateProvider._();
|
||||
|
||||
final class NovelReaderLineHeightStateProvider
|
||||
extends $NotifierProvider<NovelReaderLineHeightState, double> {
|
||||
const NovelReaderLineHeightStateProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'novelReaderLineHeightStateProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$novelReaderLineHeightStateHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
NovelReaderLineHeightState create() => NovelReaderLineHeightState();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(double value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<double>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$novelReaderLineHeightStateHash() =>
|
||||
r'cc21fb550eecf8d7869c076ab47647afd2873996';
|
||||
|
||||
abstract class _$NovelReaderLineHeightState extends $Notifier<double> {
|
||||
double build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<double, double>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<double, double>,
|
||||
double,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(NovelShowScrollPercentageState)
|
||||
const novelShowScrollPercentageStateProvider =
|
||||
NovelShowScrollPercentageStateProvider._();
|
||||
|
||||
final class NovelShowScrollPercentageStateProvider
|
||||
extends $NotifierProvider<NovelShowScrollPercentageState, bool> {
|
||||
const NovelShowScrollPercentageStateProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'novelShowScrollPercentageStateProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$novelShowScrollPercentageStateHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
NovelShowScrollPercentageState create() => NovelShowScrollPercentageState();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(bool value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<bool>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$novelShowScrollPercentageStateHash() =>
|
||||
r'adc9cb5def293fa4ed8b367929e7538f6f056b76';
|
||||
|
||||
abstract class _$NovelShowScrollPercentageState extends $Notifier<bool> {
|
||||
bool build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<bool, bool>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<bool, bool>,
|
||||
bool,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(NovelAutoScrollState)
|
||||
const novelAutoScrollStateProvider = NovelAutoScrollStateProvider._();
|
||||
|
||||
final class NovelAutoScrollStateProvider
|
||||
extends $NotifierProvider<NovelAutoScrollState, bool> {
|
||||
const NovelAutoScrollStateProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'novelAutoScrollStateProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$novelAutoScrollStateHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
NovelAutoScrollState create() => NovelAutoScrollState();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(bool value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<bool>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$novelAutoScrollStateHash() =>
|
||||
r'80f717515844fa97396dffc6f45ee0b7b9e6f96d';
|
||||
|
||||
abstract class _$NovelAutoScrollState extends $Notifier<bool> {
|
||||
bool build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<bool, bool>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<bool, bool>,
|
||||
bool,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(NovelRemoveExtraParagraphSpacingState)
|
||||
const novelRemoveExtraParagraphSpacingStateProvider =
|
||||
NovelRemoveExtraParagraphSpacingStateProvider._();
|
||||
|
||||
final class NovelRemoveExtraParagraphSpacingStateProvider
|
||||
extends $NotifierProvider<NovelRemoveExtraParagraphSpacingState, bool> {
|
||||
const NovelRemoveExtraParagraphSpacingStateProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'novelRemoveExtraParagraphSpacingStateProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() =>
|
||||
_$novelRemoveExtraParagraphSpacingStateHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
NovelRemoveExtraParagraphSpacingState create() =>
|
||||
NovelRemoveExtraParagraphSpacingState();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(bool value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<bool>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$novelRemoveExtraParagraphSpacingStateHash() =>
|
||||
r'5c784a57ce5ee57524317dd00d4b40020e5e0582';
|
||||
|
||||
abstract class _$NovelRemoveExtraParagraphSpacingState extends $Notifier<bool> {
|
||||
bool build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<bool, bool>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<bool, bool>,
|
||||
bool,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
@ProviderFor(NovelTapToScrollState)
|
||||
const novelTapToScrollStateProvider = NovelTapToScrollStateProvider._();
|
||||
|
||||
final class NovelTapToScrollStateProvider
|
||||
extends $NotifierProvider<NovelTapToScrollState, bool> {
|
||||
const NovelTapToScrollStateProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'novelTapToScrollStateProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$novelTapToScrollStateHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
NovelTapToScrollState create() => NovelTapToScrollState();
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(bool value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<bool>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$novelTapToScrollStateHash() =>
|
||||
r'4ad09be8c324b019bd1d94cd8d77ef6077bd2100';
|
||||
|
||||
abstract class _$NovelTapToScrollState extends $Notifier<bool> {
|
||||
bool build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<bool, bool>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<bool, bool>,
|
||||
bool,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'package:isar_community/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/download.dart';
|
||||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'novel_reader_controller_provider.g.dart';
|
||||
|
||||
|
|
@ -188,115 +188,3 @@ class NovelReaderController extends _$NovelReaderController {
|
|||
return chapter.name!;
|
||||
}
|
||||
}
|
||||
|
||||
extension MangaExtensions on Manga {
|
||||
List<Chapter> getFilteredChapterList() {
|
||||
final data = this.chapters.toList().toList();
|
||||
final filterUnread =
|
||||
(isar.settings
|
||||
.getSync(227)!
|
||||
.chapterFilterUnreadList!
|
||||
.where((element) => element.mangaId == id)
|
||||
.toList()
|
||||
.firstOrNull ??
|
||||
ChapterFilterUnread(mangaId: id, type: 0))
|
||||
.type!;
|
||||
|
||||
final filterBookmarked =
|
||||
(isar.settings
|
||||
.getSync(227)!
|
||||
.chapterFilterBookmarkedList!
|
||||
.where((element) => element.mangaId == id)
|
||||
.toList()
|
||||
.firstOrNull ??
|
||||
ChapterFilterBookmarked(mangaId: id, type: 0))
|
||||
.type!;
|
||||
final filterDownloaded =
|
||||
(isar.settings
|
||||
.getSync(227)!
|
||||
.chapterFilterDownloadedList!
|
||||
.where((element) => element.mangaId == id)
|
||||
.toList()
|
||||
.firstOrNull ??
|
||||
ChapterFilterDownloaded(mangaId: id, type: 0))
|
||||
.type!;
|
||||
|
||||
final sortChapter =
|
||||
(isar.settings
|
||||
.getSync(227)!
|
||||
.sortChapterList!
|
||||
.where((element) => element.mangaId == id)
|
||||
.toList()
|
||||
.firstOrNull ??
|
||||
SortChapter(mangaId: id, index: 1, reverse: false))
|
||||
.index;
|
||||
final filterScanlator = _getFilterScanlator(this) ?? [];
|
||||
List<Chapter>? chapterList;
|
||||
chapterList = data
|
||||
.where(
|
||||
(element) => filterUnread == 1
|
||||
? element.isRead == false
|
||||
: filterUnread == 2
|
||||
? element.isRead == true
|
||||
: true,
|
||||
)
|
||||
.where(
|
||||
(element) => filterBookmarked == 1
|
||||
? element.isBookmarked == true
|
||||
: filterBookmarked == 2
|
||||
? element.isBookmarked == false
|
||||
: true,
|
||||
)
|
||||
.where((element) {
|
||||
final modelChapDownload = isar.downloads
|
||||
.filter()
|
||||
.idIsNotNull()
|
||||
.idEqualTo(element.id)
|
||||
.findAllSync();
|
||||
return filterDownloaded == 1
|
||||
? modelChapDownload.isNotEmpty &&
|
||||
modelChapDownload.first.isDownload == true
|
||||
: filterDownloaded == 2
|
||||
? !(modelChapDownload.isNotEmpty &&
|
||||
modelChapDownload.first.isDownload == true)
|
||||
: true;
|
||||
})
|
||||
.where((element) => !filterScanlator.contains(element.scanlator))
|
||||
.toList();
|
||||
List<Chapter> chapters = sortChapter == 1
|
||||
? chapterList.reversed.toList()
|
||||
: chapterList;
|
||||
if (sortChapter == 0) {
|
||||
chapters.sort((a, b) {
|
||||
return (a.scanlator == null ||
|
||||
b.scanlator == null ||
|
||||
a.dateUpload == null ||
|
||||
b.dateUpload == null)
|
||||
? 0
|
||||
: a.scanlator!.compareTo(b.scanlator!) |
|
||||
a.dateUpload!.compareTo(b.dateUpload!);
|
||||
});
|
||||
} else if (sortChapter == 2) {
|
||||
chapters.sort((a, b) {
|
||||
return (a.dateUpload == null || b.dateUpload == null)
|
||||
? 0
|
||||
: int.parse(a.dateUpload!).compareTo(int.parse(b.dateUpload!));
|
||||
});
|
||||
} else if (sortChapter == 3) {
|
||||
chapters.sort((a, b) {
|
||||
return (a.name == null || b.name == null)
|
||||
? 0
|
||||
: a.name!.compareTo(b.name!);
|
||||
});
|
||||
}
|
||||
return chapterList;
|
||||
}
|
||||
}
|
||||
|
||||
List<String>? _getFilterScanlator(Manga manga) {
|
||||
final scanlators = isar.settings.getSync(227)!.filterScanlatorList ?? [];
|
||||
final filter = scanlators
|
||||
.where((element) => element.mangaId == manga.id)
|
||||
.toList();
|
||||
return filter.firstOrNull?.scanlators;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import 'package:mangayomi/modules/anime/widgets/desktop.dart';
|
|||
import 'package:mangayomi/modules/manga/reader/widgets/btn_chapter_list_dialog.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
import 'package:mangayomi/modules/novel/novel_reader_controller_provider.dart';
|
||||
import 'package:mangayomi/modules/novel/widgets/novel_reader_settings_sheet.dart';
|
||||
import 'package:mangayomi/modules/widgets/custom_draggable_tabbar.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/services/get_html_content.dart';
|
||||
import 'package:mangayomi/utils/extensions/dom_extensions.dart';
|
||||
|
|
@ -24,7 +26,7 @@ import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
|
|||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||
import 'package:flutter_html/flutter_html.dart';
|
||||
import 'package:html/dom.dart' as dom;
|
||||
import 'package:flutter/widgets.dart' as widgets;
|
||||
|
||||
|
|
@ -73,6 +75,7 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
|
|||
if (_scrollController.hasClients) {
|
||||
offset = _scrollController.offset;
|
||||
maxOffset = _scrollController.position.maxScrollExtent;
|
||||
_rebuildDetail.add(offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,119 +206,254 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
|
|||
bottom: false,
|
||||
child: Stack(
|
||||
children: [
|
||||
widget.result.when(
|
||||
data: (data) {
|
||||
epubBook = data.$2;
|
||||
Future.delayed(const Duration(milliseconds: 1000), () {
|
||||
if (!scrolled && _scrollController.hasClients) {
|
||||
_scrollController.animateTo(
|
||||
_scrollController.position.maxScrollExtent *
|
||||
(double.tryParse(chapter.lastPageRead!) ?? 0),
|
||||
duration: Duration(seconds: 2),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
);
|
||||
scrolled = true;
|
||||
}
|
||||
});
|
||||
return Scrollbar(
|
||||
controller: _scrollController,
|
||||
interactive: true,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () {
|
||||
_isViewFunction();
|
||||
},
|
||||
child: CustomScrollView(
|
||||
controller: _scrollController,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
slivers: [
|
||||
HtmlWidget(
|
||||
data.$1,
|
||||
customWidgetBuilder: (element) =>
|
||||
_buildCustomWidgets(element),
|
||||
customStylesBuilder: (element) {
|
||||
switch (backgroundColor) {
|
||||
case BackgroundColor.black:
|
||||
return {'background-color': 'black'};
|
||||
default:
|
||||
return {'background-color': '#F0F0F0'};
|
||||
}
|
||||
},
|
||||
onTapUrl: (url) {
|
||||
context.push(
|
||||
"/mangawebview",
|
||||
extra: {'url': url, 'title': url},
|
||||
);
|
||||
return true;
|
||||
},
|
||||
renderMode: RenderMode.sliverList,
|
||||
textStyle: TextStyle(
|
||||
color: backgroundColor == BackgroundColor.white
|
||||
? Colors.black
|
||||
: Colors.white,
|
||||
fontSize: fontSize.toDouble(),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Center(
|
||||
heightFactor: 2,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 5,
|
||||
children: [
|
||||
IconButton(
|
||||
padding: const EdgeInsets.all(5),
|
||||
onPressed: () =>
|
||||
pushReplacementMangaReaderView(
|
||||
context: context,
|
||||
chapter: _readerController
|
||||
.getPrevChapter(),
|
||||
),
|
||||
icon: Icon(
|
||||
size: 32,
|
||||
Icons.arrow_back,
|
||||
color:
|
||||
backgroundColor ==
|
||||
BackgroundColor.white
|
||||
? Colors.black
|
||||
: Colors.white,
|
||||
Column(
|
||||
children: [
|
||||
Flexible(
|
||||
child: widget.result.when(
|
||||
data: (data) {
|
||||
epubBook = data.$2;
|
||||
|
||||
final padding = ref.watch(
|
||||
novelReaderPaddingStateProvider,
|
||||
);
|
||||
final lineHeight = ref.watch(
|
||||
novelReaderLineHeightStateProvider,
|
||||
);
|
||||
final textAlign = ref.watch(
|
||||
novelTextAlignStateProvider,
|
||||
);
|
||||
final removeExtraSpacing = ref.watch(
|
||||
novelRemoveExtraParagraphSpacingStateProvider,
|
||||
);
|
||||
final customBackgroundColor = ref.watch(
|
||||
novelReaderThemeStateProvider,
|
||||
);
|
||||
final customTextColor = ref.watch(
|
||||
novelReaderTextColorStateProvider,
|
||||
);
|
||||
|
||||
Color parseColor(String hex) {
|
||||
final hexColor = hex.replaceAll('#', '');
|
||||
return Color(int.parse('FF$hexColor', radix: 16));
|
||||
}
|
||||
|
||||
TextAlign getTextAlign() {
|
||||
switch (textAlign) {
|
||||
case NovelTextAlign.left:
|
||||
return TextAlign.left;
|
||||
case NovelTextAlign.center:
|
||||
return TextAlign.center;
|
||||
case NovelTextAlign.right:
|
||||
return TextAlign.right;
|
||||
case NovelTextAlign.block:
|
||||
return TextAlign.justify;
|
||||
}
|
||||
}
|
||||
|
||||
Future.delayed(const Duration(milliseconds: 10), () {
|
||||
if (!scrolled && _scrollController.hasClients) {
|
||||
_scrollController.animateTo(
|
||||
_scrollController.position.maxScrollExtent *
|
||||
(double.tryParse(chapter.lastPageRead!) ??
|
||||
0),
|
||||
duration: Duration(seconds: 2),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
);
|
||||
scrolled = true;
|
||||
}
|
||||
});
|
||||
return Consumer(
|
||||
builder: (context, ref, _) {
|
||||
final fontSize = ref.read(
|
||||
novelFontSizeStateProvider,
|
||||
);
|
||||
return Scrollbar(
|
||||
controller: _scrollController,
|
||||
interactive: true,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onTap: () {
|
||||
_isViewFunction();
|
||||
},
|
||||
child: CustomScrollView(
|
||||
controller: _scrollController,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Html(
|
||||
data: data.$1,
|
||||
style: {
|
||||
"body": Style(
|
||||
fontSize: FontSize(
|
||||
fontSize.toDouble(),
|
||||
),
|
||||
color: parseColor(
|
||||
customTextColor,
|
||||
),
|
||||
backgroundColor: parseColor(
|
||||
customBackgroundColor,
|
||||
),
|
||||
margin: Margins.zero,
|
||||
padding: HtmlPaddings.all(
|
||||
padding.toDouble(),
|
||||
),
|
||||
lineHeight: LineHeight(
|
||||
lineHeight,
|
||||
),
|
||||
textAlign: getTextAlign(),
|
||||
),
|
||||
"p": Style(
|
||||
margin: removeExtraSpacing
|
||||
? Margins.only(bottom: 4)
|
||||
: Margins.only(bottom: 8),
|
||||
fontSize: FontSize(
|
||||
fontSize.toDouble(),
|
||||
),
|
||||
lineHeight: LineHeight(
|
||||
lineHeight,
|
||||
),
|
||||
textAlign: getTextAlign(),
|
||||
),
|
||||
"div": Style(
|
||||
fontSize: FontSize(
|
||||
fontSize.toDouble(),
|
||||
),
|
||||
lineHeight: LineHeight(
|
||||
lineHeight,
|
||||
),
|
||||
textAlign: getTextAlign(),
|
||||
),
|
||||
"span": Style(
|
||||
fontSize: FontSize(
|
||||
fontSize.toDouble(),
|
||||
),
|
||||
lineHeight: LineHeight(
|
||||
lineHeight,
|
||||
),
|
||||
),
|
||||
"h1, h2, h3, h4, h5, h6": Style(
|
||||
color: parseColor(
|
||||
customTextColor,
|
||||
),
|
||||
lineHeight: LineHeight(
|
||||
lineHeight,
|
||||
),
|
||||
textAlign: getTextAlign(),
|
||||
),
|
||||
"a": Style(
|
||||
color: Colors.blue,
|
||||
textDecoration:
|
||||
TextDecoration.underline,
|
||||
),
|
||||
"img": Style(
|
||||
width: Width(100, Unit.percent),
|
||||
height: Height.auto(),
|
||||
),
|
||||
},
|
||||
extensions: [
|
||||
TagExtension(
|
||||
tagsToExtend: {"img"},
|
||||
builder: (extensionContext) {
|
||||
final element =
|
||||
extensionContext.node
|
||||
as dom.Element;
|
||||
final customWidget =
|
||||
_buildCustomWidgets(
|
||||
element,
|
||||
);
|
||||
if (customWidget != null) {
|
||||
return customWidget;
|
||||
}
|
||||
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
),
|
||||
],
|
||||
onLinkTap:
|
||||
(url, attributes, element) {
|
||||
if (url != null) {
|
||||
context.push(
|
||||
"/mangawebview",
|
||||
extra: {
|
||||
'url': url,
|
||||
'title': url,
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
padding: const EdgeInsets.all(5),
|
||||
onPressed: () =>
|
||||
pushReplacementMangaReaderView(
|
||||
context: context,
|
||||
chapter: _readerController
|
||||
.getNextChapter(),
|
||||
),
|
||||
icon: Icon(
|
||||
size: 32,
|
||||
Icons.arrow_forward,
|
||||
color:
|
||||
backgroundColor ==
|
||||
BackgroundColor.white
|
||||
? Colors.black
|
||||
: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
loading: () => scaffoldWith(
|
||||
context,
|
||||
Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
error: (err, stack) => scaffoldWith(
|
||||
context,
|
||||
Center(child: Text(err.toString())),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => scaffoldWith(
|
||||
context,
|
||||
Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
error: (err, stack) => scaffoldWith(
|
||||
context,
|
||||
Center(child: Text(err.toString())),
|
||||
),
|
||||
),
|
||||
if (ref.watch(novelShowScrollPercentageStateProvider))
|
||||
StreamBuilder(
|
||||
stream: _rebuildDetail.stream,
|
||||
builder: (context, asyncSnapshot) {
|
||||
return Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final customBackgroundColor = ref.watch(
|
||||
novelReaderThemeStateProvider,
|
||||
);
|
||||
final customTextColor = ref.watch(
|
||||
novelReaderTextColorStateProvider,
|
||||
);
|
||||
final scrollPercentage = maxOffset > 0
|
||||
? ((offset / maxOffset) * 100)
|
||||
.clamp(0, 100)
|
||||
.toInt()
|
||||
: 0;
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: Color(
|
||||
int.parse(
|
||||
'FF${customBackgroundColor.replaceAll('#', '')}',
|
||||
radix: 16,
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Text(
|
||||
'$scrollPercentage %',
|
||||
style: TextStyle(
|
||||
color: Color(
|
||||
int.parse(
|
||||
'FF${customTextColor.replaceAll('#', '')}',
|
||||
radix: 16,
|
||||
),
|
||||
),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
_appBar(),
|
||||
_bottomBar(backgroundColor),
|
||||
|
|
@ -485,70 +623,186 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
|
|||
_readerController.getChapterIndex().$2,
|
||||
);
|
||||
bool hasNextChapter = _readerController.getChapterIndex().$1 != 0;
|
||||
final novelTextAlign = ref.watch(novelTextAlignStateProvider);
|
||||
|
||||
final bodyLargeColor = Theme.of(context).textTheme.bodyLarge!.color;
|
||||
return Positioned(
|
||||
bottom: 0,
|
||||
child: AnimatedContainer(
|
||||
curve: Curves.ease,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
width: context.width(1),
|
||||
height: (_isView ? 130 : 0),
|
||||
height: (_isView ? 140 : 0),
|
||||
child: Column(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Transform.scale(
|
||||
scaleX: 1,
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: CircleAvatar(
|
||||
radius: 23,
|
||||
backgroundColor: _backgroundColor(context),
|
||||
child: IconButton(
|
||||
onPressed: hasPrevChapter
|
||||
? () {
|
||||
pushReplacementMangaReaderView(
|
||||
context: context,
|
||||
chapter: _readerController.getPrevChapter(),
|
||||
);
|
||||
}
|
||||
: null,
|
||||
icon: Transform.scale(
|
||||
scaleX: 1,
|
||||
child: Icon(
|
||||
Icons.skip_previous_rounded,
|
||||
color: hasPrevChapter
|
||||
? Theme.of(context).textTheme.bodyLarge!.color
|
||||
: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color!
|
||||
.withValues(alpha: 0.4),
|
||||
),
|
||||
if (_isView)
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: CircleAvatar(
|
||||
radius: 21,
|
||||
backgroundColor: _backgroundColor(context),
|
||||
child: IconButton(
|
||||
onPressed: hasPrevChapter
|
||||
? () {
|
||||
pushReplacementMangaReaderView(
|
||||
context: context,
|
||||
chapter: _readerController.getPrevChapter(),
|
||||
);
|
||||
}
|
||||
: null,
|
||||
icon: Icon(
|
||||
Icons.skip_previous_rounded,
|
||||
color: hasPrevChapter
|
||||
? bodyLargeColor
|
||||
: bodyLargeColor!.withValues(alpha: 0.4),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Container(
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: _backgroundColor(context),
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: StreamBuilder(
|
||||
stream: _rebuildDetail.stream,
|
||||
builder: (context, asyncSnapshot) {
|
||||
return Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final scrollPercentage = maxOffset > 0
|
||||
? ((offset / maxOffset) * 100)
|
||||
.clamp(0, 100)
|
||||
.toInt()
|
||||
: 0;
|
||||
return Row(
|
||||
children: [
|
||||
SizedBox(width: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Text(
|
||||
scrollPercentage.toInt().toString(),
|
||||
style: TextStyle(
|
||||
color: bodyLargeColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_isView)
|
||||
Expanded(
|
||||
flex: 14,
|
||||
child: SliderTheme(
|
||||
data: SliderTheme.of(context).copyWith(
|
||||
trackHeight: 2.0,
|
||||
thumbShape:
|
||||
const RoundSliderThumbShape(
|
||||
enabledThumbRadius: 6.0,
|
||||
),
|
||||
overlayShape:
|
||||
const RoundSliderOverlayShape(
|
||||
overlayRadius: 12.0,
|
||||
),
|
||||
),
|
||||
child: Slider(
|
||||
onChanged: (value) {
|
||||
_scrollController.jumpTo(
|
||||
_scrollController
|
||||
.position
|
||||
.maxScrollExtent *
|
||||
value,
|
||||
);
|
||||
},
|
||||
value: scrollPercentage / 100,
|
||||
min: 0,
|
||||
max: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: Text(
|
||||
'100',
|
||||
style: TextStyle(
|
||||
color: bodyLargeColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: CircleAvatar(
|
||||
radius: 21,
|
||||
backgroundColor: _backgroundColor(context),
|
||||
child: IconButton(
|
||||
onPressed: hasNextChapter
|
||||
? () {
|
||||
pushReplacementMangaReaderView(
|
||||
context: context,
|
||||
chapter: _readerController.getNextChapter(),
|
||||
);
|
||||
}
|
||||
: null,
|
||||
icon: Transform.scale(
|
||||
scaleX: 1,
|
||||
child: Icon(
|
||||
Icons.skip_next_rounded,
|
||||
color: hasNextChapter
|
||||
? bodyLargeColor
|
||||
: bodyLargeColor!.withValues(alpha: 0.4),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Container(
|
||||
height: 70,
|
||||
decoration: BoxDecoration(
|
||||
color: _backgroundColor(context),
|
||||
borderRadius: BorderRadius.circular(25),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_isView)
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: _backgroundColor(context),
|
||||
child: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: SizedBox(
|
||||
height: 50,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Transform.scale(
|
||||
scaleX: 1,
|
||||
child: SizedBox(
|
||||
width: 55,
|
||||
child: Center(
|
||||
child: IconButton(
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: bodyLargeColor!,
|
||||
width: 0.2,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Text Size :',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: bodyLargeColor,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
final newFontSize = max(
|
||||
4,
|
||||
|
|
@ -564,58 +818,52 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
|
|||
fontSize = newFontSize;
|
||||
});
|
||||
},
|
||||
icon: const Icon(Icons.text_decrease),
|
||||
icon: Icon(Icons.text_decrease),
|
||||
iconSize: 20,
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 40,
|
||||
minHeight: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (_isView)
|
||||
Flexible(
|
||||
flex: 14,
|
||||
child: Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final currentFontSize = ref.watch(
|
||||
novelFontSizeStateProvider,
|
||||
);
|
||||
return SliderTheme(
|
||||
data: SliderTheme.of(context).copyWith(
|
||||
overlayShape:
|
||||
const RoundSliderOverlayShape(
|
||||
overlayRadius: 5.0,
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 5,
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 6,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.primaryContainer
|
||||
.withValues(alpha: 0.5),
|
||||
borderRadius: BorderRadius.circular(
|
||||
8,
|
||||
),
|
||||
),
|
||||
child: Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final currentFontSize = ref.watch(
|
||||
novelFontSizeStateProvider,
|
||||
);
|
||||
return Text(
|
||||
"$currentFontSize px",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 14,
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.onPrimaryContainer,
|
||||
),
|
||||
),
|
||||
child: Slider(
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(
|
||||
novelFontSizeStateProvider
|
||||
.notifier,
|
||||
)
|
||||
.set(value.toInt());
|
||||
);
|
||||
},
|
||||
onChangeEnd: (newValue) {
|
||||
try {
|
||||
setState(() {
|
||||
fontSize = newValue.toInt();
|
||||
});
|
||||
} catch (_) {}
|
||||
},
|
||||
divisions: 36,
|
||||
value: currentFontSize.toDouble(),
|
||||
label: "$currentFontSize",
|
||||
min: 4,
|
||||
max: 40,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Transform.scale(
|
||||
scaleX: 1,
|
||||
child: SizedBox(
|
||||
width: 55,
|
||||
child: Center(
|
||||
child: IconButton(
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
final newFontSize = min(
|
||||
40,
|
||||
|
|
@ -632,106 +880,42 @@ class _NovelWebViewState extends ConsumerState<NovelWebView>
|
|||
});
|
||||
},
|
||||
icon: const Icon(Icons.text_increase),
|
||||
iconSize: 20,
|
||||
padding: EdgeInsets.zero,
|
||||
constraints: const BoxConstraints(
|
||||
minWidth: 40,
|
||||
minHeight: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
customDraggableTabBar(
|
||||
tabs: [
|
||||
Tab(text: context.l10n.reader),
|
||||
Tab(text: context.l10n.general),
|
||||
],
|
||||
children: [
|
||||
ReaderSettingsTab(),
|
||||
GeneralSettingsTab(),
|
||||
],
|
||||
context: context,
|
||||
vsync: this,
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.settings),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: CircleAvatar(
|
||||
radius: 23,
|
||||
backgroundColor: _backgroundColor(context),
|
||||
child: IconButton(
|
||||
onPressed: hasNextChapter
|
||||
? () {
|
||||
pushReplacementMangaReaderView(
|
||||
context: context,
|
||||
chapter: _readerController.getNextChapter(),
|
||||
);
|
||||
}
|
||||
: null,
|
||||
icon: Transform.scale(
|
||||
scaleX: 1,
|
||||
child: Icon(
|
||||
Icons.skip_next_rounded,
|
||||
color: hasNextChapter
|
||||
? Theme.of(context).textTheme.bodyLarge!.color
|
||||
: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color!
|
||||
.withValues(alpha: 0.4),
|
||||
// size: 17,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
/*Flexible(
|
||||
child: Container(
|
||||
height: 65,
|
||||
color: _backgroundColor(context),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
PopupMenuButton(
|
||||
popUpAnimationStyle: popupAnimationStyle,
|
||||
color: Colors.black,
|
||||
child: const Icon(
|
||||
Icons.format_align_center_outlined,
|
||||
),
|
||||
onSelected: (value) {
|
||||
ref
|
||||
.read(novelTextAlignStateProvider.notifier)
|
||||
.set(value);
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
for (var mode in NovelTextAlign.values)
|
||||
PopupMenuItem(
|
||||
value: mode,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: novelTextAlign == mode
|
||||
? Colors.white
|
||||
: Colors.transparent,
|
||||
),
|
||||
const SizedBox(
|
||||
width: 7,
|
||||
),
|
||||
Text(
|
||||
mode.name,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
// _showModalSettings();
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.settings_rounded,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),*/
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
591
lib/modules/novel/widgets/novel_reader_settings_sheet.dart
Normal file
591
lib/modules/novel/widgets/novel_reader_settings_sheet.dart
Normal file
|
|
@ -0,0 +1,591 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
|
||||
|
||||
class ReaderSettingsTab extends ConsumerWidget {
|
||||
const ReaderSettingsTab({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final padding = ref.watch(novelReaderPaddingStateProvider);
|
||||
final lineHeight = ref.watch(novelReaderLineHeightStateProvider);
|
||||
final textAlign = ref.watch(novelTextAlignStateProvider);
|
||||
final backgroundColor = ref.watch(novelReaderThemeStateProvider);
|
||||
final textColor = ref.watch(novelReaderTextColorStateProvider);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
_SettingSection(
|
||||
title: 'Theme',
|
||||
child: Column(
|
||||
children: [
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
_ThemeButton(
|
||||
backgroundColor: '#292832',
|
||||
textColor: '#CCCCCC',
|
||||
label: 'Dark',
|
||||
isSelected: backgroundColor == '#292832',
|
||||
onTap: () {
|
||||
ref
|
||||
.read(novelReaderThemeStateProvider.notifier)
|
||||
.set('#292832');
|
||||
ref
|
||||
.read(novelReaderTextColorStateProvider.notifier)
|
||||
.set('#CCCCCC');
|
||||
},
|
||||
),
|
||||
_ThemeButton(
|
||||
backgroundColor: '#FFFFFF',
|
||||
textColor: '#000000',
|
||||
label: 'Light',
|
||||
isSelected: backgroundColor == '#FFFFFF',
|
||||
onTap: () {
|
||||
ref
|
||||
.read(novelReaderThemeStateProvider.notifier)
|
||||
.set('#FFFFFF');
|
||||
ref
|
||||
.read(novelReaderTextColorStateProvider.notifier)
|
||||
.set('#000000');
|
||||
},
|
||||
),
|
||||
_ThemeButton(
|
||||
backgroundColor: '#000000',
|
||||
textColor: '#FFFFFF',
|
||||
label: 'Black',
|
||||
isSelected: backgroundColor == '#000000',
|
||||
onTap: () {
|
||||
ref
|
||||
.read(novelReaderThemeStateProvider.notifier)
|
||||
.set('#000000');
|
||||
ref
|
||||
.read(novelReaderTextColorStateProvider.notifier)
|
||||
.set('#FFFFFF');
|
||||
},
|
||||
),
|
||||
_ThemeButton(
|
||||
backgroundColor: '#F5E6D3',
|
||||
textColor: '#5F4B32',
|
||||
label: 'Sepia',
|
||||
isSelected: backgroundColor == '#F5E6D3',
|
||||
onTap: () {
|
||||
ref
|
||||
.read(novelReaderThemeStateProvider.notifier)
|
||||
.set('#F5E6D3');
|
||||
ref
|
||||
.read(novelReaderTextColorStateProvider.notifier)
|
||||
.set('#5F4B32');
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _ColorPicker(
|
||||
label: 'Background',
|
||||
color: backgroundColor,
|
||||
onColorChanged: (color) {
|
||||
ref
|
||||
.read(novelReaderThemeStateProvider.notifier)
|
||||
.set(color);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: _ColorPicker(
|
||||
label: 'Text',
|
||||
color: textColor,
|
||||
onColorChanged: (color) {
|
||||
ref
|
||||
.read(novelReaderTextColorStateProvider.notifier)
|
||||
.set(color);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
_SettingSection(
|
||||
title: 'Text Align',
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
_AlignButton(
|
||||
icon: Icons.format_align_left,
|
||||
isSelected: textAlign == NovelTextAlign.left,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(novelTextAlignStateProvider.notifier)
|
||||
.set(NovelTextAlign.left);
|
||||
},
|
||||
),
|
||||
_AlignButton(
|
||||
icon: Icons.format_align_center,
|
||||
isSelected: textAlign == NovelTextAlign.center,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(novelTextAlignStateProvider.notifier)
|
||||
.set(NovelTextAlign.center);
|
||||
},
|
||||
),
|
||||
_AlignButton(
|
||||
icon: Icons.format_align_right,
|
||||
isSelected: textAlign == NovelTextAlign.right,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(novelTextAlignStateProvider.notifier)
|
||||
.set(NovelTextAlign.right);
|
||||
},
|
||||
),
|
||||
_AlignButton(
|
||||
icon: Icons.format_align_justify,
|
||||
isSelected: textAlign == NovelTextAlign.block,
|
||||
onTap: () {
|
||||
ref
|
||||
.read(novelTextAlignStateProvider.notifier)
|
||||
.set(NovelTextAlign.block);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
_SettingSection(
|
||||
title: 'Padding',
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.space_bar, size: 20),
|
||||
Expanded(
|
||||
child: Slider(
|
||||
value: padding.toDouble(),
|
||||
min: 0,
|
||||
max: 50,
|
||||
divisions: 50,
|
||||
label: '$padding px',
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(novelReaderPaddingStateProvider.notifier)
|
||||
.set(value.toInt());
|
||||
},
|
||||
),
|
||||
),
|
||||
Text('${padding}px'),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
_SettingSection(
|
||||
title: 'Line Height',
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.height, size: 20),
|
||||
Expanded(
|
||||
child: Slider(
|
||||
value: lineHeight,
|
||||
min: 1.0,
|
||||
max: 3.0,
|
||||
divisions: 20,
|
||||
label: lineHeight.toStringAsFixed(1),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(novelReaderLineHeightStateProvider.notifier)
|
||||
.set(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
Text(lineHeight.toStringAsFixed(1)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GeneralSettingsTab extends ConsumerWidget {
|
||||
const GeneralSettingsTab({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
_SwitchListTileSetting(
|
||||
title: 'Show Scroll Percentage',
|
||||
subtitle: 'Display reading progress percentage',
|
||||
value: ref.watch(novelShowScrollPercentageStateProvider),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(novelShowScrollPercentageStateProvider.notifier)
|
||||
.set(value);
|
||||
},
|
||||
),
|
||||
|
||||
// _SwitchListTileSetting(
|
||||
// title: 'Auto Scroll',
|
||||
// subtitle: 'Automatically scroll through pages',
|
||||
// value: ref.watch(novelAutoScrollStateProvider),
|
||||
// onChanged: (value) {
|
||||
// ref.read(novelAutoScrollStateProvider.notifier).set(value);
|
||||
// },
|
||||
// ),
|
||||
_SwitchListTileSetting(
|
||||
title: 'Remove Extra Paragraph Spacing',
|
||||
subtitle: 'Reduce spacing between paragraphs',
|
||||
value: ref.watch(novelRemoveExtraParagraphSpacingStateProvider),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(novelRemoveExtraParagraphSpacingStateProvider.notifier)
|
||||
.set(value);
|
||||
},
|
||||
),
|
||||
|
||||
// _SwitchListTileSetting(
|
||||
// title: 'Tap to Scroll',
|
||||
// subtitle: 'Tap screen to scroll up/down',
|
||||
// value: ref.watch(novelTapToScrollStateProvider),
|
||||
// onChanged: (value) {
|
||||
// ref.read(novelTapToScrollStateProvider.notifier).set(value);
|
||||
// },
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SettingSection extends StatelessWidget {
|
||||
final String title;
|
||||
final Widget child;
|
||||
|
||||
const _SettingSection({required this.title, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Theme.of(context).textTheme.titleLarge?.color,
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SwitchListTileSetting extends StatelessWidget {
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final bool value;
|
||||
final ValueChanged<bool> onChanged;
|
||||
|
||||
const _SwitchListTileSetting({
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SwitchListTile(
|
||||
title: Text(title),
|
||||
subtitle: Text(subtitle, style: Theme.of(context).textTheme.bodySmall),
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ThemeButton extends StatelessWidget {
|
||||
final String backgroundColor;
|
||||
final String textColor;
|
||||
final String label;
|
||||
final bool isSelected;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _ThemeButton({
|
||||
required this.backgroundColor,
|
||||
required this.textColor,
|
||||
required this.label,
|
||||
required this.isSelected,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
Color _parseColor(String hex) {
|
||||
final hexColor = hex.replaceAll('#', '');
|
||||
return Color(int.parse('FF$hexColor', radix: 16));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
width: 70,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: _parseColor(backgroundColor),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? Theme.of(context).primaryColor
|
||||
: Colors.grey.withValues(alpha: 0.3),
|
||||
width: isSelected ? 3 : 1,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
'Aa',
|
||||
style: TextStyle(
|
||||
color: _parseColor(textColor),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(color: _parseColor(textColor), fontSize: 10),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ColorPicker extends StatelessWidget {
|
||||
final String label;
|
||||
final String color;
|
||||
final ValueChanged<String> onColorChanged;
|
||||
|
||||
const _ColorPicker({
|
||||
required this.label,
|
||||
required this.color,
|
||||
required this.onColorChanged,
|
||||
});
|
||||
|
||||
Color _parseColor(String hex) {
|
||||
final hexColor = hex.replaceAll('#', '');
|
||||
return Color(int.parse('FF$hexColor', radix: 16));
|
||||
}
|
||||
|
||||
String _colorToHex(Color color) {
|
||||
return '#${color.toARGB32().toRadixString(16).substring(2).toUpperCase()}';
|
||||
}
|
||||
|
||||
void _showColorPickerDialog(BuildContext context) {
|
||||
Color selectedColor = _parseColor(color);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Select $label Color'),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
_colorOption(context, Colors.white, selectedColor),
|
||||
_colorOption(context, Colors.black, selectedColor),
|
||||
_colorOption(
|
||||
context,
|
||||
const Color(0xFF292832),
|
||||
selectedColor,
|
||||
),
|
||||
_colorOption(
|
||||
context,
|
||||
const Color(0xFFF5E6D3),
|
||||
selectedColor,
|
||||
),
|
||||
_colorOption(
|
||||
context,
|
||||
const Color(0xFF5F4B32),
|
||||
selectedColor,
|
||||
),
|
||||
_colorOption(
|
||||
context,
|
||||
const Color(0xFFCCCCCC),
|
||||
selectedColor,
|
||||
),
|
||||
_colorOption(context, Colors.grey[800]!, selectedColor),
|
||||
_colorOption(context, Colors.grey[300]!, selectedColor),
|
||||
_colorOption(context, Colors.brown[100]!, selectedColor),
|
||||
_colorOption(context, Colors.blue[100]!, selectedColor),
|
||||
_colorOption(context, Colors.green[100]!, selectedColor),
|
||||
_colorOption(context, Colors.amber[100]!, selectedColor),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _colorOption(
|
||||
BuildContext context,
|
||||
Color optionColor,
|
||||
Color selectedColor,
|
||||
) {
|
||||
final isSelected = optionColor.toARGB32() == selectedColor.toARGB32();
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
onColorChanged(_colorToHex(optionColor));
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: optionColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: isSelected ? Theme.of(context).primaryColor : Colors.grey,
|
||||
width: isSelected ? 3 : 1,
|
||||
),
|
||||
),
|
||||
child: isSelected
|
||||
? Icon(
|
||||
Icons.check,
|
||||
color: optionColor.computeLuminance() > 0.5
|
||||
? Colors.black
|
||||
: Colors.white,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () => _showColorPickerDialog(context),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey.withValues(alpha: 0.3)),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
color: _parseColor(color),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(color: Colors.grey),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(label, style: const TextStyle(fontSize: 12)),
|
||||
Text(
|
||||
color,
|
||||
style: TextStyle(fontSize: 10, color: Colors.grey[600]),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Icon(Icons.arrow_drop_down),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AlignButton extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final bool isSelected;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _AlignButton({
|
||||
required this.icon,
|
||||
required this.isSelected,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? Theme.of(context).primaryColor.withValues(alpha: 0.2)
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? Theme.of(context).primaryColor
|
||||
: Colors.grey.withValues(alpha: 0.3),
|
||||
width: isSelected ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: isSelected
|
||||
? Theme.of(context).primaryColor
|
||||
: Theme.of(context).iconTheme.color,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -65,7 +65,7 @@ final class FetchItemSourcesListProvider
|
|||
}
|
||||
|
||||
String _$fetchItemSourcesListHash() =>
|
||||
r'16238be20517fddacf52a2694fbd50cafbfa7496';
|
||||
r'219aed67d2329f03101f2270e2f344bf70eff128';
|
||||
|
||||
final class FetchItemSourcesListFamily extends $Family
|
||||
with
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ final class GetDetailProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$getDetailHash() => r'6b758b79281cb00a7df2fe1903d4a67068052bca';
|
||||
String _$getDetailHash() => r'7eab7d00e6ad61a9bafaee855eae1f49b127af9f';
|
||||
|
||||
final class GetDetailFamily extends $Family
|
||||
with
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ final class GetHtmlContentProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$getHtmlContentHash() => r'f1f734a95f8dfcd7197712eee61609589d76de1f';
|
||||
String _$getHtmlContentHash() => r'a5763e11960bfe0dbd38ce2b2a3f4b51fefc976e';
|
||||
|
||||
final class GetHtmlContentFamily extends $Family
|
||||
with $FunctionalFamilyOverride<FutureOr<(String, EpubBook?)>, Chapter> {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ final class GetLatestUpdatesProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$getLatestUpdatesHash() => r'7a3c06c469c77ec933cf2f4dd7d39780d993f0ea';
|
||||
String _$getLatestUpdatesHash() => r'6f99dfe1d4aa950b6852110ec23f92b5c73c413c';
|
||||
|
||||
final class GetLatestUpdatesFamily extends $Family
|
||||
with
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ final class GetPopularProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$getPopularHash() => r'f169b6a9ba76d9dd9237ba9c21805151a1419843';
|
||||
String _$getPopularHash() => r'7e1139bc0f6a3a495fa0dc59d450bc7fd70f36a8';
|
||||
|
||||
final class GetPopularFamily extends $Family
|
||||
with
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ final class GetVideoListProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$getVideoListHash() => r'c99fd33a99b3fb2e2cc66353f1b8b560f3c8e184';
|
||||
String _$getVideoListHash() => r'd374dccf3edc478c883cb79b9f1be724342b9ac7';
|
||||
|
||||
final class GetVideoListFamily extends $Family
|
||||
with
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ final class SearchProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$searchHash() => r'b6bac0a3af58547bb93356f3c00a04135cd5a891';
|
||||
String _$searchHash() => r'03bfee6172b386c53aee05fe2429a10ce5915b18';
|
||||
|
||||
final class SearchFamily extends $Family
|
||||
with
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ final class SearchProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$searchHash() => r'e23c6dd56549ffdfc89b5fcfa43719d90ca1760e';
|
||||
String _$searchHash() => r'0fa9d882436b1b58b3420dae5a757e7622273eb5';
|
||||
|
||||
final class SearchFamily extends $Family
|
||||
with
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import FlutterMacOS
|
|||
import Foundation
|
||||
|
||||
import app_links
|
||||
import audio_session
|
||||
import connectivity_plus
|
||||
import device_info_plus
|
||||
import file_picker
|
||||
|
|
@ -14,7 +13,6 @@ import flutter_inappwebview_macos
|
|||
import flutter_qjs
|
||||
import flutter_web_auth_2
|
||||
import isar_community_flutter_libs
|
||||
import just_audio
|
||||
import media_kit_libs_macos_video
|
||||
import media_kit_video
|
||||
import package_info_plus
|
||||
|
|
@ -22,18 +20,14 @@ import path_provider_foundation
|
|||
import screen_brightness_macos
|
||||
import screen_retriever_macos
|
||||
import share_plus
|
||||
import sqflite_darwin
|
||||
import url_launcher_macos
|
||||
import video_player_avfoundation
|
||||
import volume_controller
|
||||
import wakelock_plus
|
||||
import webview_flutter_wkwebview
|
||||
import window_manager
|
||||
import window_to_front
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
|
||||
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
|
||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
||||
|
|
@ -41,7 +35,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
FlutterQjsPlugin.register(with: registry.registrar(forPlugin: "FlutterQjsPlugin"))
|
||||
FlutterWebAuth2Plugin.register(with: registry.registrar(forPlugin: "FlutterWebAuth2Plugin"))
|
||||
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))
|
||||
JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin"))
|
||||
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
||||
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
|
|
@ -49,12 +42,9 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
ScreenBrightnessMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenBrightnessMacosPlugin"))
|
||||
ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin"))
|
||||
SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
|
||||
VolumeControllerPlugin.register(with: registry.registrar(forPlugin: "VolumeControllerPlugin"))
|
||||
WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin"))
|
||||
WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin"))
|
||||
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
||||
WindowToFrontPlugin.register(with: registry.registrar(forPlugin: "WindowToFrontPlugin"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
PODS:
|
||||
- app_links (6.4.1):
|
||||
- FlutterMacOS
|
||||
- audio_session (0.0.1):
|
||||
- FlutterMacOS
|
||||
- connectivity_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- device_info_plus (0.0.1):
|
||||
|
|
@ -21,9 +19,6 @@ PODS:
|
|||
- FlutterMacOS (1.0.0)
|
||||
- isar_community_flutter_libs (1.0.0):
|
||||
- FlutterMacOS
|
||||
- just_audio (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- media_kit_libs_macos_video (1.0.4):
|
||||
- FlutterMacOS
|
||||
- media_kit_video (0.0.1):
|
||||
|
|
@ -42,21 +37,12 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- share_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- sqflite_darwin (0.0.4):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- url_launcher_macos (0.0.1):
|
||||
- FlutterMacOS
|
||||
- video_player_avfoundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- volume_controller (0.0.1):
|
||||
- FlutterMacOS
|
||||
- wakelock_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- webview_flutter_wkwebview (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- window_manager (0.5.0):
|
||||
- FlutterMacOS
|
||||
- window_to_front (0.0.1):
|
||||
|
|
@ -64,7 +50,6 @@ PODS:
|
|||
|
||||
DEPENDENCIES:
|
||||
- app_links (from `Flutter/ephemeral/.symlinks/plugins/app_links/macos`)
|
||||
- audio_session (from `Flutter/ephemeral/.symlinks/plugins/audio_session/macos`)
|
||||
- connectivity_plus (from `Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos`)
|
||||
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
|
||||
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
|
||||
|
|
@ -74,7 +59,6 @@ DEPENDENCIES:
|
|||
- flutter_web_auth_2 (from `Flutter/ephemeral/.symlinks/plugins/flutter_web_auth_2/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- isar_community_flutter_libs (from `Flutter/ephemeral/.symlinks/plugins/isar_community_flutter_libs/macos`)
|
||||
- just_audio (from `Flutter/ephemeral/.symlinks/plugins/just_audio/darwin`)
|
||||
- media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`)
|
||||
- media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`)
|
||||
- package_info_plus (from `Flutter/ephemeral/.symlinks/plugins/package_info_plus/macos`)
|
||||
|
|
@ -83,12 +67,9 @@ DEPENDENCIES:
|
|||
- screen_brightness_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_brightness_macos/macos`)
|
||||
- screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`)
|
||||
- share_plus (from `Flutter/ephemeral/.symlinks/plugins/share_plus/macos`)
|
||||
- sqflite_darwin (from `Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
|
||||
- video_player_avfoundation (from `Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||
- volume_controller (from `Flutter/ephemeral/.symlinks/plugins/volume_controller/macos`)
|
||||
- wakelock_plus (from `Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos`)
|
||||
- webview_flutter_wkwebview (from `Flutter/ephemeral/.symlinks/plugins/webview_flutter_wkwebview/darwin`)
|
||||
- window_manager (from `Flutter/ephemeral/.symlinks/plugins/window_manager/macos`)
|
||||
- window_to_front (from `Flutter/ephemeral/.symlinks/plugins/window_to_front/macos`)
|
||||
|
||||
|
|
@ -99,8 +80,6 @@ SPEC REPOS:
|
|||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/app_links/macos
|
||||
audio_session:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/audio_session/macos
|
||||
connectivity_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/connectivity_plus/macos
|
||||
device_info_plus:
|
||||
|
|
@ -119,8 +98,6 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral
|
||||
isar_community_flutter_libs:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/isar_community_flutter_libs/macos
|
||||
just_audio:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/just_audio/darwin
|
||||
media_kit_libs_macos_video:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos
|
||||
media_kit_video:
|
||||
|
|
@ -137,18 +114,12 @@ EXTERNAL SOURCES:
|
|||
:path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos
|
||||
share_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/share_plus/macos
|
||||
sqflite_darwin:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/sqflite_darwin/darwin
|
||||
url_launcher_macos:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
|
||||
video_player_avfoundation:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/video_player_avfoundation/darwin
|
||||
volume_controller:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/volume_controller/macos
|
||||
wakelock_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/wakelock_plus/macos
|
||||
webview_flutter_wkwebview:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/webview_flutter_wkwebview/darwin
|
||||
window_manager:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/window_manager/macos
|
||||
window_to_front:
|
||||
|
|
@ -156,7 +127,6 @@ EXTERNAL SOURCES:
|
|||
|
||||
SPEC CHECKSUMS:
|
||||
app_links: 05a6ec2341985eb05e9f97dc63f5837c39895c3f
|
||||
audio_session: eaca2512cf2b39212d724f35d11f46180ad3a33e
|
||||
connectivity_plus: 4adf20a405e25b42b9c9f87feff8f4b6fde18a4e
|
||||
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
|
||||
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||
|
|
@ -166,7 +136,6 @@ SPEC CHECKSUMS:
|
|||
flutter_web_auth_2: 62b08da29f15a20fa63f144234622a1488d45b65
|
||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||
isar_community_flutter_libs: a631ceb5622413b56bcd0a8bf49cb55bf3d8bb2b
|
||||
just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed
|
||||
media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65
|
||||
media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758
|
||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||
|
|
@ -176,12 +145,9 @@ SPEC CHECKSUMS:
|
|||
screen_brightness_macos: 2a3ee243f8051c340381e8e51bcedced8360f421
|
||||
screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f
|
||||
share_plus: 510bf0af1a42cd602274b4629920c9649c52f4cc
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
||||
video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
|
||||
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
|
||||
wakelock_plus: 917609be14d812ddd9e9528876538b2263aaa03b
|
||||
webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d
|
||||
window_manager: b729e31d38fb04905235df9ea896128991cad99e
|
||||
window_to_front: 9e76fd432e36700a197dac86a0011e49c89abe0a
|
||||
|
||||
|
|
|
|||
328
pubspec.lock
328
pubspec.lock
|
|
@ -105,14 +105,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.13.0"
|
||||
audio_session:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: audio_session
|
||||
sha256: "8f96a7fecbb718cb093070f868b4cdcb8a9b1053dce342ff8ab2fde10eb9afb7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.2"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -201,30 +193,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.12.0"
|
||||
cached_network_image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image
|
||||
sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
cached_network_image_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_platform_interface
|
||||
sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
cached_network_image_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_web
|
||||
sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.1"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -241,14 +209,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.4"
|
||||
chewie:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: chewie
|
||||
sha256: "44bcfc5f0dfd1de290c87c9d86a61308b3282a70b63435d5557cfd60f54a69ca"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.13.0"
|
||||
cli_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -552,14 +512,6 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_cache_manager:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_cache_manager
|
||||
sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
flutter_discord_rpc_fork:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -569,6 +521,14 @@ packages:
|
|||
url: "https://github.com/Schnitzel5/flutter-discord-rpc.git"
|
||||
source: git
|
||||
version: "1.0.5"
|
||||
flutter_html:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_html
|
||||
sha256: "38a2fd702ffdf3243fb7441ab58aa1bc7e6922d95a50db76534de8260638558d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
flutter_inappwebview:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -687,14 +647,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.1"
|
||||
flutter_svg:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_svg
|
||||
sha256: b9c2ad5872518a27507ab432d1fb97e8813b05f0fc693f9d40fad06d073e0678
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.1"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
|
@ -722,22 +674,6 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_widget_from_html:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_widget_from_html
|
||||
sha256: "7f1daefcd3009c43c7e7fb37501e6bb752d79aa7bfad0085fb0444da14e89bd0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.17.1"
|
||||
flutter_widget_from_html_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_widget_from_html_core
|
||||
sha256: "1120ee6ed3509ceff2d55aa6c6cbc7b6b1291434422de2411b5a59364dd6ff03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.17.0"
|
||||
font_awesome_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -770,54 +706,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
fwfh_cached_network_image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fwfh_cached_network_image
|
||||
sha256: "484cb5f8047f02cfac0654fca5832bfa91bb715fd7fc651c04eb7454187c4af8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
fwfh_chewie:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fwfh_chewie
|
||||
sha256: ae74fc26798b0e74f3983f7b851e74c63b9eeb2d3015ecd4b829096b2c3f8818
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
fwfh_just_audio:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fwfh_just_audio
|
||||
sha256: dfd622a0dfe049ac647423a2a8afa7f057d9b2b93d92710b624e3d370b1ac69a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.17.0"
|
||||
fwfh_svg:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fwfh_svg
|
||||
sha256: "2e6bb241179eeeb1a7941e05c8c923b05d332d36a9085233e7bf110ea7deb915"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
fwfh_url_launcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fwfh_url_launcher
|
||||
sha256: c38aa8fb373fda3a89b951fa260b539f623f6edb45eee7874cb8b492471af881
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
fwfh_webview:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fwfh_webview
|
||||
sha256: f71b0aa16e15d82f3c017f33560201ff5ae04e91e970cab5d12d3bcf970b870c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.15.6"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1042,30 +930,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
just_audio:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: just_audio
|
||||
sha256: "9694e4734f515f2a052493d1d7e0d6de219ee0427c7c29492e246ff32a219908"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.5"
|
||||
just_audio_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: just_audio_platform_interface
|
||||
sha256: "2532c8d6702528824445921c5ff10548b518b13f808c2e34c2fd54793b999a6a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.6.0"
|
||||
just_audio_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: just_audio_web
|
||||
sha256: "6ba8a2a7e87d57d32f0f7b42856ade3d6a9fbe0f1a11fabae0a4f00bb73f0663"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.16"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1098,6 +962,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
list_counter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: list_counter
|
||||
sha256: c447ae3dfcd1c55f0152867090e67e219d42fe6d4f2807db4bbe8b8d69912237
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.2"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1226,14 +1098,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.5.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
nm:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1258,14 +1122,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
octo_image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: octo_image
|
||||
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1298,14 +1154,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_parsing
|
||||
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -1474,14 +1322,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "23.0.0"
|
||||
provider:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: provider
|
||||
sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.5+1"
|
||||
pseudom:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -1790,46 +1630,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
sqflite:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite
|
||||
sha256: e2297b1da52f127bc7a3da11439985d9b536f75070f3325e62ada69a5c585d03
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
sqflite_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_android
|
||||
sha256: ecd684501ebc2ae9a83536e8b15731642b9570dc8623e0073d227d0ee2bfea88
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2+2"
|
||||
sqflite_common:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.6"
|
||||
sqflite_darwin:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_darwin
|
||||
sha256: "279832e5cde3fe99e8571879498c9211f3ca6391b0d818df4e17d9fff5c6ccb3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.2"
|
||||
sqflite_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_platform_interface
|
||||
sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2038,30 +1838,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.1"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.19"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_codec
|
||||
sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.13"
|
||||
vector_graphics_compiler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.19"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2070,46 +1846,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
video_player:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player
|
||||
sha256: "0d55b1f1a31e5ad4c4967bfaa8ade0240b07d20ee4af1dfef5f531056512961a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.10.0"
|
||||
video_player_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_android
|
||||
sha256: a8dc4324f67705de057678372bedb66cd08572fe7c495605ac68c5f503324a39
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.8.15"
|
||||
video_player_avfoundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_avfoundation
|
||||
sha256: f9a780aac57802b2892f93787e5ea53b5f43cc57dc107bee9436458365be71cd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.8.4"
|
||||
video_player_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_platform_interface
|
||||
sha256: "9e372520573311055cb353b9a0da1c9d72b094b7ba01b8ecc66f28473553793b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
video_player_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_web
|
||||
sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -2182,38 +1918,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
webview_flutter:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter
|
||||
sha256: c3e4fe614b1c814950ad07186007eff2f2e5dd2935eba7b9a9a1af8e5885f1ba
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.13.0"
|
||||
webview_flutter_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_android
|
||||
sha256: e5201c620eb2637dca88a756961fae4a7191bb30b4f2271e08b746405ffdf3fd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.10.5"
|
||||
webview_flutter_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_platform_interface
|
||||
sha256: "63d26ee3aca7256a83ccb576a50272edd7cfc80573a4305caa98985feb493ee0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.14.0"
|
||||
webview_flutter_wkwebview:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_wkwebview
|
||||
sha256: fea63576b3b7e02b2df8b78ba92b48ed66caec2bb041e9a0b1cbd586d5d80bfd
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.23.1"
|
||||
win32:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ dependencies:
|
|||
path: packages/desktop_webview_window
|
||||
ref: main
|
||||
screen_brightness: ^2.1.1
|
||||
flutter_widget_from_html: ^0.17.1
|
||||
flutter_html: ^3.0.0
|
||||
convert: ^3.1.2
|
||||
connectivity_plus: ^7.0.0
|
||||
app_links: ^6.4.0
|
||||
|
|
|
|||
Loading…
Reference in a new issue