feat: clean fav

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-01-27 13:26:31 +08:00
parent caee40a5d9
commit 1d8e469a46
35 changed files with 148 additions and 107 deletions

View File

@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void showConfirmDialog({
required BuildContext context,
required String title,
String? content,
required VoidCallback onConfirm,
}) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(title),
content: content == null ? null : Text(content),
actions: [
TextButton(
onPressed: Get.back,
child: Text(
'取消',
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
TextButton(
onPressed: onConfirm,
child: Text('确认'),
),
],
);
},
);
}

View File

@@ -182,6 +182,8 @@ class Api {
static const String deleteFolder = '/x/v3/fav/folder/del'; static const String deleteFolder = '/x/v3/fav/folder/del';
static const String cleanFav = '/x/v3/fav/resource/clean';
/// 收藏夹 详情 /// 收藏夹 详情
/// media_id 当前收藏夹id 搜索全部时为默认收藏夹id /// media_id 当前收藏夹id 搜索全部时为默认收藏夹id
/// pn int 当前页 /// pn int 当前页

View File

@@ -62,6 +62,27 @@ class UserHttp {
} }
} }
static Future cleanFav({
required dynamic mediaId,
}) async {
var res = await Request().post(
Api.cleanFav,
data: {
'media_id': mediaId,
'platform': 'web',
'csrf': await Request.getCsrf(),
},
options: Options(
contentType: Headers.formUrlEncodedContentType,
),
);
if (res.data['code'] == 0) {
return {'status': true, 'data': res.data['data']};
} else {
return {'status': false, 'msg': res.data['message']};
}
}
static Future deleteFolder({ static Future deleteFolder({
required List<dynamic> mediaIds, required List<dynamic> mediaIds,
}) async { }) async {

View File

@@ -275,6 +275,9 @@ class MyApp extends StatelessWidget {
progressIndicatorTheme: ProgressIndicatorThemeData( progressIndicatorTheme: ProgressIndicatorThemeData(
refreshBackgroundColor: colorScheme.onSecondary, refreshBackgroundColor: colorScheme.onSecondary,
), ),
dialogTheme: DialogTheme(
titleTextStyle: TextStyle(fontSize: 18),
),
); );
} }
} }

View File

@@ -53,7 +53,8 @@ class _AboutPageState extends State<AboutPage> {
TextStyle subTitleStyle = TextStyle subTitleStyle =
TextStyle(fontSize: 13, color: Theme.of(context).colorScheme.outline); TextStyle(fontSize: 13, color: Theme.of(context).colorScheme.outline);
return Scaffold( return Scaffold(
appBar: widget.showAppBar == false ? null : AppBar(title: Text('关于')), appBar:
widget.showAppBar == false ? null : AppBar(title: const Text('关于')),
body: ListView( body: ListView(
children: [ children: [
GestureDetector( GestureDetector(

View File

@@ -156,7 +156,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
Scaffold( Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
title: Text('评论详情'), title: const Text('评论详情'),
titleSpacing: automaticallyImplyLeading ? null : 12, titleSpacing: automaticallyImplyLeading ? null : 12,
automaticallyImplyLeading: automaticallyImplyLeading, automaticallyImplyLeading: automaticallyImplyLeading,
), ),

View File

@@ -309,10 +309,7 @@ class AuthorPanel extends StatelessWidget {
context: context, context: context,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: Text( title: const Text('举报动态'),
'举报动态',
style: TextStyle(fontSize: 18),
),
titlePadding: const EdgeInsets.only(left: 22, top: 16, right: 22), titlePadding: const EdgeInsets.only(left: 22, top: 16, right: 22),
contentPadding: const EdgeInsets.only(top: 5), contentPadding: const EdgeInsets.only(top: 5),
actionsPadding: actionsPadding:

View File

@@ -26,7 +26,7 @@ class _FavPageState extends State<FavPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('我的收藏'), title: const Text('我的收藏'),
actions: [ actions: [
IconButton( IconButton(
onPressed: () { onPressed: () {

View File

@@ -1,3 +1,4 @@
import 'package:PiliPlus/common/widgets/dialog.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/http/user.dart'; import 'package:PiliPlus/http/user.dart';
import 'package:PiliPlus/models/user/fav_folder.dart'; import 'package:PiliPlus/models/user/fav_folder.dart';
@@ -159,23 +160,51 @@ class _FavDetailPageState extends State<FavDetailPage> {
}, },
child: Text('编辑信息'), child: Text('编辑信息'),
), ),
PopupMenuItem(
onTap: () {
UserHttp.cleanFav(mediaId: mediaId)
.then((data) {
if (data['status']) {
SmartDialog.showToast('清除成功');
_favDetailController.onReload();
} else {
SmartDialog.showToast(data['msg']);
}
});
},
child: Text('清除失效内容'),
),
if (!Utils.isDefault( if (!Utils.isDefault(
_favDetailController.item.value.attr ?? _favDetailController.item.value.attr ??
0)) 0))
PopupMenuItem( PopupMenuItem(
onTap: () { onTap: () {
UserHttp.deleteFolder( showConfirmDialog(
mediaIds: [mediaId]).then((data) { context: context,
if (data['status']) { title: '确定删除该收藏夹?',
SmartDialog.showToast('删除成功'); onConfirm: () {
Get.back(result: true); UserHttp.deleteFolder(
} else { mediaIds: [mediaId])
SmartDialog.showToast( .then((data) {
data['msg']); if (data['status']) {
} SmartDialog.showToast('删除成功');
}); Get.back(result: true);
} else {
SmartDialog.showToast(
data['msg']);
}
});
},
);
}, },
child: Text('删除'), child: Text(
'删除',
style: TextStyle(
color: Theme.of(context)
.colorScheme
.error,
),
),
), ),
], ],
) )

View File

@@ -36,7 +36,7 @@ class _HistoryPageState extends State<HistoryPage> {
appBar: AppBarWidget( appBar: AppBarWidget(
visible: _historyController.enableMultiSelect.value, visible: _historyController.enableMultiSelect.value,
child1: AppBar( child1: AppBar(
title: Text('观看记录'), title: const Text('观看记录'),
actions: [ actions: [
IconButton( IconButton(
tooltip: '搜索', tooltip: '搜索',

View File

@@ -145,7 +145,7 @@ class _HtmlRenderPageState extends State<HtmlRenderPage>
Scaffold( Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
title: Text('评论详情'), title: const Text('评论详情'),
titleSpacing: automaticallyImplyLeading ? null : 12, titleSpacing: automaticallyImplyLeading ? null : 12,
automaticallyImplyLeading: automaticallyImplyLeading, automaticallyImplyLeading: automaticallyImplyLeading,
), ),

View File

@@ -1,3 +1,4 @@
import 'package:PiliPlus/common/widgets/dialog.dart';
import 'package:PiliPlus/http/loading_state.dart'; import 'package:PiliPlus/http/loading_state.dart';
import 'package:PiliPlus/models/model_hot_video_item.dart'; import 'package:PiliPlus/models/model_hot_video_item.dart';
import 'package:PiliPlus/pages/common/multi_select_controller.dart'; import 'package:PiliPlus/pages/common/multi_select_controller.dart';
@@ -79,34 +80,18 @@ class LaterController extends MultiSelectController {
} }
// 一键清空 // 一键清空
Future toViewClear(BuildContext context) async { void toViewClear(BuildContext context) {
await showDialog( showConfirmDialog(
context: context, context: context,
builder: (context) { title: '清空确认',
return AlertDialog( content: '确定要清空你的稍后再看列表吗?',
title: const Text('清空确认'), onConfirm: () async {
content: const Text('确定要清空你的稍后再看列表吗?'), var res = await UserHttp.toViewClear();
actions: [ if (res['status']) {
TextButton( loadingState.value = LoadingState.success([]);
onPressed: () => Get.back(), }
child: Text( Get.back();
'取消', SmartDialog.showToast(res['msg']);
style: TextStyle(color: Theme.of(context).colorScheme.outline),
),
),
TextButton(
onPressed: () async {
var res = await UserHttp.toViewClear();
if (res['status']) {
loadingState.value = LoadingState.success([]);
}
Get.back();
SmartDialog.showToast(res['msg']);
},
child: const Text('确认'),
)
],
);
}, },
); );
} }

View File

@@ -313,7 +313,6 @@ class LoginPageController extends GetxController
title: const Text( title: const Text(
"本次登录需要验证您的手机号", "本次登录需要验证您的手机号",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
), ),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,

View File

@@ -276,10 +276,7 @@ class _EditProfilePageState extends State<EditProfilePage> {
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text( title: Text('修改$title'),
'修改$title',
style: TextStyle(fontSize: 18),
),
content: TextField( content: TextField(
controller: _textController, controller: _textController,
minLines: type == ProfileType.uname ? 1 : 4, minLines: type == ProfileType.uname ? 1 : 4,

View File

@@ -53,7 +53,7 @@ class _MemberArchivePageState extends State<MemberArchivePage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('Ta的投稿'), title: const Text('Ta的投稿'),
actions: [ actions: [
Obx( Obx(
() => TextButton.icon( () => TextButton.icon(

View File

@@ -46,7 +46,7 @@ class _MemberDynamicsPageState extends State<MemberDynamicsPage>
super.build(context); super.build(context);
return widget.mid == null return widget.mid == null
? Scaffold( ? Scaffold(
appBar: AppBar(title: Text('Ta的动态')), appBar: AppBar(title: const Text('Ta的动态')),
body: _buildBody, body: _buildBody,
) )
: _buildBody; : _buildBody;

View File

@@ -47,7 +47,7 @@ class _MemberSeasonsPageState extends State<MemberSeasonsPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: Text('Ta的专栏')), appBar: AppBar(title: const Text('Ta的专栏')),
body: Padding( body: Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
left: StyleString.safeSpace, left: StyleString.safeSpace,

View File

@@ -95,7 +95,7 @@ class _LogsPageState extends State<LogsPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('日志'), title: const Text('日志'),
actions: [ actions: [
PopupMenuButton<String>( PopupMenuButton<String>(
onSelected: (String type) { onSelected: (String type) {

View File

@@ -191,7 +191,7 @@ class _PlaySpeedPageState extends State<PlaySpeedPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('倍速设置'), title: const Text('倍速设置'),
actions: [ actions: [
TextButton( TextButton(
onPressed: () async { onPressed: () async {

View File

@@ -23,7 +23,9 @@ class _PlaySettingState extends State<PlaySetting> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: widget.showAppBar == false ? null : AppBar(title: Text('播放器设置')), appBar: widget.showAppBar == false
? null
: AppBar(title: const Text('播放器设置')),
body: ListView( body: ListView(
children: [ children: [
...playSettings.map((item) => item.widget), ...playSettings.map((item) => item.widget),

View File

@@ -9,7 +9,7 @@ class PrivacySetting extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: showAppBar == false ? null : AppBar(title: Text('隐私设置')), appBar: showAppBar == false ? null : AppBar(title: const Text('隐私设置')),
body: ListView( body: ListView(
children: [ children: [
...privacySettings.map((item) => item.widget), ...privacySettings.map((item) => item.widget),

View File

@@ -9,7 +9,7 @@ class RecommendSetting extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: showAppBar == false ? null : AppBar(title: Text('推荐流设置')), appBar: showAppBar == false ? null : AppBar(title: const Text('推荐流设置')),
body: ListView( body: ListView(
children: [ children: [
...recommendSettings.map((item) => item.widget), ...recommendSettings.map((item) => item.widget),

View File

@@ -9,7 +9,7 @@ class VideoSetting extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: showAppBar == false ? null : AppBar(title: Text('音视频设置')), appBar: showAppBar == false ? null : AppBar(title: const Text('音视频设置')),
body: ListView( body: ListView(
children: [ children: [
...videoSettings.map((item) => item.widget), ...videoSettings.map((item) => item.widget),

View File

@@ -1268,10 +1268,7 @@ List<SettingsModel> get recommendSettings => [
builder: (context) { builder: (context) {
String duration = ''; String duration = '';
return AlertDialog( return AlertDialog(
title: Text( title: const Text('自定义时长'),
'自定义时长',
style: TextStyle(fontSize: 18),
),
content: TextField( content: TextField(
autofocus: true, autofocus: true,
onChanged: (value) => duration = value, onChanged: (value) => duration = value,
@@ -1415,7 +1412,7 @@ List<SettingsModel> get extraSettings => [
context: Get.context!, context: Get.context!,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: Text('检查周期', style: TextStyle(fontSize: 18)), title: const Text('检查周期'),
content: TextFormField( content: TextFormField(
autofocus: true, autofocus: true,
initialValue: dynamicPeriod.toString(), initialValue: dynamicPeriod.toString(),
@@ -1543,7 +1540,7 @@ List<SettingsModel> get extraSettings => [
context: Get.context!, context: Get.context!,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: Text('评论折叠行数', style: TextStyle(fontSize: 18)), title: const Text('评论折叠行数'),
content: TextFormField( content: TextFormField(
autofocus: true, autofocus: true,
initialValue: replyLengthLimit, initialValue: replyLengthLimit,
@@ -1601,7 +1598,7 @@ List<SettingsModel> get extraSettings => [
context: Get.context!, context: Get.context!,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: Text('弹幕行高', style: TextStyle(fontSize: 18)), title: const Text('弹幕行高'),
content: TextFormField( content: TextFormField(
autofocus: true, autofocus: true,
initialValue: danmakuLineHeight, initialValue: danmakuLineHeight,
@@ -1824,10 +1821,7 @@ List<SettingsModel> get extraSettings => [
context: Get.context!, context: Get.context!,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: const Text( title: const Text('自定义参数'),
'自定义参数',
style: TextStyle(fontSize: 18),
),
content: TextField( content: TextField(
autofocus: true, autofocus: true,
onChanged: (value) => param = value, onChanged: (value) => param = value,
@@ -2178,10 +2172,7 @@ SettingsModel getBanwordModel({
context: Get.context!, context: Get.context!,
builder: (context) { builder: (context) {
return AlertDialog( return AlertDialog(
title: Text( title: Text(title),
title,
style: TextStyle(fontSize: 18),
),
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,

View File

@@ -30,10 +30,7 @@ class _MultiSelectDialogState<T> extends State<MultiSelectDialog<T>> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
title: Text( title: Text(widget.title),
widget.title,
style: TextStyle(fontSize: 18),
),
contentPadding: const EdgeInsets.only(top: 12), contentPadding: const EdgeInsets.only(top: 12),
content: StatefulBuilder(builder: (context, StateSetter setState) { content: StatefulBuilder(builder: (context, StateSetter setState) {
return SingleChildScrollView( return SingleChildScrollView(

View File

@@ -107,10 +107,7 @@ class _SelectDialogState<T> extends State<SelectDialog<T>> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
title: Text( title: Text(widget.title),
widget.title,
style: TextStyle(fontSize: 18),
),
contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12), contentPadding: const EdgeInsets.fromLTRB(0, 12, 0, 12),
content: StatefulBuilder(builder: (context, StateSetter setState) { content: StatefulBuilder(builder: (context, StateSetter setState) {
return SingleChildScrollView( return SingleChildScrollView(

View File

@@ -37,10 +37,7 @@ class _SlideDialogState<T extends num> extends State<SlideDialog<T>> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
title: Text( title: Text(widget.title),
widget.title,
style: TextStyle(fontSize: 18),
),
contentPadding: contentPadding:
const EdgeInsets.only(top: 20, left: 8, right: 8, bottom: 8), const EdgeInsets.only(top: 20, left: 8, right: 8, bottom: 8),
content: SizedBox( content: SizedBox(

View File

@@ -49,10 +49,7 @@ class _SetSwitchItemState extends State<SetSwitchItem> {
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
title: Text( title: const Text('确定禁用 SSL 证书验证?'),
'确定禁用 SSL 证书验证?',
style: TextStyle(fontSize: 18),
),
content: const Text('禁用容易受到中间人攻击'), content: const Text('禁用容易受到中间人攻击'),
actions: [ actions: [
TextButton( TextButton(

View File

@@ -21,7 +21,7 @@ class _SubPageState extends State<SubPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar(title: Text('我的订阅')), appBar: AppBar(title: const Text('我的订阅')),
body: CustomScrollView( body: CustomScrollView(
slivers: [ slivers: [
Obx(() => _buildBody(_subController.loadingState.value)), Obx(() => _buildBody(_subController.loadingState.value)),

View File

@@ -1662,10 +1662,7 @@ class VideoDetailController extends GetxController
showDialog( showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
title: const Text( title: const Text('确定无误再提交'),
'确定无误再提交',
style: TextStyle(fontSize: 18),
),
actions: [ actions: [
TextButton( TextButton(
onPressed: Get.back, onPressed: Get.back,

View File

@@ -56,7 +56,7 @@ class _FavPanelState extends State<FavPanel> {
onPressed: Get.back, onPressed: Get.back,
icon: const Icon(Icons.close_outlined), icon: const Icon(Icons.close_outlined),
), ),
title: Text('添加到收藏夹'), title: const Text('添加到收藏夹'),
actions: [ actions: [
TextButton.icon( TextButton.icon(
onPressed: () { onPressed: () {

View File

@@ -94,7 +94,7 @@ class _GroupPanelState extends State<GroupPanel> {
tooltip: '关闭', tooltip: '关闭',
onPressed: Get.back, onPressed: Get.back,
icon: const Icon(Icons.close_outlined)), icon: const Icon(Icons.close_outlined)),
title: Text('设置关注分组'), title: const Text('设置关注分组'),
), ),
Expanded( Expanded(
child: Material( child: Material(

View File

@@ -1826,7 +1826,7 @@ class _VideoDetailPageState extends State<VideoDetailPage>
appBar: AppBar( appBar: AppBar(
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
titleSpacing: 16, titleSpacing: 16,
title: Text('分段信息'), title: const Text('分段信息'),
actions: [ actions: [
Text( Text(
'分段进度条', '分段进度条',

View File

@@ -659,10 +659,7 @@ class _HeaderControlState extends State<HeaderControl> {
builder: (context) { builder: (context) {
String duration = ''; String duration = '';
return AlertDialog( return AlertDialog(
title: Text( title: const Text('自定义时长'),
'自定义时长',
style: TextStyle(fontSize: 18),
),
content: TextField( content: TextField(
autofocus: true, autofocus: true,
onChanged: (value) => duration = value, onChanged: (value) => duration = value,

View File

@@ -49,7 +49,7 @@ class PiliScheme {
() => Scaffold( () => Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
title: Text('评论详情'), title: const Text('评论详情'),
actions: [ actions: [
IconButton( IconButton(
tooltip: '前往原视频', tooltip: '前往原视频',
@@ -133,7 +133,7 @@ class PiliScheme {
() => Scaffold( () => Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
title: Text('评论详情'), title: const Text('评论详情'),
actions: [ actions: [
IconButton( IconButton(
tooltip: '前往', tooltip: '前往',
@@ -173,7 +173,7 @@ class PiliScheme {
() => Scaffold( () => Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
title: Text('评论详情'), title: const Text('评论详情'),
actions: [ actions: [
IconButton( IconButton(
tooltip: '前往', tooltip: '前往',