mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-01-11 22:40:36 +00:00
add reader , browse , general setting
This commit is contained in:
parent
8379b1a076
commit
9d4a7e8cb1
31 changed files with 1156 additions and 179 deletions
|
|
@ -65,6 +65,14 @@ class Settings {
|
|||
|
||||
List<PersonalReaderMode>? personalReaderModeList;
|
||||
|
||||
bool? animatePageTransitions;
|
||||
|
||||
int? doubleTapAnimationSpeed;
|
||||
|
||||
bool? showNSFW;
|
||||
|
||||
bool? onlyIncludePinnedSources;
|
||||
|
||||
Settings(
|
||||
{this.id = 227,
|
||||
this.displayType = DisplayType.compactGrid,
|
||||
|
|
@ -92,7 +100,11 @@ class Settings {
|
|||
this.userAgent = defaultUserAgent,
|
||||
this.cookiesList,
|
||||
this.defaultReaderMode = ReaderMode.vertical,
|
||||
this.personalReaderModeList});
|
||||
this.personalReaderModeList,
|
||||
this.animatePageTransitions = true,
|
||||
this.doubleTapAnimationSpeed = 1,
|
||||
this.showNSFW = true,
|
||||
this.onlyIncludePinnedSources = false});
|
||||
}
|
||||
|
||||
enum DisplayType {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -7,7 +7,7 @@ import 'package:mangayomi/services/webviews/webview.dart';
|
|||
import 'package:mangayomi/views/browse/browse_screen.dart';
|
||||
import 'package:mangayomi/views/browse/extension/extension_lang.dart';
|
||||
import 'package:mangayomi/views/browse/global_search_screen.dart';
|
||||
import 'package:mangayomi/views/general/general_screen.dart';
|
||||
import 'package:mangayomi/views/main_view/main_screen.dart';
|
||||
import 'package:mangayomi/views/history/history_screen.dart';
|
||||
import 'package:mangayomi/views/library/library_screen.dart';
|
||||
import 'package:mangayomi/views/manga/detail/manga_detail_main.dart';
|
||||
|
|
@ -18,7 +18,10 @@ import 'package:mangayomi/views/more/about_screen.dart';
|
|||
import 'package:mangayomi/views/more/download_queue/download_queue_screen.dart';
|
||||
import 'package:mangayomi/views/more/more_screen.dart';
|
||||
import 'package:mangayomi/views/more/settings/appearance/appearance_screen.dart';
|
||||
import 'package:mangayomi/views/more/settings/categoties/categories_screen.dart';
|
||||
import 'package:mangayomi/views/more/categoties/categories_screen.dart';
|
||||
import 'package:mangayomi/views/more/settings/browse/browse_screen.dart';
|
||||
import 'package:mangayomi/views/more/settings/general/general_screen.dart';
|
||||
import 'package:mangayomi/views/more/settings/reader/reader_screen.dart';
|
||||
import 'package:mangayomi/views/more/settings/settings_screen.dart';
|
||||
import 'package:mangayomi/views/updates/updates_screen.dart';
|
||||
|
||||
|
|
@ -36,7 +39,7 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||
class AsyncRouterNotifier extends ChangeNotifier {
|
||||
List<RouteBase> get _routes => [
|
||||
ShellRoute(
|
||||
builder: (context, state, child) => GeneralScreen(child: child),
|
||||
builder: (context, state, child) => MainScreen(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: "library",
|
||||
|
|
@ -276,6 +279,45 @@ class AsyncRouterNotifier extends ChangeNotifier {
|
|||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: "/general",
|
||||
name: "general",
|
||||
builder: (context, state) {
|
||||
return const GeneralScreen();
|
||||
},
|
||||
pageBuilder: (context, state) {
|
||||
return CustomTransition(
|
||||
key: state.pageKey,
|
||||
child: const GeneralScreen(),
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: "/readerMode",
|
||||
name: "readerMode",
|
||||
builder: (context, state) {
|
||||
return const ReaderScreen();
|
||||
},
|
||||
pageBuilder: (context, state) {
|
||||
return CustomTransition(
|
||||
key: state.pageKey,
|
||||
child: const ReaderScreen(),
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
path: "/browseS",
|
||||
name: "browseS",
|
||||
builder: (context, state) {
|
||||
return const BrowseSScreen();
|
||||
},
|
||||
pageBuilder: (context, state) {
|
||||
return CustomTransition(
|
||||
key: state.pageKey,
|
||||
child: const BrowseSScreen(),
|
||||
);
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import 'package:mangayomi/sources/multisrc/mangathemesia/src/mangathemesia.dart'
|
|||
import 'package:mangayomi/sources/multisrc/mmrcms/src/mmrcms.dart';
|
||||
import 'package:mangayomi/sources/utils/utils.dart';
|
||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'get_chapter_url.g.dart';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:grouped_list/grouped_list.dart';
|
||||
|
|
@ -9,6 +7,7 @@ import 'package:mangayomi/models/source.dart';
|
|||
import 'package:mangayomi/utils/lang.dart';
|
||||
import 'package:mangayomi/views/browse/extension/refresh_filter_data.dart';
|
||||
import 'package:mangayomi/views/browse/extension/widgets/extension_list_tile_widget.dart';
|
||||
import 'package:mangayomi/views/more/settings/browse/providers/browse_state_provider.dart';
|
||||
|
||||
class ExtensionScreen extends ConsumerWidget {
|
||||
final Function(dynamic) entriesData;
|
||||
|
|
@ -30,7 +29,11 @@ class ExtensionScreen extends ConsumerWidget {
|
|||
.watch(fireImmediately: true),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
|
||||
final entries = snapshot.data!;
|
||||
final entries = snapshot.data!
|
||||
.where((element) => ref.watch(showNSFWStateProvider)
|
||||
? true
|
||||
: element.isNsfw == false)
|
||||
.toList();
|
||||
entriesData(entries);
|
||||
return GroupedListView<Source, String>(
|
||||
elements: entriesFilter.isNotEmpty ? entriesFilter : entries,
|
||||
|
|
@ -48,11 +51,6 @@ class ExtensionScreen extends ConsumerWidget {
|
|||
),
|
||||
),
|
||||
itemBuilder: (context, Source element) {
|
||||
if (element.isCloudflare! && !Platform.isWindows ||
|
||||
element.isCloudflare! && !Platform.isLinux) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
return ExtensionListTileWidget(
|
||||
lang: element.lang!,
|
||||
onChanged: (val) {
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ import 'package:mangayomi/services/get_manga_detail.dart';
|
|||
import 'package:mangayomi/services/search_manga.dart';
|
||||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/sources/service.dart';
|
||||
import 'package:mangayomi/sources/source_list.dart';
|
||||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
import 'package:mangayomi/views/library/search_text_form_field.dart';
|
||||
import 'package:mangayomi/views/more/settings/browse/providers/browse_state_provider.dart';
|
||||
import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/manga_image_card_widget.dart';
|
||||
|
||||
|
|
@ -28,7 +30,9 @@ class _GlobalSearchScreenState extends ConsumerState<GlobalSearchScreen> {
|
|||
final _textEditingController = TextEditingController();
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final sourceList = isar.sources.filter().isAddedEqualTo(true).findAllSync();
|
||||
final sourceList = ref.watch(onlyIncludePinnedSourceStateProvider)
|
||||
? isar.sources.filter().isAddedEqualTo(true).findAllSync()
|
||||
: sourcesList;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: Container(),
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import 'package:mangayomi/models/source.dart';
|
|||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/utils/lang.dart';
|
||||
import 'package:mangayomi/views/browse/extension/refresh_filter_data.dart';
|
||||
import 'package:mangayomi/views/more/settings/browse/providers/browse_state_provider.dart';
|
||||
|
||||
class SourcesScreen extends ConsumerWidget {
|
||||
const SourcesScreen({super.key});
|
||||
|
|
@ -30,7 +31,11 @@ class SourcesScreen extends ConsumerWidget {
|
|||
if (!snapshot.hasData) {
|
||||
return const Center(child: Text("Empty"));
|
||||
}
|
||||
final entries = snapshot.data!;
|
||||
final entries = snapshot.data!
|
||||
.where((element) => ref.watch(showNSFWStateProvider)
|
||||
? true
|
||||
: element.isNsfw == false)
|
||||
.toList();
|
||||
return GroupedListView<Source, String>(
|
||||
elements: entries,
|
||||
groupBy: (element) => completeLang(element.lang!.toLowerCase()),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import 'package:mangayomi/views/library/widgets/library_listview_widget.dart';
|
|||
import 'package:mangayomi/views/library/widgets/list_tile_manga_category.dart';
|
||||
import 'package:mangayomi/views/manga/detail/widgets/chapter_filter_list_tile_widget.dart';
|
||||
import 'package:mangayomi/views/manga/detail/widgets/chapter_sort_list_tile_widget.dart';
|
||||
import 'package:mangayomi/views/more/settings/categoties/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/views/more/categoties/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/views/widgets/error_text.dart';
|
||||
import 'package:mangayomi/views/widgets/progress_center.dart';
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:mangayomi/models/manga.dart';
|
|||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/widgets/bottom_text_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/cover_view_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/error_text.dart';
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import 'package:mangayomi/models/manga.dart';
|
|||
import 'package:mangayomi/utils/cached_network.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/widgets/error_text.dart';
|
||||
import 'package:mangayomi/views/widgets/listview_widget.dart';
|
||||
import 'package:mangayomi/views/widgets/manga_image_card_widget.dart';
|
||||
|
|
|
|||
|
|
@ -7,18 +7,18 @@ import 'package:google_fonts/google_fonts.dart';
|
|||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/media_query.dart';
|
||||
import 'package:mangayomi/views/library/providers/library_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/providers/incognito_mode_state_provider.dart';
|
||||
|
||||
class GeneralScreen extends StatefulWidget {
|
||||
const GeneralScreen({super.key, required this.child});
|
||||
class MainScreen extends StatefulWidget {
|
||||
const MainScreen({super.key, required this.child});
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
State<GeneralScreen> createState() => _GeneralScreenState();
|
||||
State<MainScreen> createState() => _MainScreenState();
|
||||
}
|
||||
|
||||
class _GeneralScreenState extends State<GeneralScreen> {
|
||||
class _MainScreenState extends State<MainScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final route = GoRouter.of(context);
|
||||
|
|
@ -931,12 +931,13 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||
elevation: 0),
|
||||
onPressed: () {
|
||||
String url = getMangaAPIUrl(widget.manga!.source!).isEmpty
|
||||
? widget.manga!.link!
|
||||
: "${getMangaBaseUrl(widget.manga!.source!)}${widget.manga!.link!}";
|
||||
final manga = widget.manga!;
|
||||
String url = getMangaAPIUrl(manga.source!).isEmpty
|
||||
? manga.link!
|
||||
: "${getMangaBaseUrl(manga.source!)}${manga.link!}";
|
||||
Map<String, String> data = {
|
||||
'url': url,
|
||||
'source': widget.manga!.source!,
|
||||
'source': manga.source!,
|
||||
};
|
||||
context.push("/mangawebview", extra: data);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import 'package:mangayomi/utils/media_query.dart';
|
|||
import 'package:mangayomi/views/manga/detail/manga_detail_view.dart';
|
||||
import 'package:mangayomi/views/manga/detail/providers/state_providers.dart';
|
||||
import 'package:mangayomi/views/manga/detail/widgets/chapter_filter_list_tile_widget.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/widgets/error_text.dart';
|
||||
import 'package:mangayomi/views/widgets/progress_center.dart';
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@ import 'package:extended_image/extended_image.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/sources/utils/utils.dart';
|
||||
import 'package:mangayomi/views/manga/reader/providers/push_router.dart';
|
||||
import 'package:mangayomi/services/get_chapter_url.dart';
|
||||
import 'package:mangayomi/utils/image_detail_info.dart';
|
||||
|
|
@ -16,6 +19,7 @@ import 'package:mangayomi/views/manga/reader/image_view_horizontal.dart';
|
|||
import 'package:mangayomi/views/manga/reader/image_view_vertical.dart';
|
||||
import 'package:mangayomi/views/manga/reader/providers/reader_controller_provider.dart';
|
||||
import 'package:mangayomi/views/manga/reader/widgets/circular_progress_indicator_animate_rotate.dart';
|
||||
import 'package:mangayomi/views/more/settings/reader/reader_screen.dart';
|
||||
import 'package:mangayomi/views/widgets/progress_center.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:photo_view/photo_view_gallery.dart';
|
||||
|
|
@ -141,13 +145,26 @@ class _MangaChapterPageGalleryState
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
bool animatePageTransitions =
|
||||
isar.settings.getSync(227)!.animatePageTransitions!;
|
||||
Duration? _doubleTapAnimationDuration() {
|
||||
int doubleTapAnimationValue =
|
||||
isar.settings.getSync(227)!.doubleTapAnimationSpeed!;
|
||||
if (doubleTapAnimationValue == 0) {
|
||||
return const Duration(milliseconds: 10);
|
||||
} else if (doubleTapAnimationValue == 1) {
|
||||
return const Duration(milliseconds: 800);
|
||||
}
|
||||
return const Duration(milliseconds: 200);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_doubleClickAnimationController = AnimationController(
|
||||
duration: const Duration(milliseconds: 300), vsync: this);
|
||||
duration: _doubleTapAnimationDuration(), vsync: this);
|
||||
|
||||
_scaleAnimationController = AnimationController(
|
||||
duration: const Duration(milliseconds: 300), vsync: this);
|
||||
duration: _doubleTapAnimationDuration(), vsync: this);
|
||||
_animation = Tween(begin: 1.0, end: 2.0).animate(
|
||||
CurvedAnimation(curve: Curves.ease, parent: _scaleAnimationController));
|
||||
_animation.addListener(() => _photoViewController.scale = _animation.value);
|
||||
|
|
@ -202,10 +219,14 @@ class _MangaChapterPageGalleryState
|
|||
index: index,
|
||||
);
|
||||
} else {
|
||||
_itemScrollController.scrollTo(
|
||||
curve: Curves.ease,
|
||||
index: index,
|
||||
duration: Duration(milliseconds: isSlide ? 2 : 150));
|
||||
animatePageTransitions
|
||||
? _itemScrollController.scrollTo(
|
||||
curve: Curves.ease,
|
||||
index: index,
|
||||
duration: Duration(milliseconds: isSlide ? 2 : 150))
|
||||
: _itemScrollController.jumpTo(
|
||||
index: index,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -214,9 +235,11 @@ class _MangaChapterPageGalleryState
|
|||
setState(() {
|
||||
_isZoom = false;
|
||||
});
|
||||
_extendedController.animateToPage(index,
|
||||
duration: Duration(milliseconds: isSlide ? 2 : 150),
|
||||
curve: Curves.ease);
|
||||
animatePageTransitions
|
||||
? _extendedController.animateToPage(index,
|
||||
duration: Duration(milliseconds: isSlide ? 2 : 150),
|
||||
curve: Curves.ease)
|
||||
: _extendedController.jumpToPage(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,10 +252,14 @@ class _MangaChapterPageGalleryState
|
|||
index: index,
|
||||
);
|
||||
} else {
|
||||
_itemScrollController.scrollTo(
|
||||
curve: Curves.ease,
|
||||
index: index,
|
||||
duration: Duration(milliseconds: isSlide ? 2 : 150));
|
||||
animatePageTransitions
|
||||
? _itemScrollController.scrollTo(
|
||||
curve: Curves.ease,
|
||||
index: index,
|
||||
duration: Duration(milliseconds: isSlide ? 2 : 150))
|
||||
: _itemScrollController.jumpTo(
|
||||
index: index,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -241,9 +268,11 @@ class _MangaChapterPageGalleryState
|
|||
setState(() {
|
||||
_isZoom = false;
|
||||
});
|
||||
_extendedController.animateToPage(index.toInt(),
|
||||
duration: Duration(milliseconds: isSlide ? 2 : 150),
|
||||
curve: Curves.ease);
|
||||
animatePageTransitions
|
||||
? _extendedController.animateToPage(index,
|
||||
duration: Duration(milliseconds: isSlide ? 2 : 150),
|
||||
curve: Curves.ease)
|
||||
: _extendedController.jumpToPage(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -418,7 +447,18 @@ class _MangaChapterPageGalleryState
|
|||
? Icons.bookmark
|
||||
: Icons.bookmark_border_outlined)),
|
||||
IconButton(
|
||||
onPressed: () {}, icon: const Icon(Icons.public)),
|
||||
onPressed: () {
|
||||
final manga = widget.chapter.manga.value!;
|
||||
String url = getMangaAPIUrl(manga.source!).isEmpty
|
||||
? manga.link!
|
||||
: "${getMangaBaseUrl(manga.source!)}${manga.link!}";
|
||||
Map<String, String> data = {
|
||||
'url': url,
|
||||
'source': manga.source!,
|
||||
};
|
||||
context.push("/mangawebview", extra: data);
|
||||
},
|
||||
icon: const Icon(Icons.public)),
|
||||
],
|
||||
backgroundColor: _backgroundColor(context),
|
||||
),
|
||||
|
|
@ -611,8 +651,7 @@ class _MangaChapterPageGalleryState
|
|||
width: 7,
|
||||
),
|
||||
Text(
|
||||
widget.readerController
|
||||
.getReaderModeValue(readerMode),
|
||||
getReaderModeName(readerMode),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import 'package:mangayomi/models/chapter.dart';
|
|||
import 'package:mangayomi/models/history.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'reader_controller_provider.g.dart';
|
||||
|
||||
|
|
@ -51,18 +51,6 @@ class ReaderController extends _$ReaderController {
|
|||
return isar.settings.getSync(227)!.defaultReaderMode;
|
||||
}
|
||||
|
||||
String getReaderModeValue(ReaderMode readerMode) {
|
||||
return readerMode == ReaderMode.vertical
|
||||
? 'Vertical'
|
||||
: readerMode == ReaderMode.verticalContinuous
|
||||
? 'Verical continuous'
|
||||
: readerMode == ReaderMode.ltr
|
||||
? 'Left to Right'
|
||||
: readerMode == ReaderMode.rtl
|
||||
? 'Right to Left'
|
||||
: 'Webtoon';
|
||||
}
|
||||
|
||||
void setReaderMode(ReaderMode newReaderMode) {
|
||||
List<PersonalReaderMode>? personalReaderModeLists = [];
|
||||
for (var personalReaderMode in getIsarSetting().personalReaderModeList!) {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class CurrentIndexProvider
|
|||
}
|
||||
}
|
||||
|
||||
String _$readerControllerHash() => r'cffb8dfcfd338288d90757414d579fffcd478d29';
|
||||
String _$readerControllerHash() => r'f4d0d66cf65887527b59bb10feaab80cccdcb59a';
|
||||
|
||||
abstract class _$ReaderController extends BuildlessAutoDisposeNotifier<void> {
|
||||
late final Chapter chapter;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/category.dart';
|
||||
import 'package:mangayomi/views/more/settings/categoties/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/views/more/settings/categoties/widgets/custom_textfield.dart';
|
||||
import 'package:mangayomi/views/more/categoties/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/views/more/categoties/widgets/custom_textfield.dart';
|
||||
import 'package:mangayomi/views/widgets/progress_center.dart';
|
||||
|
||||
class CategoriesScreen extends ConsumerStatefulWidget {
|
||||
89
lib/views/more/settings/browse/browse_screen.dart
Normal file
89
lib/views/more/settings/browse/browse_screen.dart
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/views/more/settings/browse/providers/browse_state_provider.dart';
|
||||
|
||||
class BrowseSScreen extends ConsumerWidget {
|
||||
const BrowseSScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final showNSFWS = ref.watch(showNSFWStateProvider);
|
||||
final onlyIncludePinnedSource =
|
||||
ref.watch(onlyIncludePinnedSourceStateProvider);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Browse"),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Global search",
|
||||
style: TextStyle(
|
||||
fontSize: 13, color: primaryColor(context))),
|
||||
],
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: onlyIncludePinnedSource,
|
||||
title: const Text("Only inclued pinned sources"),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(onlyIncludePinnedSourceStateProvider.notifier)
|
||||
.set(value);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("NSFW (18+) sources",
|
||||
style: TextStyle(
|
||||
fontSize: 13, color: primaryColor(context))),
|
||||
],
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: showNSFWS,
|
||||
title: const Text("Show in sources and extensions lists"),
|
||||
onChanged: (value) {
|
||||
ref.read(showNSFWStateProvider.notifier).set(value);
|
||||
}),
|
||||
ListTile(
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.info_outline_rounded,
|
||||
color: secondaryColor(context),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
"This does not prevent unofficial or potentially incorrectly flagged extensions from surfacing NSFW (18+) content within the app",
|
||||
style: TextStyle(
|
||||
fontSize: 11, color: secondaryColor(context))),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'browse_state_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
class OnlyIncludePinnedSourceState extends _$OnlyIncludePinnedSourceState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.onlyIncludePinnedSources!;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(() =>
|
||||
isar.settings.putSync(settings!..onlyIncludePinnedSources = value));
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class ShowNSFWState extends _$ShowNSFWState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.showNSFW!;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(() => isar.settings.putSync(settings!..showNSFW = value));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'browse_state_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$onlyIncludePinnedSourceStateHash() =>
|
||||
r'77c4bff96e186c4bce0a5c312871ceec88a269d0';
|
||||
|
||||
/// See also [OnlyIncludePinnedSourceState].
|
||||
@ProviderFor(OnlyIncludePinnedSourceState)
|
||||
final onlyIncludePinnedSourceStateProvider =
|
||||
AutoDisposeNotifierProvider<OnlyIncludePinnedSourceState, bool>.internal(
|
||||
OnlyIncludePinnedSourceState.new,
|
||||
name: r'onlyIncludePinnedSourceStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$onlyIncludePinnedSourceStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$OnlyIncludePinnedSourceState = AutoDisposeNotifier<bool>;
|
||||
String _$showNSFWStateHash() => r'fdb147ceef80a95066adc64ee63237fbdb3de81e';
|
||||
|
||||
/// See also [ShowNSFWState].
|
||||
@ProviderFor(ShowNSFWState)
|
||||
final showNSFWStateProvider =
|
||||
AutoDisposeNotifierProvider<ShowNSFWState, bool>.internal(
|
||||
ShowNSFWState.new,
|
||||
name: r'showNSFWStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$showNSFWStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$ShowNSFWState = AutoDisposeNotifier<bool>;
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
78
lib/views/more/settings/general/general_screen.dart
Normal file
78
lib/views/more/settings/general/general_screen.dart
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/media_query.dart';
|
||||
|
||||
class GeneralScreen extends ConsumerWidget {
|
||||
const GeneralScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("General"),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"App language",
|
||||
),
|
||||
content: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: 1,
|
||||
itemBuilder: (context, index) {
|
||||
return RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: index,
|
||||
groupValue: 0,
|
||||
onChanged: (value) {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: const Row(
|
||||
children: [Text("English")],
|
||||
),
|
||||
);
|
||||
},
|
||||
)),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style:
|
||||
TextStyle(color: primaryColor(context)),
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
title: const Text(
|
||||
"App language",
|
||||
style: TextStyle(),
|
||||
),
|
||||
subtitle: Text(
|
||||
"English",
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'reader_state_provider.g.dart';
|
||||
|
||||
@riverpod
|
||||
class DefaultReadingModeState extends _$DefaultReadingModeState {
|
||||
@override
|
||||
ReaderMode build() {
|
||||
return isar.settings.getSync(227)!.defaultReaderMode;
|
||||
}
|
||||
|
||||
void set(ReaderMode value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..defaultReaderMode = value));
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class AnimatePageTransitionsState extends _$AnimatePageTransitionsState {
|
||||
@override
|
||||
bool build() {
|
||||
return isar.settings.getSync(227)!.animatePageTransitions!;
|
||||
}
|
||||
|
||||
void set(bool value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(
|
||||
() => isar.settings.putSync(settings!..animatePageTransitions = value));
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class DoubleTapAnimationSpeedState extends _$DoubleTapAnimationSpeedState {
|
||||
@override
|
||||
int build() {
|
||||
return isar.settings.getSync(227)!.doubleTapAnimationSpeed!;
|
||||
}
|
||||
|
||||
void set(int value) {
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = value;
|
||||
isar.writeTxnSync(() =>
|
||||
isar.settings.putSync(settings!..doubleTapAnimationSpeed = value));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'reader_state_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$defaultReadingModeStateHash() =>
|
||||
r'2fe1d264041dd115bcc1a8c5648d0062a19f4c44';
|
||||
|
||||
/// See also [DefaultReadingModeState].
|
||||
@ProviderFor(DefaultReadingModeState)
|
||||
final defaultReadingModeStateProvider =
|
||||
AutoDisposeNotifierProvider<DefaultReadingModeState, ReaderMode>.internal(
|
||||
DefaultReadingModeState.new,
|
||||
name: r'defaultReadingModeStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$defaultReadingModeStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$DefaultReadingModeState = AutoDisposeNotifier<ReaderMode>;
|
||||
String _$animatePageTransitionsStateHash() =>
|
||||
r'c8fdb2acb7a551c41a54c1aa14e378f6b1edd5c1';
|
||||
|
||||
/// See also [AnimatePageTransitionsState].
|
||||
@ProviderFor(AnimatePageTransitionsState)
|
||||
final animatePageTransitionsStateProvider =
|
||||
AutoDisposeNotifierProvider<AnimatePageTransitionsState, bool>.internal(
|
||||
AnimatePageTransitionsState.new,
|
||||
name: r'animatePageTransitionsStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$animatePageTransitionsStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$AnimatePageTransitionsState = AutoDisposeNotifier<bool>;
|
||||
String _$doubleTapAnimationSpeedStateHash() =>
|
||||
r'd88657a8a587a0a77b6230a7fe5b2c1b833afca8';
|
||||
|
||||
/// See also [DoubleTapAnimationSpeedState].
|
||||
@ProviderFor(DoubleTapAnimationSpeedState)
|
||||
final doubleTapAnimationSpeedStateProvider =
|
||||
AutoDisposeNotifierProvider<DoubleTapAnimationSpeedState, int>.internal(
|
||||
DoubleTapAnimationSpeedState.new,
|
||||
name: r'doubleTapAnimationSpeedStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$doubleTapAnimationSpeedStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$DoubleTapAnimationSpeedState = AutoDisposeNotifier<int>;
|
||||
// ignore_for_file: unnecessary_raw_strings, subtype_of_sealed_class, invalid_use_of_internal_member, do_not_use_environment, prefer_const_constructors, public_member_api_docs, avoid_private_typedef_functions
|
||||
183
lib/views/more/settings/reader/reader_screen.dart
Normal file
183
lib/views/more/settings/reader/reader_screen.dart
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/utils/colors.dart';
|
||||
import 'package:mangayomi/utils/media_query.dart';
|
||||
import 'package:mangayomi/views/more/settings/reader/providers/reader_state_provider.dart';
|
||||
|
||||
class ReaderScreen extends ConsumerWidget {
|
||||
const ReaderScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final defaultReadingMode = ref.watch(defaultReadingModeStateProvider);
|
||||
final animatePageTransitions =
|
||||
ref.watch(animatePageTransitionsStateProvider);
|
||||
final doubleTapAnimationSpeed =
|
||||
ref.watch(doubleTapAnimationSpeedStateProvider);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("Reader"),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"Default reading mode",
|
||||
),
|
||||
content: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: ReaderMode.values.length,
|
||||
itemBuilder: (context, index) {
|
||||
return RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: ReaderMode.values[index],
|
||||
groupValue: defaultReadingMode,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(defaultReadingModeStateProvider
|
||||
.notifier)
|
||||
.set(value!);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: Row(
|
||||
children: [
|
||||
Text(getReaderModeName(
|
||||
ReaderMode.values[index]))
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style:
|
||||
TextStyle(color: primaryColor(context)),
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
title: const Text(
|
||||
"Default reading mode",
|
||||
style: TextStyle(),
|
||||
),
|
||||
subtitle: Text(
|
||||
getReaderModeName(defaultReadingMode),
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
"Double tap animation speed",
|
||||
),
|
||||
content: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: 3,
|
||||
itemBuilder: (context, index) {
|
||||
return RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: index,
|
||||
groupValue: doubleTapAnimationSpeed,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(doubleTapAnimationSpeedStateProvider
|
||||
.notifier)
|
||||
.set(value!);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: Row(
|
||||
children: [
|
||||
Text(getAnimationSpeedName(index))
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
)),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style:
|
||||
TextStyle(color: primaryColor(context)),
|
||||
)),
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
title: const Text(
|
||||
"Double tap animation speed",
|
||||
style: TextStyle(),
|
||||
),
|
||||
subtitle: Text(
|
||||
getAnimationSpeedName(doubleTapAnimationSpeed),
|
||||
style: TextStyle(fontSize: 11, color: secondaryColor(context)),
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
value: animatePageTransitions,
|
||||
title: const Text("Animate page transitions"),
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(animatePageTransitionsStateProvider.notifier)
|
||||
.set(value);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String getReaderModeName(ReaderMode readerMode) {
|
||||
return readerMode == ReaderMode.vertical
|
||||
? 'Vertical'
|
||||
: readerMode == ReaderMode.verticalContinuous
|
||||
? 'Verical continuous'
|
||||
: readerMode == ReaderMode.ltr
|
||||
? 'Left to Right'
|
||||
: readerMode == ReaderMode.rtl
|
||||
? 'Right to Left'
|
||||
: 'Webtoon';
|
||||
}
|
||||
|
||||
String getAnimationSpeedName(int type) {
|
||||
return type == 0
|
||||
? 'No animation'
|
||||
: type == 1
|
||||
? 'Normal'
|
||||
: "Fast";
|
||||
}
|
||||
|
|
@ -17,27 +17,27 @@ class SettingsScreen extends StatelessWidget {
|
|||
title: 'General',
|
||||
subtitle: 'App language',
|
||||
icon: Icons.tune_rounded,
|
||||
onTap: () {}),
|
||||
onTap: () => context.push('/general')),
|
||||
ListTileWidget(
|
||||
title: 'Appearance',
|
||||
subtitle: 'Theme',
|
||||
icon: Icons.color_lens_rounded,
|
||||
onTap: () => context.push('/appearance')),
|
||||
ListTileWidget(
|
||||
title: 'Library',
|
||||
subtitle: 'Categories',
|
||||
icon: Icons.collections_bookmark_rounded,
|
||||
onTap: () {}),
|
||||
// ListTileWidget(
|
||||
// title: 'Library',
|
||||
// subtitle: 'Categories',
|
||||
// icon: Icons.collections_bookmark_rounded,
|
||||
// onTap: () {}),
|
||||
ListTileWidget(
|
||||
title: 'Reader',
|
||||
subtitle: 'Reading mode, display, navigation',
|
||||
icon: Icons.chrome_reader_mode_rounded,
|
||||
onTap: () {}),
|
||||
onTap: () => context.push('/readerMode')),
|
||||
ListTileWidget(
|
||||
title: 'Browse',
|
||||
subtitle: 'Sources, extensions, global search',
|
||||
subtitle: 'Sources, global search',
|
||||
icon: Icons.explore_rounded,
|
||||
onTap: () {}),
|
||||
onTap: () => context.push('/browseS')),
|
||||
ListTileWidget(
|
||||
onTap: () {
|
||||
context.push('/about');
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mangayomi/views/more/settings/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/providers/incognito_mode_state_provider.dart';
|
||||
import 'package:mangayomi/views/more/widgets/list_tile_widget.dart';
|
||||
|
||||
class IncognitoModeWidget extends ConsumerWidget {
|
||||
|
|
|
|||
Loading…
Reference in a new issue