fix:新增审核新进群成员功能

This commit is contained in:
SL 2025-04-11 15:29:31 +08:00
parent a21ddf7382
commit 72661006ed
16 changed files with 346 additions and 152 deletions

View File

@ -28,7 +28,6 @@ import { ConnectStatus } from "wukongimjssdk";
import { WKBaseContext } from "./Components/WKBase";
import StorageService from "./Service/StorageService";
import { ProhibitwordsService } from "./Service/ProhibitwordsService";
import { JSX } from "react";
export enum ThemeMode {
light,
@ -230,7 +229,7 @@ export default class WKApp extends ProviderListener {
new Array<MessageDeleteListener>(); // 消息删除监听
supportFavorites = [MessageContentType.text, MessageContentType.image]; // 注册收藏的消息
supportEdit = [MessageContentType.text]; // 注册编辑的消息
notSupportForward: number[] = []; // 不支持转发的消息
openChannel?: Channel; // 当前打开的会话频道

View File

@ -9,88 +9,98 @@ export default interface ConversationContext {
* @param content
* @param channel ,
*/
sendMessage(content:MessageContent,channel?:Channel):Promise<Message>
sendMessage(content: MessageContent, channel?: Channel): Promise<Message>
/**
*
* @param message
*/
resendMessage(message:Message) :Promise<Message>
/**
*
*/
scrollToBottom(animate?:boolean):void
insertText(text:string):void
editOn() :boolean // 编辑模式是否开启
setEditOn(edit:boolean):void // 是否开启编辑
// 消息是否被选中
checkeMessage(message :Message,checked:boolean) :void
/**
*
* @param messages
*/
deleteMessages(messages: Message[]): void
/**
*
* @param message
*/
resendMessage(message: Message): Promise<Message>
/**
*
* @param message
*/
revokeMessage(message:Message) :Promise<void>
/**
*
* @param uid
*/
onTapAvatar(uid: string,event:React.MouseEvent<Element, MouseEvent>): void
/**
*
* @param uid uid
*/
showUser(uid:string):any
/**
*
* @param message
*/
reply(message: Message): void
/**
*
*/
scrollToBottom(animate?: boolean): void
/**
*
* @param event
*/
showContextMenus(message:Message,event:React.MouseEvent):void
insertText(text: string): void
/**
*
*/
hideContextMenus():void
editOn(): boolean // 编辑模式是否开启
setEditOn(edit: boolean): void // 是否开启编辑
// 消息是否被选中
checkeMessage(message: Message, checked: boolean): void
channel():Channel
/**
*
* @param messages
*/
deleteMessages(messages: Message[]): void
// 消息输入框上下文
messageInputContext():MessageInputContext
/**
*
* @param message
*/
revokeMessage(message: Message): Promise<void>
/**
* drag文件到最近会话里的时候会回调设置的此函数
* @param f
*/
setDragFileCallback(f:(file:File)=>void):void
/**
*
* @param messageID ID
* @param messageSeq
* @param channelID ID
* @param channelType
* @param content
*/
editMessage(messageID: String, messageSeq: number, channelID: String, channelType: number, content: String): Promise<void>
/**
*
* @param uid
*/
onTapAvatar(uid: string, event: React.MouseEvent<Element, MouseEvent>): void
/**
*
* @param message
*/
fowardMessageUI(message:Message):void
/**
*
* @param uid uid
*/
showUser(uid: string): any
/**
*
* @param message
* @param handlerType 1: 回复消息 2: 编辑消息
*/
reply(message: Message, handlerType: number): void
/**
*
* @param messageSeq
* @param tip
*/
locateMessage(messageSeq:number):any
/**
*
* @param event
*/
showContextMenus(message: Message, event: React.MouseEvent): void
/**
*
*/
hideContextMenus(): void
channel(): Channel
// 消息输入框上下文
messageInputContext(): MessageInputContext
/**
* drag文件到最近会话里的时候会回调设置的此函数
* @param f
*/
setDragFileCallback(f: (file: File) => void): void
/**
*
* @param message
*/
fowardMessageUI(message: Message): void
/**
*
* @param messageSeq
* @param tip
*/
locateMessage(messageSeq: number): any
}

View File

@ -1,4 +1,4 @@
import { Channel, ChannelTypeGroup, ChannelTypePerson, ConversationAction, WKSDK, Mention, Message, MessageContent, Reminder, ReminderType, Reply, MessageText } from "wukongimjssdk";
import { Channel, ChannelTypeGroup, ChannelTypePerson, ConversationAction, WKSDK, Mention, Message, MessageContent, Reminder, ReminderType, Reply, MessageText, MessageContentType } from "wukongimjssdk";
import React, { Component, HTMLProps } from "react";
import Provider from "../../Service/Provider";
import ConversationVM from "./vm";
@ -12,7 +12,7 @@ import MessageInput, { MentionModel, MessageInputContext } from "../MessageInput
import ContextMenus, { ContextMenusContext } from "../ContextMenus";
import classNames from "classnames";
import WKAvatar from "../WKAvatar";
import { IconClose } from "@douyinfe/semi-icons";
import { IconClose, IconEdit, IconReply } from "@douyinfe/semi-icons";
import { Toast, Spin } from "@douyinfe/semi-ui";
import { FlameMessageCell } from "../../Messages/Flame";
@ -89,6 +89,9 @@ export class Conversation extends Component<ConversationProps> implements Conver
revokeMessage(message: Message): Promise<void> {
return this.vm.revokeMessage(message)
}
editMessage(messageID: String, messageSeq: number, channelID: String, channelType: number, content: String): Promise<void> {
return this.vm.editMessage(messageID, messageSeq, channelID, channelType, content)
}
onTapAvatar(uid: string, event: React.MouseEvent<Element, MouseEvent>): void {
this.vm.selectUID = uid
@ -130,7 +133,7 @@ export class Conversation extends Component<ConversationProps> implements Conver
}
// 回复消息
reply(message: Message): void {
reply(message: Message, handlerType: number): void {
if (message.fromUID !== WKApp.loginInfo.uid) {
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(new Channel(message.fromUID, ChannelTypePerson))
let name = ""
@ -140,6 +143,11 @@ export class Conversation extends Component<ConversationProps> implements Conver
this._messageInputContext.addMention(message.fromUID, name)
}
if (handlerType === 2) {
let content = message.remoteExtra?.isEdit ? message.remoteExtra?.contentEdit?.conversationDigest : message.content.conversationDigest
this.insertText(content)
}
this.vm.currentHandlerType = handlerType
this.vm.currentReplyMessage = message
}
@ -480,12 +488,12 @@ export class Conversation extends Component<ConversationProps> implements Conver
}
render() {
const { chatBg, channel,initLocateMessageSeq } = this.props
const { chatBg, channel, initLocateMessageSeq } = this.props
const channelInfo = WKSDK.shared().channelManager.getChannelInfo(channel)
return <Provider create={() => {
this.vm = new ConversationVM(channel,initLocateMessageSeq)
this.vm = new ConversationVM(channel, initLocateMessageSeq)
return this.vm
}} render={(vm: ConversationVM) => {
return <>
@ -548,7 +556,7 @@ export class Conversation extends Component<ConversationProps> implements Conver
</div>
<div className="wk-conversation-topview">
{
vm.currentReplyMessage ? <ReplyView message={vm.currentReplyMessage} onClose={() => {
vm.currentReplyMessage ? <ReplyView message={vm.currentReplyMessage} vm={vm} onClose={() => {
vm.currentReplyMessage = undefined
}}></ReplyView> : undefined
}
@ -596,7 +604,7 @@ export class Conversation extends Component<ConversationProps> implements Conver
<MessageInput members={this.vm.subscribers.filter((s) => s.uid !== WKApp.loginInfo.uid)} onContext={(ctx) => {
this._messageInputContext = ctx
}} toolbar={this.chatToolbarUI()} context={this} onSend={(text: string, mention?: MentionModel) => {
}} toolbar={this.chatToolbarUI()} context={this} onSend={async (text: string, mention?: MentionModel) => {
const content = new MessageText(text)
if (mention) {
const mn = new Mention()
@ -605,6 +613,14 @@ export class Conversation extends Component<ConversationProps> implements Conver
content.mention = mn
}
if (vm.currentReplyMessage) {
if (vm.currentHandlerType === 2) {
// 编辑消息
let json = content.encodeJSON()
json['type'] = MessageContentType.text
await vm.editMessage(vm.currentReplyMessage.messageID, vm.currentReplyMessage.messageSeq, vm.currentReplyMessage.channel.channelID, vm.currentReplyMessage.channel.channelType, JSON.stringify(json))
vm.currentReplyMessage = undefined
return
}
const reply = new Reply()
reply.messageID = vm.currentReplyMessage.messageID
reply.messageSeq = vm.currentReplyMessage.messageSeq
@ -796,19 +812,18 @@ class ConversationPositionView extends Component<ConversationPositionViewProps,
interface ReplyViewProps {
message: Message
vm: ConversationVM
onClose?: () => void
}
class ReplyView extends Component<ReplyViewProps> {
render(): React.ReactNode {
const { message, onClose } = this.props
const { message, onClose, vm } = this.props
const fromChannelInfo = WKSDK.shared().channelManager.getChannelInfo(new Channel(message.fromUID, ChannelTypePerson))
return <div className="wk-replyview">
<div className="wk-replyview-close" onClick={() => {
if (onClose) {
onClose()
<div className="wk-replyview-close">
{
vm.currentHandlerType === 1 ? <IconReply className="wk-replyview-close-icon" /> : <IconEdit className="wk-replyview-close-icon" />
}
}}>
<IconClose className="wk-replyview-close-icon" />
</div>
<div className="wk-replyview-content">
<div className="wk-replyview-content-first">
@ -825,10 +840,19 @@ class ReplyView extends Component<ReplyViewProps> {
</div>
<div className="wk-replyview-content-second">
<div className="wk-replyview-content-msg">
{message.content.conversationDigest}
{
message.remoteExtra?.isEdit ? message.remoteExtra?.contentEdit?.conversationDigest : message.content.conversationDigest
}
</div>
</div>
</div>
<div className="wk-replyview-close" onClick={() => {
if (onClose) {
onClose()
}
}}>
<IconClose className="wk-replyview-close-icon" />
</div>
</div>
}
}
@ -859,8 +883,7 @@ class MultiplePanel extends Component<MultiplePanelProps> {
}
}}>
<div className="wk-multiplepanel-content-item-icon">
<svg className="wk-multiplepanel-content-item-icon-svg" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M362.666667 704h554.666666a21.333333 21.333333 0 0 1 21.333334 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333334 21.333333H362.666667a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333zM106.666667 874.666667h810.666666a21.333333 21.333333 0 0 1 21.333334 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333334 21.333333H106.666667a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333z m427.093333-661.034667V57.152c0-3.84 1.6-7.530667 4.416-10.24a15.36 15.36 0 0 1 21.184 0L846.72 326.122667a21.205333 21.205333 0 0 1 0 30.698666L559.36 635.754667a15.253333 15.253333 0 0 1-10.602667 4.245333 14.72 14.72 0 0 1-14.976-14.485333v-155.733334H503.893333c-116.053333 0-203.946667 22.762667-257.301333 89.792-4.416 5.546667-9.216 11.264-16.256 20.096a8.106667 8.106667 0 0 1-5.248 3.264c-3.989333 0.512-7.125333-1.536-8.128-6.144-2.730667-14.421333-3.626667-29.866667-3.626667-40.746666 0-175.210667 143.466667-322.410667 320.426667-322.410667z m85.333333 85.333333h-85.333333c-80.277333 0-151.914667 41.984-194.453333 104.981334 47.722667-13.44 102.421333-19.52 164.586666-19.52h115.2v74.410666l120.96-117.397333-120.96-117.504v75.029333z"></path></svg>
</div>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 14 4 9 9 4"></polyline><path d="M20 20v-7a4 4 0 0 0-4-4H4"></path></svg> </div>
<div className="wk-multiplepanel-content-item-title">
</div>
@ -883,8 +906,7 @@ class MultiplePanel extends Component<MultiplePanelProps> {
}
}}>
<div className="wk-multiplepanel-content-item-icon">
<svg className="wk-multiplepanel-content-item-icon-svg" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M362.666667 704h554.666666a21.333333 21.333333 0 0 1 21.333334 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333334 21.333333H362.666667a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333zM106.666667 874.666667h810.666666a21.333333 21.333333 0 0 1 21.333334 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333334 21.333333H106.666667a21.333333 21.333333 0 0 1-21.333334-21.333333v-42.666667a21.333333 21.333333 0 0 1 21.333334-21.333333z m427.093333-661.034667V57.152c0-3.84 1.6-7.530667 4.416-10.24a15.36 15.36 0 0 1 21.184 0L846.72 326.122667a21.205333 21.205333 0 0 1 0 30.698666L559.36 635.754667a15.253333 15.253333 0 0 1-10.602667 4.245333 14.72 14.72 0 0 1-14.976-14.485333v-155.733334H503.893333c-116.053333 0-203.946667 22.762667-257.301333 89.792-4.416 5.546667-9.216 11.264-16.256 20.096a8.106667 8.106667 0 0 1-5.248 3.264c-3.989333 0.512-7.125333-1.536-8.128-6.144-2.730667-14.421333-3.626667-29.866667-3.626667-40.746666 0-175.210667 143.466667-322.410667 320.426667-322.410667z m85.333333 85.333333h-85.333333c-80.277333 0-151.914667 41.984-194.453333 104.981334 47.722667-13.44 102.421333-19.52 164.586666-19.52h115.2v74.410666l120.96-117.397333-120.96-117.504v75.029333z"></path></svg>
</div>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg> </div>
<div className="wk-multiplepanel-content-item-title">
</div>

View File

@ -54,19 +54,25 @@ export default class ConversationVM extends ProviderListener {
selectUID?: string // 点击头像的用户uid
private _currentReplyMessage?: Message // 当前回复的消息
private _currentHandlerType: number = 0 // 当前处理类型
onFirstMessagesLoaded?: Function // 第一屏消息已加载完成
constructor(channel: Channel, initLocateMessageSeq?: number) {
super()
this.channel = channel
if(initLocateMessageSeq==0) {
if (initLocateMessageSeq == 0) {
this.initLocateMessageSeq = undefined
}else {
} else {
this.initLocateMessageSeq = initLocateMessageSeq
}
}
get currentHandlerType(): number {
return this._currentHandlerType
}
set currentHandlerType(v: number) {
this._currentHandlerType = v
this.notifyListener()
}
get currentReplyMessage() {
return this._currentReplyMessage
}
@ -190,6 +196,11 @@ export default class ConversationVM extends ProviderListener {
}
// 编辑消息
async editMessage(messageID: String, messageSeq: number, channelID: String, channelType: number, content: String): Promise<void> {
return WKApp.conversationProvider.editMessage(messageID, messageSeq, channelID, channelType, content)
}
// 仅仅删除本地消息
async deleteMessagesFromLocal(deletedMessages: Message[]): Promise<void> {
@ -575,15 +586,33 @@ export default class ConversationVM extends ProviderListener {
return
}
for (const messageExtra of messageExtras) {
this.updateReplyMessageContent(messageExtra)
const message = this.findMessageWithMessageID(messageExtra.messageID)
if (message) {
message.message.remoteExtra = messageExtra
message.resetParts()
}
}
this.notifyListener()
}
// 修改被回复的消息体
updateReplyMessageContent(extra: MessageExtra) {
if (!this.messages || this.messages.length <= 0) {
return
}
for (let i = this.messages.length - 1; i >= 0; i--) {
const message = this.messages[i]
if(message.content.reply === undefined){
continue
}
if (message.content.reply.messageID && message.content.reply.messageID === extra.messageID) {
message.content.reply.content = extra.contentEdit
}
}
this.notifyListener()
}
// 通过clientSeq获取消息对象
findMessageWithClientSeq(clientSeq: number): MessageWrap | undefined {
if (!this.messages || this.messages.length <= 0) {

View File

@ -85,6 +85,7 @@ export default class TabAll extends Component<TabAllProps> {
{
this.props.searchResult?.messages.map((item: any) => {
let digest = "[未知消息]"
console.log("item.content--->",item.content)
if(item.content) {
digest = item.content.conversationDigest
}else {

View File

@ -0,0 +1,18 @@
.wk-message-system {
padding: 10px 20px;
width: 85%;
margin: 0 auto;
text-align: center;
margin-top: 15px;
font-size: 12px;
color: rgba(9,30,66,.87);
white-space: pre-line;
}
.wk-message-approve {
margin-left: 10px;
color: #f65835;
}
body[theme-mode=dark] .wk-message-system {
color: #999;
}

View File

@ -0,0 +1,29 @@
import { SystemContent } from "wukongimjssdk"
import React from "react"
import { MessageCell } from "../MessageCell"
import './index.css'
import { MessageWrap } from "../../Service/Model"
import WKApp from "../../App"
export class ApproveGroupMemberCell extends MessageCell {
render() {
const { message } = this.props
const content = message.content as SystemContent
return <div className="wk-message-system">{content.displayText}<a href="#" onClick={() => this.goApproval(message)} className="wk-message-approve"></a></div>
}
async goApproval(message: MessageWrap) {
let inviteNo = message.content["content"]["invite_no"]
const resp = await WKApp.apiClient.get(`groups/${message.channel.channelID}/member/h5confirm`, {
param: { invite_no: inviteNo || '' },
});
if (resp) {
let url = resp["url"]
if (url) {
window.open(url, '_blank');
}
}
}
}

View File

@ -33,6 +33,7 @@ export default class MessageTrail extends Component<MessageTrailProps> {
render() {
const { message,timeStyle,statusStyle } = this.props
return <span className="messageMeta">
{message.remoteExtra?.isEdit?<span className="messageTime"></span>:null}
<span className="messageTime" style={timeStyle}> {moment(message.timestamp * 1000).format('HH:mm')}</span>
{message.send?<span className="messageStatus" style={statusStyle}> {this.getMessageStatusIcon()}</span>:null}
</span>

View File

@ -112,7 +112,7 @@ export class ImageCell extends MessageCell<any, ImageCellState> {
visible={showPreview}
noImgDetails={true}
downloadable={true}
rotatable={true}
rotatable={false}
changeable={false}
showTotal={false}
onMaskClick={() => { this.setState({ showPreview: false }); }}
@ -121,4 +121,4 @@ export class ImageCell extends MessageCell<any, ImageCellState> {
/>
</MessageBase>
}
}
}

View File

@ -14,32 +14,45 @@ export class ChannelSettingManager {
return this._onSetting({ "mute": v ? 1 : 0 }, channel)
}
top(v:boolean,channel:Channel) : Promise<void> {
top(v: boolean, channel: Channel): Promise<void> {
return this._onSetting({ "top": v ? 1 : 0 }, channel)
}
save(v:boolean,channel:Channel) : Promise<void>{
save(v: boolean, channel: Channel): Promise<void> {
return this._onSetting({ "save": v ? 1 : 0 }, channel)
}
invite(v:boolean,channel:Channel) :Promise<void> {
invite(v: boolean, channel: Channel): Promise<void> {
return this._onSetting({ "invite": v ? 1 : 0 }, channel)
}
remark(remark: string, channel: Channel): Promise<void> {
return this._onSetting({ "remark": remark }, channel)
}
// 消息回执
receipt(v:boolean,channel:Channel): Promise<void> {
receipt(v: boolean, channel: Channel): Promise<void> {
return this._onSetting({ "receipt": v ? 1 : 0 }, channel)
}
// 频道禁言
forbidden(v:boolean,channel:Channel):Promise<void> {
forbidden(v: boolean, channel: Channel): Promise<void> {
return this._onSetting({ "forbidden": v ? 1 : 0 }, channel)
}
// 禁止互加好友
forbiddenAddFriend(v:boolean,channel:Channel) :Promise<void> {
return this._onSetting({"forbidden_add_friend":v?1:0},channel)
forbiddenAddFriend(v: boolean, channel: Channel): Promise<void> {
return this._onSetting({ "forbidden_add_friend": v ? 1 : 0 }, channel)
}
// 允许新成员查看历史消息
allowViewHistoryMsg(v: boolean, channel: Channel): Promise<void> {
return this._onSetting({ "allow_view_history_msg": v ? 1 : 0 }, channel)
}
// 允许群成员置顶消息
allowMemberPinnedMessage(v: boolean, channel: Channel): Promise<void> {
return this._onSetting({ "allow_member_pinned_message": v ? 1 : 0 }, channel)
}
_onSetting(setting: any, channel: Channel): Promise<void> {
return WKApp.dataSource.channelDataSource.updateSetting(setting, channel).catch((err) => {

View File

@ -58,8 +58,9 @@ export class MessageContentTypeConst {
static addMembers: number = 1002 // 添加群成员
static removeMembers: number = 1003 // 删除群成员
static channelUpdate: number = 1005 // 频道更新
static newGroupOwner: number = 1008 // 成为新群主
static screenshot:number = 1014 // 截屏消息
static newGroupOwner: number = 1008 // 新的管理员
static approveGroupMember: number = 1009 // 审批群成员
static screenshot:number = 20 // 截屏消息
// 音频通话消息号段 9900 - 9999
static rtcResult:number = 9989 // 音视频通话结果

View File

@ -36,6 +36,16 @@ export interface IConversationProvider {
*/
revokeMessage(message: Message): Promise<void>
/**
*
* @param messageID ID
* @param messageSeq
* @param channelID ID
* @param channelType
* @param content
*/
editMessage(messageID:String,messageSeq:number,channelID:String,channelType:number,content:String):Promise<void>
/**
*
* @param channel

View File

@ -1,5 +1,5 @@
import { Setting } from "wukongimjssdk"
import { Channel, ChannelInfo, ChannelTypePerson, Conversation, WKSDK, Message, MessageContentType, MessageStatus,MessageText } from "wukongimjssdk"
import { Channel, ChannelInfo, ChannelTypePerson, Conversation, WKSDK, Message, MessageContentType, MessageStatus, MessageText } from "wukongimjssdk"
import WKApp from "../App"
import { MessageContentTypeConst, MessageReasonCode, OrderFactor } from "./Const"
import { DefaultEmojiService } from "./EmojiService"
@ -24,7 +24,7 @@ export class ConversationWrap {
public get avatar() {
if(this.channelInfo&& this.channelInfo.logo && this.channelInfo.logo !== "") {
if (this.channelInfo && this.channelInfo.logo && this.channelInfo.logo !== "") {
return `${WKApp.dataSource.commonDataSource.getImageURL(this.channelInfo.logo)}?v=${WKApp.shared.getChannelAvatarTag(this.channel)}`
}
return WKApp.shared.avatarChannel(this.channel)
@ -40,11 +40,11 @@ export class ConversationWrap {
public get unread() {
return this.conversation.unread
}
public get timestamp() {
return this.conversation.timestamp
}
public set timestamp(timestamp:number) {
public set timestamp(timestamp: number) {
this.conversation.timestamp = timestamp
}
@ -53,10 +53,10 @@ export class ConversationWrap {
}
public set lastMessage(lastMessage: Message | undefined) {
this.conversation.lastMessage = lastMessage
}
public get isMentionMe() {
public get isMentionMe() {
return this.conversation.isMentionMe
}
@ -64,7 +64,7 @@ export class ConversationWrap {
return this.conversation.remoteExtra
}
public set isMentionMe(isMentionMe:boolean | undefined) {
public set isMentionMe(isMentionMe: boolean | undefined) {
this.conversation.isMentionMe = isMentionMe
}
@ -81,28 +81,28 @@ export class ConversationWrap {
}
public get extra() {
if(!this.conversation.extra) {
if (!this.conversation.extra) {
this.conversation.extra = {}
}
return this.conversation.extra
}
public get category() {
if(!this.conversation.channelInfo || !this.conversation.channelInfo.orgData) {
public get category() {
if (!this.conversation.channelInfo || !this.conversation.channelInfo.orgData) {
return ""
}
const channelInfo = this.conversation.channelInfo;
if(channelInfo.orgData.category !=='' && channelInfo.orgData.category ==='solved') {
if (channelInfo.orgData.category !== '' && channelInfo.orgData.category === 'solved') {
return channelInfo.orgData.category
}
if(channelInfo.orgData.category ==='' && channelInfo.orgData.agent_uid==='') {
if (channelInfo.orgData.category === '' && channelInfo.orgData.agent_uid === '') {
return "new"
}
if(channelInfo.orgData.agent_uid === WKApp.loginInfo.uid) {
if (channelInfo.orgData.agent_uid === WKApp.loginInfo.uid) {
return "assignMe"
}
if(channelInfo.orgData.agent_uid!=='') {
if (channelInfo.orgData.agent_uid !== '') {
return "allAssigned"
}
return channelInfo.orgData.category
@ -136,7 +136,7 @@ export class Part {
text!: string
data?: any
constructor(type: PartType, text: string,data?:any) {
constructor(type: PartType, text: string, data?: any) {
this.type = type
this.text = text
this.data = data
@ -145,23 +145,23 @@ export class Part {
export class MessageWrap {
public message: Message
public checked!: boolean // 是否选中
public locateRemind?:boolean // 定位到消息后是否需要提醒
public locateRemind?: boolean // 定位到消息后是否需要提醒
constructor(message: Message) {
this.message = message
this.order = message.messageSeq * OrderFactor
}
private _parts!: Array<Part>
private _parts?: Array<Part>
preMessage?: MessageWrap
nextMessage?: MessageWrap
voiceBuff?: any // 声音的二进制文件,用于缓存
private _reasonCode?:number // 消息错误原因代码
order:number = 0 // 消息排序号
private _reasonCode?: number // 消息错误原因代码
order: number = 0 // 消息排序号
/* tslint:disable-line */
public get header() {
return this.message.header
}
public get setting():Setting {
public get setting(): Setting {
return this.message.setting
}
public get clientSeq() {
@ -179,7 +179,7 @@ export class MessageWrap {
public get fromUID() {
return this.message.fromUID
}
public get from(): ChannelInfo | undefined {
return WKSDK.shared().channelManager.getChannelInfo(new Channel(this.fromUID, ChannelTypePerson))
@ -201,12 +201,12 @@ export class MessageWrap {
this.message.status = status
}
public get reasonCode() {
if(this.status == MessageStatus.Normal) {
if (this.status == MessageStatus.Normal) {
return MessageReasonCode.reasonSuccess
}
return this._reasonCode||MessageReasonCode.reasonUnknown
return this._reasonCode || MessageReasonCode.reasonUnknown
}
public set reasonCode(v:number) {
public set reasonCode(v: number) {
this._reasonCode = v
}
public get voicePlaying() {
@ -224,7 +224,7 @@ export class MessageWrap {
public get readedCount() {
return this.message.remoteExtra.readedCount
}
public set readedCount(v:number) {
public set readedCount(v: number) {
this.message.remoteExtra.readedCount = v
}
public get isDeleted() {
@ -258,6 +258,11 @@ export class MessageWrap {
return this.message.contentType
}
public resetParts() {
this._parts = undefined
this._parts = this.parts
}
public get parts(): Array<Part> {
if (!this._parts) {
this._parts = this.parseMention()
@ -309,7 +314,10 @@ export class MessageWrap {
if (this.content.contentType !== MessageContentType.text) {
return new Array<Part>()
}
const textContent = this.content as MessageText
let textContent = this.content as MessageText
if (this.message.remoteExtra.isEdit && this.message.remoteExtra.contentEdit !== undefined) {
textContent = this.message.remoteExtra.contentEdit as MessageText
}
let text = textContent.text || ''
const mention = this.content.mention
if (!mention?.uids || mention.uids.length <= 0) {
@ -331,11 +339,11 @@ export class MessageWrap {
parts.push(new Part(PartType.text, text.substring(0, index)));
}
let data = {}
if(i<mention.uids.length) {
data = {"uid": mention.uids[i]}
if (i < mention.uids.length) {
data = { "uid": mention.uids[i] }
}
parts.push(new Part(PartType.mention, text.substr(index, mentionMatchResult[0].length),data))
parts.push(new Part(PartType.mention, text.substr(index, mentionMatchResult[0].length), data))
text = text.substring(index + mentionMatchResult[0].length);
i++
@ -357,7 +365,7 @@ export class MessageWrap {
const matchResult = text.match(DefaultEmojiService.shared.emojiRegExp())
if (!matchResult) {
newParts.push(new Part(PartType.text, text))
break
break
}
let index = matchResult?.index
if (index === undefined) {
@ -395,7 +403,7 @@ export class MessageWrap {
const matchResult = text.match(/((http|ftp|https):\/\/|www.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?/)
if (!matchResult) {
newParts.push(new Part(PartType.text, text))
break
break
}
let index = matchResult?.index
if (index === undefined) {
@ -411,18 +419,18 @@ export class MessageWrap {
newParts.push(new Part(PartType.link, text.substr(index, matchResult[0].length)));
text = text.substring(index + matchResult[0].length);
}
}else {
} else {
newParts.push(part)
}
}
return newParts
}
public get flame() :boolean {
if(this.message.content.contentObj) {
return this.message.content.contentObj.flame === 1
public get flame(): boolean {
if (this.message.content.contentObj) {
return this.message.content.contentObj.flame === 1
}
return false
return false
}
public get remoteExtra() {

View File

@ -1,4 +1,4 @@
import React, { JSX } from "react";
import React from "react";
import WKApp from "../App";
import { EndpointCategory, EndpointID } from "./Const";
import { EndpointManager } from "./Module";

View File

@ -82,6 +82,7 @@ import { ProhibitwordsService } from "./Service/ProhibitwordsService";
import { SubscriberList } from "./Components/Subscribers/list";
import GlobalSearch from "./Components/GlobalSearch";
import { handleGlobalSearchClick } from "./Pages/Chat/vm";
import { ApproveGroupMemberCell } from "./Messages/ApproveGroupMember";
export default class BaseModule implements IModule {
messageTone?: Howl;
@ -136,6 +137,8 @@ export default class BaseModule implements IModule {
case MessageContentTypeConst.screenshot:
return ScreenshotCell;
case MessageContentType.signalMessage: // 端对端加密错误消息
case MessageContentTypeConst.approveGroupMember: // 审批群成员
return ApproveGroupMemberCell;
case 98:
return SignalMessageCell;
default:
@ -610,7 +613,7 @@ export default class BaseModule implements IModule {
return {
title: "回复",
onClick: () => {
context.reply(message);
context.reply(message, 1);
},
};
}
@ -1205,7 +1208,29 @@ export default class BaseModule implements IModule {
},
})
);
rows.push(
new Row({
cell: ListItem,
properties: {
title: "备注",
subTitle: channelInfo?.orgData?.remark,
onClick: () => {
this.inputEditPush(
context,
channelInfo?.orgData?.remark || "",
(value: string) => {
return ChannelSettingManager.shared.remark(value, channel).then(() => {
data.refresh()
})
},
"群聊的备注仅自己可见",
15,
true
);
},
},
})
);
return new Section({
rows: rows,
});
@ -1228,7 +1253,7 @@ export default class BaseModule implements IModule {
onClick: () => {
WKApp.shared.baseContext.showGlobalModal({
body: <GlobalSearch channel={channel} onClick={(item: any, type: string) => {
handleGlobalSearchClick(item, type,()=>{
handleGlobalSearchClick(item, type, () => {
WKApp.shared.baseContext.hideGlobalModal()
})
}} />,

View File

@ -0,0 +1,28 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"js-tokens@^3.0.0 || ^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
loose-envify@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
react@*:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
dependencies:
loose-envify "^1.1.0"
object-assign "^4.1.1"