Files
video_socket-server/client/public/call/chat/chatmessage.js
2026-05-25 20:37:36 +08:00

252 lines
6.0 KiB
JavaScript
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.
import { createLogger } from '../../shared/logger.js';
const logger = createLogger('chat');
/**
* 消息模块
* 处理聊天消息的发送、接收和显示
*/
import { showNotification, generateId } from '../../shared/utils.js';
import store from '../store.js';
import { mockMessages } from '../models.js';
const MAX_IMAGE_SIZE = 5 * 1024 * 1024; // 5MB
// 消息相关的状态管理方法
let messageState = {
messages: [...mockMessages],
unreadCount: 0,
isSidebarOpen: false
};
let listeners = [];
/**
* 订阅状态变化
* @param {Function} callback - 回调函数
* @returns {Function} 取消订阅的函数
*/
function subscribe(callback) {
listeners.push(callback);
return () => {
listeners = listeners.filter(cb => cb !== callback);
};
}
/**
* 通知所有监听器
* @param {Object} changes - 变化对象
*/
function notify(changes) {
listeners.forEach(cb => cb(messageState, changes));
}
/**
* 添加消息
* @param {Object} message - 消息对象
*/
function addMessage (message) {
messageState.messages.push(message);
// 如果侧边栏关闭且不是自己发的,增加未读
if (!messageState.isSidebarOpen && !message.isSelf) {
messageState.unreadCount++;
notify({ type: 'SIDEBAR_TOGGLE', unreadCount: messageState.unreadCount });
}
notify({ type: 'NEW_MESSAGE', message, unreadCount: messageState.unreadCount });
}
/**
* 发送聊天消息
* @param {Object} message - 消息对象
* @param {Object} renderstreaming - WebRTC连接管理实例
*/
function sendChatMessage(message) {
if (store.getRenderStreaming()) {
store.getRenderStreaming().sendMessage({
type: 'chat-message',
data: message,
});
}
}
/**
* 处理接收到的聊天消息
* @param {Object} data - 消息数据
*/
function handleChatMessage(data) {
logger.debug('处理聊天:', data);
addMessage(data);
const isImage = data.content && data.content.startsWith('data:image/');
// 显示通知
if (!data.isSelf) {
const content = isImage ? '[图片]' : data.content;
showNotification(`${data.senderName}: ${content.substring(0, 20)}${content.length > 20 ? '...' : ''}`);
}
}
/**
* 切换侧边栏
* @returns {boolean} 切换后的状态
*/
function toggleSidebar() {
messageState.isSidebarOpen = !messageState.isSidebarOpen;
if (messageState.isSidebarOpen) {
messageState.unreadCount = 0;
}
notify({ type: 'SIDEBAR_TOGGLE', isOpen: messageState.isSidebarOpen, unreadCount: messageState.unreadCount });
return messageState.isSidebarOpen;
}
/**
* 获取消息状态
* @returns {Object} 消息状态
*/
function getMessageState() {
return messageState;
}
/**
* 发送消息
*/
function sendMessage() {
const chatInput = document.getElementById('chatInput');
const content = chatInput.value.trim();
if (content) {
const state = store.getState();
const message = {
id: generateId(),
senderId: state.session.localUser.id,
senderName: state.session.localUser.name,
senderAvatar: state.session.localUser.avatar,
content: content,
type: 'text',
timestamp: new Date().toISOString(),
isSelf: true
};
addMessage(message);
const newMessage = { ...message };
newMessage.isSelf = false;
chatInput.value = '';
// 发送消息到服务器
sendChatMessage(newMessage);
//wsManager.send('chat-message', message);
}
}
/**
* 处理聊天输入回车
* @param {KeyboardEvent} event - 键盘事件
*/
function handleChatSubmit(event) {
if (event.key === 'Enter') {
sendMessage();
}
}
/**
* 打开图片选择器
*/
function openImagePicker() {
document.getElementById('imageInput').click();
}
/**
* 处理图片上传
* @param {Event} event - 事件对象
*/
function handleImageUpload(event) {
const file = event.target.files[0];
if (file) {
// 检查文件类型
if (!file.type.startsWith('image/')) {
showNotification('请选择图片文件', 3000);
return;
}
// 检查文件大小限制为5MB
if (file.size > MAX_IMAGE_SIZE) {
showNotification('图片文件不能超过5MB', 3000);
return;
}
// 读取图片文件
const reader = new FileReader();
reader.onload = function (e) {
const imageUrl = e.target.result;
sendImageMessage(imageUrl, file.name);
};
reader.readAsDataURL(file);
// 重置文件输入
event.target.value = '';
}
}
/**
* 发送图片消息
* @param {string} imageUrl - 图片URL
* @param {string} fileName - 文件名
*/
function sendImageMessage(imageUrl, fileName) {
const state = store.getState();
const newMessage = {
id: generateId(),
senderId: state.session.localUser.id,
senderName: state.session.localUser.name,
senderAvatar: state.session.localUser.avatar,
content: imageUrl,
fileName: fileName,
type: 'file',
timestamp: new Date().toISOString(),
isSelf: true
};
// 添加消息到本地列表
addMessage(newMessage);
// 发送消息到服务器
const messageToSend = { ...newMessage };
messageToSend.isSelf = false;
sendChatMessage(messageToSend);
}
/**
* 绑定消息相关的DOM事件
*/
function bindMessageEvents() {
// 发送消息
window.sendMessage = sendMessage;
// 处理聊天输入回车
window.handleChatSubmit = handleChatSubmit;
// 打开图片选择器
window.openImagePicker = openImagePicker;
// 处理图片上传
window.handleImageUpload = handleImageUpload;
}
// 导出所有函数
export default {
sendMessage,
handleChatSubmit,
openImagePicker,
handleImageUpload,
sendImageMessage,
bindMessageEvents,
addMessage,
sendChatMessage,
handleChatMessage,
toggleSidebar,
getMessageState,
subscribe
};