opt view later

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-06-07 15:00:21 +08:00
parent 13f1392821
commit e3c920dc87
16 changed files with 182 additions and 125 deletions

View File

@@ -1,6 +1,7 @@
import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/http/user.dart';
import 'package:PiliPlus/utils/download.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -9,12 +10,31 @@ import 'package:get/get.dart';
void imageSaveDialog({
required String? title,
required String? cover,
dynamic aid,
String? bvid,
}) {
final double imgWidth = Get.mediaQuery.size.shortestSide - 8 * 2;
SmartDialog.show(
animationType: SmartAnimationType.centerScale_otherSlide,
builder: (context) {
final theme = Theme.of(context);
late final iconColor = theme.colorScheme.onSurfaceVariant;
Widget iconBtn({
String? tooltip,
required IconData icon,
required VoidCallback? onPressed,
}) {
return iconButton(
context: context,
onPressed: onPressed,
iconSize: 20,
icon: icon,
bgColor: Colors.transparent,
iconColor: iconColor,
);
}
return Container(
width: imgWidth,
margin: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
@@ -66,28 +86,36 @@ void imageSaveDialog({
padding: const EdgeInsets.fromLTRB(12, 10, 8, 10),
child: Row(
children: [
if (title != null)
Expanded(
child: SelectableText(
title ?? '',
title,
style: theme.textTheme.titleSmall,
),
)
else
const Spacer(),
if (aid != null || bvid != null)
iconBtn(
tooltip: '稍后再看',
onPressed: () => {
SmartDialog.dismiss(),
UserHttp.toViewLater(aid: aid, bvid: bvid).then(
(res) => SmartDialog.showToast(res['msg']),
),
},
icon: Icons.watch_later_outlined,
),
if (cover?.isNotEmpty == true) ...[
const SizedBox(width: 4),
iconButton(
context: context,
iconBtn(
tooltip: '分享',
onPressed: () {
SmartDialog.dismiss();
DownloadUtils.onShareImg(cover!);
},
iconSize: 20,
icon: Icons.share,
bgColor: Colors.transparent,
iconColor: theme.colorScheme.onSurfaceVariant,
),
iconButton(
context: context,
iconBtn(
tooltip: '保存封面图',
onPressed: () async {
bool saveStatus = await DownloadUtils.downloadImg(
@@ -98,10 +126,7 @@ void imageSaveDialog({
SmartDialog.dismiss();
}
},
iconSize: 20,
icon: Icons.download,
bgColor: Colors.transparent,
iconColor: theme.colorScheme.onSurfaceVariant,
),
],
],

View File

@@ -59,6 +59,7 @@ class VideoCardH extends StatelessWidget {
child: InkWell(
onLongPress: onLongPress ??
() => imageSaveDialog(
bvid: videoItem.bvid,
title: videoItem.title,
cover: videoItem.cover,
),

View File

@@ -108,6 +108,7 @@ class VideoCardV extends StatelessWidget {
onLongPress: () => imageSaveDialog(
title: videoItem.title,
cover: videoItem.cover,
bvid: videoItem.bvid,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,

View File

@@ -130,15 +130,13 @@ class UserHttp {
// 稍后再看
static Future toViewLater({String? bvid, dynamic aid}) async {
var data = {'csrf': Accounts.main.csrf};
if (bvid != null) {
data['bvid'] = bvid;
} else if (aid != null) {
data['aid'] = aid;
}
var res = await Request().post(
Api.toViewLater,
queryParameters: data,
queryParameters: {
if (aid != null) 'aid': aid,
if (bvid != null) 'bvid': bvid,
'csrf': Accounts.main.csrf,
},
);
if (res.data['code'] == 0) {
return {'status': true, 'msg': 'yeah稍后再看'};

View File

@@ -19,7 +19,6 @@ class FavDetailItemModel with MultiSelectData {
int? ctime;
int? pubtime;
int? favTime;
String? bvId;
String? bvid;
Ogv? ogv;
Ugc? ugc;
@@ -40,7 +39,6 @@ class FavDetailItemModel with MultiSelectData {
this.ctime,
this.pubtime,
this.favTime,
this.bvId,
this.bvid,
this.ogv,
this.ugc,
@@ -67,8 +65,7 @@ class FavDetailItemModel with MultiSelectData {
ctime: json['ctime'] as int?,
pubtime: json['pubtime'] as int?,
favTime: json['fav_time'] as int?,
bvId: json['bv_id'] as String?,
bvid: json['bvid'] as String?,
bvid: json['bvid'] ?? json['bv_id'],
ogv: json['ogv'] == null ? null : Ogv.fromJson(json['ogv']),
ugc: json['ugc'] == null
? null

View File

@@ -104,17 +104,20 @@ class DynamicPanel extends StatelessWidget {
BuildContext context,
Function(BuildContext) morePanel,
) {
late String? title;
late String? cover;
String? title;
String? cover;
String? bvid;
late final major = item.modules.moduleDynamic?.major;
switch (item.type) {
case 'DYNAMIC_TYPE_AV':
title = major?.archive?.title;
cover = major?.archive?.cover;
bvid = major?.archive?.bvid;
break;
case 'DYNAMIC_TYPE_UGC_SEASON':
title = major?.ugcSeason?.title;
cover = major?.ugcSeason?.cover;
bvid = major?.ugcSeason?.bvid;
break;
case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
title = major?.pgc?.title;
@@ -135,6 +138,7 @@ class DynamicPanel extends StatelessWidget {
imageSaveDialog(
title: title,
cover: cover,
bvid: bvid,
);
}
}

View File

@@ -54,17 +54,19 @@ Widget module(
onLongPress: isNoneMajor
? null
: () {
late String? title, cover;
String? title, cover, bvid;
late var origMajor = orig.modules.moduleDynamic?.major;
late var major = item.modules.moduleDynamic?.major;
switch (orig.type) {
case 'DYNAMIC_TYPE_AV':
title = origMajor?.archive?.title;
cover = origMajor?.archive?.cover;
bvid = origMajor?.archive?.bvid;
break;
case 'DYNAMIC_TYPE_UGC_SEASON':
title = origMajor?.ugcSeason?.title;
cover = origMajor?.ugcSeason?.cover;
bvid = origMajor?.ugcSeason?.bvid;
break;
case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
title = origMajor?.pgc?.title;
@@ -84,6 +86,7 @@ Widget module(
imageSaveDialog(
title: title,
cover: cover,
bvid: bvid,
);
},
child: Container(

View File

@@ -90,16 +90,24 @@ class _FavDetailPageState extends State<FavDetailPage> {
Widget _buildHeader(ThemeData theme) {
return SliverAppBar.medium(
leading: _favDetailController.enableMultiSelect.value
? IconButton(
? Row(
children: [
IconButton(
tooltip: '取消',
onPressed: _favDetailController.handleSelect,
icon: const Icon(Icons.close_outlined),
),
Text(
'已选: ${_favDetailController.checkedCount.value}',
style: const TextStyle(fontSize: 15),
),
],
)
: null,
expandedHeight: kToolbarHeight + 130,
pinned: true,
title: _favDetailController.enableMultiSelect.value
? Text('已选: ${_favDetailController.checkedCount.value}')
? null
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -288,7 +296,6 @@ class _FavDetailPageState extends State<FavDetailPage> {
fontSize: 12.5,
color: theme.colorScheme.outline,
);
final item = _favDetailController.item.value;
return FlexibleSpaceBar(
background: Padding(
padding: EdgeInsets.only(
@@ -300,7 +307,9 @@ class _FavDetailPageState extends State<FavDetailPage> {
child: SizedBox(
height: 110,
child: Obx(
() => Row(
() {
final item = _favDetailController.item.value;
return Row(
spacing: 12,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -330,11 +339,14 @@ class _FavDetailPageState extends State<FavDetailPage> {
iconSize: 18,
tooltip: '${isFav ? '取消' : ''}收藏',
onPressed: () => _favDetailController.onFav(isFav),
icon: isFav ? Icons.favorite : Icons.favorite_border,
bgColor:
isFav ? null : theme.colorScheme.onInverseSurface,
iconColor:
isFav ? null : theme.colorScheme.onSurfaceVariant,
icon:
isFav ? Icons.favorite : Icons.favorite_border,
bgColor: isFav
? null
: theme.colorScheme.onInverseSurface,
iconColor: isFav
? null
: theme.colorScheme.onSurfaceVariant,
);
}),
)
@@ -390,7 +402,8 @@ class _FavDetailPageState extends State<FavDetailPage> {
key: ValueKey(_favDetailController.item.value),
)
],
),
);
},
),
),
),

View File

@@ -60,6 +60,7 @@ class FavVideoCardH extends StatelessWidget {
() => imageSaveDialog(
title: item.title,
cover: item.cover,
bvid: item.bvid,
),
child: Padding(
padding: const EdgeInsets.symmetric(

View File

@@ -93,6 +93,7 @@ class HistoryItem extends StatelessWidget {
imageSaveDialog(
title: item.title,
cover: item.cover,
bvid: bvid,
);
},
child: Stack(

View File

@@ -44,6 +44,7 @@ class VideoCardHLater extends StatelessWidget {
() => imageSaveDialog(
title: videoItem.title,
cover: videoItem.pic,
bvid: videoItem.bvid,
),
onTap: onTap ??
() async {

View File

@@ -50,6 +50,7 @@ class MemberCoinLikeItem extends StatelessWidget {
onLongPress: () => imageSaveDialog(
title: item.title,
cover: item.cover,
aid: item.param,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,

View File

@@ -26,27 +26,32 @@ class VideoCardVMemberHome extends StatelessWidget {
case 'bangumi':
PageUtils.viewPgc(epId: videoItem.param);
break;
case 'av':
if (videoItem.isPgc == true && videoItem.uri?.isNotEmpty == true) {
if (PageUtils.viewPgcFromUri(videoItem.uri!)) {
if (videoItem.isPgc == true) {
if (videoItem.uri?.isNotEmpty == true) {
PageUtils.viewPgcFromUri(videoItem.uri!);
}
return;
}
}
String? aid = videoItem.param;
String? bvid = videoItem.bvid;
if (aid == null && bvid == null) {
return;
}
int? cid = videoItem.cid;
cid ??= await SearchHttp.ab2c(aid: aid, bvid: bvid);
bvid ??= IdUtils.av2bv(int.parse(aid!));
int? cid = videoItem.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
PageUtils.toVideoPage(
'bvid=${bvid ?? IdUtils.av2bv(int.parse(aid!))}&cid=$cid',
'bvid=$bvid&cid=$cid',
arguments: {
'pic': videoItem.cover,
'heroTag': heroTag,
},
);
break;
default:
if (videoItem.uri?.isNotEmpty == true) {
PiliScheme.routePushFromUrl(videoItem.uri!);
@@ -64,6 +69,8 @@ class VideoCardVMemberHome extends StatelessWidget {
onLongPress: () => imageSaveDialog(
title: videoItem.title,
cover: videoItem.cover,
aid: videoItem.param,
bvid: videoItem.bvid,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,

View File

@@ -37,6 +37,7 @@ class VideoCardHMemberVideo extends StatelessWidget {
onLongPress: () => imageSaveDialog(
title: videoItem.title,
cover: videoItem.cover,
bvid: videoItem.bvid,
),
onTap: onTap ??
() async {

View File

@@ -42,6 +42,7 @@ class SubVideoCardH extends StatelessWidget {
onLongPress: () => imageSaveDialog(
title: videoItem.title,
cover: videoItem.cover,
bvid: videoItem.bvid,
),
child: Padding(
padding: const EdgeInsets.symmetric(

View File

@@ -174,6 +174,8 @@ class _MediaListPanelState
onLongPress: () => imageSaveDialog(
title: item.title,
cover: item.cover,
aid: item.aid,
bvid: item.bvid,
),
child: Stack(
clipBehavior: Clip.none,