From a0dd3d7ac642111faeaefd02c5a452898b9c6d49 Mon Sep 17 00:00:00 2001 From: haoyuren <13851610112@163.com> Date: Thu, 12 Mar 2026 18:11:10 -0500 Subject: Add collaborator cursors and project chat Collaborator cursors: - Real-time cursor positions via clientTracking Socket.IO events - CM6 extension renders colored cursor widgets with name labels - Throttled cursor position broadcasting (300ms) - Connected users count in toolbar and status bar Project chat: - Chat panel in right sidebar (toggleable) - Load message history via REST API - Send messages with real-time delivery via Socket.IO new-chat-message - Auto-scroll, avatars, timestamps Co-Authored-By: Claude Opus 4.6 --- src/preload/index.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src/preload') diff --git a/src/preload/index.ts b/src/preload/index.ts index 5dcbbff..ca7f098 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -144,6 +144,33 @@ const api = { syncContentChanged: (docId: string, content: string) => ipcRenderer.invoke('sync:contentChanged', docId, content), + // Cursor tracking + cursorUpdate: (docId: string, row: number, column: number) => + ipcRenderer.invoke('cursor:update', docId, row, column), + cursorGetConnectedUsers: () => + ipcRenderer.invoke('cursor:getConnectedUsers') as Promise, + onCursorRemoteUpdate: (cb: (data: unknown) => void) => { + const handler = (_e: Electron.IpcRendererEvent, data: unknown) => cb(data) + ipcRenderer.on('cursor:remoteUpdate', handler) + return () => ipcRenderer.removeListener('cursor:remoteUpdate', handler) + }, + onCursorRemoteDisconnected: (cb: (clientId: string) => void) => { + const handler = (_e: Electron.IpcRendererEvent, clientId: string) => cb(clientId) + ipcRenderer.on('cursor:remoteDisconnected', handler) + return () => ipcRenderer.removeListener('cursor:remoteDisconnected', handler) + }, + + // Chat + chatGetMessages: (projectId: string, limit?: number) => + ipcRenderer.invoke('chat:getMessages', projectId, limit) as Promise<{ success: boolean; messages: unknown[] }>, + chatSendMessage: (projectId: string, content: string) => + ipcRenderer.invoke('chat:sendMessage', projectId, content) as Promise<{ success: boolean }>, + onChatMessage: (cb: (msg: unknown) => void) => { + const handler = (_e: Electron.IpcRendererEvent, msg: unknown) => cb(msg) + ipcRenderer.on('chat:newMessage', handler) + return () => ipcRenderer.removeListener('chat:newMessage', handler) + }, + // Shell openExternal: (url: string) => ipcRenderer.invoke('shell:openExternal', url), showInFinder: (path: string) => ipcRenderer.invoke('shell:showInFinder', path) -- cgit v1.2.3