feature: fix reader & add preloaded chapter

This commit is contained in:
kodjomoustapha 2023-06-17 02:43:55 +01:00
parent 4fddc658a9
commit 4f68505a9b
13 changed files with 666 additions and 1848 deletions

View file

@ -1,207 +0,0 @@
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:mangayomi/modules/archive_reader/models/models.dart';
import 'package:mangayomi/modules/archive_reader/providers/archive_reader_providers.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:mangayomi/utils/media_query.dart';
class LocalReaderScreen extends ConsumerStatefulWidget {
const LocalReaderScreen({super.key});
@override
ConsumerState createState() => _LocalReaderScreenState();
}
class _LocalReaderScreenState extends ConsumerState<LocalReaderScreen> {
List<LocalArchive> images = [];
bool isLoading = false;
@override
Widget build(BuildContext context) {
return Stack(
children: [
Scaffold(
appBar: AppBar(
title: const Text('Archive Reader'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton.icon(
onPressed: () async {
setState(() {
isLoading = true;
});
//File
FilePickerResult? result = await FilePicker.platform
.pickFiles(
type: FileType.custom,
allowedExtensions: [
'cbz',
'zip',
'cbt',
'tar'
]);
if (result != null) {
//File
final ddd = await ref.watch(
getArchiveDataFromFileProvider(
result.files.first.path!)
.future);
setState(() {
images.add(ddd);
isLoading = false;
});
} else {
setState(() {
isLoading = false;
});
}
},
label: const Text("Load cbz file"),
icon: const Icon(Icons.archive_rounded)),
ElevatedButton.icon(
onPressed: () async {
setState(() {
isLoading = true;
});
//Directory
String? result =
await FilePicker.platform.getDirectoryPath();
if (result != null) {
//Directory
final ddd = await ref.watch(
getArchiveDataFromDirectoryProvider(result)
.future);
setState(() {
images = ddd;
isLoading = false;
});
} else {
setState(() {
isLoading = false;
});
}
},
label: const Text("Load from directory"),
icon: const Icon(Icons.create_new_folder_rounded)),
],
),
Expanded(
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: 0.68, crossAxisCount: 3),
itemCount: images.length,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Material(
borderRadius: BorderRadius.circular(10),
clipBehavior: Clip.antiAliasWithSaveLayer,
child: InkWell(
onTap: () {
context.push("/archiveReaderReaderView",
extra: images[index]);
},
child: Ink.image(
height: 200,
fit: BoxFit.cover,
image: MemoryImage(images[index].coverImage!),
child: Container(
height: 70,
decoration: BoxDecoration(
color:
Theme.of(context).scaffoldBackgroundColor,
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black.withOpacity(0.6)
],
stops: const [0, 1],
),
),
child: Stack(
children: [
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
images[index].name!,
style: const TextStyle(
fontSize: 12,
color: Colors.white,
shadows: <Shadow>[
Shadow(
offset: Offset(0.5, 0.9),
blurRadius: 3.0)
],
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.start,
),
),
),
Padding(
padding: const EdgeInsets.all(5),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(5)),
child: Padding(
padding: const EdgeInsets.all(2),
child: Text(
getTypeExtension(images[index]
.extensionType!)
.toUpperCase(),
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10),
),
)),
)
],
),
),
),
),
),
);
},
),
),
],
),
),
if (isLoading)
Container(
width: mediaWidth(context, 1),
height: mediaHeight(context, 1),
color: Colors.black45,
child: UnconstrainedBox(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Theme.of(context).scaffoldBackgroundColor,
),
height: 200,
width: 200,
child: const Center(child: ProgressCenter())),
),
)
],
);
}
}

View file

@ -1,938 +0,0 @@
import 'dart:async';
import 'dart:math';
import 'package:draggable_menu/draggable_menu.dart';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/modules/archive_reader/models/models.dart';
import 'package:mangayomi/utils/image_detail_info.dart';
import 'package:mangayomi/utils/media_query.dart';
import 'package:mangayomi/modules/manga/reader/widgets/circular_progress_indicator_animate_rotate.dart';
import 'package:mangayomi/modules/more/settings/reader/reader_screen.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
typedef DoubleClickAnimationListener = void Function();
class ArchiveReaderReaderView extends ConsumerWidget {
final LocalArchive localArchive;
const ArchiveReaderReaderView({
super.key,
required this.localArchive,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky,
overlays: []);
return MangaChapterPageGallery(localArchive: localArchive);
}
}
class MangaChapterPageGallery extends ConsumerStatefulWidget {
const MangaChapterPageGallery({super.key, required this.localArchive});
final LocalArchive localArchive;
@override
ConsumerState createState() {
return _MangaChapterPageGalleryState();
}
}
class _MangaChapterPageGalleryState
extends ConsumerState<MangaChapterPageGallery>
with TickerProviderStateMixin {
late final ItemScrollController _itemScrollController =
ItemScrollController();
late AnimationController _scaleAnimationController;
late Animation<double> _animation;
late int _currentIndex = 0;
@override
void dispose() {
_rebuildDetail.close();
_doubleClickAnimationController.dispose();
clearGestureDetailsCache();
super.dispose();
}
bool animatePageTransitions =
isar.settings.getSync(227)!.animatePageTransitions!;
Duration? _doubleTapAnimationDuration() {
int doubleTapAnimationValue =
isar.settings.getSync(227)!.doubleTapAnimationSpeed!;
if (doubleTapAnimationValue == 0) {
return const Duration(milliseconds: 10);
} else if (doubleTapAnimationValue == 1) {
return const Duration(milliseconds: 800);
}
return const Duration(milliseconds: 200);
}
Future setIndex(int index) async {
setState(() {
_currentIndex = index;
});
}
@override
void initState() {
_doubleClickAnimationController = AnimationController(
duration: _doubleTapAnimationDuration(), vsync: this);
_scaleAnimationController = AnimationController(
duration: _doubleTapAnimationDuration(), vsync: this);
_animation = Tween(begin: 1.0, end: 2.0).animate(
CurvedAnimation(curve: Curves.ease, parent: _scaleAnimationController));
_animation.addListener(() => _photoViewController.scale = _animation.value);
_initCurrentIndex();
_itemPositionsListener.itemPositions.addListener(_readProgressListener);
super.initState();
}
_readProgressListener() {
var posIndex = _itemPositionsListener.itemPositions.value.first.index;
if (posIndex >= 0 && posIndex < widget.localArchive.images!.length) {
if (_currentIndex != posIndex) {
setState(() {
_currentIndex = posIndex;
});
}
}
}
_initCurrentIndex() async {
await Future.delayed(const Duration(milliseconds: 1));
_selectedValue = ReaderMode.vertical;
_(_selectedValue!, true);
}
void _onPageChanged(int index) {
setState(() {
_currentIndex = index;
});
if (_imageDetailY != 0) {
_imageDetailY = 0;
_rebuildDetail.sink.add(_imageDetailY);
}
}
void _onBtnTapped(int index, bool isPrev, {bool isSlide = false}) {
if (isPrev) {
if (_selectedValue == ReaderMode.verticalContinuous ||
_selectedValue == ReaderMode.webtoon) {
if (index != -1) {
if (isSlide) {
_itemScrollController.jumpTo(
index: index,
);
} else {
animatePageTransitions
? _itemScrollController.scrollTo(
curve: Curves.ease,
index: index,
duration: Duration(milliseconds: isSlide ? 2 : 150))
: _itemScrollController.jumpTo(
index: index,
);
}
}
} else {
if (index != -1) {
if (_extendedController.hasClients) {
setState(() {
_isZoom = false;
});
animatePageTransitions
? _extendedController.animateToPage(index,
duration: Duration(milliseconds: isSlide ? 2 : 150),
curve: Curves.ease)
: _extendedController.jumpToPage(index);
}
}
}
} else {
if (_selectedValue == ReaderMode.verticalContinuous ||
_selectedValue == ReaderMode.webtoon) {
if (widget.localArchive.images!.length != index) {
if (isSlide) {
_itemScrollController.jumpTo(
index: index,
);
} else {
animatePageTransitions
? _itemScrollController.scrollTo(
curve: Curves.ease,
index: index,
duration: Duration(milliseconds: isSlide ? 2 : 150))
: _itemScrollController.jumpTo(
index: index,
);
}
}
} else {
if (widget.localArchive.images!.length != index) {
if (_extendedController.hasClients) {
setState(() {
_isZoom = false;
});
animatePageTransitions
? _extendedController.animateToPage(index,
duration: Duration(milliseconds: isSlide ? 2 : 150),
curve: Curves.ease)
: _extendedController.jumpToPage(index);
}
}
}
}
}
ReaderMode? _selectedValue;
bool _isView = false;
Alignment _scalePosition = Alignment.center;
final PhotoViewController _photoViewController = PhotoViewController();
final PhotoViewScaleStateController _photoViewScaleStateController =
PhotoViewScaleStateController();
final ItemPositionsListener _itemPositionsListener =
ItemPositionsListener.create();
void _onScaleEnd(BuildContext context, ScaleEndDetails details,
PhotoViewControllerValue controllerValue) {
if (controllerValue.scale! < 1) {
_photoViewScaleStateController.reset();
}
}
late final _extendedController = ExtendedPageController(
initialPage: _currentIndex,
shouldIgnorePointerWhenScrolling: false,
);
double get pixelRatio => View.of(context).devicePixelRatio;
Size get size => View.of(context).physicalSize / pixelRatio;
Alignment _computeAlignmentByTapOffset(Offset offset) {
return Alignment((offset.dx - size.width / 2) / (size.width / 2),
(offset.dy - size.height / 2) / (size.height / 2));
}
void _toggleScale(Offset tapPosition) {
setState(() {
if (_scaleAnimationController.isAnimating) {
return;
}
if (_photoViewController.scale == 1.0) {
_scalePosition = _computeAlignmentByTapOffset(tapPosition);
if (_scaleAnimationController.isCompleted) {
_scaleAnimationController.reset();
}
_scaleAnimationController.forward();
return;
}
if (_photoViewController.scale == 2.0) {
_scaleAnimationController.reverse();
return;
}
_photoViewScaleStateController.reset();
});
}
Axis _scrollDirection = Axis.vertical;
bool _isReversHorizontal = false;
late bool _showPagesNumber = true;
_(ReaderMode value, bool isInit) async {
if (value == ReaderMode.vertical) {
if (mounted) {
setState(() {
_selectedValue = value;
_scrollDirection = Axis.vertical;
_isReversHorizontal = false;
});
if (isInit) {
await Future.delayed(const Duration(milliseconds: 30));
}
_extendedController.jumpToPage(_currentIndex);
}
} else if (value == ReaderMode.ltr || value == ReaderMode.rtl) {
if (mounted) {
setState(() {
if (value == ReaderMode.rtl) {
_isReversHorizontal = true;
} else {
_isReversHorizontal = false;
}
_selectedValue = value;
_scrollDirection = Axis.horizontal;
});
if (isInit) {
await Future.delayed(const Duration(milliseconds: 30));
}
_extendedController.jumpToPage(_currentIndex);
}
} else {
if (mounted) {
setState(() {
_selectedValue = value;
_isReversHorizontal = false;
});
if (isInit) {
await Future.delayed(const Duration(milliseconds: 30));
}
_itemScrollController.scrollTo(
index: _currentIndex, duration: const Duration(milliseconds: 1));
}
}
}
Color _backgroundColor(BuildContext context) =>
Theme.of(context).scaffoldBackgroundColor.withOpacity(0.9);
Widget _showMore() {
return Consumer(
builder: (context, ref, child) {
final currentIndex = _currentIndex;
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AnimatedContainer(
height: _isView ? 80 : 0,
curve: Curves.ease,
duration: const Duration(milliseconds: 200),
child: PreferredSize(
preferredSize: Size.fromHeight(_isView ? 80 : 0),
child: AppBar(
centerTitle: false,
automaticallyImplyLeading: false,
titleSpacing: 0,
leading: BackButton(
onPressed: () {
Navigator.pop(context);
},
),
title: ListTile(
dense: true,
title: SizedBox(
width: mediaWidth(context, 0.8),
child: Text(
'${widget.localArchive.name} ',
style: const TextStyle(fontWeight: FontWeight.bold),
overflow: TextOverflow.ellipsis,
),
),
subtitle: SizedBox(
width: mediaWidth(context, 0.8),
child: const Text(
"",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
),
overflow: TextOverflow.ellipsis,
),
),
),
backgroundColor: _backgroundColor(context),
),
),
),
AnimatedContainer(
curve: Curves.ease,
duration: const Duration(milliseconds: 300),
width: mediaWidth(context, 1),
height: _isView ? 130 : 0,
child: Column(
children: [
Flexible(
child: Row(
children: [
Expanded(
child: Transform.scale(
scaleX: !_isReversHorizontal ? 1 : -1,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Container(
height: 70,
decoration: BoxDecoration(
color: _backgroundColor(context),
borderRadius: BorderRadius.circular(25)),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 12),
child: Transform.scale(
scaleX: !_isReversHorizontal ? 1 : -1,
child: SizedBox(
width: 25,
child: Text(
"${currentIndex + 1} ",
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
Flexible(
child: Slider(
onChanged: (newValue) {
_onBtnTapped(newValue.toInt(), true,
isSlide: true);
},
divisions: max(
widget.localArchive.images!.length -
1,
1),
value: min(
_currentIndex.toDouble(),
widget.localArchive.images!.length
.toDouble()),
min: 0,
max: (widget.localArchive.images!
.length -
1)
.toDouble(),
),
),
Padding(
padding: const EdgeInsets.only(right: 12),
child: Transform.scale(
scaleX: !_isReversHorizontal ? 1 : -1,
child: SizedBox(
width: 25,
child: Text(
"${widget.localArchive.images!.length}",
style: const TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
),
),
),
],
),
),
Flexible(
child: Container(
height: 65,
color: _backgroundColor(context),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
PopupMenuButton(
color: Colors.black,
child: const Icon(
Icons.app_settings_alt_outlined,
),
onSelected: (value) {
if (mounted) {
setState(() {
_selectedValue = value;
});
}
_(value, true);
},
itemBuilder: (context) => [
for (var readerMode in ReaderMode.values)
PopupMenuItem(
value: readerMode,
child: Row(
children: [
Icon(
Icons.check,
color: _selectedValue == readerMode
? Colors.white
: Colors.transparent,
),
const SizedBox(
width: 7,
),
Text(
getReaderModeName(readerMode),
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
),
],
)),
],
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.screen_rotation,
),
),
IconButton(
onPressed: () {
_showModalSettings();
},
icon: const Icon(
Icons.settings_rounded,
),
),
],
),
),
),
],
),
),
],
);
},
);
}
Widget _showPage() {
return Consumer(
builder: (context, ref, child) {
final currentIndex = _currentIndex;
return _isView
? Container()
: _showPagesNumber
? Align(
alignment: Alignment.bottomCenter,
child: Text(
'${currentIndex + 1} / ${widget.localArchive.images!.length}',
style: const TextStyle(
color: Colors.white,
fontSize: 12.0,
shadows: <Shadow>[
Shadow(offset: Offset(0.0, 0.0), blurRadius: 10.0)
],
),
textAlign: TextAlign.center,
),
)
: Container();
},
);
}
_isViewFunction() {
if (mounted) {
setState(() {
_isView = !_isView;
});
}
if (_isView) {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values);
} else {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky,
overlays: []);
}
}
Widget _gestureRightLeft() {
return Consumer(
builder: (context, ref, child) {
return Row(
children: [
/// left region
Expanded(
flex: 2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
if (_isReversHorizontal) {
_onBtnTapped(_currentIndex + 1, false);
} else {
_onBtnTapped(_currentIndex - 1, true);
}
},
onDoubleTapDown: _isVerticalContinous()
? (TapDownDetails details) {
_toggleScale(details.globalPosition);
}
: null,
onDoubleTap: _isVerticalContinous() ? () {} : null,
),
),
/// center region
Expanded(
flex: 2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
_isViewFunction();
},
onDoubleTapDown: _isVerticalContinous()
? (TapDownDetails details) {
_toggleScale(details.globalPosition);
}
: null,
onDoubleTap: _isVerticalContinous() ? () {} : null,
),
),
/// right region
Expanded(
flex: 2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
if (_isReversHorizontal) {
_onBtnTapped(_currentIndex - 1, true);
} else {
_onBtnTapped(_currentIndex + 1, false);
}
},
onDoubleTapDown: _isVerticalContinous()
? (TapDownDetails details) {
_toggleScale(details.globalPosition);
}
: null,
onDoubleTap: _isVerticalContinous() ? () {} : null,
),
),
],
);
},
);
}
Widget _gestureTopBottom() {
return Consumer(
builder: (context, ref, child) {
return Column(
children: [
/// top region
Expanded(
flex: 2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
_onBtnTapped(_currentIndex - 1, true);
},
onDoubleTapDown: _isVerticalContinous()
? (TapDownDetails details) {
_toggleScale(details.globalPosition);
}
: null,
onDoubleTap: _isVerticalContinous() ? () {} : null,
),
),
/// center region
Expanded(flex: 5, child: Container()),
/// bottom region
Expanded(
flex: 2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
_onBtnTapped(_currentIndex + 1, false);
},
onDoubleTapDown: _isVerticalContinous()
? (TapDownDetails details) {
_toggleScale(details.globalPosition);
}
: null,
onDoubleTap: _isVerticalContinous() ? () {} : null,
),
),
],
);
},
);
}
bool _isZoom = false;
bool _isVerticalContinous() {
return _selectedValue == ReaderMode.verticalContinuous ||
_selectedValue == ReaderMode.webtoon;
}
final StreamController<double> _rebuildDetail =
StreamController<double>.broadcast();
final Map<int, ImageDetailInfo> detailKeys = <int, ImageDetailInfo>{};
late AnimationController _doubleClickAnimationController;
Animation<double>? _doubleClickAnimation;
late DoubleClickAnimationListener _doubleClickAnimationListener;
List<double> doubleTapScales = <double>[1.0, 2.0];
GlobalKey<ExtendedImageSlidePageState> slidePagekey =
GlobalKey<ExtendedImageSlidePageState>();
double _imageDetailY = 0;
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values);
Navigator.pop(context);
return false;
},
child: Stack(
children: [
_isVerticalContinous()
? PhotoViewGallery.builder(
itemCount: 1,
builder: (_, __) => PhotoViewGalleryPageOptions.customChild(
controller: _photoViewController,
scaleStateController: _photoViewScaleStateController,
basePosition: _scalePosition,
onScaleEnd: _onScaleEnd,
child: ScrollablePositionedList.separated(
physics: const ClampingScrollPhysics(),
minCacheExtent: 8 * (MediaQuery.of(context).size.height),
initialScrollIndex: _currentIndex,
itemCount: widget.localArchive.images!.length,
itemScrollController: _itemScrollController,
itemPositionsListener: _itemPositionsListener,
itemBuilder: (context, index) => GestureDetector(
behavior: HitTestBehavior.translucent,
onDoubleTapDown: (TapDownDetails details) {
_toggleScale(details.globalPosition);
},
onDoubleTap: () {},
child: Image.memory(
widget.localArchive.images![index].image!)),
separatorBuilder: (_, __) => Divider(
color: Colors.black,
height: _selectedValue == ReaderMode.webtoon ? 0 : 6),
),
),
)
: Material(
color: Colors.black,
shadowColor: Colors.black,
child: ExtendedImageGesturePageView.builder(
controller: _extendedController,
scrollDirection: _scrollDirection,
reverse: _isReversHorizontal,
physics: const ClampingScrollPhysics(),
preloadPagesCount:
_isZoom ? 0 : widget.localArchive.images!.length,
canScrollPage: (GestureDetails? gestureDetails) {
return gestureDetails != null
? !(gestureDetails.totalScale! > 1.0)
: true;
},
itemBuilder: (BuildContext context, int index) {
return ExtendedImage.memory(
widget.localArchive.images![index].image!,
clearMemoryCacheWhenDispose: true,
enableMemoryCache: false,
mode: ExtendedImageMode.gesture,
loadStateChanged: (ExtendedImageState 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: Colors.black,
height: mediaHeight(context, 0.8),
child: CircularProgressIndicatorAnimateRotate(
progress: progress),
);
}
if (state.extendedImageLoadState ==
LoadState.completed) {
return StreamBuilder<double>(
builder: (BuildContext context,
AsyncSnapshot<double> data) {
return ExtendedImageGesture(
state,
canScaleImage: (_) => _imageDetailY == 0,
imageBuilder: (Widget image) {
return Stack(
children: <Widget>[
Positioned.fill(
top: _imageDetailY,
bottom: -_imageDetailY,
child: image,
),
],
);
},
);
},
initialData: _imageDetailY,
stream: _rebuildDetail.stream,
);
}
if (state.extendedImageLoadState ==
LoadState.failed) {
return Container(
color: Colors.black,
height: mediaHeight(context, 0.8),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
state.reLoadImage();
},
child: const Icon(
Icons.replay_outlined,
size: 30,
)),
],
));
}
return Container();
},
initGestureConfigHandler: (ExtendedImageState state) {
double? initialScale = 1.0;
final size = MediaQuery.of(context).size;
if (state.extendedImageInfo != null) {
initialScale = initScale(
size: size,
initialScale: initialScale,
imageSize: Size(
state.extendedImageInfo!.image.width
.toDouble(),
state.extendedImageInfo!.image.height
.toDouble()));
}
return GestureConfig(
inertialSpeed: 200,
inPageView: true,
initialScale: initialScale!,
maxScale: 8,
animationMaxScale: 8,
initialAlignment: InitialAlignment.center,
cacheGesture: true,
hitTestBehavior: HitTestBehavior.translucent,
);
},
onDoubleTap: (ExtendedImageGestureState state) {
final Offset? pointerDownPosition =
state.pointerDownPosition;
final double? begin =
state.gestureDetails!.totalScale;
double end;
//remove old
_doubleClickAnimation
?.removeListener(_doubleClickAnimationListener);
//stop pre
_doubleClickAnimationController.stop();
//reset to use
_doubleClickAnimationController.reset();
if (begin == doubleTapScales[0]) {
setState(() {
_isZoom = true;
});
end = doubleTapScales[1];
} else {
setState(() {
_isZoom = false;
});
end = doubleTapScales[0];
}
_doubleClickAnimationListener = () {
state.handleDoubleTap(
scale: _doubleClickAnimation!.value,
doubleTapPosition: pointerDownPosition);
};
_doubleClickAnimation = Tween(
begin: begin, end: end)
.animate(CurvedAnimation(
curve: Curves.ease,
parent: _doubleClickAnimationController));
_doubleClickAnimation!
.addListener(_doubleClickAnimationListener);
_doubleClickAnimationController.forward();
},
);
},
itemCount: widget.localArchive.images!.length,
onPageChanged: _onPageChanged)),
_gestureRightLeft(),
_gestureTopBottom(),
_showMore(),
_showPage(),
],
),
);
}
_showModalSettings() {
DraggableMenu.open(
context,
DraggableMenu(
ui: ClassicDraggableMenu(barItem: Container()),
expandable: false,
maxHeight: mediaHeight(context, 0.4),
fastDrag: false,
minimizeBeforeFastDrag: false,
child: StatefulBuilder(
builder: (context, setState) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 10,
),
const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Settings',
style: TextStyle(
fontSize: 17, fontWeight: FontWeight.bold),
),
),
const Divider(),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
SwitchListTile(
dense: true,
title: const Text('Show Page Number'),
value: _showPagesNumber,
onChanged: (value) {
setState(() {
_showPagesNumber = value;
});
},
),
],
),
)
],
),
);
},
)));
}
}

View file

@ -24,7 +24,7 @@ class _MainScreenState extends State<MainScreen> {
final route = GoRouter.of(context);
int currentIndex = route.location == '/library'
? 0
: route.location == '/archiveReader'
: route.location == '/updates'
? 1
: route.location == '/history'
? 2
@ -79,7 +79,7 @@ class _MainScreenState extends State<MainScreen> {
width: isLongPressed
? 0
: route.location != '/library' &&
route.location != '/archiveReader' &&
route.location != '/updates' &&
route.location != '/history' &&
route.location != '/browse' &&
route.location != '/more'
@ -113,7 +113,7 @@ class _MainScreenState extends State<MainScreen> {
),
label: Padding(
padding: EdgeInsets.only(top: 5),
child: Text('A-Reader'))),
child: Text('Updates'))),
NavigationRailDestination(
selectedIcon: Icon(
Icons.history,
@ -158,7 +158,7 @@ class _MainScreenState extends State<MainScreen> {
if (newIndex == 0) {
route.go('/library');
} else if (newIndex == 1) {
route.go('/archiveReader');
route.go('/updates');
} else if (newIndex == 2) {
route.go('/history');
} else if (newIndex == 3) {
@ -186,7 +186,7 @@ class _MainScreenState extends State<MainScreen> {
height: isLongPressed
? 0
: route.location != '/library' &&
route.location != '/archiveReader' &&
route.location != '/updates' &&
route.location != '/history' &&
route.location != '/browse' &&
route.location != '/more'
@ -212,12 +212,12 @@ class _MainScreenState extends State<MainScreen> {
label: 'Library'),
NavigationDestination(
selectedIcon: Icon(
Icons.library_books,
Icons.new_releases,
),
icon: Icon(
Icons.library_books_outlined,
Icons.new_releases_outlined,
),
label: 'A-Reader'),
label: 'Updates'),
NavigationDestination(
selectedIcon: Icon(
Icons.history,
@ -252,7 +252,7 @@ class _MainScreenState extends State<MainScreen> {
if (newIndex == 0) {
route.go('/library');
} else if (newIndex == 1) {
route.go('/archiveReader');
route.go('/updates');
} else if (newIndex == 2) {
route.go('/history');
} else if (newIndex == 3) {

View file

@ -0,0 +1,150 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:mangayomi/modules/manga/reader/manga_reader_view.dart';
import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provider.dart';
import 'package:mangayomi/utils/media_query.dart';
class ChapterIntervalPageView extends ConsumerWidget {
final bool hasPrevChapter;
final bool hasNextChapter;
final UChapDataPreload uChapDataPreload;
final VoidCallback onTap;
const ChapterIntervalPageView(
{super.key,
required this.uChapDataPreload,
required this.hasPrevChapter,
required this.hasNextChapter,
required this.onTap});
@override
Widget build(BuildContext context, WidgetRef ref) {
final readerController =
ReaderController(chapter: uChapDataPreload.chapter!);
String text = uChapDataPreload.isPrevPrePage && hasPrevChapter
? "Current:"
: "Finished:";
final noMoreChapter = uChapDataPreload.isNextPrePage && !hasNextChapter ||
uChapDataPreload.isPrevPrePage && !hasPrevChapter;
String noMore =
uChapDataPreload.isNextPrePage && !hasNextChapter ? "Next" : "Previous";
return SizedBox(
height: mediaHeight(context, 0.27),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (uChapDataPreload.isPrevPrePage && hasPrevChapter)
Column(
children: [
const Text(
"Previous:",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 12),
),
Text(readerController.getPrevChapter().name!,
style: const TextStyle(color: Colors.white, fontSize: 12),
textAlign: TextAlign.center),
const SizedBox(
height: 10,
),
Column(
children: [
Text(
text,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 12),
),
Wrap(
children: [
Text(
uChapDataPreload.chapter!.name!,
style: const TextStyle(
color: Colors.white, fontSize: 12),
textAlign: TextAlign.center,
),
const SizedBox(
width: 3,
),
const Icon(
FontAwesomeIcons.circleCheck,
color: Colors.white,
size: 17,
),
],
),
// ElevatedButton(onPressed: onTap, child: const Text("Retry")),
],
),
],
),
if (noMoreChapter)
Text(
"There is no $noMore chapter",
style: const TextStyle(color: Colors.white, fontSize: 14),
textAlign: TextAlign.center,
),
if (uChapDataPreload.isNextPrePage && hasNextChapter)
Column(
children: [
Column(
children: [
Text(
text,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
fontSize: 12),
),
Wrap(
alignment: WrapAlignment.center,
children: [
Text(
uChapDataPreload.chapter!.name!,
style: const TextStyle(
color: Colors.white, fontSize: 12),
textAlign: TextAlign.center,
),
const SizedBox(
width: 3,
),
const Icon(
FontAwesomeIcons.circleCheck,
color: Colors.white,
size: 16,
),
],
),
const SizedBox(
height: 10,
),
const Text(
"Next:",
style: TextStyle(
fontWeight: FontWeight.bold, color: Colors.white),
),
Text(
readerController.getNextChapter().name!,
style: const TextStyle(color: Colors.white, fontSize: 12),
textAlign: TextAlign.center,
),
const SizedBox(
height: 30,
),
// ElevatedButton(
// onPressed: onTap,
// child: const Text("Load Next chapter")),
],
),
],
),
],
),
);
}
}

View file

@ -3,7 +3,6 @@ import 'dart:typed_data';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:mangayomi/utils/headers.dart';
import 'package:mangayomi/utils/media_query.dart';
import 'package:mangayomi/utils/reg_exp_matcher.dart';
@ -46,17 +45,31 @@ class ImageViewVertical extends ConsumerWidget {
),
isLocale
? archiveImage != null
? ExtendedImage.memory(
archiveImage!,
? ExtendedImage.memory(archiveImage!,
fit: BoxFit.contain,
clearMemoryCacheWhenDispose: true,
enableMemoryCache: false,
)
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
return Container(
color: Colors.black,
height: mediaHeight(context, 0.8),
);
}
return null;
})
: ExtendedImage.file(
fit: BoxFit.contain,
clearMemoryCacheWhenDispose: true,
enableMemoryCache: false,
File('${path.path}${padIndex(index + 1)}.jpg'))
File('${path.path}${padIndex(index + 1)}.jpg'),
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
return Container(
color: Colors.black,
height: mediaHeight(context, 0.8),
);
}
return null;
})
: ExtendedImage.network(url,
headers: ref.watch(headersProvider(source: source)),
handleLoadingProgress: true,
@ -99,32 +112,6 @@ class ImageViewVertical extends ConsumerWidget {
}
return null;
}),
if (index + 1 == length)
SizedBox(
height: mediaHeight(context, 0.3),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$chapter finished',
style: const TextStyle(
fontSize: 17.0,
fontWeight: FontWeight.bold,
color: Colors.white),
),
const SizedBox(
height: 10,
),
const Icon(
FontAwesomeIcons.circleCheck,
color: Colors.white,
),
const SizedBox(
height: 20,
),
],
),
)
],
),
);

File diff suppressed because it is too large Load diff

View file

@ -14,9 +14,7 @@ class CurrentIndex extends _$CurrentIndex {
int build(Chapter chapter) {
final incognitoMode = ref.watch(incognitoModeStateProvider);
if (!incognitoMode) {
return ref
.read(readerControllerProvider(chapter: chapter).notifier)
.getPageIndex();
return ReaderController(chapter: chapter).getPageIndex();
}
return 0;
}
@ -28,235 +26,9 @@ class CurrentIndex extends _$CurrentIndex {
}
}
@riverpod
class ReaderController extends _$ReaderController {
@override
void build({required Chapter chapter}) {}
Manga getManga() {
return chapter.manga.value!;
}
Chapter geChapter() {
return chapter;
}
ReaderMode getReaderMode() {
final personalReaderModeList =
getIsarSetting().personalReaderModeList ?? [];
final personalReaderMode = personalReaderModeList
.where((element) => element.mangaId == getManga().id);
if (personalReaderMode.isNotEmpty) {
return personalReaderMode.first.readerMode;
}
return isar.settings.getSync(227)!.defaultReaderMode;
}
void setReaderMode(ReaderMode newReaderMode) {
List<PersonalReaderMode>? personalReaderModeLists = [];
for (var personalReaderMode
in getIsarSetting().personalReaderModeList ?? []) {
if (personalReaderMode.mangaId != getManga().id) {
personalReaderModeLists.add(personalReaderMode);
}
}
personalReaderModeLists.add(PersonalReaderMode()
..mangaId = getManga().id
..readerMode = newReaderMode);
isar.writeTxnSync(() => isar.settings.putSync(
getIsarSetting()..personalReaderModeList = personalReaderModeLists));
}
void setShowPageNumber(bool value) {
final incognitoMode = ref.watch(incognitoModeStateProvider);
if (!incognitoMode) {
isar.writeTxnSync(() =>
isar.settings.putSync(getIsarSetting()..showPagesNumber = value));
}
}
Settings getIsarSetting() {
return isar.settings.getSync(227)!;
}
bool getShowPageNumber() {
final incognitoMode = ref.watch(incognitoModeStateProvider);
if (!incognitoMode) {
return getIsarSetting().showPagesNumber!;
}
return true;
}
void setMangaHistoryUpdate() {
// log("message");
final incognitoMode = ref.watch(incognitoModeStateProvider);
if (!incognitoMode) {
isar.writeTxnSync(() {
Manga? manga = chapter.manga.value;
manga!.lastRead = DateTime.now().millisecondsSinceEpoch;
isar.mangas.putSync(manga);
});
History? history;
final empty =
isar.historys.filter().mangaIdEqualTo(getManga().id).isEmptySync();
if (empty) {
history = History(
mangaId: getManga().id,
date: DateTime.now().millisecondsSinceEpoch.toString())
..chapter.value = chapter;
} else {
history = (isar.historys
.filter()
.mangaIdEqualTo(getManga().id)
.findFirstSync())!
..chapter.value = chapter
..date = DateTime.now().millisecondsSinceEpoch.toString();
}
isar.writeTxnSync(() {
isar.historys.putSync(history!);
history.chapter.saveSync();
});
}
}
void setChapterPageLastRead(int pageIndex) {
final incognitoMode = ref.watch(incognitoModeStateProvider);
if (!incognitoMode) {
final chap = chapter;
isar.writeTxnSync(() {
chap.isRead = (pageIndex + 1) == getPageLength([]);
chap.lastPageRead = (pageIndex + 1).toString();
isar.chapters.putSync(chap);
});
}
}
void setChapterBookmarked() {
final incognitoMode = ref.watch(incognitoModeStateProvider);
if (!incognitoMode) {
final isBookmarked = getChapterBookmarked();
final chap = chapter;
isar.writeTxnSync(() {
chap.isBookmarked = !isBookmarked;
isar.chapters.putSync(chap);
});
}
}
bool getChapterBookmarked() {
return isar.chapters.getSync(chapter.id!)!.isBookmarked!;
}
int getNextChapterIndex() {
final chapters = getManga().chapters.toList();
int? index;
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i + 1;
}
}
return index!;
}
int getPrevChapterIndex() {
final chapters = getManga().chapters.toList();
int? index;
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i - 1;
}
}
return index!;
}
int getChapterIndex() {
final chapters = getManga().chapters.toList();
int? index;
for (var i = 0; i < chapters.length; i++) {
if (chapters[i].id == chapter.id) {
index = i;
}
}
return index!;
}
Chapter getNextChapter() {
return getManga().chapters.toList()[getNextChapterIndex()];
}
Chapter getPrevChapter() {
return getManga().chapters.toList()[getPrevChapterIndex()];
}
int getChaptersLength() {
return getManga().chapters.length;
}
int getPageIndex() {
final incognitoMode = ref.watch(incognitoModeStateProvider);
final chapterPageIndexList = getIsarSetting().chapterPageIndexList ?? [];
final index = chapterPageIndexList
.where((element) => element.chapterId == chapter.id);
if (!incognitoMode) {
return chapter.isRead!
? 0
: index.isNotEmpty
? index.first.index!
: 0;
}
return 0;
}
int getPageLength(List incognitoPageLength) {
final incognitoMode = ref.watch(incognitoModeStateProvider);
if (!incognitoMode) {
return getIsarSetting()
.chapterPageUrlsList!
.where((element) => element.chapterId == chapter.id)
.first
.urls!
.length;
}
return incognitoPageLength.length;
}
void setPageIndex(int newIndex) {
final incognitoMode = ref.watch(incognitoModeStateProvider);
if (!incognitoMode) {
List<ChapterPageIndex>? chapterPageIndexs = [];
for (var chapterPageIndex
in getIsarSetting().chapterPageIndexList ?? []) {
if (chapterPageIndex.chapterId != chapter.id) {
chapterPageIndexs.add(chapterPageIndex);
}
}
chapterPageIndexs.add(ChapterPageIndex()
..chapterId = chapter.id
..index = newIndex);
isar.writeTxnSync(() => isar.settings
.putSync(getIsarSetting()..chapterPageIndexList = chapterPageIndexs));
}
}
String getMangaName() {
return getManga().name!;
}
String getSourceName() {
return getManga().source!;
}
String getChapterTitle() {
return chapter.name!;
}
}
class ReaderControllerAA {
class ReaderController {
final Chapter chapter;
bool incognitoMode;
ReaderControllerAA({required this.chapter, required this.incognitoMode});
ReaderController({required this.chapter});
Manga getManga() {
return chapter.manga.value!;
@ -266,6 +38,7 @@ class ReaderControllerAA {
return chapter;
}
final incognitoMode = isar.settings.getSync(227)!.incognitoMode!;
ReaderMode getReaderMode() {
final personalReaderModeList =
getIsarSetting().personalReaderModeList ?? [];
@ -311,8 +84,6 @@ class ReaderControllerAA {
}
void setMangaHistoryUpdate() {
// log("message");
if (!incognitoMode) {
isar.writeTxnSync(() {
Manga? manga = chapter.manga.value;
@ -370,7 +141,7 @@ class ReaderControllerAA {
return isar.chapters.getSync(chapter.id!)!.isBookmarked!;
}
int getNextChapterIndex() {
int getPrevChapterIndex() {
final chapters = getManga().chapters.toList();
int? index;
for (var i = 0; i < chapters.length; i++) {
@ -381,7 +152,7 @@ class ReaderControllerAA {
return index!;
}
int getPrevChapterIndex() {
int getNextChapterIndex() {
final chapters = getManga().chapters.toList();
int? index;
for (var i = 0; i < chapters.length; i++) {
@ -403,14 +174,14 @@ class ReaderControllerAA {
return index!;
}
Chapter getNextChapter() {
return getManga().chapters.toList()[getNextChapterIndex()];
}
Chapter getPrevChapter() {
return getManga().chapters.toList()[getPrevChapterIndex()];
}
Chapter getNextChapter() {
return getManga().chapters.toList()[getNextChapterIndex()];
}
int getChaptersLength() {
return getManga().chapters.length;
}

View file

@ -122,100 +122,4 @@ class CurrentIndexProvider
);
}
}
String _$readerControllerHash() => r'65ce80e436f72efffea6ba9b1b6f87be702b79cd';
abstract class _$ReaderController extends BuildlessAutoDisposeNotifier<void> {
late final Chapter chapter;
void build({
required Chapter chapter,
});
}
/// See also [ReaderController].
@ProviderFor(ReaderController)
const readerControllerProvider = ReaderControllerFamily();
/// See also [ReaderController].
class ReaderControllerFamily extends Family<void> {
/// See also [ReaderController].
const ReaderControllerFamily();
/// See also [ReaderController].
ReaderControllerProvider call({
required Chapter chapter,
}) {
return ReaderControllerProvider(
chapter: chapter,
);
}
@override
ReaderControllerProvider getProviderOverride(
covariant ReaderControllerProvider provider,
) {
return call(
chapter: provider.chapter,
);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'readerControllerProvider';
}
/// See also [ReaderController].
class ReaderControllerProvider
extends AutoDisposeNotifierProviderImpl<ReaderController, void> {
/// See also [ReaderController].
ReaderControllerProvider({
required this.chapter,
}) : super.internal(
() => ReaderController()..chapter = chapter,
from: readerControllerProvider,
name: r'readerControllerProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$readerControllerHash,
dependencies: ReaderControllerFamily._dependencies,
allTransitiveDependencies:
ReaderControllerFamily._allTransitiveDependencies,
);
final Chapter chapter;
@override
bool operator ==(Object other) {
return other is ReaderControllerProvider && other.chapter == chapter;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, chapter.hashCode);
return _SystemHash.finish(hash);
}
@override
void runNotifierBuild(
covariant ReaderController notifier,
) {
return notifier.build(
chapter: chapter,
);
}
}
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions

View file

@ -3,10 +3,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/manga_type.dart';
import 'package:mangayomi/modules/archive_reader/archive_reader_screen.dart';
import 'package:mangayomi/modules/archive_reader/models/models.dart';
import 'package:mangayomi/modules/archive_reader/reader/archive_reader_reader_view.dart';
import 'package:mangayomi/modules/more/settings/downloads/downloads_screen.dart';
import 'package:mangayomi/modules/updates/updates_screen.dart';
import 'package:mangayomi/modules/webview/webview.dart';
import 'package:mangayomi/modules/browse/browse_screen.dart';
import 'package:mangayomi/modules/browse/extension/extension_lang.dart';
@ -53,15 +51,6 @@ class AsyncRouterNotifier extends ChangeNotifier {
child: const LibraryScreen(),
),
),
GoRoute(
name: "archiveReader",
path: '/archiveReader',
builder: (context, state) => const LocalReaderScreen(),
pageBuilder: (context, state) => CustomTransition(
key: state.pageKey,
child: const LocalReaderScreen(),
),
),
GoRoute(
name: "history",
path: '/history',
@ -80,6 +69,15 @@ class AsyncRouterNotifier extends ChangeNotifier {
child: const BrowseScreen(),
),
),
GoRoute(
name: "updates",
path: '/updates',
builder: (context, state) => const UpdatesScreen(),
pageBuilder: (context, state) => CustomTransition(
key: state.pageKey,
child: const UpdatesScreen(),
),
),
GoRoute(
name: "more",
path: '/more',
@ -335,25 +333,6 @@ class AsyncRouterNotifier extends ChangeNotifier {
);
},
),
GoRoute(
path: "/archiveReaderReaderView",
name: "archiveReaderReaderView",
builder: (context, state) {
final localArchive = state.extra as LocalArchive;
return ArchiveReaderReaderView(
localArchive: localArchive,
);
},
pageBuilder: (context, state) {
final localArchive = state.extra as LocalArchive;
return CustomTransition(
key: state.pageKey,
child: ArchiveReaderReaderView(
localArchive: localArchive,
),
);
},
),
];
}

View file

@ -7,6 +7,7 @@ import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/models/source.dart';
import 'package:mangayomi/modules/archive_reader/providers/archive_reader_providers.dart';
import 'package:mangayomi/modules/manga/reader/manga_reader_view.dart';
import 'package:mangayomi/providers/storage_provider.dart';
import 'package:mangayomi/sources/multisrc/heancms/heancms.dart';
import 'package:mangayomi/sources/multisrc/madara/src/madara.dart';
@ -28,11 +29,13 @@ class GetChapterUrlModel {
List<String> pageUrls = [];
List<bool> isLocaleList = [];
List<Uint8List> archiveImages = [];
List<UChapDataPreload> uChapDataPreload;
GetChapterUrlModel(
{required this.path,
required this.pageUrls,
required this.isLocaleList,
required this.archiveImages});
required this.archiveImages,
required this.uChapDataPreload});
}
@riverpod
@ -40,6 +43,7 @@ Future<GetChapterUrlModel> getChapterUrl(
GetChapterUrlRef ref, {
required Chapter chapter,
}) async {
List<UChapDataPreload> uChapDataPreloadp = [];
Directory? path;
List<String> pageUrls = [];
final manga = chapter.manga.value!;
@ -177,11 +181,29 @@ Future<GetChapterUrlModel> getChapterUrl(
isar.writeTxnSync(() => isar.settings
.putSync(settings..chapterPageUrlsList = chapterPageUrls));
}
for (var i = 0; i < pageUrls.length; i++) {
uChapDataPreloadp.add(UChapDataPreload(
chapter,
path,
pageUrls[i],
isLocaleList[i],
archiveImages[i],
i,
false,
false,
GetChapterUrlModel(
path: path,
pageUrls: pageUrls,
isLocaleList: isLocaleList,
archiveImages: archiveImages,
uChapDataPreload: uChapDataPreloadp)));
}
}
return GetChapterUrlModel(
path: path,
pageUrls: pageUrls,
isLocaleList: isLocaleList,
archiveImages: archiveImages);
archiveImages: archiveImages,
uChapDataPreload: uChapDataPreloadp);
}

View file

@ -6,7 +6,7 @@ part of 'get_chapter_url.dart';
// RiverpodGenerator
// **************************************************************************
String _$getChapterUrlHash() => r'd34b2bbc9062d7675347ff44d57943ff135b0135';
String _$getChapterUrlHash() => r'6e9e28c2d3775791f9c8544cf0f41bb07b5eaf81';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -957,6 +957,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.5"
scrollview_observer:
dependency: "direct main"
description:
name: scrollview_observer
sha256: "459ab67e3b1680e660d3bff24b64c9de4fc6f22a49bd3ecbbafece8e83f0b973"
url: "https://pub.dev"
source: hosted
version: "1.14.0"
share_plus:
dependency: "direct main"
description:

View file

@ -64,6 +64,7 @@ dependencies:
file_picker: ^5.3.0
path_provider: ^2.0.15
image: ^3.3.0
scrollview_observer: ^1.14.0
# The following adds the Cupertino Icons font to your application.