diff --git a/lib/common/constants.dart b/lib/common/constants.dart index 01cdbcb7e..d27be60ec 100644 --- a/lib/common/constants.dart +++ b/lib/common/constants.dart @@ -6,6 +6,8 @@ abstract final class StyleString { static const BorderRadius mdRadius = BorderRadius.all(imgRadius); static const Radius imgRadius = Radius.circular(10); static const double aspectRatio = 16 / 10; + static const double aspectRatio16x9 = 16 / 9; + static const double imgMaxRatio = 22 / 9; static const bottomSheetRadius = BorderRadius.vertical( top: Radius.circular(18), ); diff --git a/lib/common/widgets/image/custom_grid_view.dart b/lib/common/widgets/image/custom_grid_view.dart index 046f51d1a..736a1a669 100644 --- a/lib/common/widgets/image/custom_grid_view.dart +++ b/lib/common/widgets/image/custom_grid_view.dart @@ -60,15 +60,14 @@ class ImageModel { bool? _isLongPic; bool? _isLivePhoto; - bool get isLongPic => _isLongPic ??= (height / width) > _maxRatio; + bool get isLongPic => + _isLongPic ??= (height / width) > StyleString.imgMaxRatio; bool get isLivePhoto => _isLivePhoto ??= enableLivePhoto && liveUrl?.isNotEmpty == true; static bool enableLivePhoto = Pref.enableLivePhoto; } -const double _maxRatio = 22 / 9; - class CustomGridView extends StatelessWidget { const CustomGridView({ super.key, @@ -222,7 +221,7 @@ class CustomGridView extends StatelessWidget { if (width != 1) { imageWidth = min(imageWidth, width.toDouble()); } - imageHeight = imageWidth * min(ratioHW, _maxRatio); + imageHeight = imageWidth * min(ratioHW, StyleString.imgMaxRatio); } } diff --git a/lib/common/widgets/image/image_save.dart b/lib/common/widgets/image/image_save.dart index 3b3dc1129..acfa58c60 100644 --- a/lib/common/widgets/image/image_save.dart +++ b/lib/common/widgets/image/image_save.dart @@ -14,7 +14,7 @@ void imageSaveDialog({ dynamic aid, String? bvid, }) { - final double imgWidth = MediaQuery.sizeOf(Get.context!).shortestSide - 8 * 2; + final double imgWidth = MediaQuery.sizeOf(Get.context!).shortestSide - 16; SmartDialog.show( animationType: SmartAnimationType.centerScale_otherSlide, builder: (context) { @@ -22,7 +22,7 @@ void imageSaveDialog({ final theme = Theme.of(context); return Container( width: imgWidth, - margin: const EdgeInsets.symmetric(horizontal: StyleString.safeSpace), + margin: const .symmetric(horizontal: StyleString.safeSpace), decoration: BoxDecoration( color: theme.colorScheme.surface, borderRadius: StyleString.mdRadius, @@ -36,32 +36,29 @@ void imageSaveDialog({ GestureDetector( onTap: SmartDialog.dismiss, child: NetworkImgLayer( - width: imgWidth, - height: imgWidth / StyleString.aspectRatio, src: cover, quality: 100, + width: imgWidth, + height: imgWidth / StyleString.aspectRatio16x9, + borderRadius: const .vertical(top: StyleString.imgRadius), ), ), Positioned( right: 8, top: 8, - child: SizedBox( - width: 30, - height: 30, - child: IconButton( - tooltip: '关闭', - style: ButtonStyle( - backgroundColor: WidgetStatePropertyAll( - Colors.black.withValues(alpha: 0.3), - ), - padding: const WidgetStatePropertyAll(EdgeInsets.zero), - ), - onPressed: SmartDialog.dismiss, - icon: const Icon( - Icons.close, - size: 18, - color: Colors.white, - ), + width: 30, + height: 30, + child: IconButton( + tooltip: '关闭', + style: IconButton.styleFrom( + padding: .zero, + backgroundColor: Colors.black.withValues(alpha: 0.3), + ), + onPressed: SmartDialog.dismiss, + icon: const Icon( + Icons.close, + size: 18, + color: Colors.white, ), ), ), diff --git a/lib/common/widgets/progress_bar/audio_video_progress_bar.dart b/lib/common/widgets/progress_bar/audio_video_progress_bar.dart index b52e25d9a..665d8fd6f 100644 --- a/lib/common/widgets/progress_bar/audio_video_progress_bar.dart +++ b/lib/common/widgets/progress_bar/audio_video_progress_bar.dart @@ -662,8 +662,7 @@ class RenderProgressBar extends RenderBox implements MouseTrackerAnnotation { Size computeDryLayout(BoxConstraints constraints) { final desiredWidth = constraints.maxWidth; final desiredHeight = _heightWhenNoLabels(); - final desiredSize = Size(desiredWidth, desiredHeight); - return constraints.constrain(desiredSize); + return constraints.constrainDimensions(desiredWidth, desiredHeight); } double _heightWhenNoLabels() { diff --git a/lib/common/widgets/progress_bar/segment_progress_bar.dart b/lib/common/widgets/progress_bar/segment_progress_bar.dart index 227ed46d5..cac3bfe76 100644 --- a/lib/common/widgets/progress_bar/segment_progress_bar.dart +++ b/lib/common/widgets/progress_bar/segment_progress_bar.dart @@ -185,7 +185,7 @@ class RenderViewPointProgressBar @override void performLayout() { - size = constraints.constrain(Size(constraints.maxWidth, _barHeight)); + size = constraints.constrainDimensions(constraints.maxWidth, _barHeight); } static const double _barHeight = 15.0; @@ -334,7 +334,6 @@ class BaseRenderProgressBar extends RenderBox { BaseRenderProgressBar({ required double height, required List segments, - ValueSetter? onSeek, }) : _height = height, _segments = segments; @@ -356,7 +355,7 @@ class BaseRenderProgressBar extends RenderBox { @override void performLayout() { - size = constraints.constrain(Size(constraints.maxWidth, height)); + size = constraints.constrainDimensions(constraints.maxWidth, height); } @override diff --git a/lib/common/widgets/progress_bar/video_progress_indicator.dart b/lib/common/widgets/progress_bar/video_progress_indicator.dart index 2f121f060..7fe68cb4c 100644 --- a/lib/common/widgets/progress_bar/video_progress_indicator.dart +++ b/lib/common/widgets/progress_bar/video_progress_indicator.dart @@ -96,7 +96,7 @@ class RenderProgressBar extends RenderBox { } double _radius; - double get borderRadius => _radius; + double get radius => _radius; set radius(double value) { if (_radius == value) return; _radius = value; @@ -113,7 +113,7 @@ class RenderProgressBar extends RenderBox { @override void performLayout() { - size = constraints.constrain(Size(constraints.maxWidth, _radius)); + size = constraints.constrainDimensions(constraints.maxWidth, _radius); } @override diff --git a/lib/common/widgets/video_card/video_card_h.dart b/lib/common/widgets/video_card/video_card_h.dart index 9be6cdd64..4f2cd2bdd 100644 --- a/lib/common/widgets/video_card/video_card_h.dart +++ b/lib/common/widgets/video_card/video_card_h.dart @@ -199,8 +199,9 @@ class VideoCardH extends StatelessWidget { Positioned( bottom: 0, right: 12, + width: 29, + height: 29, child: VideoPopupMenu( - size: 29, iconSize: 17, videoItem: videoItem, onRemove: onRemove, diff --git a/lib/common/widgets/video_card/video_card_v.dart b/lib/common/widgets/video_card/video_card_v.dart index 6c7d7f305..9f2c8c730 100644 --- a/lib/common/widgets/video_card/video_card_v.dart +++ b/lib/common/widgets/video_card/video_card_v.dart @@ -124,8 +124,9 @@ class VideoCardV extends StatelessWidget { Positioned( right: -5, bottom: -2, + width: 29, + height: 29, child: VideoPopupMenu( - size: 29, iconSize: 17, videoItem: videoItem, onRemove: onRemove, diff --git a/lib/common/widgets/video_popup_menu.dart b/lib/common/widgets/video_popup_menu.dart index be7b7e5a5..fd08d17ed 100644 --- a/lib/common/widgets/video_popup_menu.dart +++ b/lib/common/widgets/video_popup_menu.dart @@ -24,7 +24,6 @@ class _VideoCustomAction { } class VideoPopupMenu extends StatelessWidget { - final double? size; final double? iconSize; final double menuItemHeight; final BaseSimpleVideoItemModel videoItem; @@ -32,7 +31,6 @@ class VideoPopupMenu extends StatelessWidget { const VideoPopupMenu({ super.key, - required this.size, required this.iconSize, required this.videoItem, this.onRemove, @@ -41,358 +39,349 @@ class VideoPopupMenu extends StatelessWidget { @override Widget build(BuildContext context) { - return ExcludeSemantics( - child: SizedBox( - width: size, - height: size, - child: PopupMenuButton( - padding: EdgeInsets.zero, - icon: Icon( - Icons.more_vert_outlined, - color: Theme.of(context).colorScheme.outline, - size: iconSize, - ), - position: PopupMenuPosition.under, - itemBuilder: (context) => - [ - if (videoItem.bvid?.isNotEmpty == true) ...[ - _VideoCustomAction( - videoItem.bvid!, - const Stack( - clipBehavior: Clip.none, - children: [ - Icon(MdiIcons.identifier, size: 16), - Icon(MdiIcons.circleOutline, size: 16), - ], - ), - () => Utils.copyText(videoItem.bvid!), - ), - _VideoCustomAction( - '稍后再看', - const Icon(MdiIcons.clockTimeEightOutline, size: 16), - () => UserHttp.toViewLater(bvid: videoItem.bvid), - ), - if (videoItem.cid != null && Pref.enableAi) - _VideoCustomAction( - 'AI总结', - const Stack( - alignment: Alignment.center, - clipBehavior: Clip.none, - children: [ - Icon(Icons.circle_outlined, size: 16), - ExcludeSemantics( - child: Text( - 'AI', - style: TextStyle( - fontSize: 10, - height: 1, - fontWeight: FontWeight.w700, - ), - strutStyle: StrutStyle( - fontSize: 10, - height: 1, - leading: 0, - fontWeight: FontWeight.w700, - ), - textScaler: TextScaler.noScaling, - ), + return PopupMenuButton( + padding: EdgeInsets.zero, + icon: Icon( + Icons.more_vert_outlined, + color: Theme.of(context).colorScheme.outline, + size: iconSize, + ), + position: PopupMenuPosition.under, + itemBuilder: (context) => + [ + if (videoItem.bvid?.isNotEmpty == true) ...[ + _VideoCustomAction( + videoItem.bvid!, + const Stack( + clipBehavior: Clip.none, + children: [ + Icon(MdiIcons.identifier, size: 16), + Icon(MdiIcons.circleOutline, size: 16), + ], + ), + () => Utils.copyText(videoItem.bvid!), + ), + _VideoCustomAction( + '稍后再看', + const Icon(MdiIcons.clockTimeEightOutline, size: 16), + () => UserHttp.toViewLater(bvid: videoItem.bvid), + ), + if (videoItem.cid != null && Pref.enableAi) + _VideoCustomAction( + 'AI总结', + const Stack( + alignment: Alignment.center, + clipBehavior: Clip.none, + children: [ + Icon(Icons.circle_outlined, size: 16), + ExcludeSemantics( + child: Text( + 'AI', + style: TextStyle( + fontSize: 10, + height: 1, + fontWeight: FontWeight.w700, ), - ], + strutStyle: StrutStyle( + fontSize: 10, + height: 1, + leading: 0, + fontWeight: FontWeight.w700, + ), + textScaler: TextScaler.noScaling, + ), ), - () async { - final res = - await UgcIntroController.getAiConclusion( - videoItem.bvid!, - videoItem.cid!, - videoItem.owner.mid, - ); - if (res != null && context.mounted) { - showDialog( - context: context, - builder: (context) { - return Dialog( - child: Padding( - padding: const .symmetric(vertical: 14), - child: AiConclusionPanel.buildContent( - context, - Theme.of(context), - res, - tap: false, - ), - ), - ); - }, - ); - } - }, - ), - ], - if (videoItem is! SpaceArchiveItem) ...[ - _VideoCustomAction( - '访问:${videoItem.owner.name}', - const Icon(MdiIcons.accountCircleOutline, size: 16), - () => Get.toNamed('/member?mid=${videoItem.owner.mid}'), + ], ), - _VideoCustomAction( - '不感兴趣', - const Icon(MdiIcons.thumbDownOutline, size: 16), - () { - String? accessKey = Accounts.get( - AccountType.recommend, - ).accessKey; - if (accessKey == null || accessKey == "") { - SmartDialog.showToast("请退出账号后重新登录"); - return; - } - if (videoItem case final RecVideoItemAppModel item) { - ThreePoint? tp = item.threePoint; - if (tp == null) { - SmartDialog.showToast("未能获取threePoint"); - return; - } - if (tp.dislikeReasons == null && - tp.feedbacks == null) { - SmartDialog.showToast( - "未能获取dislikeReasons或feedbacks", + () async { + final res = await UgcIntroController.getAiConclusion( + videoItem.bvid!, + videoItem.cid!, + videoItem.owner.mid, + ); + if (res != null && context.mounted) { + showDialog( + context: context, + builder: (context) { + return Dialog( + child: Padding( + padding: const .symmetric(vertical: 14), + child: AiConclusionPanel.buildContent( + context, + Theme.of(context), + res, + tap: false, + ), + ), ); - return; - } - Widget actionButton(Reason? r, Reason? f) { - return SearchText( - text: r?.name ?? f?.name ?? '未知', - onTap: (_) async { - Get.back(); - SmartDialog.showLoading(msg: '正在提交'); - final res = await VideoHttp.feedDislike( - reasonId: r?.id, - feedbackId: f?.id, - id: item.param!, - goto: item.goto!, - ); - SmartDialog.dismiss(); - if (res.isSuccess) { - SmartDialog.showToast( - r?.toast ?? f!.toast!, - ); - onRemove?.call(); - } else { - res.toast(); - } - }, + }, + ); + } + }, + ), + ], + if (videoItem is! SpaceArchiveItem) ...[ + _VideoCustomAction( + '访问:${videoItem.owner.name}', + const Icon(MdiIcons.accountCircleOutline, size: 16), + () => Get.toNamed('/member?mid=${videoItem.owner.mid}'), + ), + _VideoCustomAction( + '不感兴趣', + const Icon(MdiIcons.thumbDownOutline, size: 16), + () { + String? accessKey = Accounts.get( + AccountType.recommend, + ).accessKey; + if (accessKey == null || accessKey == "") { + SmartDialog.showToast("请退出账号后重新登录"); + return; + } + if (videoItem case final RecVideoItemAppModel item) { + ThreePoint? tp = item.threePoint; + if (tp == null) { + SmartDialog.showToast("未能获取threePoint"); + return; + } + if (tp.dislikeReasons == null && tp.feedbacks == null) { + SmartDialog.showToast( + "未能获取dislikeReasons或feedbacks", + ); + return; + } + Widget actionButton(Reason? r, Reason? f) { + return SearchText( + text: r?.name ?? f?.name ?? '未知', + onTap: (_) async { + Get.back(); + SmartDialog.showLoading(msg: '正在提交'); + final res = await VideoHttp.feedDislike( + reasonId: r?.id, + feedbackId: f?.id, + id: item.param!, + goto: item.goto!, ); - } + SmartDialog.dismiss(); + if (res.isSuccess) { + SmartDialog.showToast( + r?.toast ?? f!.toast!, + ); + onRemove?.call(); + } else { + res.toast(); + } + }, + ); + } - showDialog( - context: context, - builder: (context) { - return AlertDialog( - content: SingleChildScrollView( - child: Column( - crossAxisAlignment: .start, - children: [ - if (tp.dislikeReasons != null) ...[ - const Text('我不想看'), - const SizedBox(height: 5), - Wrap( - spacing: 8.0, - runSpacing: 8.0, - children: tp.dislikeReasons!.map(( - item, - ) { - return actionButton(item, null); - }).toList(), - ), - ], - if (tp.feedbacks != null) ...[ - const SizedBox(height: 5), - const Text('反馈'), - const SizedBox(height: 5), - Wrap( - spacing: 8.0, - runSpacing: 8.0, - children: tp.feedbacks!.map((item) { - return actionButton(null, item); - }).toList(), - ), - ], - const Divider(), - Center( - child: FilledButton.tonal( - onPressed: () async { - SmartDialog.showLoading( - msg: '正在提交', - ); - final res = - await VideoHttp.feedDislikeCancel( - id: item.param!, - goto: item.goto!, - ); - SmartDialog.dismiss(); - SmartDialog.showToast( - res.isSuccess - ? "成功" - : res.toString(), - ); - Get.back(); - }, - style: FilledButton.styleFrom( - visualDensity: - VisualDensity.compact, - ), - child: const Text("撤销"), - ), - ), - ], - ), - ), - ); - }, - ); - } else { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - content: SingleChildScrollView( - child: Column( - children: [ - const SizedBox(height: 5), - const Text("web端暂不支持精细选择"), - const SizedBox(height: 5), - Wrap( - spacing: 5.0, - runSpacing: 2.0, - children: [ - FilledButton.tonal( - onPressed: () async { - Get.back(); - SmartDialog.showLoading( - msg: '正在提交', - ); - final res = - await VideoHttp.dislikeVideo( - bvid: videoItem.bvid!, - type: true, - ); - SmartDialog.dismiss(); - if (res.isSuccess) { - SmartDialog.showToast('点踩成功'); - onRemove?.call(); - } else { - res.toast(); - } - }, - style: FilledButton.styleFrom( - visualDensity: - VisualDensity.compact, - ), - child: const Text("点踩"), - ), - FilledButton.tonal( - onPressed: () async { - Get.back(); - SmartDialog.showLoading( - msg: '正在提交', - ); - final res = - await VideoHttp.dislikeVideo( - bvid: videoItem.bvid!, - type: false, - ); - SmartDialog.dismiss(); - SmartDialog.showToast( - res.isSuccess - ? '取消踩' - : res.toString(), - ); - }, - style: FilledButton.styleFrom( - visualDensity: - VisualDensity.compact, - ), - child: const Text("撤销"), - ), - ], - ), - ], - ), - ), - ); - }, - ); - } - }, - ), - _VideoCustomAction( - '拉黑:${videoItem.owner.name}', - const Icon(MdiIcons.cancel, size: 16), - () => showDialog( + showDialog( context: context, builder: (context) { return AlertDialog( - title: const Text('提示'), - content: Text( - '确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?' - '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除', - ), - actions: [ - TextButton( - onPressed: Get.back, - child: Text( - '点错了', - style: TextStyle( - color: Theme.of( - context, - ).colorScheme.outline, + content: SingleChildScrollView( + child: Column( + crossAxisAlignment: .start, + children: [ + if (tp.dislikeReasons != null) ...[ + const Text('我不想看'), + const SizedBox(height: 5), + Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: tp.dislikeReasons!.map(( + item, + ) { + return actionButton(item, null); + }).toList(), + ), + ], + if (tp.feedbacks != null) ...[ + const SizedBox(height: 5), + const Text('反馈'), + const SizedBox(height: 5), + Wrap( + spacing: 8.0, + runSpacing: 8.0, + children: tp.feedbacks!.map((item) { + return actionButton(null, item); + }).toList(), + ), + ], + const Divider(), + Center( + child: FilledButton.tonal( + onPressed: () async { + SmartDialog.showLoading( + msg: '正在提交', + ); + final res = + await VideoHttp.feedDislikeCancel( + id: item.param!, + goto: item.goto!, + ); + SmartDialog.dismiss(); + SmartDialog.showToast( + res.isSuccess + ? "成功" + : res.toString(), + ); + Get.back(); + }, + style: FilledButton.styleFrom( + visualDensity: VisualDensity.compact, + ), + child: const Text("撤销"), + ), ), - ), + ], ), - TextButton( - onPressed: () async { - Get.back(); - final res = await VideoHttp.relationMod( - mid: videoItem.owner.mid!, - act: 5, - reSrc: 11, - ); - if (res.isSuccess) { - onRemove?.call(); - } else { - res.toast(); - } - }, - child: const Text('确认'), - ), - ], + ), ); }, - ), - ), + ); + } else { + showDialog( + context: context, + builder: (context) { + return AlertDialog( + content: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 5), + const Text("web端暂不支持精细选择"), + const SizedBox(height: 5), + Wrap( + spacing: 5.0, + runSpacing: 2.0, + children: [ + FilledButton.tonal( + onPressed: () async { + Get.back(); + SmartDialog.showLoading( + msg: '正在提交', + ); + final res = + await VideoHttp.dislikeVideo( + bvid: videoItem.bvid!, + type: true, + ); + SmartDialog.dismiss(); + if (res.isSuccess) { + SmartDialog.showToast('点踩成功'); + onRemove?.call(); + } else { + res.toast(); + } + }, + style: FilledButton.styleFrom( + visualDensity: + VisualDensity.compact, + ), + child: const Text("点踩"), + ), + FilledButton.tonal( + onPressed: () async { + Get.back(); + SmartDialog.showLoading( + msg: '正在提交', + ); + final res = + await VideoHttp.dislikeVideo( + bvid: videoItem.bvid!, + type: false, + ); + SmartDialog.dismiss(); + SmartDialog.showToast( + res.isSuccess + ? '取消踩' + : res.toString(), + ); + }, + style: FilledButton.styleFrom( + visualDensity: + VisualDensity.compact, + ), + child: const Text("撤销"), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } + }, + ), + _VideoCustomAction( + '拉黑:${videoItem.owner.name}', + const Icon(MdiIcons.cancel, size: 16), + () => showDialog( + context: context, + builder: (context) { + return AlertDialog( + title: const Text('提示'), + content: Text( + '确定拉黑:${videoItem.owner.name}(${videoItem.owner.mid})?' + '\n\n注:被拉黑的Up可以在隐私设置-黑名单管理中解除', + ), + actions: [ + TextButton( + onPressed: Get.back, + child: Text( + '点错了', + style: TextStyle( + color: Theme.of( + context, + ).colorScheme.outline, + ), + ), + ), + TextButton( + onPressed: () async { + Get.back(); + final res = await VideoHttp.relationMod( + mid: videoItem.owner.mid!, + act: 5, + reSrc: 11, + ); + if (res.isSuccess) { + onRemove?.call(); + } else { + res.toast(); + } + }, + child: const Text('确认'), + ), + ], + ); + }, + ), + ), + ], + _VideoCustomAction( + "${MineController.anonymity.value ? '退出' : '进入'}无痕模式", + MineController.anonymity.value + ? const Icon(MdiIcons.incognitoOff, size: 16) + : const Icon(MdiIcons.incognito, size: 16), + MineController.onChangeAnonymity, + ), + ] + .map( + (e) => PopupMenuItem( + height: menuItemHeight, + onTap: e.onTap, + child: Row( + children: [ + e.icon, + const SizedBox(width: 6), + Text(e.title, style: const TextStyle(fontSize: 13)), ], - _VideoCustomAction( - "${MineController.anonymity.value ? '退出' : '进入'}无痕模式", - MineController.anonymity.value - ? const Icon(MdiIcons.incognitoOff, size: 16) - : const Icon(MdiIcons.incognito, size: 16), - MineController.onChangeAnonymity, - ), - ] - .map( - (e) => PopupMenuItem( - height: menuItemHeight, - onTap: e.onTap, - child: Row( - children: [ - e.icon, - const SizedBox(width: 6), - Text(e.title, style: const TextStyle(fontSize: 13)), - ], - ), - ), - ) - .toList(), - ), - ), + ), + ), + ) + .toList(), ); } } diff --git a/lib/http/msg.dart b/lib/http/msg.dart index 67186a632..e6d9138a4 100644 --- a/lib/http/msg.dart +++ b/lib/http/msg.dart @@ -607,7 +607,7 @@ abstract final class MsgHttp { } static Future> imMsgReport({ - required Object accusedUid, + required int accusedUid, required int reasonType, required String reasonDesc, required Map comment, diff --git a/lib/models/dynamics/article_content_model.dart b/lib/models/dynamics/article_content_model.dart index 028d3efa1..7b7d6ad18 100644 --- a/lib/models/dynamics/article_content_model.dart +++ b/lib/models/dynamics/article_content_model.dart @@ -1,3 +1,4 @@ +import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/models/dynamics/result.dart'; import 'package:PiliPlus/models/dynamics/vote_model.dart'; @@ -48,7 +49,7 @@ class Pic { style = json['style']; liveUrl = json['live_url']; if (width != null && height != null) { - isLongPic = (height! / width!) > 22 / 9; + isLongPic = (height! / width!) > StyleString.imgMaxRatio; } } } diff --git a/lib/pages/history/widgets/item.dart b/lib/pages/history/widgets/item.dart index 601b5635d..c821189e2 100644 --- a/lib/pages/history/widgets/item.dart +++ b/lib/pages/history/widgets/item.dart @@ -182,69 +182,66 @@ class HistoryItem extends StatelessWidget { Positioned( right: 12, bottom: 0, - child: SizedBox( - width: 29, - height: 29, - child: PopupMenuButton( - padding: EdgeInsets.zero, - tooltip: '功能菜单', - icon: Icon( - Icons.more_vert_outlined, - color: theme.colorScheme.outline, - size: 18, - ), - position: PopupMenuPosition.under, - itemBuilder: (_) => [ - if (item.authorMid != null && - item.authorName?.isNotEmpty == true) - PopupMenuItem( - onTap: () => - Get.toNamed('/member?mid=${item.authorMid}'), - height: 38, - child: Row( - children: [ - const Icon( - MdiIcons.accountCircleOutline, - size: 16, - ), - const SizedBox(width: 6), - Text( - '访问:${item.authorName}', - style: const TextStyle(fontSize: 13), - ), - ], - ), - ), - if (business != 'pgc' && - item.badge != '番剧' && - item.tagName?.contains('动画') != true && - business != 'live' && - business?.contains('article') != true) - PopupMenuItem( - onTap: () => - UserHttp.toViewLater(bvid: item.history.bvid), - height: 38, - child: const Row( - children: [ - Icon(Icons.watch_later_outlined, size: 16), - SizedBox(width: 6), - Text('稍后再看', style: TextStyle(fontSize: 13)), - ], - ), - ), + width: 29, + height: 29, + child: PopupMenuButton( + padding: EdgeInsets.zero, + tooltip: '功能菜单', + icon: Icon( + Icons.more_vert_outlined, + color: theme.colorScheme.outline, + size: 18, + ), + position: PopupMenuPosition.under, + itemBuilder: (_) => [ + if (item.authorMid != null && + item.authorName?.isNotEmpty == true) PopupMenuItem( - onTap: () => onDelete(item.kid!, business!), + onTap: () => Get.toNamed('/member?mid=${item.authorMid}'), height: 38, - child: const Row( + child: Row( children: [ - Icon(Icons.close_outlined, size: 16), - SizedBox(width: 6), - Text('删除记录', style: TextStyle(fontSize: 13)), + const Icon( + MdiIcons.accountCircleOutline, + size: 16, + ), + const SizedBox(width: 6), + Text( + '访问:${item.authorName}', + style: const TextStyle(fontSize: 13), + ), ], ), ), - ], - ), + if (business != 'pgc' && + item.badge != '番剧' && + item.tagName?.contains('动画') != true && + business != 'live' && + business?.contains('article') != true) + PopupMenuItem( + onTap: () => + UserHttp.toViewLater(bvid: item.history.bvid), + height: 38, + child: const Row( + children: [ + Icon(Icons.watch_later_outlined, size: 16), + SizedBox(width: 6), + Text('稍后再看', style: TextStyle(fontSize: 13)), + ], + ), + ), + PopupMenuItem( + onTap: () => onDelete(item.kid!, business!), + height: 38, + child: const Row( + children: [ + Icon(Icons.close_outlined, size: 16), + SizedBox(width: 6), + Text('删除记录', style: TextStyle(fontSize: 13)), + ], + ), + ), + ], ), ), ], diff --git a/lib/pages/live_room/view.dart b/lib/pages/live_room/view.dart index 5abb1c588..d33d3826b 100644 --- a/lib/pages/live_room/view.dart +++ b/lib/pages/live_room/view.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'dart:math'; import 'dart:ui'; +import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/widgets/button/icon_button.dart'; import 'package:PiliPlus/common/widgets/custom_icon.dart'; import 'package:PiliPlus/common/widgets/flutter/text_field/controller.dart'; @@ -308,41 +309,38 @@ class _LiveRoomPageState extends State Positioned( left: padding.left + 25, bottom: 25, + width: 255, child: Obx(() { final item = _liveRoomController.fsSC.value; if (item == null) { return const SizedBox.shrink(); } try { - return SizedBox( + return Stack( key: ValueKey(item.id), - width: 255, - child: Stack( - clipBehavior: Clip.none, - children: [ - Padding( - padding: const EdgeInsets.only(right: 6, top: 6), - child: SuperChatCard( - item: item, - onRemove: () => _liveRoomController.fsSC.value = null, - onReport: () => _liveRoomController.reportSC(item), - ), + clipBehavior: Clip.none, + children: [ + Padding( + padding: const EdgeInsets.only(right: 6, top: 6), + child: SuperChatCard( + item: item, + onRemove: () => _liveRoomController.fsSC.value = null, + onReport: () => _liveRoomController.reportSC(item), ), - Positioned( - right: 0, - top: 0, - child: iconButton( - size: 24, - iconSize: 14, - bgColor: const Color(0xEEFFFFFF), - iconColor: Colors.black54, - icon: const Icon(Icons.clear), - onPressed: () => - _liveRoomController.fsSC.value = null, - ), + ), + Positioned( + right: 0, + top: 0, + child: iconButton( + size: 24, + iconSize: 14, + bgColor: const Color(0xEEFFFFFF), + iconColor: Colors.black54, + icon: const Icon(Icons.clear), + onPressed: () => _liveRoomController.fsSC.value = null, ), - ], - ), + ), + ], ); } catch (_) { if (kDebugMode) rethrow; @@ -428,7 +426,7 @@ class _LiveRoomPageState extends State } Widget _buildPH(bool isFullScreen) { - final height = maxWidth * 9 / 16; + final height = maxWidth / StyleString.aspectRatio16x9; final videoHeight = isFullScreen ? maxHeight - padding.top : height; final bottomHeight = maxHeight - padding.top - height - kToolbarHeight; return Column( @@ -476,24 +474,20 @@ class _LiveRoomPageState extends State left: 0, right: 0, bottom: 55 + bottomHeight, + height: maxHeight * 0.32, child: Offstage( offstage: isFullScreen, - child: SizedBox( - height: maxHeight * 0.32, - child: _buildChatWidget(true), - ), + child: _buildChatWidget(true), ), ), Positioned( left: 0, right: 0, bottom: 0, + height: bottomHeight, child: Offstage( offstage: isFullScreen, - child: SizedBox( - height: bottomHeight, - child: _buildInputWidget, - ), + child: _buildInputWidget, ), ), ], @@ -998,7 +992,7 @@ class _RenderBorderIndicator extends RenderBox { @override void performLayout() { - size = constraints.constrain(Size(constraints.maxWidth, _radius.x)); + size = constraints.constrainDimensions(constraints.maxWidth, _radius.x); } @override @@ -1011,7 +1005,7 @@ class _RenderBorderIndicator extends RenderBox { } BoxBorder.paintNonUniformBorder( canvas, - Rect.fromLTWH(0, 0, width, size.height), + Rect.fromLTRB(0, 0, width, size.height), borderRadius: BorderRadius.only( topLeft: _isLeft ? _radius : .zero, topRight: _isLeft ? .zero : _radius, diff --git a/lib/pages/member_video/widgets/video_card_h_member_video.dart b/lib/pages/member_video/widgets/video_card_h_member_video.dart index fb561a863..c09b3cdd5 100644 --- a/lib/pages/member_video/widgets/video_card_h_member_video.dart +++ b/lib/pages/member_video/widgets/video_card_h_member_video.dart @@ -214,8 +214,9 @@ class VideoCardHMemberVideo extends StatelessWidget { Positioned( bottom: 0, right: 12, + width: 29, + height: 29, child: VideoPopupMenu( - size: 29, iconSize: 17, videoItem: videoItem, ), diff --git a/lib/pages/save_panel/view.dart b/lib/pages/save_panel/view.dart index a8411b00f..74a577e8d 100644 --- a/lib/pages/save_panel/view.dart +++ b/lib/pages/save_panel/view.dart @@ -410,7 +410,8 @@ class _SavePanelState extends State { src: cover!, height: coverSize, width: coverType == _CoverType.def16_9 - ? coverSize * 16 / 9 + ? coverSize * + StyleString.aspectRatio16x9 : coverSize, quality: 100, borderRadius: const BorderRadius.all( diff --git a/lib/pages/subscription/widgets/item.dart b/lib/pages/subscription/widgets/item.dart index 28d72ee4f..49bbcb3f3 100644 --- a/lib/pages/subscription/widgets/item.dart +++ b/lib/pages/subscription/widgets/item.dart @@ -140,17 +140,15 @@ class SubItem extends StatelessWidget { Positioned( bottom: 0, right: 0, - child: SizedBox( - height: 35, - width: 35, - child: IconButton( - onPressed: cancelSub, - style: TextButton.styleFrom( - foregroundColor: theme.colorScheme.outline, - padding: EdgeInsets.zero, - ), - icon: const Icon(Icons.delete_outline, size: 18), + height: 35, + width: 35, + child: IconButton( + onPressed: cancelSub, + style: TextButton.styleFrom( + foregroundColor: theme.colorScheme.outline, + padding: EdgeInsets.zero, ), + icon: const Icon(Icons.delete_outline, size: 18), ), ), ], diff --git a/lib/pages/video/view.dart b/lib/pages/video/view.dart index b64f5af5c..272ed6dd5 100644 --- a/lib/pages/video/view.dart +++ b/lib/pages/video/view.dart @@ -478,7 +478,7 @@ class _VideoDetailPageVState extends State maxHeight = size.height; final shortestSide = size.shortestSide; - final minVideoHeight = shortestSide * 9 / 16; + final minVideoHeight = shortestSide / StyleString.aspectRatio16x9; final maxVideoHeight = max(size.longestSide * 0.65, shortestSide); videoDetailController ..isPortrait = isPortrait = maxHeight >= maxWidth @@ -960,7 +960,7 @@ class _VideoDetailPageVState extends State enableVerticalExpand && !isPortrait) { final double videoHeight = maxHeight - padding.vertical; - final double width = videoHeight * 9 / 16; + final double width = videoHeight / StyleString.aspectRatio16x9; final videoWidth = isFullScreen ? maxWidth : width; final introWidth = (maxWidth - padding.horizontal - width) / 2; final introHeight = maxHeight - padding.top; @@ -1022,10 +1022,10 @@ class _VideoDetailPageVState extends State width = maxWidth - clampDouble(maxWidth - width, 280, 425); } final videoWidth = isFullScreen ? maxWidth : width; - final double height = width * 9 / 16; + final double height = width / StyleString.aspectRatio16x9; final videoHeight = isFullScreen ? maxHeight - padding.top : height; if (height > maxHeight) { - return childSplit(16 / 9); + return childSplit(StyleString.aspectRatio16x9); } final introHeight = maxHeight - height - padding.top; final showIntro = @@ -1396,7 +1396,7 @@ class _VideoDetailPageVState extends State child = childWhenDisabled; } else if (maxWidth / maxHeight >= kScreenRatio) { child = childWhenDisabledLandscape; - } else if (maxWidth * (9 / 16) < (2 / 5) * maxHeight) { + } else if (maxWidth / StyleString.aspectRatio16x9 < 0.4 * maxHeight) { child = childWhenDisabled; } else { child = childWhenDisabledAlmostSquare; @@ -1620,21 +1620,19 @@ class _VideoDetailPageVState extends State Positioned( left: 16, bottom: isFullScreen ? max(75, maxHeight * 0.25) : 75, - child: SizedBox( - width: MediaQuery.textScalerOf(context).scale(120), - child: AnimatedList( - padding: EdgeInsets.zero, - key: videoDetailController.listKey, - reverse: true, - shrinkWrap: true, - initialItemCount: videoDetailController.listData.length, - itemBuilder: (context, index, animation) { - return videoDetailController.buildItem( - videoDetailController.listData[index], - animation, - ); - }, - ), + width: MediaQuery.textScalerOf(context).scale(120), + child: AnimatedList( + padding: EdgeInsets.zero, + key: videoDetailController.listKey, + reverse: true, + shrinkWrap: true, + initialItemCount: videoDetailController.listData.length, + itemBuilder: (context, index, animation) { + return videoDetailController.buildItem( + videoDetailController.listData[index], + animation, + ); + }, ), ), diff --git a/lib/pages/whisper_detail/controller.dart b/lib/pages/whisper_detail/controller.dart index e2a21d635..3a0e1b96d 100644 --- a/lib/pages/whisper_detail/controller.dart +++ b/lib/pages/whisper_detail/controller.dart @@ -134,10 +134,10 @@ class WhisperDetailController extends CommonListController { Future onReport(Msg item, int reasonType, String reasonDesc) { return MsgHttp.imMsgReport( - accusedUid: item.senderUid, + accusedUid: item.senderUid.toInt(), reasonType: reasonType, reasonDesc: reasonDesc, - comment: {'group_id': 0, 'msg_key': item.msgKey}, + comment: {'group_id': 0, 'msg_key': item.msgKey.toString()}, extra: {"msg_keys": []}, ); } diff --git a/lib/pages/whisper_detail/widget/chat_item.dart b/lib/pages/whisper_detail/widget/chat_item.dart index b2df79f8c..e0e915cd6 100644 --- a/lib/pages/whisper_detail/widget/chat_item.dart +++ b/lib/pages/whisper_detail/widget/chat_item.dart @@ -435,7 +435,8 @@ class ChatItem extends StatelessWidget { NetworkImgLayer( type: ImageType.emote, width: constrains.maxWidth, - height: constrains.maxWidth * 9 / 16, + height: + constrains.maxWidth / StyleString.aspectRatio16x9, src: content['cover'], ), PBadge( diff --git a/lib/plugin/pl_player/models/video_fit_type.dart b/lib/plugin/pl_player/models/video_fit_type.dart index 88b470b22..67938c72d 100644 --- a/lib/plugin/pl_player/models/video_fit_type.dart +++ b/lib/plugin/pl_player/models/video_fit_type.dart @@ -1,3 +1,4 @@ +import 'package:PiliPlus/common/constants.dart'; import 'package:flutter/material.dart' show BoxFit; enum VideoFitType { @@ -9,7 +10,7 @@ enum VideoFitType { none('原始', boxFit: BoxFit.none), scaleDown('限制', boxFit: BoxFit.scaleDown), ratio_4x3('4:3', aspectRatio: 4 / 3), - ratio_16x9('16:9', aspectRatio: 16 / 9) + ratio_16x9('16:9', aspectRatio: StyleString.aspectRatio16x9) ; final String desc; diff --git a/lib/plugin/pl_player/view.dart b/lib/plugin/pl_player/view.dart index 49ebb5df5..be205ffc5 100644 --- a/lib/plugin/pl_player/view.dart +++ b/lib/plugin/pl_player/view.dart @@ -2459,7 +2459,7 @@ Widget buildDmChart( bottom: videoDetailController.viewPointList.isNotEmpty && videoDetailController.showVP.value - ? 20.25 + offset + ? 19.25 + offset : 4.25 + offset, ), child: LineChart(