mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-21 00:28:38 +00:00
opt msg item
Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
@@ -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(),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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) ...[
|
||||||
|
|||||||
Reference in New Issue
Block a user