opt msg item

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2025-05-24 10:48:01 +08:00
parent 5bd6b38908
commit da56c66168
2 changed files with 145 additions and 124 deletions

View File

@@ -147,7 +147,7 @@ class _WhisperDetailPageState
shrinkWrap: true, shrinkWrap: true,
reverse: true, reverse: true,
itemCount: response!.length, itemCount: response!.length,
padding: const EdgeInsets.all(12), padding: const EdgeInsets.all(14),
physics: const AlwaysScrollableScrollPhysics( physics: const AlwaysScrollableScrollPhysics(
parent: ClampingScrollPhysics(), parent: ClampingScrollPhysics(),
), ),

View File

@@ -1,11 +1,13 @@
import 'dart:convert'; import 'dart:convert';
import 'package:PiliPlus/common/constants.dart'; import 'package:PiliPlus/common/constants.dart';
import 'package:PiliPlus/common/widgets/badge.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart'; import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/grpc/bilibili/im/interfaces/v1.pb.dart' import 'package:PiliPlus/grpc/bilibili/im/interfaces/v1.pb.dart'
show EmotionInfo; show EmotionInfo;
import 'package:PiliPlus/grpc/bilibili/im/type.pb.dart' show Msg, MsgType; import 'package:PiliPlus/grpc/bilibili/im/type.pb.dart' show Msg, MsgType;
import 'package:PiliPlus/http/search.dart'; import 'package:PiliPlus/http/search.dart';
import 'package:PiliPlus/models/common/badge_type.dart';
import 'package:PiliPlus/models/common/image_preview_type.dart'; import 'package:PiliPlus/models/common/image_preview_type.dart';
import 'package:PiliPlus/models/common/image_type.dart'; import 'package:PiliPlus/models/common/image_type.dart';
import 'package:PiliPlus/utils/app_scheme.dart'; import 'package:PiliPlus/utils/app_scheme.dart';
@@ -39,7 +41,8 @@ class ChatItem extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool isPic = item.msgType == MsgType.EN_MSG_TYPE_PIC.value; // 图片 bool isPic = item.msgType == MsgType.EN_MSG_TYPE_PIC.value; // 图片
bool isRevoke = item.msgType == MsgType.EN_MSG_TYPE_DRAW_BACK.value; // 撤回消息 bool isRevoke = item.msgType == MsgType.EN_MSG_TYPE_DRAW_BACK.value; // 撤回消息
bool isSystem = item.msgType == MsgType.EN_MSG_TYPE_TIP_MESSAGE.value || bool isSystem = item.msgType == MsgType.EN_MSG_TYPE_VIDEO_CARD.value ||
item.msgType == MsgType.EN_MSG_TYPE_TIP_MESSAGE.value ||
item.msgType == MsgType.EN_MSG_TYPE_NOTIFY_MSG.value || item.msgType == MsgType.EN_MSG_TYPE_NOTIFY_MSG.value ||
item.msgType == MsgType.EN_MSG_TYPE_PICTURE_CARD.value || item.msgType == MsgType.EN_MSG_TYPE_PICTURE_CARD.value ||
item.msgType == 16; item.msgType == 16;
@@ -52,80 +55,81 @@ class ChatItem extends StatelessWidget {
return isRevoke return isRevoke
? const SizedBox.shrink() ? const SizedBox.shrink()
: isSystem : Column(
? messageContent( children: [
context: context, Padding(
theme: theme, padding: const EdgeInsets.only(top: 6, bottom: 18),
content: content, child: Text(
textColor: textColor, Utils.dateFormat(item.timestamp.toInt()),
) textAlign: TextAlign.center,
: GestureDetector( style: TextStyle(color: theme.colorScheme.outline),
onLongPress: () { ),
Feedback.forLongPress(context); ),
onLongPress?.call(); isSystem
}, ? messageContent(
child: Row( context: context,
mainAxisAlignment: theme: theme,
isOwner ? MainAxisAlignment.end : MainAxisAlignment.start, content: content,
children: [ textColor: textColor,
Container( )
constraints: const BoxConstraints(maxWidth: 300.0), : GestureDetector(
decoration: BoxDecoration( onLongPress: onLongPress == null
color: isOwner ? null
? theme.colorScheme.secondaryContainer : () {
: theme.colorScheme.onInverseSurface, Feedback.forLongPress(context);
borderRadius: BorderRadius.only( onLongPress!();
topLeft: const Radius.circular(16), },
topRight: const Radius.circular(16), child: Row(
bottomLeft: Radius.circular(isOwner ? 16 : 6), mainAxisAlignment: isOwner
bottomRight: Radius.circular(isOwner ? 6 : 16), ? MainAxisAlignment.end
), : MainAxisAlignment.start,
),
padding: EdgeInsets.only(
top: 8,
bottom: 6,
left: isPic ? 8 : 12,
right: isPic ? 8 : 12,
),
child: Column(
crossAxisAlignment: isOwner
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [ children: [
messageContent( Container(
context: context, constraints: const BoxConstraints(maxWidth: 300.0),
theme: theme, decoration: BoxDecoration(
content: content, color: isOwner
textColor: textColor, ? theme.colorScheme.secondaryContainer
), : theme.colorScheme.onInverseSurface,
SizedBox(height: isPic ? 7 : 2), borderRadius: BorderRadius.only(
Row( topLeft: const Radius.circular(16),
mainAxisSize: MainAxisSize.min, topRight: const Radius.circular(16),
children: [ bottomLeft: Radius.circular(isOwner ? 16 : 6),
Text( bottomRight: Radius.circular(isOwner ? 6 : 16),
Utils.dateFormat(item.timestamp.toInt()),
style: theme.textTheme.labelSmall!.copyWith(
color: isOwner
? theme.colorScheme.onSecondaryContainer
.withValues(alpha: 0.8)
: theme.colorScheme.onSurfaceVariant
.withValues(alpha: 0.8)),
), ),
if (item.msgStatus == 1) ),
Text( padding: EdgeInsets.only(
' 已撤回', top: 8,
style: theme.textTheme.labelSmall!.copyWith( bottom: 6,
color: theme.colorScheme.onErrorContainer, left: isPic ? 8 : 12,
), right: isPic ? 8 : 12,
),
child: Column(
crossAxisAlignment: isOwner
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
messageContent(
context: context,
theme: theme,
content: content,
textColor: textColor,
), ),
], SizedBox(height: isPic ? 7 : 2),
) if (item.msgStatus == 1)
Text(
' 已撤回',
style: theme.textTheme.labelSmall!.copyWith(
color: theme.colorScheme.onErrorContainer,
),
),
],
),
),
], ],
), ),
), ),
], ],
), );
);
} }
Widget messageContent({ Widget messageContent({
@@ -149,7 +153,7 @@ class ChatItem extends StatelessWidget {
case MsgType.EN_MSG_TYPE_SHARE_V2: case MsgType.EN_MSG_TYPE_SHARE_V2:
return msgTypeShareV2_7(content, textColor); return msgTypeShareV2_7(content, textColor);
case MsgType.EN_MSG_TYPE_VIDEO_CARD: case MsgType.EN_MSG_TYPE_VIDEO_CARD:
return msgTypeVideoCard_11(content, textColor); return msgTypeVideoCard_11(theme, content, textColor);
case MsgType.EN_MSG_TYPE_ARTICLE_CARD: case MsgType.EN_MSG_TYPE_ARTICLE_CARD:
return msgTypeArticleCard_12(content, textColor); return msgTypeArticleCard_12(content, textColor);
case MsgType.EN_MSG_TYPE_COMMON_SHARE_CARD: case MsgType.EN_MSG_TYPE_COMMON_SHARE_CARD:
@@ -357,56 +361,78 @@ class ChatItem extends StatelessWidget {
); );
} }
Widget msgTypeVideoCard_11(content, Color textColor) { Widget msgTypeVideoCard_11(ThemeData theme, content, Color textColor) {
return Column( return Center(
crossAxisAlignment: CrossAxisAlignment.start, child: Container(
children: [ clipBehavior: Clip.hardEdge,
GestureDetector( constraints: const BoxConstraints(maxWidth: 400.0),
onTap: () async { decoration: BoxDecoration(
try { borderRadius: StyleString.mdRadius,
SmartDialog.showLoading(); color: theme.colorScheme.onInverseSurface,
var bvid = content["bvid"]; ),
final int cid = await SearchHttp.ab2c(bvid: bvid); child: LayoutBuilder(
SmartDialog.dismiss(); builder: (_, constrains) {
PageUtils.toVideoPage( return GestureDetector(
'bvid=$bvid&cid=$cid', behavior: HitTestBehavior.opaque,
arguments: { onTap: () async {
'pic': content['thumb'], try {
'heroTag': Utils.makeHeroTag(bvid), SmartDialog.showLoading();
}, var bvid = content["bvid"];
); final int cid = await SearchHttp.ab2c(bvid: bvid);
} catch (err) { SmartDialog.dismiss();
SmartDialog.dismiss(); PageUtils.toVideoPage(
SmartDialog.showToast(err.toString()); 'bvid=$bvid&cid=$cid',
} arguments: {
'pic': content['thumb'],
'heroTag': Utils.makeHeroTag(bvid),
},
);
} catch (err) {
SmartDialog.dismiss();
SmartDialog.showToast(err.toString());
}
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
clipBehavior: Clip.none,
children: [
NetworkImgLayer(
type: ImageType.emote,
width: constrains.maxWidth,
height: constrains.maxWidth * 9 / 16,
src: content['cover'],
),
PBadge(
left: 6,
bottom: 6,
type: PBadgeType.gray,
text: content['times'] == 0
? '--:--'
: Utils.timeFormat(content['times']),
)
],
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
child: Text(
content['times'] == 0 ? '内容已失效' : content['title'],
style: TextStyle(
letterSpacing: 0.6,
height: 1.5,
color: textColor,
fontWeight: FontWeight.bold,
),
),
),
],
),
);
}, },
child: NetworkImgLayer(
width: 220,
height: 220 * 9 / 16,
src: content['cover'],
),
), ),
const SizedBox(height: 6), ),
SelectableText(
content['title'],
style: TextStyle(
letterSpacing: 0.6,
height: 1.5,
color: textColor,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 1),
Text(
Utils.timeFormat(content['times']),
style: TextStyle(
letterSpacing: 0.6,
height: 1.5,
color: textColor.withValues(alpha: 0.6),
fontSize: 12,
),
),
],
); );
} }
@@ -620,11 +646,6 @@ class ChatItem extends StatelessWidget {
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
Text(
Utils.dateFormat(item.timestamp.toInt()),
style: theme.textTheme.labelSmall!
.copyWith(color: theme.colorScheme.outline),
),
Divider(color: theme.colorScheme.primary.withValues(alpha: 0.05)), Divider(color: theme.colorScheme.primary.withValues(alpha: 0.05)),
SelectableText(content['text']), SelectableText(content['text']),
if (modules?.isNotEmpty == true) ...[ if (modules?.isNotEmpty == true) ...[