【m】优化拆分,拆分为多个脚本
This commit is contained in:
146
WebApp/client/public/onebyone/store.js
Normal file
146
WebApp/client/public/onebyone/store.js
Normal file
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* 状态管理
|
||||
* 使用简单的 Observable 模式,可替换为 Redux/Vuex/Pinia
|
||||
*/
|
||||
import { mockCallSession, mockMessages } from './models.js';
|
||||
|
||||
class CallStateManager {
|
||||
constructor() {
|
||||
// 核心状态
|
||||
this.state = {
|
||||
session: { ...mockCallSession },
|
||||
messages: [...mockMessages],
|
||||
isSidebarOpen: false,
|
||||
unreadCount: 0,
|
||||
localStream: null, // MediaStream 对象
|
||||
remoteStream: null // MediaStream 对象
|
||||
};
|
||||
|
||||
// 监听器数组
|
||||
this.listeners = [];
|
||||
|
||||
// 初始化
|
||||
this.init();
|
||||
}
|
||||
|
||||
// 订阅状态变化
|
||||
subscribe(callback) {
|
||||
this.listeners.push(callback);
|
||||
return () => {
|
||||
this.listeners = this.listeners.filter(cb => cb !== callback);
|
||||
};
|
||||
}
|
||||
|
||||
// 通知所有监听器
|
||||
notify(changes) {
|
||||
this.listeners.forEach(cb => cb(this.state, changes));
|
||||
}
|
||||
|
||||
// 初始化
|
||||
init() {
|
||||
// 启动通话时长计时器
|
||||
this.durationInterval = setInterval(() => {
|
||||
this.state.session.duration++;
|
||||
this.notify({ type: 'DURATION_UPDATE', duration: this.state.session.duration });
|
||||
}, 1000);
|
||||
|
||||
// 模拟远端音频活动 (实际应由 WebRTC VAD 检测触发)
|
||||
this.simulateRemoteActivity();
|
||||
|
||||
// 模拟网络质量变化
|
||||
this.simulateNetworkChange();
|
||||
}
|
||||
|
||||
// 更新本地媒体状态
|
||||
updateLocalMedia(mediaType, value) {
|
||||
this.state.session.localUser.mediaState[mediaType] = value;
|
||||
this.notify({ type: 'LOCAL_MEDIA_CHANGE', mediaType, value });
|
||||
|
||||
// 发送媒体状态到服务器
|
||||
this.emitMediaStateChange();
|
||||
}
|
||||
|
||||
// 更新远端媒体状态 (由 WebSocket 消息触发)
|
||||
updateRemoteMedia(mediaState) {
|
||||
this.state.session.remoteUser.mediaState = {
|
||||
...this.state.session.remoteUser.mediaState,
|
||||
...mediaState
|
||||
};
|
||||
this.notify({ type: 'REMOTE_MEDIA_CHANGE', mediaState });
|
||||
}
|
||||
|
||||
// 添加消息
|
||||
addMessage(message) {
|
||||
this.state.messages.push(message);
|
||||
|
||||
// 如果侧边栏关闭且不是自己发的,增加未读
|
||||
if (!this.state.isSidebarOpen && !message.isSelf) {
|
||||
this.state.unreadCount++;
|
||||
}
|
||||
|
||||
this.notify({ type: 'NEW_MESSAGE', message, unreadCount: this.state.unreadCount });
|
||||
}
|
||||
|
||||
// 切换侧边栏
|
||||
toggleSidebar() {
|
||||
this.state.isSidebarOpen = !this.state.isSidebarOpen;
|
||||
if (this.state.isSidebarOpen) {
|
||||
this.state.unreadCount = 0;
|
||||
}
|
||||
this.notify({ type: 'SIDEBAR_TOGGLE', isOpen: this.state.isSidebarOpen });
|
||||
}
|
||||
|
||||
// 结束通话
|
||||
endCall() {
|
||||
clearInterval(this.durationInterval);
|
||||
this.state.session.status = 'ended';
|
||||
this.notify({ type: 'CALL_ENDED' });
|
||||
|
||||
// 发送结束通话请求到服务器
|
||||
// [API_CALL: POST /api/call/:callId/leave]
|
||||
// [WEBSOCKET_EMIT: leave-call]
|
||||
}
|
||||
|
||||
// 模拟远端活动 (开发测试用)
|
||||
simulateRemoteActivity() {
|
||||
setInterval(() => {
|
||||
if (Math.random() > 0.7) {
|
||||
const isSpeaking = Math.random() > 0.5;
|
||||
this.updateRemoteMedia({ isSpeaking });
|
||||
}
|
||||
}, 800);
|
||||
}
|
||||
|
||||
// 模拟网络质量变化 (开发测试用)
|
||||
simulateNetworkChange() {
|
||||
const qualities = ['excellent', 'good', 'fair', 'poor'];
|
||||
setInterval(() => {
|
||||
if (Math.random() > 0.8) {
|
||||
const quality = qualities[Math.floor(Math.random() * qualities.length)];
|
||||
this.state.session.remoteUser.networkQuality = quality;
|
||||
this.notify({ type: 'NETWORK_CHANGE', quality });
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
// 发送媒体状态到服务器
|
||||
emitMediaStateChange() {
|
||||
const payload = {
|
||||
userId: this.state.session.localUser.id,
|
||||
...this.state.session.localUser.mediaState
|
||||
};
|
||||
console.log('[WebSocket Emit] media-state-changed:', payload);
|
||||
// socket.emit('media-state-changed', payload);
|
||||
}
|
||||
|
||||
// Getters
|
||||
getState() { return this.state; }
|
||||
getLocalUser() { return this.state.session.localUser; }
|
||||
getRemoteUser() { return this.state.session.remoteUser; }
|
||||
getMessages() { return this.state.messages; }
|
||||
}
|
||||
|
||||
// 创建单例实例
|
||||
const store = new CallStateManager();
|
||||
|
||||
export default store;
|
||||
Reference in New Issue
Block a user