From 0c5fe6c14af23cb5c820d729388c4974bed526b4 Mon Sep 17 00:00:00 2001 From: Le Vivilet Date: Sun, 16 Aug 2026 10:36:53 +0000 Subject: [PATCH] feature: handle view events directly --- .../src/parts/CommandMap/CommandMap.ts | 4 ++- .../HandleMessagePort/HandleMessagePort.ts | 19 ++++++++++++-- .../diff-view/test/HandleMessagePort.test.ts | 26 ++++++++++++++++--- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/packages/diff-view/src/parts/CommandMap/CommandMap.ts b/packages/diff-view/src/parts/CommandMap/CommandMap.ts index d600f1f..74cea8d 100644 --- a/packages/diff-view/src/parts/CommandMap/CommandMap.ts +++ b/packages/diff-view/src/parts/CommandMap/CommandMap.ts @@ -47,6 +47,8 @@ import { showSearch } from '../ShowSearch/ShowSearch.ts' import { toggleDiffMode } from '../ToggleDiffMode/ToggleDiffMode.ts' import { toggleWhitespace } from '../ToggleWhitespace/ToggleWhitespace.ts' +const handleDirectMessagePort = (port: any): Promise => handleMessagePort(port, commandMap) + export const commandMap = { 'Diff.getCommandIds': getCommandIds, 'DiffView.create': Create2.create2, @@ -67,7 +69,7 @@ export const commandMap = { 'DiffView.handleCopy': wrapCommand(handleCopy), 'DiffView.handleCut': wrapCommand(handleCut), 'DiffView.handleInput': wrapCommand(handleInput), - 'DiffView.handleMessagePort': handleMessagePort, + 'DiffView.handleMessagePort': handleDirectMessagePort, 'DiffView.handlePaste': wrapCommand(handlePaste), 'DiffView.handleResize': wrapCommand(handleResize), 'DiffView.handleSashPointerDown': wrapCommand(handleSashPointerDown), diff --git a/packages/diff-view/src/parts/HandleMessagePort/HandleMessagePort.ts b/packages/diff-view/src/parts/HandleMessagePort/HandleMessagePort.ts index b9a1360..3d90e8e 100644 --- a/packages/diff-view/src/parts/HandleMessagePort/HandleMessagePort.ts +++ b/packages/diff-view/src/parts/HandleMessagePort/HandleMessagePort.ts @@ -1,7 +1,22 @@ import { PlainMessagePortRpc } from '@lvce-editor/rpc' +import { RendererWorker } from '@lvce-editor/rpc-registry' import * as RendererProcess from '../RendererProcess/RendererProcess.ts' -export const handleMessagePort = async (port: any): Promise => { - const rpc = await PlainMessagePortRpc.create({ commandMap: {}, messagePort: port }) +export const handleMessagePort = async (port: any, viewletCommandMap: Readonly>): Promise => { + const executeViewletCommand = async (uid: number, command: string, ...args: readonly any[]): Promise => { + const fn = viewletCommandMap[`DiffView.${command}`] + if (typeof fn !== 'function') { + throw new TypeError(`Viewlet command not found: ${command}`) + } + await fn(uid, ...args) + await RendererWorker.invoke('Viewlet.requestRender', uid) + } + + const rpc = await PlainMessagePortRpc.create({ + commandMap: { + 'Viewlet.executeViewletCommand': executeViewletCommand, + }, + messagePort: port, + }) RendererProcess.set(rpc) } diff --git a/packages/diff-view/test/HandleMessagePort.test.ts b/packages/diff-view/test/HandleMessagePort.test.ts index 8326cdf..13830ed 100644 --- a/packages/diff-view/test/HandleMessagePort.test.ts +++ b/packages/diff-view/test/HandleMessagePort.test.ts @@ -1,6 +1,6 @@ import { expect, jest, test } from '@jest/globals' -import { PlainMessagePortRpcParent } from '@lvce-editor/rpc' -import { RendererProcess as RendererProcessRegistry } from '@lvce-editor/rpc-registry' +import { createMockRpc, PlainMessagePortRpcParent } from '@lvce-editor/rpc' +import { RendererProcess as RendererProcessRegistry, RendererWorker } from '@lvce-editor/rpc-registry' import { handleMessagePort } from '../src/parts/HandleMessagePort/HandleMessagePort.ts' import * as RendererProcess from '../src/parts/RendererProcess/RendererProcess.ts' @@ -13,12 +13,32 @@ test('connects the view directly to the renderer process', async () => { commandMap: { 'Viewlet.queueCommands': queueCommands }, messagePort: port1, }) + const handleEvent = jest.fn(async (_uid: number, _value: string) => {}) - await handleMessagePort(port2) + await handleMessagePort(port2, { + 'DiffView.handleEvent': handleEvent, + }) expect(RendererProcess.isConnected()).toBe(true) await expect(RendererProcess.invoke('Viewlet.queueCommands', 7, [['Viewlet.setDom2', 7, []]])).resolves.toBe(31) expect(queueCommands).toHaveBeenCalledWith(7, [['Viewlet.setDom2', 7, []]]) + const requestRender = jest.fn(async (_uid: number) => {}) + RendererWorker.set( + Object.assign( + createMockRpc({ + commandMap: { + 'Viewlet.requestRender': requestRender, + }, + }), + { dispose: jest.fn() }, + ), + ) + await rendererProcessRpc.invoke('Viewlet.executeViewletCommand', 7, 'handleEvent', 'hello') + expect(handleEvent).toHaveBeenCalledWith(7, 'hello') + expect(requestRender).toHaveBeenCalledWith(7) + await expect(rendererProcessRpc.invoke('Viewlet.executeViewletCommand', 7, 'missing')).rejects.toThrow('Viewlet command not found: missing') + await RendererProcessRegistry.dispose() + await RendererWorker.dispose() await rendererProcessRpc.dispose() })