mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-04 11:49:02 +08:00
- Added deprecation notices to various services and components, indicating they are scheduled for removal in v2.0.0. - Noted that feature PRs affecting these files are currently blocked, and only critical bug fixes will be accepted during the migration phase. - Provided context and status links for ongoing v2 refactoring efforts. This change is part of the preparation for the upcoming major version update.
150 lines
4.7 KiB
TypeScript
150 lines
4.7 KiB
TypeScript
/**
|
|
* @deprecated Scheduled for removal in v2.0.0
|
|
* --------------------------------------------------------------------------
|
|
* ⚠️ NOTICE: V2 DATA&UI REFACTORING (by 0xfullex)
|
|
* --------------------------------------------------------------------------
|
|
* STOP: Feature PRs affecting this file are currently BLOCKED.
|
|
* Only critical bug fixes are accepted during this migration phase.
|
|
*
|
|
* This file is being refactored to v2 standards.
|
|
* Any non-critical changes will conflict with the ongoing work.
|
|
*
|
|
* 🔗 Context & Status:
|
|
* - Contribution Hold: https://github.com/CherryHQ/cherry-studio/issues/10954
|
|
* - v2 Refactor PR : https://github.com/CherryHQ/cherry-studio/pull/10162
|
|
* --------------------------------------------------------------------------
|
|
*/
|
|
import { IpcChannel } from '@shared/IpcChannel'
|
|
import type { StoreSyncAction } from '@types'
|
|
import { BrowserWindow, ipcMain } from 'electron'
|
|
|
|
/**
|
|
* StoreSyncService class manages Redux store synchronization between multiple windows in the main process
|
|
* It uses singleton pattern to ensure only one sync service instance exists in the application
|
|
*
|
|
* Main features:
|
|
* 1. Manages window subscriptions for store sync
|
|
* 2. Handles IPC communication for store sync between windows
|
|
* 3. Broadcasts Redux actions from one window to all other windows
|
|
* 4. Adds metadata to synced actions to prevent infinite sync loops
|
|
*/
|
|
export class StoreSyncService {
|
|
private static instance: StoreSyncService
|
|
private windowIds: number[] = []
|
|
private isIpcHandlerRegistered = false
|
|
|
|
private constructor() {
|
|
return
|
|
}
|
|
|
|
/**
|
|
* Get the singleton instance of StoreSyncService
|
|
*/
|
|
public static getInstance(): StoreSyncService {
|
|
if (!StoreSyncService.instance) {
|
|
StoreSyncService.instance = new StoreSyncService()
|
|
}
|
|
return StoreSyncService.instance
|
|
}
|
|
|
|
/**
|
|
* Subscribe a window to store sync
|
|
* @param windowId ID of the window to subscribe
|
|
*/
|
|
public subscribe(windowId: number): void {
|
|
if (!this.windowIds.includes(windowId)) {
|
|
this.windowIds.push(windowId)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Unsubscribe a window from store sync
|
|
* @param windowId ID of the window to unsubscribe
|
|
*/
|
|
public unsubscribe(windowId: number): void {
|
|
this.windowIds = this.windowIds.filter((id) => id !== windowId)
|
|
}
|
|
|
|
/**
|
|
* Sync an action to all renderer windows
|
|
* @param type Action type, like 'settings/setTray'
|
|
* @param payload Action payload
|
|
*
|
|
* NOTICE: DO NOT use directly in ConfigManager, may cause infinite sync loop
|
|
*/
|
|
public syncToRenderer(type: string, payload: any): void {
|
|
const action: StoreSyncAction = {
|
|
type,
|
|
payload
|
|
}
|
|
|
|
//-1 means the action is from the main process, will be broadcast to all windows
|
|
this.broadcastToOtherWindows(-1, action)
|
|
}
|
|
|
|
/**
|
|
* Register IPC handlers for store sync communication
|
|
* Handles window subscription, unsubscription and action broadcasting
|
|
*/
|
|
public registerIpcHandler(): void {
|
|
if (this.isIpcHandlerRegistered) return
|
|
|
|
ipcMain.handle(IpcChannel.StoreSync_Subscribe, (event) => {
|
|
const windowId = BrowserWindow.fromWebContents(event.sender)?.id
|
|
if (windowId) {
|
|
this.subscribe(windowId)
|
|
}
|
|
})
|
|
|
|
ipcMain.handle(IpcChannel.StoreSync_Unsubscribe, (event) => {
|
|
const windowId = BrowserWindow.fromWebContents(event.sender)?.id
|
|
if (windowId) {
|
|
this.unsubscribe(windowId)
|
|
}
|
|
})
|
|
|
|
ipcMain.handle(IpcChannel.StoreSync_OnUpdate, (event, action: StoreSyncAction) => {
|
|
const sourceWindowId = BrowserWindow.fromWebContents(event.sender)?.id
|
|
|
|
if (!sourceWindowId) return
|
|
|
|
// Broadcast the action to all other windows
|
|
this.broadcastToOtherWindows(sourceWindowId, action)
|
|
})
|
|
|
|
this.isIpcHandlerRegistered = true
|
|
}
|
|
|
|
/**
|
|
* Broadcast a Redux action to all other windows except the source
|
|
* @param sourceWindowId ID of the window that originated the action
|
|
* @param action Redux action to broadcast
|
|
*/
|
|
private broadcastToOtherWindows(sourceWindowId: number, action: StoreSyncAction): void {
|
|
// Add metadata to indicate this action came from sync
|
|
const syncAction = {
|
|
...action,
|
|
meta: {
|
|
...action.meta,
|
|
fromSync: true,
|
|
source: `windowId:${sourceWindowId}`
|
|
}
|
|
}
|
|
|
|
// Send to all windows except the source
|
|
this.windowIds.forEach((windowId) => {
|
|
if (windowId !== sourceWindowId) {
|
|
const targetWindow = BrowserWindow.fromId(windowId)
|
|
if (targetWindow && !targetWindow.isDestroyed()) {
|
|
targetWindow.webContents.send(IpcChannel.StoreSync_BroadcastSync, syncAction)
|
|
} else {
|
|
this.unsubscribe(windowId)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Export singleton instance
|
|
export default StoreSyncService.getInstance()
|