pikapika/lib/screens/CategoriesScreen.dart

349 lines
9.3 KiB
Dart
Raw Permalink Normal View History

2021-09-29 23:57:09 +00:00
import 'package:event/event.dart';
import 'package:flutter/material.dart';
import 'package:flutter_search_bar/flutter_search_bar.dart';
2021-11-11 03:00:38 +00:00
import 'package:pikapika/basic/Entities.dart';
2021-11-24 13:22:22 +00:00
import 'package:pikapika/basic/config/ShadowCategoriesEvent.dart';
2022-06-29 19:02:01 +00:00
import 'package:pikapika/basic/config/ShadowCategoriesMode.dart';
2021-11-11 03:00:38 +00:00
import 'package:pikapika/basic/store/Categories.dart';
import 'package:pikapika/basic/config/ShadowCategories.dart';
2022-04-15 16:53:37 +00:00
import 'package:pikapika/screens/ComicCollectionsScreen.dart';
2021-11-11 03:00:38 +00:00
import 'package:pikapika/screens/RankingsScreen.dart';
import 'package:pikapika/screens/SearchScreen.dart';
import 'package:pikapika/screens/components/ContentError.dart';
import 'package:pikapika/basic/Method.dart';
2023-02-16 08:33:16 +00:00
import '../basic/config/Address.dart';
2022-09-05 03:36:25 +00:00
import '../basic/config/CategoriesColumnCount.dart';
2023-01-31 10:50:51 +00:00
import '../basic/config/IconLoading.dart';
2021-09-29 23:57:09 +00:00
import 'ComicsScreen.dart';
import 'GamesScreen.dart';
import 'RandomComicsScreen.dart';
2023-02-16 08:14:29 +00:00
import 'components/Common.dart';
2021-09-29 23:57:09 +00:00
import 'components/ContentLoading.dart';
import 'components/Images.dart';
2023-05-08 09:57:28 +00:00
import 'components/ListView.dart';
2021-09-29 23:57:09 +00:00
// 分类
class CategoriesScreen extends StatefulWidget {
2022-03-17 03:31:25 +00:00
const CategoriesScreen({Key? key}) : super(key: key);
2021-09-29 23:57:09 +00:00
@override
State<StatefulWidget> createState() => _CategoriesScreenState();
}
2021-11-29 03:26:30 +00:00
class _CategoriesScreenState extends State<CategoriesScreen> {
2022-03-19 04:12:27 +00:00
late final SearchBar _searchBar = SearchBar(
2021-09-29 23:57:09 +00:00
hintText: '搜索',
inBar: false,
setState: setState,
onSubmitted: (value) {
if (value.isNotEmpty) {
Navigator.push(
context,
2023-01-31 10:50:51 +00:00
mixRoute(
2021-09-29 23:57:09 +00:00
builder: (context) => SearchScreen(keyword: value),
),
);
}
},
buildDefaultAppBar: (BuildContext context) {
return AppBar(
2022-03-19 04:12:27 +00:00
title: const Text('分类'),
2021-09-29 23:57:09 +00:00
actions: [
2023-04-07 01:56:11 +00:00
commonPopMenu(context),
addressPopMenu(context),
2021-09-29 23:57:09 +00:00
_searchBar.getSearchAction(context),
],
);
},
);
late Future<List<Category>> _categoriesFuture = _fetch();
Future<List<Category>> _fetch() async {
List<Category> categories = await method.categories();
storedCategories = [];
2022-03-17 03:31:25 +00:00
for (var element in categories) {
2021-09-29 23:57:09 +00:00
if (!element.isWeb) {
storedCategories.add(element.title);
}
2022-03-17 03:31:25 +00:00
}
2021-09-29 23:57:09 +00:00
return categories;
}
void _reloadCategories() {
setState(() {
this._categoriesFuture = _fetch();
});
}
@override
void initState() {
shadowCategoriesEvent.subscribe(_onShadowChange);
2022-09-05 03:36:25 +00:00
categoriesColumnCountEvent.subscribe(_setState);
2021-09-29 23:57:09 +00:00
super.initState();
}
@override
void dispose() {
shadowCategoriesEvent.unsubscribe(_onShadowChange);
2022-09-05 03:36:25 +00:00
categoriesColumnCountEvent.unsubscribe(_setState);
2021-09-29 23:57:09 +00:00
super.dispose();
}
void _onShadowChange(EventArgs? args) {
_reloadCategories();
}
2022-09-05 03:36:25 +00:00
_setState(_) {
setState(() {});
}
2021-09-29 23:57:09 +00:00
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var themeBackground = theme.scaffoldBackgroundColor;
var shadeBackground = Color.fromARGB(
0x11,
255 - themeBackground.red,
255 - themeBackground.green,
255 - themeBackground.blue,
);
return Scaffold(
appBar: _searchBar.build(context),
body: Container(
color: shadeBackground,
child: FutureBuilder(
future: _categoriesFuture,
builder:
((BuildContext context, AsyncSnapshot<List<Category>> snapshot) {
if (snapshot.hasError) {
return ContentError(
error: snapshot.error,
stackTrace: snapshot.stackTrace,
onRefresh: () async {
_reloadCategories();
},
);
}
if (snapshot.connectionState != ConnectionState.done) {
2022-03-19 04:12:27 +00:00
return const ContentLoading(label: '加载中');
2021-09-29 23:57:09 +00:00
}
2023-05-08 09:57:28 +00:00
return PikaListView(
2021-09-29 23:57:09 +00:00
children: [
Container(height: 20),
Wrap(
runSpacing: 20,
alignment: WrapAlignment.spaceAround,
children: _buildChannels(),
),
2022-03-19 04:12:27 +00:00
const Divider(),
2021-09-29 23:57:09 +00:00
Wrap(
runSpacing: 20,
alignment: WrapAlignment.spaceAround,
children: _buildCategories(snapshot.data!),
),
Container(height: 20),
],
);
}),
),
),
);
}
List<Widget> _buildCategories(List<Category> cList) {
2022-09-05 03:36:25 +00:00
late double blockSize;
late double imageSize;
late double imageRs;
if (categoriesColumnCount == 0) {
var size = MediaQuery.of(context).size;
var min = size.width < size.height ? size.width : size.height;
2022-10-14 17:54:50 +00:00
blockSize = (min ~/ 3).floorToDouble();
2022-09-05 03:36:25 +00:00
} else {
var size = MediaQuery.of(context).size;
var min = size.width;
2022-10-14 17:54:50 +00:00
blockSize = (min ~/ categoriesColumnCount).floorToDouble();
2022-09-05 03:36:25 +00:00
}
imageSize = blockSize - 15;
imageRs = imageSize / 10;
2021-09-29 23:57:09 +00:00
List<Widget> list = [];
2022-03-25 14:57:30 +00:00
append(Widget widget, String title, Function() onTap) {
2021-09-29 23:57:09 +00:00
list.add(
GestureDetector(
onTap: onTap,
2022-03-17 03:31:25 +00:00
child: SizedBox(
2021-09-29 23:57:09 +00:00
width: blockSize,
child: Column(
children: [
Card(
elevation: .5,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(imageRs)),
child: widget,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(imageRs)),
),
),
Container(height: 5),
Center(
child: Text(title),
),
],
),
),
),
);
2022-03-25 14:57:30 +00:00
}
2021-09-29 23:57:09 +00:00
append(
buildSvg('lib/assets/books.svg', imageSize, imageSize, margin: 20),
"全分类",
() => _navigateToCategory(null),
);
2022-04-15 16:53:37 +00:00
append(
Icon(
Icons.recommend_outlined,
size: imageSize,
color: Colors.grey,
),
"推荐",
() {
Navigator.push(
context,
2023-01-31 10:50:51 +00:00
mixRoute(
2022-04-15 16:53:37 +00:00
builder: (context) => const ComicCollectionsScreen(),
),
);
},
);
2021-09-29 23:57:09 +00:00
for (var i = 0; i < cList.length; i++) {
var c = cList[i];
if (c.isWeb) continue;
2021-11-24 13:22:22 +00:00
switch (currentShadowCategoriesMode()) {
case ShadowCategoriesMode.BLACK_LIST:
if (shadowCategories.contains(c.title)) continue;
break;
case ShadowCategoriesMode.WHITE_LIST:
if (!shadowCategories.contains(c.title)) continue;
break;
}
2021-09-29 23:57:09 +00:00
append(
RemoteImage(
fileServer: c.thumb.fileServer,
path: c.thumb.path,
width: imageSize,
height: imageSize,
),
c.title,
() => _navigateToCategory(c.title),
);
}
return list;
}
List<Widget> _buildChannels() {
2022-09-14 10:15:56 +00:00
late double blockSize;
late double imageSize;
late double imageRs;
if (categoriesColumnCount == 0) {
var size = MediaQuery.of(context).size;
var min = size.width < size.height ? size.width : size.height;
2022-10-14 17:54:50 +00:00
blockSize = (min ~/ 3).floorToDouble();
2022-09-14 10:15:56 +00:00
} else {
var size = MediaQuery.of(context).size;
var min = size.width;
2022-10-14 17:54:50 +00:00
blockSize = (min ~/ categoriesColumnCount).floorToDouble();
2022-09-14 10:15:56 +00:00
}
imageSize = blockSize - 15;
imageRs = imageSize / 10;
2021-09-29 23:57:09 +00:00
List<Widget> list = [];
2022-03-25 14:57:30 +00:00
append(Widget widget, String title, Function() onTap) {
2021-09-29 23:57:09 +00:00
list.add(
GestureDetector(
onTap: onTap,
2022-03-17 03:31:25 +00:00
child: SizedBox(
2021-09-29 23:57:09 +00:00
width: blockSize,
child: Column(
children: [
Card(
elevation: .5,
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(imageRs)),
child: widget,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(imageRs)),
),
),
Container(height: 5),
Center(
child: Text(title),
),
],
),
),
),
);
2022-03-25 14:57:30 +00:00
}
2021-09-29 23:57:09 +00:00
append(
buildSvg('lib/assets/rankings.svg', imageSize, imageSize,
margin: 20, color: Colors.red.shade700),
"排行榜",
() {
Navigator.push(
context,
2023-01-31 10:50:51 +00:00
mixRoute(builder: (context) => const RankingsScreen()),
2021-09-29 23:57:09 +00:00
);
},
);
append(
buildSvg('lib/assets/random.svg', imageSize, imageSize,
margin: 20, color: Colors.orangeAccent.shade700),
"随机本子",
() {
Navigator.push(
context,
2023-01-31 10:50:51 +00:00
mixRoute(builder: (context) => const RandomComicsScreen()),
2021-09-29 23:57:09 +00:00
);
},
);
append(
buildSvg('lib/assets/gamepad.svg', imageSize, imageSize,
margin: 20, color: Colors.blue.shade500),
"游戏专区",
() {
Navigator.push(
context,
2023-01-31 10:50:51 +00:00
mixRoute(builder: (context) => const GamesScreen()),
2021-09-29 23:57:09 +00:00
);
},
);
return list;
}
void _navigateToCategory(String? categoryTitle) {
Navigator.push(
context,
2023-01-31 10:50:51 +00:00
mixRoute(
2021-09-29 23:57:09 +00:00
builder: (context) => ComicsScreen(category: categoryTitle),
),
);
}
}