Files
zyt/TUICallKit-Vue3/TUIKit/states/MessageInputState/MessageInputState.ts
T
2026-03-11 09:49:47 +08:00

150 lines
3.9 KiB
TypeScript

import { ref } from 'vue';
import type { Ref } from 'vue';
import { StoreName, TUIChatService, TUIStore } from '../chat-uikit-engine-lite';
import { MessageContentType } from './type';
import { convertInputContentToEditorNode } from './utils';
import type { InputContent } from './type';
/**
* Message Input Store
*
* This store manages the state and operations related to the chat message input, including:
* - Raw input value (text or structured content)
* - Editor instance management
* - Content manipulation (insertion, updating, etc.)
* - Message sending functionality
*/
interface MessageInputState {
inputRawValue: Ref<string | InputContent[]>;
isPeerTyping: Ref<boolean>;
}
interface MessageInputAction {
updateRawValue: (value: string | InputContent[]) => void;
setEditorInstance: (editor) => void;
setContent: (value: string | InputContent[]) => void;
insertContent: (value: string | InputContent[], focus?: boolean) => void;
focusEditor: () => void;
blurEditor: () => void;
sendMessage: (msg?: string | InputContent[]) => void;
}
const editor = ref(null);
const inputRawValue = ref<string | InputContent[]>('');
const isPeerTyping = ref(false);
/* =====================================================
* MessageInputActions begin
* ===================================================== */
const updateRawValue = (value: string | InputContent[]) => {
if (typeof value !== 'string' && !Array.isArray(value)) {
console.warn('Invalid input type for updateRawValue');
return;
}
if (typeof value === 'string') {
inputRawValue.value = value.trim();
} else {
inputRawValue.value = value?.length > 0 ? value : '';
}
TUIChatService.enterTypingState();
setTimeout(() => {
TUIChatService.leaveTypingState();
}, 3000);
};
const setEditorInstance = (instance) => {
if (editor.value) {
editor.value.destroy();
}
editor.value = instance;
};
const setContent = (content: string | InputContent[]) => {
if (!editor.value) {
return;
}
if (typeof content === 'string') {
editor.value.commands.setContent(content, true);
} else {
const editorContent = content.map(convertInputContentToEditorNode);
editor.value.commands.setContent(editorContent, true);
}
editor.value.commands.focus();
};
const insertContent = (content: string | InputContent[], focus = true) => {
if (!editor.value) {
return;
}
if (typeof content === 'string') {
editor.value.commands.insertContent(content);
} else {
const editorContent = content.map(convertInputContentToEditorNode);
editor.value.commands.insertContent(editorContent);
}
if (focus) {
editor.value.commands.focus();
}
};
const focusEditor = () => {
editor.value?.commands.focus();
};
const blurEditor = () => {
editor.value?.commands.blur();
};
const sendMessage = async (options) => {
const { type, content } = options
if (type === MessageContentType.TEXT) {
await TUIChatService.sendTextMessage({
payload: { text: content },
})
}
if (type === MessageContentType.IMAGE) {
await TUIChatService.sendImageMessage({
payload: { file: content },
});
}
if (type === MessageContentType.VIDEO) {
await TUIChatService.sendVideoMessage({
payload: { file: content },
});
}
};
/* =====================================================
* MessageInputActions end
* ===================================================== */
function useMessageInputState(): MessageInputState & MessageInputAction {
return {
inputRawValue,
isPeerTyping,
updateRawValue,
setEditorInstance,
setContent,
insertContent,
focusEditor,
blurEditor,
sendMessage,
};
}
function initWatcher() {
TUIStore.watch(StoreName.CHAT, {
typingStatus: (typingStatus) => {
isPeerTyping.value = typingStatus;
},
});
}
initWatcher();
export { useMessageInputState, MessageContentType };
export type { InputContent };