This commit is contained in:
NBA2K1 2025-07-13 01:24:14 +02:00
parent 7a5c25b94f
commit 00462f3066
16 changed files with 293 additions and 238 deletions

View file

@ -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 (_) {}
});
}

View file

@ -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(() {
@ -54,11 +54,11 @@ class _BrowseScreenState extends ConsumerState<BrowseScreen>
@override
void dispose() {
_tabBarController.dispose();
_textEditingController.dispose();
super.dispose();
}
final _textEditingController = TextEditingController();
bool _isSearch = false;
@override
Widget build(BuildContext context) {

View file

@ -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(

View file

@ -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)!;

View file

@ -33,6 +33,7 @@ class HistoryScreen extends ConsumerStatefulWidget {
class _HistoryScreenState extends ConsumerState<HistoryScreen>
with TickerProviderStateMixin {
final _textEditingController = TextEditingController();
late TabController _tabBarController;
int tabs = 3;
@ -53,11 +54,11 @@ class _HistoryScreenState extends ConsumerState<HistoryScreen>
@override
void dispose() {
_tabBarController.dispose();
_textEditingController.dispose();
super.dispose();
}
final _textEditingController = TextEditingController();
bool _isSearch = false;
List<History> entriesData = [];
@override

View file

@ -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) {

View file

@ -116,6 +116,7 @@ class _MangaHomeScreenState extends ConsumerState<MangaHomeScreen> {
@override
void dispose() {
_scrollController.dispose();
_textEditingController.dispose();
super.dispose();
}

View file

@ -83,6 +83,12 @@ class _DoubleColummViewState extends State<DoubleColummView>
});
}
@override
void dispose() {
_scaleAnimationController.dispose();
super.dispose();
}
void _toggleScale(Offset tapPosition) {
if (mounted) {
setState(() {

View file

@ -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(

View file

@ -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)!;

View file

@ -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(),
),
),
);

View file

@ -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

View file

@ -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(),
),
);
}

View file

@ -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;
@ -122,8 +116,13 @@ class _UpdatesScreenState extends ConsumerState<UpdatesScreen>
@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);
}
@ -132,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,
),
],
),
),
);

View file

@ -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) {

View file

@ -212,4 +212,5 @@ Future<void> customDraggableTabBar({
),
);
}
tabBarController.dispose();
}