mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-07-09 02:30:14 +08:00
@@ -12,7 +12,6 @@ import 'package:PiliPlus/pages/video/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/pgc/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/pgc/widgets/pgc_panel.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_item.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_row_item.dart';
|
||||
import 'package:PiliPlus/utils/extension.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -261,148 +260,86 @@ class _PgcIntroPageState extends State<PgcIntroPage>
|
||||
|
||||
Widget actionGrid(ThemeData theme, PgcInfoModel item,
|
||||
PgcIntroController pgcIntroController) {
|
||||
return Material(
|
||||
color: theme.colorScheme.surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 1),
|
||||
child: SizedBox(
|
||||
height: 48,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: <Widget>[
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
|
||||
onTap: () => handleState(pgcIntroController.actionLikeVideo),
|
||||
onLongPress: pgcIntroController.actionOneThree,
|
||||
selectStatus: pgcIntroController.hasLike.value,
|
||||
isLoading: false,
|
||||
semanticsLabel: '点赞',
|
||||
text: Utils.numFormat(item.stat!.likes),
|
||||
needAnim: true,
|
||||
hasTriple: pgcIntroController.hasLike.value &&
|
||||
pgcIntroController.hasCoin &&
|
||||
pgcIntroController.hasFav.value,
|
||||
callBack: (start) {
|
||||
if (start) {
|
||||
HapticFeedback.lightImpact();
|
||||
_coinKey.currentState?.controller?.forward();
|
||||
_favKey.currentState?.controller?.forward();
|
||||
} else {
|
||||
_coinKey.currentState?.controller?.reverse();
|
||||
_favKey.currentState?.controller?.reverse();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
key: _coinKey,
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
selectIcon: const Icon(FontAwesomeIcons.b),
|
||||
onTap: () => handleState(pgcIntroController.actionCoinVideo),
|
||||
selectStatus: pgcIntroController.hasCoin,
|
||||
isLoading: false,
|
||||
semanticsLabel: '投币',
|
||||
text: Utils.numFormat(item.stat!.coins),
|
||||
needAnim: true,
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
key: _favKey,
|
||||
icon: const Icon(FontAwesomeIcons.star),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidStar),
|
||||
onTap: () => pgcIntroController.showFavBottomSheet(context),
|
||||
onLongPress: () => pgcIntroController
|
||||
.showFavBottomSheet(context, type: 'longPress'),
|
||||
selectStatus: pgcIntroController.hasFav.value,
|
||||
isLoading: false,
|
||||
semanticsLabel: '收藏',
|
||||
text: Utils.numFormat(item.stat!.favorite),
|
||||
needAnim: true,
|
||||
),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.comment),
|
||||
selectIcon: const Icon(FontAwesomeIcons.reply),
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
selectStatus: false,
|
||||
isLoading: false,
|
||||
semanticsLabel: '评论',
|
||||
text: Utils.numFormat(item.stat!.reply),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||
onTap: () => pgcIntroController.actionShareVideo(context),
|
||||
selectStatus: false,
|
||||
isLoading: false,
|
||||
semanticsLabel: '转发',
|
||||
text: Utils.numFormat(item.stat!.share),
|
||||
),
|
||||
],
|
||||
return SizedBox(
|
||||
height: 48,
|
||||
child: Row(
|
||||
children: [
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidThumbsUp),
|
||||
onTap: () => handleState(pgcIntroController.actionLikeVideo),
|
||||
onLongPress: pgcIntroController.actionOneThree,
|
||||
selectStatus: pgcIntroController.hasLike.value,
|
||||
isLoading: false,
|
||||
semanticsLabel: '点赞',
|
||||
text: Utils.numFormat(item.stat!.likes),
|
||||
needAnim: true,
|
||||
hasTriple: pgcIntroController.hasLike.value &&
|
||||
pgcIntroController.hasCoin &&
|
||||
pgcIntroController.hasFav.value,
|
||||
callBack: (start) {
|
||||
if (start) {
|
||||
HapticFeedback.lightImpact();
|
||||
_coinKey.currentState?.controller?.forward();
|
||||
_favKey.currentState?.controller?.forward();
|
||||
} else {
|
||||
_coinKey.currentState?.controller?.reverse();
|
||||
_favKey.currentState?.controller?.reverse();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
key: _coinKey,
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
selectIcon: const Icon(FontAwesomeIcons.b),
|
||||
onTap: () => handleState(pgcIntroController.actionCoinVideo),
|
||||
selectStatus: pgcIntroController.hasCoin,
|
||||
isLoading: false,
|
||||
semanticsLabel: '投币',
|
||||
text: Utils.numFormat(item.stat!.coins),
|
||||
needAnim: true,
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
key: _favKey,
|
||||
icon: const Icon(FontAwesomeIcons.star),
|
||||
selectIcon: const Icon(FontAwesomeIcons.solidStar),
|
||||
onTap: () => pgcIntroController.showFavBottomSheet(context),
|
||||
onLongPress: () => pgcIntroController.showFavBottomSheet(context,
|
||||
type: 'longPress'),
|
||||
selectStatus: pgcIntroController.hasFav.value,
|
||||
isLoading: false,
|
||||
semanticsLabel: '收藏',
|
||||
text: Utils.numFormat(item.stat!.favorite),
|
||||
needAnim: true,
|
||||
),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.comment),
|
||||
selectIcon: const Icon(FontAwesomeIcons.reply),
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
selectStatus: false,
|
||||
isLoading: false,
|
||||
semanticsLabel: '评论',
|
||||
text: Utils.numFormat(item.stat!.reply),
|
||||
),
|
||||
ActionItem(
|
||||
icon: const Icon(FontAwesomeIcons.shareFromSquare),
|
||||
onTap: () => pgcIntroController.actionShareVideo(context),
|
||||
selectStatus: false,
|
||||
isLoading: false,
|
||||
semanticsLabel: '转发',
|
||||
text: Utils.numFormat(item.stat!.share),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget actionRow(
|
||||
PgcInfoModel item,
|
||||
PgcIntroController pgcIntroController,
|
||||
VideoDetailController videoDetailCtr,
|
||||
) {
|
||||
return Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Obx(
|
||||
() => ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
onTap: () => handleState(pgcIntroController.actionLikeVideo),
|
||||
selectStatus: pgcIntroController.hasLike.value,
|
||||
isLoading: false,
|
||||
text: item.stat!.likes!.toString(),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
onTap: () => handleState(pgcIntroController.actionCoinVideo),
|
||||
selectStatus: pgcIntroController.hasCoin,
|
||||
isLoading: false,
|
||||
text: item.stat!.coins!.toString(),
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.heart),
|
||||
onTap: () => pgcIntroController.showFavBottomSheet(context),
|
||||
onLongPress: () => pgcIntroController.showFavBottomSheet(context,
|
||||
type: 'longPress'),
|
||||
selectStatus: pgcIntroController.hasFav.value,
|
||||
isLoading: false,
|
||||
text: item.stat!.favorite!.toString(),
|
||||
),
|
||||
),
|
||||
ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.comment),
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
selectStatus: false,
|
||||
isLoading: false,
|
||||
text: item.stat!.reply!.toString(),
|
||||
),
|
||||
ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.share),
|
||||
onTap: () => pgcIntroController.actionShareVideo(context),
|
||||
selectStatus: false,
|
||||
isLoading: false,
|
||||
text: '转发',
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget areasAndPubTime(ThemeData theme, PgcInfoModel item) {
|
||||
return Row(
|
||||
spacing: 6,
|
||||
|
||||
@@ -144,8 +144,8 @@ class _PgcPanelState extends State<PgcPanel> {
|
||||
child: Material(
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
onTap: () {
|
||||
if (item.badge != null &&
|
||||
item.badge == '会员' &&
|
||||
|
||||
@@ -13,7 +13,6 @@ import 'package:PiliPlus/pages/search/widgets/search_text.dart';
|
||||
import 'package:PiliPlus/pages/video/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/controller.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_item.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/action_row_item.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/page.dart';
|
||||
import 'package:PiliPlus/pages/video/introduction/ugc/widgets/season.dart';
|
||||
import 'package:PiliPlus/utils/app_scheme.dart';
|
||||
@@ -435,7 +434,9 @@ class _VideoInfoState extends State<VideoInfo> {
|
||||
'${videoItem['staff'][index].mid}'] ==
|
||||
null
|
||||
? Material(
|
||||
color: Colors.transparent,
|
||||
type:
|
||||
MaterialType.transparency,
|
||||
shape: const CircleBorder(),
|
||||
child: InkWell(
|
||||
customBorder:
|
||||
const CircleBorder(),
|
||||
@@ -837,11 +838,9 @@ class _VideoInfoState extends State<VideoInfo> {
|
||||
|
||||
Widget actionGrid(
|
||||
BuildContext context, VideoIntroController videoIntroController) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(top: 1),
|
||||
return SizedBox(
|
||||
height: 48,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Obx(
|
||||
() => ActionItem(
|
||||
@@ -941,63 +940,6 @@ class _VideoInfoState extends State<VideoInfo> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget actionRow(
|
||||
BuildContext context,
|
||||
VideoIntroController videoIntroController,
|
||||
VideoDetailController videoDetailCtr,
|
||||
) {
|
||||
return Row(children: <Widget>[
|
||||
Obx(
|
||||
() => ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.thumbsUp),
|
||||
onTap: () => handleState(videoIntroController.actionLikeVideo),
|
||||
selectStatus: videoIntroController.hasLike.value,
|
||||
isLoading: widget.isLoading,
|
||||
text: !widget.isLoading ? videoDetail.stat!.like!.toString() : '-',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Obx(
|
||||
() => ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.b),
|
||||
onTap: () => handleState(videoIntroController.actionCoinVideo),
|
||||
selectStatus: videoIntroController.hasCoin,
|
||||
isLoading: widget.isLoading,
|
||||
text: !widget.isLoading ? videoDetail.stat!.coin!.toString() : '-',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Obx(
|
||||
() => ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.heart),
|
||||
onTap: () => videoIntroController.showFavBottomSheet(context),
|
||||
onLongPress: () => videoIntroController.showFavBottomSheet(context,
|
||||
type: 'longPress'),
|
||||
selectStatus: videoIntroController.hasFav.value,
|
||||
isLoading: widget.isLoading,
|
||||
text:
|
||||
!widget.isLoading ? videoDetail.stat!.favorite!.toString() : '-',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.comment),
|
||||
onTap: () => videoDetailCtr.tabCtr.animateTo(1),
|
||||
selectStatus: false,
|
||||
isLoading: widget.isLoading,
|
||||
text: !widget.isLoading ? videoDetail.stat!.reply!.toString() : '-',
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
ActionRowItem(
|
||||
icon: const Icon(FontAwesomeIcons.share),
|
||||
onTap: () => videoIntroController.actionShareVideo(context),
|
||||
selectStatus: false,
|
||||
isLoading: widget.isLoading,
|
||||
text: '转发',
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
InlineSpan buildContent(ThemeData theme, VideoDetailData content) {
|
||||
final List descV2 = content.descV2!;
|
||||
// type
|
||||
@@ -1073,15 +1015,11 @@ class _VideoInfoState extends State<VideoInfo> {
|
||||
return TextSpan(children: spanChildren);
|
||||
case 2:
|
||||
final Color colorSchemePrimary = theme.colorScheme.primary;
|
||||
final String heroTag = Utils.makeHeroTag(currentDesc.bizId);
|
||||
return TextSpan(
|
||||
text: '@${currentDesc.rawText}',
|
||||
style: TextStyle(color: colorSchemePrimary),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => Get.toNamed(
|
||||
'/member?mid=${currentDesc.bizId}',
|
||||
arguments: {'face': '', 'heroTag': heroTag},
|
||||
),
|
||||
..onTap = () => Get.toNamed('/member?mid=${currentDesc.bizId}'),
|
||||
);
|
||||
default:
|
||||
return const TextSpan();
|
||||
|
||||
@@ -136,70 +136,73 @@ class ActionItemState extends State<ActionItem>
|
||||
label: (widget.text ?? "") +
|
||||
(widget.selectStatus ? "已" : "") +
|
||||
widget.semanticsLabel,
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
onTap: _isThumbsUp
|
||||
? null
|
||||
: () {
|
||||
feedBack();
|
||||
widget.onTap?.call();
|
||||
},
|
||||
onLongPress: _isThumbsUp ? null : widget.onLongPress,
|
||||
onTapDown: _isThumbsUp ? (details) => _startLongPress() : null,
|
||||
onTapUp: _isThumbsUp ? (details) => _cancelLongPress() : null,
|
||||
onTapCancel: _isThumbsUp ? () => _cancelLongPress(true) : null,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
if (widget.needAnim && !_hideCircle)
|
||||
CustomPaint(
|
||||
size: const Size(28, 28),
|
||||
painter: _ArcPainter(
|
||||
color: theme.colorScheme.primary,
|
||||
sweepAngle: _animation!.value,
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
onTap: _isThumbsUp
|
||||
? null
|
||||
: () {
|
||||
feedBack();
|
||||
widget.onTap?.call();
|
||||
},
|
||||
onLongPress: _isThumbsUp ? null : widget.onLongPress,
|
||||
onTapDown: _isThumbsUp ? (details) => _startLongPress() : null,
|
||||
onTapUp: _isThumbsUp ? (details) => _cancelLongPress() : null,
|
||||
onTapCancel: _isThumbsUp ? () => _cancelLongPress(true) : null,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
if (widget.needAnim && !_hideCircle)
|
||||
CustomPaint(
|
||||
size: const Size(28, 28),
|
||||
painter: _ArcPainter(
|
||||
color: theme.colorScheme.primary,
|
||||
sweepAngle: _animation!.value,
|
||||
),
|
||||
)
|
||||
else
|
||||
const SizedBox(width: 28, height: 28),
|
||||
Icon(
|
||||
widget.selectStatus
|
||||
? widget.selectIcon!.icon!
|
||||
: widget.icon.icon,
|
||||
size: 18,
|
||||
color: widget.selectStatus
|
||||
? theme.colorScheme.primary
|
||||
: widget.icon.color ?? theme.colorScheme.outline,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.text != null)
|
||||
AnimatedOpacity(
|
||||
opacity: widget.isLoading! ? 0 : 1,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
transitionBuilder:
|
||||
(Widget child, Animation<double> animation) {
|
||||
return ScaleTransition(scale: animation, child: child);
|
||||
},
|
||||
child: Text(
|
||||
widget.text!,
|
||||
key: ValueKey<String>(widget.text!),
|
||||
style: TextStyle(
|
||||
color: widget.selectStatus
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
semanticsLabel: "",
|
||||
),
|
||||
)
|
||||
else
|
||||
const SizedBox(width: 28, height: 28),
|
||||
Icon(
|
||||
widget.selectStatus
|
||||
? widget.selectIcon!.icon!
|
||||
: widget.icon.icon,
|
||||
size: 18,
|
||||
color: widget.selectStatus
|
||||
? theme.colorScheme.primary
|
||||
: widget.icon.color ?? theme.colorScheme.outline,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (widget.text != null)
|
||||
AnimatedOpacity(
|
||||
opacity: widget.isLoading! ? 0 : 1,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
transitionBuilder:
|
||||
(Widget child, Animation<double> animation) {
|
||||
return ScaleTransition(scale: animation, child: child);
|
||||
},
|
||||
child: Text(
|
||||
widget.text!,
|
||||
key: ValueKey<String>(widget.text!),
|
||||
style: TextStyle(
|
||||
color: widget.selectStatus
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.outline,
|
||||
fontSize: theme.textTheme.labelSmall!.fontSize,
|
||||
),
|
||||
semanticsLabel: "",
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import 'package:PiliPlus/utils/feed_back.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ActionRowItem extends StatelessWidget {
|
||||
final Icon? icon;
|
||||
final Icon? selectIcon;
|
||||
final Function? onTap;
|
||||
final bool? isLoading;
|
||||
final String? text;
|
||||
final bool selectStatus;
|
||||
final Function? onLongPress;
|
||||
|
||||
const ActionRowItem({
|
||||
super.key,
|
||||
this.icon,
|
||||
this.selectIcon,
|
||||
this.onTap,
|
||||
this.isLoading,
|
||||
this.text,
|
||||
this.selectStatus = false,
|
||||
this.onLongPress,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Material(
|
||||
color: selectStatus
|
||||
? theme.colorScheme.primaryContainer.withValues(alpha: 0.6)
|
||||
: theme.highlightColor.withValues(alpha: 0.2),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(30)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
onTap: () => {
|
||||
feedBack(),
|
||||
onTap?.call(),
|
||||
},
|
||||
onLongPress: () {
|
||||
feedBack();
|
||||
onLongPress?.call();
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(15, 7, 15, 7),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (icon != null) ...[
|
||||
Icon(icon!.icon!,
|
||||
size: 13,
|
||||
color: selectStatus
|
||||
? theme.colorScheme.primary
|
||||
: theme.colorScheme.onSecondaryContainer),
|
||||
const SizedBox(width: 6),
|
||||
],
|
||||
AnimatedOpacity(
|
||||
opacity: isLoading! ? 0 : 1,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
transitionBuilder:
|
||||
(Widget child, Animation<double> animation) {
|
||||
return ScaleTransition(scale: animation, child: child);
|
||||
},
|
||||
child: Text(
|
||||
text ?? '',
|
||||
key: ValueKey<String>(text ?? ''),
|
||||
style: TextStyle(
|
||||
color: selectStatus ? theme.colorScheme.primary : null,
|
||||
fontSize: theme.textTheme.labelMedium!.fontSize),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,102 +1,6 @@
|
||||
import 'package:PiliPlus/utils/feed_back.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MenuRow extends StatelessWidget {
|
||||
const MenuRow({
|
||||
super.key,
|
||||
this.isLoading,
|
||||
});
|
||||
final bool? isLoading;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
color: theme.colorScheme.surface,
|
||||
padding: const EdgeInsets.only(top: 9, bottom: 9, left: 12),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(children: [
|
||||
ActionRowLineItem(
|
||||
onTap: () => {},
|
||||
isLoading: isLoading,
|
||||
text: '推荐',
|
||||
selectStatus: false,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
ActionRowLineItem(
|
||||
onTap: () => {},
|
||||
isLoading: isLoading,
|
||||
text: '弹幕',
|
||||
selectStatus: false,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
ActionRowLineItem(
|
||||
onTap: () => {},
|
||||
isLoading: isLoading,
|
||||
text: '评论列表',
|
||||
selectStatus: false,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
ActionRowLineItem(
|
||||
onTap: () => {},
|
||||
isLoading: isLoading,
|
||||
text: '播放列表',
|
||||
selectStatus: false,
|
||||
),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget actionRowLineItem(
|
||||
ThemeData theme, Function? onTap, bool? isLoading, String? text,
|
||||
{bool selectStatus = false}) {
|
||||
return Material(
|
||||
color: selectStatus
|
||||
? theme.highlightColor.withValues(alpha: 0.2)
|
||||
: Colors.transparent,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(30)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
onTap: () => {
|
||||
feedBack(),
|
||||
onTap?.call(),
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.fromLTRB(13, 5.5, 13, 4.5),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(30)),
|
||||
border: Border.all(
|
||||
color: selectStatus
|
||||
? Colors.transparent
|
||||
: theme.highlightColor.withValues(alpha: 0.2),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AnimatedOpacity(
|
||||
opacity: isLoading! ? 0 : 1,
|
||||
duration: const Duration(milliseconds: 200),
|
||||
child: Text(
|
||||
text!,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: selectStatus
|
||||
? theme.colorScheme.onSurface
|
||||
: theme.colorScheme.outline),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ActionRowLineItem extends StatelessWidget {
|
||||
const ActionRowLineItem({
|
||||
super.key,
|
||||
@@ -118,12 +22,11 @@ class ActionRowLineItem extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return Material(
|
||||
color: selectStatus
|
||||
? theme.colorScheme.secondaryContainer
|
||||
: Colors.transparent,
|
||||
color: selectStatus ? theme.colorScheme.secondaryContainer : null,
|
||||
type: selectStatus ? MaterialType.canvas : MaterialType.transparency,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(30)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(30)),
|
||||
onTap: () => {
|
||||
feedBack(),
|
||||
onTap?.call(),
|
||||
|
||||
@@ -147,8 +147,8 @@ class _PagesPanelState extends State<PagesPanel> {
|
||||
child: Material(
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
onTap: () {
|
||||
if (widget.showEpisodes == null) {
|
||||
Get.back();
|
||||
|
||||
@@ -90,68 +90,66 @@ class _SeasonPanelState extends State<SeasonPanel> {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final theme = Theme.of(context);
|
||||
return Builder(builder: (BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(
|
||||
top: 8,
|
||||
left: 2,
|
||||
right: 2,
|
||||
),
|
||||
child: Material(
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 8,
|
||||
left: 2,
|
||||
right: 2,
|
||||
),
|
||||
child: Material(
|
||||
color: theme.colorScheme.onInverseSurface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(6)),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
onTap: widget.onTap == false
|
||||
? null
|
||||
: () => widget.showEpisodes(
|
||||
_videoDetailController.seasonIndex.value,
|
||||
videoDetail.ugcSeason,
|
||||
null,
|
||||
_videoDetailController.bvid,
|
||||
null,
|
||||
_videoDetailController.seasonCid,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
'合集:${videoDetail.ugcSeason!.title!}',
|
||||
style: theme.textTheme.labelMedium,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
onTap: widget.onTap == false
|
||||
? null
|
||||
: () => widget.showEpisodes(
|
||||
_videoDetailController.seasonIndex.value,
|
||||
videoDetail.ugcSeason,
|
||||
null,
|
||||
_videoDetailController.bvid,
|
||||
null,
|
||||
_videoDetailController.seasonCid,
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Image.asset(
|
||||
'assets/images/live.png',
|
||||
color: theme.colorScheme.primary,
|
||||
height: 12,
|
||||
semanticLabel: "正在播放:",
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
'合集:${videoDetail.ugcSeason!.title!}',
|
||||
style: theme.textTheme.labelMedium,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Obx(
|
||||
() => Text(
|
||||
'${currentIndex.value + 1}/${episodes.length}',
|
||||
style: theme.textTheme.labelMedium,
|
||||
semanticsLabel:
|
||||
'第${currentIndex.value + 1}集,共${episodes.length}集',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Image.asset(
|
||||
'assets/images/live.png',
|
||||
color: theme.colorScheme.primary,
|
||||
height: 12,
|
||||
semanticLabel: "正在播放:",
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Obx(
|
||||
() => Text(
|
||||
'${currentIndex.value + 1}/${episodes.length}',
|
||||
style: theme.textTheme.labelMedium,
|
||||
semanticsLabel:
|
||||
'第${currentIndex.value + 1}集,共${episodes.length}集',
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios_outlined,
|
||||
size: 13,
|
||||
semanticLabel: '查看',
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
const Icon(
|
||||
Icons.arrow_forward_ios_outlined,
|
||||
size: 13,
|
||||
semanticLabel: '查看',
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _findEpisode() {
|
||||
|
||||
@@ -90,6 +90,7 @@ class _MediaListPanelState
|
||||
automaticallyImplyLeading: false,
|
||||
titleSpacing: 16,
|
||||
title: Text(widget.panelTitle ?? '稍后再看'),
|
||||
backgroundColor: Colors.transparent,
|
||||
actions: [
|
||||
Obx(
|
||||
() => mediumButton(
|
||||
@@ -155,158 +156,163 @@ class _MediaListPanelState
|
||||
final isCurr = item.bvid == widget.getBvId();
|
||||
return SizedBox(
|
||||
height: 98,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
if (item.type != 2) {
|
||||
SmartDialog.showToast('不支持播放该类型视频');
|
||||
return;
|
||||
}
|
||||
Get.back();
|
||||
String bvid = item.bvid!;
|
||||
int? aid = item.aid;
|
||||
String cover = item.cover ?? '';
|
||||
final int? cid =
|
||||
item.cid ?? await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
||||
if (cid != null) {
|
||||
widget.changeMediaList?.call(bvid, cid, aid, cover);
|
||||
}
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
title: item.title,
|
||||
cover: item.cover,
|
||||
aid: item.aid,
|
||||
bvid: item.bvid,
|
||||
),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, boxConstraints) {
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
src: item.cover,
|
||||
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,
|
||||
},
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
if (item.type != 2) {
|
||||
SmartDialog.showToast('不支持播放该类型视频');
|
||||
return;
|
||||
}
|
||||
Get.back();
|
||||
String bvid = item.bvid!;
|
||||
int? aid = item.aid;
|
||||
String cover = item.cover ?? '';
|
||||
final int? cid = item.cid ??
|
||||
await SearchHttp.ab2c(aid: aid, bvid: bvid);
|
||||
if (cid != null) {
|
||||
widget.changeMediaList?.call(bvid, cid, aid, cover);
|
||||
}
|
||||
},
|
||||
onLongPress: () => imageSaveDialog(
|
||||
title: item.title,
|
||||
cover: item.cover,
|
||||
aid: item.aid,
|
||||
bvid: item.bvid,
|
||||
),
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 5,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: StyleString.aspectRatio,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, boxConstraints) {
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
NetworkImgLayer(
|
||||
src: item.cover,
|
||||
width: boxConstraints.maxWidth,
|
||||
height: boxConstraints.maxHeight,
|
||||
),
|
||||
PBadge(
|
||||
text: Utils.timeFormat(item.duration!),
|
||||
right: 6.0,
|
||||
bottom: 6.0,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
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,
|
||||
bottom: 6.0,
|
||||
type: PBadgeType.gray,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.title!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontWeight:
|
||||
isCurr ? FontWeight.bold : null,
|
||||
color: isCurr
|
||||
? theme.colorScheme.primary
|
||||
: null,
|
||||
),
|
||||
),
|
||||
if (item.type == 24 &&
|
||||
item.intro?.isNotEmpty == true) ...[
|
||||
const SizedBox(height: 3),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
item.intro!,
|
||||
item.title!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight:
|
||||
isCurr ? FontWeight.bold : null,
|
||||
color: isCurr
|
||||
? theme.colorScheme.primary
|
||||
: 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!,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
if (item.type == 2) ...[
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
StatWidget(
|
||||
type: StatType.play,
|
||||
value: item.cntInfo!.play,
|
||||
),
|
||||
StatWidget(
|
||||
type: StatType.danmaku,
|
||||
value: item.cntInfo!.danmaku,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
const Spacer(),
|
||||
Text(
|
||||
item.upper!.name!,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
if (item.type == 2) ...[
|
||||
const SizedBox(height: 3),
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
StatWidget(
|
||||
type: StatType.play,
|
||||
value: item.cntInfo!.play,
|
||||
),
|
||||
StatWidget(
|
||||
type: StatType.danmaku,
|
||||
value: item.cntInfo!.danmaku,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (showDelBtn && !isCurr)
|
||||
Positioned(
|
||||
right: 12,
|
||||
bottom: -6,
|
||||
child: InkWell(
|
||||
customBorder: const CircleBorder(),
|
||||
onTap: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定移除该视频?',
|
||||
onConfirm: () => widget.onDelete!(index),
|
||||
),
|
||||
onLongPress: () => widget.onDelete!(index),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(9),
|
||||
child: Icon(
|
||||
Icons.clear,
|
||||
size: 18,
|
||||
color: theme.colorScheme.outline,
|
||||
if (showDelBtn && !isCurr)
|
||||
Positioned(
|
||||
right: 12,
|
||||
bottom: -6,
|
||||
child: InkWell(
|
||||
customBorder: const CircleBorder(),
|
||||
onTap: () => showConfirmDialog(
|
||||
context: context,
|
||||
title: '确定移除该视频?',
|
||||
onConfirm: () => widget.onDelete!(index),
|
||||
),
|
||||
onLongPress: () => widget.onDelete!(index),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(9),
|
||||
child: Icon(
|
||||
Icons.clear,
|
||||
size: 18,
|
||||
color: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -190,26 +190,23 @@ class _HorizontalMemberPageState extends State<HorizontalMemberPage> {
|
||||
_controller.onLoadMore();
|
||||
}
|
||||
final SpaceArchiveItem videoItem = response[index];
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
child: VideoCardHMemberVideo(
|
||||
videoItem: videoItem,
|
||||
bvid: _bvid,
|
||||
onTap: () {
|
||||
final status =
|
||||
widget.videoIntroController.changeSeasonOrbangu(
|
||||
null,
|
||||
videoItem.bvid,
|
||||
videoItem.cid,
|
||||
IdUtils.bv2av(videoItem.bvid!),
|
||||
videoItem.cover,
|
||||
);
|
||||
if (status) {
|
||||
_bvid = videoItem.bvid;
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
),
|
||||
return VideoCardHMemberVideo(
|
||||
videoItem: videoItem,
|
||||
bvid: _bvid,
|
||||
onTap: () {
|
||||
final status =
|
||||
widget.videoIntroController.changeSeasonOrbangu(
|
||||
null,
|
||||
videoItem.bvid,
|
||||
videoItem.cid,
|
||||
IdUtils.bv2av(videoItem.bvid!),
|
||||
videoItem.cover,
|
||||
);
|
||||
if (status) {
|
||||
_bvid = videoItem.bvid;
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
childCount: response!.length,
|
||||
@@ -387,22 +384,19 @@ class _HorizontalMemberPageState extends State<HorizontalMemberPage> {
|
||||
);
|
||||
}
|
||||
|
||||
Hero _buildAvatar(String face) => Hero(
|
||||
tag: face,
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
widget.videoDetailController.onViewImage();
|
||||
context.imageView(
|
||||
imgList: [SourceModel(url: face)],
|
||||
onDismissed: widget.videoDetailController.onDismissed,
|
||||
);
|
||||
},
|
||||
child: NetworkImgLayer(
|
||||
src: face,
|
||||
type: ImageType.avatar,
|
||||
width: 70,
|
||||
height: 70,
|
||||
),
|
||||
Widget _buildAvatar(String face) => GestureDetector(
|
||||
onTap: () {
|
||||
widget.videoDetailController.onViewImage();
|
||||
context.imageView(
|
||||
imgList: [SourceModel(url: face)],
|
||||
onDismissed: widget.videoDetailController.onDismissed,
|
||||
);
|
||||
},
|
||||
child: NetworkImgLayer(
|
||||
src: face,
|
||||
type: ImageType.avatar,
|
||||
width: 70,
|
||||
height: 70,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ class _NoteListPageState extends CommonSlidePageState<NoteListPage> {
|
||||
automaticallyImplyLeading: false,
|
||||
titleSpacing: 16,
|
||||
toolbarHeight: 45,
|
||||
backgroundColor: Colors.transparent,
|
||||
title: Obx(
|
||||
() => Text(
|
||||
'笔记${_controller.count.value == -1 ? '' : '(${_controller.count.value})'}'),
|
||||
@@ -195,88 +196,92 @@ class _NoteListPageState extends CommonSlidePageState<NoteListPage> {
|
||||
}
|
||||
|
||||
Widget _itemWidget(ThemeData theme, VideoNoteItemModel item) {
|
||||
return InkWell(
|
||||
onTap: () => Get.toNamed(
|
||||
'/articlePage',
|
||||
parameters: {
|
||||
'id': item.cvid!.toString(),
|
||||
'type': 'read',
|
||||
},
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.author!.mid}'),
|
||||
child: NetworkImgLayer(
|
||||
height: 34,
|
||||
width: 34,
|
||||
src: item.author!.face,
|
||||
type: ImageType.avatar,
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: () => Get.toNamed(
|
||||
'/articlePage',
|
||||
parameters: {
|
||||
'id': item.cvid!.toString(),
|
||||
'type': 'read',
|
||||
},
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.author!.mid}'),
|
||||
child: NetworkImgLayer(
|
||||
height: 34,
|
||||
width: 34,
|
||||
src: item.author!.face,
|
||||
type: ImageType.avatar,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Get.toNamed('/member?mid=${item.author!.mid}'),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
item.author!.name!,
|
||||
style: TextStyle(
|
||||
color: item.author?.vipInfo?.status != null &&
|
||||
item.author!.vipInfo!.status > 0 &&
|
||||
item.author!.vipInfo!.type == 2
|
||||
? context.vipColor
|
||||
: theme.colorScheme.outline,
|
||||
fontSize: 13,
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () =>
|
||||
Get.toNamed('/member?mid=${item.author!.mid}'),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
item.author!.name!,
|
||||
style: TextStyle(
|
||||
color: item.author?.vipInfo?.status != null &&
|
||||
item.author!.vipInfo!.status > 0 &&
|
||||
item.author!.vipInfo!.type == 2
|
||||
? context.vipColor
|
||||
: theme.colorScheme.outline,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Image.asset(
|
||||
'assets/images/lv/lv${item.author!.isSeniorMember == 1 ? '6_s' : item.author!.level}.png',
|
||||
height: 11,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (item.pubtime != null)
|
||||
Text(
|
||||
item.pubtime!,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: 12,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Image.asset(
|
||||
'assets/images/lv/lv${item.author!.isSeniorMember == 1 ? '6_s' : item.author!.level}.png',
|
||||
height: 11,
|
||||
),
|
||||
if (item.summary != null) ...[
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
item.summary!,
|
||||
style: TextStyle(
|
||||
height: 1.75,
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
if (item.pubtime != null)
|
||||
Text(
|
||||
item.pubtime!,
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.outline,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
if (item.summary != null) ...[
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
item.summary!,
|
||||
style: TextStyle(
|
||||
height: 1.75,
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
Text(
|
||||
'查看全部',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
height: 1.75,
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'查看全部',
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
height: 1.75,
|
||||
fontSize: theme.textTheme.bodyMedium!.fontSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -74,7 +74,7 @@ class ReplyItemGrpc extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
return Material(
|
||||
color: Colors.transparent,
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
feedBack();
|
||||
|
||||
@@ -1731,84 +1731,78 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
|
||||
Widget videoIntro([bool needRelated = true, bool needCtr = true]) {
|
||||
final bottom = MediaQuery.paddingOf(context).bottom;
|
||||
Widget introPanel() => Scaffold(
|
||||
resizeToAvoidBottomInset: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
body: CustomScrollView(
|
||||
key: const PageStorageKey<String>('简介'),
|
||||
controller: needCtr ? _introController : null,
|
||||
physics: !needCtr
|
||||
? const AlwaysScrollableScrollPhysics(
|
||||
parent: ClampingScrollPhysics())
|
||||
: null,
|
||||
slivers: [
|
||||
if (videoDetailController.videoType == SearchType.video) ...[
|
||||
VideoIntroPanel(
|
||||
key: ugcPanelKey,
|
||||
Widget introPanel() => CustomScrollView(
|
||||
key: const PageStorageKey<String>('简介'),
|
||||
controller: needCtr ? _introController : null,
|
||||
physics: !needCtr
|
||||
? const AlwaysScrollableScrollPhysics(
|
||||
parent: ClampingScrollPhysics())
|
||||
: null,
|
||||
slivers: [
|
||||
if (videoDetailController.videoType == SearchType.video) ...[
|
||||
VideoIntroPanel(
|
||||
key: ugcPanelKey,
|
||||
heroTag: heroTag,
|
||||
showAiBottomSheet: showAiBottomSheet,
|
||||
showEpisodes: showEpisodes,
|
||||
onShowMemberPage: onShowMemberPage,
|
||||
),
|
||||
if (needRelated &&
|
||||
videoDetailController
|
||||
.plPlayerController.showRelatedVideo) ...[
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: StyleString.safeSpace),
|
||||
child: Divider(
|
||||
height: 1,
|
||||
indent: 12,
|
||||
endIndent: 12,
|
||||
color:
|
||||
themeData.colorScheme.outline.withValues(alpha: 0.08),
|
||||
),
|
||||
),
|
||||
),
|
||||
RelatedVideoPanel(key: relatedVideoPanelKey, heroTag: heroTag),
|
||||
] else
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: bottom + StyleString.safeSpace,
|
||||
),
|
||||
),
|
||||
] else if (videoDetailController.videoType ==
|
||||
SearchType.media_bangumi)
|
||||
Obx(
|
||||
() => PgcIntroPage(
|
||||
key: pgcPanelKey,
|
||||
heroTag: heroTag,
|
||||
showAiBottomSheet: showAiBottomSheet,
|
||||
cid: videoDetailController.cid.value,
|
||||
showEpisodes: showEpisodes,
|
||||
onShowMemberPage: onShowMemberPage,
|
||||
showIntroDetail: showIntroDetail,
|
||||
),
|
||||
if (needRelated &&
|
||||
videoDetailController
|
||||
.plPlayerController.showRelatedVideo) ...[
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(top: StyleString.safeSpace),
|
||||
child: Divider(
|
||||
height: 1,
|
||||
indent: 12,
|
||||
endIndent: 12,
|
||||
color: themeData.colorScheme.outline
|
||||
.withValues(alpha: 0.08),
|
||||
),
|
||||
),
|
||||
),
|
||||
RelatedVideoPanel(
|
||||
key: relatedVideoPanelKey, heroTag: heroTag),
|
||||
] else
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: bottom + StyleString.safeSpace,
|
||||
),
|
||||
),
|
||||
] else if (videoDetailController.videoType ==
|
||||
SearchType.media_bangumi)
|
||||
Obx(
|
||||
() => PgcIntroPage(
|
||||
key: pgcPanelKey,
|
||||
heroTag: heroTag,
|
||||
cid: videoDetailController.cid.value,
|
||||
showEpisodes: showEpisodes,
|
||||
showIntroDetail: showIntroDetail,
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: bottom +
|
||||
(videoDetailController.isPlayAll &&
|
||||
MediaQuery.orientationOf(context) ==
|
||||
Orientation.landscape
|
||||
? 75
|
||||
: 0),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: bottom +
|
||||
(videoDetailController.isPlayAll &&
|
||||
MediaQuery.orientationOf(context) ==
|
||||
Orientation.landscape
|
||||
? 75
|
||||
: 0),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
if (videoDetailController.isPlayAll) {
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
introPanel(),
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
introPanel(),
|
||||
if (videoDetailController.isPlayAll)
|
||||
Positioned(
|
||||
left: 12,
|
||||
right: 12,
|
||||
bottom: bottom + 12,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: () => videoDetailController.showMediaListPanel(context),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(14)),
|
||||
@@ -1839,12 +1833,11 @@ class _VideoDetailPageVState extends State<VideoDetailPageV>
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return introPanel();
|
||||
}
|
||||
)
|
||||
else
|
||||
const SizedBox.shrink(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget get seasonPanel => Column(
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'dart:math';
|
||||
|
||||
import 'package:PiliPlus/common/widgets/button/icon_button.dart';
|
||||
import 'package:PiliPlus/common/widgets/custom_icon.dart';
|
||||
import 'package:PiliPlus/common/widgets/self_sized_horizontal_list.dart';
|
||||
import 'package:PiliPlus/models/common/search_type.dart';
|
||||
import 'package:PiliPlus/models/common/super_resolution_type.dart';
|
||||
import 'package:PiliPlus/models/common/video/audio_quality.dart';
|
||||
@@ -125,9 +124,8 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
color: theme.colorScheme.surface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
children: [
|
||||
const SizedBox(height: 14),
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
@@ -272,66 +270,64 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
}
|
||||
},
|
||||
),
|
||||
SelfSizedHorizontalList(
|
||||
itemCount: 4,
|
||||
gapSize: 10,
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
childBuilder: (index) {
|
||||
return switch (index) {
|
||||
0 => Obx(
|
||||
() => ActionRowLineItem(
|
||||
iconData: Icons.flip,
|
||||
onTap: () => widget.controller.flipX.value =
|
||||
!widget.controller.flipX.value,
|
||||
text: " 左右翻转 ",
|
||||
selectStatus: widget.controller.flipX.value,
|
||||
),
|
||||
child: Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Obx(
|
||||
() => ActionRowLineItem(
|
||||
iconData: Icons.flip,
|
||||
onTap: () => widget.controller.flipX.value =
|
||||
!widget.controller.flipX.value,
|
||||
text: " 左右翻转 ",
|
||||
selectStatus: widget.controller.flipX.value,
|
||||
),
|
||||
1 => Obx(
|
||||
() => ActionRowLineItem(
|
||||
icon: Transform.rotate(
|
||||
angle: pi / 2,
|
||||
child: Icon(
|
||||
Icons.flip,
|
||||
size: 13,
|
||||
color: widget.controller.flipY.value
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: theme.colorScheme.outline,
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionRowLineItem(
|
||||
icon: Transform.rotate(
|
||||
angle: pi / 2,
|
||||
child: Icon(
|
||||
Icons.flip,
|
||||
size: 13,
|
||||
color: widget.controller.flipY.value
|
||||
? theme.colorScheme.onSecondaryContainer
|
||||
: theme.colorScheme.outline,
|
||||
),
|
||||
onTap: () {
|
||||
widget.controller.flipY.value =
|
||||
!widget.controller.flipY.value;
|
||||
},
|
||||
text: " 上下翻转 ",
|
||||
selectStatus: widget.controller.flipY.value,
|
||||
),
|
||||
onTap: () {
|
||||
widget.controller.flipY.value =
|
||||
!widget.controller.flipY.value;
|
||||
},
|
||||
text: " 上下翻转 ",
|
||||
selectStatus: widget.controller.flipY.value,
|
||||
),
|
||||
2 => Obx(
|
||||
() => ActionRowLineItem(
|
||||
iconData: Icons.headphones,
|
||||
onTap: () {
|
||||
widget.controller.onlyPlayAudio.value =
|
||||
!widget.controller.onlyPlayAudio.value;
|
||||
widget.videoDetailCtr.playerInit();
|
||||
},
|
||||
text: " 听视频 ",
|
||||
selectStatus: widget.controller.onlyPlayAudio.value,
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionRowLineItem(
|
||||
iconData: Icons.headphones,
|
||||
onTap: () {
|
||||
widget.controller.onlyPlayAudio.value =
|
||||
!widget.controller.onlyPlayAudio.value;
|
||||
widget.videoDetailCtr.playerInit();
|
||||
},
|
||||
text: " 听视频 ",
|
||||
selectStatus: widget.controller.onlyPlayAudio.value,
|
||||
),
|
||||
3 => Obx(
|
||||
() => ActionRowLineItem(
|
||||
iconData: Icons.play_circle_outline,
|
||||
onTap:
|
||||
widget.controller.setContinuePlayInBackground,
|
||||
text: " 后台播放 ",
|
||||
selectStatus: widget
|
||||
.controller.continuePlayInBackground.value,
|
||||
),
|
||||
),
|
||||
Obx(
|
||||
() => ActionRowLineItem(
|
||||
iconData: Icons.play_circle_outline,
|
||||
onTap: widget.controller.setContinuePlayInBackground,
|
||||
text: " 后台播放 ",
|
||||
selectStatus:
|
||||
widget.controller.continuePlayInBackground.value,
|
||||
),
|
||||
_ => throw UnimplementedError(),
|
||||
};
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
@@ -536,7 +532,6 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
leading: const Icon(Icons.error_outline, size: 20),
|
||||
title: const Text('举报', style: titleStyle),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -578,7 +573,8 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
clipBehavior: Clip.hardEdge,
|
||||
color: theme.colorScheme.surface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
child: Column(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 45,
|
||||
@@ -599,77 +595,59 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: Scrollbar(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
for (int i = 0; i < totalQaSam; i++) ...[
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () async {
|
||||
if (currentVideoQa.code ==
|
||||
videoFormat[i].quality) {
|
||||
return;
|
||||
}
|
||||
Get.back();
|
||||
final int quality = videoFormat[i].quality!;
|
||||
videoDetailCtr
|
||||
..currentVideoQa =
|
||||
VideoQuality.fromCode(quality)
|
||||
..updatePlayer();
|
||||
for (int i = 0; i < totalQaSam; i++) ...[
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () async {
|
||||
if (currentVideoQa.code == videoFormat[i].quality) {
|
||||
return;
|
||||
}
|
||||
Get.back();
|
||||
final int quality = videoFormat[i].quality!;
|
||||
videoDetailCtr
|
||||
..currentVideoQa = VideoQuality.fromCode(quality)
|
||||
..updatePlayer();
|
||||
|
||||
// update
|
||||
late String oldQualityDesc;
|
||||
await Connectivity()
|
||||
.checkConnectivity()
|
||||
.then((res) {
|
||||
if (res.contains(ConnectivityResult.wifi)) {
|
||||
oldQualityDesc = VideoQuality.fromCode(
|
||||
GStorage.defaultVideoQa)
|
||||
.description;
|
||||
setting.put(
|
||||
SettingBoxKey.defaultVideoQa,
|
||||
quality,
|
||||
);
|
||||
} else {
|
||||
oldQualityDesc = VideoQuality.fromCode(
|
||||
GStorage.defaultVideoQaCellular)
|
||||
.description;
|
||||
setting.put(
|
||||
SettingBoxKey.defaultVideoQaCellular,
|
||||
quality,
|
||||
);
|
||||
}
|
||||
});
|
||||
SmartDialog.showToast(
|
||||
"默认画质由:$oldQualityDesc 变为:${VideoQuality.fromCode(quality).description}",
|
||||
);
|
||||
},
|
||||
// 可能包含会员解锁画质
|
||||
enabled: i >= totalQaSam - userfulQaSam,
|
||||
contentPadding:
|
||||
const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(videoFormat[i].newDesc!),
|
||||
trailing:
|
||||
currentVideoQa.code == videoFormat[i].quality
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: theme.colorScheme.primary,
|
||||
)
|
||||
: Text(
|
||||
videoFormat[i].format!,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
// update
|
||||
late String oldQualityDesc;
|
||||
await Connectivity().checkConnectivity().then((res) {
|
||||
if (res.contains(ConnectivityResult.wifi)) {
|
||||
oldQualityDesc =
|
||||
VideoQuality.fromCode(GStorage.defaultVideoQa)
|
||||
.description;
|
||||
setting.put(
|
||||
SettingBoxKey.defaultVideoQa,
|
||||
quality,
|
||||
);
|
||||
} else {
|
||||
oldQualityDesc = VideoQuality.fromCode(
|
||||
GStorage.defaultVideoQaCellular)
|
||||
.description;
|
||||
setting.put(
|
||||
SettingBoxKey.defaultVideoQaCellular,
|
||||
quality,
|
||||
);
|
||||
}
|
||||
});
|
||||
SmartDialog.showToast(
|
||||
"默认画质由:$oldQualityDesc 变为:${VideoQuality.fromCode(quality).description}",
|
||||
);
|
||||
},
|
||||
// 可能包含会员解锁画质
|
||||
enabled: i >= totalQaSam - userfulQaSam,
|
||||
contentPadding: const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(videoFormat[i].newDesc!),
|
||||
trailing: currentVideoQa.code == videoFormat[i].quality
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: theme.colorScheme.primary,
|
||||
)
|
||||
: Text(
|
||||
videoFormat[i].format!,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -691,77 +669,67 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
clipBehavior: Clip.hardEdge,
|
||||
color: theme.colorScheme.surface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
child: Column(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 45,
|
||||
child: Center(child: Text('选择音质', style: titleStyle))),
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
for (final AudioItem i in audio) ...[
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () async {
|
||||
if (currentAudioQa.code == i.id) {
|
||||
return;
|
||||
}
|
||||
Get.back();
|
||||
final int quality = i.id!;
|
||||
videoDetailCtr
|
||||
..currentAudioQa =
|
||||
AudioQuality.fromCode(quality)
|
||||
..updatePlayer();
|
||||
|
||||
// update
|
||||
late String oldQualityDesc;
|
||||
await Connectivity()
|
||||
.checkConnectivity()
|
||||
.then((res) {
|
||||
if (res.contains(ConnectivityResult.wifi)) {
|
||||
oldQualityDesc = AudioQuality.fromCode(
|
||||
GStorage.defaultAudioQa)
|
||||
.description;
|
||||
setting.put(
|
||||
SettingBoxKey.defaultAudioQa,
|
||||
quality,
|
||||
);
|
||||
} else {
|
||||
oldQualityDesc = AudioQuality.fromCode(
|
||||
GStorage.defaultAudioQaCellular)
|
||||
.description;
|
||||
setting.put(
|
||||
SettingBoxKey.defaultAudioQaCellular,
|
||||
quality,
|
||||
);
|
||||
}
|
||||
});
|
||||
SmartDialog.showToast(
|
||||
"默认音质由:$oldQualityDesc 变为:${AudioQuality.fromCode(quality).description}",
|
||||
);
|
||||
},
|
||||
contentPadding:
|
||||
const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(i.quality),
|
||||
subtitle: Text(
|
||||
i.codecs!,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
trailing: currentAudioQa.code == i.id
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: theme.colorScheme.primary,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
height: 45,
|
||||
child: Center(
|
||||
child: Text('选择音质', style: titleStyle),
|
||||
),
|
||||
),
|
||||
for (final AudioItem i in audio) ...[
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () async {
|
||||
if (currentAudioQa.code == i.id) {
|
||||
return;
|
||||
}
|
||||
Get.back();
|
||||
final int quality = i.id!;
|
||||
videoDetailCtr
|
||||
..currentAudioQa = AudioQuality.fromCode(quality)
|
||||
..updatePlayer();
|
||||
|
||||
// update
|
||||
late String oldQualityDesc;
|
||||
await Connectivity().checkConnectivity().then((res) {
|
||||
if (res.contains(ConnectivityResult.wifi)) {
|
||||
oldQualityDesc =
|
||||
AudioQuality.fromCode(GStorage.defaultAudioQa)
|
||||
.description;
|
||||
setting.put(
|
||||
SettingBoxKey.defaultAudioQa,
|
||||
quality,
|
||||
);
|
||||
} else {
|
||||
oldQualityDesc = AudioQuality.fromCode(
|
||||
GStorage.defaultAudioQaCellular)
|
||||
.description;
|
||||
setting.put(
|
||||
SettingBoxKey.defaultAudioQaCellular,
|
||||
quality,
|
||||
);
|
||||
}
|
||||
});
|
||||
SmartDialog.showToast(
|
||||
"默认音质由:$oldQualityDesc 变为:${AudioQuality.fromCode(quality).description}",
|
||||
);
|
||||
},
|
||||
contentPadding: const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(i.quality),
|
||||
subtitle: Text(
|
||||
i.codecs!,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
trailing: currentAudioQa.code == i.id
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: theme.colorScheme.primary,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -798,45 +766,45 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 45,
|
||||
child: Center(child: Text('选择解码格式', style: titleStyle))),
|
||||
height: 45,
|
||||
child: Center(
|
||||
child: Text('选择解码格式', style: titleStyle),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
for (var i in list) ...[
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
if (i.startsWith(currentDecodeFormats.code)) {
|
||||
return;
|
||||
}
|
||||
videoDetailCtr
|
||||
..currentDecodeFormats =
|
||||
VideoDecodeFormatTypeExt.fromString(i)!
|
||||
..updatePlayer();
|
||||
Get.back();
|
||||
},
|
||||
contentPadding:
|
||||
const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(VideoDecodeFormatTypeExt.fromString(i)!
|
||||
.description),
|
||||
subtitle: Text(
|
||||
i!,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
trailing: i.startsWith(currentDecodeFormats.code)
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: theme.colorScheme.primary,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
for (var i in list) ...[
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
if (i.startsWith(currentDecodeFormats.code)) {
|
||||
return;
|
||||
}
|
||||
videoDetailCtr
|
||||
..currentDecodeFormats =
|
||||
VideoDecodeFormatTypeExt.fromString(i)!
|
||||
..updatePlayer();
|
||||
Get.back();
|
||||
},
|
||||
contentPadding:
|
||||
const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(VideoDecodeFormatTypeExt.fromString(i)!
|
||||
.description),
|
||||
subtitle: Text(
|
||||
i!,
|
||||
style: subTitleStyle,
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
trailing: i.startsWith(currentDecodeFormats.code)
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: theme.colorScheme.primary,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -1786,39 +1754,32 @@ class HeaderControlState extends State<HeaderControl> {
|
||||
clipBehavior: Clip.hardEdge,
|
||||
color: theme.colorScheme.surface,
|
||||
borderRadius: const BorderRadius.all(Radius.circular(12)),
|
||||
child: Column(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 45,
|
||||
child: Center(child: Text('选择播放顺序', style: titleStyle))),
|
||||
Expanded(
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
for (final PlayRepeat i in PlayRepeat.values) ...[
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
widget.controller.setPlayRepeat(i);
|
||||
Get.back();
|
||||
},
|
||||
contentPadding:
|
||||
const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(i.description),
|
||||
trailing: widget.controller.playRepeat == i
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: theme.colorScheme.primary,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
)
|
||||
],
|
||||
],
|
||||
),
|
||||
height: 45,
|
||||
child: Center(
|
||||
child: Text('选择播放顺序', style: titleStyle),
|
||||
),
|
||||
),
|
||||
for (final PlayRepeat i in PlayRepeat.values) ...[
|
||||
ListTile(
|
||||
dense: true,
|
||||
onTap: () {
|
||||
widget.controller.setPlayRepeat(i);
|
||||
Get.back();
|
||||
},
|
||||
contentPadding: const EdgeInsets.only(left: 20, right: 20),
|
||||
title: Text(i.description),
|
||||
trailing: widget.controller.playRepeat == i
|
||||
? Icon(
|
||||
Icons.done,
|
||||
color: theme.colorScheme.primary,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
)
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user