mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 15:57:25 +00:00
Add buttons for adding pages
This commit is contained in:
@@ -269,12 +269,19 @@ class _MySliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AppTabBar extends StatefulWidget {
|
class AppTabBar extends StatefulWidget {
|
||||||
const AppTabBar({super.key, this.controller, required this.tabs});
|
const AppTabBar({
|
||||||
|
super.key,
|
||||||
|
this.controller,
|
||||||
|
required this.tabs,
|
||||||
|
this.actionButton,
|
||||||
|
});
|
||||||
|
|
||||||
final TabController? controller;
|
final TabController? controller;
|
||||||
|
|
||||||
final List<Tab> tabs;
|
final List<Tab> tabs;
|
||||||
|
|
||||||
|
final Widget? actionButton;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<AppTabBar> createState() => _AppTabBarState();
|
State<AppTabBar> createState() => _AppTabBarState();
|
||||||
}
|
}
|
||||||
@@ -378,7 +385,8 @@ class _AppTabBarState extends State<AppTabBar> {
|
|||||||
painter: painter,
|
painter: painter,
|
||||||
child: _TabRow(
|
child: _TabRow(
|
||||||
callback: _tabLayoutCallback,
|
callback: _tabLayoutCallback,
|
||||||
children: List.generate(widget.tabs.length, buildTab),
|
children: List.generate(widget.tabs.length, buildTab)
|
||||||
|
..addIfNotNull(widget.actionButton?.padding(tabPadding)),
|
||||||
),
|
),
|
||||||
).paddingHorizontal(4),
|
).paddingHorizontal(4),
|
||||||
);
|
);
|
||||||
@@ -396,7 +404,8 @@ class _AppTabBarState extends State<AppTabBar> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: widget.tabs.isEmpty ? const SizedBox() : child);
|
child: widget.tabs.isEmpty ? const SizedBox() : child,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
int? previousIndex;
|
int? previousIndex;
|
||||||
@@ -633,7 +642,6 @@ class _TabViewBodyState extends State<TabViewBody> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SearchBarController {
|
class SearchBarController {
|
||||||
_SearchBarMixin? _state;
|
_SearchBarMixin? _state;
|
||||||
|
|
||||||
@@ -906,3 +914,42 @@ class _SearchBarState extends State<AppSearchBar> with _SearchBarMixin {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TabActionButton extends StatelessWidget {
|
||||||
|
const TabActionButton({
|
||||||
|
super.key,
|
||||||
|
required this.icon,
|
||||||
|
required this.text,
|
||||||
|
required this.onPressed,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Icon icon;
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
|
||||||
|
final void Function() onPressed;
|
||||||
|
|
||||||
|
static const _kTabHeight = 46.0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return InkWell(
|
||||||
|
onTap: onPressed,
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: Container(
|
||||||
|
height: _kTabHeight,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
|
child: IconTheme(
|
||||||
|
data: IconThemeData(size: 20, color: context.colorScheme.primary),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
icon,
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(text, style: ts.withColor(context.colorScheme.primary)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -3,36 +3,72 @@ import 'package:venera/components/components.dart';
|
|||||||
import 'package:venera/foundation/app.dart';
|
import 'package:venera/foundation/app.dart';
|
||||||
import 'package:venera/foundation/appdata.dart';
|
import 'package:venera/foundation/appdata.dart';
|
||||||
import 'package:venera/foundation/comic_source/comic_source.dart';
|
import 'package:venera/foundation/comic_source/comic_source.dart';
|
||||||
import 'package:venera/foundation/state_controller.dart';
|
|
||||||
import 'package:venera/pages/ranking_page.dart';
|
import 'package:venera/pages/ranking_page.dart';
|
||||||
import 'package:venera/pages/search_result_page.dart';
|
import 'package:venera/pages/search_result_page.dart';
|
||||||
|
import 'package:venera/pages/settings/settings_page.dart';
|
||||||
|
import 'package:venera/utils/ext.dart';
|
||||||
import 'package:venera/utils/translations.dart';
|
import 'package:venera/utils/translations.dart';
|
||||||
|
|
||||||
import 'category_comics_page.dart';
|
import 'category_comics_page.dart';
|
||||||
|
|
||||||
class CategoriesPage extends StatelessWidget {
|
class CategoriesPage extends StatefulWidget {
|
||||||
const CategoriesPage({super.key});
|
const CategoriesPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
State<CategoriesPage> createState() => _CategoriesPageState();
|
||||||
return StateBuilder<SimpleController>(
|
}
|
||||||
tag: "category",
|
|
||||||
init: SimpleController(),
|
class _CategoriesPageState extends State<CategoriesPage> {
|
||||||
builder: (controller) {
|
var categories = <String>[];
|
||||||
var categories = List.from(appdata.settings["categories"]);
|
|
||||||
|
void onSettingsChanged() {
|
||||||
|
var categories =
|
||||||
|
List.from(appdata.settings["categories"]).whereType<String>().toList();
|
||||||
var allCategories = ComicSource.all()
|
var allCategories = ComicSource.all()
|
||||||
.map((e) => e.categoryData?.key)
|
.map((e) => e.categoryData?.key)
|
||||||
.where((element) => element != null)
|
.where((element) => element != null)
|
||||||
.map((e) => e!)
|
.map((e) => e!)
|
||||||
.toList();
|
.toList();
|
||||||
categories = categories
|
categories =
|
||||||
.where((element) => allCategories.contains(element))
|
categories.where((element) => allCategories.contains(element)).toList();
|
||||||
.toList();
|
if (!categories.isEqualsTo(this.categories)) {
|
||||||
|
setState(() {
|
||||||
|
this.categories = categories;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(categories.isEmpty) {
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
var categories =
|
||||||
|
List.from(appdata.settings["categories"]).whereType<String>().toList();
|
||||||
|
var allCategories = ComicSource.all()
|
||||||
|
.map((e) => e.categoryData?.key)
|
||||||
|
.where((element) => element != null)
|
||||||
|
.map((e) => e!)
|
||||||
|
.toList();
|
||||||
|
this.categories =
|
||||||
|
categories.where((element) => allCategories.contains(element)).toList();
|
||||||
|
appdata.settings.addListener(onSettingsChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPage() {
|
||||||
|
showPopUpWidget(App.rootContext, setCategoryPagesWidget());
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
super.dispose();
|
||||||
|
appdata.settings.removeListener(onSettingsChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (categories.isEmpty) {
|
||||||
var msg = "No Category Pages".tl;
|
var msg = "No Category Pages".tl;
|
||||||
msg += '\n';
|
msg += '\n';
|
||||||
if(ComicSource.isEmpty) {
|
if (ComicSource.isEmpty) {
|
||||||
msg += "Add a comic source in home page".tl;
|
msg += "Add a comic source in home page".tl;
|
||||||
} else {
|
} else {
|
||||||
msg += "Please check your settings".tl;
|
msg += "Please check your settings".tl;
|
||||||
@@ -40,7 +76,7 @@ class CategoriesPage extends StatelessWidget {
|
|||||||
return NetworkError(
|
return NetworkError(
|
||||||
message: msg,
|
message: msg,
|
||||||
retry: () {
|
retry: () {
|
||||||
controller.update();
|
setState(() {});
|
||||||
},
|
},
|
||||||
withAppbar: false,
|
withAppbar: false,
|
||||||
);
|
);
|
||||||
@@ -66,18 +102,21 @@ class CategoriesPage extends StatelessWidget {
|
|||||||
key: Key(e),
|
key: Key(e),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
actionButton: TabActionButton(
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
text: "Add".tl,
|
||||||
|
onPressed: addPage,
|
||||||
|
),
|
||||||
).paddingTop(context.padding.top),
|
).paddingTop(context.padding.top),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
children:
|
children: categories.map((e) => _CategoryPage(e)).toList(),
|
||||||
categories.map((e) => _CategoryPage(e)).toList()),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ import 'package:venera/foundation/comic_source/comic_source.dart';
|
|||||||
import 'package:venera/foundation/res.dart';
|
import 'package:venera/foundation/res.dart';
|
||||||
import 'package:venera/foundation/state_controller.dart';
|
import 'package:venera/foundation/state_controller.dart';
|
||||||
import 'package:venera/pages/search_result_page.dart';
|
import 'package:venera/pages/search_result_page.dart';
|
||||||
|
import 'package:venera/pages/settings/settings_page.dart';
|
||||||
import 'package:venera/utils/ext.dart';
|
import 'package:venera/utils/ext.dart';
|
||||||
import 'package:venera/utils/translations.dart';
|
import 'package:venera/utils/translations.dart';
|
||||||
|
|
||||||
@@ -56,6 +57,10 @@ class _ExplorePageState extends State<ExplorePage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addPage() {
|
||||||
|
showPopUpWidget(App.rootContext, setExplorePagesWidget());
|
||||||
|
}
|
||||||
|
|
||||||
NaviPaneState? naviPane;
|
NaviPaneState? naviPane;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -141,6 +146,11 @@ class _ExplorePageState extends State<ExplorePage>
|
|||||||
key: PageStorageKey(pages.toString()),
|
key: PageStorageKey(pages.toString()),
|
||||||
tabs: pages.map((e) => buildTab(e)).toList(),
|
tabs: pages.map((e) => buildTab(e)).toList(),
|
||||||
controller: controller,
|
controller: controller,
|
||||||
|
actionButton: TabActionButton(
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
text: "Add".tl,
|
||||||
|
onPressed: addPage,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
).paddingTop(context.padding.top);
|
).paddingTop(context.padding.top);
|
||||||
|
|
||||||
|
@@ -30,35 +30,11 @@ class _ExploreSettingsState extends State<ExploreSettings> {
|
|||||||
).toSliver(),
|
).toSliver(),
|
||||||
_PopupWindowSetting(
|
_PopupWindowSetting(
|
||||||
title: "Explore Pages".tl,
|
title: "Explore Pages".tl,
|
||||||
builder: () {
|
builder: setExplorePagesWidget,
|
||||||
var pages = <String, String>{};
|
|
||||||
for (var c in ComicSource.all()) {
|
|
||||||
for (var page in c.explorePages) {
|
|
||||||
pages[page.title] = page.title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _MultiPagesFilter(
|
|
||||||
title: "Explore Pages".tl,
|
|
||||||
settingsIndex: "explore_pages",
|
|
||||||
pages: pages,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).toSliver(),
|
).toSliver(),
|
||||||
_PopupWindowSetting(
|
_PopupWindowSetting(
|
||||||
title: "Category Pages".tl,
|
title: "Category Pages".tl,
|
||||||
builder: () {
|
builder: setCategoryPagesWidget,
|
||||||
var pages = <String, String>{};
|
|
||||||
for (var c in ComicSource.all()) {
|
|
||||||
if (c.categoryData != null) {
|
|
||||||
pages[c.categoryData!.key] = c.categoryData!.title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _MultiPagesFilter(
|
|
||||||
title: "Category Pages".tl,
|
|
||||||
settingsIndex: "categories",
|
|
||||||
pages: pages,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).toSliver(),
|
).toSliver(),
|
||||||
_PopupWindowSetting(
|
_PopupWindowSetting(
|
||||||
title: "Network Favorite Pages".tl,
|
title: "Network Favorite Pages".tl,
|
||||||
@@ -205,3 +181,31 @@ class _ManageBlockingWordViewState extends State<_ManageBlockingWordView> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget setExplorePagesWidget() {
|
||||||
|
var pages = <String, String>{};
|
||||||
|
for (var c in ComicSource.all()) {
|
||||||
|
for (var page in c.explorePages) {
|
||||||
|
pages[page.title] = page.title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _MultiPagesFilter(
|
||||||
|
title: "Explore Pages".tl,
|
||||||
|
settingsIndex: "explore_pages",
|
||||||
|
pages: pages,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget setCategoryPagesWidget() {
|
||||||
|
var pages = <String, String>{};
|
||||||
|
for (var c in ComicSource.all()) {
|
||||||
|
if (c.categoryData != null) {
|
||||||
|
pages[c.categoryData!.key] = c.categoryData!.title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _MultiPagesFilter(
|
||||||
|
title: "Category Pages".tl,
|
||||||
|
settingsIndex: "categories",
|
||||||
|
pages: pages,
|
||||||
|
);
|
||||||
|
}
|
Reference in New Issue
Block a user