mirror of
https://github.com/HChaZZY/PiliPlus.git
synced 2025-12-06 09:13:48 +08:00
@@ -56,7 +56,7 @@ class NetworkImgLayer extends StatelessWidget {
|
||||
: getPlaceHolder?.call() ?? placeholder(context);
|
||||
}
|
||||
|
||||
Widget _buildImage(context) {
|
||||
Widget _buildImage(BuildContext context) {
|
||||
int? memCacheWidth, memCacheHeight;
|
||||
if (height == null || callback?.call() == true || width <= height!) {
|
||||
memCacheWidth = width.cacheSize(context);
|
||||
|
||||
@@ -21,7 +21,6 @@ class VideoCardH extends StatelessWidget {
|
||||
const VideoCardH({
|
||||
super.key,
|
||||
required this.videoItem,
|
||||
this.source = 'normal',
|
||||
this.showOwner = true,
|
||||
this.showView = true,
|
||||
this.showDanmaku = true,
|
||||
@@ -31,7 +30,6 @@ class VideoCardH extends StatelessWidget {
|
||||
this.onViewLater,
|
||||
});
|
||||
final BaseVideoItemModel videoItem;
|
||||
final String source;
|
||||
final bool showOwner;
|
||||
final bool showView;
|
||||
final bool showDanmaku;
|
||||
@@ -42,8 +40,6 @@ class VideoCardH extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final int aid = videoItem.aid!;
|
||||
final String bvid = videoItem.bvid!;
|
||||
String type = 'video';
|
||||
if (videoItem case SearchVideoItemModel item) {
|
||||
var typeOrNull = item.type;
|
||||
@@ -90,19 +86,16 @@ class VideoCardH extends StatelessWidget {
|
||||
}
|
||||
try {
|
||||
final int? cid = videoItem.cid ??
|
||||
await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
||||
await SearchHttp.ab2c(
|
||||
aid: videoItem.aid, bvid: videoItem.bvid);
|
||||
if (cid != null) {
|
||||
if (source == 'later') {
|
||||
onViewLater!(cid);
|
||||
} else {
|
||||
PageUtils.toVideoPage(
|
||||
'bvid=$bvid&cid=$cid',
|
||||
arguments: {
|
||||
'videoItem': videoItem,
|
||||
'heroTag': Utils.makeHeroTag(aid)
|
||||
},
|
||||
);
|
||||
}
|
||||
PageUtils.toVideoPage(
|
||||
'bvid=${videoItem.bvid}&cid=$cid',
|
||||
arguments: {
|
||||
'videoItem': videoItem,
|
||||
'heroTag': Utils.makeHeroTag(videoItem.aid)
|
||||
},
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
SmartDialog.showToast(err.toString());
|
||||
@@ -181,28 +174,27 @@ class VideoCardH extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
content(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (source == 'normal')
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 12,
|
||||
child: VideoPopupMenu(
|
||||
size: 29,
|
||||
iconSize: 17,
|
||||
videoItem: videoItem,
|
||||
),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 12,
|
||||
child: VideoPopupMenu(
|
||||
size: 29,
|
||||
iconSize: 17,
|
||||
videoItem: videoItem,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(BuildContext context) {
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
String pubdate = showPubdate
|
||||
? Utils.dateFormat(videoItem.pubdate!, formatType: 'day')
|
||||
@@ -262,23 +254,20 @@ class VideoCardH extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
if (showView) ...[
|
||||
if (showView)
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: videoItem.stat.viewStr,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
if (showDanmaku)
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: videoItem.stat.danmuStr,
|
||||
),
|
||||
const Spacer(),
|
||||
if (source == 'normal') const SizedBox(width: 24),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -32,7 +32,7 @@ class VideoCardV extends StatelessWidget {
|
||||
return numericRegex.hasMatch(str);
|
||||
}
|
||||
|
||||
Future<void> onPushDetail(heroTag) async {
|
||||
Future<void> onPushDetail(String heroTag) async {
|
||||
String? goto = videoItem.goto;
|
||||
switch (goto) {
|
||||
case 'bangumi':
|
||||
@@ -136,7 +136,7 @@ class VideoCardV extends StatelessWidget {
|
||||
);
|
||||
}),
|
||||
),
|
||||
videoContent(context)
|
||||
content(context)
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -157,7 +157,7 @@ class VideoCardV extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
|
||||
@@ -41,36 +41,36 @@ class DynamicsHttp {
|
||||
};
|
||||
var res = await Request().get(Api.followDynamic, queryParameters: data);
|
||||
if (res.data['code'] == 0) {
|
||||
// try {
|
||||
DynamicsDataModel data = DynamicsDataModel.fromJson(res.data['data']);
|
||||
final antiGoodsDyn = GStorage.antiGoodsDyn;
|
||||
final filterWord = banWordForDyn.pattern.isNotEmpty;
|
||||
try {
|
||||
DynamicsDataModel data = DynamicsDataModel.fromJson(res.data['data']);
|
||||
final antiGoodsDyn = GStorage.antiGoodsDyn;
|
||||
final filterWord = banWordForDyn.pattern.isNotEmpty;
|
||||
|
||||
data.items?.removeWhere(
|
||||
(item) =>
|
||||
(antiGoodsDyn &&
|
||||
(item.orig?.modules.moduleDynamic?.additional?.type ==
|
||||
'ADDITIONAL_TYPE_GOODS' ||
|
||||
item.modules.moduleDynamic?.additional?.type ==
|
||||
'ADDITIONAL_TYPE_GOODS')) ||
|
||||
(filterWord &&
|
||||
(item.orig?.modules.moduleDynamic?.major?.opus?.summary?.text
|
||||
?.contains(banWordForDyn) ==
|
||||
true ||
|
||||
item.modules.moduleDynamic?.major?.opus?.summary?.text
|
||||
?.contains(banWordForDyn) ==
|
||||
true ||
|
||||
item.orig?.modules.moduleDynamic?.desc?.text
|
||||
?.contains(banWordForDyn) ==
|
||||
true ||
|
||||
item.modules.moduleDynamic?.desc?.text
|
||||
?.contains(banWordForDyn) ==
|
||||
true)),
|
||||
);
|
||||
return Success(data);
|
||||
// } catch (err) {
|
||||
// return Error(err.toString());
|
||||
// }
|
||||
data.items?.removeWhere(
|
||||
(item) =>
|
||||
(antiGoodsDyn &&
|
||||
(item.orig?.modules.moduleDynamic?.additional?.type ==
|
||||
'ADDITIONAL_TYPE_GOODS' ||
|
||||
item.modules.moduleDynamic?.additional?.type ==
|
||||
'ADDITIONAL_TYPE_GOODS')) ||
|
||||
(filterWord &&
|
||||
(item.orig?.modules.moduleDynamic?.major?.opus?.summary?.text
|
||||
?.contains(banWordForDyn) ==
|
||||
true ||
|
||||
item.modules.moduleDynamic?.major?.opus?.summary?.text
|
||||
?.contains(banWordForDyn) ==
|
||||
true ||
|
||||
item.orig?.modules.moduleDynamic?.desc?.text
|
||||
?.contains(banWordForDyn) ==
|
||||
true ||
|
||||
item.modules.moduleDynamic?.desc?.text
|
||||
?.contains(banWordForDyn) ==
|
||||
true)),
|
||||
);
|
||||
return Success(data);
|
||||
} catch (err) {
|
||||
return Error(err.toString());
|
||||
}
|
||||
} else {
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/http/api.dart';
|
||||
import 'package:PiliPlus/http/init.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models/model_hot_video_item.dart';
|
||||
import 'package:PiliPlus/models/user/info.dart';
|
||||
import 'package:PiliPlus/models/user/stat.dart';
|
||||
import 'package:PiliPlus/models_new/history/data.dart';
|
||||
import 'package:PiliPlus/models_new/later/data.dart';
|
||||
import 'package:PiliPlus/models_new/media_list/data.dart';
|
||||
import 'package:PiliPlus/models_new/sub/sub/data.dart';
|
||||
import 'package:PiliPlus/models_new/sub/sub/list.dart';
|
||||
@@ -48,7 +48,7 @@ class UserHttp {
|
||||
}
|
||||
|
||||
// 稍后再看
|
||||
static Future<LoadingState<Map>> seeYouLater({
|
||||
static Future<LoadingState<LaterData>> seeYouLater({
|
||||
required int page,
|
||||
int viewed = 0,
|
||||
String keyword = '',
|
||||
@@ -67,19 +67,7 @@ class UserHttp {
|
||||
}),
|
||||
);
|
||||
if (res.data['code'] == 0) {
|
||||
if (res.data['data']['count'] == 0) {
|
||||
return const Success({'count': 0});
|
||||
}
|
||||
List<HotVideoItemModel> list = <HotVideoItemModel>[];
|
||||
if (res.data['data']?['list'] != null) {
|
||||
for (var i in res.data['data']['list']) {
|
||||
list.add(HotVideoItemModel.fromJson(i));
|
||||
}
|
||||
}
|
||||
return Success({
|
||||
'list': list,
|
||||
'count': res.data['data']?['count'] ?? 0,
|
||||
});
|
||||
return Success(LaterData.fromJson(res.data['data']));
|
||||
} else {
|
||||
return Error(res.data['message']);
|
||||
}
|
||||
|
||||
33
lib/models_new/later/bangumi.dart
Normal file
33
lib/models_new/later/bangumi.dart
Normal file
@@ -0,0 +1,33 @@
|
||||
import 'package:PiliPlus/models_new/later/season.dart';
|
||||
|
||||
class Bangumi {
|
||||
int? epId;
|
||||
String? title;
|
||||
String? longTitle;
|
||||
int? episodeStatus;
|
||||
int? follow;
|
||||
String? cover;
|
||||
Season? season;
|
||||
|
||||
Bangumi({
|
||||
this.epId,
|
||||
this.title,
|
||||
this.longTitle,
|
||||
this.episodeStatus,
|
||||
this.follow,
|
||||
this.cover,
|
||||
this.season,
|
||||
});
|
||||
|
||||
factory Bangumi.fromJson(Map<String, dynamic> json) => Bangumi(
|
||||
epId: json['ep_id'] as int?,
|
||||
title: json['title'] as String?,
|
||||
longTitle: json['long_title'] as String?,
|
||||
episodeStatus: json['episode_status'] as int?,
|
||||
follow: json['follow'] as int?,
|
||||
cover: json['cover'] as String?,
|
||||
season: json['season'] == null
|
||||
? null
|
||||
: Season.fromJson(json['season'] as Map<String, dynamic>),
|
||||
);
|
||||
}
|
||||
15
lib/models_new/later/data.dart
Normal file
15
lib/models_new/later/data.dart
Normal file
@@ -0,0 +1,15 @@
|
||||
import 'package:PiliPlus/models_new/later/list.dart';
|
||||
|
||||
class LaterData {
|
||||
int? count;
|
||||
List<LaterItemModel>? list;
|
||||
|
||||
LaterData({this.count, this.list});
|
||||
|
||||
factory LaterData.fromJson(Map<String, dynamic> json) => LaterData(
|
||||
count: json['count'] as int?,
|
||||
list: (json['list'] as List<dynamic>?)
|
||||
?.map((e) => LaterItemModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
13
lib/models_new/later/dimension.dart
Normal file
13
lib/models_new/later/dimension.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
class Dimension {
|
||||
int? width;
|
||||
int? height;
|
||||
int? rotate;
|
||||
|
||||
Dimension({this.width, this.height, this.rotate});
|
||||
|
||||
factory Dimension.fromJson(Map<String, dynamic> json) => Dimension(
|
||||
width: json['width'] as int?,
|
||||
height: json['height'] as int?,
|
||||
rotate: json['rotate'] as int?,
|
||||
);
|
||||
}
|
||||
164
lib/models_new/later/list.dart
Normal file
164
lib/models_new/later/list.dart
Normal file
@@ -0,0 +1,164 @@
|
||||
import 'package:PiliPlus/pages/common/multi_select_controller.dart';
|
||||
|
||||
import 'package:PiliPlus/models_new/later/bangumi.dart';
|
||||
import 'package:PiliPlus/models_new/later/dimension.dart';
|
||||
import 'package:PiliPlus/models_new/later/owner.dart';
|
||||
import 'package:PiliPlus/models_new/later/page.dart';
|
||||
import 'package:PiliPlus/models_new/later/rights.dart';
|
||||
import 'package:PiliPlus/models_new/later/stat.dart';
|
||||
|
||||
class LaterItemModel with MultiSelectData {
|
||||
int? aid;
|
||||
int? videos;
|
||||
int? tid;
|
||||
String? tname;
|
||||
int? copyright;
|
||||
String? pic;
|
||||
String? title;
|
||||
String? subtitle;
|
||||
int? pubdate;
|
||||
int? ctime;
|
||||
String? desc;
|
||||
int? state;
|
||||
int? duration;
|
||||
String? redirectUrl;
|
||||
Rights? rights;
|
||||
Owner? owner;
|
||||
Stat? stat;
|
||||
String? dynam1c;
|
||||
Dimension? dimension;
|
||||
String? shortLinkV2;
|
||||
int? upFromV2;
|
||||
String? pubLocation;
|
||||
String? cover43;
|
||||
int? tidv2;
|
||||
String? tnamev2;
|
||||
int? pidV2;
|
||||
String? pidNameV2;
|
||||
List<Page>? pages;
|
||||
Bangumi? bangumi;
|
||||
int? cid;
|
||||
int? progress;
|
||||
int? addAt;
|
||||
String? bvid;
|
||||
String? uri;
|
||||
bool? viewed;
|
||||
int? seq;
|
||||
int? enableVt;
|
||||
String? viewText1;
|
||||
bool? isPgc;
|
||||
String? pgcLabel;
|
||||
bool? isPugv;
|
||||
int? missionId;
|
||||
String? firstFrame;
|
||||
int? seasonId;
|
||||
|
||||
LaterItemModel({
|
||||
this.aid,
|
||||
this.videos,
|
||||
this.tid,
|
||||
this.tname,
|
||||
this.copyright,
|
||||
this.pic,
|
||||
this.title,
|
||||
this.subtitle,
|
||||
this.pubdate,
|
||||
this.ctime,
|
||||
this.desc,
|
||||
this.state,
|
||||
this.duration,
|
||||
this.redirectUrl,
|
||||
this.rights,
|
||||
this.owner,
|
||||
this.stat,
|
||||
this.dynam1c,
|
||||
this.dimension,
|
||||
this.shortLinkV2,
|
||||
this.upFromV2,
|
||||
this.pubLocation,
|
||||
this.cover43,
|
||||
this.tidv2,
|
||||
this.tnamev2,
|
||||
this.pidV2,
|
||||
this.pidNameV2,
|
||||
this.pages,
|
||||
this.bangumi,
|
||||
this.cid,
|
||||
this.progress,
|
||||
this.addAt,
|
||||
this.bvid,
|
||||
this.uri,
|
||||
this.viewed,
|
||||
this.seq,
|
||||
this.enableVt,
|
||||
this.viewText1,
|
||||
this.isPgc,
|
||||
this.pgcLabel,
|
||||
this.isPugv,
|
||||
this.missionId,
|
||||
this.firstFrame,
|
||||
this.seasonId,
|
||||
});
|
||||
|
||||
factory LaterItemModel.fromJson(Map<String, dynamic> json) => LaterItemModel(
|
||||
aid: json['aid'] as int?,
|
||||
videos: json['videos'] as int?,
|
||||
tid: json['tid'] as int?,
|
||||
tname: json['tname'] as String?,
|
||||
copyright: json['copyright'] as int?,
|
||||
pic: json['pic'] as String?,
|
||||
title: json['title'] as String?,
|
||||
pubdate: json['pubdate'] as int?,
|
||||
ctime: json['ctime'] as int?,
|
||||
desc: json['desc'] as String?,
|
||||
state: json['state'] as int?,
|
||||
duration: json['duration'] as int?,
|
||||
redirectUrl: json['redirect_url'] as String?,
|
||||
rights: json['rights'] == null
|
||||
? null
|
||||
: Rights.fromJson(json['rights'] as Map<String, dynamic>),
|
||||
owner: json['owner'] == null
|
||||
? null
|
||||
: Owner.fromJson(json['owner'] as Map<String, dynamic>),
|
||||
stat: json['stat'] == null
|
||||
? null
|
||||
: Stat.fromJson(json['stat'] as Map<String, dynamic>),
|
||||
dynam1c: json['dynamic'] as String?,
|
||||
dimension: json['dimension'] == null
|
||||
? null
|
||||
: Dimension.fromJson(json['dimension'] as Map<String, dynamic>),
|
||||
shortLinkV2: json['short_link_v2'] as String?,
|
||||
upFromV2: json['up_from_v2'] as int?,
|
||||
pubLocation: json['pub_location'] as String?,
|
||||
cover43: json['cover43'] as String?,
|
||||
tidv2: json['tidv2'] as int?,
|
||||
tnamev2: json['tnamev2'] as String?,
|
||||
pidV2: json['pid_v2'] as int?,
|
||||
pidNameV2: json['pid_name_v2'] as String?,
|
||||
pages: (json['pages'] as List<dynamic>?)
|
||||
?.map((e) => Page.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
bangumi: json['bangumi'] == null
|
||||
? null
|
||||
: Bangumi.fromJson(json['bangumi'] as Map<String, dynamic>),
|
||||
subtitle: json['bangumi'] == null
|
||||
? null
|
||||
: (json['title'] as String)
|
||||
.replaceFirst('${json['bangumi']['season']['title']} ', ''),
|
||||
cid: json['cid'] as int?,
|
||||
progress: json['progress'] as int?,
|
||||
addAt: json['add_at'] as int?,
|
||||
bvid: json['bvid'] as String?,
|
||||
uri: json['uri'] as String?,
|
||||
viewed: json['viewed'] as bool?,
|
||||
seq: json['seq'] as int?,
|
||||
enableVt: json['enable_vt'] as int?,
|
||||
viewText1: json['view_text_1'] as String?,
|
||||
isPgc: json['is_pgc'] as bool?,
|
||||
pgcLabel: json['pgc_label'] as String?,
|
||||
isPugv: json['is_pugv'] as bool?,
|
||||
missionId: json['mission_id'] as int?,
|
||||
firstFrame: json['first_frame'] as String?,
|
||||
seasonId: json['season_id'] as int?,
|
||||
);
|
||||
}
|
||||
13
lib/models_new/later/owner.dart
Normal file
13
lib/models_new/later/owner.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
class Owner {
|
||||
int? mid;
|
||||
String? name;
|
||||
String? face;
|
||||
|
||||
Owner({this.mid, this.name, this.face});
|
||||
|
||||
factory Owner.fromJson(Map<String, dynamic> json) => Owner(
|
||||
mid: json['mid'] as int?,
|
||||
name: json['name'] as String?,
|
||||
face: json['face'] as String?,
|
||||
);
|
||||
}
|
||||
39
lib/models_new/later/page.dart
Normal file
39
lib/models_new/later/page.dart
Normal file
@@ -0,0 +1,39 @@
|
||||
import 'package:PiliPlus/models_new/later/dimension.dart';
|
||||
|
||||
class Page {
|
||||
int? cid;
|
||||
int? page;
|
||||
String? from;
|
||||
String? part;
|
||||
int? duration;
|
||||
String? vid;
|
||||
String? weblink;
|
||||
Dimension? dimension;
|
||||
int? ctime;
|
||||
|
||||
Page({
|
||||
this.cid,
|
||||
this.page,
|
||||
this.from,
|
||||
this.part,
|
||||
this.duration,
|
||||
this.vid,
|
||||
this.weblink,
|
||||
this.dimension,
|
||||
this.ctime,
|
||||
});
|
||||
|
||||
factory Page.fromJson(Map<String, dynamic> json) => Page(
|
||||
cid: json['cid'] as int?,
|
||||
page: json['page'] as int?,
|
||||
from: json['from'] as String?,
|
||||
part: json['part'] as String?,
|
||||
duration: json['duration'] as int?,
|
||||
vid: json['vid'] as String?,
|
||||
weblink: json['weblink'] as String?,
|
||||
dimension: json['dimension'] == null
|
||||
? null
|
||||
: Dimension.fromJson(json['dimension'] as Map<String, dynamic>),
|
||||
ctime: json['ctime'] as int?,
|
||||
);
|
||||
}
|
||||
50
lib/models_new/later/rights.dart
Normal file
50
lib/models_new/later/rights.dart
Normal file
@@ -0,0 +1,50 @@
|
||||
class Rights {
|
||||
int? bp;
|
||||
int? elec;
|
||||
int? download;
|
||||
int? movie;
|
||||
int? pay;
|
||||
int? hd5;
|
||||
int? noReprint;
|
||||
int? autoplay;
|
||||
int? ugcPay;
|
||||
int? isCooperation;
|
||||
int? ugcPayPreview;
|
||||
int? noBackground;
|
||||
int? arcPay;
|
||||
int? payFreeWatch;
|
||||
|
||||
Rights({
|
||||
this.bp,
|
||||
this.elec,
|
||||
this.download,
|
||||
this.movie,
|
||||
this.pay,
|
||||
this.hd5,
|
||||
this.noReprint,
|
||||
this.autoplay,
|
||||
this.ugcPay,
|
||||
this.isCooperation,
|
||||
this.ugcPayPreview,
|
||||
this.noBackground,
|
||||
this.arcPay,
|
||||
this.payFreeWatch,
|
||||
});
|
||||
|
||||
factory Rights.fromJson(Map<String, dynamic> json) => Rights(
|
||||
bp: json['bp'] as int?,
|
||||
elec: json['elec'] as int?,
|
||||
download: json['download'] as int?,
|
||||
movie: json['movie'] as int?,
|
||||
pay: json['pay'] as int?,
|
||||
hd5: json['hd5'] as int?,
|
||||
noReprint: json['no_reprint'] as int?,
|
||||
autoplay: json['autoplay'] as int?,
|
||||
ugcPay: json['ugc_pay'] as int?,
|
||||
isCooperation: json['is_cooperation'] as int?,
|
||||
ugcPayPreview: json['ugc_pay_preview'] as int?,
|
||||
noBackground: json['no_background'] as int?,
|
||||
arcPay: json['arc_pay'] as int?,
|
||||
payFreeWatch: json['pay_free_watch'] as int?,
|
||||
);
|
||||
}
|
||||
32
lib/models_new/later/season.dart
Normal file
32
lib/models_new/later/season.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
class Season {
|
||||
int? seasonId;
|
||||
String? title;
|
||||
int? seasonStatus;
|
||||
int? isFinish;
|
||||
int? totalCount;
|
||||
int? newestEpId;
|
||||
String? newestEpIndex;
|
||||
int? seasonType;
|
||||
|
||||
Season({
|
||||
this.seasonId,
|
||||
this.title,
|
||||
this.seasonStatus,
|
||||
this.isFinish,
|
||||
this.totalCount,
|
||||
this.newestEpId,
|
||||
this.newestEpIndex,
|
||||
this.seasonType,
|
||||
});
|
||||
|
||||
factory Season.fromJson(Map<String, dynamic> json) => Season(
|
||||
seasonId: json['season_id'] as int?,
|
||||
title: json['title'] as String?,
|
||||
seasonStatus: json['season_status'] as int?,
|
||||
isFinish: json['is_finish'] as int?,
|
||||
totalCount: json['total_count'] as int?,
|
||||
newestEpId: json['newest_ep_id'] as int?,
|
||||
newestEpIndex: json['newest_ep_index'] as String?,
|
||||
seasonType: json['season_type'] as int?,
|
||||
);
|
||||
}
|
||||
47
lib/models_new/later/stat.dart
Normal file
47
lib/models_new/later/stat.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
class Stat {
|
||||
int? aid;
|
||||
int? view;
|
||||
int? danmaku;
|
||||
int? reply;
|
||||
int? favorite;
|
||||
int? coin;
|
||||
int? share;
|
||||
int? nowRank;
|
||||
int? hisRank;
|
||||
int? like;
|
||||
int? dislike;
|
||||
int? vt;
|
||||
int? vv;
|
||||
|
||||
Stat({
|
||||
this.aid,
|
||||
this.view,
|
||||
this.danmaku,
|
||||
this.reply,
|
||||
this.favorite,
|
||||
this.coin,
|
||||
this.share,
|
||||
this.nowRank,
|
||||
this.hisRank,
|
||||
this.like,
|
||||
this.dislike,
|
||||
this.vt,
|
||||
this.vv,
|
||||
});
|
||||
|
||||
factory Stat.fromJson(Map<String, dynamic> json) => Stat(
|
||||
aid: json['aid'] as int?,
|
||||
view: json['view'] as int?,
|
||||
danmaku: json['danmaku'] as int?,
|
||||
reply: json['reply'] as int?,
|
||||
favorite: json['favorite'] as int?,
|
||||
coin: json['coin'] as int?,
|
||||
share: json['share'] as int?,
|
||||
nowRank: json['now_rank'] as int?,
|
||||
hisRank: json['his_rank'] as int?,
|
||||
like: json['like'] as int?,
|
||||
dislike: json['dislike'] as int?,
|
||||
vt: json['vt'] as int?,
|
||||
vv: json['vv'] as int?,
|
||||
);
|
||||
}
|
||||
@@ -193,7 +193,7 @@ class _ArticlePageState extends State<ArticlePage>
|
||||
id: id,
|
||||
oid: oid,
|
||||
rpid: rpid,
|
||||
source: 'dynamic',
|
||||
isVideoDetail: false,
|
||||
replyType: _articleCtr.commentType,
|
||||
firstFloor: replyItem,
|
||||
onDispose: onDispose,
|
||||
|
||||
@@ -22,7 +22,7 @@ import 'package:get/get.dart';
|
||||
class AuthorPanel extends StatelessWidget {
|
||||
final DynamicItemModel item;
|
||||
final Function? addBannedList;
|
||||
final String? source;
|
||||
final bool isDetail;
|
||||
final ValueChanged? onRemove;
|
||||
final bool isSave;
|
||||
final Function(bool isTop, dynamic dynId)? onSetTop;
|
||||
@@ -32,7 +32,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
super.key,
|
||||
required this.item,
|
||||
this.addBannedList,
|
||||
this.source,
|
||||
this.isDetail = false,
|
||||
this.onRemove,
|
||||
this.isSave = false,
|
||||
this.onSetTop,
|
||||
@@ -119,7 +119,7 @@ class AuthorPanel extends StatelessWidget {
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: source != 'detail' && item.modules.moduleTag?.text != null
|
||||
child: !isDetail && item.modules.moduleTag?.text != null
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
||||
@@ -11,7 +11,7 @@ Widget content(
|
||||
bool isSave,
|
||||
BuildContext context,
|
||||
DynamicItemModel item,
|
||||
String? source,
|
||||
bool isDetail,
|
||||
Function(List<String>, int)? callback, {
|
||||
floor = 1,
|
||||
}) {
|
||||
@@ -53,7 +53,7 @@ Widget content(
|
||||
style: TextStyle(
|
||||
fontSize: floor != 1
|
||||
? 14
|
||||
: source == 'detail' && !isSave
|
||||
: isDetail && !isSave
|
||||
? 16
|
||||
: 15,
|
||||
color: theme.colorScheme.primary,
|
||||
@@ -61,7 +61,7 @@ Widget content(
|
||||
),
|
||||
),
|
||||
if (richNodes != null)
|
||||
source == 'detail' && floor == 1
|
||||
isDetail && floor == 1
|
||||
? SelectableText.rich(
|
||||
richNodes,
|
||||
style: isSave
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'package:get/get.dart';
|
||||
|
||||
class DynamicPanel extends StatelessWidget {
|
||||
final DynamicItemModel item;
|
||||
final String? source;
|
||||
final bool isDetail;
|
||||
final ValueChanged? onRemove;
|
||||
final Function(List<String>, int)? callback;
|
||||
final bool isSave;
|
||||
@@ -22,7 +22,7 @@ class DynamicPanel extends StatelessWidget {
|
||||
const DynamicPanel({
|
||||
super.key,
|
||||
required this.item,
|
||||
this.source,
|
||||
this.isDetail = false,
|
||||
this.onRemove,
|
||||
this.callback,
|
||||
this.isSave = false,
|
||||
@@ -35,7 +35,7 @@ class DynamicPanel extends StatelessWidget {
|
||||
final theme = Theme.of(context);
|
||||
final authorWidget = AuthorPanel(
|
||||
item: item,
|
||||
source: source,
|
||||
isDetail: isDetail,
|
||||
onRemove: onRemove,
|
||||
isSave: isSave,
|
||||
onSetTop: onSetTop,
|
||||
@@ -45,7 +45,7 @@ class DynamicPanel extends StatelessWidget {
|
||||
elevation: 0,
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: source == 'detail' &&
|
||||
onTap: isDetail &&
|
||||
!const {
|
||||
'DYNAMIC_TYPE_AV',
|
||||
'DYNAMIC_TYPE_UGC_SEASON',
|
||||
@@ -67,22 +67,21 @@ class DynamicPanel extends StatelessWidget {
|
||||
child: authorWidget,
|
||||
),
|
||||
if (item.type != 'DYNAMIC_TYPE_NONE')
|
||||
content(theme, isSave, context, item, source, callback),
|
||||
module(theme, isSave, item, context, source, callback),
|
||||
content(theme, isSave, context, item, isDetail, callback),
|
||||
module(theme, isSave, item, context, isDetail, callback),
|
||||
if (item.modules.moduleDynamic?.additional != null)
|
||||
addWidget(theme, item, context),
|
||||
if (item.modules.moduleDynamic?.major?.blocked != null)
|
||||
blockedItem(theme, item.modules.moduleDynamic!.major!.blocked!),
|
||||
const SizedBox(height: 2),
|
||||
if (source == null) ActionPanel(item: item),
|
||||
if (source == 'detail' && !isSave) const SizedBox(height: 12),
|
||||
if (!isDetail) ActionPanel(item: item),
|
||||
if (isDetail && !isSave) const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
if (isSave ||
|
||||
(source == 'detail' &&
|
||||
Get.context!.orientation == Orientation.landscape)) {
|
||||
(isDetail && Get.context!.orientation == Orientation.landscape)) {
|
||||
return child;
|
||||
}
|
||||
return DecoratedBox(
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:get/get.dart';
|
||||
|
||||
Widget livePanel(
|
||||
ThemeData theme,
|
||||
String? source,
|
||||
bool isDetail,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
int floor = 1,
|
||||
@@ -45,8 +45,8 @@ Widget livePanel(
|
||||
children: [
|
||||
Text(
|
||||
content.live!.title!,
|
||||
maxLines: source == 'detail' ? null : 2,
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
maxLines: isDetail ? null : 2,
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (content.live?.descFirst != null)
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:get/get.dart';
|
||||
|
||||
Widget livePanelSub(
|
||||
ThemeData theme,
|
||||
String? source,
|
||||
bool isDetail,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
int floor = 1,
|
||||
@@ -113,9 +113,9 @@ Widget livePanelSub(
|
||||
const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: Text(
|
||||
content.title!,
|
||||
maxLines: source == 'detail' ? null : 1,
|
||||
maxLines: isDetail ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
Widget liveRcmdPanel(
|
||||
ThemeData theme,
|
||||
String? source,
|
||||
bool isDetail,
|
||||
DynamicItemModel item,
|
||||
BuildContext context, {
|
||||
int floor = 1,
|
||||
@@ -113,9 +113,9 @@ Widget liveRcmdPanel(
|
||||
const EdgeInsets.symmetric(horizontal: StyleString.safeSpace),
|
||||
child: Text(
|
||||
liveRcmd.title!,
|
||||
maxLines: source == 'detail' ? null : 1,
|
||||
maxLines: isDetail ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
|
||||
@@ -22,7 +22,7 @@ Widget module(
|
||||
bool isSave,
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
String? source,
|
||||
bool isDetail,
|
||||
Function(List<String>, int)? callback, {
|
||||
floor = 1,
|
||||
}) {
|
||||
@@ -36,7 +36,7 @@ Widget module(
|
||||
// 视频
|
||||
case 'DYNAMIC_TYPE_AV':
|
||||
return videoSeasonWidget(
|
||||
theme, isSave, source, item, context, 'archive', callback,
|
||||
theme, isSave, isDetail, item, context, 'archive', callback,
|
||||
floor: floor);
|
||||
// 转发
|
||||
case 'DYNAMIC_TYPE_FORWARD':
|
||||
@@ -45,108 +45,134 @@ Widget module(
|
||||
orig.modules.moduleDynamic?.major?.type == 'MAJOR_TYPE_NONE';
|
||||
late final isNormalAuth =
|
||||
orig.modules.moduleAuthor!.type == 'AUTHOR_TYPE_NORMAL';
|
||||
return InkWell(
|
||||
onTap:
|
||||
isNoneMajor ? null : () => PageUtils.pushDynDetail(orig, floor + 1),
|
||||
onLongPress: isNoneMajor
|
||||
? null
|
||||
: () {
|
||||
late String? title, cover;
|
||||
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;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_UGC_SEASON':
|
||||
title = origMajor?.ugcSeason?.title;
|
||||
cover = origMajor?.ugcSeason?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
|
||||
title = origMajor?.pgc?.title;
|
||||
cover = origMajor?.pgc?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_LIVE_RCMD':
|
||||
title = major?.liveRcmd?.title;
|
||||
cover = major?.liveRcmd?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_LIVE':
|
||||
title = major?.live?.title;
|
||||
cover = major?.live?.cover;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
imageSaveDialog(
|
||||
title: title,
|
||||
cover: cover,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
|
||||
color: theme.dividerColor.withValues(alpha: 0.08),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (orig.type != 'DYNAMIC_TYPE_NONE') ...[
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: isNormalAuth
|
||||
? () => Get.toNamed(
|
||||
'/member?mid=${orig.modules.moduleAuthor!.mid}',
|
||||
arguments: {
|
||||
'face': orig.modules.moduleAuthor!.face
|
||||
},
|
||||
)
|
||||
: null,
|
||||
child: Text(
|
||||
'${isNormalAuth ? '@' : ''}${orig.modules.moduleAuthor!.name}',
|
||||
style: TextStyle(color: theme.colorScheme.primary),
|
||||
return orig.type == 'DYNAMIC_TYPE_NONE'
|
||||
? const SizedBox.shrink()
|
||||
: InkWell(
|
||||
onTap: isNoneMajor
|
||||
? null
|
||||
: () => PageUtils.pushDynDetail(orig, floor + 1),
|
||||
onLongPress: isNoneMajor
|
||||
? null
|
||||
: () {
|
||||
late String? title, cover;
|
||||
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;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_UGC_SEASON':
|
||||
title = origMajor?.ugcSeason?.title;
|
||||
cover = origMajor?.ugcSeason?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_PGC' || 'DYNAMIC_TYPE_PGC_UNION':
|
||||
title = origMajor?.pgc?.title;
|
||||
cover = origMajor?.pgc?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_LIVE_RCMD':
|
||||
title = major?.liveRcmd?.title;
|
||||
cover = major?.liveRcmd?.cover;
|
||||
break;
|
||||
case 'DYNAMIC_TYPE_LIVE':
|
||||
title = major?.live?.title;
|
||||
cover = major?.live?.cover;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
imageSaveDialog(
|
||||
title: title,
|
||||
cover: cover,
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 15, vertical: 8),
|
||||
color: theme.dividerColor.withValues(alpha: 0.08),
|
||||
child: isNoneMajor
|
||||
? Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.error,
|
||||
size: 18,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
orig.modules.moduleDynamic?.major?.none?.tips ??
|
||||
'NONE',
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: isNormalAuth
|
||||
? () => Get.toNamed(
|
||||
'/member?mid=${orig.modules.moduleAuthor!.mid}',
|
||||
arguments: {
|
||||
'face':
|
||||
orig.modules.moduleAuthor!.face
|
||||
},
|
||||
)
|
||||
: null,
|
||||
child: Text(
|
||||
'${isNormalAuth ? '@' : ''}${orig.modules.moduleAuthor!.name}',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
Utils.dateFormat(
|
||||
orig.modules.moduleAuthor!.pubTs),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize:
|
||||
theme.textTheme.labelSmall!.fontSize),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
content(
|
||||
theme, isSave, context, orig, isDetail, callback,
|
||||
floor: floor + 1),
|
||||
module(
|
||||
theme, isSave, orig, context, isDetail, callback,
|
||||
floor: floor + 1),
|
||||
if (orig.modules.moduleDynamic?.additional != null)
|
||||
addWidget(theme, orig, context, floor: floor + 1),
|
||||
if (orig.modules.moduleDynamic?.major?.blocked !=
|
||||
null)
|
||||
blockedItem(theme,
|
||||
orig.modules.moduleDynamic!.major!.blocked!),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
Utils.dateFormat(orig.modules.moduleAuthor!.pubTs),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
content(theme, isSave, context, orig, source, callback,
|
||||
floor: floor + 1),
|
||||
],
|
||||
module(theme, isSave, orig, context, source, callback,
|
||||
floor: floor + 1),
|
||||
if (orig.modules.moduleDynamic?.additional != null)
|
||||
addWidget(theme, orig, context, floor: floor + 1),
|
||||
if (orig.modules.moduleDynamic?.major?.blocked != null)
|
||||
blockedItem(theme, orig.modules.moduleDynamic!.major!.blocked!),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
),
|
||||
);
|
||||
// 直播
|
||||
case 'DYNAMIC_TYPE_LIVE_RCMD':
|
||||
return liveRcmdPanel(theme, source, item, context, floor: floor);
|
||||
return liveRcmdPanel(theme, isDetail, item, context, floor: floor);
|
||||
// 直播
|
||||
case 'DYNAMIC_TYPE_LIVE':
|
||||
return livePanel(theme, source, item, context, floor: floor);
|
||||
return livePanel(theme, isDetail, item, context, floor: floor);
|
||||
// 合集
|
||||
case 'DYNAMIC_TYPE_UGC_SEASON':
|
||||
return videoSeasonWidget(
|
||||
theme, isSave, source, item, context, 'ugcSeason', callback);
|
||||
theme, isSave, isDetail, item, context, 'ugcSeason', callback);
|
||||
case 'DYNAMIC_TYPE_PGC':
|
||||
return videoSeasonWidget(
|
||||
theme, isSave, source, item, context, 'pgc', callback,
|
||||
theme, isSave, isDetail, item, context, 'pgc', callback,
|
||||
floor: floor);
|
||||
case 'DYNAMIC_TYPE_PGC_UNION':
|
||||
return videoSeasonWidget(
|
||||
theme, isSave, source, item, context, 'pgc', callback,
|
||||
theme, isSave, isDetail, item, context, 'pgc', callback,
|
||||
floor: floor);
|
||||
case 'DYNAMIC_TYPE_NONE':
|
||||
return Row(
|
||||
@@ -342,7 +368,7 @@ Widget module(
|
||||
case 'DYNAMIC_TYPE_SUBSCRIPTION_NEW'
|
||||
when item.modules.moduleDynamic?.major?.type ==
|
||||
'MAJOR_TYPE_SUBSCRIPTION_NEW':
|
||||
return livePanelSub(theme, source, item, context, floor: floor);
|
||||
return livePanelSub(theme, isDetail, item, context, floor: floor);
|
||||
|
||||
default:
|
||||
return Padding(
|
||||
|
||||
@@ -10,7 +10,7 @@ import 'package:flutter/material.dart';
|
||||
Widget videoSeasonWidget(
|
||||
ThemeData theme,
|
||||
bool isSave,
|
||||
String? source,
|
||||
bool isDetail,
|
||||
DynamicItemModel item,
|
||||
BuildContext context,
|
||||
String type,
|
||||
@@ -29,9 +29,7 @@ Widget videoSeasonWidget(
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
item.modules.moduleDynamic!.major!.none!.tips!,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
style: TextStyle(color: theme.colorScheme.outline),
|
||||
),
|
||||
],
|
||||
)
|
||||
@@ -159,9 +157,9 @@ Widget videoSeasonWidget(
|
||||
: EdgeInsets.zero,
|
||||
child: Text(
|
||||
itemContent.title!,
|
||||
maxLines: source == 'detail' ? null : 1,
|
||||
maxLines: isDetail ? null : 1,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
overflow: source == 'detail' ? null : TextOverflow.ellipsis,
|
||||
overflow: isDetail ? null : TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -137,7 +137,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
id: id,
|
||||
oid: oid,
|
||||
rpid: rpid,
|
||||
source: 'dynamic',
|
||||
isVideoDetail: false,
|
||||
replyType: _controller.replyType,
|
||||
firstFloor: replyItem,
|
||||
onDispose: onDispose,
|
||||
@@ -253,7 +253,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: AuthorPanel(
|
||||
item: _controller.dynItem,
|
||||
source: 'detail', //to remove tag
|
||||
isDetail: true,
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -332,7 +332,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
SliverToBoxAdapter(
|
||||
child: DynamicPanel(
|
||||
item: _controller.dynItem,
|
||||
source: 'detail',
|
||||
isDetail: true,
|
||||
callback: _getImageCallback,
|
||||
),
|
||||
),
|
||||
@@ -363,7 +363,7 @@ class _DynamicDetailPageState extends State<DynamicDetailPage>
|
||||
sliver: SliverToBoxAdapter(
|
||||
child: DynamicPanel(
|
||||
item: _controller.dynItem,
|
||||
source: 'detail',
|
||||
isDetail: true,
|
||||
callback: _getImageCallback,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -512,20 +512,19 @@ class _EpisodePanelState extends CommonSlidePageState<EpisodePanel> {
|
||||
if (view != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: view,
|
||||
),
|
||||
if (danmaku != null) ...[
|
||||
const SizedBox(width: 8),
|
||||
if (danmaku != null)
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: danmaku,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -72,7 +72,7 @@ class _FavVideoPageState extends State<FavVideoPage>
|
||||
String heroTag = Utils.makeHeroTag(item.fid);
|
||||
return FavVideoItem(
|
||||
heroTag: heroTag,
|
||||
favFolderItem: item,
|
||||
item: item,
|
||||
onTap: () async {
|
||||
var res = await Get.toNamed(
|
||||
'/favDetail',
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class FavVideoItem extends StatelessWidget {
|
||||
final String heroTag;
|
||||
final FavVideoItemModel favFolderItem;
|
||||
final FavVideoItemModel item;
|
||||
final VoidCallback? onTap;
|
||||
final VoidCallback? onLongPress;
|
||||
|
||||
@@ -16,7 +16,7 @@ class FavVideoItem extends StatelessWidget {
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
required this.heroTag,
|
||||
required this.favFolderItem,
|
||||
required this.item,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -27,8 +27,8 @@ class FavVideoItem extends StatelessWidget {
|
||||
(onTap == null
|
||||
? null
|
||||
: () => imageSaveDialog(
|
||||
title: favFolderItem.title,
|
||||
cover: favFolderItem.cover,
|
||||
title: item.title,
|
||||
cover: item.cover,
|
||||
)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 5),
|
||||
@@ -43,7 +43,7 @@ class FavVideoItem extends StatelessWidget {
|
||||
return Hero(
|
||||
tag: heroTag,
|
||||
child: NetworkImgLayer(
|
||||
src: favFolderItem.cover,
|
||||
src: item.cover,
|
||||
width: boxConstraints.maxWidth,
|
||||
height: boxConstraints.maxHeight,
|
||||
),
|
||||
@@ -52,14 +52,14 @@ class FavVideoItem extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
content(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final fontSize = theme.textTheme.labelMedium!.fontSize;
|
||||
final color = theme.colorScheme.outline;
|
||||
@@ -68,22 +68,22 @@ class FavVideoItem extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
favFolderItem.title ?? '',
|
||||
item.title!,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
),
|
||||
if (favFolderItem.intro?.isNotEmpty == true)
|
||||
if (item.intro?.isNotEmpty == true)
|
||||
Text(
|
||||
favFolderItem.intro!,
|
||||
item.intro!,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${favFolderItem.mediaCount}个内容',
|
||||
'${item.mediaCount}个内容',
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
@@ -91,7 +91,7 @@ class FavVideoItem extends StatelessWidget {
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
Utils.isPublicFavText(favFolderItem.attr ?? 0),
|
||||
Utils.isPublicFavText(item.attr ?? 0),
|
||||
style: TextStyle(
|
||||
fontSize: fontSize,
|
||||
color: color,
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/models_new/fav/fav_detail/data.dart';
|
||||
import 'package:PiliPlus/models_new/fav/fav_detail/media.dart';
|
||||
import 'package:PiliPlus/models_new/fav/fav_video/list.dart';
|
||||
import 'package:PiliPlus/pages/dynamics_repost/view.dart';
|
||||
import 'package:PiliPlus/pages/fav_detail/controller.dart';
|
||||
import 'package:PiliPlus/pages/fav_detail/widget/fav_video_card.dart';
|
||||
import 'package:PiliPlus/pages/fav_sort/view.dart';
|
||||
@@ -134,6 +135,16 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
),
|
||||
icon: const Icon(Icons.search_outlined),
|
||||
),
|
||||
Obx(
|
||||
() => Utils.isPublicFav(_favDetailController.item.value.attr ?? 0)
|
||||
? IconButton(
|
||||
tooltip: '分享',
|
||||
onPressed: () => Utils.shareText(
|
||||
'https://www.bilibili.com/medialist/detail/ml${_favDetailController.mediaId}'),
|
||||
icon: const Icon(Icons.share),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
Obx(
|
||||
() => _favDetailController.isOwner.value
|
||||
? PopupMenuButton(
|
||||
@@ -150,6 +161,23 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
}),
|
||||
child: const Text('编辑信息'),
|
||||
),
|
||||
if (Utils.isPublicFav(
|
||||
_favDetailController.item.value.attr ?? 0))
|
||||
PopupMenuItem(
|
||||
onTap: () => showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useSafeArea: true,
|
||||
builder: (context) => RepostPanel(
|
||||
rid: _favDetailController.mediaId,
|
||||
dynType: 4300,
|
||||
pic: _favDetailController.item.value.cover,
|
||||
title: _favDetailController.item.value.title,
|
||||
uname: _favDetailController.item.value.upper?.name,
|
||||
),
|
||||
),
|
||||
child: const Text('分享至动态'),
|
||||
),
|
||||
PopupMenuItem(
|
||||
onTap: () =>
|
||||
FavHttp.cleanFav(mediaId: mediaId).then((data) {
|
||||
@@ -225,7 +253,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: 10),
|
||||
];
|
||||
|
||||
List<Widget> _selectActions(ThemeData theme) => [
|
||||
@@ -410,7 +438,7 @@ class _FavDetailPageState extends State<FavDetailPage> {
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: FavVideoCardH(
|
||||
videoItem: item,
|
||||
item: item,
|
||||
onDelFav: _favDetailController.isOwner.value
|
||||
? () => _favDetailController.onCancelFav(
|
||||
index,
|
||||
|
||||
@@ -13,7 +13,7 @@ import 'package:get/get.dart';
|
||||
|
||||
// 收藏视频卡片 - 水平布局
|
||||
class FavVideoCardH extends StatelessWidget {
|
||||
final FavDetailItemModel videoItem;
|
||||
final FavDetailItemModel item;
|
||||
final GestureTapCallback? onTap;
|
||||
final GestureLongPressCallback? onLongPress;
|
||||
final VoidCallback? onDelFav;
|
||||
@@ -22,7 +22,7 @@ class FavVideoCardH extends StatelessWidget {
|
||||
|
||||
const FavVideoCardH({
|
||||
super.key,
|
||||
required this.videoItem,
|
||||
required this.item,
|
||||
this.onDelFav,
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
@@ -37,16 +37,16 @@ class FavVideoCardH extends StatelessWidget {
|
||||
? null
|
||||
: onTap ??
|
||||
() {
|
||||
if (!const [0, 16].contains(videoItem.attr)) {
|
||||
Get.toNamed('/member?mid=${videoItem.upper?.mid}');
|
||||
if (!const [0, 16].contains(item.attr)) {
|
||||
Get.toNamed('/member?mid=${item.upper?.mid}');
|
||||
return;
|
||||
}
|
||||
|
||||
// pgc
|
||||
if (videoItem.type == 24) {
|
||||
if (item.type == 24) {
|
||||
PageUtils.viewPgc(
|
||||
seasonId: videoItem.ogv!.seasonId,
|
||||
epId: videoItem.id,
|
||||
seasonId: item.ogv!.seasonId,
|
||||
epId: item.id,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -57,8 +57,8 @@ class FavVideoCardH extends StatelessWidget {
|
||||
? null
|
||||
: onLongPress ??
|
||||
() => imageSaveDialog(
|
||||
title: videoItem.title,
|
||||
cover: videoItem.cover,
|
||||
title: item.title,
|
||||
cover: item.cover,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
@@ -79,18 +79,18 @@ class FavVideoCardH extends StatelessWidget {
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
src: videoItem.cover,
|
||||
src: item.cover,
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
),
|
||||
PBadge(
|
||||
text: Utils.timeFormat(videoItem.duration),
|
||||
text: Utils.timeFormat(item.duration),
|
||||
right: 6.0,
|
||||
bottom: 6.0,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
PBadge(
|
||||
text: videoItem.ogv?.typeName,
|
||||
text: item.ogv?.typeName,
|
||||
top: 6.0,
|
||||
right: 6.0,
|
||||
bottom: null,
|
||||
@@ -102,35 +102,45 @@ class FavVideoCardH extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
content(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(BuildContext context) {
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Column(
|
||||
spacing: 3,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
videoItem.title!,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
Text(
|
||||
item.title!,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
if (item.type == 24 && item.intro?.isNotEmpty == true)
|
||||
Text(
|
||||
item.intro!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
'${Utils.dateFormat(videoItem.favTime)} ${videoItem.upper?.name}',
|
||||
'${Utils.dateFormat(item.favTime)} ${item.upper?.name}',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
@@ -139,23 +149,22 @@ class FavVideoCardH extends StatelessWidget {
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(videoItem.cntInfo?.play),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(videoItem.cntInfo?.danmaku),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
if (item.type != 24)
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(item.cntInfo?.play),
|
||||
),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(item.cntInfo?.danmaku),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
if (onDelFav != null)
|
||||
|
||||
@@ -128,7 +128,7 @@ class _FavFolderSortPageState extends State<FavFolderSortPage> {
|
||||
height: 98,
|
||||
child: FavVideoItem(
|
||||
heroTag: key,
|
||||
favFolderItem: item,
|
||||
item: item,
|
||||
onLongPress:
|
||||
index == 0 ? () => SmartDialog.showToast('默认收藏夹不支持排序') : null,
|
||||
),
|
||||
|
||||
@@ -36,7 +36,7 @@ class _FavSearchPageState extends CommonSearchPageState<FavSearchPage,
|
||||
}
|
||||
final item = list[index];
|
||||
return FavVideoCardH(
|
||||
videoItem: item,
|
||||
item: item,
|
||||
onDelFav: controller.isOwner == true
|
||||
? () => controller.onCancelFav(
|
||||
index,
|
||||
|
||||
@@ -135,7 +135,7 @@ class _FavSortPageState extends State<FavSortPage> {
|
||||
height: 98,
|
||||
child: FavVideoCardH(
|
||||
isSort: true,
|
||||
videoItem: item,
|
||||
item: item,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -275,7 +275,7 @@ class _HistoryPageState extends State<HistoryPage>
|
||||
}
|
||||
final item = response[index];
|
||||
return HistoryItem(
|
||||
videoItem: item,
|
||||
item: item,
|
||||
ctr: _historyController.baseCtr,
|
||||
onChoose: () => _historyController.onSelect(index),
|
||||
onDelete: (kid, business) =>
|
||||
|
||||
@@ -20,14 +20,14 @@ import 'package:get/get.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
class HistoryItem extends StatelessWidget {
|
||||
final HistoryItemModel videoItem;
|
||||
final HistoryItemModel item;
|
||||
final dynamic ctr;
|
||||
final Function? onChoose;
|
||||
final Function(dynamic kid, dynamic business) onDelete;
|
||||
|
||||
const HistoryItem({
|
||||
super.key,
|
||||
required this.videoItem,
|
||||
required this.item,
|
||||
this.ctr,
|
||||
this.onChoose,
|
||||
required this.onDelete,
|
||||
@@ -36,8 +36,8 @@ class HistoryItem extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
int aid = videoItem.history.oid!;
|
||||
String bvid = videoItem.history.bvid ?? IdUtils.av2bv(aid);
|
||||
int aid = item.history.oid!;
|
||||
String bvid = item.history.bvid ?? IdUtils.av2bv(aid);
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
if (ctr is MultiSelectController || ctr is HistoryBaseController) {
|
||||
@@ -46,37 +46,37 @@ class HistoryItem extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (videoItem.history.business?.contains('article') == true) {
|
||||
if (item.history.business?.contains('article') == true) {
|
||||
PageUtils.toDupNamed(
|
||||
'/articlePage',
|
||||
parameters: {
|
||||
'id': videoItem.history.business == 'article-list'
|
||||
? '${videoItem.history.cid}'
|
||||
: '${videoItem.history.oid}',
|
||||
'id': item.history.business == 'article-list'
|
||||
? '${item.history.cid}'
|
||||
: '${item.history.oid}',
|
||||
'type': 'read',
|
||||
},
|
||||
);
|
||||
} else if (videoItem.history.business == 'live') {
|
||||
if (videoItem.liveStatus == 1) {
|
||||
Get.toNamed('/liveRoom?roomid=${videoItem.history.oid}');
|
||||
} else if (item.history.business == 'live') {
|
||||
if (item.liveStatus == 1) {
|
||||
Get.toNamed('/liveRoom?roomid=${item.history.oid}');
|
||||
} else {
|
||||
SmartDialog.showToast('直播未开播');
|
||||
}
|
||||
} else if (videoItem.history.business == 'pgc') {
|
||||
PageUtils.viewPgc(epId: videoItem.history.epid);
|
||||
} else if (item.history.business == 'pgc') {
|
||||
PageUtils.viewPgc(epId: item.history.epid);
|
||||
} else {
|
||||
int? cid = videoItem.history.cid ??
|
||||
int? cid = item.history.cid ??
|
||||
await SearchHttp.ab2c(
|
||||
aid: aid,
|
||||
bvid: bvid,
|
||||
part: videoItem.history.page,
|
||||
part: item.history.page,
|
||||
);
|
||||
if (cid != null) {
|
||||
PageUtils.toVideoPage(
|
||||
'bvid=$bvid&cid=$cid',
|
||||
arguments: {
|
||||
'heroTag': Utils.makeHeroTag(aid),
|
||||
'pic': videoItem.cover,
|
||||
'pic': item.cover,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -91,8 +91,8 @@ class HistoryItem extends StatelessWidget {
|
||||
return;
|
||||
}
|
||||
imageSaveDialog(
|
||||
title: videoItem.title,
|
||||
cover: videoItem.cover,
|
||||
title: item.title,
|
||||
cover: item.cover,
|
||||
);
|
||||
},
|
||||
child: Stack(
|
||||
@@ -117,51 +117,51 @@ class HistoryItem extends StatelessWidget {
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
src: videoItem.cover?.isNotEmpty == true
|
||||
? videoItem.cover
|
||||
: videoItem.covers?.firstOrNull ?? '',
|
||||
src: item.cover?.isNotEmpty == true
|
||||
? item.cover
|
||||
: item.covers?.firstOrNull ?? '',
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
),
|
||||
if (!HistoryBusinessType.hiddenDurationType
|
||||
.contains(videoItem.history.business))
|
||||
.contains(item.history.business))
|
||||
PBadge(
|
||||
text: videoItem.progress == -1
|
||||
text: item.progress == -1
|
||||
? '已看完'
|
||||
: '${Utils.timeFormat(videoItem.progress)}/${Utils.timeFormat(videoItem.duration!)}',
|
||||
: '${Utils.timeFormat(item.progress)}/${Utils.timeFormat(item.duration!)}',
|
||||
right: 6.0,
|
||||
bottom: 8.0,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
// 右上角
|
||||
if (HistoryBusinessType.showBadge
|
||||
.contains(videoItem.history.business) ||
|
||||
videoItem.history.business ==
|
||||
.contains(item.history.business) ||
|
||||
item.history.business ==
|
||||
HistoryBusinessType.live.type)
|
||||
PBadge(
|
||||
text: videoItem.badge,
|
||||
text: item.badge,
|
||||
top: 6.0,
|
||||
right: 6.0,
|
||||
bottom: null,
|
||||
left: null,
|
||||
),
|
||||
if (videoItem.duration != null &&
|
||||
videoItem.duration != 0 &&
|
||||
videoItem.progress != null &&
|
||||
videoItem.progress != 0)
|
||||
if (item.duration != null &&
|
||||
item.duration != 0 &&
|
||||
item.progress != null &&
|
||||
item.progress != 0)
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
child: videoProgressIndicator(
|
||||
videoItem.progress == -1
|
||||
item.progress == -1
|
||||
? 1
|
||||
: videoItem.progress! / videoItem.duration!,
|
||||
: item.progress! / item.duration!,
|
||||
),
|
||||
),
|
||||
Positioned.fill(
|
||||
child: AnimatedOpacity(
|
||||
opacity: videoItem.checked == true ? 1 : 0,
|
||||
opacity: item.checked == true ? 1 : 0,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
@@ -173,7 +173,7 @@ class HistoryItem extends StatelessWidget {
|
||||
width: 34,
|
||||
height: 34,
|
||||
child: AnimatedScale(
|
||||
scale: videoItem.checked == true ? 1 : 0,
|
||||
scale: item.checked == true ? 1 : 0,
|
||||
duration: const Duration(milliseconds: 250),
|
||||
curve: Curves.easeInOut,
|
||||
child: IconButton(
|
||||
@@ -207,7 +207,7 @@ class HistoryItem extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(theme),
|
||||
content(theme),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -227,13 +227,13 @@ class HistoryItem extends StatelessWidget {
|
||||
),
|
||||
position: PopupMenuPosition.under,
|
||||
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
||||
if (videoItem.authorMid != null &&
|
||||
videoItem.authorName?.isNotEmpty == true)
|
||||
if (item.authorMid != null &&
|
||||
item.authorName?.isNotEmpty == true)
|
||||
PopupMenuItem<String>(
|
||||
onTap: () => Get.toNamed(
|
||||
'/member?mid=${videoItem.authorMid}',
|
||||
'/member?mid=${item.authorMid}',
|
||||
arguments: {
|
||||
'heroTag': '${videoItem.authorMid}',
|
||||
'heroTag': '${item.authorMid}',
|
||||
},
|
||||
),
|
||||
height: 35,
|
||||
@@ -242,21 +242,21 @@ class HistoryItem extends StatelessWidget {
|
||||
const Icon(MdiIcons.accountCircleOutline, size: 16),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'访问:${videoItem.authorName}',
|
||||
'访问:${item.authorName}',
|
||||
style: const TextStyle(fontSize: 13),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if (videoItem.history.business != 'pgc' &&
|
||||
videoItem.badge != '番剧' &&
|
||||
videoItem.tagName?.contains('动画') != true &&
|
||||
videoItem.history.business != 'live' &&
|
||||
videoItem.history.business?.contains('article') != true)
|
||||
if (item.history.business != 'pgc' &&
|
||||
item.badge != '番剧' &&
|
||||
item.tagName?.contains('动画') != true &&
|
||||
item.history.business != 'live' &&
|
||||
item.history.business?.contains('article') != true)
|
||||
PopupMenuItem<String>(
|
||||
onTap: () async {
|
||||
var res = await UserHttp.toViewLater(
|
||||
bvid: videoItem.history.bvid);
|
||||
var res =
|
||||
await UserHttp.toViewLater(bvid: item.history.bvid);
|
||||
SmartDialog.showToast(res['msg']);
|
||||
},
|
||||
height: 35,
|
||||
@@ -269,8 +269,7 @@ class HistoryItem extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
onTap: () =>
|
||||
onDelete(videoItem.kid, videoItem.history.business),
|
||||
onTap: () => onDelete(item.kid, item.history.business),
|
||||
height: 35,
|
||||
child: const Row(
|
||||
children: [
|
||||
@@ -289,27 +288,37 @@ class HistoryItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(ThemeData theme) {
|
||||
Widget content(ThemeData theme) {
|
||||
return Expanded(
|
||||
child: Column(
|
||||
spacing: 2,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
videoItem.title!,
|
||||
textAlign: TextAlign.start,
|
||||
Text(
|
||||
item.title!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
maxLines: item.videos! > 1 ? 1 : 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
if (item.history.business == 'pgc' &&
|
||||
item.showTitle?.isNotEmpty == true)
|
||||
Text(
|
||||
item.showTitle!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
maxLines: videoItem.videos! > 1 ? 1 : 2,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (videoItem.authorName != '')
|
||||
const Spacer(),
|
||||
if (item.authorName?.isNotEmpty == true)
|
||||
Text(
|
||||
videoItem.authorName!,
|
||||
item.authorName!,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
@@ -317,9 +326,8 @@ class HistoryItem extends StatelessWidget {
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
Utils.dateFormat(videoItem.viewAt!),
|
||||
Utils.dateFormat(item.viewAt!),
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
color: theme.colorScheme.outline,
|
||||
|
||||
@@ -35,7 +35,7 @@ class _HistorySearchPageState extends CommonSearchPageState<HistorySearchPage,
|
||||
}
|
||||
final item = list[index];
|
||||
return HistoryItem(
|
||||
videoItem: item,
|
||||
item: item,
|
||||
ctr: controller,
|
||||
onChoose: null,
|
||||
onDelete: (kid, business) {
|
||||
|
||||
@@ -93,7 +93,7 @@ class HomeController extends GetxController
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
void showUserInfoDialog(context) {
|
||||
void showUserInfoDialog(BuildContext context) {
|
||||
feedBack();
|
||||
showDialog(
|
||||
context: context,
|
||||
|
||||
@@ -3,11 +3,11 @@ import 'package:PiliPlus/common/skeleton/video_card_h.dart';
|
||||
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
|
||||
import 'package:PiliPlus/common/widgets/loading_widget/http_error.dart';
|
||||
import 'package:PiliPlus/common/widgets/refresh_indicator.dart';
|
||||
import 'package:PiliPlus/common/widgets/video_card/video_card_h.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/models_new/later/list.dart';
|
||||
import 'package:PiliPlus/pages/later/controller.dart';
|
||||
import 'package:PiliPlus/pages/later/widgets/video_card_h_later.dart';
|
||||
import 'package:PiliPlus/utils/grid.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
@@ -56,7 +56,7 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBody(LoadingState<List<HotVideoItemModel>?> loadingState) {
|
||||
Widget _buildBody(LoadingState<List<LaterItemModel>?> loadingState) {
|
||||
final theme = Theme.of(context);
|
||||
return switch (loadingState) {
|
||||
Loading() => SliverGrid(
|
||||
@@ -80,9 +80,8 @@ class _LaterViewChildPageState extends State<LaterViewChildPage>
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
VideoCardH(
|
||||
VideoCardHLater(
|
||||
videoItem: videoItem,
|
||||
source: 'later',
|
||||
onViewLater: (cid) {
|
||||
PageUtils.toVideoPage(
|
||||
'bvid=${videoItem.bvid}&cid=$cid',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'package:PiliPlus/common/widgets/dialog/dialog.dart';
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/http/user.dart';
|
||||
import 'package:PiliPlus/models/common/later_view_type.dart';
|
||||
import 'package:PiliPlus/models/model_hot_video_item.dart';
|
||||
import 'package:PiliPlus/models_new/later/data.dart';
|
||||
import 'package:PiliPlus/models_new/later/list.dart';
|
||||
import 'package:PiliPlus/pages/common/multi_select_controller.dart';
|
||||
import 'package:PiliPlus/pages/later/base_controller.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
@@ -13,8 +15,10 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class LaterController extends MultiSelectController<Map, HotVideoItemModel> {
|
||||
LaterController(this.laterViewType);
|
||||
class LaterController extends MultiSelectController<LaterData, LaterItemModel> {
|
||||
LaterController(
|
||||
this.laterViewType,
|
||||
);
|
||||
final LaterViewType laterViewType;
|
||||
|
||||
dynamic mid;
|
||||
@@ -23,7 +27,7 @@ class LaterController extends MultiSelectController<Map, HotVideoItemModel> {
|
||||
final LaterBaseController baseCtr = Get.put(LaterBaseController());
|
||||
|
||||
@override
|
||||
Future<LoadingState<Map>> customGetData() => UserHttp.seeYouLater(
|
||||
Future<LoadingState<LaterData>> customGetData() => UserHttp.seeYouLater(
|
||||
page: page,
|
||||
viewed: laterViewType.type,
|
||||
asc: asc.value,
|
||||
@@ -31,7 +35,7 @@ class LaterController extends MultiSelectController<Map, HotVideoItemModel> {
|
||||
|
||||
@override
|
||||
void onSelect(int index, [bool disableSelect = true]) {
|
||||
List<HotVideoItemModel> list = loadingState.value.data!;
|
||||
List<LaterItemModel> list = loadingState.value.data!;
|
||||
list[index].checked = !(list[index].checked ?? false);
|
||||
baseCtr.checkedCount.value =
|
||||
list.where((item) => item.checked == true).length;
|
||||
@@ -44,9 +48,9 @@ class LaterController extends MultiSelectController<Map, HotVideoItemModel> {
|
||||
@override
|
||||
void handleSelect([bool checked = false, bool disableSelect = true]) {
|
||||
if (loadingState.value.isSuccess) {
|
||||
List<HotVideoItemModel>? list = loadingState.value.data;
|
||||
List<LaterItemModel>? list = loadingState.value.data;
|
||||
if (list?.isNotEmpty == true) {
|
||||
for (HotVideoItemModel item in list!) {
|
||||
for (LaterItemModel item in list!) {
|
||||
item.checked = checked;
|
||||
}
|
||||
baseCtr.checkedCount.value = checked ? list.length : 0;
|
||||
@@ -66,8 +70,9 @@ class LaterController extends MultiSelectController<Map, HotVideoItemModel> {
|
||||
}
|
||||
|
||||
@override
|
||||
List<HotVideoItemModel>? getDataList(response) {
|
||||
return response['list'];
|
||||
List<LaterItemModel>? getDataList(response) {
|
||||
baseCtr.counts[laterViewType] = response.count ?? 0;
|
||||
return response.list;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -77,12 +82,6 @@ class LaterController extends MultiSelectController<Map, HotVideoItemModel> {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool customHandleResponse(bool isRefresh, Success response) {
|
||||
baseCtr.counts[laterViewType] = response.response['count'];
|
||||
return false;
|
||||
}
|
||||
|
||||
// single
|
||||
void toViewDel(BuildContext context, int index, int? aid) {
|
||||
showDialog(
|
||||
@@ -180,12 +179,12 @@ class LaterController extends MultiSelectController<Map, HotVideoItemModel> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onDelete(List<HotVideoItemModel> result) async {
|
||||
Future<void> _onDelete(List<LaterItemModel> result) async {
|
||||
SmartDialog.showLoading(msg: '请求中');
|
||||
List<int?> aids = result.map((item) => item.aid).toList();
|
||||
var res = await UserHttp.toViewDel(aids: aids);
|
||||
if (res['status']) {
|
||||
Set<HotVideoItemModel> remainList =
|
||||
Set<LaterItemModel> remainList =
|
||||
loadingState.value.data!.toSet().difference(result.toSet());
|
||||
baseCtr.counts[laterViewType] =
|
||||
baseCtr.counts[laterViewType]! - aids.length;
|
||||
@@ -202,10 +201,10 @@ class LaterController extends MultiSelectController<Map, HotVideoItemModel> {
|
||||
// 稍后再看播放全部
|
||||
void toViewPlayAll() {
|
||||
if (loadingState.value.isSuccess) {
|
||||
List<HotVideoItemModel>? list = loadingState.value.data;
|
||||
List<LaterItemModel>? list = loadingState.value.data;
|
||||
if (list.isNullOrEmpty) return;
|
||||
|
||||
for (HotVideoItemModel item in list!) {
|
||||
for (LaterItemModel item in list!) {
|
||||
if (item.cid == null || item.pgcLabel?.isNotEmpty == true) {
|
||||
continue;
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:PiliPlus/common/widgets/scroll_physics.dart';
|
||||
import 'package:PiliPlus/models/common/later_view_type.dart';
|
||||
import 'package:PiliPlus/models/model_hot_video_item.dart';
|
||||
import 'package:PiliPlus/models_new/later/data.dart';
|
||||
import 'package:PiliPlus/models_new/later/list.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';
|
||||
@@ -266,7 +267,7 @@ class _LaterPageState extends State<LaterPage>
|
||||
),
|
||||
onPressed: () {
|
||||
final ctr = currCtr();
|
||||
RequestUtils.onCopyOrMove<Map, HotVideoItemModel>(
|
||||
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>(
|
||||
context: context,
|
||||
isCopy: true,
|
||||
ctr: ctr,
|
||||
@@ -287,7 +288,7 @@ class _LaterPageState extends State<LaterPage>
|
||||
),
|
||||
onPressed: () {
|
||||
final ctr = currCtr();
|
||||
RequestUtils.onCopyOrMove<Map, HotVideoItemModel>(
|
||||
RequestUtils.onCopyOrMove<LaterData, LaterItemModel>(
|
||||
context: context,
|
||||
isCopy: false,
|
||||
ctr: ctr,
|
||||
|
||||
226
lib/pages/later/widgets/video_card_h_later.dart
Normal file
226
lib/pages/later/widgets/video_card_h_later.dart
Normal file
@@ -0,0 +1,226 @@
|
||||
import 'package:PiliPlus/common/constants.dart';
|
||||
import 'package:PiliPlus/common/widgets/badge.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/image_save.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/common/widgets/progress_bar/video_progress_indicator.dart';
|
||||
import 'package:PiliPlus/common/widgets/stat/stat.dart';
|
||||
import 'package:PiliPlus/http/search.dart';
|
||||
import 'package:PiliPlus/models/common/badge_type.dart';
|
||||
import 'package:PiliPlus/models/search/result.dart';
|
||||
import 'package:PiliPlus/models_new/later/list.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
|
||||
// 视频卡片 - 水平布局
|
||||
class VideoCardHLater extends StatelessWidget {
|
||||
const VideoCardHLater({
|
||||
super.key,
|
||||
required this.videoItem,
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.onViewLater,
|
||||
});
|
||||
final LaterItemModel videoItem;
|
||||
final VoidCallback? onTap;
|
||||
final VoidCallback? onLongPress;
|
||||
final ValueChanged<int>? onViewLater;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String type = 'video';
|
||||
if (videoItem case SearchVideoItemModel item) {
|
||||
var typeOrNull = item.type;
|
||||
if (typeOrNull?.isNotEmpty == true) {
|
||||
type = typeOrNull!;
|
||||
}
|
||||
}
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onLongPress: onLongPress ??
|
||||
() => imageSaveDialog(
|
||||
title: videoItem.title,
|
||||
cover: videoItem.pic,
|
||||
),
|
||||
onTap: onTap ??
|
||||
() async {
|
||||
if (type == 'ketang') {
|
||||
SmartDialog.showToast('课堂视频暂不支持播放');
|
||||
return;
|
||||
}
|
||||
if (videoItem.isPgc == true) {
|
||||
if (videoItem.bangumi?.epId != null) {
|
||||
PageUtils.viewPgc(epId: videoItem.bangumi!.epId);
|
||||
} else if (videoItem.redirectUrl?.isNotEmpty == true) {
|
||||
PageUtils.viewPgcFromUri(videoItem.redirectUrl!);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final int? cid = videoItem.cid ??
|
||||
await SearchHttp.ab2c(
|
||||
aid: videoItem.aid, bvid: videoItem.bvid);
|
||||
if (cid != null) {
|
||||
onViewLater!(cid);
|
||||
}
|
||||
} catch (err) {
|
||||
SmartDialog.showToast(err.toString());
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: StyleString.safeSpace,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, boxConstraints) {
|
||||
final double maxWidth = boxConstraints.maxWidth;
|
||||
final double maxHeight = boxConstraints.maxHeight;
|
||||
num? progress = videoItem.progress;
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
src: videoItem.pic,
|
||||
width: maxWidth,
|
||||
height: maxHeight,
|
||||
),
|
||||
PBadge(
|
||||
text: videoItem.pgcLabel,
|
||||
top: 6.0,
|
||||
right: 6.0,
|
||||
),
|
||||
if (progress != null && progress != 0) ...[
|
||||
PBadge(
|
||||
text: progress == -1
|
||||
? '已看完'
|
||||
: '${Utils.timeFormat(progress)}/${Utils.timeFormat(videoItem.duration)}',
|
||||
right: 6,
|
||||
bottom: 8,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
Positioned(
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: videoProgressIndicator(
|
||||
progress == -1
|
||||
? 1
|
||||
: progress / videoItem.duration!,
|
||||
),
|
||||
)
|
||||
] else if (videoItem.duration! > 0)
|
||||
PBadge(
|
||||
text: Utils.timeFormat(videoItem.duration),
|
||||
right: 6.0,
|
||||
bottom: 6.0,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
if (type != 'video')
|
||||
PBadge(
|
||||
text: type,
|
||||
left: 6.0,
|
||||
bottom: 6.0,
|
||||
type: PBadgeType.primary,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
content(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (videoItem.isPgc == true && videoItem.bangumi != null) ...[
|
||||
Text(
|
||||
videoItem.bangumi!.season!.title!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Text(
|
||||
videoItem.subtitle!,
|
||||
textAlign: TextAlign.start,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const Spacer(),
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(videoItem.stat?.view),
|
||||
),
|
||||
] else ...[
|
||||
Expanded(
|
||||
child: Text(
|
||||
videoItem.title!,
|
||||
style: TextStyle(
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
height: 1.42,
|
||||
letterSpacing: 0.3,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
videoItem.owner!.name!,
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
height: 1,
|
||||
color: theme.colorScheme.outline,
|
||||
overflow: TextOverflow.clip,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(videoItem.stat?.view),
|
||||
),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(videoItem.stat?.danmaku),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,26 @@
|
||||
import 'package:PiliPlus/http/loading_state.dart';
|
||||
import 'package:PiliPlus/http/user.dart';
|
||||
import 'package:PiliPlus/models/model_hot_video_item.dart';
|
||||
import 'package:PiliPlus/models_new/later/data.dart';
|
||||
import 'package:PiliPlus/models_new/later/list.dart';
|
||||
import 'package:PiliPlus/pages/common/common_search_controller.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class LaterSearchController
|
||||
extends CommonSearchController<Map, HotVideoItemModel> {
|
||||
extends CommonSearchController<LaterData, LaterItemModel> {
|
||||
dynamic mid = Get.arguments['mid'];
|
||||
dynamic count = Get.arguments['count'];
|
||||
|
||||
@override
|
||||
Future<LoadingState<Map>> customGetData() => UserHttp.seeYouLater(
|
||||
Future<LoadingState<LaterData>> customGetData() => UserHttp.seeYouLater(
|
||||
page: page,
|
||||
keyword: editController.value.text,
|
||||
);
|
||||
|
||||
@override
|
||||
List<HotVideoItemModel>? getDataList(Map response) {
|
||||
return response['list'];
|
||||
List<LaterItemModel>? getDataList(LaterData response) {
|
||||
return response.list;
|
||||
}
|
||||
|
||||
Future<void> toViewDel(BuildContext context, int index, aid) async {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
|
||||
import 'package:PiliPlus/common/widgets/video_card/video_card_h.dart';
|
||||
import 'package:PiliPlus/models/model_hot_video_item.dart';
|
||||
import 'package:PiliPlus/models_new/later/data.dart';
|
||||
import 'package:PiliPlus/models_new/later/list.dart';
|
||||
import 'package:PiliPlus/pages/common/common_search_page.dart';
|
||||
import 'package:PiliPlus/pages/later/widgets/video_card_h_later.dart';
|
||||
import 'package:PiliPlus/pages/later_search/controller.dart';
|
||||
import 'package:PiliPlus/utils/grid.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
@@ -17,7 +18,7 @@ class LaterSearchPage extends CommonSearchPage {
|
||||
}
|
||||
|
||||
class _LaterSearchPageState
|
||||
extends CommonSearchPageState<LaterSearchPage, Map, HotVideoItemModel> {
|
||||
extends CommonSearchPageState<LaterSearchPage, LaterData, LaterItemModel> {
|
||||
@override
|
||||
final LaterSearchController controller = Get.put(
|
||||
LaterSearchController(),
|
||||
@@ -25,7 +26,7 @@ class _LaterSearchPageState
|
||||
);
|
||||
|
||||
@override
|
||||
Widget buildList(List<HotVideoItemModel> list) {
|
||||
Widget buildList(List<LaterItemModel> list) {
|
||||
return SliverGrid(
|
||||
gridDelegate: Grid.videoCardHDelegate(context, minHeight: 110),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
@@ -38,9 +39,8 @@ class _LaterSearchPageState
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
VideoCardH(
|
||||
VideoCardHLater(
|
||||
videoItem: item,
|
||||
source: 'later',
|
||||
onViewLater: (cid) {
|
||||
PageUtils.toVideoPage(
|
||||
'bvid=${item.bvid}&cid=$cid',
|
||||
|
||||
@@ -66,7 +66,7 @@ class LiveCardVApp extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget liveContent(context) {
|
||||
Widget liveContent(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
flex: 1,
|
||||
@@ -107,7 +107,7 @@ class LiveCardVApp extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoStat(context) {
|
||||
Widget videoStat(BuildContext context) {
|
||||
return Container(
|
||||
height: 50,
|
||||
padding: const EdgeInsets.only(top: 26, left: 10, right: 10),
|
||||
|
||||
@@ -66,7 +66,7 @@ class LiveCardVFollow extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget liveContent(context) {
|
||||
Widget liveContent(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
flex: 1,
|
||||
@@ -107,7 +107,7 @@ class LiveCardVFollow extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoStat(context) {
|
||||
Widget videoStat(BuildContext context) {
|
||||
return Container(
|
||||
height: 50,
|
||||
padding: const EdgeInsets.only(top: 26, left: 10, right: 10),
|
||||
|
||||
@@ -105,7 +105,7 @@ class _LiveRoomPageState extends State<LiveRoomPage>
|
||||
}
|
||||
}
|
||||
|
||||
double _getFontSize(isFullScreen) {
|
||||
double _getFontSize(bool isFullScreen) {
|
||||
return isFullScreen == false || _isPipMode == true
|
||||
? 15 * plPlayerController.fontSize
|
||||
: 15 * plPlayerController.fontSizeFS;
|
||||
|
||||
@@ -78,7 +78,7 @@ class LiveCardVSearch extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoStat(context) {
|
||||
Widget videoStat(BuildContext context) {
|
||||
return Container(
|
||||
height: 50,
|
||||
padding: const EdgeInsets.only(top: 26, left: 10, right: 10),
|
||||
|
||||
@@ -95,14 +95,14 @@ class VideoCardVMemberHome extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
videoContent(context)
|
||||
content(context)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(BuildContext context) {
|
||||
Widget content(BuildContext context) {
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(6, 5, 6, 5),
|
||||
|
||||
@@ -58,14 +58,14 @@ class SeasonSeriesCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
content(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Column(
|
||||
|
||||
@@ -165,7 +165,7 @@ class VideoCardHMemberVideo extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context, theme),
|
||||
content(context, theme),
|
||||
],
|
||||
);
|
||||
},
|
||||
@@ -185,7 +185,7 @@ class VideoCardHMemberVideo extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(BuildContext context, ThemeData theme) {
|
||||
Widget content(BuildContext context, ThemeData theme) {
|
||||
final isCurr = fromViewAid == videoItem.param ||
|
||||
(videoItem.bvid != null && videoItem.bvid == bvid);
|
||||
return Expanded(
|
||||
@@ -221,13 +221,13 @@ class VideoCardHMemberVideo extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: videoItem.stat.viewStr,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
|
||||
@@ -66,14 +66,14 @@ class PgcCardV extends StatelessWidget {
|
||||
);
|
||||
}),
|
||||
),
|
||||
bagumiContent(context)
|
||||
content(context)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget bagumiContent(context) {
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final style = TextStyle(
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize,
|
||||
|
||||
@@ -59,14 +59,14 @@ class PgcCardVTimeline extends StatelessWidget {
|
||||
);
|
||||
}),
|
||||
),
|
||||
bagumiContent(context)
|
||||
content(context)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget bagumiContent(context) {
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
|
||||
@@ -61,14 +61,14 @@ class PgcCardVPgcIndex extends StatelessWidget {
|
||||
);
|
||||
}),
|
||||
),
|
||||
bagumiContent(context)
|
||||
conetent(context)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget bagumiContent(context) {
|
||||
Widget conetent(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
|
||||
@@ -323,7 +323,7 @@ class _SavePanelState extends State<SavePanel> {
|
||||
IgnorePointer(
|
||||
child: DynamicPanel(
|
||||
item: _item,
|
||||
source: 'detail',
|
||||
isDetail: true,
|
||||
isSave: true,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -88,14 +88,14 @@ class SubItem extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
content(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
Widget content(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final style = TextStyle(
|
||||
fontSize: 13,
|
||||
|
||||
@@ -24,17 +24,15 @@ class SubVideoCardH extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int id = videoItem.id!;
|
||||
String bvid = videoItem.bvid!;
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
int? cid = await SearchHttp.ab2c(bvid: bvid);
|
||||
int? cid = await SearchHttp.ab2c(bvid: videoItem.bvid);
|
||||
if (cid != null) {
|
||||
PageUtils.toVideoPage(
|
||||
'bvid=$bvid&cid=$cid',
|
||||
'bvid=${videoItem.bvid}&cid=$cid',
|
||||
arguments: {
|
||||
'videoItem': videoItem,
|
||||
'heroTag': Utils.makeHeroTag(id),
|
||||
'heroTag': Utils.makeHeroTag(videoItem.id),
|
||||
'videoType': SearchType.video,
|
||||
},
|
||||
);
|
||||
@@ -79,21 +77,21 @@ class SubVideoCardH extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
videoContent(context),
|
||||
content(context),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget videoContent(context) {
|
||||
Widget content(BuildContext context) {
|
||||
return Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'${videoItem.title}',
|
||||
videoItem.title!,
|
||||
textAlign: TextAlign.start,
|
||||
style: const TextStyle(
|
||||
letterSpacing: 0.3,
|
||||
@@ -111,19 +109,18 @@ class SubVideoCardH extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(videoItem.cntInfo?.play),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(videoItem.cntInfo?.danmaku),
|
||||
),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -6,19 +6,19 @@ import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class AiDetail extends CommonCollapseSlidePage {
|
||||
final AiConclusionResult modelResult;
|
||||
class AiConclusionPanel extends CommonCollapseSlidePage {
|
||||
final AiConclusionResult item;
|
||||
|
||||
const AiDetail({
|
||||
const AiConclusionPanel({
|
||||
super.key,
|
||||
required this.modelResult,
|
||||
required this.item,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AiDetail> createState() => _AiDetailState();
|
||||
State<AiConclusionPanel> createState() => _AiDetailState();
|
||||
}
|
||||
|
||||
class _AiDetailState extends CommonCollapseSlidePageState<AiDetail> {
|
||||
class _AiDetailState extends CommonCollapseSlidePageState<AiConclusionPanel> {
|
||||
@override
|
||||
Widget buildPage(ThemeData theme) {
|
||||
return Material(
|
||||
@@ -56,12 +56,12 @@ class _AiDetailState extends CommonCollapseSlidePageState<AiDetail> {
|
||||
controller: ScrollController(),
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
slivers: [
|
||||
if (widget.modelResult.summary?.isNotEmpty == true) ...[
|
||||
if (widget.item.summary?.isNotEmpty == true) ...[
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||
child: SelectableText(
|
||||
widget.modelResult.summary!,
|
||||
widget.item.summary!,
|
||||
style: const TextStyle(
|
||||
fontSize: 15,
|
||||
height: 1.5,
|
||||
@@ -69,7 +69,7 @@ class _AiDetailState extends CommonCollapseSlidePageState<AiDetail> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.modelResult.outline?.isNotEmpty == true)
|
||||
if (widget.item.outline?.isNotEmpty == true)
|
||||
SliverToBoxAdapter(
|
||||
child: Divider(
|
||||
height: 20,
|
||||
@@ -78,7 +78,7 @@ class _AiDetailState extends CommonCollapseSlidePageState<AiDetail> {
|
||||
),
|
||||
),
|
||||
],
|
||||
if (widget.modelResult.outline?.isNotEmpty == true)
|
||||
if (widget.item.outline?.isNotEmpty == true)
|
||||
SliverPadding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 14,
|
||||
@@ -86,14 +86,14 @@ class _AiDetailState extends CommonCollapseSlidePageState<AiDetail> {
|
||||
bottom: MediaQuery.paddingOf(context).bottom + 80,
|
||||
),
|
||||
sliver: SliverList.builder(
|
||||
itemCount: widget.modelResult.outline!.length,
|
||||
itemCount: widget.item.outline!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (index != 0) const SizedBox(height: 10),
|
||||
SelectableText(
|
||||
widget.modelResult.outline![index].title!,
|
||||
widget.item.outline![index].title!,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
@@ -101,10 +101,9 @@ class _AiDetailState extends CommonCollapseSlidePageState<AiDetail> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
if (widget.modelResult.outline![index].partOutline
|
||||
?.isNotEmpty ==
|
||||
if (widget.item.outline![index].partOutline?.isNotEmpty ==
|
||||
true)
|
||||
...widget.modelResult.outline![index].partOutline!.map(
|
||||
...widget.item.outline![index].partOutline!.map(
|
||||
(item) => Wrap(
|
||||
children: [
|
||||
SelectableText.rich(
|
||||
@@ -122,7 +121,6 @@ class _AiDetailState extends CommonCollapseSlidePageState<AiDetail> {
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
// 跳转到指定位置
|
||||
try {
|
||||
Get.find<VideoDetailController>(
|
||||
tag: Get.arguments['heroTag'])
|
||||
|
||||
@@ -220,7 +220,7 @@ class PgcIntroController extends GetxController {
|
||||
}
|
||||
|
||||
// 分享视频
|
||||
void actionShareVideo(context) {
|
||||
void actionShareVideo(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) {
|
||||
@@ -360,7 +360,7 @@ class PgcIntroController extends GetxController {
|
||||
}
|
||||
|
||||
// 修改分P或番剧分集
|
||||
void changeSeasonOrbangu(epId, bvid, cid, aid, cover) {
|
||||
void changeSeasonOrbangu(dynamic epId, bvid, cid, aid, cover) {
|
||||
// 重新获取视频资源
|
||||
this.epId = epId;
|
||||
this.bvid = bvid;
|
||||
@@ -420,7 +420,7 @@ class PgcIntroController extends GetxController {
|
||||
SmartDialog.showToast(result['msg']);
|
||||
}
|
||||
|
||||
Future<void> pgcUpdate(status) async {
|
||||
Future<void> pgcUpdate(int status) async {
|
||||
var result = await VideoHttp.pgcUpdate(
|
||||
seasonId: [pgcItem.seasonId],
|
||||
status: status,
|
||||
|
||||
@@ -19,13 +19,13 @@ import 'package:flutter/services.dart' show HapticFeedback;
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class PgcIntroPanel extends StatefulWidget {
|
||||
class PgcIntroPage extends StatefulWidget {
|
||||
final int? cid;
|
||||
final String heroTag;
|
||||
final Function showEpisodes;
|
||||
final Function showIntroDetail;
|
||||
|
||||
const PgcIntroPanel({
|
||||
const PgcIntroPage({
|
||||
super.key,
|
||||
this.cid,
|
||||
required this.heroTag,
|
||||
@@ -34,10 +34,10 @@ class PgcIntroPanel extends StatefulWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
State<PgcIntroPanel> createState() => _PgcIntroPanelState();
|
||||
State<PgcIntroPage> createState() => _PgcIntroPageState();
|
||||
}
|
||||
|
||||
class _PgcIntroPanelState extends State<PgcIntroPanel>
|
||||
class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
with AutomaticKeepAliveClientMixin {
|
||||
late PgcIntroController pgcIntroController;
|
||||
late VideoDetailController videoDetailCtr;
|
||||
|
||||
@@ -13,11 +13,11 @@ import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart' hide TabBarView;
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class IntroDetail extends CommonCollapseSlidePage {
|
||||
class PgcIntroPanel extends CommonCollapseSlidePage {
|
||||
final PgcInfoModel item;
|
||||
final List<VideoTagItem>? videoTags;
|
||||
|
||||
const IntroDetail({
|
||||
const PgcIntroPanel({
|
||||
super.key,
|
||||
required this.item,
|
||||
super.enableSlide = false,
|
||||
@@ -25,10 +25,10 @@ class IntroDetail extends CommonCollapseSlidePage {
|
||||
});
|
||||
|
||||
@override
|
||||
State<IntroDetail> createState() => _IntroDetailState();
|
||||
State<PgcIntroPanel> createState() => _IntroDetailState();
|
||||
}
|
||||
|
||||
class _IntroDetailState extends CommonCollapseSlidePageState<IntroDetail> {
|
||||
class _IntroDetailState extends CommonCollapseSlidePageState<PgcIntroPanel> {
|
||||
late final _tabController = TabController(length: 2, vsync: this);
|
||||
final _controller = ScrollController();
|
||||
|
||||
@@ -106,13 +106,13 @@ class _IntroDetailState extends CommonCollapseSlidePageState<IntroDetail> {
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
spacing: 6,
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(widget.item.stat!.views),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
|
||||
@@ -551,6 +551,7 @@ class _VideoInfoState extends State<VideoInfo> {
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
@@ -560,7 +561,6 @@ class _VideoInfoState extends State<VideoInfo> {
|
||||
: videoItem['stat']?.view ?? '-'),
|
||||
textColor: theme.colorScheme.outline,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
@@ -569,7 +569,6 @@ class _VideoInfoState extends State<VideoInfo> {
|
||||
: videoItem['stat']?.danmu ?? '-'),
|
||||
textColor: theme.colorScheme.outline,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
Utils.dateFormat(
|
||||
!widget.isLoading
|
||||
@@ -581,16 +580,13 @@ class _VideoInfoState extends State<VideoInfo> {
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
if (MineController.anonymity.value) ...<Widget>[
|
||||
const SizedBox(width: 10),
|
||||
if (MineController.anonymity.value)
|
||||
Icon(
|
||||
MdiIcons.incognito,
|
||||
size: 15,
|
||||
color: theme.colorScheme.outline,
|
||||
semanticLabel: '无痕',
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 10),
|
||||
if (videoIntroController.isShowOnlineTotal)
|
||||
Obx(
|
||||
() => Text(
|
||||
|
||||
@@ -198,6 +198,16 @@ class _MediaListPanelState
|
||||
width: boxConstraints.maxWidth,
|
||||
height: boxConstraints.maxHeight,
|
||||
),
|
||||
if (item.badge?.text?.isNotEmpty == true)
|
||||
PBadge(
|
||||
text: item.badge?.text,
|
||||
right: 6.0,
|
||||
top: 6.0,
|
||||
type: switch (item.badge?.text) {
|
||||
'充电专属' => PBadgeType.error,
|
||||
_ => PBadgeType.primary,
|
||||
},
|
||||
),
|
||||
PBadge(
|
||||
text: Utils.timeFormat(item.duration!),
|
||||
right: 6.0,
|
||||
@@ -216,7 +226,6 @@ class _MediaListPanelState
|
||||
children: [
|
||||
Text(
|
||||
item.title!,
|
||||
textAlign: TextAlign.start,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
@@ -227,6 +236,19 @@ class _MediaListPanelState
|
||||
: null,
|
||||
),
|
||||
),
|
||||
if (item.type == 24 &&
|
||||
item.intro?.isNotEmpty == true) ...[
|
||||
const SizedBox(height: 3),
|
||||
Text(
|
||||
item.intro!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
],
|
||||
const Spacer(),
|
||||
Text(
|
||||
item.upper!.name!,
|
||||
@@ -237,24 +259,26 @@ class _MediaListPanelState
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(
|
||||
item.cntInfo!.play!),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(
|
||||
item.cntInfo!.danmaku!),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (item.type == 2) ...[
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
StatView(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(
|
||||
item.cntInfo!.play!),
|
||||
),
|
||||
StatDanMu(
|
||||
context: context,
|
||||
theme: 'gray',
|
||||
value: Utils.numFormat(
|
||||
item.cntInfo!.danmaku!),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -218,7 +218,7 @@ class _PayCoinsPageState extends State<PayCoinsPage>
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildBody(isV) => Stack(
|
||||
Widget _buildBody(bool isV) => Stack(
|
||||
key: _key,
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
|
||||
@@ -25,7 +25,7 @@ class VideoReplyReplyPanel extends CommonSlidePage {
|
||||
required this.rpid,
|
||||
this.dialog,
|
||||
this.firstFloor,
|
||||
this.source,
|
||||
required this.isVideoDetail,
|
||||
required this.replyType,
|
||||
this.isDialogue = false,
|
||||
this.onViewImage,
|
||||
@@ -37,7 +37,7 @@ class VideoReplyReplyPanel extends CommonSlidePage {
|
||||
final int rpid;
|
||||
final int? dialog;
|
||||
final ReplyInfo? firstFloor;
|
||||
final String? source;
|
||||
final bool isVideoDetail;
|
||||
final int replyType;
|
||||
final bool isDialogue;
|
||||
final VoidCallback? onViewImage;
|
||||
@@ -118,7 +118,7 @@ class _VideoReplyReplyPanelState
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Column(
|
||||
children: [
|
||||
widget.source == 'videoDetail'
|
||||
widget.isVideoDetail
|
||||
? Container(
|
||||
height: 45,
|
||||
decoration: BoxDecoration(
|
||||
@@ -439,7 +439,7 @@ class _VideoReplyReplyPanelState
|
||||
rpid: replyItem.root.toInt(),
|
||||
dialog: replyItem.dialog.toInt(),
|
||||
replyType: widget.replyType,
|
||||
source: 'videoDetail',
|
||||
isVideoDetail: true,
|
||||
isDialogue: true,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1799,7 +1799,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
] else if (videoDetailController.videoType ==
|
||||
SearchType.media_bangumi)
|
||||
Obx(
|
||||
() => PgcIntroPanel(
|
||||
() => PgcIntroPage(
|
||||
key: pgcPanelKey,
|
||||
heroTag: heroTag,
|
||||
cid: videoDetailController.cid.value,
|
||||
@@ -2027,7 +2027,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
rpid: rpid,
|
||||
firstFloor: replyItem,
|
||||
replyType: 1,
|
||||
source: 'videoDetail',
|
||||
isVideoDetail: true,
|
||||
onViewImage: videoDetailController.onViewImage,
|
||||
onDismissed: videoDetailController.onDismissed,
|
||||
),
|
||||
@@ -2040,7 +2040,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
videoDetailController.childKey.currentState?.showBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
(context) =>
|
||||
AiDetail(modelResult: videoIntroController.aiConclusionResult!),
|
||||
AiConclusionPanel(item: videoIntroController.aiConclusionResult!),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2048,7 +2048,7 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
PgcInfoModel videoDetail, List<VideoTagItem>? videoTags) {
|
||||
videoDetailController.childKey.currentState?.showBottomSheet(
|
||||
backgroundColor: Colors.transparent,
|
||||
(context) => IntroDetail(
|
||||
(context) => PgcIntroPanel(
|
||||
item: videoDetail,
|
||||
videoTags: videoTags,
|
||||
),
|
||||
|
||||
@@ -998,14 +998,7 @@ class PlPlayerController {
|
||||
if (event.startsWith("Failed to open .") ||
|
||||
event.startsWith("Cannot open") ||
|
||||
event.startsWith("Can not open")) {
|
||||
List list = [
|
||||
if (dataSource.videoSource.isNullOrEmpty) '视频',
|
||||
if (dataSource.audioSource.isNullOrEmpty) '音频',
|
||||
];
|
||||
if (list.isNotEmpty) {
|
||||
SmartDialog.showToast('${list.join('、')}源为空');
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
SmartDialog.showToast('视频加载错误, $event');
|
||||
if (kDebugMode) debugPrint('视频加载错误, $event');
|
||||
|
||||
@@ -142,7 +142,7 @@ class PiliScheme {
|
||||
enableSlide: false,
|
||||
oid: int.parse(oid),
|
||||
rpid: rpid,
|
||||
source: 'routePush',
|
||||
isVideoDetail: false,
|
||||
replyType: 1,
|
||||
firstFloor: null,
|
||||
id: commentSecondaryId != null
|
||||
@@ -284,7 +284,7 @@ class PiliScheme {
|
||||
oid: oid,
|
||||
rpid: rootId,
|
||||
id: rpId,
|
||||
source: 'routePush',
|
||||
isVideoDetail: false,
|
||||
replyType: type,
|
||||
firstFloor: null,
|
||||
),
|
||||
@@ -333,7 +333,7 @@ class PiliScheme {
|
||||
enableSlide: false,
|
||||
oid: oid,
|
||||
rpid: rpId,
|
||||
source: 'routePush',
|
||||
isVideoDetail: false,
|
||||
replyType: type,
|
||||
firstFloor: null,
|
||||
),
|
||||
@@ -397,7 +397,7 @@ class PiliScheme {
|
||||
enableSlide: false,
|
||||
oid: oid ?? int.parse(dynId),
|
||||
rpid: rpid,
|
||||
source: 'routePush',
|
||||
isVideoDetail: false,
|
||||
replyType: businessId ?? 17,
|
||||
firstFloor: null,
|
||||
id: commentSecondaryId != null
|
||||
@@ -788,7 +788,7 @@ class PiliScheme {
|
||||
enableSlide: false,
|
||||
oid: int.parse(oid),
|
||||
rpid: int.parse(root),
|
||||
source: 'routePush',
|
||||
isVideoDetail: false,
|
||||
replyType: int.parse(pageType),
|
||||
firstFloor: null,
|
||||
id: commentSecondaryId != null
|
||||
|
||||
Reference in New Issue
Block a user