249 lines
5.9 KiB
JavaScript
249 lines
5.9 KiB
JavaScript
/**
|
||
* 消息模块
|
||
* 处理聊天消息的发送、接收和显示
|
||
*/
|
||
import { showNotification, generateId } from './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',
|
||
message: message,
|
||
});
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 处理接收到的聊天消息
|
||
* @param {Object} data - 消息数据
|
||
*/
|
||
function handleChatMessage(data) {
|
||
console.log('处理聊天:', 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
|
||
};
|