diff --git a/lib/views/library/library_screen.dart b/lib/views/library/library_screen.dart index 16c1c29d..32d9f5ce 100644 --- a/lib/views/library/library_screen.dart +++ b/lib/views/library/library_screen.dart @@ -1,16 +1,15 @@ +import 'dart:developer'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:mangayomi/models/model_manga.dart'; import 'package:mangayomi/providers/hive_provider.dart'; -import 'package:mangayomi/utils/cached_network.dart'; import 'package:mangayomi/utils/media_query.dart'; import 'package:mangayomi/views/library/providers/state_providers.dart'; import 'package:mangayomi/views/library/search_text_form_field.dart'; -import 'package:mangayomi/views/widgets/bottom_text_widget.dart'; -import 'package:mangayomi/views/widgets/cover_view_widget.dart'; -import 'package:mangayomi/views/widgets/gridview_widget.dart'; +import 'package:mangayomi/views/library/widgets/library_gridview_widget.dart'; +import 'package:mangayomi/views/library/widgets/library_listview_widget.dart'; import 'package:modal_bottom_sheet/modal_bottom_sheet.dart'; class LibraryScreen extends ConsumerStatefulWidget { @@ -30,6 +29,7 @@ class _LibraryScreenState extends ConsumerState @override Widget build(BuildContext context) { final reverse = ref.watch(reverseStateProvider); + final display = ref.watch(displayValueStateProvider); return Scaffold( appBar: AppBar( elevation: 0, @@ -74,26 +74,15 @@ class _LibraryScreenState extends ConsumerState }, icon: Icon(Icons.filter_list_sharp, color: Theme.of(context).hintColor)), - PopupMenuButton( - color: Theme.of(context).hintColor, - itemBuilder: (context) { - return [ - const PopupMenuItem(value: 0, child: Text("1")), - const PopupMenuItem( - value: 1, - child: Text("2"), - ), - const PopupMenuItem( - value: 2, - child: Text("3"), - ), - ]; - }, - onSelected: (value) { - if (value == 0) { - } else if (value == 1) { - } else if (value == 2) {} - }), + // PopupMenuButton( + // color: Theme.of(context).hintColor, + // itemBuilder: (context) { + // return [ + // const PopupMenuItem( + // value: 0, child: Text("Open random entry")), + // ]; + // }, + // onSelected: (value) {}), ], ), body: ValueListenableBuilder>( @@ -106,63 +95,13 @@ class _LibraryScreenState extends ConsumerState ? entries.reversed.toList() : entries; if (entries.isNotEmpty || entriesFilter.isNotEmpty) { - return GridViewWidget( - itemCount: entriesManga.length, - itemBuilder: (context, index) { - return GestureDetector( - onTap: () { - final model = ModelManga( - imageUrl: entriesManga[index].imageUrl, - name: entriesManga[index].name, - genre: entriesManga[index].genre, - author: entriesManga[index].author, - status: entriesManga[index].status, - chapterDate: entriesManga[index].chapterDate, - chapterTitle: entriesManga[index].chapterTitle, - chapterUrl: entriesManga[index].chapterUrl, - description: entriesManga[index].description, - favorite: entriesManga[index].favorite, - link: entriesManga[index].link, - source: entriesManga[index].source, - lang: entriesManga[index].lang); - - context.push('/manga-reader/detail', extra: model); - }, - child: CoverViewWidget( - children: [ - Stack( - children: [ - cachedNetworkImage( - imageUrl: entriesManga[index].imageUrl!, - width: 200, - height: 270, - fit: BoxFit.cover), - Positioned( - top: 0, - left: 0, - child: Padding( - padding: const EdgeInsets.all(5), - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(3), - color: Theme.of(context).cardColor), - child: Padding( - padding: const EdgeInsets.all(1), - child: Text(entriesManga[index] - .chapterDate! - .length - .toString()), - ), - ), - )) - ], - ), - BottomTextWidget(text: entriesManga[index].name!) - ], - ), - ); - }, - ); + return display == 'List' + ? LibraryListViewWidget( + entriesManga: entriesManga, + ) + : LibraryGridViewWidget( + entriesManga: entriesManga, + ); } return const Center(child: Text("Empty Library")); }, @@ -171,11 +110,9 @@ class _LibraryScreenState extends ConsumerState } _showModalSort() { - List sortList = [ - "Alphabetically", - "Total chapters", - "Latest chapter", - "Date added" + List displayList = [ + "Compact grid", + "List", ]; late TabController tabBarController; showMaterialModalBottomSheet( @@ -192,7 +129,7 @@ class _LibraryScreenState extends ConsumerState tabBarController.animateTo(0); } return SizedBox( - height: mediaHeight(context, 0.4), + height: mediaHeight(context, 0.3), child: DefaultTabController( length: 3, child: Scaffold( @@ -214,37 +151,49 @@ class _LibraryScreenState extends ConsumerState Consumer(builder: (context, ref, chil) { final reverse = ref.watch(reverseStateProvider); - final sortedValue = - ref.watch(sortedValueStateProvider); + return Column( children: [ - for (var i = 0; i < sortList.length; i++) - ListTile( - onTap: () { + ListTile( + onTap: () { + ref + .read( + reverseStateProvider.notifier) + .state = !reverse; + }, + dense: true, + leading: Icon(reverse + ? Icons.arrow_downward_sharp + : Icons.arrow_upward_sharp), + title: const Text("Alphabetically"), + ), + ], + ); + }), + Consumer(builder: (context, ref, chil) { + final display = + ref.watch(displayValueStateProvider); + + return Column( + children: [ + for (var i = 0; + i < displayList.length; + i++) + RadioListTile( + title: Text(displayList[i]), + value: displayList[i], + groupValue: display, + selected: true, + onChanged: (value) { ref - .read(reverseStateProvider + .read(displayValueStateProvider .notifier) - .state = !reverse; - ref - .read(sortedValueStateProvider - .notifier) - .state = sortList[i]; + .state = value.toString(); }, - dense: true, - leading: sortedValue == sortList[i] - ? Icon(reverse - ? Icons.arrow_downward_sharp - : Icons.arrow_upward_sharp) - : const Icon( - Icons.arrow_upward_sharp, - color: Colors.transparent, - ), - title: Text(sortList[i]), ), ], ); }), - const Center(child: Text("soon")) ]), ), ], diff --git a/lib/views/library/providers/state_providers.dart b/lib/views/library/providers/state_providers.dart index 56ec168a..92dd3fc7 100644 --- a/lib/views/library/providers/state_providers.dart +++ b/lib/views/library/providers/state_providers.dart @@ -4,6 +4,6 @@ final reverseStateProvider = StateProvider.autoDispose( (ref) => false, ); -final sortedValueStateProvider = StateProvider.autoDispose( - (ref) => 'Alphabetically', +final displayValueStateProvider = StateProvider.autoDispose( + (ref) => 'Compact grid', ); diff --git a/lib/views/library/widgets/library_gridview_widget.dart b/lib/views/library/widgets/library_gridview_widget.dart new file mode 100644 index 00000000..8190ec2b --- /dev/null +++ b/lib/views/library/widgets/library_gridview_widget.dart @@ -0,0 +1,74 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mangayomi/models/model_manga.dart'; +import 'package:mangayomi/utils/cached_network.dart'; +import 'package:mangayomi/views/widgets/bottom_text_widget.dart'; +import 'package:mangayomi/views/widgets/cover_view_widget.dart'; +import 'package:mangayomi/views/widgets/gridview_widget.dart'; + +class LibraryGridViewWidget extends StatelessWidget { + final List entriesManga; + const LibraryGridViewWidget({super.key, required this.entriesManga}); + + @override + Widget build(BuildContext context) { + return GridViewWidget( + itemCount: entriesManga.length, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + final model = ModelManga( + imageUrl: entriesManga[index].imageUrl, + name: entriesManga[index].name, + genre: entriesManga[index].genre, + author: entriesManga[index].author, + status: entriesManga[index].status, + chapterDate: entriesManga[index].chapterDate, + chapterTitle: entriesManga[index].chapterTitle, + chapterUrl: entriesManga[index].chapterUrl, + description: entriesManga[index].description, + favorite: entriesManga[index].favorite, + link: entriesManga[index].link, + source: entriesManga[index].source, + lang: entriesManga[index].lang); + + context.push('/manga-reader/detail', extra: model); + }, + child: CoverViewWidget( + children: [ + Stack( + children: [ + cachedNetworkImage( + imageUrl: entriesManga[index].imageUrl!, + width: 200, + height: 270, + fit: BoxFit.cover), + Positioned( + top: 0, + left: 0, + child: Padding( + padding: const EdgeInsets.all(5), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(3), + color: Theme.of(context).cardColor), + child: Padding( + padding: const EdgeInsets.all(1), + child: Text(entriesManga[index] + .chapterDate! + .length + .toString()), + ), + ), + )) + ], + ), + BottomTextWidget(text: entriesManga[index].name!) + ], + ), + ); + }, + ); + ; + } +} diff --git a/lib/views/library/widgets/library_listview_widget.dart b/lib/views/library/widgets/library_listview_widget.dart new file mode 100644 index 00000000..048a68ef --- /dev/null +++ b/lib/views/library/widgets/library_listview_widget.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mangayomi/models/model_manga.dart'; +import 'package:mangayomi/utils/cached_network.dart'; +import 'package:mangayomi/utils/media_query.dart'; +import 'package:mangayomi/views/widgets/listview_widget.dart'; + +class LibraryListViewWidget extends StatelessWidget { + final List entriesManga; + const LibraryListViewWidget({super.key, required this.entriesManga}); + + @override + Widget build(BuildContext context) { + return ListViewWidget( + itemCount: entriesManga.length, + itemBuilder: (context, index) { + return GestureDetector( + onTap: () { + final model = ModelManga( + imageUrl: entriesManga[index].imageUrl, + name: entriesManga[index].name, + genre: entriesManga[index].genre, + author: entriesManga[index].author, + status: entriesManga[index].status, + chapterDate: entriesManga[index].chapterDate, + chapterTitle: entriesManga[index].chapterTitle, + chapterUrl: entriesManga[index].chapterUrl, + description: entriesManga[index].description, + favorite: entriesManga[index].favorite, + link: entriesManga[index].link, + source: entriesManga[index].source, + lang: entriesManga[index].lang); + + context.push('/manga-reader/detail', extra: model); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + height: 45, + decoration: BoxDecoration( + color: Theme.of(context).canvasColor, + borderRadius: BorderRadius.circular(5)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(5), + bottomLeft: Radius.circular(5)), + child: cachedNetworkImage( + imageUrl: entriesManga[index].imageUrl!, + width: 30, + height: 40, + fit: BoxFit.cover), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: SizedBox( + width: mediaWidth(context, 0.7), + child: Text(entriesManga[index].name!)), + ), + ], + ), + Padding( + padding: const EdgeInsets.all(5), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(3), + color: Theme.of(context).cardColor), + child: Padding( + padding: const EdgeInsets.all(1), + child: Text( + entriesManga[index].chapterDate!.length.toString()), + ), + ), + ) + ], + ), + ), + ), + ); + }, + ); + ; + } +} diff --git a/lib/views/manga/detail/manga_detail_view.dart b/lib/views/manga/detail/manga_detail_view.dart index 7304f73c..8bf9137c 100644 --- a/lib/views/manga/detail/manga_detail_view.dart +++ b/lib/views/manga/detail/manga_detail_view.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:cached_network_image/cached_network_image.dart'; import 'package:draggable_scrollbar/draggable_scrollbar.dart'; import 'package:flutter/material.dart'; @@ -10,6 +8,7 @@ import 'package:mangayomi/models/manga_reader.dart'; import 'package:mangayomi/models/model_manga.dart'; import 'package:mangayomi/utils/cached_network.dart'; import 'package:mangayomi/utils/media_query.dart'; +import 'package:mangayomi/views/manga/detail/providers/state_providers.dart'; import 'package:mangayomi/views/manga/detail/readmore.dart'; class MangaDetailView extends ConsumerStatefulWidget { @@ -34,7 +33,8 @@ class MangaDetailView extends ConsumerStatefulWidget { ConsumerState createState() => _MangaDetailViewState(); } -class _MangaDetailViewState extends ConsumerState { +class _MangaDetailViewState extends ConsumerState + with TickerProviderStateMixin { @override void initState() { _scrollController = ScrollController() @@ -45,7 +45,8 @@ class _MangaDetailViewState extends ConsumerState { } final offetProvider = StateProvider((ref) => 0.0); - bool _reverse = false; + bool isOk = false; + bool _expanded = false; ScrollController _scrollController = ScrollController(); @override Widget build(BuildContext context) { @@ -65,91 +66,124 @@ class _MangaDetailViewState extends ConsumerState { preferredSize: Size.fromHeight(AppBar().preferredSize.height), child: Consumer( builder: (context, ref, child) { + final reverse = ref.watch(reverseMangaStateProvider); return AppBar( title: ref.watch(offetProvider) > 200 - ? Text(widget.modelManga!.name!) + ? Text( + widget.modelManga!.name!, + style: const TextStyle(fontSize: 17), + ) : null, backgroundColor: ref.watch(offetProvider) == 0.0 ? Colors.transparent : Theme.of(context).scaffoldBackgroundColor, actions: [ + // IconButton( + // splashRadius: 20, + // onPressed: () {}, + // icon: Icon(Icons.download_outlined, + // color: Theme.of(context).hintColor)), IconButton( splashRadius: 20, - onPressed: () {}, - icon: Icon(Icons.download_outlined, - color: Theme.of(context).hintColor)), - IconButton( - splashRadius: 20, - onPressed: () {}, - icon: Icon(Icons.filter_list_sharp, - color: Theme.of(context).hintColor)), - PopupMenuButton( - color: Theme.of(context).hintColor, - itemBuilder: (context) { - return [ - const PopupMenuItem( - value: 0, - child: Text("1"), - ), - const PopupMenuItem( - value: 1, - child: Text("2"), - ), - const PopupMenuItem( - value: 2, - child: Text("3"), - ), - ]; + onPressed: () { + ref.read(reverseMangaStateProvider.notifier).state = + !reverse; }, - onSelected: (value) { - if (value == 0) { - } else if (value == 1) { - } else if (value == 2) {} - }), + icon: Icon( + reverse + ? Icons.arrow_downward_sharp + : Icons.arrow_upward_sharp, + color: Theme.of(context).hintColor)), ], ); }, )), - body: _listView(), + body: Stack( + children: [ + Positioned( + top: 0, + child: Stack( + children: [ + cachedNetworkImage( + imageUrl: widget.modelManga!.imageUrl!, + width: mediaWidth(context, 1), + height: 461, + fit: BoxFit.cover), + Container( + width: mediaWidth(context, 1), + height: 465, + color: Theme.of(context) + .scaffoldBackgroundColor + .withOpacity(0.9), + ), + SafeArea( + child: Container( + width: mediaWidth(context, 1), + height: mediaHeight(context, 1), + color: Theme.of(context).scaffoldBackgroundColor), + ) + ], + )), + SafeArea(child: _listView()), + ], + ), )); } - _listView() { - return DraggableScrollbar.rrect( - alwaysVisibleScrollThumb: true, - controller: _scrollController, - child: ListView.builder( - controller: _scrollController, - padding: const EdgeInsets.only(top: 0), - reverse: _reverse, - itemCount: widget.listLength, - itemBuilder: (context, index) { - int finalIndex = index - 1; - if (index == 0) { - return _bodyContainer(); - } - return ListTile( - key: ObjectKey(widget.modelManga!.chapterUrl), - onTap: () { - pushMangaReaderView( - context: context, - modelManga: widget.modelManga!, - index: finalIndex); - }, - trailing: const Icon( - FontAwesomeIcons.circleDown, - size: 20, - ), - subtitle: Text( - widget.modelManga!.chapterDate![finalIndex], - style: const TextStyle(fontSize: 12), - ), - title: Text( - widget.modelManga!.chapterTitle![finalIndex], - style: const TextStyle(fontSize: 13), - ), - ); - })); + Widget _listView() { + return Consumer(builder: (context, ref, child) { + final reverse = ref.watch(reverseMangaStateProvider); + return DraggableScrollbar.rrect( + scrollbarTimeToFade: const Duration(seconds: 2), + controller: _scrollController, + child: ListView.builder( + controller: _scrollController, + padding: const EdgeInsets.only(top: 0), + itemCount: widget.listLength, + itemBuilder: (context, index) { + int finalIndex = index - 1; + if (index == 0) { + return _bodyContainer(); + } + + int reverseIndex = widget.modelManga!.chapterDate!.length - + widget.modelManga!.chapterDate!.reversed.toList().indexOf( + widget.modelManga!.chapterDate!.reversed + .toList()[finalIndex]) - + 1; + List? chapterUrl = reverse + ? widget.modelManga!.chapterUrl!.reversed.toList() + : widget.modelManga!.chapterUrl!; + List? chapterDate = reverse + ? widget.modelManga!.chapterDate!.reversed.toList() + : widget.modelManga!.chapterDate!; + List? chapterTitle = reverse + ? widget.modelManga!.chapterTitle!.reversed.toList() + : widget.modelManga!.chapterTitle!; + + return ListTile( + key: ObjectKey(chapterUrl), + onTap: () { + pushMangaReaderView( + context: context, + modelManga: widget.modelManga!, + index: reverse ? reverseIndex : finalIndex); + }, + trailing: const Icon( + FontAwesomeIcons.circleDown, + size: 20, + ), + subtitle: Text( + chapterDate[finalIndex], + style: const TextStyle(fontSize: 12), + ), + title: Text( + chapterTitle[finalIndex], + style: const TextStyle(fontSize: 13), + ), + ); + })); + }); } Widget _bodyContainer() { @@ -164,18 +198,15 @@ class _MangaDetailViewState extends ConsumerState { begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - Theme.of(context).scaffoldBackgroundColor.withOpacity(0.6), + Theme.of(context).scaffoldBackgroundColor.withOpacity(0.9), Color(Theme.of(context).scaffoldBackgroundColor.value) ], - stops: const [0, .8], + stops: const [0, .35], ), ), ), Column( children: [ - SizedBox( - height: AppBar().preferredSize.height * 1.5, - ), SizedBox( height: 180, child: Stack( @@ -197,36 +228,71 @@ class _MangaDetailViewState extends ConsumerState { padding: const EdgeInsets.all(8.0), child: ReadMoreWidget( text: widget.modelManga!.description!, + onChanged: (value) { + setState(() { + _expanded = value; + }); + }, ), ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 12), - child: Wrap( - children: [ - for (var i = 0; - i < widget.modelManga!.genre!.length; - i++) - Padding( - padding: const EdgeInsets.only( - left: 2, right: 2, bottom: 5), - child: SizedBox( - height: 30, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - shape: BeveledRectangleBorder( - borderRadius: - BorderRadius.circular(3))), - onPressed: () {}, - child: Text( - widget.modelManga!.genre![i], - style: const TextStyle(fontSize: 12), - ), + padding: const EdgeInsets.symmetric(horizontal: 12), + child: _expanded + ? Wrap( + children: [ + for (var i = 0; + i < widget.modelManga!.genre!.length; + i++) + Padding( + padding: const EdgeInsets.only( + left: 2, right: 2, bottom: 5), + child: SizedBox( + height: 30, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(5))), + onPressed: () {}, + child: Text( + widget.modelManga!.genre![i], + style: const TextStyle(fontSize: 12), + ), + ), + ), + ), + ], + ) + : SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + for (var i = 0; + i < widget.modelManga!.genre!.length; + i++) + Padding( + padding: const EdgeInsets.only( + left: 2, right: 2, bottom: 5), + child: SizedBox( + height: 30, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + 5))), + onPressed: () {}, + child: Text( + widget.modelManga!.genre![i], + style: + const TextStyle(fontSize: 12), + ), + ), + ), + ), + ], ), - ), - ), - ], - ), - ), + )), // log Column( children: [ diff --git a/lib/views/manga/detail/manga_details_view.dart b/lib/views/manga/detail/manga_details_view.dart index 9f777779..3226121b 100644 --- a/lib/views/manga/detail/manga_details_view.dart +++ b/lib/views/manga/detail/manga_details_view.dart @@ -113,7 +113,7 @@ class _MangaDetailsViewState extends ConsumerState { width: !ref.watch(isExtended) ? 60 : mediaWidth(context, 0.25), - duration: const Duration(milliseconds: 500), + duration: const Duration(milliseconds: 300), curve: Curves.easeIn, child: ElevatedButton( style: ElevatedButton.styleFrom( @@ -126,7 +126,7 @@ class _MangaDetailsViewState extends ConsumerState { AnimatedContainer( curve: Curves.easeIn, width: !ref.watch(isExtended) ? 0 : 30, - duration: const Duration(milliseconds: 500), + duration: const Duration(milliseconds: 300), child: const Text( "Read", overflow: TextOverflow.ellipsis, @@ -136,7 +136,7 @@ class _MangaDetailsViewState extends ConsumerState { AnimatedContainer( curve: Curves.easeIn, width: !ref.watch(isExtended) ? 0 : 10, - duration: const Duration(milliseconds: 500), + duration: const Duration(milliseconds: 300), ), const Icon( Icons.play_arrow, diff --git a/lib/views/manga/detail/providers/state_providers.dart b/lib/views/manga/detail/providers/state_providers.dart new file mode 100644 index 00000000..0bff4292 --- /dev/null +++ b/lib/views/manga/detail/providers/state_providers.dart @@ -0,0 +1,9 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final reverseMangaStateProvider = StateProvider.autoDispose( + (ref) => false, +); + +final sortedMangaValueStateProvider = StateProvider.autoDispose( + (ref) => 'By source', +); diff --git a/lib/views/manga/detail/readmore.dart b/lib/views/manga/detail/readmore.dart index 3ae44587..e960de55 100644 --- a/lib/views/manga/detail/readmore.dart +++ b/lib/views/manga/detail/readmore.dart @@ -3,8 +3,9 @@ import 'package:flutter/material.dart'; import 'package:mangayomi/utils/media_query.dart'; class ReadMoreWidget extends StatefulWidget { - const ReadMoreWidget({Key? key, required this.text}) : super(key: key); - + const ReadMoreWidget({Key? key, required this.text, required this.onChanged}) + : super(key: key); + final Function(bool) onChanged; final String text; @override @@ -24,6 +25,7 @@ class ReadMoreWidgetState extends State animationDuration: const Duration(milliseconds: 500), onExpandedChanged: (ok) { setState(() => expanded = ok); + widget.onChanged(ok); }, expandOnTextTap: true, widget.text, @@ -32,25 +34,46 @@ class ReadMoreWidgetState extends State expanded: false, onPrefixTap: () { setState(() => expanded = !expanded); + widget.onChanged(expanded); }, linkColor: Theme.of(context).scaffoldBackgroundColor, animation: true, collapseOnTextTap: true, prefixText: '', ), - Positioned( + if (!expanded) + Positioned( bottom: 0, - left: 0, right: 0, - child: expanded - ? const Icon(Icons.keyboard_arrow_up_sharp) - : const Icon(Icons.keyboard_arrow_down_sharp)) + left: 0, + child: Container( + width: mediaWidth(context, 1), + height: 20, + decoration: BoxDecoration( + color: Theme.of(context).scaffoldBackgroundColor, + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Theme.of(context) + .scaffoldBackgroundColor + .withOpacity(0.2), + Theme.of(context).scaffoldBackgroundColor + ], + stops: const [0, .9], + ), + ), + child: const Icon(Icons.keyboard_arrow_down_sharp), + ), + ), ], ), - Container( - color: Theme.of(context).cardColor.withOpacity(0.15), - width: mediaWidth(context, 1), - ) + if (expanded) + SizedBox( + width: mediaWidth(context, 1), + height: 20, + child: const Icon(Icons.keyboard_arrow_up_sharp), + ) ], ); } diff --git a/lib/views/manga/reader/manga_reader_view.dart b/lib/views/manga/reader/manga_reader_view.dart index 0cdf91d4..9f28f9b0 100644 --- a/lib/views/manga/reader/manga_reader_view.dart +++ b/lib/views/manga/reader/manga_reader_view.dart @@ -216,13 +216,16 @@ class _MangaChapterPageGalleryState widget.modelManga.link, MangaHistoryModel( date: DateTime.now().toString(), modelManga: widget.modelManga)); - setState(() { - _currentIndex = index; - if (_imageDetailY != 0) { - _imageDetailY = 0; - _rebuildDetail.sink.add(_imageDetailY); - } - }); + if (mounted) { + setState(() { + _currentIndex = index; + if (_imageDetailY != 0) { + _imageDetailY = 0; + _rebuildDetail.sink.add(_imageDetailY); + } + }); + } + ref.watch(hiveBoxMangaInfo).put( "${widget.source}/${widget.titleManga}/${widget.chapter}-page_index", index); diff --git a/lib/views/widgets/listview_widget.dart b/lib/views/widgets/listview_widget.dart new file mode 100644 index 00000000..8f052211 --- /dev/null +++ b/lib/views/widgets/listview_widget.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; + +class ListViewWidget extends StatelessWidget { + final ScrollController? controller; + final int? itemCount; + final bool reverse; + final Widget? Function(BuildContext, int) itemBuilder; + const ListViewWidget( + {super.key, + this.controller, + required this.itemCount, + required this.itemBuilder, + this.reverse = false}); + + @override + Widget build(BuildContext context) { + return Container( + color: Theme.of(context).scaffoldBackgroundColor, + child: ListView.builder( + controller: controller, + itemCount: itemCount, + itemBuilder: itemBuilder), + ); + } +}