fix
This commit is contained in:
parent
eeddf0d929
commit
2353b48e59
11 changed files with 700 additions and 674 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -1117,9 +1117,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rinf"
|
||||
version = "6.7.0"
|
||||
version = "6.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cac0dc63e157673747bd0286a8565762fd34d0890ff7eedb90eba035dfa4c43"
|
||||
checksum = "b0aa1d51ab106785c8d06df0b3aaa2fd4ca4134afc2757aac95688e60a952a65"
|
||||
dependencies = [
|
||||
"allo-isolate",
|
||||
"backtrace",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:grouped_list/grouped_list.dart';
|
||||
import 'package:grouped_list/sliver_grouped_list.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
|
|
@ -39,80 +39,85 @@ class SourcesFilterScreen extends ConsumerWidget {
|
|||
: element.isNsfw == false)
|
||||
.toList();
|
||||
|
||||
return GroupedListView<Source, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => element.lang!,
|
||||
groupSeparatorBuilder: (String groupByValue) =>
|
||||
SwitchListTile(
|
||||
value: entries
|
||||
.where((element) =>
|
||||
element.lang!.toLowerCase() == groupByValue &&
|
||||
element.isActive! &&
|
||||
element.isManga == isManga)
|
||||
.isNotEmpty,
|
||||
onChanged: (val) {
|
||||
isar.writeTxnSync(() {
|
||||
for (var source in entries) {
|
||||
if (source.lang!.toLowerCase() == groupByValue) {
|
||||
isar.sources
|
||||
.putSync(source..isActive = val == true);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
completeLanguageName(groupByValue),
|
||||
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)
|
||||
.isEmpty) {
|
||||
return Container();
|
||||
}
|
||||
return CheckboxListTile(
|
||||
secondary: Container(
|
||||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.secondaryHeaderColor
|
||||
.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: element.iconUrl!.isEmpty
|
||||
? const Icon(Icons.source_outlined)
|
||||
: cachedNetworkImage(
|
||||
imageUrl: element.iconUrl!,
|
||||
fit: BoxFit.contain,
|
||||
width: 37,
|
||||
height: 37,
|
||||
errorWidget: const SizedBox(
|
||||
width: 37,
|
||||
height: 37,
|
||||
child: Center(
|
||||
child: Icon(Icons.source_outlined),
|
||||
),
|
||||
),
|
||||
),
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverGroupedListView<Source, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => element.lang!,
|
||||
groupSeparatorBuilder: (String groupByValue) =>
|
||||
SwitchListTile(
|
||||
value: entries
|
||||
.where((element) =>
|
||||
element.lang!.toLowerCase() == groupByValue &&
|
||||
element.isActive! &&
|
||||
element.isManga == isManga)
|
||||
.isNotEmpty,
|
||||
onChanged: (val) {
|
||||
isar.writeTxnSync(() {
|
||||
for (var source in entries) {
|
||||
if (source.lang!.toLowerCase() == groupByValue) {
|
||||
isar.sources
|
||||
.putSync(source..isActive = val == true);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
title: Text(
|
||||
completeLanguageName(groupByValue),
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 13),
|
||||
),
|
||||
),
|
||||
onChanged: (bool? value) {
|
||||
isar.writeTxnSync(() {
|
||||
isar.sources.putSync(element..isAdded = value);
|
||||
});
|
||||
itemBuilder: (context, Source element) {
|
||||
if (entries
|
||||
.where((s) =>
|
||||
s.lang!.toLowerCase() == element.lang &&
|
||||
s.isActive! &&
|
||||
s.isManga == isManga)
|
||||
.isEmpty) {
|
||||
return Container();
|
||||
}
|
||||
return CheckboxListTile(
|
||||
secondary: Container(
|
||||
height: 37,
|
||||
width: 37,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context)
|
||||
.secondaryHeaderColor
|
||||
.withOpacity(0.5),
|
||||
borderRadius: BorderRadius.circular(5)),
|
||||
child: element.iconUrl!.isEmpty
|
||||
? const Icon(Icons.source_outlined)
|
||||
: cachedNetworkImage(
|
||||
imageUrl: element.iconUrl!,
|
||||
fit: BoxFit.contain,
|
||||
width: 37,
|
||||
height: 37,
|
||||
errorWidget: const SizedBox(
|
||||
width: 37,
|
||||
height: 37,
|
||||
child: Center(
|
||||
child: Icon(Icons.source_outlined),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
onChanged: (bool? value) {
|
||||
isar.writeTxnSync(() {
|
||||
isar.sources.putSync(element..isAdded = value);
|
||||
});
|
||||
},
|
||||
value: element.isAdded!,
|
||||
title: Text(element.name!),
|
||||
);
|
||||
},
|
||||
value: element.isAdded!,
|
||||
title: Text(element.name!),
|
||||
);
|
||||
},
|
||||
groupComparator: (group1, group2) => group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
groupComparator: (group1, group2) =>
|
||||
group1.compareTo(group2),
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.name!.compareTo(item2.name!),
|
||||
order: GroupedListOrder.ASC,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import 'dart:typed_data';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:grouped_list/grouped_list.dart';
|
||||
import 'package:grouped_list/sliver_grouped_list.dart';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
|
|
@ -198,198 +199,209 @@ class _HistoryTabState extends ConsumerState<HistoryTab> {
|
|||
.toList();
|
||||
|
||||
if (entries.isNotEmpty) {
|
||||
return GroupedListView<History, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => dateFormat(element.date!,
|
||||
context: context,
|
||||
ref: ref,
|
||||
forHistoryValue: true,
|
||||
useRelativeTimesTamps: false),
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8, left: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(dateFormat(
|
||||
null,
|
||||
return CustomScrollView(
|
||||
slivers: [
|
||||
SliverGroupedListView<History, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => dateFormat(element.date!,
|
||||
context: context,
|
||||
stringDate: groupByValue,
|
||||
ref: ref,
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, History element) {
|
||||
final manga = element.chapter.value!.manga.value!;
|
||||
final chapter = element.chapter.value!;
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(0)),
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
pushMangaReaderView(context: context, chapter: chapter);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: SizedBox(
|
||||
height: 105,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 60,
|
||||
height: 90,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(7)),
|
||||
forHistoryValue: true,
|
||||
useRelativeTimesTamps: false),
|
||||
groupSeparatorBuilder: (String groupByValue) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8, left: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(dateFormat(
|
||||
null,
|
||||
context: context,
|
||||
stringDate: groupByValue,
|
||||
ref: ref,
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
itemBuilder: (context, History element) {
|
||||
final manga = element.chapter.value!.manga.value!;
|
||||
final chapter = element.chapter.value!;
|
||||
return ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
backgroundColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(0)),
|
||||
elevation: 0,
|
||||
shadowColor: Colors.transparent),
|
||||
onPressed: () {
|
||||
pushMangaReaderView(context: context, chapter: chapter);
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: SizedBox(
|
||||
height: 105,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 60,
|
||||
height: 90,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.all(0),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(7)),
|
||||
),
|
||||
onPressed: () {
|
||||
context.push('/manga-reader/detail',
|
||||
extra: manga.id);
|
||||
},
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
child: manga.customCoverImage != null
|
||||
? Image.memory(
|
||||
manga.customCoverImage as Uint8List)
|
||||
: cachedNetworkImage(
|
||||
headers: ref.watch(headersProvider(
|
||||
source: manga.source!,
|
||||
lang: manga.lang!)),
|
||||
imageUrl: toImgUrl(
|
||||
manga.customCoverFromTracker ??
|
||||
manga.imageUrl!),
|
||||
width: 60,
|
||||
height: 90,
|
||||
fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
context.push('/manga-reader/detail',
|
||||
extra: manga.id);
|
||||
},
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(7),
|
||||
child: manga.customCoverImage != null
|
||||
? Image.memory(
|
||||
manga.customCoverImage as Uint8List)
|
||||
: cachedNetworkImage(
|
||||
headers: ref.watch(headersProvider(
|
||||
source: manga.source!,
|
||||
lang: manga.lang!)),
|
||||
imageUrl: toImgUrl(
|
||||
manga.customCoverFromTracker ??
|
||||
manga.imageUrl!),
|
||||
width: 60,
|
||||
height: 90,
|
||||
fit: BoxFit.cover),
|
||||
),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
manga.name!,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
Wrap(
|
||||
Flexible(
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
crossAxisAlignment:
|
||||
WrapCrossAlignment.end,
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
chapter.name!,
|
||||
manga.name!,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
" - ${dateFormatHour(element.date!, context)}",
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontSize: 14,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
fontWeight: FontWeight.w400),
|
||||
fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.start,
|
||||
),
|
||||
Wrap(
|
||||
crossAxisAlignment:
|
||||
WrapCrossAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
chapter.name!,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
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),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
l10n.remove,
|
||||
),
|
||||
content:
|
||||
Text(l10n.remove_history_msg),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(l10n.cancel)),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await isar
|
||||
.writeTxn(() async {
|
||||
await isar.historys
|
||||
.delete(
|
||||
element.id!);
|
||||
});
|
||||
if (context.mounted) {
|
||||
Navigator.pop(
|
||||
context);
|
||||
}
|
||||
},
|
||||
child: Text(l10n.remove)),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(
|
||||
l10n.remove,
|
||||
),
|
||||
content: Text(
|
||||
l10n.remove_history_msg),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(
|
||||
context);
|
||||
},
|
||||
child: Text(
|
||||
l10n.cancel)),
|
||||
const SizedBox(
|
||||
width: 15,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
await isar.writeTxn(
|
||||
() async {
|
||||
await isar
|
||||
.historys
|
||||
.delete(
|
||||
element
|
||||
.id!);
|
||||
});
|
||||
if (context
|
||||
.mounted) {
|
||||
Navigator.pop(
|
||||
context);
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
l10n.remove)),
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.delete_outline,
|
||||
size: 25,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
)),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.delete_outline,
|
||||
size: 25,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyLarge!
|
||||
.color,
|
||||
)),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.date!.compareTo(item2.date!),
|
||||
order: GroupedListOrder.DESC,
|
||||
);
|
||||
},
|
||||
itemComparator: (item1, item2) =>
|
||||
item1.date!.compareTo(item2.date!),
|
||||
order: GroupedListOrder.DESC,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return Center(
|
||||
|
|
|
|||
|
|
@ -14,13 +14,11 @@ import 'package:photo_view/photo_view_gallery.dart';
|
|||
class DoubleColummView extends StatefulWidget {
|
||||
final List<UChapDataPreload?> datas;
|
||||
final Function(UChapDataPreload datas) onLongPressData;
|
||||
final Function(double) scale;
|
||||
final BackgroundColor backgroundColor;
|
||||
final Function(bool) isFailedToLoadImage;
|
||||
const DoubleColummView(
|
||||
{super.key,
|
||||
required this.datas,
|
||||
required this.scale,
|
||||
required this.onLongPressData,
|
||||
required this.backgroundColor,
|
||||
required this.isFailedToLoadImage});
|
||||
|
|
@ -70,7 +68,6 @@ class _DoubleColummViewState extends State<DoubleColummView>
|
|||
CurvedAnimation(curve: Curves.ease, parent: _scaleAnimationController));
|
||||
_animation.addListener(() {
|
||||
_photoViewController.scale = _animation.value;
|
||||
widget.scale(_animation.value);
|
||||
});
|
||||
|
||||
super.initState();
|
||||
|
|
|
|||
|
|
@ -24,12 +24,12 @@ Future<Uint8List?> cropBorders(CropBordersRef ref,
|
|||
nextId++;
|
||||
final completer = Completer<Uint8List>();
|
||||
CropBordersInput(
|
||||
interactionId: currentId,
|
||||
).sendSignalToRust(imageBytes);
|
||||
image: imageBytes,
|
||||
).sendSignalToRust();
|
||||
final stream = CropBordersOutput.rustSignalStream;
|
||||
final subscription = stream.listen((rustSignal) {
|
||||
if (rustSignal.message.interactionId == currentId) {
|
||||
completer.complete(rustSignal.blob!);
|
||||
completer.complete(rustSignal.message.image as Uint8List);
|
||||
}
|
||||
});
|
||||
final image = await completer.future;
|
||||
|
|
|
|||
|
|
@ -473,374 +473,385 @@ class _MangaChapterPageGalleryState
|
|||
|
||||
return true;
|
||||
},
|
||||
child: SafeArea(
|
||||
top: !fullScreenReader,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _failedToLoadImage,
|
||||
builder: (context, failedToLoadImage, child) {
|
||||
return Stack(
|
||||
children: [
|
||||
_isVerticalOrHorizontalContinous()
|
||||
? PhotoViewGallery.builder(
|
||||
itemCount: 1,
|
||||
builder: (_, __) =>
|
||||
PhotoViewGalleryPageOptions.customChild(
|
||||
controller: _photoViewController,
|
||||
scaleStateController:
|
||||
_photoViewScaleStateController,
|
||||
basePosition: _scalePosition,
|
||||
onScaleEnd: _onScaleEnd,
|
||||
child: ScrollablePositionedList.separated(
|
||||
scrollDirection: isHorizontalContinuaous
|
||||
? Axis.horizontal
|
||||
: Axis.vertical,
|
||||
minCacheExtent:
|
||||
pagePreloadAmount * context.height(1),
|
||||
initialScrollIndex:
|
||||
_readerController.getPageIndex(),
|
||||
itemCount:
|
||||
(_pageMode == PageMode.doublePage &&
|
||||
!isHorizontalContinuaous)
|
||||
? (_uChapDataPreload.length / 2)
|
||||
.ceil() +
|
||||
1
|
||||
: _uChapDataPreload.length,
|
||||
child: Material(
|
||||
child: SafeArea(
|
||||
top: !fullScreenReader,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _failedToLoadImage,
|
||||
builder: (context, failedToLoadImage, child) {
|
||||
return Stack(
|
||||
children: [
|
||||
_isVerticalOrHorizontalContinous()
|
||||
? PhotoViewGallery.builder(
|
||||
itemCount: 1,
|
||||
builder: (_, __) =>
|
||||
PhotoViewGalleryPageOptions.customChild(
|
||||
controller: _photoViewController,
|
||||
scaleStateController:
|
||||
_photoViewScaleStateController,
|
||||
basePosition: _scalePosition,
|
||||
onScaleEnd: _onScaleEnd,
|
||||
child: ScrollablePositionedList.separated(
|
||||
scrollDirection: isHorizontalContinuaous
|
||||
? Axis.horizontal
|
||||
: Axis.vertical,
|
||||
minCacheExtent: pagePreloadAmount *
|
||||
context.height(1),
|
||||
initialScrollIndex:
|
||||
_readerController.getPageIndex(),
|
||||
itemCount:
|
||||
(_pageMode == PageMode.doublePage &&
|
||||
!isHorizontalContinuaous)
|
||||
? (_uChapDataPreload.length / 2)
|
||||
.ceil() +
|
||||
1
|
||||
: _uChapDataPreload.length,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
itemScrollController:
|
||||
_itemScrollController,
|
||||
scrollOffsetController:
|
||||
_pageOffsetController,
|
||||
itemPositionsListener:
|
||||
_itemPositionsListener,
|
||||
itemBuilder: (context, index) {
|
||||
int index1 = index * 2 - 1;
|
||||
int index2 = index1 + 1;
|
||||
return GestureDetector(
|
||||
behavior:
|
||||
HitTestBehavior.translucent,
|
||||
onDoubleTapDown: (details) {
|
||||
_toggleScale(
|
||||
details.globalPosition);
|
||||
},
|
||||
onDoubleTap: () {},
|
||||
child: (_pageMode ==
|
||||
PageMode.doublePage &&
|
||||
!isHorizontalContinuaous)
|
||||
? DoubleColummVerticalView(
|
||||
datas: index == 0
|
||||
? [
|
||||
_uChapDataPreload[
|
||||
0],
|
||||
null
|
||||
]
|
||||
: [
|
||||
index1 <
|
||||
_uChapDataPreload
|
||||
.length
|
||||
? _uChapDataPreload[
|
||||
index1]
|
||||
: null,
|
||||
index2 <
|
||||
_uChapDataPreload
|
||||
.length
|
||||
? _uChapDataPreload[
|
||||
index2]
|
||||
: null,
|
||||
],
|
||||
scale: (a) {},
|
||||
backgroundColor:
|
||||
backgroundColor,
|
||||
isFailedToLoadImage:
|
||||
(val) {},
|
||||
onLongPressData: (datas) {
|
||||
_onLongPressImageDialog(
|
||||
datas, context);
|
||||
},
|
||||
)
|
||||
: ImageViewVertical(
|
||||
data: _uChapDataPreload[
|
||||
index],
|
||||
failedToLoadImage: (value) {
|
||||
// _failedToLoadImage.value = value;
|
||||
},
|
||||
onLongPressData: (datas) {
|
||||
_onLongPressImageDialog(
|
||||
datas, context);
|
||||
},
|
||||
isHorizontal: ref.watch(
|
||||
_currentReaderMode) ==
|
||||
ReaderMode
|
||||
.horizontalContinuous,
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, __) => ref.watch(
|
||||
_currentReaderMode) ==
|
||||
ReaderMode.webtoon
|
||||
? const SizedBox.shrink()
|
||||
: ref.watch(_currentReaderMode) ==
|
||||
ReaderMode
|
||||
.horizontalContinuous
|
||||
? VerticalDivider(
|
||||
color: getBackgroundColor(
|
||||
backgroundColor),
|
||||
width: 6)
|
||||
: Divider(
|
||||
color: getBackgroundColor(
|
||||
backgroundColor),
|
||||
height: 6),
|
||||
)),
|
||||
)
|
||||
: Material(
|
||||
color: getBackgroundColor(backgroundColor),
|
||||
shadowColor: getBackgroundColor(backgroundColor),
|
||||
child: (_pageMode == PageMode.doublePage &&
|
||||
!isHorizontalContinuaous)
|
||||
? ExtendedImageGesturePageView.builder(
|
||||
controller: _extendedController,
|
||||
scrollDirection: _scrollDirection,
|
||||
reverse: _isReverseHorizontal,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
itemScrollController:
|
||||
_itemScrollController,
|
||||
scrollOffsetController:
|
||||
_pageOffsetController,
|
||||
itemPositionsListener:
|
||||
_itemPositionsListener,
|
||||
canScrollPage: (_) {
|
||||
return _horizontalScaleValue == 1.0;
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
int index1 = index * 2 - 1;
|
||||
int index2 = index1 + 1;
|
||||
return GestureDetector(
|
||||
behavior: HitTestBehavior.translucent,
|
||||
onDoubleTapDown:
|
||||
(TapDownDetails details) {
|
||||
_toggleScale(
|
||||
details.globalPosition);
|
||||
final pageList = (index == 0
|
||||
? [_uChapDataPreload[0], null]
|
||||
: [
|
||||
index1 <
|
||||
_uChapDataPreload.length
|
||||
? _uChapDataPreload[index1]
|
||||
: null,
|
||||
index2 <
|
||||
_uChapDataPreload.length
|
||||
? _uChapDataPreload[index2]
|
||||
: null,
|
||||
]);
|
||||
return DoubleColummView(
|
||||
datas: _isReverseHorizontal
|
||||
? pageList.reversed.toList()
|
||||
: pageList,
|
||||
backgroundColor: backgroundColor,
|
||||
isFailedToLoadImage: (val) {
|
||||
if (_failedToLoadImage.value !=
|
||||
val &&
|
||||
mounted) {
|
||||
_failedToLoadImage.value = val;
|
||||
}
|
||||
},
|
||||
onLongPressData: (datas) {
|
||||
_onLongPressImageDialog(
|
||||
datas, context);
|
||||
},
|
||||
onDoubleTap: () {},
|
||||
child: (_pageMode ==
|
||||
PageMode.doublePage &&
|
||||
!isHorizontalContinuaous)
|
||||
? DoubleColummVerticalView(
|
||||
datas: index == 0
|
||||
? [
|
||||
_uChapDataPreload[0],
|
||||
null
|
||||
]
|
||||
: [
|
||||
index1 <
|
||||
_uChapDataPreload
|
||||
.length
|
||||
? _uChapDataPreload[
|
||||
index1]
|
||||
: null,
|
||||
index2 <
|
||||
_uChapDataPreload
|
||||
.length
|
||||
? _uChapDataPreload[
|
||||
index2]
|
||||
: null,
|
||||
],
|
||||
scale: (a) {},
|
||||
backgroundColor:
|
||||
backgroundColor,
|
||||
isFailedToLoadImage: (val) {},
|
||||
onLongPressData: (datas) {
|
||||
_onLongPressImageDialog(
|
||||
datas, context);
|
||||
},
|
||||
)
|
||||
: ImageViewVertical(
|
||||
data:
|
||||
_uChapDataPreload[index],
|
||||
failedToLoadImage: (value) {
|
||||
// _failedToLoadImage.value = value;
|
||||
},
|
||||
onLongPressData: (datas) {
|
||||
_onLongPressImageDialog(
|
||||
datas, context);
|
||||
},
|
||||
isHorizontal: ref.watch(
|
||||
_currentReaderMode) ==
|
||||
ReaderMode
|
||||
.horizontalContinuous,
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, __) =>
|
||||
ref.watch(_currentReaderMode) ==
|
||||
ReaderMode.webtoon
|
||||
? const SizedBox.shrink()
|
||||
: ref.watch(_currentReaderMode) ==
|
||||
ReaderMode
|
||||
.horizontalContinuous
|
||||
? VerticalDivider(
|
||||
color: getBackgroundColor(
|
||||
backgroundColor),
|
||||
width: 6)
|
||||
: Divider(
|
||||
color: getBackgroundColor(
|
||||
backgroundColor),
|
||||
height: 6),
|
||||
)),
|
||||
)
|
||||
: Material(
|
||||
color: getBackgroundColor(backgroundColor),
|
||||
shadowColor: getBackgroundColor(backgroundColor),
|
||||
child: (_pageMode == PageMode.doublePage &&
|
||||
!isHorizontalContinuaous)
|
||||
? ExtendedImageGesturePageView.builder(
|
||||
controller: _extendedController,
|
||||
scrollDirection: _scrollDirection,
|
||||
reverse: _isReverseHorizontal,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
canScrollPage: (_) {
|
||||
return _horizontalScaleValue == 1.0;
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
int index1 = index * 2 - 1;
|
||||
int index2 = index1 + 1;
|
||||
final pageList = (index == 0
|
||||
? [_uChapDataPreload[0], null]
|
||||
: [
|
||||
index1 < _uChapDataPreload.length
|
||||
? _uChapDataPreload[index1]
|
||||
: null,
|
||||
index2 < _uChapDataPreload.length
|
||||
? _uChapDataPreload[index2]
|
||||
: null,
|
||||
]);
|
||||
return DoubleColummView(
|
||||
datas: _isReverseHorizontal
|
||||
? pageList.reversed.toList()
|
||||
: pageList,
|
||||
scale: (a) {},
|
||||
backgroundColor: backgroundColor,
|
||||
isFailedToLoadImage: (val) {
|
||||
if (_failedToLoadImage.value != val &&
|
||||
mounted) {
|
||||
_failedToLoadImage.value = val;
|
||||
}
|
||||
},
|
||||
onLongPressData: (datas) {
|
||||
_onLongPressImageDialog(
|
||||
datas, context);
|
||||
},
|
||||
);
|
||||
},
|
||||
itemCount:
|
||||
(_uChapDataPreload.length / 2).ceil() +
|
||||
1,
|
||||
onPageChanged: _onPageChanged)
|
||||
: ExtendedImageGesturePageView.builder(
|
||||
controller: _extendedController,
|
||||
scrollDirection: _scrollDirection,
|
||||
reverse: _isReverseHorizontal,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
canScrollPage: (gestureDetails) {
|
||||
return gestureDetails != null
|
||||
? !(gestureDetails.totalScale! > 1.0)
|
||||
: true;
|
||||
},
|
||||
itemBuilder:
|
||||
(BuildContext context, int index) {
|
||||
return ImageViewCenter(
|
||||
data: _uChapDataPreload[index],
|
||||
loadStateChanged: (state) {
|
||||
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(
|
||||
backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child:
|
||||
CircularProgressIndicatorAnimateRotate(
|
||||
progress: progress),
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.completed) {
|
||||
if (_failedToLoadImage.value ==
|
||||
true) {
|
||||
_failedToLoadImage.value = false;
|
||||
}
|
||||
return StreamBuilder(
|
||||
builder: (context, data) {
|
||||
return ExtendedImageGesture(
|
||||
state,
|
||||
canScaleImage: (_) =>
|
||||
_imageDetailY == 0,
|
||||
imageBuilder: (image) {
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
top: _imageDetailY,
|
||||
bottom:
|
||||
-_imageDetailY,
|
||||
child: image,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
initialData: _imageDetailY,
|
||||
stream: _rebuildDetail.stream,
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.failed) {
|
||||
if (_failedToLoadImage.value ==
|
||||
false) {
|
||||
_failedToLoadImage.value = true;
|
||||
}
|
||||
return Container(
|
||||
itemCount: (_uChapDataPreload.length / 2)
|
||||
.ceil() +
|
||||
1,
|
||||
onPageChanged: _onPageChanged)
|
||||
: ExtendedImageGesturePageView.builder(
|
||||
controller: _extendedController,
|
||||
scrollDirection: _scrollDirection,
|
||||
reverse: _isReverseHorizontal,
|
||||
physics: const ClampingScrollPhysics(),
|
||||
canScrollPage: (gestureDetails) {
|
||||
return gestureDetails != null
|
||||
? !(gestureDetails.totalScale! >
|
||||
1.0)
|
||||
: true;
|
||||
},
|
||||
itemBuilder:
|
||||
(BuildContext context, int index) {
|
||||
return ImageViewCenter(
|
||||
data: _uChapDataPreload[index],
|
||||
loadStateChanged: (state) {
|
||||
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(
|
||||
backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
l10n.image_loading_error,
|
||||
style: TextStyle(
|
||||
color: Colors.white
|
||||
.withOpacity(
|
||||
0.7)),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.all(
|
||||
8.0),
|
||||
child: GestureDetector(
|
||||
onLongPress: () {
|
||||
state.reLoadImage();
|
||||
_failedToLoadImage
|
||||
.value = false;
|
||||
},
|
||||
onTap: () {
|
||||
state.reLoadImage();
|
||||
_failedToLoadImage
|
||||
.value = false;
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context
|
||||
.primaryColor,
|
||||
borderRadius:
|
||||
BorderRadius
|
||||
.circular(
|
||||
30)),
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets
|
||||
.symmetric(
|
||||
vertical:
|
||||
8,
|
||||
horizontal:
|
||||
16),
|
||||
child: Text(
|
||||
l10n.retry,
|
||||
child:
|
||||
CircularProgressIndicatorAnimateRotate(
|
||||
progress: progress),
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.completed) {
|
||||
if (_failedToLoadImage.value ==
|
||||
true) {
|
||||
_failedToLoadImage.value =
|
||||
false;
|
||||
}
|
||||
return StreamBuilder(
|
||||
builder: (context, data) {
|
||||
return ExtendedImageGesture(
|
||||
state,
|
||||
canScaleImage: (_) =>
|
||||
_imageDetailY == 0,
|
||||
imageBuilder: (image) {
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
top: _imageDetailY,
|
||||
bottom:
|
||||
-_imageDetailY,
|
||||
child: image,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
initialData: _imageDetailY,
|
||||
stream: _rebuildDetail.stream,
|
||||
);
|
||||
}
|
||||
if (state.extendedImageLoadState ==
|
||||
LoadState.failed) {
|
||||
if (_failedToLoadImage.value ==
|
||||
false) {
|
||||
_failedToLoadImage.value = true;
|
||||
}
|
||||
return Container(
|
||||
color: getBackgroundColor(
|
||||
backgroundColor),
|
||||
height: context.height(0.8),
|
||||
child: Column(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.center,
|
||||
children: [
|
||||
Text(
|
||||
l10n.image_loading_error,
|
||||
style: TextStyle(
|
||||
color: Colors.white
|
||||
.withOpacity(
|
||||
0.7)),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets
|
||||
.all(8.0),
|
||||
child: GestureDetector(
|
||||
onLongPress: () {
|
||||
state
|
||||
.reLoadImage();
|
||||
_failedToLoadImage
|
||||
.value =
|
||||
false;
|
||||
},
|
||||
onTap: () {
|
||||
state
|
||||
.reLoadImage();
|
||||
_failedToLoadImage
|
||||
.value =
|
||||
false;
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: context
|
||||
.primaryColor,
|
||||
borderRadius:
|
||||
BorderRadius
|
||||
.circular(
|
||||
30)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets
|
||||
.symmetric(
|
||||
vertical: 8,
|
||||
horizontal:
|
||||
16),
|
||||
child: Text(
|
||||
l10n.retry,
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
initGestureConfigHandler: (state) {
|
||||
return GestureConfig(
|
||||
inertialSpeed: 200,
|
||||
inPageView: true,
|
||||
maxScale: 8,
|
||||
animationMaxScale: 8,
|
||||
cacheGesture: true,
|
||||
hitTestBehavior:
|
||||
HitTestBehavior.translucent,
|
||||
);
|
||||
},
|
||||
onDoubleTap: (state) {
|
||||
final Offset? pointerDownPosition =
|
||||
state.pointerDownPosition;
|
||||
final double? begin =
|
||||
state.gestureDetails!.totalScale;
|
||||
double end;
|
||||
)),
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
initGestureConfigHandler: (state) {
|
||||
return GestureConfig(
|
||||
inertialSpeed: 200,
|
||||
inPageView: true,
|
||||
maxScale: 8,
|
||||
animationMaxScale: 8,
|
||||
cacheGesture: true,
|
||||
hitTestBehavior:
|
||||
HitTestBehavior.translucent,
|
||||
);
|
||||
},
|
||||
onDoubleTap: (state) {
|
||||
final Offset? pointerDownPosition =
|
||||
state.pointerDownPosition;
|
||||
final double? begin = state
|
||||
.gestureDetails!.totalScale;
|
||||
double end;
|
||||
|
||||
//remove old
|
||||
_doubleClickAnimation?.removeListener(
|
||||
_doubleClickAnimationListener);
|
||||
//remove old
|
||||
_doubleClickAnimation?.removeListener(
|
||||
_doubleClickAnimationListener);
|
||||
|
||||
//stop pre
|
||||
_doubleClickAnimationController
|
||||
.stop();
|
||||
//stop pre
|
||||
_doubleClickAnimationController
|
||||
.stop();
|
||||
|
||||
//reset to use
|
||||
_doubleClickAnimationController
|
||||
.reset();
|
||||
//reset to use
|
||||
_doubleClickAnimationController
|
||||
.reset();
|
||||
|
||||
if (begin == doubleTapScales[0]) {
|
||||
end = doubleTapScales[1];
|
||||
} else {
|
||||
end = doubleTapScales[0];
|
||||
}
|
||||
if (begin == doubleTapScales[0]) {
|
||||
end = doubleTapScales[1];
|
||||
} else {
|
||||
end = doubleTapScales[0];
|
||||
}
|
||||
|
||||
_doubleClickAnimationListener = () {
|
||||
state.handleDoubleTap(
|
||||
scale: _doubleClickAnimation!
|
||||
.value,
|
||||
doubleTapPosition:
|
||||
pointerDownPosition);
|
||||
};
|
||||
_doubleClickAnimationListener = () {
|
||||
state.handleDoubleTap(
|
||||
scale: _doubleClickAnimation!
|
||||
.value,
|
||||
doubleTapPosition:
|
||||
pointerDownPosition);
|
||||
};
|
||||
|
||||
_doubleClickAnimation = Tween(
|
||||
begin: begin, end: end)
|
||||
.animate(CurvedAnimation(
|
||||
curve: Curves.ease,
|
||||
parent:
|
||||
_doubleClickAnimationController));
|
||||
_doubleClickAnimation = Tween(
|
||||
begin: begin, end: end)
|
||||
.animate(CurvedAnimation(
|
||||
curve: Curves.ease,
|
||||
parent:
|
||||
_doubleClickAnimationController));
|
||||
|
||||
_doubleClickAnimation!.addListener(
|
||||
_doubleClickAnimationListener);
|
||||
_doubleClickAnimation!.addListener(
|
||||
_doubleClickAnimationListener);
|
||||
|
||||
_doubleClickAnimationController
|
||||
.forward();
|
||||
},
|
||||
onLongPressData: (datas) {
|
||||
_onLongPressImageDialog(
|
||||
datas, context);
|
||||
},
|
||||
);
|
||||
},
|
||||
itemCount: _uChapDataPreload.length,
|
||||
onPageChanged: _onPageChanged)),
|
||||
_gestureRightLeft(failedToLoadImage, usePageTapZones),
|
||||
_gestureTopBottom(failedToLoadImage, usePageTapZones),
|
||||
_appBar(),
|
||||
_bottomBar(),
|
||||
_showPage(),
|
||||
_autoScrollPlayPauseBtn()
|
||||
],
|
||||
);
|
||||
}),
|
||||
_doubleClickAnimationController
|
||||
.forward();
|
||||
},
|
||||
onLongPressData: (datas) {
|
||||
_onLongPressImageDialog(
|
||||
datas, context);
|
||||
},
|
||||
);
|
||||
},
|
||||
itemCount: _uChapDataPreload.length,
|
||||
onPageChanged: _onPageChanged)),
|
||||
_gestureRightLeft(failedToLoadImage, usePageTapZones),
|
||||
_gestureTopBottom(failedToLoadImage, usePageTapZones),
|
||||
_appBar(),
|
||||
_bottomBar(),
|
||||
_showPage(),
|
||||
_autoScrollPlayPauseBtn()
|
||||
],
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -1853,12 +1864,12 @@ class _MangaChapterPageGalleryState
|
|||
}
|
||||
},
|
||||
onDoubleTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
onSecondaryTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
|
|
@ -1882,12 +1893,12 @@ class _MangaChapterPageGalleryState
|
|||
_isViewFunction();
|
||||
},
|
||||
onDoubleTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
onSecondaryTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
|
|
@ -1915,12 +1926,12 @@ class _MangaChapterPageGalleryState
|
|||
}
|
||||
},
|
||||
onDoubleTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
onSecondaryTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
|
|
@ -1953,12 +1964,12 @@ class _MangaChapterPageGalleryState
|
|||
: _isViewFunction();
|
||||
},
|
||||
onDoubleTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
onSecondaryTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
|
|
@ -1984,12 +1995,12 @@ class _MangaChapterPageGalleryState
|
|||
: _isViewFunction();
|
||||
},
|
||||
onDoubleTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
onSecondaryTapDown: _isVerticalOrHorizontalContinous()
|
||||
? (TapDownDetails details) {
|
||||
? (details) {
|
||||
_toggleScale(details.globalPosition);
|
||||
}
|
||||
: null,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ syntax = "proto3";
|
|||
package crop_borders;
|
||||
|
||||
// [RINF:DART-SIGNAL]
|
||||
message CropBordersInput { int32 interaction_id = 1; }
|
||||
message CropBordersInput { int32 interaction_id = 1; bytes image = 2; }
|
||||
|
||||
// [RINF:RUST-SIGNAL]
|
||||
message CropBordersOutput { int32 interaction_id = 1; }
|
||||
message CropBordersOutput { int32 interaction_id = 1; bytes image = 2; }
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ edition = "2021"
|
|||
crate-type = ["lib", "cdylib", "staticlib"]
|
||||
|
||||
[dependencies]
|
||||
rinf = "6.7.0"
|
||||
rinf = "6.9.2"
|
||||
allo-isolate = "0.1.24"
|
||||
wasm-bindgen = "0.2.90"
|
||||
prost = "0.12.3"
|
||||
|
|
|
|||
|
|
@ -142,14 +142,15 @@ pub async fn start_croping() {
|
|||
|
||||
let mut receiver = CropBordersInput::get_dart_signal_receiver();
|
||||
while let Some(dart_signal) = receiver.recv().await {
|
||||
let image = dart_signal.blob.unwrap();
|
||||
let image = dart_signal.message.image;
|
||||
let res = crop_image(image);
|
||||
let mut image_data: Vec<u8> = Vec::new();
|
||||
res.write_to(&mut Cursor::new(&mut image_data), image::ImageFormat::Png)
|
||||
.unwrap();
|
||||
CropBordersOutput {
|
||||
interaction_id: dart_signal.message.interaction_id,
|
||||
image: image_data,
|
||||
}
|
||||
.send_signal_to_dart(Some(image_data));
|
||||
.send_signal_to_dart();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
80
pubspec.lock
80
pubspec.lock
|
|
@ -221,10 +221,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
|
||||
sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.3+8"
|
||||
version: "0.3.4+1"
|
||||
crypto:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -404,10 +404,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: ffigen
|
||||
sha256: dead012f29db2be71ea152458f5eab600de98fbc244e01088ae6bf2616bceca7
|
||||
sha256: "3e12e80ccb6539bb3917217bb6f32709220efb737de0d0fa8736da0b7cb507da"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.0.0"
|
||||
version: "12.0.0"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -420,10 +420,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: file_picker
|
||||
sha256: "1bbf65dd997458a08b531042ec3794112a6c39c07c37ff22113d2e7e4f81d4e4"
|
||||
sha256: "29c90806ac5f5fb896547720b73b17ee9aed9bba540dc5d91fe29f8c5745b10a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.1"
|
||||
version: "8.0.3"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -444,10 +444,10 @@ packages:
|
|||
dependency: "direct overridden"
|
||||
description:
|
||||
name: flex_seed_scheme
|
||||
sha256: "116dc56093aa4e64d2f03135957b5ef61b1134a4a4990c66f76bc635903d0d8c"
|
||||
sha256: fb66cdb8ca89084e79efcad2bc2d9deb144666875116f08cdd8d9f8238c8b3ab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0-dev.1"
|
||||
version: "2.0.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
@ -489,10 +489,10 @@ packages:
|
|||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_lints
|
||||
sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
|
||||
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
version: "4.0.0"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
|
|
@ -594,10 +594,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: go_router
|
||||
sha256: c5fa45fa502ee880839e3b2152d987c44abae26d064a2376d4aad434cf0f7b15
|
||||
sha256: aa073287b8f43553678e6fa9e8bb9c83212ff76e09542129a8099bbc8db4df65
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.1.3"
|
||||
version: "14.1.2"
|
||||
google_api_availability:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
@ -674,10 +674,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
|
||||
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
http_client_helper:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -866,10 +866,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: lints
|
||||
sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
|
||||
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "4.0.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1019,18 +1019,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
|
||||
sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
version: "8.0.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
|
||||
sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "3.0.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1147,10 +1147,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: photo_view
|
||||
sha256: "8036802a00bae2a78fc197af8a158e3e2f7b500561ed23b4c458107685e645bb"
|
||||
sha256: "1fc3d970a91295fbd1364296575f854c9863f225505c28c46e0a03e48960c75e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.14.0"
|
||||
version: "0.15.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1235,10 +1235,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: rinf
|
||||
sha256: a8a61585a5c8e57bb374d6491821dd4656096a44761d300e435490495af73e77
|
||||
sha256: "2b4cb68c83634c3e7012c67443dab3f03d232ea326362ab1ca89585192468ffb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.7.0"
|
||||
version: "6.9.2"
|
||||
riverpod:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1355,18 +1355,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: share_plus
|
||||
sha256: "3ef39599b00059db0990ca2e30fca0a29d8b37aae924d60063f8e0184cf20900"
|
||||
sha256: ef3489a969683c4f3d0239010cc8b7a2a46543a8d139e111c06c558875083544
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.2.2"
|
||||
version: "9.0.0"
|
||||
share_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share_plus_platform_interface
|
||||
sha256: "251eb156a8b5fa9ce033747d73535bf53911071f8d3b6f4f0b578505ce0d4496"
|
||||
sha256: "0f9e4418835d1b2c3ae78fdb918251959106cefdbc4dd43526e182f80e82f6d4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.0"
|
||||
version: "4.0.0"
|
||||
shelf:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1576,10 +1576,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b
|
||||
sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
version: "2.3.1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1624,18 +1624,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus
|
||||
sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d
|
||||
sha256: "14758533319a462ffb5aa3b7ddb198e59b29ac3b02da14173a1715d65d4e6e68"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.4"
|
||||
version: "1.2.5"
|
||||
wakelock_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus_platform_interface
|
||||
sha256: "40fabed5da06caff0796dc638e1f07ee395fb18801fbff3255a2372db2d80385"
|
||||
sha256: "422d1cdbb448079a8a62a5a770b69baa489f8f7ca21aef47800c726d404f9d16"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.2.1"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
@ -1648,26 +1648,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05"
|
||||
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.2"
|
||||
version: "0.5.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: "939ab60734a4f8fa95feacb55804fa278de28bdeef38e616dc08e44a84adea23"
|
||||
sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
version: "2.4.5"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
|
||||
sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.3.0"
|
||||
version: "5.5.1"
|
||||
window_manager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
|||
28
pubspec.yaml
28
pubspec.yaml
|
|
@ -11,7 +11,7 @@ dependencies:
|
|||
sdk: flutter
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
go_router: ^12.1.3
|
||||
go_router: ^14.1.2
|
||||
flutter_riverpod: ^2.4.10
|
||||
riverpod_annotation: ^2.3.3
|
||||
html: ^0.15.4
|
||||
|
|
@ -19,26 +19,26 @@ dependencies:
|
|||
expandable_text: ^2.3.0
|
||||
flex_color_scheme: ^7.3.1
|
||||
extended_image: ^8.2.0
|
||||
photo_view: ^0.14.0
|
||||
photo_view: ^0.15.0
|
||||
draggable_scrollbar: ^0.1.0
|
||||
grouped_list: ^5.1.2
|
||||
intl: ^0.19.0
|
||||
google_fonts: ^6.1.0
|
||||
url_launcher: ^6.2.4
|
||||
package_info_plus: ^5.0.1
|
||||
package_info_plus: ^8.0.0
|
||||
permission_handler: ^11.2.0
|
||||
flutter_inappwebview: ^5.8.0
|
||||
draggable_menu: ^4.4.1
|
||||
isar: 3.1.0+1
|
||||
isar_flutter_libs: 3.1.0+1
|
||||
share_plus: ^7.2.2
|
||||
share_plus: ^9.0.0
|
||||
xpath_selector_html_parser: ^3.0.1
|
||||
desktop_webview_window:
|
||||
path: ./packages/desktop_webview_window
|
||||
archive: ^3.4.10
|
||||
file_picker: ^6.1.1
|
||||
file_picker: ^8.0.3
|
||||
path_provider: ^2.1.2
|
||||
scrollable_positioned_list: ^0.3.5
|
||||
scrollable_positioned_list: ^0.3.8
|
||||
dart_eval: ^0.7.9
|
||||
json_path: ^0.7.0
|
||||
bot_toast: ^4.1.3
|
||||
|
|
@ -56,8 +56,8 @@ dependencies:
|
|||
protobuf: ^3.1.0
|
||||
cupertino_icons: ^1.0.6
|
||||
window_manager: ^0.3.8
|
||||
ffi: ^2.1.0
|
||||
ffigen: ^11.0.0
|
||||
ffi: ^2.1.1
|
||||
ffigen: ^12.0.0
|
||||
http_interceptor: ^2.0.0-beta.8
|
||||
js_packer: ^0.0.5
|
||||
flutter_windows_webview:
|
||||
|
|
@ -70,19 +70,19 @@ dependencies:
|
|||
ref: main
|
||||
cronet_http: ^1.2.0
|
||||
cupertino_http: ^1.3.0
|
||||
http: ^1.2.0
|
||||
http: ^1.2.1
|
||||
google_api_availability: ^5.0.0
|
||||
flutter_code_editor: ^0.3.1
|
||||
flutter_highlight: ^0.7.0
|
||||
highlight: ^0.7.0
|
||||
json_view: ^0.4.2
|
||||
rinf: ^6.7.0
|
||||
rinf: ^6.9.2
|
||||
|
||||
dependency_overrides:
|
||||
analyzer: ">=5.2.0 <7.0.0"
|
||||
http: ^1.2.0
|
||||
ffi: ^2.1.0
|
||||
flex_seed_scheme: ^2.0.0-dev.1
|
||||
http: ^1.2.1
|
||||
ffi: ^2.1.2
|
||||
flex_seed_scheme: ^2.0.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
@ -91,7 +91,7 @@ dev_dependencies:
|
|||
riverpod_generator: ^2.3.2
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
isar_generator: ^3.1.0+1
|
||||
flutter_lints: ^3.0.1
|
||||
flutter_lints: ^4.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
|
|
|||
Loading…
Reference in a new issue