360 lines
10 KiB
JavaScript
360 lines
10 KiB
JavaScript
/**
|
||
* 主入口文件
|
||
* 初始化应用,连接各个模块
|
||
*/
|
||
import store from './store.js';
|
||
import UIRenderer from './renderer.js';
|
||
import apiClient from './api.js';
|
||
import wsManager from './websocket.js';
|
||
import { mockCallSession } from './models.js';
|
||
import { showNotification, generateId } from './utils.js';
|
||
|
||
// 全局变量
|
||
let renderer = null;
|
||
let connectionId = "";
|
||
/**
|
||
* 初始化应用
|
||
*/
|
||
function initApp() {
|
||
// 初始化渲染器
|
||
renderer = new UIRenderer(store);
|
||
|
||
// 初始化WebSocket连接
|
||
wsManager.connect();
|
||
|
||
// 绑定WebSocket事件
|
||
bindWebSocketEvents();
|
||
|
||
// 绑定DOM事件
|
||
bindDomEvents();
|
||
|
||
// 初始化WebRTC (如果需要)
|
||
// initWebRTC();
|
||
|
||
|
||
console.log('App initialized');
|
||
}
|
||
|
||
/**
|
||
* 绑定WebSocket事件
|
||
*/
|
||
function bindWebSocketEvents() {
|
||
wsManager.on('connect', () => {
|
||
console.log('WebSocket connected');
|
||
showNotification('已连接到服务器');
|
||
});
|
||
|
||
wsManager.on('disconnect', () => {
|
||
console.log('WebSocket disconnected');
|
||
showNotification('与服务器的连接已断开', 5000);
|
||
});
|
||
|
||
wsManager.on('message-received', (data) => {
|
||
console.log('Message received:', data);
|
||
store.addMessage(data.message);
|
||
});
|
||
|
||
wsManager.on('user-joined', (data) => {
|
||
console.log('User joined:', data);
|
||
showNotification(`${data.userId} 加入了通话`);
|
||
});
|
||
|
||
wsManager.on('user-left', (data) => {
|
||
console.log('User left:', data);
|
||
showNotification(`${data.userId} 离开了通话`);
|
||
});
|
||
|
||
wsManager.on('media-state-changed', (data) => {
|
||
console.log('Media state changed:', data);
|
||
// 更新远端媒体状态
|
||
if (data.userId !== store.getLocalUser().id) {
|
||
store.updateRemoteMedia(data);
|
||
}
|
||
});
|
||
|
||
wsManager.on('network-quality', (data) => {
|
||
console.log('Network quality changed:', data);
|
||
// 更新网络质量
|
||
const state = store.getState();
|
||
if (data.userId === state.session.remoteUser.id) {
|
||
state.session.remoteUser.networkQuality = data.quality;
|
||
store.notify({ type: 'NETWORK_CHANGE', quality: data.quality });
|
||
}
|
||
});
|
||
|
||
wsManager.on('call-ended', (data) => {
|
||
console.log('Call ended:', data);
|
||
store.endCall();
|
||
showNotification('通话已结束', 3000);
|
||
});
|
||
|
||
wsManager.on('call-request', (data) => {
|
||
console.log('Call request received:', data);
|
||
// 显示通话请求弹窗
|
||
if (window.showCallRequest) {
|
||
const caller = {
|
||
name: mockCallSession.remoteUser.name,
|
||
avatar:mockCallSession.remoteUser.avatar
|
||
};
|
||
window.showCallRequest(caller);
|
||
connectionId =data.connectionId;
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 绑定DOM事件
|
||
*/
|
||
function bindDomEvents() {
|
||
// 切换侧边栏
|
||
window.toggleSidebar = function () {
|
||
store.toggleSidebar();
|
||
};
|
||
|
||
// 切换麦克风
|
||
window.toggleMute = function (button) {
|
||
const state = store.getState();
|
||
const currentState = state.session.localUser.mediaState.audio;
|
||
store.updateLocalMedia('audio', !currentState);
|
||
};
|
||
|
||
// 切换视频
|
||
window.toggleVideo = function (button) {
|
||
const state = store.getState();
|
||
const currentState = state.session.localUser.mediaState.video;
|
||
store.updateLocalMedia('video', !currentState);
|
||
};
|
||
|
||
// 切换本地视频(用于悬停控制)
|
||
window.toggleLocalVideo = function () {
|
||
window.toggleVideo();
|
||
};
|
||
|
||
// 切换录屏
|
||
window.toggleRecording = function (button) {
|
||
const state = store.getState();
|
||
const currentState = state.session.localUser.mediaState.recording || false;
|
||
store.updateLocalMedia('recording', !currentState);
|
||
|
||
// 显示录制状态通知
|
||
if (!currentState) {
|
||
showNotification('开始录制');
|
||
} else {
|
||
showNotification('停止录制');
|
||
}
|
||
};
|
||
|
||
// 结束通话
|
||
window.endCall = function () {
|
||
// 显示确认对话框
|
||
document.getElementById('endCallDialog').classList.remove('hidden');
|
||
};
|
||
|
||
// 取消结束通话
|
||
window.cancelEndCall = function () {
|
||
document.getElementById('endCallDialog').classList.add('hidden');
|
||
};
|
||
|
||
// 确认结束通话
|
||
window.confirmEndCall = function () {
|
||
document.getElementById('endCallDialog').classList.add('hidden');
|
||
store.endCall();
|
||
showNotification('通话已结束');
|
||
};
|
||
|
||
// 显示通话请求弹窗
|
||
window.showCallRequest = function (caller) {
|
||
const dialog = document.getElementById('callRequestDialog');
|
||
if (dialog) {
|
||
// 设置通话请求信息
|
||
if (document.getElementById('callRequestName')) {
|
||
document.getElementById('callRequestName').textContent = caller.name;
|
||
}
|
||
if (document.getElementById('callRequestAvatar')) {
|
||
document.getElementById('callRequestAvatar').src = caller.avatar;
|
||
}
|
||
// 显示弹窗
|
||
dialog.classList.remove('hidden');
|
||
}
|
||
};
|
||
|
||
// 拒绝通话
|
||
window.rejectCall = function () {
|
||
const dialog = document.getElementById('callRequestDialog');
|
||
if (dialog) {
|
||
dialog.classList.add('hidden');
|
||
}
|
||
showNotification('已拒绝通话请求');
|
||
// 可以在这里添加发送拒绝通话请求到服务器的逻辑
|
||
};
|
||
|
||
// 接受通话
|
||
window.acceptCall = function () {
|
||
const dialog = document.getElementById('callRequestDialog');
|
||
if (dialog) {
|
||
dialog.classList.add('hidden');
|
||
}
|
||
showNotification('已接受通话请求');
|
||
// 可以在这里添加发送接受通话请求到服务器的逻辑
|
||
// 然后初始化通话
|
||
store.initCall();
|
||
store.setUp(connectionId);
|
||
};
|
||
|
||
// 发送消息
|
||
window.sendMessage = function () {
|
||
const chatInput = document.getElementById('chatInput');
|
||
const content = chatInput.value.trim();
|
||
|
||
if (content) {
|
||
const state = store.getState();
|
||
const newMessage = {
|
||
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
|
||
};
|
||
|
||
store.addMessage(newMessage);
|
||
chatInput.value = '';
|
||
|
||
// 发送消息到服务器
|
||
// wsManager.send('send-message', newMessage);
|
||
}
|
||
};
|
||
|
||
// 处理聊天输入回车
|
||
window.handleChatSubmit = function (event) {
|
||
if (event.key === 'Enter') {
|
||
window.sendMessage();
|
||
}
|
||
};
|
||
|
||
// 打开图片选择器
|
||
window.openImagePicker = function () {
|
||
document.getElementById('imageInput').click();
|
||
};
|
||
|
||
// 处理图片上传
|
||
window.handleImageUpload = function (event) {
|
||
const file = event.target.files[0];
|
||
if (file) {
|
||
// 检查文件类型
|
||
if (!file.type.startsWith('image/')) {
|
||
showNotification('请选择图片文件', 3000);
|
||
return;
|
||
}
|
||
|
||
// 检查文件大小(限制为5MB)
|
||
if (file.size > 5 * 1024 * 1024) {
|
||
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 = '';
|
||
}
|
||
};
|
||
|
||
// 发送图片消息
|
||
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
|
||
};
|
||
|
||
store.addMessage(newMessage);
|
||
|
||
// 发送消息到服务器
|
||
// wsManager.send('send-message', newMessage);
|
||
}
|
||
|
||
// 键盘快捷键
|
||
document.addEventListener('keydown', (event) => {
|
||
// 空格键静音
|
||
if (event.code === 'Space' && !event.target.matches('input, textarea')) {
|
||
event.preventDefault();
|
||
window.toggleMute();
|
||
}
|
||
|
||
// Ctrl+V 切换视频
|
||
if (event.ctrlKey && event.key === 'v') {
|
||
event.preventDefault();
|
||
window.toggleVideo();
|
||
}
|
||
});
|
||
|
||
// 绑定对话框事件
|
||
document.getElementById('cancelEndCall').addEventListener('click', window.cancelEndCall);
|
||
document.getElementById('confirmEndCall').addEventListener('click', window.confirmEndCall);
|
||
|
||
// 绑定通话请求对话框事件
|
||
if (document.getElementById('rejectCall')) {
|
||
document.getElementById('rejectCall').addEventListener('click', window.rejectCall);
|
||
}
|
||
if (document.getElementById('acceptCall')) {
|
||
document.getElementById('acceptCall').addEventListener('click', window.acceptCall);
|
||
}
|
||
}
|
||
|
||
|
||
// 页面加载完成后初始化
|
||
window.addEventListener('DOMContentLoaded', async () => {
|
||
try {
|
||
// 检查本地存储中是否有连接ID
|
||
const connectionId = localStorage.getItem('connectionId');
|
||
|
||
if (!connectionId) {
|
||
// 如果没有连接ID,跳转到连接界面
|
||
window.location.href = './connect/connect.html';
|
||
return;
|
||
}
|
||
|
||
// 初始化 store
|
||
//await store.init();
|
||
|
||
// 初始化渲染器
|
||
new UIRenderer(store);
|
||
|
||
// 加入通话
|
||
await store.joinCall(connectionId);
|
||
|
||
// 设置WebRTC连接
|
||
await store.setUp(connectionId);
|
||
|
||
// 绑定DOM事件
|
||
bindDomEvents();
|
||
|
||
// 绑定WebSocket事件
|
||
bindWebSocketEvents();
|
||
|
||
console.log('Video call app initialized successfully');
|
||
} catch (error) {
|
||
console.error('Error initializing app:', error);
|
||
showNotification('初始化失败,请刷新页面重试', 'error');
|
||
}
|
||
});
|
||
|
||
// 导出全局变量
|
||
export { store, renderer, apiClient, wsManager };
|