Fix next chapter preload, Flutter 3.13.0, update dependecies

This commit is contained in:
kodjomoustapha 2023-08-18 11:18:26 +01:00
parent 0ac46000ec
commit 582e7ad4a8
6 changed files with 433 additions and 485 deletions

View file

@ -8,12 +8,9 @@ import 'package:mangayomi/utils/reg_exp_matcher.dart';
class ImageViewCenter extends ConsumerWidget {
final String lang;
final int length;
final String url;
final int index;
final String titleManga;
final String source;
final String chapter;
final Directory path;
final bool isLocale;
final Uint8List? archiveImage;
@ -24,12 +21,9 @@ class ImageViewCenter extends ConsumerWidget {
const ImageViewCenter({
super.key,
required this.url,
required this.chapter,
required this.index,
required this.path,
required this.titleManga,
required this.source,
required this.length,
required this.loadStateChanged,
required this.onDoubleTap,
required this.initGestureConfigHandler,

View file

@ -9,13 +9,10 @@ import 'package:mangayomi/utils/reg_exp_matcher.dart';
import 'package:mangayomi/modules/manga/reader/widgets/circular_progress_indicator_animate_rotate.dart';
class ImageViewVertical extends ConsumerWidget {
final int length;
final bool isLocale;
final String url;
final int index;
final String titleManga;
final String source;
final String chapter;
final Directory path;
final String lang;
final Uint8List? archiveImage;
@ -23,12 +20,9 @@ class ImageViewVertical extends ConsumerWidget {
const ImageViewVertical({
super.key,
required this.url,
required this.chapter,
required this.index,
required this.path,
required this.titleManga,
required this.source,
required this.length,
required this.isLocale,
required this.lang,
this.archiveImage,
@ -48,12 +42,14 @@ class ImageViewVertical extends ConsumerWidget {
isLocale
? archiveImage != null
? ExtendedImage.memory(archiveImage!,
fit: BoxFit.contain, enableMemoryCache: false,
fit: BoxFit.contain,
enableMemoryCache: false,
enableLoadState: true,
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
return Container(
color: Colors.black,
height: mediaHeight(context, 0.8),
height: mediaHeight(context, 0.6),
);
}
return null;
@ -62,11 +58,12 @@ class ImageViewVertical extends ConsumerWidget {
fit: BoxFit.contain,
enableMemoryCache: false,
File('${path.path}${padIndex(index + 1)}.jpg'),
enableLoadState: true,
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
return Container(
color: Colors.black,
height: mediaHeight(context, 0.8),
height: mediaHeight(context, 0.6),
);
}
return null;
@ -78,6 +75,7 @@ class ImageViewVertical extends ConsumerWidget {
cacheMaxAge: const Duration(days: 7),
fit: BoxFit.contain,
enableMemoryCache: true,
enableLoadState: true,
loadStateChanged: (ExtendedImageState state) {
if (state.extendedImageLoadState == LoadState.loading) {
final ImageChunkEvent? loadingProgress =

View file

@ -12,7 +12,6 @@ import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/settings.dart';
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/sources/utils/utils.dart';
import 'package:mangayomi/modules/manga/reader/providers/push_router.dart';
import 'package:mangayomi/services/get_chapter_url.dart';
@ -26,7 +25,7 @@ import 'package:mangayomi/modules/more/settings/reader/reader_screen.dart';
import 'package:mangayomi/modules/widgets/progress_center.dart';
import 'package:photo_view/photo_view.dart';
import 'package:photo_view/photo_view_gallery.dart';
import 'package:scrollview_observer/scrollview_observer.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
typedef DoubleClickAnimationListener = void Function();
@ -157,8 +156,7 @@ class _MangaChapterPageGalleryState
@override
void dispose() {
_readerController.setMangaHistoryUpdate();
_readerController
.setPageIndex(_uChapDataPreload[_currentIndex ?? 0].index!);
_readerController.setPageIndex(_uChapDataPreload[_currentIndex!].index!);
_rebuildDetail.close();
_doubleClickAnimationController.dispose();
clearGestureDetailsCache();
@ -169,7 +167,7 @@ class _MangaChapterPageGalleryState
late Chapter chapter = widget.chapter;
final List<UChapDataPreload> _uChapDataPreload = [];
List<UChapDataPreload> _uChapDataPreload = [];
bool animatePageTransitions =
isar.settings.getSync(227)!.animatePageTransitions!;
Duration? _doubleTapAnimationDuration() {
@ -185,14 +183,12 @@ class _MangaChapterPageGalleryState
late int? _currentIndex = _readerController.getPageIndex();
late ListObserverController _observerController;
final ScrollController _scrollController = ScrollController();
late final ItemScrollController _itemScrollController =
ItemScrollController();
final ItemPositionsListener _itemPositionsListener =
ItemPositionsListener.create();
@override
void initState() {
_observerController = ListObserverController(
controller: _scrollController,
);
_doubleClickAnimationController = AnimationController(
duration: _doubleTapAnimationDuration(), vsync: this);
@ -201,11 +197,48 @@ class _MangaChapterPageGalleryState
_animation = Tween(begin: 1.0, end: 2.0).animate(
CurvedAnimation(curve: Curves.ease, parent: _scaleAnimationController));
_animation.addListener(() => _photoViewController.scale = _animation.value);
_itemPositionsListener.itemPositions.addListener(_readProgressListener);
_initCurrentIndex();
super.initState();
}
void _readProgressListener() {
_currentIndex = _itemPositionsListener.itemPositions.value.first.index;
if (_currentIndex! >= 0 && _currentIndex! < _uChapDataPreload.length) {
if (_readerController.chapter.id !=
_uChapDataPreload[_currentIndex!].chapter!.id) {
setState(() {
_readerController = ReaderController(
chapter: _uChapDataPreload[_currentIndex!].chapter!);
_chapterUrlModel = _uChapDataPreload[_currentIndex!].chapterUrlModel!;
});
}
ref.read(currentIndexProvider(chapter).notifier).setCurrentIndex(
_uChapDataPreload[_currentIndex!].index!,
);
}
if (_itemPositionsListener.itemPositions.value.last.index ==
_uChapDataPreload.length - 1) {
try {
bool hasNextChapter = _readerController.getChapterIndex() != 0;
final chapter =
hasNextChapter ? _readerController.getNextChapter() : null;
if (chapter != null) {
ref
.watch(getChapterUrlProvider(
chapter: chapter,
).future)
.then((value) {
_preloadNextChapter(value, chapter);
});
}
} catch (_) {}
}
}
_preloadNextChapter(GetChapterUrlModel chapterData, Chapter chap) {
try {
int length = 0;
@ -213,15 +246,15 @@ class _MangaChapterPageGalleryState
List<UChapDataPreload> uChapDataPreloadP = [];
List<UChapDataPreload> uChapDataPreloadL = _uChapDataPreload;
List<UChapDataPreload> preChap = [];
for (var data in _uChapDataPreload) {
for (var ee in _uChapDataPreload) {
if (chapterData.uChapDataPreload.first.chapter!.url ==
data.chapter!.url) {
ee.chapter!.url) {
isExist = true;
}
}
if (!isExist) {
for (var data in chapterData.uChapDataPreload) {
preChap.add(data);
for (var aa in chapterData.uChapDataPreload) {
preChap.add(aa);
}
}
@ -230,10 +263,26 @@ class _MangaChapterPageGalleryState
for (var i = 0; i < preChap.length; i++) {
int index = i + length;
final dataPreload = preChap[i];
uChapDataPreloadP.add(dataPreload..index = index);
uChapDataPreloadP.add(UChapDataPreload(
dataPreload.chapter,
dataPreload.path,
dataPreload.url,
dataPreload.isLocale,
dataPreload.archiveImage,
dataPreload.index,
dataPreload.chapterUrlModel,
index));
}
if (mounted) {
uChapDataPreloadL.addAll(uChapDataPreloadP);
setState(() {
_uChapDataPreload = uChapDataPreloadL;
_chapterUrlModel = chapterData;
_readerController = ReaderController(chapter: chap);
_readerController = ReaderController(
chapter: _uChapDataPreload[_currentIndex!].chapter!);
chapter = chap;
});
}
}
} catch (_) {}
@ -247,27 +296,26 @@ class _MangaChapterPageGalleryState
_selectedValue = _readerController.getReaderMode();
_setReaderMode(_selectedValue!, true);
ref.read(currentIndexProvider(chapter).notifier).setCurrentIndex(
_uChapDataPreload[_currentIndex ?? 0].index!,
_uChapDataPreload[_currentIndex!].index!,
);
}
void _onPageChanged(int index) {
_currentIndex = index;
if (_chapterId != _uChapDataPreload[_currentIndex ?? 0].chapter!.id) {
if (mounted) {
setState(() {
_chapterUrlModel =
_uChapDataPreload[_currentIndex ?? 0].chapterUrlModel!;
_chapterId = _uChapDataPreload[_currentIndex ?? 0].chapter!.id;
});
}
if (_readerController.chapter.id != _uChapDataPreload[index].chapter!.id) {
setState(() {
_readerController =
ReaderController(chapter: _uChapDataPreload[index].chapter!);
_chapterUrlModel = _uChapDataPreload[index].chapterUrlModel!;
});
}
_currentIndex = index;
ref.read(currentIndexProvider(chapter).notifier).setCurrentIndex(
_uChapDataPreload[index].index!,
);
if (_uChapDataPreload[index].index! ==
_readerController.getPageLength([]) - 1) {
if (_uChapDataPreload[index].pageIndex! == _uChapDataPreload.length - 1) {
try {
bool hasNextChapter = _readerController.getChapterIndex() != 0;
final chapter =
@ -293,25 +341,22 @@ class _MangaChapterPageGalleryState
_selectedValue == ReaderMode.webtoon) {
if (index != -1) {
if (isSlide) {
_observerController.jumpTo(
_itemScrollController.jumpTo(
index: index,
);
} else {
animatePageTransitions
? _observerController.animateTo(
? _itemScrollController.scrollTo(
curve: Curves.ease,
index: index,
duration: const Duration(milliseconds: 150))
: _observerController.jumpTo(
: _itemScrollController.jumpTo(
index: index,
);
}
}
} else {
if (index != -1) {
setState(() {
_isZoom = false;
});
if (_extendedController.hasClients) {
if (isSlide) {
_extendedController.jumpToPage(index);
@ -329,26 +374,23 @@ class _MangaChapterPageGalleryState
if (_selectedValue == ReaderMode.verticalContinuous ||
_selectedValue == ReaderMode.webtoon) {
if (isSlide) {
_observerController.jumpTo(
_itemScrollController.jumpTo(
index: index,
);
} else {
animatePageTransitions
? _observerController.animateTo(
? _itemScrollController.scrollTo(
curve: Curves.ease,
index: index,
duration: const Duration(milliseconds: 150))
: _observerController.jumpTo(
: _itemScrollController.jumpTo(
index: index,
);
}
} else {
if (_extendedController.hasClients) {
setState(() {
_isZoom = false;
});
if (isSlide) {
_observerController.jumpTo(
_itemScrollController.jumpTo(
index: index,
);
} else {
@ -395,7 +437,7 @@ class _MangaChapterPageGalleryState
}
late final _extendedController = ExtendedPageController(
initialPage: _currentIndex ?? 0,
initialPage: _currentIndex!,
shouldIgnorePointerWhenScrolling: false,
);
@ -472,7 +514,7 @@ class _MangaChapterPageGalleryState
_isReversHorizontal = false;
});
await Future.delayed(const Duration(milliseconds: 30));
_observerController.animateTo(
_itemScrollController.scrollTo(
index: _currentIndex!,
duration: const Duration(milliseconds: 1),
curve: Curves.ease);
@ -491,11 +533,11 @@ class _MangaChapterPageGalleryState
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
AnimatedContainer(
height: _isView ? Platform.isIOS?120:80 : 0,
height: _isView ? 80 : 0,
curve: Curves.ease,
duration: const Duration(milliseconds: 200),
child: PreferredSize(
preferredSize: Size.fromHeight(_isView ?Platform.isIOS?120: 80 : 0),
preferredSize: Size.fromHeight(_isView ? 80 : 0),
child: AppBar(
centerTitle: false,
automaticallyImplyLeading: false,
@ -995,13 +1037,11 @@ class _MangaChapterPageGalleryState
);
}
bool _isZoom = false;
bool _isVerticalContinous() {
return _selectedValue == ReaderMode.verticalContinuous ||
_selectedValue == ReaderMode.webtoon;
}
late int? _chapterId = widget.chapter.id;
final StreamController<double> _rebuildDetail =
StreamController<double>.broadcast();
final Map<int, ImageDetailInfo> detailKeys = <int, ImageDetailInfo>{};
@ -1029,329 +1069,236 @@ class _MangaChapterPageGalleryState
if (notification.direction == ScrollDirection.idle) {
_readerController.setMangaHistoryUpdate();
_readerController
.setPageIndex(_uChapDataPreload[_currentIndex ?? 0].index!);
.setPageIndex(_uChapDataPreload[_currentIndex!].index!);
_isBookmarked = _readerController.getChapterBookmarked();
}
return true;
},
child: StreamBuilder(
stream:
isar.chapters.watchObject(_chapterId!, fireImmediately: true),
builder: (context, snapshot) {
final chapterData = snapshot.hasData && snapshot.data != null
? snapshot.data
: chapter;
if (chapterData != null) {
_readerController = ReaderController(chapter: chapterData);
_isBookmarked = chapterData.isBookmarked!;
}
return Stack(
children: [
_isVerticalContinous()
? PhotoViewGallery.builder(
itemCount: 1,
builder: (_, __) =>
PhotoViewGalleryPageOptions.customChild(
controller: _photoViewController,
scaleStateController:
_photoViewScaleStateController,
basePosition: _scalePosition,
onScaleEnd: _onScaleEnd,
child: ListViewObserver(
controller: _observerController,
onObserve: (result) {
_currentIndex = result.firstChild?.index ?? 0;
if (_chapterId !=
_uChapDataPreload[_currentIndex ?? 0]
.chapter!
.id) {
if (mounted) {
setState(() {
_chapterUrlModel =
_uChapDataPreload[_currentIndex ?? 0]
.chapterUrlModel!;
_chapterId =
_uChapDataPreload[_currentIndex ?? 0]
.chapter!
.id;
});
}
}
ref
.read(
currentIndexProvider(chapter).notifier)
.setCurrentIndex(
_uChapDataPreload[_currentIndex ?? 0]
.index!,
);
},
child: ListView.separated(
cacheExtent: 15 * mediaHeight(context, 1),
itemCount: _uChapDataPreload.length,
controller: _scrollController,
itemBuilder: (context, index) {
_scrollController.addListener(() {
if (_scrollController.position.pixels ==
_scrollController
.position.maxScrollExtent) {
try {
bool hasNextChapter = _readerController
.getChapterIndex() !=
0;
final chapter = hasNextChapter
? _readerController.getNextChapter()
: null;
if (chapter != null) {
ref
.watch(getChapterUrlProvider(
chapter: chapter,
).future)
.then((value) {
_preloadNextChapter(value, chapter);
});
}
} catch (_) {}
}
});
return GestureDetector(
behavior: HitTestBehavior.translucent,
onDoubleTapDown: (TapDownDetails details) {
_toggleScale(details.globalPosition);
},
onDoubleTap: () {},
child: ImageViewVertical(
archiveImage:
_cropImagesList.isNotEmpty &&
cropBorders == true
? _cropImagesList[index]
: _uChapDataPreload[index]
.archiveImage,
titleManga:
_readerController.getMangaName(),
source: _readerController.getSourceName(),
index: _uChapDataPreload[index].index!,
url: _uChapDataPreload[index].url!,
path: _uChapDataPreload[index].path!,
chapter:
_readerController.getChapterTitle(),
length: _readerController.getPageLength(
_chapterUrlModel.pageUrls),
isLocale: _cropImagesList.isNotEmpty &&
cropBorders == true
? true
: _uChapDataPreload[index].isLocale!,
lang: _uChapDataPreload[index]
.chapter!
.manga
.value!
.lang!,
),
);
},
separatorBuilder: (_, __) => Divider(
color: Colors.black,
height: _selectedValue == ReaderMode.webtoon
? 0
: 6),
),
child: Stack(
children: [
_isVerticalContinous()
? PhotoViewGallery.builder(
itemCount: 1,
builder: (_, __) => PhotoViewGalleryPageOptions.customChild(
controller: _photoViewController,
scaleStateController: _photoViewScaleStateController,
basePosition: _scalePosition,
onScaleEnd: _onScaleEnd,
child: ScrollablePositionedList.separated(
// scrollOffsetController: _scrollController,
physics: const ClampingScrollPhysics(),
minCacheExtent: 15 * mediaHeight(context, 1),
initialScrollIndex: _currentIndex!,
itemCount: _uChapDataPreload.length,
itemScrollController: _itemScrollController,
itemPositionsListener: _itemPositionsListener,
itemBuilder: (context, index) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onDoubleTapDown: (TapDownDetails details) {
_toggleScale(details.globalPosition);
},
onDoubleTap: () {},
child: ImageViewVertical(
archiveImage: _cropImagesList.isNotEmpty &&
cropBorders == true
? _cropImagesList[index]
: _uChapDataPreload[index].archiveImage,
source: _readerController.getSourceName(),
index: _uChapDataPreload[index].index!,
url: _uChapDataPreload[index].url!,
path: _uChapDataPreload[index].path!,
isLocale: _cropImagesList.isNotEmpty &&
cropBorders == true
? true
: _uChapDataPreload[index].isLocale!,
lang: _uChapDataPreload[index]
.chapter!
.manga
.value!
.lang!,
),
),
)
: Material(
color: Colors.black,
shadowColor: Colors.black,
child: ExtendedImageGesturePageView.builder(
controller: _extendedController,
scrollDirection: _scrollDirection,
reverse: _isReversHorizontal,
physics: const ClampingScrollPhysics(),
preloadPagesCount: _isZoom ? 0 : 6,
canScrollPage: (GestureDetails? gestureDetails) {
return gestureDetails != null
? !(gestureDetails.totalScale! > 1.0)
: true;
},
itemBuilder: (BuildContext context, int index) {
return ImageViewCenter(
archiveImage: _cropImagesList.isNotEmpty &&
cropBorders == true
? _cropImagesList[index]
: _uChapDataPreload[index].archiveImage,
titleManga: _readerController.getMangaName(),
source: _readerController.getSourceName(),
index: _uChapDataPreload[index].index!,
url: _uChapDataPreload[index].url!,
path: _uChapDataPreload[index].path!,
chapter: _readerController.getChapterTitle(),
length: _readerController
.getPageLength(_chapterUrlModel.pageUrls),
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,
);
},
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(),
canScrollPage: (GestureDetails? gestureDetails) {
return gestureDetails != null
? !(gestureDetails.totalScale! > 1.0)
: true;
},
itemBuilder: (BuildContext context, int index) {
return ImageViewCenter(
archiveImage: _cropImagesList.isNotEmpty &&
cropBorders == true
? _cropImagesList[index]
: _uChapDataPreload[index].archiveImage,
source: _readerController.getSourceName(),
index: _uChapDataPreload[index].index!,
url: _uChapDataPreload[index].url!,
path: _uChapDataPreload[index].path!,
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,
),
],
);
},
);
},
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();
},
isLocale: _cropImagesList.isNotEmpty &&
cropBorders == true
? true
: _uChapDataPreload[index].isLocale!,
lang: _uChapDataPreload[index]
.chapter!
.manga
.value!
.lang!,
initialData: _imageDetailY,
stream: _rebuildDetail.stream,
);
},
itemCount: _uChapDataPreload.length,
onPageChanged: _onPageChanged)),
_gestureRightLeft(),
_gestureTopBottom(),
_showMore(),
_showPage(),
],
);
}),
}
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]) {
end = doubleTapScales[1];
} else {
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();
},
isLocale: _cropImagesList.isNotEmpty &&
cropBorders == true
? true
: _uChapDataPreload[index].isLocale!,
lang: _uChapDataPreload[index]
.chapter!
.manga
.value!
.lang!,
);
},
itemCount: _uChapDataPreload.length,
onPageChanged: _onPageChanged)),
_gestureRightLeft(),
_gestureTopBottom(),
_showMore(),
_showPage(),
],
),
),
);
}
@ -1361,14 +1308,10 @@ class _MangaChapterPageGalleryState
context,
DraggableMenu(
ui: ClassicDraggableMenu(barItem: Container()),
levels: [
DraggableMenuLevel.ratio(ratio: 0.4),
],
fastDrag: false,
minimizeBeforeFastDrag: false,
child: StatefulBuilder(
builder: (context, setState) {
final l10n = l10nLocalizations(context)!;
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -1376,11 +1319,11 @@ class _MangaChapterPageGalleryState
const SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.all(8.0),
const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
l10n.settings,
style: const TextStyle(
'Settings',
style: TextStyle(
fontSize: 17, fontWeight: FontWeight.bold),
),
),
@ -1391,7 +1334,7 @@ class _MangaChapterPageGalleryState
children: [
SwitchListTile(
dense: true,
title: Text(l10n.show_page_number),
title: const Text('Show Page Number'),
value: _showPagesNumber,
onChanged: (value) {
setState(() {
@ -1412,14 +1355,14 @@ class _MangaChapterPageGalleryState
}
class UChapDataPreload {
Chapter? chapter;
Directory? path;
String? url;
bool? isLocale;
Uint8List? archiveImage;
int? index;
GetChapterUrlModel? chapterUrlModel;
int? pageIndex;
final Chapter? chapter;
final Directory? path;
final String? url;
final bool? isLocale;
final Uint8List? archiveImage;
final int? index;
final GetChapterUrlModel? chapterUrlModel;
final int? pageIndex;
UChapDataPreload(
this.chapter,
this.path,

View file

@ -5,18 +5,18 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: "405666cd3cf0ee0a48d21ec67e65406aad2c726d9fa58840d3375e7bdcd32a07"
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
url: "https://pub.dev"
source: hosted
version: "60.0.0"
version: "61.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "1952250bd005bacb895a01bf1b4dc00e3ba1c526cf47dca54dfe24979c65f5b3"
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
url: "https://pub.dev"
source: hosted
version: "5.12.0"
version: "5.13.0"
analyzer_plugin:
dependency: transitive
description:
@ -69,10 +69,10 @@ packages:
dependency: "direct main"
description:
name: background_downloader
sha256: dca018b102a8c5efb09aadf587c07729d6cb2c9840e471e725c746c2195a1cd3
sha256: "8edf16baa5fceb31cf103f6113ee01c0cbef17cdd8aabf6152fa0b1b89f6543b"
url: "https://pub.dev"
source: hosted
version: "7.9.0"
version: "7.9.1"
boolean_selector:
dependency: transitive
description:
@ -229,10 +229,10 @@ packages:
dependency: transitive
description:
name: collection
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
url: "https://pub.dev"
source: hosted
version: "1.17.1"
version: "1.17.2"
convert:
dependency: transitive
description:
@ -277,18 +277,18 @@ packages:
dependency: transitive
description:
name: custom_lint
sha256: "3ce36c04d30c60cde295588c6185b3f9800e6c18f6670a7ffdb3d5eab39bb942"
sha256: ae3cf0f83a155bdfc50315d4a11c7b358ea1e201a57ab0bb2b397f1a9a2a9b80
url: "https://pub.dev"
source: hosted
version: "0.4.0"
version: "0.5.2"
custom_lint_core:
dependency: transitive
description:
name: custom_lint_core
sha256: "9170d9db2daf774aa2251a3bc98e4ba903c7702ab07aa438bc83bd3c9a0de57f"
sha256: a420aa57121a22b2a42e7e1dbbcaf7b91ef73b90adce07149419c16cf67d6fcc
url: "https://pub.dev"
source: hosted
version: "0.4.0"
version: "0.5.2"
dart_eval:
dependency: "direct main"
description:
@ -389,18 +389,18 @@ packages:
dependency: "direct main"
description:
name: extended_image
sha256: e77d18f956649ba6e5ecebd0cb68542120886336a75ee673788145bd4c3f0767
sha256: d1b122d6f5cf5596ea61d703d116d89e2ece7e324db414cfeed12967b72b7aef
url: "https://pub.dev"
source: hosted
version: "8.0.2"
version: "8.1.0"
extended_image_library:
dependency: transitive
description:
name: extended_image_library
sha256: bb8d08c504ebc73d476ec1c99451a61f12e95538869e734fc4f55a3a2d5c98ec
sha256: "8bf87c0b14dcb59200c923a9a3952304e4732a0901e40811428834ef39018ee1"
url: "https://pub.dev"
source: hosted
version: "3.5.3"
version: "3.6.0"
fake_async:
dependency: transitive
description:
@ -413,10 +413,10 @@ packages:
dependency: transitive
description:
name: ffi
sha256: ed5337a5660c506388a9f012be0288fb38b49020ce2b45fe1f8b8323fe429f99
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
version: "2.1.0"
file:
dependency: transitive
description:
@ -445,10 +445,10 @@ packages:
dependency: "direct main"
description:
name: flex_color_scheme
sha256: "659cf59bd5ccaa1e7de9384342be8b666ff10b108ed57a7fd46c122fb8bf6aca"
sha256: "57feb7e5b783e843a43e7d2713b0b0a58941ac3abc0439501290661cad4183a5"
url: "https://pub.dev"
source: hosted
version: "7.2.0"
version: "7.3.0"
flex_seed_scheme:
dependency: transitive
description:
@ -519,10 +519,10 @@ packages:
dependency: "direct main"
description:
name: flutter_meedu_videoplayer
sha256: "5d687cca1681041b1ca078de3abd677b4e97d9a5b141009963927c43438b7ad9"
sha256: "8f4880ac0dbe1662ea8d0d03e35c86ea5696651600b59e9005f5607fbb9a8b6f"
url: "https://pub.dev"
source: hosted
version: "4.2.22"
version: "4.2.24"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
@ -535,10 +535,10 @@ packages:
dependency: "direct main"
description:
name: flutter_riverpod
sha256: b83ac5827baadefd331ea1d85110f34645827ea234ccabf53a655f41901a9bf4
sha256: b6cb0041c6c11cefb2dcb97ef436eba43c6d41287ac6d8ca93e02a497f53a4f3
url: "https://pub.dev"
source: hosted
version: "2.3.6"
version: "2.3.7"
flutter_spinkit:
dependency: transitive
description:
@ -705,10 +705,10 @@ packages:
dependency: "direct main"
description:
name: intl
sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev"
source: hosted
version: "0.18.0"
version: "0.18.1"
io:
dependency: transitive
description:
@ -809,18 +809,18 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
version: "0.12.15"
version: "0.12.16"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
version: "0.5.0"
maybe_just_nothing:
dependency: transitive
description:
@ -833,50 +833,50 @@ packages:
dependency: transitive
description:
name: media_kit
sha256: eb47c2d51b7c06b319d8c776b47be912c5a4f53af7ab4814927a52a76442609e
sha256: "0a89e7037002a62701ec319c375586849f9ef8e681820e1dd4a4ff7b843f7542"
url: "https://pub.dev"
source: hosted
version: "1.1.2+1"
version: "1.1.4+1"
media_kit_libs_android_video:
dependency: "direct main"
description:
name: media_kit_libs_android_video
sha256: ddb0d26ecba72bf7117e37e29b6a50f4ba198bbccb4e47246cae1812087dc721
sha256: "142d389bf3efcf8469594a9c7a06a92fc25843fc6c0c3247f76cdcf70b3b29de"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
version: "1.3.2"
media_kit_libs_ios_video:
dependency: "direct main"
description:
name: media_kit_libs_ios_video
sha256: b65d1f22442e6074948f501e7156c310fbf133cd63aa914c84d0d4db1c683ee0
sha256: fed403dc9d54462e51ee80e0cb23c12a53fadea9a8fa18aca2de9054176d1159
url: "https://pub.dev"
source: hosted
version: "1.1.1"
version: "1.1.3"
media_kit_libs_linux:
dependency: transitive
description:
name: media_kit_libs_linux
sha256: "838b9e8041d376873cc938872c75812989d0feb247ad93afd8dbc92bf052680a"
sha256: "570bf18ebbd1221caec082657468be05d180510385d3515ec38e0be44fdcc859"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
version: "1.1.1"
media_kit_libs_macos_video:
dependency: transitive
description:
name: media_kit_libs_macos_video
sha256: dcabf2731b6b7dee143c18617fd32a063146303e7388f87dd4e974e03c9c795a
sha256: c06e831f3c22a45296d375788d9bc07871b448f8e9ec98d77b11e5e118a83fb2
url: "https://pub.dev"
source: hosted
version: "1.1.1"
version: "1.1.3"
media_kit_libs_windows_video:
dependency: transitive
description:
name: media_kit_libs_windows_video
sha256: b343e644927982a2ef3db63877b36d84bdda8173d8318ca0d1c68c1ea8a35982
sha256: f33aabd8414470d99e2c91dd98d605e6a5f1c4b8082dd933c10951bc961b9124
url: "https://pub.dev"
source: hosted
version: "1.0.5"
version: "1.0.7"
media_kit_native_event_loop:
dependency: transitive
description:
@ -889,10 +889,10 @@ packages:
dependency: transitive
description:
name: media_kit_video
sha256: "4b627683ef9e7f5cd049fd01be4b5deb5f31effc878503f108c81b19fd745040"
sha256: e7fcbe426d42a78ad6696f8f557adb9cbdc012177829026d04992cc106a1c815
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.1.5"
meedu:
dependency: transitive
description:
@ -969,10 +969,10 @@ packages:
dependency: "direct main"
description:
name: path_provider
sha256: "3087813781ab814e4157b172f1a11c46be20179fcc9bea043e0fba36bc0acaa2"
sha256: "909b84830485dbcd0308edf6f7368bc8fd76afa26a270420f34cabea2a6467a0"
url: "https://pub.dev"
source: hosted
version: "2.0.15"
version: "2.1.0"
path_provider_android:
dependency: transitive
description:
@ -1073,10 +1073,10 @@ packages:
dependency: transitive
description:
name: platform
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
version: "3.1.1"
plugin_platform_interface:
dependency: transitive
description:
@ -1153,34 +1153,34 @@ packages:
dependency: transitive
description:
name: riverpod
sha256: "80e48bebc83010d5e67a11c9514af6b44bbac1ec77b4333c8ea65dbc79e2d8ef"
sha256: b0657b5b30c81a3184bdaab353045f0a403ebd60bb381591a8b7ad77dcade793
url: "https://pub.dev"
source: hosted
version: "2.3.6"
version: "2.3.7"
riverpod_analyzer_utils:
dependency: transitive
description:
name: riverpod_analyzer_utils
sha256: "1b2632a6fc0b659c923a4dcc7cd5da42476f5b3294c70c86c971e63bdd443384"
sha256: aa216069d72f5478126029fa555874b4b38119f17e3f0f6c93fd63365f74502d
url: "https://pub.dev"
source: hosted
version: "0.3.1"
version: "0.3.3"
riverpod_annotation:
dependency: "direct main"
description:
name: riverpod_annotation
sha256: cedd6a54b6f5764ffd5c05df57b6676bfc8c01978e14ee60a2c16891038820fe
sha256: "8b3f7a54ddd5d53d6ea04bfb4ff77ee1b0816a1b563c0d9d43e73ce94bf2016d"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "2.1.2"
riverpod_generator:
dependency: "direct dev"
description:
name: riverpod_generator
sha256: "691180275664a5420c87d72c1ed26ef8404d32b823807540172bfd1660425376"
sha256: f668015d7b719c413c6001d4790689ea4a7bf76d5109118a1a98d5c23b20160d
url: "https://pub.dev"
source: hosted
version: "2.2.4"
version: "2.2.6"
rxdart:
dependency: transitive
description:
@ -1253,14 +1253,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.1.6"
scrollview_observer:
scrollable_positioned_list:
dependency: "direct main"
description:
name: scrollview_observer
sha256: "6bdd5c0a38690f0f0fcb9a839db9f404a5f10c9c002f6592ca33056c4a7c886c"
name: scrollable_positioned_list
sha256: "1b54d5f1329a1e263269abc9e2543d90806131aa14fe7c6062a8054d57249287"
url: "https://pub.dev"
source: hosted
version: "1.15.0"
version: "0.3.8"
share_plus:
dependency: "direct main"
description:
@ -1297,10 +1297,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: f39696b83e844923b642ce9dd4bd31736c17e697f6731a5adf445b1274cf3cd4
sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef
url: "https://pub.dev"
source: hosted
version: "2.3.2"
version: "2.3.3"
shared_preferences_linux:
dependency: transitive
description:
@ -1366,10 +1366,10 @@ packages:
dependency: transitive
description:
name: source_span
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
version: "1.10.0"
sqflite:
dependency: transitive
description:
@ -1398,10 +1398,10 @@ packages:
dependency: transitive
description:
name: state_notifier
sha256: "8fe42610f179b843b12371e40db58c9444f8757f8b69d181c97e50787caed289"
sha256: b8677376aa54f2d7c58280d5a007f9e8774f1968d1fb1c096adcb4792fba29bb
url: "https://pub.dev"
source: hosted
version: "0.7.2+1"
version: "1.0.0"
stream_channel:
dependency: transitive
description:
@ -1446,10 +1446,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
url: "https://pub.dev"
source: hosted
version: "0.5.1"
version: "0.6.0"
time:
dependency: transitive
description:
@ -1502,10 +1502,10 @@ packages:
dependency: transitive
description:
name: url_launcher_android
sha256: "78cb6dea3e93148615109e58e42c35d1ffbf5ef66c44add673d0ab75f12ff3af"
sha256: "3dd2388cc0c42912eee04434531a26a82512b9cb1827e0214430c9bcbddfe025"
url: "https://pub.dev"
source: hosted
version: "6.0.37"
version: "6.0.38"
url_launcher_ios:
dependency: transitive
description:
@ -1598,10 +1598,10 @@ packages:
dependency: transitive
description:
name: video_player_media_kit
sha256: "7472fca414cfe372560d9328a3da9e57d9ba1de4af7ed8d887ce6a9868dc2430"
sha256: "5f52455b3dc7df286a50b40629e7662e87a1c4bf282fa771d10223618a7fac8b"
url: "https://pub.dev"
source: hosted
version: "0.0.22"
version: "0.0.23"
video_player_platform_interface:
dependency: transitive
description:
@ -1650,6 +1650,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.1.0"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
web_socket_channel:
dependency: transitive
description:
@ -1686,10 +1694,10 @@ packages:
dependency: transitive
description:
name: xdg_directories
sha256: e0b1147eec179d3911f1f19b59206448f78195ca1d20514134e10641b7d7fbff
sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247
url: "https://pub.dev"
source: hosted
version: "1.0.1"
version: "1.0.2"
xml:
dependency: transitive
description:
@ -1731,5 +1739,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.0.6 <4.0.0"
flutter: ">=3.10.0"
dart: ">=3.1.0 <4.0.0"
flutter: ">=3.13.0"

View file

@ -4,7 +4,7 @@ description: Free and open source manga reader multi plateform app inspired by T
version: 0.0.26+7
environment:
sdk: '>=3.0.6 <4.0.0'
sdk: '>=3.1.0 <4.0.0'
dependencies:
@ -13,46 +13,46 @@ dependencies:
flutter_localizations:
sdk: flutter
go_router: ^10.0.0
flutter_riverpod: ^2.3.6
flutter_riverpod: ^2.3.7
cached_network_image: ^3.2.3
http: ^1.1.0
riverpod_annotation: ^2.1.1
riverpod_annotation: ^2.1.2
html: ^0.15.4
# flutter_js: ^0.8.0
font_awesome_flutter: ^10.5.0
expandable_text: ^2.3.0
flex_color_scheme: ^7.2.0
extended_image: ^8.0.2
flex_color_scheme: ^7.3.0
extended_image: ^8.1.0
photo_view: ^0.14.0
draggable_scrollbar: ^0.1.0
grouped_list: ^5.1.2
intl: ^0.18.0
google_fonts: ^5.1.0
url_launcher: ^6.1.12
package_info_plus: ^4.0.2
background_downloader: ^7.8.1
package_info_plus: ^4.1.0
background_downloader: ^7.9.1
permission_handler: ^10.4.3
flutter_inappwebview: ^5.7.2+3
draggable_menu: ^4.1.3
isar: 3.1.0+1
isar_flutter_libs: 3.1.0+1
share_plus: ^7.0.2
share_plus: ^7.1.0
xpath_selector_html_parser: ^3.0.1
desktop_webview_window: ^0.2.0
desktop_webview_window: ^0.2.1
archive: ^3.3.7
file_picker: ^5.3.3
path_provider: ^2.0.15
path_provider: ^2.1.0
# image: ^3.3.0
scrollview_observer: ^1.15.0
scrollable_positioned_list: ^0.3.5
dart_eval: ^0.6.0
json_path: ^0.6.2
bot_toast: ^4.0.4
flutter_web_auth_2: ^2.1.5
numberpicker: ^2.1.2
encrypt: ^5.0.1
flutter_meedu_videoplayer: ^4.2.22
media_kit_libs_android_video: ^1.3.0
media_kit_libs_ios_video: ^1.1.1
flutter_meedu_videoplayer: ^4.2.24
media_kit_libs_android_video: ^1.3.2
media_kit_libs_ios_video: ^1.1.3
js_packer: ^0.0.5

View file

@ -31,6 +31,11 @@ bool FlutterWindow::OnCreate() {
this->Show();
});
// Flutter can complete the first frame before the "show window" callback is
// registered. The following call ensures a frame is pending to ensure the
// window is shown. It is a no-op if the first frame hasn't completed yet.
flutter_controller_->ForceRedraw();
return true;
}