harmony/chatkit_ui/src/main/ets/pages/ChatTeamPage.ets
2025-08-15 17:16:19 +08:00

1435 lines
56 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2022 NetEase, Inc. All rights reserved.
* Use of this source code is governed by a MIT license that can be
* found in the LICENSE file.
*
*/
import { ChatTeamInfo } from '../model/ChatTeamInfo';
import { NIMMessageInfo } from '../model/NIMMessageInfo';
import { MessageComponent } from '../view/MessageComponent';
import { ChatTeamViewModel } from '../viewmodel/ChatTeamViewModel';
import { AitEditorSpan, InputStyleType, NEChatInputView } from '../view/ChatInputView';
import { NEChatEmojiView } from '../view/NEChatEmojiView';
import { NEEmojiManager, NEEmojiParseResult, NIMEmoticonType } from '../manager/NEEmojiManager';
import { NEChatMoreOperation } from '../view/ChatMoreOperationLayout';
import { NEChatMoreOperationData, NEChatMoreOperationType } from '../model/NEChatMoreOperationData';
import { NEAudioRecordView } from '../view/NEAudioRecordView';
import {
DoubleAlertDialog,
ImagesIndexModel,
ImageViewDialog,
MediaUtils,
NavigationBackBuilder,
NECommonUtils,
NetworkBrokenBuilder,
PermissionsUtils,
VideoViewerDialog
} from '@nimkit/common';
import { NECameraSelectView } from '../view/NECameraSelectView';
import { common } from '@kit.AbilityKit';
import { cameraPicker } from '@kit.CameraKit';
import { LengthMetrics, window } from '@kit.ArkUI';
import { NERectData } from '../model/NERectData';
import { MessageOperationView } from '../view/MessageOperationView';
import { MessageOperationItem, MessageOperationType } from '../model/MessageOperationItem';
import { BusinessError, pasteboard } from '@kit.BasicServicesKit';
import { DeviceUtils } from '../common/DeviceUtils';
import {
V2NIMMessage,
V2NIMMessageAudioAttachment,
V2NIMMessageLocationAttachment,
V2NIMMessageSendingState,
V2NIMMessageType
} from '@nimsdk/base';
import { ChatConst } from '../constants/ChatConst';
import {
ChatKitClient,
ConversationRepo,
conversationSelectLimitCount,
ConversationSelectParam,
CustomMessageUtils,
ErrorUtils,
MergedMessageAttachment,
mergedMessageCustomType,
mergedMessageLimitCount,
mergedMessageMaxDepth,
singleMessageLimitCount,
TeamMemberCache,
TeamSettingParam
} from '@nimkit/chatkit';
import { TeamExitDialogParam, TeamExitWarningDialog } from '../view/TeamExitWarningDialog';
import { AudioPlayerManager } from '../manager/AudioPlayerManager';
import { ConversationSelectModel } from '@nimkit/chatkit/src/main/ets/model/ConversationSelectModel';
import { ForwardMessageDialog } from '../view/ForwardMessageDialog';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import {
downLoadAndOpenFile,
getAitNodes,
getMessageImageUrl,
getMessageImageUrls,
getMessageVideoRatio,
getMessageVideoUrl,
parseMessageText
} from '../common/MessageHelper';
import { computeOperateViewHeight, computeOperateViewWidth, setupMoreOperationData } from '../common/ChatUtils';
import { sceneMap } from '@kit.MapKit';
import { ChatMultiSelectView } from '../view/ChatMultiSelectView';
import { AitManager } from '../manager/ait/AitManager';
import { ChatAitNode } from '../model/ChatAitNode';
import { TextMessageDetailDialog } from '../view/TextMessageDetailDialog';
@ComponentV2
export struct ChatTeamPage {
pathStack: NavPathStack = new NavPathStack()
@Local chatTeamInfo: ChatTeamInfo = new ChatTeamInfo('');
chatViewModel: ChatTeamViewModel = new ChatTeamViewModel();
// 底部扩展区域高度默认为0
@Local expandHeight: number = 0;
@Local inputStyle: InputStyleType = InputStyleType.None;
operationMoreDataList: Array<NEChatMoreOperationData> = Array();
@Local showMultiSelect: boolean = false;
@Local multiSelectCount: number = 0;
@Local hideInput: boolean = false;
@Local scrollHeight: number = 0;
@Local showOperationView: boolean = false;
conversationId: string = '';
// 长按操作弹窗的边距值
operationViewMargin: number = 12;
defaultInputViewHeight: number = 0;
// 长按操作选中的消息
@Local operationMsg: NIMMessageInfo | undefined = undefined;
@Local replyMsg: NIMMessageInfo | undefined = undefined;
textMessageDetailDialog: CustomDialogController | undefined = undefined;
operationRect: NERectData = new NERectData();
screenHeight: number = 0;
screenWidth: number = 0;
keyboardHeight: number = 0
//导航栏高度,用于计算弹窗位置
navBarHeight: number = 80;
// 底部输入框以及固定按钮操作栏高度
@Local bottomHeight: number = 105;
bottomMargin: number = 100;
bottomWithReplyHeight: number = 135;
controller: RichEditorController = new RichEditorController()
//@所在的span
builderSpans: AitEditorSpan[] = [];
// 接受消息标记
msgSize: number = 0;
// 列表滚动位置
listScrollStartPosition: number = 0;
listScrollEndPosition: number = 0;
//首次加载数据滚动到底部
firstLoadData: boolean = true;
listScroller: Scroller = new Scroller();
toScroll: boolean = false
selectVideoView: CustomDialogController = new CustomDialogController({
builder: NECameraSelectView({
onTakePhotoFromCamera: () => {
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
MediaUtils.showCameraPicker(context, cameraPicker.PickerMediaType.PHOTO).then((result) => {
if (result.uri) {
if (result.type === photoAccessHelper.PhotoType.IMAGE) {
this.chatViewModel.sendImageMessage(result.uri)
} else if (result.type === photoAccessHelper.PhotoType.VIDEO) {
this.chatViewModel.sendVideoMessage(result.uri, result.duration, result.width, result.height)
}
}
});
},
onTakeVideoFromCamera: () => {
const context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
MediaUtils.showCameraPicker(context, cameraPicker.PickerMediaType.VIDEO).then(async (result) => {
if (result.uri) {
if (result.type === photoAccessHelper.PhotoType.IMAGE) {
this.chatViewModel.sendImageMessage(result.uri)
} else if (result.type === photoAccessHelper.PhotoType.VIDEO) {
this.chatViewModel.sendVideoMessage(result.uri, result.duration, result.width, result.height)
}
}
});
}
}),
cornerRadius: 0,
alignment: DialogAlignment.Bottom,
backgroundColor: Color.Transparent,
backgroundBlurStyle: BlurStyle.NONE,
height: 140,
})
@Local imagesIndexModel?: ImagesIndexModel
@Local currentImageIndex: number = 0
imageViewerDialog: CustomDialogController = new CustomDialogController({
builder: ImageViewDialog({
imagesIndexModel: this.imagesIndexModel
}),
cornerRadius: 0,
alignment: DialogAlignment.Center,
backgroundColor: Color.Black,
backgroundBlurStyle: BlurStyle.NONE,
height: '100%',
width: '100%',
customStyle: true,
})
@Local videoFileUrl?: string
@Local videoRatio?: number
videoViewerDialog: CustomDialogController = new CustomDialogController({
builder: VideoViewerDialog({
videoUrl: this.videoFileUrl,
videoRatio: this.videoRatio
}),
cornerRadius: 0,
alignment: DialogAlignment.Center,
backgroundColor: Color.Black,
backgroundBlurStyle: BlurStyle.NONE,
height: '100%',
width: '100%',
customStyle: true
})
forwardMessages: V2NIMMessage[] = []
forwardConversations: ConversationSelectModel[] = []
currentConversationName?: string
forwardType?: ResourceStr = $r('app.string.chat_operation_forward')
forwardMessageDialog = new CustomDialogController({
builder: ForwardMessageDialog({
conversationList: this.forwardConversations,
currentConversationName: this.currentConversationName,
forwardType: this.forwardType,
sendForwardMsg: (text: string | undefined) => {
if (ErrorUtils.checkNetworkAndToast()) {
this.chatViewModel.forwardMessage(this.forwardMessages, this.forwardConversations, text)
this.showMultiSelect = false
}
}
}),
cornerRadius: 14,
backgroundColor: Color.White,
height: 250,
width: 276,
})
invalidForwardDialogSureAction?: () => void
invalidForwardFailureDialog?: CustomDialogController = new CustomDialogController({
builder: DoubleAlertDialog({
title: $r('app.string.exception_description'),
message: $r("app.string.multiForward_exist_invalid_fail"),
sureAction: this.invalidForwardDialogSureAction
}),
cornerRadius: 14,
backgroundColor: Color.White,
height: 140,
width: 270,
})
invalidForwardDepthDialog?: CustomDialogController = new CustomDialogController({
builder: DoubleAlertDialog({
title: $r('app.string.exception_description'),
message: $r('app.string.multiForward_exist_invalid_depth'),
sureAction: this.invalidForwardDialogSureAction
}),
cornerRadius: 14,
backgroundColor: Color.White,
height: 140,
width: 270,
})
aitManager: AitManager = new AitManager()
forwardMessageAction = (selectedList: ConversationSelectModel[]) => {
if (this.operationMsg?.message) {
this.forwardMessages = [this.operationMsg.message]
this.forwardConversations = selectedList
this.currentConversationName = this.chatTeamInfo.team?.name
this.forwardMessageDialog.open()
}
}
@Monitor("chatTeamInfo.isReceiveMsg")
onReceiveMsg() {
if (this.firstLoadData || this.chatTeamInfo.isReceiveMsg) {
this.listScroller.scrollEdge(Edge.Bottom)
this.chatTeamInfo.setReceiveMsg(false)
this.firstLoadData = false;
}
}
@Monitor("chatViewModel.needScrollToBottom")
onNeedScrollToBottom() {
if (this.chatViewModel.needScrollToBottom &&
this.listScrollEndPosition >= this.chatTeamInfo.msgList.totalCount() - 2) {
this.listScroller.scrollEdge(Edge.Bottom)
this.chatViewModel.needScrollToBottom = false;
}
}
@Monitor("chatTeamInfo.team")
onGetTeamInfo() {
let team = this.chatTeamInfo.team
if (team && !team.isValidTeam) {
TeamExitWarningDialog.show(this.getUIContext(), new TeamExitDialogParam(
() => {
ConversationRepo.deleteConversation(this.conversationId, true)
TeamExitWarningDialog.close(this.getUIContext())
this.pathStack.clear()
}
))
}
}
@Monitor("chatTeamInfo.scrollIndex")
onScrollIndex() {
if (this.chatTeamInfo.scrollIndex > -1) {
let height = DeviceUtils.windowPXHeight / 2
this.toScroll = true
this.listScroller.scrollToIndex(this.chatTeamInfo.scrollIndex, false, undefined, {
'extraOffset': new LengthMetrics(-height, 0)
})
this.chatViewModel.setAnchorMessage(undefined)
this.chatTeamInfo.setScrollIndex(-1)
}
}
@Monitor("chatViewModel.anchorMsg")
onAnchorMsg() {
if (this.chatViewModel.anchorMsg) {
if (this.chatTeamInfo.msgMap.has(this.chatViewModel.anchorMsg.getMessageClientId())) {
let position = this.chatTeamInfo.searchPosition(this.chatViewModel.anchorMsg.getMessageClientId())
this.toScroll = true
this.listScroller.scrollToIndex(position)
this.chatViewModel.setAnchorMessage(undefined)
} else {
this.chatViewModel.loadAnchorMsg(this.chatViewModel.anchorMsg)
}
}
}
@Monitor("chatViewModel.isMuteModel")
onMuteModel() {
if (this.chatViewModel.isMuteModel) {
this.clearInput(true)
}
}
@Monitor("chatViewModel.selectMsgCount")
onSelectMsg() {
this.multiSelectCount = this.chatViewModel.getSelectMessageSize()
}
@Monitor("expandHeight")
onExpandInputView() {
if (this.expandHeight > 10) {
// 如果是定位消息状态,收到键盘展开重新切换最新消息
if (this.chatViewModel.hasNew) {
this.chatViewModel.reloadMessageList()
} else {
this.listScroller.scrollEdge(Edge.Bottom)
}
}
}
aboutToAppear(): void {
NEEmojiManager.instance.setup()
DeviceUtils.rootDirPath = getContext(this).filesDir
this.operationMoreDataList = setupMoreOperationData()
window.getLastWindow(getContext(this)).then(currentWindow => {
let property = currentWindow.getWindowProperties();
// 初始化窗口高度
let avoidArea = currentWindow.getWindowAvoidArea(window.AvoidAreaType.TYPE_KEYBOARD);
this.screenHeight = px2vp(property.windowRect.height);
this.screenWidth = px2vp(property.windowRect.width);
DeviceUtils.windowPXWidth = property.windowRect.width;
DeviceUtils.windowPXHeight = property.windowRect.height;
this.scrollHeight =
px2vp(property.windowRect.height - avoidArea.bottomRect.height) - this.bottomHeight;
this.defaultInputViewHeight = this.scrollHeight;
// 监听软键盘的隐藏和显示
currentWindow.on('avoidAreaChange', data => {
if (data.type == window.AvoidAreaType.TYPE_KEYBOARD) {
this.showOperationView = false
this.keyboardHeight = px2vp(data.area.bottomRect.height);
// 如果是定位消息状态,收到键盘展开重新切换最新消息
if (this.keyboardHeight > 10 && this.chatViewModel.hasNew) {
this.chatViewModel.reloadMessageList()
}
this.computeScrollHeight()
return;
}
})
})
}
computeScrollHeight() {
if ((this.inputStyle === InputStyleType.Emoji || this.inputStyle === InputStyleType.Record ||
this.inputStyle === InputStyleType.More) && this.keyboardHeight <= 0) {
this.scrollHeight = this.screenHeight - this.keyboardHeight - this.bottomHeight - this.expandHeight
} else {
this.scrollHeight = this.screenHeight - this.keyboardHeight - this.bottomHeight
if (this.keyboardHeight > 10) {
this.expandHeight = 0
this.inputStyle = InputStyleType.None;
this.listScroller.scrollEdge(Edge.Bottom)
}
}
}
/**
* 是否是@的span
* @param span
* @returns
*/
isAitEditorSpan(span: RichEditorImageSpanResult | RichEditorTextSpanResult): boolean {
return !(span as RichEditorTextSpanResult).value &&
!(span as RichEditorImageSpanResult).valueResourceStr?.toString().replaceAll(' ', '');
}
/**
* 获取输入数据
* @returns
*/
getMessageText(): string {
let text = '';
let builderSpanIndex = 0;
if (this.controller) {
this.controller.getSpans().forEach((span) => {
const textSpan = span as RichEditorTextSpanResult;
const imageSpan = span as RichEditorImageSpanResult;
if (textSpan.value) {
text += textSpan.value;
} else if (this.isAitEditorSpan(span) && builderSpanIndex < this.builderSpans.length) {
let aitSpan: AitEditorSpan = this.builderSpans[builderSpanIndex]
let contentText = aitSpan.value
this.aitManager.addAitWithText(aitSpan.accountId, contentText, text.length)
text += contentText
builderSpanIndex += 1;
} else {
let resourcePath = imageSpan.valueResourceStr;
if (resourcePath != null && resourcePath.toString().length > 0) {
let path = resourcePath.toString();
let splits = path.split("/")
let fileName = splits[splits.length - 1];
let emoji = NEEmojiManager.instance.getEmojiByName(String(fileName));
if (emoji?.tag != null) {
text += emoji.tag;
}
}
}
});
}
return text
}
getInputContentLength(): number {
let length = 0
this.controller.getSpans().forEach((item) => {
if (typeof (item as RichEditorImageSpanResult)['imageStyle'] != 'undefined') {
let span = item as RichEditorImageSpanResult;
if (span.spanPosition.spanRange) {
let end = span.spanPosition.spanRange[1];
if (end > length) {
length = end;
}
}
} else {
let span = item as RichEditorTextSpanResult
if (span.spanPosition.spanRange) {
let end = span.spanPosition.spanRange[1];
if (end > length) {
length = end;
}
}
}
})
return length
}
async requestChatData() {
this.chatTeamInfo.setConversationId(this.conversationId)
this.chatViewModel.init(this.conversationId as string, this.chatTeamInfo);
this.chatViewModel.loadData()
this.chatViewModel.setTeamExitListener(() => {
TeamExitWarningDialog.show(this.getUIContext(), new TeamExitDialogParam(
() => {
this.pathStack.clear()
TeamExitWarningDialog.close(this.getUIContext())
}
))
})
}
async showImageDetail(msg?: NIMMessageInfo, onlyMsg?: boolean) {
try {
const imageModel =
onlyMsg ? await getMessageImageUrl(msg, this.chatTeamInfo) : await getMessageImageUrls(msg, this.chatTeamInfo)
this.imagesIndexModel = imageModel
this.imageViewerDialog.open()
} catch (err) {
console.error(err)
}
}
showVideoDetail(msg: NIMMessageInfo) {
AudioPlayerManager.instance.stopPlayAll()
this.videoFileUrl = getMessageVideoUrl(msg, this.chatTeamInfo)
if (this.videoFileUrl == undefined) {
NECommonUtils.showToast($r('app.string.chat_msg_download_tips'))
return
}
this.videoRatio = getMessageVideoRatio(msg)
if (this.videoFileUrl) {
this.videoViewerDialog.open()
}
}
@Builder
AtSpan(nickname: string) {
Text(nickname)
.fontColor('#FF337EFF');
}
/**
* 通过ID来添加@成员
* @param senderId
*/
async addAitUserById(senderId: string) {
//输入框添加@信息
let sendMember = await TeamMemberCache.getInstance().getMemberById(senderId)
if (sendMember && this.controller) {
const controller = this.controller;
let aitValue = '@' + sendMember.getAitName() + ' '
const offset = controller.getCaretOffset()
controller.addBuilderSpan(() => this.AtSpan(aitValue), {
offset: offset
});
let aitSpan: AitEditorSpan = {
spanIndex: offset,
accountId: senderId,
value: aitValue,
}
this.builderSpans.push(...[aitSpan])
}
}
showLocationDetail(msg: NIMMessageInfo) {
let attachment = msg.message.attachment as V2NIMMessageLocationAttachment
let queryLocationOptions: sceneMap.LocationQueryOptions = {
location: {
latitude: attachment.latitude,
longitude: attachment.longitude
},
name: attachment.address,
address: attachment.address,
};
// 拉起地点详情页
sceneMap.queryLocation(getContext(this) as common.UIAbilityContext, queryLocationOptions).then(() => {
console.info("netease QueryLocation", "Succeeded in querying location.");
}).catch((err: BusinessError) => {
console.error("netease QueryLocation", `Failed to query Location, code: ${err.code}, message: ${err.message}`);
});
}
@Builder
build() {
NavDestination() {
NavigationBackBuilder({
title: this.chatTeamInfo.conversationName,
leftButtonAction: () => {
this.pathStack.pop()
},
rightButtonIcon: this.showMultiSelect ? undefined : $r('app.media.ic_public_more_dot'),
rightButtonTitle: this.showMultiSelect ? $r('app.string.chat_msg_dialog_cancel') : undefined,
rightButtonAction: () => {
this.goToTeamSettingPage(this.pathStack)
}
})
RelativeContainer() {
List({ scroller: this.listScroller }) {
LazyForEach(this.chatTeamInfo.msgList, (msg: NIMMessageInfo) => {
ListItem() {
MessageComponent({
message: msg,
chatInfo: this.chatTeamInfo,
showSelect: this.showMultiSelect,
onMessageClick: {
onAvatarClick: (msg: NIMMessageInfo | undefined) => {
if (this.showMultiSelect) {
return
}
if (msg != null) {
if (msg?.message.senderId == ChatKitClient.getLoginUserId()) {
this.pathStack.pushPath({
name: 'MineInfoPage'
})
} else {
this.pathStack.pushPath({ name: 'PersonInfoPage', param: msg?.message.senderId })
}
}
},
onAvatarLongPress: (msg: NIMMessageInfo | undefined) => {
if (this.showMultiSelect) {
return
}
if (msg != null) {
if (msg?.message.senderId && msg?.message.senderId !== ChatKitClient.getLoginUserId()) {
this.addAitUserById(msg.message.senderId)
}
}
},
onItemLongClick: (event: GestureEvent, msg: NIMMessageInfo | undefined) => {
if (this.showMultiSelect) {
return
}
this.operationMsg = msg
let opMenuWidth = computeOperateViewWidth(msg)
let opMenuHeight = computeOperateViewHeight(msg)
let marginSize = this.operationViewMargin
if (event.target.area.position.x !== undefined) {
let xPoint = Number(event.target.area.globalPosition.x) +
(Number(event.target.area.width) - opMenuWidth) / 2
if (xPoint < marginSize) {
xPoint = marginSize
}
if (xPoint + opMenuWidth + marginSize > this.screenWidth) {
xPoint = this.screenWidth - opMenuWidth - marginSize
}
this.operationRect.x = xPoint;
}
if (event.target.area.position.y !== undefined) {
let yPoint =
Number(event.target.area.globalPosition.y) - this.navBarHeight +
Number(event.target.area.height)
if (yPoint + opMenuHeight + marginSize + this.bottomHeight > this.scrollHeight) {
yPoint =
yPoint - opMenuHeight - marginSize * 2 - Number(event.target.area.height);
}
if (yPoint < 0) {
yPoint = this.scrollHeight / 2;
}
this.operationRect.y = yPoint
}
this.showOperationView = true
},
onItemClick: (event: ClickEvent, msg: NIMMessageInfo | undefined) => {
if (this.showMultiSelect) {
if (msg && !msg.isRevokeMsg) {
if (!msg?.isSelectedMsg) {
this.chatViewModel.addSelectMessage(msg)
} else {
this.chatViewModel.removeSelectMessage(msg)
}
}
return
}
this.showMessageDetail(msg)
},
onRevokeEditClick: (_event: ClickEvent, msg: NIMMessageInfo | undefined) => {
if (msg?.checkRevokeEdit()) {
const controller = this.controller
if (msg.isReplyMsg && msg.replyMsg) {
this.controller.deleteSpans()
this.loadReplyInfo(msg.replyMsg, false)
} else {
this.clearInput(true)
}
this.builderSpans.splice(0, this.builderSpans.length)
parseMessageText(msg.revokeInfo?.revokeMsgText)?.forEach((item: NEEmojiParseResult) => {
let spanIndex = 0
if (item.text) {
getAitNodes(item.startIndex, item.text, msg.message.serverExtension)
.forEach((node: ChatAitNode) => {
if (node.segment) {
controller.addBuilderSpan(() => this.AtSpan(node.text));
let aitSpan: AitEditorSpan = {
spanIndex: spanIndex,
accountId: node.account ?? '',
value: node.text,
}
this.builderSpans.push(...[aitSpan])
spanIndex++
} else {
controller.addTextSpan(node.text)
spanIndex = spanIndex + node.text.length
}
})
} else if (item.emoji) {
controller.addImageSpan($rawfile(`emoji/${item.emoji.file}`),
{
imageStyle: { size: [16, 16] }
})
spanIndex++
}
})
} else if (msg?.revokeInfo !== undefined) {
NECommonUtils.showToast($r('app.string.chat_revoke_edit_error_tips'))
}
},
onReadReceiptClick: (_event: ClickEvent, msg: NIMMessageInfo | undefined) => {
if (ErrorUtils.checkNetworkAndToast()) {
this.pathStack.pushPath({ name: 'ChatReadReceiptPage', param: msg?.message })
}
},
onMultiSelect: (select: boolean, msg: NIMMessageInfo | undefined) => {
if (msg) {
if (select) {
this.chatViewModel.addSelectMessage(msg)
} else {
this.chatViewModel.removeSelectMessage(msg)
}
this.operationMsg = undefined
}
},
onReplyClick: (event: ClickEvent, msg: NIMMessageInfo | undefined) => {
if (msg) {
if (this.chatTeamInfo.msgMap.has(msg.getMessageClientId())) {
let index = this.chatTeamInfo.searchPosition(msg.getMessageClientId())
this.listScroller.scrollToIndex(index)
} else {
this.showMessageDetail(msg, true)
}
}
},
onSendFailClick: (_event: ClickEvent, msg: NIMMessageInfo | undefined) => {
if (this.showMultiSelect) {
return
}
if (msg) {
this.chatViewModel.resendMessage(msg)
}
},
}
})
}
}, (item: NIMMessageInfo, index: number) => {
try {
return item.message.messageClientId
}catch (e) {
return index.toString()
}
})
}
.id("chatPageListView")
.cachedCount(20)
.padding({ bottom: 10 })
.maintainVisibleContentPosition(true)
.onScrollIndex((start: number, end: number) => {
if (!this.toScroll) {
if (start >= 0 && start < 3
&& this.listScrollStartPosition > start && this.chatViewModel.canLoadMore()) {
this.chatViewModel.getMoreMessageList()
} else if (this.listScrollEndPosition < end && this.chatViewModel.canLoadNext(end)) {
this.chatViewModel.getNewMessageList()
}
}
this.listScrollEndPosition = end;
this.listScrollStartPosition = start;
})
.onScrollStop(() => {
console.debug('netease to scroll stop:', this.toScroll)
if (this.toScroll) {
this.toScroll = false
}
})
.alignRules({
left: { anchor: "__container__", align: HorizontalAlign.Start },
right: { anchor: "__container__", align: HorizontalAlign.End },
top: { anchor: "__container__", align: VerticalAlign.Top },
})
.height(this.scrollHeight - this.bottomMargin)
.onScrollStart(() => {
this.showOperationView = false
})
.onTouch((event) => {
if (event.type == TouchType.Down) {
this.showOperationView = false
this.getUIContext().getFocusController().clearFocus();
this.scrollHeight = this.defaultInputViewHeight;
this.expandHeight = 0;
this.inputStyle = InputStyleType.None
}
})
if (this.chatViewModel.networkBroken) {
NetworkBrokenBuilder()
}
Column()
.height(this.bottomHeight)
.backgroundColor(Color.Transparent)
.backgroundColor($r('app.color.chat_input_background'))
.id("chat_input")
.alignRules({
left: { anchor: "__container__", align: HorizontalAlign.Start },
right: { anchor: "__container__", align: HorizontalAlign.End },
top: { anchor: "chatPageListView", align: VerticalAlign.Bottom },
})
if (this.hideInput === false && !this.showMultiSelect) {
NEChatInputView({
aitManager: this.aitManager,
controller: this.controller,
builderSpans: this.builderSpans,
placeHolder: (this.chatTeamInfo.conversationName ?? '').length > 15 ?
this.chatTeamInfo.conversationName?.substring(0, 15) + '...' : this.chatTeamInfo.conversationName,
replyMsg: this.replyMsg,
chatInfo: this.chatTeamInfo,
onDidClickCloseReply: () => {
this.clearInput(false)
},
onDidClickImage: () => {
this.showOperationView = false
MediaUtils.showImageVideoPicker().then((result) => {
if (result.errorMsg == null && result.uri) {
if (result.type === photoAccessHelper.PhotoType.IMAGE) {
this.chatViewModel.sendImageMessage(result.uri);
} else if (result.type === photoAccessHelper.PhotoType.VIDEO) {
this.chatViewModel.sendVideoMessage(result.uri, result.duration, result.width, result.height);
}
}
})
},
onDidClickAudio: () => {
let context = getContext(this) as common.UIAbilityContext
this.showOperationView = false
this.getUIContext().getFocusController().clearFocus()
PermissionsUtils.reqPermissionsFromUser(['ohos.permission.MICROPHONE'], context).then((result) => {
if (result.grantStatus == true) {
if (this.inputStyle == InputStyleType.Record) {
this.expandHeight = 0
this.inputStyle = InputStyleType.None;
this.scrollHeight = this.screenHeight - this.expandHeight - this.bottomHeight
} else {
this.inputStyle = InputStyleType.Record
this.expandHeight = ChatConst.messageInputAreaHeight
this.scrollHeight = this.screenHeight - this.expandHeight - this.bottomHeight
}
} else {
NECommonUtils.showToast($r('app.string.chat_permission_deny_tips'))
}
})
},
onDidClickEmoji: () => {
this.showOperationView = false
if (this.inputStyle == InputStyleType.Emoji) {
this.expandHeight = 0
this.inputStyle = InputStyleType.None;
this.scrollHeight = this.screenHeight - this.expandHeight - this.bottomHeight
} else {
this.inputStyle = InputStyleType.Emoji
this.expandHeight = ChatConst.messageInputAreaHeight
this.scrollHeight = this.screenHeight - this.expandHeight - this.bottomHeight
}
},
onDidClickMore: () => {
this.showOperationView = false
if (this.inputStyle == InputStyleType.More) {
this.expandHeight = 0
this.inputStyle = InputStyleType.None;
this.scrollHeight = this.screenHeight - this.expandHeight - this.bottomHeight
} else {
this.inputStyle = InputStyleType.More
this.expandHeight = ChatConst.messageInputAreaHeight
this.scrollHeight = this.screenHeight - this.expandHeight - this.bottomHeight
}
},
onSendTextMessage: () => {
const text = this.getMessageText()
let textSend = text.trimEnd()
this.showOperationView = false
if (textSend.length <= 0) {
NECommonUtils.showToast($r('app.string.null_message_not_support'))
return
}
if (text.length - textSend.length <= 1) {
textSend = text
}
this.chatViewModel.sendTextMessage(textSend, this.replyMsg, this.aitManager.aitModel,
this.aitManager.getPushList())
this.clearInput(true)
this.aitManager.cleanAit()
this.builderSpans.splice(0, this.builderSpans.length)
},
onChangeInputHeight:(height:number)=>{
this.bottomHeight = height
},
inputStyle: this.inputStyle,
mute: this.chatViewModel.isMuteModel,
teamId: this.chatTeamInfo.team?.teamId,
team: this.chatTeamInfo.team
}).alignRules({
left: { anchor: "chat_input", align: HorizontalAlign.Start },
right: { anchor: "chat_input", align: HorizontalAlign.End },
bottom: { anchor: "chat_input", align: VerticalAlign.Bottom },
top: { anchor: "chat_input", align: VerticalAlign.Top },
}).backgroundColor(this.chatViewModel.isMuteModel ? '#ffE9EFF5' : $r('app.color.chat_input_background'))
} else if (this.showMultiSelect) {
ChatMultiSelectView({
isEnable: this.multiSelectCount > 0,
onMultiForward: () => {
if (ChatKitClient.connectBroken()) {
NECommonUtils.showToast($r('app.string.chat_network_error_tips'))
} else {
this.multiForwardMessage()
}
},
onSingleForward: () => {
if (ChatKitClient.connectBroken()) {
NECommonUtils.showToast($r('app.string.chat_network_error_tips'))
} else {
this.singleForwardMessage()
}
},
onMultiDelete: () => {
let selectMsg = this.chatViewModel.getSelectMessageList()
if (selectMsg.length > ChatConst.messageDeleteLimit) {
NECommonUtils.showToast($r('app.string.chat_multi_delete_limit_tips', ChatConst.messageDeleteLimit))
} else {
this.showDialogToDelete(selectMsg)
}
},
}).width('100%').height(this.bottomHeight)
.alignRules({
left: { anchor: "chat_input", align: HorizontalAlign.Start },
right: { anchor: "chat_input", align: HorizontalAlign.End },
bottom: { anchor: "chat_input", align: VerticalAlign.Bottom },
top: { anchor: "chat_input", align: VerticalAlign.Top },
}).backgroundColor($r('app.color.chat_input_background'))
}
Column() {
if (this.inputStyle === InputStyleType.Record) {
NEAudioRecordView({
onRecordAudio: (filepath, duration) => {
console.log("net ease record audio " + filepath);
this.chatViewModel.sendAudioMessage(filepath, duration)
},
onRecordStart: () => {
this.hideInput = true
},
onRecordEnd: () => {
this.hideInput = false
}
})
.width('100%')
.height(150)
.alignRules({
left: { anchor: "__container__", align: HorizontalAlign.Start },
right: { anchor: "__container__", align: HorizontalAlign.End },
top: { anchor: "__container__", align: VerticalAlign.Top },
})
} else if (this.inputStyle === InputStyleType.More) {
NEChatMoreOperation({
dataList: this.operationMoreDataList, onDidClick: (data) => {
let context = getContext(this) as common.UIAbilityContext;
if (data.type == NEChatMoreOperationType.Video) {
PermissionsUtils.reqPermissionsFromUser(['ohos.permission.CAMERA'], context).then((result) => {
if (result.grantStatus == true) {
this.selectVideoView.open()
} else {
NECommonUtils.showToast($r('app.string.chat_permission_deny_tips'))
}
})
} else if (data.type == NEChatMoreOperationType.File) {
console.log("net ease click file")
MediaUtils.showFilePicker().then((result) => {
if (result.errorMsg == null && result.uri) {
this.chatViewModel.sendFileMessage(result.uri);
}
})
} else if (data.type == NEChatMoreOperationType.Location) {
PermissionsUtils.reqPermissionsFromUser(['ohos.permission.LOCATION',
'ohos.permission.APPROXIMATELY_LOCATION'], context).then((result) => {
if (result.grantStatus == true) {
let locationChoosingOptions: sceneMap.LocationChoosingOptions = {
// 展示搜索控件
searchEnabled: true,
// 展示附近Poi
showNearbyPoi: true
};
// 拉起地点选取页
sceneMap.chooseLocation(getContext(this) as common.UIAbilityContext, locationChoosingOptions)
.then((data) => {
this.chatViewModel.sendLocationMessage(data)
console.info("ChooseLocation", "Succeeded in choosing location.");
})
.catch((err: BusinessError) => {
console.error("ChooseLocation",
`Failed to choose location, code: ${err.code}, message: ${err.message}`);
// NECommonUtils.showToast(`code: ${err.code}, message: ${err.message}`)
});
} else {
NECommonUtils.showToast($r('app.string.chat_permission_deny_tips'))
}
})
}
}
}).padding({ top: 10 })
.width('100%')
.height(150)
.alignRules({
left: { anchor: "__container__", align: HorizontalAlign.Start },
right: { anchor: "__container__", align: HorizontalAlign.End },
top: { anchor: "__container__", align: VerticalAlign.Top },
})
} else if (this.inputStyle === InputStyleType.Emoji) {
NEChatEmojiView({
onDidClick: (emoji) => {
console.log("net ease click emoji", emoji);
if (emoji.type === NIMEmoticonType.file) {
this.controller.addImageSpan($rawfile(`emoji/${emoji.file}`),
{
offset: this.controller.getCaretOffset(),
imageStyle: { size: [16, 16] }
})
} else if (emoji.type === NIMEmoticonType.delete) {
if (this.controller) {
let index = this.controller.getCaretOffset()
if (index > 0) {
this.controller.deleteSpans({
start: index - 1,
end: index
})
}
}
}
},
onEmojiSendMessage: () => {
const text = this.getMessageText()
let textSend = text.trimEnd()
if (textSend.length <= 0) {
NECommonUtils.showToast($r('app.string.null_message_not_support'))
return
}
if (text.length - textSend.length <= 1) {
textSend = text
}
this.chatViewModel.sendTextMessage(textSend, this.replyMsg, this.aitManager.aitModel,
this.aitManager.getPushList())
this.clearInput(true)
this.aitManager.cleanAit()
this.builderSpans.splice(0, this.builderSpans.length)
}
}).padding({ top: 0 })
.width('100%')
.height(170)
.alignRules({
left: { anchor: "__container__", align: HorizontalAlign.Start },
right: { anchor: "__container__", align: HorizontalAlign.End },
top: { anchor: "__container__", align: VerticalAlign.Top }
})
}
}
.height(this.expandHeight)
.width('100%')
.alignRules({
left: { anchor: "__container__", align: HorizontalAlign.Start },
right: { anchor: "__container__", align: HorizontalAlign.End },
top: { anchor: "chat_input", align: VerticalAlign.Bottom },
})
.id("input_expand_back_container")
.backgroundColor($r('app.color.chat_input_background'))
if (this.showOperationView) {
MessageOperationView({
operateMsg: this.operationMsg,
didClickItem: (item: MessageOperationItem) => {
console.log('net ease click operation item event')
this.showOperationView = false
if (this.operationMsg == undefined) {
return;
}
if (item.operationType == MessageOperationType.Copy) {
const pasteboardData =
pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, this.operationMsg.message.text)
pasteboard.getSystemPasteboard().setDataSync(pasteboardData)
NECommonUtils.showToast($r('app.string.chat_message_copy_success_tips'))
} else if (item.operationType == MessageOperationType.Delete) {
this.showDialogToDelete([this.operationMsg])
} else if (item.operationType == MessageOperationType.Undo) {
this.showDialogToRevoke(this.operationMsg)
} else if (item.operationType == MessageOperationType.Forward) {
// 转发
this.forwardMessageAction = (selectedList: ConversationSelectModel[]) => {
if (this.operationMsg?.message) {
this.forwardMessages = [this.operationMsg.message]
this.forwardConversations = selectedList
this.currentConversationName = this.chatTeamInfo.team?.name
this.forwardMessageDialog.open()
}
}
this.forwardType = $r('app.string.chat_operation_forward')
this.pathStack.pushPath({
name: 'ConversationSelectPage',
param: new ConversationSelectParam([], conversationSelectLimitCount, this.forwardMessageAction)
})
} else if (item.operationType == MessageOperationType.Collection) {
// 收藏
this.chatViewModel.collectionMessage(this.operationMsg)
} else if (item.operationType == MessageOperationType.Pin) {
this.chatViewModel.pinMessage(this.operationMsg)
} else if (item.operationType == MessageOperationType.Unpin) {
this.chatViewModel.unpinMessage(this.operationMsg)
} else if (item.operationType == MessageOperationType.Select) {
this.chatViewModel.clearSelectMessage()
this.chatViewModel.addSelectMessage(this.operationMsg)
this.showMultiSelect = true
} else if (item.operationType == MessageOperationType.Reply) {
this.loadReplyInfo(this.operationMsg, true)
}
}
})
.position({ x: this.operationRect.x, y: this.operationRect.y })
.borderRadius(8)
.shadow(ShadowStyle.OUTER_DEFAULT_MD)
}
}.margin({ bottom: this.bottomMargin })
.expandSafeArea([SafeAreaType.KEYBOARD])
.zIndex(1)
}
.hideTitleBar(true)
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
let param = this.pathStack.getParamByName("ChatTeamPage") as string[];
if (param.length > 0) {
this.conversationId = param[0];
this.requestChatData();
} else {
this.pathStack.removeByName("ChatTeamPage")
}
})
.onHidden(() => {
AudioPlayerManager.instance.stopPlayAll()
})
}
clearInput(clearInput?: boolean) {
if (clearInput) {
this.controller.deleteSpans()
}
this.replyMsg = undefined
this.bottomHeight = 105
this.computeScrollHeight()
}
loadReplyInfo(msg: NIMMessageInfo, needAit: boolean) {
this.bottomHeight = 135
this.replyMsg = msg
if (needAit && this.replyMsg.message.senderId !== ChatKitClient.getLoginUserId()) {
this.addAitUserById(this.replyMsg.message.senderId)
}
this.getUIContext().getFocusController().requestFocus("chat_edit_input")
}
/**
* 【逐条转发】将多个消息逐条转发到多个会话中,并将留言发送到多个会话中
*/
singleForwardMessage() {
// 校验网络
if (ErrorUtils.checkNetworkAndToast()) {
this.forwardType = $r('app.string.chat_operation_single_forward')
// 校验转发条数
if (this.chatViewModel.selectMsgMap.size > singleMessageLimitCount) {
let resourceManager = getContext(this).resourceManager
NECommonUtils.showToast($r("app.string.chat_forward_limit", resourceManager.getStringSync(this.forwardType.id),
singleMessageLimitCount))
return
}
// 不可合并转发的消息列表
let invalidMessages: NIMMessageInfo[] = []
for (const message of this.chatViewModel.selectMsgMap.values()) {
// 发送失败的消息不可转发
// 语音消息不可转发
// 话单消息不可转发
if (message.message.sendingState === V2NIMMessageSendingState.V2NIM_MESSAGE_SENDING_STATE_FAILED ||
message.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_AUDIO ||
message.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_CALL) {
invalidMessages.push(message)
continue
}
}
this.forwardMessageAction = async (selectedList: ConversationSelectModel[]) => {
let selectMessage = this.chatViewModel.getSelectMessageList().map(msg => msg.message)
selectMessage = selectMessage.sort((m1, m2) => {
if (m1.createTime < m2.createTime) {
return -1
}
if (m1.createTime > m2.createTime) {
return 1
}
return 0
})
this.forwardMessages = selectMessage
this.forwardConversations = selectedList
this.currentConversationName = this.chatTeamInfo.team?.name
this.forwardMessageDialog.open()
}
// 存在不可转发的消息:提示 + 取消勾选
if (invalidMessages.length > 0) {
this.invalidForwardFailureDialog?.open()
this.invalidForwardDialogSureAction = () => {
for (const invalidMessage of invalidMessages) {
this.chatViewModel.removeSelectMessage(invalidMessage)
invalidMessage.isSelectedMsg = false
}
if (this.chatViewModel.getSelectMessageSize() > 0) {
this.pathStack.pushPath({
name: 'ConversationSelectPage',
param: new ConversationSelectParam([], conversationSelectLimitCount, this.forwardMessageAction)
})
}
}
} else {
if (this.chatViewModel.getSelectMessageSize() > 0) {
this.pathStack.pushPath({
name: 'ConversationSelectPage',
param: new ConversationSelectParam([], conversationSelectLimitCount, this.forwardMessageAction)
})
}
}
}
}
/**
* 【合并转发】将多个消息合并为一条自定义消息,转发到多个会话中,并将留言发送到多个会话中
*/
multiForwardMessage() {
// 校验网络
if (ErrorUtils.checkNetworkAndToast()) {
this.forwardType = $r('app.string.chat_operation_multi_forward')
// 校验转发条数
if (this.chatViewModel.selectMsgMap.size > mergedMessageLimitCount) {
let resourceManager = getContext(this).resourceManager
NECommonUtils.showToast($r("app.string.chat_forward_limit", resourceManager.getStringSync(this.forwardType.id),
mergedMessageLimitCount))
return
}
// 计算层数(深度) depth
let depth = 0
// 不可合并转发的消息列表(1.发送失败的消息2.转发层数超过 mergedMessageMaxDepth 的消息)
const invalidMessages: NIMMessageInfo[] = []
let invalidFail: boolean = false
let invalidDepth: boolean = false
for (const message of this.chatViewModel.selectMsgMap.values()) {
// 发送失败的消息不可转发
if (message.message.sendingState === V2NIMMessageSendingState.V2NIM_MESSAGE_SENDING_STATE_FAILED) {
invalidMessages.push(message)
invalidFail = true
continue
}
// 解析消息中的 depth
if (message.message.attachment) {
let data = CustomMessageUtils.dataOfCustomMessage(message.message.attachment)
if (data) {
let dep = data["depth"] as number
if (dep >= mergedMessageMaxDepth) {
invalidMessages.push(message)
invalidDepth = true
} else if (dep >= depth) {
depth = dep
}
}
}
}
// 当前合并转发消息深度 + 1
depth += 1
this.forwardMessageAction = async (selectedList: ConversationSelectModel[]) => {
let forwardMessages =
await this.chatViewModel.mergeForwardMessage(this.chatViewModel.getSelectMessageList(), depth)
if (forwardMessages) {
this.forwardMessages = [forwardMessages]
}
this.forwardConversations = selectedList
this.currentConversationName = this.chatTeamInfo.team?.name
this.forwardMessageDialog.open()
}
// 存在不可转发的消息:提示 + 取消勾选
if (invalidMessages.length > 0) {
if (invalidFail) {
this.invalidForwardFailureDialog?.open()
} else if (invalidDepth) {
this.invalidForwardDepthDialog?.open()
}
this.invalidForwardDialogSureAction = () => {
for (const invalidMessage of invalidMessages) {
this.chatViewModel.removeSelectMessage(invalidMessage)
invalidMessage.isSelectedMsg = false
}
if (this.chatViewModel.getSelectMessageSize() > 0) {
this.pathStack.pushPath({
name: 'ConversationSelectPage',
param: new ConversationSelectParam([], conversationSelectLimitCount, this.forwardMessageAction)
})
}
}
} else {
if (this.chatViewModel.getSelectMessageSize() > 0) {
this.pathStack.pushPath({
name: 'ConversationSelectPage',
param: new ConversationSelectParam([], conversationSelectLimitCount, this.forwardMessageAction)
})
}
}
}
}
/**
* 查看消息详情,点击消息体查看或者点击被回复内容查看
* @param msg 点击的消息
* @param onlyShow 是否为只展示该消息,如果是则文本消息会直接弹窗展示,图片消息则只查看当前消息
*/
showMessageDetail(msg: NIMMessageInfo | undefined, onlyShow?: boolean) {
if (msg) {
if (onlyShow && msg.getMessageType() == V2NIMMessageType.V2NIM_MESSAGE_TYPE_TEXT) {
this.textMessageDetailDialog = new CustomDialogController({
builder: TextMessageDetailDialog({
message: msg
}),
cornerRadius: 0,
alignment: DialogAlignment.Center,
backgroundColor: Color.White,
height: '100%',
width: '100%',
customStyle: true
})
this.textMessageDetailDialog.open()
}
if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_IMAGE) {
this.showImageDetail(msg, onlyShow)
} else if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_FILE) {
downLoadAndOpenFile(msg, getContext(this), this.chatTeamInfo)
} else if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_VIDEO) {
this.showVideoDetail(msg)
} else if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_LOCATION) {
this.showLocationDetail(msg)
} else if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_AUDIO) {
if (onlyShow) {
this.playAudioMessage(msg)
}
} else if (msg?.message.messageType === V2NIMMessageType.V2NIM_MESSAGE_TYPE_CUSTOM) {
const attachment = msg.message.attachment
if (attachment) {
const type = CustomMessageUtils.typeOfCustomMessage(attachment)
if (type === mergedMessageCustomType) {
let data = CustomMessageUtils.dataOfCustomMessage(attachment)
if (data as MergedMessageAttachment) {
this.pathStack.pushPath({
name: 'MergeMessageDetailPage',
param: data as MergedMessageAttachment
})
}
}
}
}
}
}
playAudioMessage(msg: NIMMessageInfo) {
if (msg.message.attachment) {
let audioManager = AudioPlayerManager.instance
audioManager.stopPlayAll()
audioManager.avPlayerLive((msg.message.attachment as V2NIMMessageAudioAttachment).url ?? '')
}
}
showDialogToDelete(messages: NIMMessageInfo[]) {
AlertDialog.show(
{
title: $r('app.string.chat_msg_delete_dialog_title'),
message: $r('app.string.chat_msg_delete_dialog_desc'),
autoCancel: true,
alignment: DialogAlignment.Bottom,
gridCount: 4,
offset: { dx: 0, dy: -20 },
primaryButton: {
value: $r('app.string.chat_msg_dialog_cancel'),
action: () => {
}
},
secondaryButton: {
enabled: true,
defaultFocus: true,
style: DialogButtonStyle.HIGHLIGHT,
value: $r('app.string.chat_msg_dialog_sure'),
action: () => {
this.chatViewModel.deleteMessageList(messages)
this.showMultiSelect = false
}
}
}
)
}
showDialogToRevoke(message: NIMMessageInfo) {
AlertDialog.show(
{
title: $r('app.string.chat_msg_revoke_dialog_title'),
message: $r('app.string.chat_msg_revoke_dialog_desc'),
autoCancel: true,
alignment: DialogAlignment.Bottom,
gridCount: 4,
offset: { dx: 0, dy: -20 },
primaryButton: {
value: $r('app.string.chat_msg_dialog_cancel'),
action: () => {
console.info('Callback when the first button is clicked')
}
},
secondaryButton: {
enabled: true,
defaultFocus: true,
style: DialogButtonStyle.HIGHLIGHT,
value: $r('app.string.chat_msg_dialog_sure'),
action: () => {
console.info('Callback when the second button is clicked')
this.chatViewModel.revokeMessage(message)
}
}
}
)
}
goToTeamSettingPage(pathStack: NavPathStack) {
if (this.showMultiSelect) {
this.chatViewModel.clearSelectMessage()
this.showMultiSelect = false
} else {
pathStack.pushPath({
name: 'TeamSettingPage',
param: this.chatTeamInfo.team?.teamId
})
}
this.controller.stopEditing()
}
onPageHide(): void {
this.chatViewModel.clearUnreadCount()
}
aboutToDisappear(): void {
this.chatViewModel.clearUnreadCount()
this.chatViewModel.onDestroy()
AudioPlayerManager.instance.stopPlayAll()
TeamMemberCache.getInstance().clear()
}
}
// 跳转页面入口函数
@Builder
export function ChatTeamPageBuilder() {
ChatTeamPage()
}