diff --git a/Cargo.lock b/Cargo.lock index e850e01..879661f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/lib/modules/browse/sources/sources_filter_screen.dart b/lib/modules/browse/sources/sources_filter_screen.dart index 2878f6f..8973390 100644 --- a/lib/modules/browse/sources/sources_filter_screen.dart +++ b/lib/modules/browse/sources/sources_filter_screen.dart @@ -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( - 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( + 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(); diff --git a/lib/modules/history/history_screen.dart b/lib/modules/history/history_screen.dart index efa15ab..ad8dae9 100644 --- a/lib/modules/history/history_screen.dart +++ b/lib/modules/history/history_screen.dart @@ -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 { .toList(); if (entries.isNotEmpty) { - return GroupedListView( - 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( + 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( diff --git a/lib/modules/manga/reader/double_columm_view_center.dart b/lib/modules/manga/reader/double_columm_view_center.dart index a94578e..d156ea1 100644 --- a/lib/modules/manga/reader/double_columm_view_center.dart +++ b/lib/modules/manga/reader/double_columm_view_center.dart @@ -14,13 +14,11 @@ import 'package:photo_view/photo_view_gallery.dart'; class DoubleColummView extends StatefulWidget { final List 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 CurvedAnimation(curve: Curves.ease, parent: _scaleAnimationController)); _animation.addListener(() { _photoViewController.scale = _animation.value; - widget.scale(_animation.value); }); super.initState(); diff --git a/lib/modules/manga/reader/providers/crop_borders_provider.dart b/lib/modules/manga/reader/providers/crop_borders_provider.dart index 5541034..ba5b886 100644 --- a/lib/modules/manga/reader/providers/crop_borders_provider.dart +++ b/lib/modules/manga/reader/providers/crop_borders_provider.dart @@ -24,12 +24,12 @@ Future cropBorders(CropBordersRef ref, nextId++; final completer = Completer(); 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; diff --git a/lib/modules/manga/reader/reader_view.dart b/lib/modules/manga/reader/reader_view.dart index 8443666..f988eca 100644 --- a/lib/modules/manga/reader/reader_view.dart +++ b/lib/modules/manga/reader/reader_view.dart @@ -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, diff --git a/messages/crop_borders.proto b/messages/crop_borders.proto index f93b85b..0d6e524 100644 --- a/messages/crop_borders.proto +++ b/messages/crop_borders.proto @@ -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; } diff --git a/native/hub/Cargo.toml b/native/hub/Cargo.toml index ac0c821..ba4de5f 100644 --- a/native/hub/Cargo.toml +++ b/native/hub/Cargo.toml @@ -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" diff --git a/native/hub/src/imagecrop.rs b/native/hub/src/imagecrop.rs index 80816e3..fe0dba9 100644 --- a/native/hub/src/imagecrop.rs +++ b/native/hub/src/imagecrop.rs @@ -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 = 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(); } } diff --git a/pubspec.lock b/pubspec.lock index c1ef458..dd5e11b 100644 --- a/pubspec.lock +++ b/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: diff --git a/pubspec.yaml b/pubspec.yaml index 29fe0d0..19b99b3 100644 --- a/pubspec.yaml +++ b/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