Files
PiliPlus/lib/pages/later/view.dart
bggRGjQaUbCoE 2f4c739f0b opt: enum
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
2025-05-05 15:13:17 +08:00

320 lines
10 KiB
Dart

import 'package:PiliPlus/common/widgets/scroll_physics.dart';
import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/common/later_view_type.dart';
import 'package:PiliPlus/models/model_hot_video_item.dart';
import 'package:PiliPlus/pages/history/view.dart' show AppBarWidget;
import 'package:PiliPlus/pages/later/base_controller.dart';
import 'package:PiliPlus/pages/later/controller.dart';
import 'package:PiliPlus/utils/extension.dart';
import 'package:PiliPlus/utils/request_utils.dart';
import 'package:PiliPlus/utils/storage.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
class LaterPage extends StatefulWidget {
const LaterPage({super.key});
@override
State<LaterPage> createState() => _LaterPageState();
}
class _LaterPageState extends State<LaterPage>
with SingleTickerProviderStateMixin {
final LaterBaseController _baseCtr = Get.put(LaterBaseController());
late final TabController _tabController = TabController(
length: LaterViewType.values.length,
vsync: this,
);
LaterController currCtr([int? index]) {
final type = LaterViewType.values[index ?? _tabController.index];
return Get.put(
LaterController(type),
tag: type.type.toString(),
);
}
final sortKey = GlobalKey();
void listener() {
(sortKey.currentContext as Element?)?.markNeedsBuild();
}
@override
void initState() {
super.initState();
_tabController.addListener(listener);
}
@override
void dispose() {
_tabController
..removeListener(listener)
..dispose();
Get.delete<LaterBaseController>();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Obx(
() => PopScope(
canPop: _baseCtr.enableMultiSelect.value.not,
onPopInvokedWithResult: (didPop, result) {
if (_baseCtr.enableMultiSelect.value) {
currCtr().handleSelect();
}
},
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: _buildAppbar,
floatingActionButton: Obx(
() => currCtr().loadingState.value is Success
? FloatingActionButton.extended(
onPressed: currCtr().toViewPlayAll,
label: const Text('播放全部'),
icon: const Icon(Icons.playlist_play),
)
: const SizedBox.shrink(),
),
body: SafeArea(
top: false,
bottom: false,
child: Column(
children: [
TabBar(
isScrollable: true,
controller: _tabController,
tabAlignment: TabAlignment.start,
tabs: LaterViewType.values.map((item) {
final count = _baseCtr.counts[item];
return Tab(
text: '${item.title}${count != -1 ? '($count)' : ''}');
}).toList(),
onTap: (_) {
if (_tabController.indexIsChanging.not) {
currCtr().scrollController.animToTop();
} else {
if (_baseCtr.enableMultiSelect.value) {
currCtr(_tabController.previousIndex).handleSelect();
}
}
},
),
Expanded(
child: TabBarView(
physics: _baseCtr.enableMultiSelect.value
? const NeverScrollableScrollPhysics()
: const CustomTabBarViewScrollPhysics(),
controller: _tabController,
children:
LaterViewType.values.map((item) => item.page).toList(),
),
),
],
),
),
),
),
);
}
PreferredSizeWidget get _buildAppbar {
final theme = Theme.of(context);
Color color = theme.colorScheme.secondary;
return AppBarWidget(
visible: _baseCtr.enableMultiSelect.value,
child1: AppBar(
title: const Text('稍后再看'),
actions: [
IconButton(
tooltip: '搜索',
onPressed: () {
final mid = Accounts.main.mid;
Get.toNamed(
'/laterSearch',
arguments: {
'type': 0,
'mediaId': mid,
'mid': mid,
'title': '稍后再看',
'count': _baseCtr.counts[LaterViewType.all],
},
);
},
icon: const Icon(Icons.search),
),
Material(
clipBehavior: Clip.hardEdge,
borderRadius: const BorderRadius.all(Radius.circular(20)),
child: Builder(
key: sortKey,
builder: (context) {
final value = currCtr().asc.value;
return PopupMenuButton(
initialValue: value,
tooltip: '排序',
onSelected: (value) {
currCtr()
..asc.value = value
..onReload();
},
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: Text.rich(
TextSpan(
children: [
TextSpan(
text: value ? '最早添加' : '最近添加',
),
WidgetSpan(
child: Icon(
size: 16,
MdiIcons.unfoldMoreHorizontal,
color: color,
),
),
],
style: TextStyle(color: color),
),
),
),
itemBuilder: (BuildContext context) => [
const PopupMenuItem(
value: false,
child: Text('最近添加'),
),
const PopupMenuItem(
value: true,
child: Text('最早添加'),
),
],
);
},
),
),
Material(
clipBehavior: Clip.hardEdge,
borderRadius: const BorderRadius.all(Radius.circular(20)),
child: PopupMenuButton(
tooltip: '清空',
child: Padding(
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: Text.rich(
TextSpan(
children: [
const TextSpan(
text: '清空',
),
WidgetSpan(
child: Icon(
size: 16,
MdiIcons.unfoldMoreHorizontal,
color: color,
),
),
],
style: TextStyle(color: color),
),
),
),
itemBuilder: (BuildContext context) => [
PopupMenuItem(
onTap: () => currCtr().toViewClear(context, 1),
child: const Text('清空失效'),
),
PopupMenuItem(
onTap: () => currCtr().toViewClear(context, 2),
child: const Text('清空看完'),
),
PopupMenuItem(
onTap: () => currCtr().toViewClear(context),
child: const Text('清空全部'),
),
],
),
),
const SizedBox(width: 8),
],
),
child2: AppBar(
leading: IconButton(
tooltip: '取消',
onPressed: currCtr().handleSelect,
icon: const Icon(Icons.close_outlined),
),
title: Obx(
() => Text(
'已选: ${_baseCtr.checkedCount.value}',
),
),
actions: [
TextButton(
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact,
),
onPressed: () => currCtr().handleSelect(true),
child: const Text('全选'),
),
TextButton(
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact,
),
onPressed: () {
final ctr = currCtr();
RequestUtils.onCopyOrMove<Map, HotVideoItemModel>(
context: context,
isCopy: true,
ctr: ctr,
mediaId: null,
mid: ctr.mid,
);
},
child: Text(
'复制',
style: TextStyle(
color: theme.colorScheme.onSurfaceVariant,
),
),
),
TextButton(
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact,
),
onPressed: () {
final ctr = currCtr();
RequestUtils.onCopyOrMove<Map, HotVideoItemModel>(
context: context,
isCopy: false,
ctr: ctr,
mediaId: null,
mid: ctr.mid,
);
},
child: Text(
'移动',
style: TextStyle(
color: theme.colorScheme.onSurfaceVariant,
),
),
),
TextButton(
style: TextButton.styleFrom(
visualDensity: VisualDensity.compact,
),
onPressed: () => currCtr().onDelChecked(context),
child: Text(
'移除',
style: TextStyle(color: theme.colorScheme.error),
),
),
const SizedBox(width: 6),
],
),
);
}
}