mod: 自定义toast样式、详情页样式修改
This commit is contained in:
23
lib/common/widgets/custom_toast.dart
Normal file
23
lib/common/widgets/custom_toast.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CustomToast extends StatelessWidget {
|
||||||
|
final String msg;
|
||||||
|
const CustomToast({Key? key, required this.msg}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
margin: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 10),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.primaryContainer.withOpacity(0.8),
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
child: Text(msg,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.labelMedium!
|
||||||
|
.copyWith(color: Theme.of(context).colorScheme.primary)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,7 +24,7 @@ class StatDanMu extends StatelessWidget {
|
|||||||
size: 14,
|
size: 14,
|
||||||
color: color,
|
color: color,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 3),
|
const SizedBox(width: 2),
|
||||||
Text(
|
Text(
|
||||||
Utils.numFormat(danmu!),
|
Utils.numFormat(danmu!),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|||||||
@ -24,7 +24,7 @@ class StatView extends StatelessWidget {
|
|||||||
size: 13,
|
size: 13,
|
||||||
color: color,
|
color: color,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 3),
|
const SizedBox(width: 2),
|
||||||
Text(
|
Text(
|
||||||
Utils.numFormat(view!),
|
Utils.numFormat(view!),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:dynamic_color/dynamic_color.dart';
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
|
import 'package:pilipala/common/widgets/custom_toast.dart';
|
||||||
import 'package:pilipala/http/init.dart';
|
import 'package:pilipala/http/init.dart';
|
||||||
import 'package:pilipala/pages/search/index.dart';
|
import 'package:pilipala/pages/search/index.dart';
|
||||||
import 'package:pilipala/pages/video/detail/index.dart';
|
import 'package:pilipala/pages/video/detail/index.dart';
|
||||||
@ -61,7 +62,9 @@ class MyApp extends StatelessWidget {
|
|||||||
fallbackLocale: const Locale("zh", "CN"),
|
fallbackLocale: const Locale("zh", "CN"),
|
||||||
getPages: Routes.getPages,
|
getPages: Routes.getPages,
|
||||||
home: const MainApp(),
|
home: const MainApp(),
|
||||||
builder: FlutterSmartDialog.init(),
|
builder: FlutterSmartDialog.init(
|
||||||
|
toastBuilder: (String msg) => CustomToast(msg: msg),
|
||||||
|
),
|
||||||
navigatorObservers: [
|
navigatorObservers: [
|
||||||
VideoDetailPage.routeObserver,
|
VideoDetailPage.routeObserver,
|
||||||
SearchPage.routeObserver
|
SearchPage.routeObserver
|
||||||
|
|||||||
@ -107,6 +107,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
sheetHeight = localCache.get('sheetHeight');
|
sheetHeight = localCache.get('sheetHeight');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 收藏
|
||||||
showFavBottomSheet() {
|
showFavBottomSheet() {
|
||||||
if (videoIntroController.user.get(UserBoxKey.userMid) == null) {
|
if (videoIntroController.user.get(UserBoxKey.userMid) == null) {
|
||||||
SmartDialog.showToast('账号未登录');
|
SmartDialog.showToast('账号未登录');
|
||||||
@ -122,8 +123,20 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 视频介绍
|
||||||
|
showIntroDetail() {
|
||||||
|
showBottomSheet(
|
||||||
|
context: context,
|
||||||
|
enableDrag: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return IntroDetail(videoDetail: widget.videoDetail!);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
ThemeData t = Theme.of(context);
|
||||||
return SliverPadding(
|
return SliverPadding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: StyleString.safeSpace, right: StyleString.safeSpace, top: 13),
|
left: StyleString.safeSpace, right: StyleString.safeSpace, top: 13),
|
||||||
@ -133,15 +146,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () => showIntroDetail(),
|
||||||
showBottomSheet(
|
|
||||||
context: context,
|
|
||||||
enableDrag: true,
|
|
||||||
builder: (BuildContext context) {
|
|
||||||
return IntroDetail(videoDetail: widget.videoDetail!);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@ -168,9 +173,7 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
MaterialStateProperty.all(EdgeInsets.zero),
|
MaterialStateProperty.all(EdgeInsets.zero),
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
MaterialStateProperty.resolveWith((states) {
|
MaterialStateProperty.resolveWith((states) {
|
||||||
return Theme.of(context)
|
return t.highlightColor.withOpacity(0.2);
|
||||||
.highlightColor
|
|
||||||
.withOpacity(0.2);
|
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@ -189,46 +192,49 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 6),
|
GestureDetector(
|
||||||
Row(
|
onTap: () => showIntroDetail(),
|
||||||
children: [
|
child: Row(
|
||||||
const SizedBox(width: 2),
|
children: [
|
||||||
StatView(
|
StatView(
|
||||||
theme: 'black',
|
theme: 'gray',
|
||||||
view: !widget.loadingStatus
|
view: !widget.loadingStatus
|
||||||
? widget.videoDetail!.stat!.view
|
? widget.videoDetail!.stat!.view
|
||||||
: videoItem['stat'].view,
|
: videoItem['stat'].view,
|
||||||
size: 'medium',
|
size: 'medium',
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
StatDanMu(
|
StatDanMu(
|
||||||
theme: 'black',
|
theme: 'gray',
|
||||||
danmu: !widget.loadingStatus
|
danmu: !widget.loadingStatus
|
||||||
? widget.videoDetail!.stat!.danmaku
|
? widget.videoDetail!.stat!.danmaku
|
||||||
: videoItem['stat'].danmaku,
|
: videoItem['stat'].danmaku,
|
||||||
size: 'medium',
|
size: 'medium',
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Text(
|
Text(
|
||||||
Utils.dateFormat(
|
Utils.dateFormat(
|
||||||
!widget.loadingStatus
|
!widget.loadingStatus
|
||||||
? widget.videoDetail!.pubdate
|
? widget.videoDetail!.pubdate
|
||||||
: videoItem['pubdate'],
|
: videoItem['pubdate'],
|
||||||
formatType: 'detail'),
|
formatType: 'detail'),
|
||||||
style: const TextStyle(fontSize: 12),
|
style: TextStyle(
|
||||||
),
|
fontSize: 12,
|
||||||
],
|
color: t.colorScheme.outline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
// 点赞收藏转发
|
// 点赞收藏转发
|
||||||
Padding(
|
SingleChildScrollView(
|
||||||
padding: const EdgeInsets.only(top: 15),
|
padding: const EdgeInsets.only(top: 7, bottom: 7),
|
||||||
child: SingleChildScrollView(
|
scrollDirection: Axis.horizontal,
|
||||||
scrollDirection: Axis.horizontal,
|
child: actionRow(
|
||||||
child: actionRow(
|
context,
|
||||||
context,
|
videoIntroController,
|
||||||
videoIntroController,
|
videoDetailCtr,
|
||||||
videoDetailCtr,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
// 合集
|
// 合集
|
||||||
@ -237,122 +243,105 @@ class _VideoInfoState extends State<VideoInfo> with TickerProviderStateMixin {
|
|||||||
seasonPanel(widget.videoDetail!.ugcSeason!,
|
seasonPanel(widget.videoDetail!.ugcSeason!,
|
||||||
widget.videoDetail!.pages!.first.cid, sheetHeight)
|
widget.videoDetail!.pages!.first.cid, sheetHeight)
|
||||||
],
|
],
|
||||||
// Divider(
|
|
||||||
// height: 26,
|
|
||||||
// color: Theme.of(context).dividerColor.withOpacity(0.1),
|
|
||||||
// ),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
int mid = !widget.loadingStatus
|
int mid = !widget.loadingStatus
|
||||||
? widget.videoDetail!.owner!.mid
|
? widget.videoDetail!.owner!.mid
|
||||||
: videoItem['owner'].mid;
|
: videoItem['owner'].mid;
|
||||||
String face = !widget.loadingStatus
|
String face = !widget.loadingStatus
|
||||||
? widget.videoDetail!.owner!.face
|
? widget.videoDetail!.owner!.face
|
||||||
: videoItem['owner'].face;
|
: videoItem['owner'].face;
|
||||||
Get.toNamed('/member?mid=$mid', arguments: {
|
Get.toNamed('/member?mid=$mid', arguments: {
|
||||||
'face': face,
|
'face': face,
|
||||||
'heroTag': (mid + 99).toString()
|
'heroTag': (mid + 99).toString()
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.only(
|
||||||
const SizedBox(width: 5),
|
top: 12, bottom: 12, left: 4, right: 4),
|
||||||
NetworkImgLayer(
|
child: Row(
|
||||||
type: 'avatar',
|
children: [
|
||||||
src: !widget.loadingStatus
|
NetworkImgLayer(
|
||||||
? widget.videoDetail!.owner!.face
|
type: 'avatar',
|
||||||
: videoItem['owner'].face,
|
src: !widget.loadingStatus
|
||||||
width: 34,
|
? widget.videoDetail!.owner!.face
|
||||||
height: 34,
|
: videoItem['owner'].face,
|
||||||
fadeInDuration: Duration.zero,
|
width: 34,
|
||||||
fadeOutDuration: Duration.zero,
|
height: 34,
|
||||||
),
|
fadeInDuration: Duration.zero,
|
||||||
const SizedBox(width: 10),
|
fadeOutDuration: Duration.zero,
|
||||||
Text(
|
|
||||||
!widget.loadingStatus
|
|
||||||
? widget.videoDetail!.owner!.name
|
|
||||||
: videoItem['owner'].name,
|
|
||||||
style: const TextStyle(fontSize: 13),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Text(
|
|
||||||
widget.loadingStatus
|
|
||||||
? '- 粉丝'
|
|
||||||
: Utils.numFormat(
|
|
||||||
videoIntroController.userStat['follower']),
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.labelSmall!
|
|
||||||
.fontSize,
|
|
||||||
color: Theme.of(context).colorScheme.outline),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
AnimatedOpacity(
|
|
||||||
opacity: widget.loadingStatus ? 0 : 1,
|
|
||||||
duration: const Duration(milliseconds: 150),
|
|
||||||
child: SizedBox(
|
|
||||||
height: 32,
|
|
||||||
child: Obx(
|
|
||||||
() => videoIntroController.followStatus.isNotEmpty
|
|
||||||
? TextButton(
|
|
||||||
onPressed: () => videoIntroController
|
|
||||||
.actionRelationMod(),
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
left: 8, right: 8),
|
|
||||||
foregroundColor:
|
|
||||||
videoIntroController.followStatus[
|
|
||||||
'attribute'] !=
|
|
||||||
0
|
|
||||||
? Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.outline
|
|
||||||
: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.onPrimary,
|
|
||||||
backgroundColor:
|
|
||||||
videoIntroController.followStatus[
|
|
||||||
'attribute'] !=
|
|
||||||
0
|
|
||||||
? Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.onInverseSurface
|
|
||||||
: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.primary, // 设置按钮背景色
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
videoIntroController.followStatus[
|
|
||||||
'attribute'] !=
|
|
||||||
0
|
|
||||||
? '已关注'
|
|
||||||
: '关注',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.labelMedium!
|
|
||||||
.fontSize),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: ElevatedButton(
|
|
||||||
onPressed: () => videoIntroController
|
|
||||||
.actionRelationMod(),
|
|
||||||
child: const Text('关注'),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 10),
|
||||||
|
Text(
|
||||||
|
!widget.loadingStatus
|
||||||
|
? widget.videoDetail!.owner!.name
|
||||||
|
: videoItem['owner'].name,
|
||||||
|
style: const TextStyle(fontSize: 13),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Text(
|
||||||
|
widget.loadingStatus
|
||||||
|
? '-'
|
||||||
|
: Utils.numFormat(videoIntroController
|
||||||
|
.userStat['follower']),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: t.textTheme.labelSmall!.fontSize,
|
||||||
|
color: t.colorScheme.outline),
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
AnimatedOpacity(
|
||||||
|
opacity: widget.loadingStatus ? 0 : 1,
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 32,
|
||||||
|
child: Obx(
|
||||||
|
() => videoIntroController
|
||||||
|
.followStatus.isNotEmpty
|
||||||
|
? TextButton(
|
||||||
|
onPressed: () => videoIntroController
|
||||||
|
.actionRelationMod(),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
left: 8, right: 8),
|
||||||
|
foregroundColor:
|
||||||
|
videoIntroController
|
||||||
|
.followStatus[
|
||||||
|
'attribute'] !=
|
||||||
|
0
|
||||||
|
? t.colorScheme.outline
|
||||||
|
: t.colorScheme.onPrimary,
|
||||||
|
backgroundColor:
|
||||||
|
videoIntroController
|
||||||
|
.followStatus[
|
||||||
|
'attribute'] !=
|
||||||
|
0
|
||||||
|
? t.colorScheme
|
||||||
|
.onInverseSurface
|
||||||
|
: t.colorScheme
|
||||||
|
.primary, // 设置按钮背景色
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
videoIntroController.followStatus[
|
||||||
|
'attribute'] !=
|
||||||
|
0
|
||||||
|
? '已关注'
|
||||||
|
: '关注',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: t.textTheme
|
||||||
|
.labelMedium!.fontSize),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: ElevatedButton(
|
||||||
|
onPressed: () => videoIntroController
|
||||||
|
.actionRelationMod(),
|
||||||
|
child: const Text('关注'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4)
|
)),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
// Divider(
|
|
||||||
// height: 12,
|
|
||||||
// color: Theme.of(context).dividerColor.withOpacity(0.1),
|
|
||||||
// ),
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: const SizedBox(
|
: const SizedBox(
|
||||||
|
|||||||
@ -22,6 +22,7 @@ class ZanButton extends StatefulWidget {
|
|||||||
class _ZanButtonState extends State<ZanButton> {
|
class _ZanButtonState extends State<ZanButton> {
|
||||||
// 评论点赞
|
// 评论点赞
|
||||||
onLikeReply() async {
|
onLikeReply() async {
|
||||||
|
SmartDialog.showLoading(msg: 'pilipala ...');
|
||||||
ReplyItemModel replyItem = widget.replyItem!;
|
ReplyItemModel replyItem = widget.replyItem!;
|
||||||
int oid = replyItem.oid!;
|
int oid = replyItem.oid!;
|
||||||
int rpid = replyItem.rpid!;
|
int rpid = replyItem.rpid!;
|
||||||
@ -29,8 +30,9 @@ class _ZanButtonState extends State<ZanButton> {
|
|||||||
int action = replyItem.action == 0 ? 1 : 0;
|
int action = replyItem.action == 0 ? 1 : 0;
|
||||||
var res = await ReplyHttp.likeReply(
|
var res = await ReplyHttp.likeReply(
|
||||||
type: widget.replyType!.index, oid: oid, rpid: rpid, action: action);
|
type: widget.replyType!.index, oid: oid, rpid: rpid, action: action);
|
||||||
|
SmartDialog.dismiss();
|
||||||
if (res['status']) {
|
if (res['status']) {
|
||||||
SmartDialog.showToast(replyItem.action == 0 ? '点赞成功' : '取消赞');
|
SmartDialog.showToast(replyItem.action == 0 ? '点赞成功 👍' : '取消赞 💔');
|
||||||
if (action == 1) {
|
if (action == 1) {
|
||||||
replyItem.like = replyItem.like! + 1;
|
replyItem.like = replyItem.like! + 1;
|
||||||
replyItem.action = 1;
|
replyItem.action = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user