mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-06-29 05:40:17 +08:00
tweaks (#2426)
* opt: danmaku weight
* opt: cache clean
* opt: level img
* opt: play icon
* opt: svg big-vip
* opt: webview ua
* opt: simple dialog
* feat: export vtt
* tweak
* opt: mapIndexed
* feat: more subtitle
* refa: settings page
* feat: codec list options
* drawPath
Signed-off-by: dom <githubaccount56556@proton.me>
* custom dialog option
Signed-off-by: dom <githubaccount56556@proton.me>
* update
Signed-off-by: dom <githubaccount56556@proton.me>
* Revert "drawPath"
This reverts commit e8a4b19f0f.
* opt: _initStreamIndex
* fix: avoid gap
* fix: scale [skip ci]
* fix: hide repost menu not login
* tweaks
Signed-off-by: dom <githubaccount56556@proton.me>
---------
Co-authored-by: dom <githubaccount56556@proton.me>
This commit is contained in:
committed by
GitHub
parent
3dee6a85e5
commit
9d94c72e95
@@ -6,11 +6,10 @@ abstract final class Assets {
|
||||
static const logoIco = 'assets/images/logo/ico/app_icon.ico';
|
||||
static const logoLarge = 'assets/images/logo/desktop/logo_large.png';
|
||||
|
||||
static const vipIcon = 'assets/images/big-vip.png';
|
||||
static const vipIcon = 'assets/images/big-vip.svg';
|
||||
static const avatarPlaceHolder = 'assets/images/noface.jpeg';
|
||||
static const loading = 'assets/images/loading.png';
|
||||
static const buffering = 'assets/images/loading.webp';
|
||||
static const play = 'assets/images/play.png';
|
||||
static const topicHeader = 'assets/images/topic-header-bg.png';
|
||||
static const trendingBanner = 'assets/images/trending_banner.png';
|
||||
static const ai = 'assets/images/ai.png';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/model_owner.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget avatars({
|
||||
@@ -28,19 +29,19 @@ Widget avatars({
|
||||
width: offset * users.length + gap,
|
||||
child: Stack(
|
||||
clipBehavior: .none,
|
||||
children: users.indexed
|
||||
.map(
|
||||
(e) => Positioned(
|
||||
children: users
|
||||
.mapIndexed(
|
||||
(i, e) => Positioned(
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: size,
|
||||
left: e.$1 * offset,
|
||||
left: i * offset,
|
||||
child: DecoratedBox(
|
||||
decoration: decoration,
|
||||
child: Padding(
|
||||
padding: const .all(padding),
|
||||
child: NetworkImgLayer(
|
||||
src: e.$2.face,
|
||||
src: e.face,
|
||||
width: imgSize,
|
||||
height: imgSize,
|
||||
type: .avatar,
|
||||
|
||||
@@ -64,42 +64,39 @@ void showPgcFollowDialog({
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
builder: (context) => SimpleDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
...const [
|
||||
(followStatus: 3, title: '看过'),
|
||||
(followStatus: 2, title: '在看'),
|
||||
(followStatus: 1, title: '想看'),
|
||||
].map(
|
||||
(item) => statusItem(
|
||||
enabled: followStatus != item.followStatus,
|
||||
text: item.title,
|
||||
onTap: () {
|
||||
Get.back();
|
||||
onUpdateStatus(item.followStatus);
|
||||
},
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: Text(
|
||||
'取消$type',
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
),
|
||||
children: [
|
||||
...const [
|
||||
(followStatus: 3, title: '看过'),
|
||||
(followStatus: 2, title: '在看'),
|
||||
(followStatus: 1, title: '想看'),
|
||||
].map(
|
||||
(item) => statusItem(
|
||||
enabled: followStatus != item.followStatus,
|
||||
text: item.title,
|
||||
onTap: () {
|
||||
Get.back();
|
||||
onUpdateStatus(-1);
|
||||
onUpdateStatus(item.followStatus);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: Text(
|
||||
'取消$type',
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
onUpdateStatus(-1);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async' show FutureOr;
|
||||
import 'dart:convert' show utf8, jsonDecode;
|
||||
|
||||
import 'package:PiliPlus/common/style.dart';
|
||||
import 'package:PiliPlus/common/widgets/dialog/simple_dialog_option.dart';
|
||||
import 'package:PiliPlus/utils/extension/theme_ext.dart';
|
||||
import 'package:PiliPlus/utils/storage_utils.dart';
|
||||
import 'package:PiliPlus/utils/utils.dart';
|
||||
@@ -214,21 +215,19 @@ Future<void> showImportExportDialog<T>(
|
||||
builder: (context) {
|
||||
const style = TextStyle(fontSize: 15);
|
||||
return SimpleDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
clipBehavior: .hardEdge,
|
||||
title: Text('导入/导出$title'),
|
||||
children: [
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text('导出至剪贴板', style: style),
|
||||
onTap: () {
|
||||
DialogOption(
|
||||
child: const Text('导出至剪贴板', style: style),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
exportToClipBoard(onExport: onExport);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text('导出文件至本地', style: style),
|
||||
onTap: () {
|
||||
DialogOption(
|
||||
child: const Text('导出文件至本地', style: style),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
exportToLocalFile(onExport: onExport, localFileName: localFileName);
|
||||
},
|
||||
@@ -237,18 +236,16 @@ Future<void> showImportExportDialog<T>(
|
||||
height: 1,
|
||||
color: ColorScheme.of(context).outline.withValues(alpha: 0.1),
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text('输入', style: style),
|
||||
onTap: () {
|
||||
DialogOption(
|
||||
child: const Text('输入', style: style),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
importFromInput<T>(context, title: title, onImport: onImport);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text('从剪贴板导入', style: style),
|
||||
onTap: () {
|
||||
DialogOption(
|
||||
child: const Text('从剪贴板导入', style: style),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
importFromClipBoard<T>(
|
||||
context,
|
||||
@@ -258,10 +255,9 @@ Future<void> showImportExportDialog<T>(
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
title: const Text('从本地文件导入', style: style),
|
||||
onTap: () {
|
||||
DialogOption(
|
||||
child: const Text('从本地文件导入', style: style),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
importFromLocalFile<T>(onImport: onImport);
|
||||
},
|
||||
|
||||
29
lib/common/widgets/dialog/simple_dialog_option.dart
Normal file
29
lib/common/widgets/dialog/simple_dialog_option.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
final EdgeInsets _padding = PlatformUtils.isMobile
|
||||
? const .symmetric(horizontal: 16, vertical: 14)
|
||||
: const .symmetric(horizontal: 16, vertical: 10);
|
||||
|
||||
class DialogOption extends StatelessWidget {
|
||||
const DialogOption({
|
||||
super.key,
|
||||
this.onPressed,
|
||||
this.child,
|
||||
});
|
||||
|
||||
final VoidCallback? onPressed;
|
||||
|
||||
final Widget? child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: onPressed,
|
||||
child: Padding(
|
||||
padding: _padding,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
import 'dart:io' show File, Platform;
|
||||
|
||||
import 'package:PiliPlus/common/widgets/colored_box_transition.dart';
|
||||
import 'package:PiliPlus/common/widgets/dialog/simple_dialog_option.dart';
|
||||
import 'package:PiliPlus/common/widgets/flutter/page/page_view.dart';
|
||||
import 'package:PiliPlus/common/widgets/gesture/image_horizontal_drag_gesture_recognizer.dart';
|
||||
import 'package:PiliPlus/common/widgets/image_viewer/image.dart';
|
||||
@@ -534,76 +535,67 @@ class _GalleryViewerState extends State<GalleryViewer>
|
||||
HapticFeedback.mediumImpact();
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
builder: (context) => SimpleDialog(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (PlatformUtils.isMobile)
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
ImageUtils.onShareImg(item.url);
|
||||
},
|
||||
dense: true,
|
||||
title: const Text('分享', style: TextStyle(fontSize: 14)),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
children: [
|
||||
if (PlatformUtils.isMobile)
|
||||
DialogOption(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
Utils.copyText(item.url);
|
||||
ImageUtils.onShareImg(item.url);
|
||||
},
|
||||
dense: true,
|
||||
title: const Text('复制链接', style: TextStyle(fontSize: 14)),
|
||||
child: const Text('分享', style: TextStyle(fontSize: 14)),
|
||||
),
|
||||
ListTile(
|
||||
onTap: () {
|
||||
DialogOption(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
Utils.copyText(item.url);
|
||||
},
|
||||
child: const Text('复制链接', style: TextStyle(fontSize: 14)),
|
||||
),
|
||||
DialogOption(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
ImageUtils.downloadImg([item.url]);
|
||||
},
|
||||
child: const Text('保存图片', style: TextStyle(fontSize: 14)),
|
||||
),
|
||||
if (PlatformUtils.isDesktop)
|
||||
DialogOption(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
ImageUtils.downloadImg([item.url]);
|
||||
PageUtils.launchURL(item.url);
|
||||
},
|
||||
dense: true,
|
||||
title: const Text('保存图片', style: TextStyle(fontSize: 14)),
|
||||
child: const Text('网页打开', style: TextStyle(fontSize: 14)),
|
||||
)
|
||||
else if (widget.sources.length > 1)
|
||||
DialogOption(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
ImageUtils.downloadImg(
|
||||
widget.sources.map((item) => item.url).toList(),
|
||||
);
|
||||
},
|
||||
child: const Text('保存全部图片', style: TextStyle(fontSize: 14)),
|
||||
),
|
||||
if (PlatformUtils.isDesktop)
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
PageUtils.launchURL(item.url);
|
||||
},
|
||||
dense: true,
|
||||
title: const Text('网页打开', style: TextStyle(fontSize: 14)),
|
||||
)
|
||||
else if (widget.sources.length > 1)
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
ImageUtils.downloadImg(
|
||||
widget.sources.map((item) => item.url).toList(),
|
||||
);
|
||||
},
|
||||
dense: true,
|
||||
title: const Text('保存全部图片', style: TextStyle(fontSize: 14)),
|
||||
if (item.sourceType == SourceType.livePhoto)
|
||||
DialogOption(
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
ImageUtils.downloadLivePhoto(
|
||||
url: item.url,
|
||||
liveUrl: item.liveUrl!,
|
||||
width: item.width!,
|
||||
height: item.height!,
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'保存${Platform.isIOS ? ' Live Photo' : '视频'}',
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
if (item.sourceType == SourceType.livePhoto)
|
||||
ListTile(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
ImageUtils.downloadLivePhoto(
|
||||
url: item.url,
|
||||
liveUrl: item.liveUrl!,
|
||||
width: item.width!,
|
||||
height: item.height!,
|
||||
);
|
||||
},
|
||||
dense: true,
|
||||
title: Text(
|
||||
'保存${Platform.isIOS ? ' Live Photo' : '视频'}',
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ import 'package:PiliPlus/common/widgets/extra_hittest_stack.dart';
|
||||
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
|
||||
import 'package:PiliPlus/models/common/avatar_badge_type.dart';
|
||||
import 'package:PiliPlus/models/common/image_type.dart';
|
||||
import 'package:PiliPlus/utils/extension/num_ext.dart';
|
||||
import 'package:PiliPlus/utils/page_utils.dart';
|
||||
import 'package:PiliPlus/utils/storage_pref.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
|
||||
class PendantAvatar extends StatelessWidget {
|
||||
const PendantAvatar(
|
||||
@@ -142,12 +142,11 @@ class PendantAvatar extends StatelessWidget {
|
||||
|
||||
Widget _buildBadge(BuildContext context, ColorScheme colorScheme) {
|
||||
final child = switch (badgeType) {
|
||||
.vip => Image.asset(
|
||||
.vip => SvgPicture.asset(
|
||||
Assets.vipIcon,
|
||||
width: badgeSize,
|
||||
height: badgeSize,
|
||||
cacheWidth: badgeSize.cacheSize(context),
|
||||
semanticLabel: badgeType.desc,
|
||||
semanticsLabel: badgeType.desc,
|
||||
),
|
||||
_ => Icon(
|
||||
Icons.offline_bolt,
|
||||
|
||||
@@ -207,13 +207,7 @@ class RenderViewPointProgressBar
|
||||
),
|
||||
),
|
||||
)
|
||||
..pushStyle(
|
||||
ui.TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: size,
|
||||
height: 1,
|
||||
),
|
||||
)
|
||||
..pushStyle(.new(color: Colors.white, fontSize: size, height: 1))
|
||||
..addText(title);
|
||||
return builder.build()
|
||||
..layout(const ui.ParagraphConstraints(width: double.infinity));
|
||||
|
||||
@@ -28,6 +28,9 @@ class _SelfSizedHorizontalListState extends State<SelfSizedHorizontalList> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_height == null) {
|
||||
if (widget.itemCount == 0) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return OnlyLayoutWidget(
|
||||
onPerformLayout: (Size size) {
|
||||
if (!mounted) return;
|
||||
|
||||
293
lib/common/widgets/svg/level_icon.dart
Normal file
293
lib/common/widgets/svg/level_icon.dart
Normal file
@@ -0,0 +1,293 @@
|
||||
// dart format width=120
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/semantics.dart';
|
||||
|
||||
class UserLevel extends LeafRenderObjectWidget {
|
||||
const UserLevel(
|
||||
this.level, {
|
||||
super.key,
|
||||
this.height = 11,
|
||||
this.flash = false,
|
||||
});
|
||||
|
||||
final double height;
|
||||
final int level;
|
||||
final bool flash;
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
return RenderLevel(height, level, flash);
|
||||
}
|
||||
|
||||
@override
|
||||
void updateRenderObject(
|
||||
BuildContext context,
|
||||
RenderLevel renderObject,
|
||||
) {
|
||||
renderObject
|
||||
..height = height
|
||||
..level = level
|
||||
..flash = flash;
|
||||
}
|
||||
}
|
||||
|
||||
class RenderLevel extends RenderBox {
|
||||
RenderLevel(this._height, this._level, this._flash);
|
||||
|
||||
double _height;
|
||||
set height(double value) {
|
||||
if (_height == value) return;
|
||||
_height = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
int _level;
|
||||
set level(int value) {
|
||||
if (_level == value) return;
|
||||
_level = value;
|
||||
markNeedsPaint();
|
||||
markNeedsSemanticsUpdate();
|
||||
}
|
||||
|
||||
bool _flash;
|
||||
set flash(bool value) {
|
||||
if (_flash == value) return;
|
||||
_flash = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
@override
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
return constraints.constrainSizeAndAttemptToPreserveAspectRatio(
|
||||
Size(
|
||||
(_flash ? LevelCanvas._extendR : LevelCanvas._totalR) * _height / LevelCanvas._totalB,
|
||||
_height,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = computeDryLayout(constraints);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
final paint = Paint()..color = lookupBackgroundColor(_level);
|
||||
LevelCanvas(context.canvas)
|
||||
..save()
|
||||
..translate(offset.dx, offset.dy)
|
||||
..scale(size.height / LevelCanvas._totalB)
|
||||
..drawLevelBack(paint, bolt: _flash)
|
||||
..drawLevelLv()
|
||||
..drawLEDigit(_level, paint..color = Colors.white)
|
||||
..restore();
|
||||
}
|
||||
|
||||
@override
|
||||
void describeSemanticsConfiguration(SemanticsConfiguration config) {
|
||||
super.describeSemanticsConfiguration(config);
|
||||
config.label = '${_flash ? "硬核" : ""}$_level级';
|
||||
}
|
||||
|
||||
static Color lookupBackgroundColor(int level) {
|
||||
return switch (level) {
|
||||
0 || 1 => const Color(0xFFC0C0C0),
|
||||
2 => const Color(0xFF8BD29B),
|
||||
3 => const Color(0xFF7BCDEF),
|
||||
4 => const Color(0xFFFEBB8B),
|
||||
5 => const Color(0xFFEE672A),
|
||||
_ => const Color(0xFFF04C49),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
extension type LevelCanvas(Canvas _) implements Canvas {
|
||||
// ========== 布局常量 ==========
|
||||
static const _r = Radius.circular(20);
|
||||
|
||||
static const double _left = 629;
|
||||
static const double _right = 877;
|
||||
static const double _colW = 68; // 竖段宽度
|
||||
static const double _lColR = _left + _colW; // 697
|
||||
static const double _rColL = _right - _colW; // 810
|
||||
|
||||
// 三条横线的边界
|
||||
static const double _rowH = 68;
|
||||
static const double _rowSp = 146;
|
||||
static const double _topY = 55;
|
||||
static const double _topYB = _topY + _rowH; // 123
|
||||
static const double _midY = _topY + _rowSp; // 201
|
||||
static const double _midYB = _midY + _rowH; // 269
|
||||
static const double _botY = _midY + _rowSp; // 347
|
||||
static const double _botYB = _botY + _rowH; // 415
|
||||
|
||||
// 竖段拼接用的中心线
|
||||
static const double _midMid = (_midY + _midYB) / 2; // 235
|
||||
|
||||
static final _boltIcon =
|
||||
(ParagraphBuilder(
|
||||
ParagraphStyle(
|
||||
fontSize: 460,
|
||||
fontFamily: Icons.bolt_rounded.fontFamily,
|
||||
height: 1,
|
||||
fontWeight: FontWeight.w900,
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
)..addText(.fromCharCode(Icons.bolt_rounded.codePoint))).build()
|
||||
..layout(const ParagraphConstraints(width: double.infinity));
|
||||
void drawBolt() => drawParagraph(_boltIcon, const Offset(840, 5));
|
||||
|
||||
void _draw1(Paint paint) {
|
||||
drawRRect(const .fromLTRBXY(673, _botY, 833, _botYB, 20, 20), paint);
|
||||
drawRRect(.fromLTRBAndCorners(673, _topY, 787, _topYB, topLeft: _r, bottomLeft: _r, topRight: _r), paint);
|
||||
drawRect(const .fromLTRB(719, _topYB, 787, _botY), paint);
|
||||
}
|
||||
|
||||
void drawLEDigit(int digit, Paint paint) {
|
||||
if (digit == 1) return _draw1(paint);
|
||||
final bits = switch (digit) {
|
||||
0 => 0x7E,
|
||||
2 => 0x6D,
|
||||
3 => 0x79,
|
||||
4 => 0x33,
|
||||
5 => 0x5B,
|
||||
6 => 0x5F,
|
||||
7 => 0x70,
|
||||
8 => 0x7F,
|
||||
9 => 0x7B,
|
||||
// _ => throw ArgumentError('Unsupported digit: $digit'),
|
||||
_ => 0x4F, // `E`
|
||||
};
|
||||
|
||||
_drawSegments(
|
||||
bits & 0x40 != 0,
|
||||
bits & 0x20 != 0,
|
||||
bits & 0x10 != 0,
|
||||
bits & 0x08 != 0,
|
||||
bits & 0x04 != 0,
|
||||
bits & 0x02 != 0,
|
||||
bits & 0x01 != 0,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
||||
void _drawSegments(bool a, bool b, bool c, bool d, bool e, bool f, bool g, Paint paint) {
|
||||
// 横段
|
||||
if (a) {
|
||||
_drawRRect(_left, _topY, _right, _topYB, _r, _r, f ? .zero : _r, b ? .zero : _r, paint);
|
||||
}
|
||||
if (g) {
|
||||
_drawRRect(_left, _midY, _right, _midYB, f ? .zero : _r, b ? .zero : _r, e ? .zero : _r, c ? .zero : _r, paint);
|
||||
}
|
||||
if (d) {
|
||||
_drawRRect(_left, _botY, _right, _botYB, e ? .zero : _r, c ? .zero : _r, _r, _r, paint);
|
||||
}
|
||||
|
||||
// 竖段
|
||||
// 左上竖段 f
|
||||
if (f) {
|
||||
final top = (a ? _topYB : _topY) - 1; // 有上横则齐底,否则到顶
|
||||
final bottom = (g ? _midY : (e ? _midMid : _midYB)) + 1;
|
||||
final rTop = a ? Radius.zero : _r;
|
||||
final rBot = g || e ? Radius.zero : _r;
|
||||
_drawRRect(_left, top, _lColR, bottom, rTop, rTop, rBot, rBot, paint);
|
||||
}
|
||||
|
||||
// 右上竖段 b
|
||||
if (b) {
|
||||
final top = (a ? _topYB : _topY) - 1;
|
||||
final bottom = (g ? _midY : (c ? _midMid : _midYB)) + 1;
|
||||
final rTop = a ? Radius.zero : _r;
|
||||
final rBot = g || c ? Radius.zero : _r;
|
||||
_drawRRect(_rColL, top, _right, bottom, rTop, rTop, rBot, rBot, paint);
|
||||
}
|
||||
|
||||
// 左下竖段 e
|
||||
if (e) {
|
||||
final top = (g ? _midYB : (f ? _midMid : _midY)) - 1;
|
||||
final bottom = (d ? _botY : _botYB) + 1;
|
||||
final rTop = g || f ? Radius.zero : _r;
|
||||
final rBot = d ? Radius.zero : _r;
|
||||
_drawRRect(_left, top, _lColR, bottom, rTop, rTop, rBot, rBot, paint);
|
||||
}
|
||||
|
||||
// 右下竖段 c
|
||||
if (c) {
|
||||
final top = (g ? _midYB : (b ? _midMid : _midY)) - 1;
|
||||
final bottom = (d ? _botY : _botYB) + 1;
|
||||
final rTop = g || b ? Radius.zero : _r;
|
||||
final rBot = d ? Radius.zero : _r;
|
||||
_drawRRect(_rColL, top, _right, bottom, rTop, rTop, rBot, rBot, paint);
|
||||
}
|
||||
}
|
||||
|
||||
/// 绘制圆角矩形,四角全零时退化为矩形
|
||||
void _drawRRect(double l, double t, double r, double b, Radius tl, Radius tr, Radius bl, Radius br, Paint paint) {
|
||||
if (tl == .zero && tr == .zero && bl == .zero && br == .zero) {
|
||||
drawRect(.fromLTRB(l, t, r, b), paint);
|
||||
} else {
|
||||
drawRRect(.fromLTRBAndCorners(l, t, r, b, topLeft: tl, topRight: tr, bottomLeft: bl, bottomRight: br), paint);
|
||||
}
|
||||
}
|
||||
|
||||
static final _lvPicture = () {
|
||||
final recorder = PictureRecorder();
|
||||
final paint = Paint()..color = Colors.white;
|
||||
final canvas = Canvas(recorder);
|
||||
|
||||
const double vLeft = 296;
|
||||
const double lvTop = 106;
|
||||
const double llr = 123;
|
||||
const double vtb = 282;
|
||||
|
||||
canvas
|
||||
// L
|
||||
..drawRRect(.fromLTRBAndCorners(56, lvTop, llr, _botYB, topLeft: _r, topRight: _r, bottomLeft: _r), paint)
|
||||
..drawRRect(.fromLTRBAndCorners(llr - 1, _botY, 256, _botYB, topRight: _r, bottomRight: _r), paint)
|
||||
// V
|
||||
..drawRRect(.fromLTRBAndCorners(vLeft, lvTop, 363, vtb + 1, topLeft: _r, topRight: _r), paint)
|
||||
..drawRRect(.fromLTRBAndCorners(476, lvTop, 543, vtb + 1, topLeft: _r, topRight: _r), paint)
|
||||
..drawPath(
|
||||
Path()
|
||||
..moveTo(vLeft, vtb)
|
||||
..lineTo(vLeft, 292)
|
||||
..arcToPoint(const Offset(300, 313), radius: const .circular(50), clockwise: false)
|
||||
..lineTo(395, 408)
|
||||
..arcToPoint(const Offset(444, 408), radius: const .circular(50), clockwise: false)
|
||||
..lineTo(539, 313)
|
||||
..arcToPoint(const Offset(543, 292), radius: const .circular(50), clockwise: false)
|
||||
..lineTo(543, vtb)
|
||||
..lineTo(476, vtb)
|
||||
..lineTo(419.5, 340)
|
||||
..lineTo(363, vtb)
|
||||
..close(),
|
||||
paint,
|
||||
);
|
||||
return recorder.endRecording();
|
||||
}();
|
||||
|
||||
void drawLevelLv() => drawPicture(_lvPicture);
|
||||
|
||||
static const double _totalR = 930;
|
||||
static const double _extendR = 1250;
|
||||
static const double _totalB = 466;
|
||||
|
||||
void drawLevelBack(Paint paint, {bool bolt = false}) {
|
||||
const radius = Radius.circular(27);
|
||||
final double right = bolt ? _extendR : _totalR;
|
||||
const double blockTop = 48;
|
||||
drawRRect(
|
||||
RRect.fromLTRBAndCorners(0, blockTop, right, _totalB, topLeft: radius, bottomLeft: radius, bottomRight: radius),
|
||||
paint,
|
||||
);
|
||||
drawRRect(
|
||||
RRect.fromLTRBAndCorners(576, 0, right, blockTop + 1, topLeft: radius, topRight: radius),
|
||||
paint,
|
||||
);
|
||||
|
||||
if (bolt) drawBolt();
|
||||
}
|
||||
}
|
||||
218
lib/common/widgets/svg/play_icon.dart
Normal file
218
lib/common/widgets/svg/play_icon.dart
Normal file
@@ -0,0 +1,218 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/semantics.dart';
|
||||
|
||||
class PlayIcon extends LeafRenderObjectWidget {
|
||||
const PlayIcon({super.key, this.size = 60});
|
||||
|
||||
final double size;
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
return RenderPlay(size);
|
||||
}
|
||||
|
||||
@override
|
||||
void updateRenderObject(BuildContext context, RenderPlay renderObject) {
|
||||
renderObject.imgSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
class RenderPlay extends RenderBox {
|
||||
RenderPlay(this._imgSize);
|
||||
|
||||
double _imgSize;
|
||||
set imgSize(double value) {
|
||||
if (_imgSize == value) return;
|
||||
_imgSize = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
@override
|
||||
Size computeDryLayout(covariant BoxConstraints constraints) {
|
||||
return constraints.constrainDimensions(_imgSize, _imgSize);
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
size = computeDryLayout(constraints);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
final canvas = context.canvas;
|
||||
final size = this.size.shortestSide;
|
||||
if (offset != .zero || size != 60) {
|
||||
canvas.save();
|
||||
if (offset != .zero) canvas.translate(offset.dx, offset.dy);
|
||||
if (size != 60) {
|
||||
canvas.scale(size / 60);
|
||||
}
|
||||
}
|
||||
canvas.drawPicture(_picture);
|
||||
if (offset != .zero || size != 60) {
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void describeSemanticsConfiguration(SemanticsConfiguration config) {
|
||||
super.describeSemanticsConfiguration(config);
|
||||
config.label = '播放';
|
||||
}
|
||||
|
||||
/// [SvgPicture] can not parse mask filter
|
||||
/// fom i0.hdslb.com/bfs/static/player/img/play.svg
|
||||
/// scale size from 80 to 60
|
||||
static final _picture = () {
|
||||
final rec = PictureRecorder();
|
||||
final canvas = Canvas(rec);
|
||||
final path = Path()
|
||||
..moveTo(41.576, 7.318)
|
||||
..cubicTo(41.244, 5.892, 39.91, 4.886, 38.41, 5.011)
|
||||
..cubicTo(38.068, 5.039, 37.813, 5.13, 37.59, 5.245)
|
||||
..cubicTo(37.37, 5.361, 37.187, 5.506, 37.034, 5.672)
|
||||
..cubicTo(36.957, 5.754, 36.891, 5.844, 36.824, 5.934)
|
||||
..lineTo(36.622, 6.203)
|
||||
..lineTo(36.222, 6.743)
|
||||
..cubicTo(35.694, 7.467, 35.178, 8.2, 34.678, 8.945)
|
||||
..cubicTo(34.179, 9.69, 33.694, 10.445, 33.231, 11.217)
|
||||
..cubicTo(33.092, 11.449, 32.954, 11.683, 32.819, 11.917)
|
||||
..cubicTo(32.258, 11.909, 31.697, 11.902, 31.137, 11.898)
|
||||
..cubicTo(29.094, 11.884, 27.051, 11.891, 25.008, 11.926)
|
||||
..cubicTo(24.871, 11.688, 24.732, 11.452, 24.591, 11.217)
|
||||
..cubicTo(24.128, 10.445, 23.643, 9.69, 23.144, 8.945)
|
||||
..cubicTo(22.645, 8.2, 22.129, 7.467, 21.6, 6.743)
|
||||
..lineTo(21.2, 6.203)
|
||||
..lineTo(20.998, 5.934)
|
||||
..cubicTo(20.931, 5.844, 20.865, 5.754, 20.788, 5.672)
|
||||
..cubicTo(20.635, 5.506, 20.452, 5.361, 20.232, 5.245)
|
||||
..cubicTo(20.009, 5.13, 19.754, 5.039, 19.412, 5.011)
|
||||
..cubicTo(17.956, 4.888, 16.59, 5.85, 16.246, 7.318)
|
||||
..cubicTo(16.168, 7.652, 16.176, 7.924, 16.217, 8.172)
|
||||
..cubicTo(16.26, 8.418, 16.34, 8.636, 16.451, 8.833)
|
||||
..cubicTo(16.506, 8.931, 16.571, 9.023, 16.635, 9.114)
|
||||
..lineTo(16.829, 9.389)
|
||||
..lineTo(17.219, 9.936)
|
||||
..cubicTo(17.743, 10.663, 18.281, 11.381, 18.834, 12.086)
|
||||
..cubicTo(18.845, 12.099, 18.855, 12.112, 18.865, 12.124)
|
||||
..cubicTo(18.025, 12.164, 17.184, 12.209, 16.344, 12.26)
|
||||
..cubicTo(15.523, 12.311, 14.701, 12.365, 13.88, 12.428)
|
||||
..lineTo(12.648, 12.525)
|
||||
..lineTo(12.032, 12.577)
|
||||
..lineTo(11.68, 12.616)
|
||||
..cubicTo(11.562, 12.63, 11.445, 12.651, 11.328, 12.668)
|
||||
..cubicTo(10.39, 12.827, 9.477, 13.141, 8.641, 13.595)
|
||||
..cubicTo(7.804, 14.049, 7.043, 14.641, 6.399, 15.34)
|
||||
..cubicTo(5.754, 16.04, 5.224, 16.845, 4.837, 17.716)
|
||||
..cubicTo(4.45, 18.586, 4.208, 19.521, 4.12, 20.467)
|
||||
..cubicTo(3.808, 23.756, 3.603, 27.055, 3.529, 30.365)
|
||||
..cubicTo(3.453, 33.676, 3.53, 36.99, 3.722, 40.289)
|
||||
..cubicTo(3.77, 41.114, 3.825, 41.939, 3.887, 42.763)
|
||||
..lineTo(3.986, 43.998)
|
||||
..lineTo(4.039, 44.616)
|
||||
..lineTo(4.046, 44.693)
|
||||
..lineTo(4.056, 44.782)
|
||||
..lineTo(4.075, 44.961)
|
||||
..cubicTo(4.087, 45.08, 4.107, 45.198, 4.126, 45.317)
|
||||
..cubicTo(4.278, 46.264, 4.586, 47.189, 5.037, 48.037)
|
||||
..cubicTo(5.486, 48.887, 6.078, 49.66, 6.777, 50.319)
|
||||
..cubicTo(7.475, 50.978, 8.283, 51.522, 9.16, 51.921)
|
||||
..cubicTo(10.035, 52.319, 10.978, 52.575, 11.935, 52.664)
|
||||
..cubicTo(11.998, 52.672, 12.047, 52.675, 12.098, 52.68)
|
||||
..lineTo(12.252, 52.693)
|
||||
..lineTo(12.56, 52.72)
|
||||
..lineTo(13.176, 52.771)
|
||||
..lineTo(14.408, 52.868)
|
||||
..cubicTo(15.23, 52.927, 16.052, 52.985, 16.874, 53.033)
|
||||
..cubicTo(23.449, 53.424, 30.03, 53.502, 36.609, 53.259)
|
||||
..cubicTo(38.254, 53.199, 39.898, 53.118, 41.542, 53.016)
|
||||
..cubicTo(42.364, 52.963, 43.186, 52.908, 44.008, 52.843)
|
||||
..lineTo(45.241, 52.743)
|
||||
..lineTo(45.857, 52.689)
|
||||
..lineTo(46.214, 52.65)
|
||||
..cubicTo(46.334, 52.635, 46.452, 52.614, 46.571, 52.596)
|
||||
..cubicTo(47.52, 52.432, 48.443, 52.112, 49.288, 51.649)
|
||||
..cubicTo(50.134, 51.188, 50.902, 50.586, 51.553, 49.878)
|
||||
..cubicTo(52.204, 49.17, 52.739, 48.353, 53.127, 47.471)
|
||||
..cubicTo(53.321, 47.03, 53.479, 46.573, 53.598, 46.107)
|
||||
..cubicTo(53.631, 45.991, 53.656, 45.873, 53.681, 45.755)
|
||||
..lineTo(53.719, 45.579)
|
||||
..lineTo(53.749, 45.401)
|
||||
..cubicTo(53.77, 45.283, 53.79, 45.164, 53.803, 45.045)
|
||||
..cubicTo(53.818, 44.927, 53.834, 44.8, 53.843, 44.704)
|
||||
..cubicTo(54.179, 41.414, 54.402, 38.111, 54.476, 34.794)
|
||||
..cubicTo(54.553, 31.475, 54.442, 28.153, 54.205, 24.853)
|
||||
..cubicTo(54.145, 24.028, 54.078, 23.204, 54.002, 22.38)
|
||||
..lineTo(53.884, 21.145)
|
||||
..lineTo(53.82, 20.528)
|
||||
..lineTo(53.804, 20.374)
|
||||
..lineTo(53.794, 20.29)
|
||||
..lineTo(53.782, 20.201)
|
||||
..cubicTo(53.766, 20.083, 53.754, 19.964, 53.731, 19.846)
|
||||
..cubicTo(53.578, 18.901, 53.266, 17.979, 52.813, 17.136)
|
||||
..cubicTo(52.362, 16.291, 51.771, 15.522, 51.073, 14.869)
|
||||
..cubicTo(50.375, 14.215, 49.57, 13.677, 48.698, 13.284)
|
||||
..cubicTo(47.827, 12.89, 46.89, 12.64, 45.94, 12.552)
|
||||
..lineTo(45.854, 12.544)
|
||||
..lineTo(45.777, 12.537)
|
||||
..lineTo(45.623, 12.524)
|
||||
..lineTo(45.315, 12.499)
|
||||
..lineTo(44.698, 12.449)
|
||||
..lineTo(43.466, 12.357)
|
||||
..cubicTo(42.644, 12.3, 41.822, 12.247, 41.0, 12.202)
|
||||
..cubicTo(40.326, 12.164, 39.651, 12.131, 38.977, 12.1)
|
||||
..cubicTo(38.98, 12.096, 38.984, 12.091, 38.988, 12.086)
|
||||
..cubicTo(39.542, 11.381, 40.079, 10.663, 40.603, 9.936)
|
||||
..lineTo(40.994, 9.389)
|
||||
..lineTo(41.187, 9.114)
|
||||
..cubicTo(41.252, 9.023, 41.316, 8.931, 41.371, 8.833)
|
||||
..cubicTo(41.482, 8.636, 41.563, 8.418, 41.605, 8.172)
|
||||
..cubicTo(41.646, 7.924, 41.654, 7.652, 41.576, 7.318)
|
||||
..close()
|
||||
..moveTo(21.283, 26.038)
|
||||
..cubicTo(21.321, 25.666, 21.427, 25.305, 21.597, 24.973)
|
||||
..cubicTo(22.351, 23.498, 24.158, 22.913, 25.634, 23.667)
|
||||
..lineTo(26.683, 24.211)
|
||||
..cubicTo(28.428, 25.126, 30.148, 26.088, 31.842, 27.097)
|
||||
..cubicTo(34.726, 28.814, 34.726, 28.814, 37.376, 30.628)
|
||||
..cubicTo(37.694, 30.846, 37.967, 31.123, 38.18, 31.444)
|
||||
..cubicTo(39.096, 32.824, 38.72, 34.686, 37.34, 35.603)
|
||||
..lineTo(36.265, 36.309)
|
||||
..cubicTo(34.823, 37.245, 33.349, 38.161, 31.842, 39.058)
|
||||
..cubicTo(28.87, 40.828, 28.87, 40.828, 25.698, 42.513)
|
||||
..cubicTo(25.352, 42.697, 24.973, 42.811, 24.583, 42.849)
|
||||
..cubicTo(22.934, 43.01, 21.466, 41.805, 21.305, 40.156)
|
||||
..lineTo(21.221, 39.247)
|
||||
..cubicTo(21.04, 37.126, 20.949, 35.005, 20.949, 32.884)
|
||||
..cubicTo(20.949, 29.361, 20.949, 29.361, 21.283, 26.038)
|
||||
..close();
|
||||
|
||||
final paint = Paint()
|
||||
..color = Colors.black.withValues(alpha: 0.3 * 0.8)
|
||||
..maskFilter = const .blur(.normal, 1.0);
|
||||
|
||||
// feOffset dy="2"
|
||||
canvas
|
||||
..save()
|
||||
..translate(0, 2)
|
||||
..drawPath(path, paint)
|
||||
..restore();
|
||||
|
||||
// dy=0, blur=3.5
|
||||
paint
|
||||
..color = Colors.black.withValues(alpha: 0.2 * 0.8)
|
||||
..maskFilter = const .blur(.normal, 3.5);
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
|
||||
paint
|
||||
..color = Colors.white.withValues(alpha: 0.8)
|
||||
..maskFilter = null;
|
||||
|
||||
canvas.drawPath(path, paint);
|
||||
|
||||
return rec.endRecording();
|
||||
}();
|
||||
}
|
||||
@@ -147,134 +147,115 @@ class VideoPopupMenu extends StatelessWidget {
|
||||
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: '正在提交',
|
||||
return SimpleDialog(
|
||||
contentPadding: const .fromLTRB(24, 16, 24, 24),
|
||||
children: [
|
||||
if (tp.dislikeReasons != null) ...[
|
||||
const Text('我不想看'),
|
||||
const SizedBox(height: 5),
|
||||
Wrap(
|
||||
spacing: 8.0,
|
||||
runSpacing: 8.0,
|
||||
children: tp.dislikeReasons!
|
||||
.map((item) => 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) => 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!,
|
||||
);
|
||||
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("撤销"),
|
||||
),
|
||||
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) => AlertDialog(
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
builder: (context) => SimpleDialog(
|
||||
contentPadding: const .all(24),
|
||||
children: [
|
||||
const Center(child: Text("web端暂不支持精细选择")),
|
||||
const SizedBox(height: 5),
|
||||
Wrap(
|
||||
spacing: 5.0,
|
||||
runSpacing: 2.0,
|
||||
alignment: .center,
|
||||
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("撤销"),
|
||||
),
|
||||
],
|
||||
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: .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: .compact,
|
||||
),
|
||||
child: const Text("撤销"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -298,9 +279,7 @@ class VideoPopupMenu extends StatelessWidget {
|
||||
child: Text(
|
||||
'点错了',
|
||||
style: TextStyle(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.outline,
|
||||
color: ColorScheme.of(context).outline,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user