fix

report im msg

Signed-off-by: bggRGjQaUbCoE <githubaccount56556@proton.me>
This commit is contained in:
bggRGjQaUbCoE
2026-01-07 11:05:16 +08:00
parent 5a0b045a1f
commit 9855b35b65
14 changed files with 343 additions and 199 deletions

View File

@@ -131,4 +131,14 @@ class WhisperDetailController extends CommonListController<RspSessionMsg, Msg> {
beginSeqno: msgSeqno != null ? Int64.ZERO : null,
endSeqno: msgSeqno,
);
Future<LoadingState> onReport(Msg item, int reasonType, String reasonDesc) {
return MsgHttp.imMsgReport(
accusedUid: item.senderUid,
reasonType: reasonType,
reasonDesc: reasonDesc,
comment: {'group_id': 0, 'msg_key': item.msgKey},
extra: {"msg_keys": []},
);
}
}

View File

@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:io' show File;
import 'package:PiliPlus/common/widgets/dialog/report.dart';
import 'package:PiliPlus/common/widgets/flutter/text_field/text_field.dart';
import 'package:PiliPlus/common/widgets/image/network_img_layer.dart';
import 'package:PiliPlus/common/widgets/loading_widget/loading_widget.dart';
@@ -168,14 +169,18 @@ class _WhisperDetailPageState
_whisperDetailController.onLoadMore();
}
final item = response[index];
final isOwner =
item.senderUid.toInt() ==
_whisperDetailController.account.mid;
return ChatItem(
item: item,
eInfos: _whisperDetailController.eInfos,
onLongPress:
item.senderUid.toInt() ==
_whisperDetailController.account.mid
? () => onLongPress(index, item)
onLongPress: () => onLongPress(index, item, isOwner),
onSecondaryTapUp: PlatformUtils.isDesktop
? (e) =>
_showMenu(e.globalPosition, index, item, isOwner)
: null,
isOwner: isOwner,
);
},
separatorBuilder: (context, index) =>
@@ -189,34 +194,86 @@ class _WhisperDetailPageState
};
}
void onLongPress(int index, Msg item) {
void _showMenu(Offset offset, int index, Msg item, bool isOwner) {
showMenu(
context: context,
position: .fromLTRB(offset.dx, offset.dy, offset.dx, 0),
items: [
if (isOwner)
PopupMenuItem(
height: 42,
onTap: () => _whisperDetailController.sendMsg(
message: '${item.msgKey}',
onClearText: editController.clear,
msgType: 5,
index: index,
),
child: const Text('撤回', style: TextStyle(fontSize: 14)),
)
else
PopupMenuItem(
height: 42,
onTap: () => autoWrapReportDialog(
context,
ban: false,
ReportOptions.imMsgReport,
(reasonType, reasonDesc, banUid) =>
_whisperDetailController.onReport(
item,
reasonType,
reasonType == 0
? reasonDesc!
: ReportOptions.imMsgReport['']![reasonType]!,
),
),
child: const Text('举报', style: TextStyle(fontSize: 14)),
),
],
);
}
void onLongPress(int index, Msg item, bool isOwner) {
Feedback.forLongPress(context);
showDialog(
context: context,
builder: (context) {
return AlertDialog(
clipBehavior: Clip.hardEdge,
contentPadding: const EdgeInsets.symmetric(vertical: 12),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
onTap: () {
Get.back();
_whisperDetailController.sendMsg(
message: '${item.msgKey}',
onClearText: editController.clear,
msgType: 5,
index: index,
);
},
dense: true,
title: const Text(
'撤回',
style: TextStyle(fontSize: 14),
content: isOwner
? ListTile(
onTap: () {
Get.back();
_whisperDetailController.sendMsg(
message: '${item.msgKey}',
onClearText: editController.clear,
msgType: 5,
index: index,
);
},
dense: true,
title: const Text('撤回', style: TextStyle(fontSize: 14)),
)
: ListTile(
onTap: () {
Get.back();
autoWrapReportDialog(
context,
ban: false,
ReportOptions.imMsgReport,
(reasonType, reasonDesc, banUid) =>
_whisperDetailController.onReport(
item,
reasonType,
reasonType == 0
? reasonDesc!
: ReportOptions.imMsgReport['']![reasonType]!,
),
);
},
dense: true,
title: const Text('举报', style: TextStyle(fontSize: 14)),
),
),
],
),
);
},
);

View File

@@ -18,7 +18,6 @@ import 'package:PiliPlus/utils/extension/num_ext.dart';
import 'package:PiliPlus/utils/id_utils.dart';
import 'package:PiliPlus/utils/image_utils.dart';
import 'package:PiliPlus/utils/page_utils.dart';
import 'package:PiliPlus/utils/platform_utils.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
@@ -33,13 +32,16 @@ class ChatItem extends StatelessWidget {
const ChatItem({
super.key,
required this.item,
this.eInfos,
this.onLongPress,
}) : isOwner = onLongPress != null;
required this.eInfos,
required this.onLongPress,
required this.onSecondaryTapUp,
required this.isOwner,
});
final Msg item;
final List<EmotionInfo>? eInfos;
final VoidCallback? onLongPress;
final VoidCallback onLongPress;
final GestureTapUpCallback? onSecondaryTapUp;
final bool isOwner;
// 消息来源
@@ -51,14 +53,11 @@ class ChatItem extends StatelessWidget {
// };
@override
Widget build(BuildContext context) {
bool isPic = item.msgType == MsgType.EN_MSG_TYPE_PIC.value; // 图片
bool isRevoke = item.msgType == MsgType.EN_MSG_TYPE_DRAW_BACK.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_PICTURE_CARD.value ||
item.msgType == 16;
final msgType = item.msgType;
final isRevoke = msgType == MsgType.EN_MSG_TYPE_DRAW_BACK.value; // 撤回消息
if (isRevoke) {
return const SizedBox.shrink();
}
late final ThemeData theme = Theme.of(context);
late final Color textColor = isOwner
@@ -66,108 +65,98 @@ class ChatItem extends StatelessWidget {
: theme.colorScheme.onSurfaceVariant;
late final dynamic content = jsonDecode(item.content);
return isRevoke
? const SizedBox.shrink()
: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 6, bottom: 18),
child: Text(
DateFormatUtils.chatFormat(item.timestamp.toInt()),
textAlign: TextAlign.center,
style: TextStyle(color: theme.colorScheme.outline),
),
),
isSystem
? messageContent(
context: context,
theme: theme,
content: content,
textColor: textColor,
Widget child = messageContent(
context: context,
theme: theme,
content: content,
textColor: textColor,
);
final isSystem =
msgType == MsgType.EN_MSG_TYPE_VIDEO_CARD.value ||
msgType == MsgType.EN_MSG_TYPE_TIP_MESSAGE.value ||
msgType == MsgType.EN_MSG_TYPE_NOTIFY_MSG.value ||
msgType == MsgType.EN_MSG_TYPE_PICTURE_CARD.value ||
msgType == 16;
if (!isSystem) {
final isPic = msgType == MsgType.EN_MSG_TYPE_PIC.value; // 图片
child = Row(
mainAxisAlignment: isOwner ? .end : .start,
children: [
Container(
constraints: const BoxConstraints(maxWidth: 300.0),
decoration: BoxDecoration(
color: isOwner
? theme.colorScheme.secondaryContainer
: theme.colorScheme.onInverseSurface,
borderRadius: isOwner
? const .only(
topLeft: .circular(16),
topRight: .circular(16),
bottomLeft: .circular(16),
bottomRight: .circular(6),
)
: GestureDetector(
onLongPress: () {
Feedback.forLongPress(context);
onLongPress!();
},
onSecondaryTap: PlatformUtils.isMobile
? null
: onLongPress,
child: Row(
mainAxisAlignment: isOwner
? MainAxisAlignment.end
: MainAxisAlignment.start,
children: [
Container(
constraints: const BoxConstraints(maxWidth: 300.0),
decoration: BoxDecoration(
color: isOwner
? theme.colorScheme.secondaryContainer
: theme.colorScheme.onInverseSurface,
borderRadius: isOwner
? const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
bottomLeft: Radius.circular(16),
bottomRight: Radius.circular(6),
)
: const BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
bottomLeft: Radius.circular(6),
bottomRight: Radius.circular(16),
),
),
padding: EdgeInsets.only(
top: 8,
bottom: 6,
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,
),
),
if (item.msgSource >= 8 &&
item.msgSource <= 11) ...[
Divider(
height: 10,
thickness: 1,
color: theme.colorScheme.outline.withValues(
alpha: 0.2,
),
),
Text(
'此条消息为自动回复',
style: theme.textTheme.labelMedium!
.copyWith(
color: theme.colorScheme.outline,
),
),
],
],
),
),
],
),
: const .only(
topLeft: .circular(16),
topRight: .circular(16),
bottomLeft: .circular(6),
bottomRight: .circular(16),
),
],
);
),
padding: isPic
? const .only(top: 8, bottom: 6, left: 8, right: 8)
: const .only(top: 8, bottom: 6, left: 12, right: 12),
child: Column(
crossAxisAlignment: isOwner ? .end : .start,
children: [
child,
isPic ? const SizedBox(height: 7) : const SizedBox(height: 2),
if (item.msgStatus == 1)
Text(
' 已撤回',
style: theme.textTheme.labelSmall!.copyWith(
color: theme.colorScheme.onErrorContainer,
),
),
if (item.msgSource >= 8 && item.msgSource <= 11) ...[
Divider(
height: 10,
thickness: 1,
color: theme.colorScheme.outline.withValues(alpha: 0.2),
),
Text(
'此条消息为自动回复',
style: theme.textTheme.labelMedium!.copyWith(
color: theme.colorScheme.outline,
),
),
],
],
),
),
],
);
}
return Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 6, bottom: 18),
child: Text(
DateFormatUtils.chatFormat(item.timestamp.toInt()),
textAlign: TextAlign.center,
style: TextStyle(color: theme.colorScheme.outline),
),
),
GestureDetector(
behavior: .opaque,
onLongPress: onLongPress,
onSecondaryTapUp: onSecondaryTapUp,
child: child,
),
],
);
}
Widget messageContent({