mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-20 15:02:07 +00:00
commit
539fd186cb
26 changed files with 401 additions and 249 deletions
|
|
@ -410,10 +410,19 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
_currentPositionSub.cancel();
|
||||
_currentTotalDurationSub.cancel();
|
||||
_completed.cancel();
|
||||
_video.dispose();
|
||||
_playbackSpeed.dispose();
|
||||
_isDoubleSpeed.dispose();
|
||||
_currentTotalDuration.dispose();
|
||||
_showFitLabel.dispose();
|
||||
_isCompleted.dispose();
|
||||
_tempPosition.dispose();
|
||||
_fit.dispose();
|
||||
if (!_isDesktop) {
|
||||
_setLandscapeMode(false);
|
||||
}
|
||||
_skipPhase.dispose();
|
||||
_currentPosition.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -498,7 +507,12 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage>
|
|||
selected,
|
||||
),
|
||||
onTap: () async {
|
||||
if (_video.value?.videoTrack?.id == quality.videoTrack?.id) {
|
||||
Navigator.pop(context);
|
||||
return;
|
||||
}
|
||||
_video.value = quality;
|
||||
_player.stop();
|
||||
if (quality.isLocal) {
|
||||
if (widget.isLocal) {
|
||||
_player.setVideoTrack(quality.videoTrack!);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class _MobileControllerWidgetState
|
|||
);
|
||||
final ValueNotifier<double> _brightnessValue = ValueNotifier(0.0);
|
||||
final ValueNotifier<bool> _brightnessIndicator = ValueNotifier(false);
|
||||
StreamSubscription<double>? _brightnessSubscription;
|
||||
Timer? _brightnessTimer;
|
||||
|
||||
final ValueNotifier<double> _volumeValue = ValueNotifier(0.0);
|
||||
|
|
@ -127,6 +128,15 @@ class _MobileControllerWidgetState
|
|||
for (final subscription in subscriptions) {
|
||||
subscription.cancel();
|
||||
}
|
||||
_timer?.cancel();
|
||||
_volumeTimer?.cancel();
|
||||
_brightnessTimer?.cancel();
|
||||
_volumeValue.dispose();
|
||||
_volumeIndicator.dispose();
|
||||
_brightnessValue.dispose();
|
||||
_brightnessIndicator.dispose();
|
||||
_brightnessSubscription?.cancel();
|
||||
_volumeController.removeListener();
|
||||
|
||||
// package:screen_brightness
|
||||
Future.microtask(() async {
|
||||
|
|
@ -134,7 +144,6 @@ class _MobileControllerWidgetState
|
|||
await ScreenBrightness.instance.resetApplicationScreenBrightness();
|
||||
} catch (_) {}
|
||||
});
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -240,13 +249,14 @@ class _MobileControllerWidgetState
|
|||
Future.microtask(() async {
|
||||
try {
|
||||
_brightnessValue.value = await ScreenBrightness.instance.application;
|
||||
ScreenBrightness.instance.onApplicationScreenBrightnessChanged.listen((
|
||||
value,
|
||||
) {
|
||||
if (mounted) {
|
||||
_brightnessValue.value = value;
|
||||
}
|
||||
});
|
||||
_brightnessSubscription = ScreenBrightness
|
||||
.instance
|
||||
.onApplicationScreenBrightnessChanged
|
||||
.listen((value) {
|
||||
if (mounted) {
|
||||
_brightnessValue.value = value;
|
||||
}
|
||||
});
|
||||
} catch (_) {}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ class BrowseScreen extends ConsumerStatefulWidget {
|
|||
|
||||
class _BrowseScreenState extends ConsumerState<BrowseScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late final hideItems = ref.watch(hideItemsStateProvider);
|
||||
late final hideItems = ref.read(hideItemsStateProvider);
|
||||
final _textEditingController = TextEditingController();
|
||||
late TabController _tabBarController;
|
||||
|
||||
late final _tabList = [
|
||||
|
|
@ -35,10 +36,9 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
|
|||
];
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabBarController = TabController(length: _tabList.length, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
_tabBarController.addListener(() {
|
||||
_chekPermission();
|
||||
setState(() {
|
||||
|
|
@ -52,7 +52,13 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
|
|||
await StorageProvider().requestPermission();
|
||||
}
|
||||
|
||||
final _textEditingController = TextEditingController();
|
||||
@override
|
||||
void dispose() {
|
||||
_tabBarController.dispose();
|
||||
_textEditingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool _isSearch = false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:json_view/json_view.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
|
@ -59,13 +61,14 @@ class _CodeEditorPageState extends ConsumerState<CodeEditorPage> {
|
|||
[],
|
||||
);
|
||||
late final _logStreamController = Logger.logStreamController;
|
||||
late final StreamSubscription _logSubscription;
|
||||
final _scrollController = ScrollController();
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller.text = source?.sourceCode ?? "";
|
||||
useLogger = true;
|
||||
_logStreamController.stream.asBroadcastStream().listen((event) async {
|
||||
_logSubscription = _logStreamController.stream.listen((event) async {
|
||||
_logsNotifier.value.add(event);
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 5));
|
||||
|
|
@ -133,11 +136,12 @@ class _CodeEditorPageState extends ConsumerState<CodeEditorPage> {
|
|||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_logSubscription.cancel();
|
||||
_logsNotifier.value.clear();
|
||||
_scrollController.dispose();
|
||||
_controller.dispose();
|
||||
useLogger = false;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@ class _ExtensionScreenState extends ConsumerState<ExtensionScreen> {
|
|||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _updateSource(Source source) {
|
||||
return ref.read(
|
||||
fetchItemSourcesListProvider(
|
||||
|
|
|
|||
|
|
@ -298,6 +298,13 @@ class EditTextDialogWidget extends StatefulWidget {
|
|||
|
||||
class _EditTextDialogWidgetState extends State<EditTextDialogWidget> {
|
||||
late final _controller = TextEditingController(text: widget.text);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class _GlobalSearchScreenState extends ConsumerState<GlobalSearchScreen> {
|
|||
String query = "";
|
||||
final _textEditingController = TextEditingController();
|
||||
late final List<Source> sourceList =
|
||||
ref.watch(onlyIncludePinnedSourceStateProvider)
|
||||
ref.read(onlyIncludePinnedSourceStateProvider)
|
||||
? isar.sources
|
||||
.filter()
|
||||
.isPinnedEqualTo(true)
|
||||
|
|
@ -97,6 +97,12 @@ class _GlobalSearchScreenState extends ConsumerState<GlobalSearchScreen> {
|
|||
: Container(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textEditingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class SourceSearchScreen extends StatefulWidget {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ class SourcesScreen extends ConsumerStatefulWidget {
|
|||
|
||||
class _SourcesScreenState extends ConsumerState<SourcesScreen> {
|
||||
final controller = ScrollController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class HistoryScreen extends ConsumerStatefulWidget {
|
|||
|
||||
class _HistoryScreenState extends ConsumerState<HistoryScreen>
|
||||
with TickerProviderStateMixin {
|
||||
final _textEditingController = TextEditingController();
|
||||
late TabController _tabBarController;
|
||||
int tabs = 3;
|
||||
|
||||
|
|
@ -51,7 +52,13 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen>
|
|||
_tabBarController.addListener(tabListener);
|
||||
}
|
||||
|
||||
final _textEditingController = TextEditingController();
|
||||
@override
|
||||
void dispose() {
|
||||
_tabBarController.dispose();
|
||||
_textEditingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool _isSearch = false;
|
||||
List<History> entriesData = [];
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -71,6 +71,13 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textEditingController.dispose();
|
||||
tabBarController?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _updateLibrary(List<Manga> mangaList) async {
|
||||
bool isDark = ref.read(themeModeStateProvider);
|
||||
botToast(
|
||||
|
|
|
|||
|
|
@ -89,9 +89,15 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
final offetProvider = StateProvider((ref) => 0.0);
|
||||
bool _expanded = false;
|
||||
ScrollController _scrollController = ScrollController();
|
||||
late final ScrollController _scrollController;
|
||||
late final isLocalArchive = widget.manga!.isLocalArchive ?? false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,12 @@ class _MigrationScreenScreenState extends ConsumerState<MigrationScreen> {
|
|||
.and()
|
||||
.itemTypeEqualTo(widget.manga.itemType)
|
||||
.findAllSync();
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final query = widget.manga.name ?? widget.manga.author ?? "";
|
||||
_textEditingController.text = query;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
@ -68,7 +74,6 @@ class _MigrationScreenScreenState extends ConsumerState<MigrationScreen> {
|
|||
final query = _query.isNotEmpty
|
||||
? _query
|
||||
: widget.manga.name ?? widget.manga.author ?? "";
|
||||
_textEditingController.text = query;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
@ -126,6 +131,12 @@ class _MigrationScreenScreenState extends ConsumerState<MigrationScreen> {
|
|||
: Container(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textEditingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
class MigrationSourceSearchScreen extends StatefulWidget {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,13 @@ class _TrackerWidgetSearchState extends ConsumerState<TrackerWidgetSearch> {
|
|||
}
|
||||
|
||||
late final _controller = TextEditingController(text: query);
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool _isLoading = true;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -114,6 +114,13 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
|
|||
return mangaRes;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scrollController.dispose();
|
||||
_textEditingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
late final _textEditingController = TextEditingController(text: widget.query);
|
||||
late String _query = widget.query;
|
||||
late bool _isSearch = widget.isSearch;
|
||||
|
|
|
|||
|
|
@ -182,6 +182,12 @@ class SeachFormTextFieldWidget extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _SeachFormTextFieldWidgetState extends State<SeachFormTextFieldWidget> {
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
late final _controller = TextEditingController(text: widget.text);
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
|||
|
|
@ -83,6 +83,12 @@ class _DoubleColummViewState extends State<DoubleColummView>
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_scaleAnimationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _toggleScale(Offset tapPosition) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
|
|
|
|||
|
|
@ -145,7 +145,15 @@ class _MangaChapterPageGalleryState
|
|||
|
||||
_rebuildDetail.close();
|
||||
_doubleClickAnimationController.dispose();
|
||||
_scaleAnimationController.dispose();
|
||||
_failedToLoadImage.dispose();
|
||||
_autoScroll.value = false;
|
||||
_autoScroll.dispose();
|
||||
_autoScrollPage.dispose();
|
||||
_itemPositionsListener.itemPositions.removeListener(_readProgressListener);
|
||||
_photoViewController.dispose();
|
||||
_photoViewScaleStateController.dispose();
|
||||
_extendedController.dispose();
|
||||
clearGestureDetailsCache();
|
||||
if (isDesktop) {
|
||||
setFullScreen(value: false);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@ class _ChapterListWidgetState extends State<ChapterListWidget> {
|
|||
_jumpTo();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _jumpTo() async {
|
||||
await Future.delayed(const Duration(milliseconds: 5));
|
||||
controller.jumpTo(
|
||||
|
|
|
|||
|
|
@ -29,6 +29,12 @@ class _DownloadFileScreenState extends ConsumerState<DownloadFileScreen> {
|
|||
final List<int> _bytes = [];
|
||||
late StreamSubscription<List<int>>? _subscription;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_subscription?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
|
|
|
|||
|
|
@ -24,33 +24,38 @@ class CategoriesScreen extends ConsumerStatefulWidget {
|
|||
class _CategoriesScreenState extends ConsumerState<CategoriesScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late TabController _tabBarController;
|
||||
int tabs = 3;
|
||||
late final List<String> _tabList;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabBarController = TabController(length: tabs, vsync: this);
|
||||
final hideItems = ref.read(hideItemsStateProvider);
|
||||
_tabList = [
|
||||
if (!hideItems.contains("/MangaLibrary")) "/MangaLibrary",
|
||||
if (!hideItems.contains("/AnimeLibrary")) "/AnimeLibrary",
|
||||
if (!hideItems.contains("/NovelLibrary")) "/NovelLibrary",
|
||||
];
|
||||
_tabBarController = TabController(length: _tabList.length, vsync: this);
|
||||
_tabBarController.animateTo(widget.data.$2);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tabBarController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int newTabs = 0;
|
||||
final hideItems = ref.watch(hideItemsStateProvider);
|
||||
if (!hideItems.contains("/MangaLibrary")) newTabs++;
|
||||
if (!hideItems.contains("/AnimeLibrary")) newTabs++;
|
||||
if (!hideItems.contains("/NovelLibrary")) newTabs++;
|
||||
if (tabs != newTabs) {
|
||||
_tabBarController.dispose();
|
||||
_tabBarController = TabController(length: newTabs, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
setState(() {
|
||||
tabs = newTabs;
|
||||
});
|
||||
if (_tabList.isEmpty) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(context.l10n.categories)),
|
||||
body: Center(child: Text("EMPTY\nMPTY\nMTY\nMT\n\n")),
|
||||
);
|
||||
}
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return DefaultTabController(
|
||||
animationDuration: Duration.zero,
|
||||
length: newTabs,
|
||||
length: _tabList.length,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
|
|
@ -62,23 +67,24 @@ class _CategoriesScreenState extends ConsumerState<CategoriesScreen>
|
|||
bottom: TabBar(
|
||||
indicatorSize: TabBarIndicatorSize.label,
|
||||
controller: _tabBarController,
|
||||
tabs: [
|
||||
if (!hideItems.contains("/MangaLibrary")) Tab(text: l10n.manga),
|
||||
if (!hideItems.contains("/AnimeLibrary")) Tab(text: l10n.anime),
|
||||
if (!hideItems.contains("/NovelLibrary")) Tab(text: l10n.novel),
|
||||
],
|
||||
tabs: _tabList.map((route) {
|
||||
if (route == "/MangaLibrary") return Tab(text: l10n.manga);
|
||||
if (route == "/AnimeLibrary") return Tab(text: l10n.anime);
|
||||
return Tab(text: l10n.novel);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
body: TabBarView(
|
||||
controller: _tabBarController,
|
||||
children: [
|
||||
if (!hideItems.contains("/MangaLibrary"))
|
||||
CategoriesTab(itemType: ItemType.manga),
|
||||
if (!hideItems.contains("/AnimeLibrary"))
|
||||
CategoriesTab(itemType: ItemType.anime),
|
||||
if (!hideItems.contains("/NovelLibrary"))
|
||||
CategoriesTab(itemType: ItemType.novel),
|
||||
],
|
||||
children: _tabList.map((route) {
|
||||
if (route == "/MangaLibrary") {
|
||||
return CategoriesTab(itemType: ItemType.manga);
|
||||
}
|
||||
if (route == "/AnimeLibrary") {
|
||||
return CategoriesTab(itemType: ItemType.anime);
|
||||
}
|
||||
return CategoriesTab(itemType: ItemType.novel);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,12 @@ class _TrackingDetailState extends State<TrackingDetail>
|
|||
void initState() {
|
||||
super.initState();
|
||||
_tabBarController = TabController(length: 2, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tabBarController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
|||
|
|
@ -15,17 +15,19 @@ class StatisticsScreen extends ConsumerStatefulWidget {
|
|||
|
||||
class _StatisticsScreenState extends ConsumerState<StatisticsScreen>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final hideItems = ref.read(hideItemsStateProvider);
|
||||
late final List<String> hideItems;
|
||||
late TabController _tabController;
|
||||
late final List<String> _tabList;
|
||||
|
||||
late final _tabList = [
|
||||
if (!hideItems.contains("/MangaLibrary")) 'manga',
|
||||
if (!hideItems.contains("/AnimeLibrary")) 'anime',
|
||||
if (!hideItems.contains("/NovelLibrary")) 'novel',
|
||||
];
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
void initState() {
|
||||
super.initState();
|
||||
hideItems = ref.read(hideItemsStateProvider);
|
||||
_tabList = [
|
||||
if (!hideItems.contains("/MangaLibrary")) "/MangaLibrary",
|
||||
if (!hideItems.contains("/AnimeLibrary")) "/AnimeLibrary",
|
||||
if (!hideItems.contains("/NovelLibrary")) "/NovelLibrary",
|
||||
];
|
||||
_tabController = TabController(length: _tabList.length, vsync: this);
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +40,10 @@ class _StatisticsScreenState extends ConsumerState<StatisticsScreen>
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_tabList.isEmpty) {
|
||||
return SizedBox.shrink();
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(context.l10n.statistics)),
|
||||
body: Center(child: Text("EMPTY\nMPTY\nMTY\nMT\n\n")),
|
||||
);
|
||||
}
|
||||
final l10n = context.l10n;
|
||||
return Scaffold(
|
||||
|
|
@ -46,23 +51,24 @@ class _StatisticsScreenState extends ConsumerState<StatisticsScreen>
|
|||
title: Text(l10n.statistics),
|
||||
bottom: TabBar(
|
||||
controller: _tabController,
|
||||
tabs: [
|
||||
if (!hideItems.contains("/MangaLibrary")) Tab(text: "Manga"),
|
||||
if (!hideItems.contains("/AnimeLibrary")) Tab(text: "Anime"),
|
||||
if (!hideItems.contains("/NovelLibrary")) Tab(text: "Novel"),
|
||||
],
|
||||
tabs: _tabList.map((route) {
|
||||
if (route == "/MangaLibrary") return Tab(text: l10n.manga);
|
||||
if (route == "/AnimeLibrary") return Tab(text: l10n.anime);
|
||||
return Tab(text: l10n.novel);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
body: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
if (!hideItems.contains("/MangaLibrary"))
|
||||
_buildStatisticsTab(itemType: ItemType.manga),
|
||||
if (!hideItems.contains("/AnimeLibrary"))
|
||||
_buildStatisticsTab(itemType: ItemType.anime),
|
||||
if (!hideItems.contains("/NovelLibrary"))
|
||||
_buildStatisticsTab(itemType: ItemType.novel),
|
||||
],
|
||||
children: _tabList.map((route) {
|
||||
if (route == "/MangaLibrary") {
|
||||
return _buildStatisticsTab(itemType: ItemType.manga);
|
||||
}
|
||||
if (route == "/AnimeLibrary") {
|
||||
return _buildStatisticsTab(itemType: ItemType.anime);
|
||||
}
|
||||
return _buildStatisticsTab(itemType: ItemType.novel);
|
||||
}).toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ class _TrackerLibraryScreenState extends ConsumerState<TrackerLibraryScreen> {
|
|||
List<TrackLibrarySection> _sections = [];
|
||||
List<TrackPreference> _preferences = [];
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textEditingController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
|
|
|
|||
|
|
@ -34,8 +34,9 @@ class UpdatesScreen extends ConsumerStatefulWidget {
|
|||
class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
||||
with TickerProviderStateMixin {
|
||||
late TabController _tabBarController;
|
||||
late final List<String> _tabList;
|
||||
late final List<String> hideItems;
|
||||
bool _isLoading = false;
|
||||
int tabs = 3;
|
||||
Future<void> _updateLibrary() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
|
|
@ -92,13 +93,6 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
|||
);
|
||||
}
|
||||
}
|
||||
await Future.doWhile(() async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
if (mangaList.length == numbers) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
BotToast.cleanAll();
|
||||
setState(() {
|
||||
_isLoading = false;
|
||||
|
|
@ -112,11 +106,23 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textEditingController.dispose();
|
||||
_tabBarController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabBarController = TabController(length: tabs, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
hideItems = ref.read(hideItemsStateProvider);
|
||||
_tabList = [
|
||||
if (!hideItems.contains("/MangaLibrary")) "/MangaLibrary",
|
||||
if (!hideItems.contains("/AnimeLibrary")) "/AnimeLibrary",
|
||||
if (!hideItems.contains("/NovelLibrary")) "/NovelLibrary",
|
||||
];
|
||||
_tabBarController = TabController(length: _tabList.length, vsync: this);
|
||||
_tabBarController.addListener(tabListener);
|
||||
}
|
||||
|
||||
|
|
@ -125,174 +131,152 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
|
|||
List<History> entriesData = [];
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int newTabs = 0;
|
||||
final hideItems = ref.watch(hideItemsStateProvider);
|
||||
if (!hideItems.contains("/MangaLibrary")) newTabs++;
|
||||
if (!hideItems.contains("/AnimeLibrary")) newTabs++;
|
||||
if (!hideItems.contains("/NovelLibrary")) newTabs++;
|
||||
if (newTabs == 0) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
if (tabs != newTabs) {
|
||||
_tabBarController.removeListener(tabListener);
|
||||
_tabBarController.dispose();
|
||||
_tabBarController = TabController(length: newTabs, vsync: this);
|
||||
_tabBarController.animateTo(0);
|
||||
_tabBarController.addListener(tabListener);
|
||||
setState(() {
|
||||
tabs = newTabs;
|
||||
});
|
||||
}
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
return DefaultTabController(
|
||||
animationDuration: Duration.zero,
|
||||
length: newTabs,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
title: _isSearch
|
||||
? null
|
||||
: Text(
|
||||
l10n.updates,
|
||||
style: TextStyle(color: Theme.of(context).hintColor),
|
||||
),
|
||||
actions: [
|
||||
_isSearch
|
||||
? SeachFormTextField(
|
||||
onChanged: (value) {
|
||||
setState(() {});
|
||||
},
|
||||
onSuffixPressed: () {
|
||||
_textEditingController.clear();
|
||||
setState(() {});
|
||||
},
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearch = false;
|
||||
});
|
||||
_textEditingController.clear();
|
||||
},
|
||||
controller: _textEditingController,
|
||||
)
|
||||
: IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearch = true;
|
||||
});
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.search_outlined,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
_updateLibrary();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.refresh_outlined,
|
||||
color: Theme.of(context).hintColor,
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
title: _isSearch
|
||||
? null
|
||||
: Text(
|
||||
l10n.updates,
|
||||
style: TextStyle(color: Theme.of(context).hintColor),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(l10n.remove_everything),
|
||||
content: Text(l10n.remove_all_update_msg),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(l10n.cancel),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
TextButton(
|
||||
onPressed: () => clearUpdates(hideItems, context),
|
||||
child: Text(l10n.ok),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
actions: [
|
||||
_isSearch
|
||||
? SeachFormTextField(
|
||||
onChanged: (value) {
|
||||
setState(() {});
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.delete_sweep_outlined,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
onSuffixPressed: () {
|
||||
_textEditingController.clear();
|
||||
setState(() {});
|
||||
},
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearch = false;
|
||||
});
|
||||
_textEditingController.clear();
|
||||
},
|
||||
controller: _textEditingController,
|
||||
)
|
||||
: IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isSearch = true;
|
||||
});
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.search_outlined,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
_updateLibrary();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.refresh_outlined,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
splashRadius: 20,
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(l10n.remove_everything),
|
||||
content: Text(l10n.remove_all_update_msg),
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(l10n.cancel),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
TextButton(
|
||||
onPressed: () => clearUpdates(hideItems, context),
|
||||
child: Text(l10n.ok),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.delete_sweep_outlined,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
bottom: TabBar(
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
controller: _tabBarController,
|
||||
tabs: [
|
||||
if (!hideItems.contains("/MangaLibrary"))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Tab(text: l10n.manga),
|
||||
const SizedBox(width: 8),
|
||||
_updateNumbers(ref, ItemType.manga),
|
||||
],
|
||||
),
|
||||
if (!hideItems.contains("/AnimeLibrary"))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Tab(text: l10n.anime),
|
||||
const SizedBox(width: 8),
|
||||
_updateNumbers(ref, ItemType.anime),
|
||||
],
|
||||
),
|
||||
if (!hideItems.contains("/NovelLibrary"))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Tab(text: l10n.novel),
|
||||
const SizedBox(width: 8),
|
||||
_updateNumbers(ref, ItemType.novel),
|
||||
],
|
||||
),
|
||||
],
|
||||
bottom: TabBar(
|
||||
indicatorSize: TabBarIndicatorSize.tab,
|
||||
controller: _tabBarController,
|
||||
tabs: [
|
||||
if (!hideItems.contains("/MangaLibrary"))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Tab(text: l10n.manga),
|
||||
const SizedBox(width: 8),
|
||||
_updateNumbers(ref, ItemType.manga),
|
||||
],
|
||||
),
|
||||
if (!hideItems.contains("/AnimeLibrary"))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Tab(text: l10n.anime),
|
||||
const SizedBox(width: 8),
|
||||
_updateNumbers(ref, ItemType.anime),
|
||||
],
|
||||
),
|
||||
if (!hideItems.contains("/NovelLibrary"))
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Tab(text: l10n.novel),
|
||||
const SizedBox(width: 8),
|
||||
_updateNumbers(ref, ItemType.novel),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: TabBarView(
|
||||
controller: _tabBarController,
|
||||
children: [
|
||||
if (!hideItems.contains("/MangaLibrary"))
|
||||
UpdateTab(
|
||||
itemType: ItemType.manga,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading,
|
||||
),
|
||||
if (!hideItems.contains("/AnimeLibrary"))
|
||||
UpdateTab(
|
||||
itemType: ItemType.anime,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading,
|
||||
),
|
||||
if (!hideItems.contains("/NovelLibrary"))
|
||||
UpdateTab(
|
||||
itemType: ItemType.novel,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: TabBarView(
|
||||
controller: _tabBarController,
|
||||
children: [
|
||||
if (!hideItems.contains("/MangaLibrary"))
|
||||
UpdateTab(
|
||||
itemType: ItemType.manga,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading,
|
||||
),
|
||||
if (!hideItems.contains("/AnimeLibrary"))
|
||||
UpdateTab(
|
||||
itemType: ItemType.anime,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading,
|
||||
),
|
||||
if (!hideItems.contains("/NovelLibrary"))
|
||||
UpdateTab(
|
||||
itemType: ItemType.novel,
|
||||
query: _textEditingController.text,
|
||||
isLoading: _isLoading,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,17 @@ class _MangaWebViewState extends ConsumerState<MangaWebView> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (Platform.isLinux) {
|
||||
_desktopWebview?.close();
|
||||
} else {
|
||||
if (browser.isOpened()) browser.close();
|
||||
browser.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Webview? _desktopWebview;
|
||||
_runWebViewDesktop() async {
|
||||
if (Platform.isLinux) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:draggable_menu/draggable_menu.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
|
@ -64,10 +65,8 @@ Future<void> customDraggableTabBar({
|
|||
index = tabBarController.index;
|
||||
if (index != currentIndex) {
|
||||
index = currentIndex;
|
||||
refresh();
|
||||
} else {
|
||||
refresh();
|
||||
}
|
||||
refresh();
|
||||
});
|
||||
|
||||
await showDialog(
|
||||
|
|
@ -79,10 +78,7 @@ Future<void> customDraggableTabBar({
|
|||
for (var i = 0; i < children.length; i++) ...[
|
||||
MeasureWidgetSize(
|
||||
onCalculateSize: (size) {
|
||||
final additionnalHeight = ((List.generate(
|
||||
10000,
|
||||
(index) => index * 0.0001,
|
||||
))..shuffle()).first;
|
||||
final additionnalHeight = Random().nextDouble() * 0.01;
|
||||
double newHeight = size!.height + 52.0 + additionnalHeight;
|
||||
if (!(newHeight <= maxHeight)) {
|
||||
newHeight = maxHeight + additionnalHeight;
|
||||
|
|
@ -212,4 +208,5 @@ Future<void> customDraggableTabBar({
|
|||
),
|
||||
);
|
||||
}
|
||||
tabBarController.dispose();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue