unify horizontal video models

Signed-off-by: dom <githubaccount56556@proton.me>
This commit is contained in:
dom
2026-04-28 10:32:15 +08:00
parent 80ecd35784
commit 524b6bca1c
8 changed files with 128 additions and 129 deletions

View File

@@ -25,7 +25,7 @@ class VideoProgressIndicator extends LeafRenderObjectWidget {
this.radius = 10,
this.height = 4,
required this.progress,
}) : assert(progress >= 0 && progress <= 1);
});
final Color color;
final Color backgroundColor;
@@ -136,9 +136,9 @@ class RenderProgressBar extends RenderBox {
bottomRight: radius,
);
if (progress == 0) {
if (progress <= 0) {
canvas.drawRRect(rrect, paint..color = _backgroundColor);
} else if (progress == 1) {
} else if (progress >= 1) {
canvas.drawRRect(rrect, paint..color = _color);
} else {
final w = size.width * progress;

View File

@@ -7,18 +7,13 @@ import 'package:PiliPlus/common/widgets/progress_bar/video_progress_indicator.da
import 'package:PiliPlus/common/widgets/stat/stat.dart';
import 'package:PiliPlus/common/widgets/video_popup_menu.dart';
import 'package:PiliPlus/http/search.dart';
import 'package:PiliPlus/models/common/badge_type.dart';
import 'package:PiliPlus/models/common/stat_type.dart';
import 'package:PiliPlus/models/model_hot_video_item.dart';
import 'package:PiliPlus/models/model_video.dart';
import 'package:PiliPlus/models/search/result.dart';
import 'package:PiliPlus/models/horizontal_video_model.dart';
import 'package:PiliPlus/models_new/video/video_detail/dimension.dart';
import 'package:PiliPlus/utils/date_utils.dart';
import 'package:PiliPlus/utils/duration_utils.dart';
import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:flutter/material.dart' hide LayoutBuilder;
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
// 视频卡片 - 水平布局
class VideoCardH extends StatelessWidget {
@@ -29,37 +24,13 @@ class VideoCardH extends StatelessWidget {
this.onViewLater,
this.onRemove,
});
final BaseVideoItemModel videoItem;
final HorizontalVideoModel videoItem;
final VoidCallback? onTap;
final ValueChanged<int>? onViewLater;
final VoidCallback? onRemove;
@override
Widget build(BuildContext context) {
String type = 'video';
String? badge;
if (videoItem case final SearchVideoItemModel item) {
final typeOrNull = item.type;
if (typeOrNull != null && typeOrNull.isNotEmpty) {
type = typeOrNull;
if (type == 'ketang') {
badge = '课堂';
} else if (type == 'live_room') {
badge = '直播';
}
}
if (item.isUnionVideo == 1) {
badge = '合作';
}
} else if (videoItem case final HotVideoItemModel item) {
if (item.isCharging == true) {
badge = '充电专属';
} else if (item.isCooperation == 1) {
badge = '合作';
} else {
badge = item.pgcLabel;
}
}
void onLongPress() => imageSaveDialog(
bvid: videoItem.bvid,
title: videoItem.title,
@@ -67,9 +38,9 @@ class VideoCardH extends StatelessWidget {
);
final theme = Theme.of(context);
return Material(
type: MaterialType.transparency,
type: .transparency,
child: Stack(
clipBehavior: Clip.none,
clipBehavior: .none,
children: [
InkWell(
onLongPress: onLongPress,
@@ -77,33 +48,25 @@ class VideoCardH extends StatelessWidget {
onTap:
onTap ??
() async {
if (type == 'ketang') {
PageUtils.viewPugv(seasonId: videoItem.aid);
if (videoItem.isPugv ?? false) {
PageUtils.viewPugv(seasonId: videoItem.seasonId);
return;
} else if (type == 'live_room') {
if (videoItem case final SearchVideoItemModel item) {
int? roomId = item.id;
if (roomId != null) {
PageUtils.toLiveRoom(roomId);
}
} else {
SmartDialog.showToast(
'err: live_room : ${videoItem.runtimeType}',
);
}
if (videoItem.isLive ?? false) {
if (videoItem.roomId case final roomId?) {
PageUtils.toLiveRoom(roomId);
}
return;
}
Dimension? dimension;
if (videoItem case final HotVideoItemModel item) {
if (item.redirectUrl?.isNotEmpty == true &&
PageUtils.viewPgcFromUri(item.redirectUrl!)) {
return;
}
dimension = item.dimension;
if (videoItem.redirectUrl?.isNotEmpty == true &&
PageUtils.viewPgcFromUri(videoItem.redirectUrl!)) {
return;
}
int? cid = videoItem.cid;
Dimension? dimension = videoItem.dimension;
if (cid == null) {
if (await SearchHttp.ab2cWithDimension(
aid: videoItem.aid,
@@ -125,40 +88,38 @@ class VideoCardH extends StatelessWidget {
}
},
child: Padding(
padding: const EdgeInsets.symmetric(
padding: const .symmetric(
horizontal: Style.safeSpace,
vertical: 5,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
crossAxisAlignment: .start,
children: [
AspectRatio(
aspectRatio: Style.aspectRatio,
child: LayoutBuilder(
builder: (context, boxConstraints) {
final double maxWidth = boxConstraints.maxWidth;
final double maxHeight = boxConstraints.maxHeight;
num? progress;
if (videoItem case final HotVideoItemModel item) {
progress = item.progress;
}
final progress = videoItem.progress;
return Stack(
clipBehavior: Clip.none,
clipBehavior: .none,
children: [
NetworkImgLayer(
src: videoItem.cover,
width: maxWidth,
height: maxHeight,
),
if (badge != null)
if (videoItem.badge case final badge?)
PBadge(
text: badge,
top: 6.0,
right: 6.0,
type: switch (badge) {
'充电专属' => PBadgeType.error,
_ => PBadgeType.primary,
'充电专属' => .error,
_ => .primary,
},
),
if (progress != null && progress != 0) ...[
@@ -168,7 +129,7 @@ class VideoCardH extends StatelessWidget {
: '${DurationUtils.formatDuration(progress)}/${DurationUtils.formatDuration(videoItem.duration)}',
right: 6,
bottom: 8,
type: PBadgeType.gray,
type: .gray,
),
Positioned(
left: 0,
@@ -190,7 +151,7 @@ class VideoCardH extends StatelessWidget {
),
right: 6.0,
bottom: 6.0,
type: PBadgeType.gray,
type: .gray,
),
],
);
@@ -224,45 +185,44 @@ class VideoCardH extends StatelessWidget {
if (pubdate != '') pubdate += ' ';
return Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: .start,
children: [
if (videoItem case final SearchVideoItemModel item) ...[
if (item.titleList?.isNotEmpty == true)
Expanded(
child: Text.rich(
overflow: TextOverflow.ellipsis,
maxLines: 2,
TextSpan(
children: item.titleList!
.map(
(e) => TextSpan(
text: e.text,
style: TextStyle(
fontSize: theme.textTheme.bodyMedium!.fontSize,
height: 1.42,
letterSpacing: 0.3,
color: e.isEm
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
),
if (videoItem.titleList?.isNotEmpty == true)
Expanded(
child: Text.rich(
overflow: .ellipsis,
maxLines: 2,
TextSpan(
children: videoItem.titleList!
.map(
(e) => TextSpan(
text: e.text,
style: TextStyle(
fontSize: theme.textTheme.bodyMedium!.fontSize,
height: 1.42,
letterSpacing: 0.3,
color: e.isEm
? theme.colorScheme.primary
: theme.colorScheme.onSurface,
),
)
.toList(),
),
),
)
.toList(),
),
),
] else
)
else
Expanded(
child: Text(
videoItem.title,
textAlign: TextAlign.start,
textAlign: .start,
style: TextStyle(
fontSize: theme.textTheme.bodyMedium!.fontSize,
height: 1.42,
letterSpacing: 0.3,
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
overflow: .ellipsis,
),
),
Text(
@@ -272,7 +232,7 @@ class VideoCardH extends StatelessWidget {
fontSize: 12,
height: 1,
color: theme.colorScheme.outline,
overflow: TextOverflow.clip,
overflow: .clip,
),
),
const SizedBox(height: 3),
@@ -280,11 +240,11 @@ class VideoCardH extends StatelessWidget {
spacing: 8,
children: [
StatWidget(
type: StatType.play,
type: .play,
value: videoItem.stat.view,
),
StatWidget(
type: StatType.danmaku,
type: .danmaku,
value: videoItem.stat.danmu,
),
],