Files
video_socket-server/client/public/call/chat/chatmessage.js

252 lines
6.0 KiB
JavaScript
Raw Normal View History

2026-05-25 20:37:36 +08:00
import { createLogger } from '../../shared/logger.js';
2026-05-24 14:16:28 +08:00
const logger = createLogger('chat');
2026-04-29 15:18:30 +08:00
/**
* 消息模块
* 处理聊天消息的发送接收和显示
*/
2026-05-25 20:37:36 +08:00
import { showNotification, generateId } from '../../shared/utils.js';
import store from '../store.js';
import { mockMessages } from '../models.js';
2026-04-29 15:18:30 +08:00
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',
2026-05-21 20:40:39 +08:00
data: message,
2026-04-29 15:18:30 +08:00
});
}
}
/**
* 处理接收到的聊天消息
* @param {Object} data - 消息数据
*/
function handleChatMessage(data) {
2026-05-24 14:16:28 +08:00
logger.debug('处理聊天:', data);
2026-04-29 15:18:30 +08:00
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
};