feat: 收藏夹取消收藏
This commit is contained in:
@ -157,15 +157,12 @@ class VideoHttp {
|
|||||||
|
|
||||||
// (取消)收藏
|
// (取消)收藏
|
||||||
static Future favVideo(
|
static Future favVideo(
|
||||||
{required String aid,
|
{required String aid, String? addIds, String? delIds}) async {
|
||||||
required bool type,
|
|
||||||
required String addIds,
|
|
||||||
required String delIds}) async {
|
|
||||||
var res = await Request().post(Api.favVideo, queryParameters: {
|
var res = await Request().post(Api.favVideo, queryParameters: {
|
||||||
'rid': aid,
|
'rid': aid,
|
||||||
'type': 2,
|
'type': 2,
|
||||||
'add_media_ids': addIds,
|
'add_media_ids': addIds ?? '',
|
||||||
'del_media_ids': delIds,
|
'del_media_ids': delIds ?? '',
|
||||||
'csrf': await Request.getCsrf(),
|
'csrf': await Request.getCsrf(),
|
||||||
});
|
});
|
||||||
if (res.data['code'] == 0) {
|
if (res.data['code'] == 0) {
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
|
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:pilipala/http/user.dart';
|
import 'package:pilipala/http/user.dart';
|
||||||
|
import 'package:pilipala/http/video.dart';
|
||||||
import 'package:pilipala/models/user/fav_detail.dart';
|
import 'package:pilipala/models/user/fav_detail.dart';
|
||||||
import 'package:pilipala/models/user/fav_folder.dart';
|
import 'package:pilipala/models/user/fav_folder.dart';
|
||||||
|
|
||||||
@ -26,4 +28,23 @@ class FavDetailController extends GetxController {
|
|||||||
favDetailData.value = res['data'];
|
favDetailData.value = res['data'];
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCancelFav(int id) async {
|
||||||
|
var result = await VideoHttp.favVideo(
|
||||||
|
aid: id.toString(), addIds: '', delIds: mediaId.toString());
|
||||||
|
if (result['status']) {
|
||||||
|
if (result['data']['prompt']) {
|
||||||
|
List<FavDetailItemData> dataList = favDetailData.value.medias!;
|
||||||
|
for (var i in dataList) {
|
||||||
|
if (i.id == id) {
|
||||||
|
dataList.remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
favDetailData.value.medias = dataList;
|
||||||
|
favDetailData.refresh();
|
||||||
|
SmartDialog.showToast('取消收藏');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -152,12 +152,15 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
|||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(top: 15, bottom: 8, left: 14),
|
padding: const EdgeInsets.only(top: 15, bottom: 8, left: 14),
|
||||||
child: Text(
|
child: Obx(
|
||||||
'共${_favDetailController.item!.mediaCount}条视频',
|
() => Text(
|
||||||
style: TextStyle(
|
'共${_favDetailController.favDetailData.value.medias != null ? _favDetailController.favDetailData.value.medias!.length : '-'}条视频',
|
||||||
fontSize: Theme.of(context).textTheme.labelMedium!.fontSize,
|
style: TextStyle(
|
||||||
color: Theme.of(context).colorScheme.outline,
|
fontSize:
|
||||||
letterSpacing: 1),
|
Theme.of(context).textTheme.labelMedium!.fontSize,
|
||||||
|
color: Theme.of(context).colorScheme.outline,
|
||||||
|
letterSpacing: 1),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,14 +1,18 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pilipala/common/constants.dart';
|
import 'package:pilipala/common/constants.dart';
|
||||||
import 'package:pilipala/common/widgets/stat/up.dart';
|
import 'package:pilipala/common/widgets/stat/danmu.dart';
|
||||||
import 'package:pilipala/common/widgets/stat/view.dart';
|
import 'package:pilipala/common/widgets/stat/view.dart';
|
||||||
import 'package:pilipala/utils/utils.dart';
|
import 'package:pilipala/utils/utils.dart';
|
||||||
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
import 'package:pilipala/common/widgets/network_img_layer.dart';
|
||||||
|
|
||||||
|
import '../controller.dart';
|
||||||
|
|
||||||
// 收藏视频卡片 - 水平布局
|
// 收藏视频卡片 - 水平布局
|
||||||
class FavVideoCardH extends StatelessWidget {
|
class FavVideoCardH extends StatelessWidget {
|
||||||
var videoItem;
|
var videoItem;
|
||||||
|
final FavDetailController _favDetailController =
|
||||||
|
Get.put(FavDetailController());
|
||||||
|
|
||||||
FavVideoCardH({Key? key, required this.videoItem}) : super(key: key);
|
FavVideoCardH({Key? key, required this.videoItem}) : super(key: key);
|
||||||
|
|
||||||
@ -16,75 +20,99 @@ class FavVideoCardH extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
int id = videoItem.id;
|
int id = videoItem.id;
|
||||||
String heroTag = Utils.makeHeroTag(id);
|
String heroTag = Utils.makeHeroTag(id);
|
||||||
return InkWell(
|
return Dismissible(
|
||||||
onTap: () async {
|
movementDuration: const Duration(milliseconds: 300),
|
||||||
await Future.delayed(const Duration(milliseconds: 200));
|
background: Container(
|
||||||
Get.toNamed('/video?aid=$id',
|
decoration: BoxDecoration(
|
||||||
arguments: {'videoItem': videoItem, 'heroTag': heroTag});
|
color: Theme.of(context).colorScheme.errorContainer,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: const [
|
||||||
|
Icon(Icons.clear_all_rounded),
|
||||||
|
SizedBox(width: 6),
|
||||||
|
Text('取消收藏')
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
direction: DismissDirection.endToStart,
|
||||||
|
key: ValueKey<int>(videoItem.id),
|
||||||
|
onDismissed: (DismissDirection direction) {
|
||||||
|
_favDetailController.onCancelFav(videoItem.id);
|
||||||
|
// widget.onDeleteNotice();
|
||||||
},
|
},
|
||||||
child: Column(
|
child: InkWell(
|
||||||
children: [
|
onTap: () async {
|
||||||
Padding(
|
await Future.delayed(const Duration(milliseconds: 200));
|
||||||
padding: const EdgeInsets.fromLTRB(12, 5, 12, 5),
|
Get.toNamed('/video?aid=$id',
|
||||||
child: LayoutBuilder(
|
arguments: {'videoItem': videoItem, 'heroTag': heroTag});
|
||||||
builder: (context, boxConstraints) {
|
},
|
||||||
double width =
|
child: Column(
|
||||||
(boxConstraints.maxWidth - StyleString.cardSpace * 6) / 2;
|
children: [
|
||||||
return SizedBox(
|
Padding(
|
||||||
height: width / StyleString.aspectRatio,
|
padding: const EdgeInsets.fromLTRB(12, 5, 12, 5),
|
||||||
child: Row(
|
child: LayoutBuilder(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
builder: (context, boxConstraints) {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
double width =
|
||||||
children: [
|
(boxConstraints.maxWidth - StyleString.cardSpace * 6) / 2;
|
||||||
AspectRatio(
|
return SizedBox(
|
||||||
aspectRatio: StyleString.aspectRatio,
|
height: width / StyleString.aspectRatio,
|
||||||
child: LayoutBuilder(
|
child: Row(
|
||||||
builder: (context, boxConstraints) {
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
double maxWidth = boxConstraints.maxWidth;
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
double maxHeight = boxConstraints.maxHeight;
|
children: [
|
||||||
double PR = MediaQuery.of(context).devicePixelRatio;
|
AspectRatio(
|
||||||
return Stack(
|
aspectRatio: StyleString.aspectRatio,
|
||||||
children: [
|
child: LayoutBuilder(
|
||||||
Hero(
|
builder: (context, boxConstraints) {
|
||||||
tag: heroTag,
|
double maxWidth = boxConstraints.maxWidth;
|
||||||
child: NetworkImgLayer(
|
double maxHeight = boxConstraints.maxHeight;
|
||||||
// src: videoItem['pic'] +
|
double PR =
|
||||||
// '@${(maxWidth * 2).toInt()}w',
|
MediaQuery.of(context).devicePixelRatio;
|
||||||
src: videoItem.pic + '@.webp',
|
return Stack(
|
||||||
width: maxWidth,
|
children: [
|
||||||
height: maxHeight,
|
Hero(
|
||||||
),
|
tag: heroTag,
|
||||||
),
|
child: NetworkImgLayer(
|
||||||
// Image.network( videoItem['pic'], width: double.infinity, height: double.infinity,),
|
// src: videoItem['pic'] +
|
||||||
Positioned(
|
// '@${(maxWidth * 2).toInt()}w',
|
||||||
right: 4,
|
src: videoItem.pic + '@.webp',
|
||||||
bottom: 4,
|
width: maxWidth,
|
||||||
child: Container(
|
height: maxHeight,
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 1, horizontal: 6),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(4),
|
|
||||||
color: Colors.black54.withOpacity(0.4)),
|
|
||||||
child: Text(
|
|
||||||
Utils.timeFormat(videoItem.duration!),
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 11, color: Colors.white),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
// Image.network( videoItem['pic'], width: double.infinity, height: double.infinity,),
|
||||||
],
|
Positioned(
|
||||||
);
|
right: 4,
|
||||||
},
|
bottom: 4,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 1, horizontal: 6),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(4),
|
||||||
|
color:
|
||||||
|
Colors.black54.withOpacity(0.4)),
|
||||||
|
child: Text(
|
||||||
|
Utils.timeFormat(videoItem.duration!),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 11, color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
VideoContent(videoItem: videoItem)
|
||||||
VideoContent(videoItem: videoItem)
|
],
|
||||||
],
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -112,7 +140,6 @@ class VideoContent extends StatelessWidget {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
const SizedBox(height: 4),
|
|
||||||
Text(
|
Text(
|
||||||
videoItem.owner.name,
|
videoItem.owner.name,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -127,12 +154,7 @@ class VideoContent extends StatelessWidget {
|
|||||||
view: videoItem.cntInfo['play'],
|
view: videoItem.cntInfo['play'],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Text(
|
StatDanMu(theme: 'gray', danmu: videoItem.cntInfo['danmaku'])
|
||||||
Utils.dateFormat(videoItem.pubdate!),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 11,
|
|
||||||
color: Theme.of(context).colorScheme.outline),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@ -186,7 +186,6 @@ class VideoIntroController extends GetxController {
|
|||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
var result = await VideoHttp.favVideo(
|
var result = await VideoHttp.favVideo(
|
||||||
aid: aid,
|
aid: aid,
|
||||||
type: true,
|
|
||||||
addIds: addMediaIdsNew.join(','),
|
addIds: addMediaIdsNew.join(','),
|
||||||
delIds: delMediaIdsNew.join(','));
|
delIds: delMediaIdsNew.join(','));
|
||||||
if (result['status']) {
|
if (result['status']) {
|
||||||
|
|||||||
Reference in New Issue
Block a user