@@ -6,10 +6,7 @@ import type {
|
|||||||
events as mainEvents,
|
events as mainEvents,
|
||||||
handlers as mainHandlers,
|
handlers as mainHandlers,
|
||||||
} from '@affine/electron/main/exposed';
|
} from '@affine/electron/main/exposed';
|
||||||
import type {
|
import type { appInfo as exposedAppInfo } from '@affine/electron/preload/electron-api';
|
||||||
affine as exposedAffineGlobal,
|
|
||||||
appInfo as exposedAppInfo,
|
|
||||||
} from '@affine/electron/preload/electron-api';
|
|
||||||
import type { sharedStorage as exposedSharedStorage } from '@affine/electron/preload/shared-storage';
|
import type { sharedStorage as exposedSharedStorage } from '@affine/electron/preload/shared-storage';
|
||||||
|
|
||||||
type MainHandlers = typeof mainHandlers;
|
type MainHandlers = typeof mainHandlers;
|
||||||
@@ -37,9 +34,7 @@ export const appInfo = (globalThis as any).appInfo as
|
|||||||
| null;
|
| null;
|
||||||
export const apis = (globalThis as any).apis as ClientHandler | null;
|
export const apis = (globalThis as any).apis as ClientHandler | null;
|
||||||
export const events = (globalThis as any).events as ClientEvents | null;
|
export const events = (globalThis as any).events as ClientEvents | null;
|
||||||
export const affine = (globalThis as any).affine as
|
|
||||||
| typeof exposedAffineGlobal
|
|
||||||
| null;
|
|
||||||
export const sharedStorage = (globalThis as any).sharedStorage as
|
export const sharedStorage = (globalThis as any).sharedStorage as
|
||||||
| typeof exposedSharedStorage
|
| typeof exposedSharedStorage
|
||||||
| null;
|
| null;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { contextBridge } from 'electron';
|
import { contextBridge } from 'electron';
|
||||||
|
|
||||||
import { affine, appInfo, getElectronAPIs } from './electron-api';
|
import { appInfo, getElectronAPIs } from './electron-api';
|
||||||
import { sharedStorage } from './shared-storage';
|
import { sharedStorage } from './shared-storage';
|
||||||
|
|
||||||
const { apis, events } = getElectronAPIs();
|
const { apis, events } = getElectronAPIs();
|
||||||
@@ -9,9 +9,3 @@ contextBridge.exposeInMainWorld('appInfo', appInfo);
|
|||||||
contextBridge.exposeInMainWorld('apis', apis);
|
contextBridge.exposeInMainWorld('apis', apis);
|
||||||
contextBridge.exposeInMainWorld('events', events);
|
contextBridge.exposeInMainWorld('events', events);
|
||||||
contextBridge.exposeInMainWorld('sharedStorage', sharedStorage);
|
contextBridge.exposeInMainWorld('sharedStorage', sharedStorage);
|
||||||
|
|
||||||
try {
|
|
||||||
contextBridge.exposeInMainWorld('affine', affine);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Failed to expose affine APIs to window object!', error);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -11,42 +11,6 @@ import type {
|
|||||||
RendererToHelper,
|
RendererToHelper,
|
||||||
} from '../shared/type';
|
} from '../shared/type';
|
||||||
|
|
||||||
export const affine = {
|
|
||||||
ipcRenderer: {
|
|
||||||
send(channel: string, ...args: any[]) {
|
|
||||||
ipcRenderer.send(channel, ...args);
|
|
||||||
},
|
|
||||||
|
|
||||||
invoke(channel: string, ...args: any[]) {
|
|
||||||
return ipcRenderer.invoke(channel, ...args);
|
|
||||||
},
|
|
||||||
|
|
||||||
on(
|
|
||||||
channel: string,
|
|
||||||
listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void
|
|
||||||
) {
|
|
||||||
ipcRenderer.on(channel, listener);
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
once(
|
|
||||||
channel: string,
|
|
||||||
listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void
|
|
||||||
) {
|
|
||||||
ipcRenderer.once(channel, listener);
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
|
|
||||||
removeListener(
|
|
||||||
channel: string,
|
|
||||||
listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void
|
|
||||||
) {
|
|
||||||
ipcRenderer.removeListener(channel, listener);
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export function getElectronAPIs() {
|
export function getElectronAPIs() {
|
||||||
const mainAPIs = getMainAPIs();
|
const mainAPIs = getMainAPIs();
|
||||||
const helperAPIs = getHelperAPIs();
|
const helperAPIs = getHelperAPIs();
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
import os from 'node:os';
|
|
||||||
|
|
||||||
import { test } from '@affine-test/kit/electron';
|
|
||||||
import { shouldCallIpcRendererHandler } from '@affine-test/kit/utils/ipc';
|
|
||||||
|
|
||||||
test.describe.skip('behavior test', () => {
|
|
||||||
if (os.platform() === 'darwin') {
|
|
||||||
test('system button should hidden correctly', async ({
|
|
||||||
page,
|
|
||||||
electronApp,
|
|
||||||
}) => {
|
|
||||||
{
|
|
||||||
const promise = shouldCallIpcRendererHandler(
|
|
||||||
electronApp,
|
|
||||||
'ui:handleSidebarVisibilityChange'
|
|
||||||
);
|
|
||||||
await page
|
|
||||||
.locator(
|
|
||||||
'[data-testid=app-sidebar-arrow-button-collapse][data-show=true]'
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
await promise;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
const promise = shouldCallIpcRendererHandler(
|
|
||||||
electronApp,
|
|
||||||
'ui:handleSidebarVisibilityChange'
|
|
||||||
);
|
|
||||||
await page
|
|
||||||
.locator(
|
|
||||||
'[data-testid=app-sidebar-arrow-button-expand][data-show=true]'
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
await promise;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
// TODO(@pengx17): remove
|
|
||||||
|
|
||||||
import type { affine } from '@affine/electron-api';
|
|
||||||
// Credit: https://github.com/spaceagetv/electron-playwright-helpers/blob/main/src/ipc_helpers.ts
|
|
||||||
import type { Page } from '@playwright/test';
|
|
||||||
import type { ElectronApplication } from 'playwright';
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
affine: typeof affine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ipcRendererInvoke(page: Page, channel: string, ...args: any[]) {
|
|
||||||
return page.evaluate(
|
|
||||||
({ channel, args }) => {
|
|
||||||
return window.affine?.ipcRenderer.invoke(channel, ...args);
|
|
||||||
},
|
|
||||||
{ channel, args }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ipcRendererSend(page: Page, channel: string, ...args: any[]) {
|
|
||||||
return page.evaluate(
|
|
||||||
({ channel, args }) => {
|
|
||||||
window.affine?.ipcRenderer.send(channel, ...args);
|
|
||||||
},
|
|
||||||
{ channel, args }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
type IpcMainWithHandlers = Electron.IpcMain & {
|
|
||||||
_invokeHandlers: Map<
|
|
||||||
string,
|
|
||||||
(e: Electron.IpcMainInvokeEvent, ...args: unknown[]) => Promise<unknown>
|
|
||||||
>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function shouldCallIpcRendererHandler(
|
|
||||||
electronApp: ElectronApplication,
|
|
||||||
channel: string
|
|
||||||
) {
|
|
||||||
return electronApp.evaluate(
|
|
||||||
async ({ ipcMain }, { channel }) => {
|
|
||||||
const ipcMainWH = ipcMain as IpcMainWithHandlers;
|
|
||||||
// this is all a bit of a hack, so let's test as we go
|
|
||||||
if (!ipcMainWH._invokeHandlers) {
|
|
||||||
throw new Error(`Cannot access ipcMain._invokeHandlers`);
|
|
||||||
}
|
|
||||||
const handler = ipcMainWH._invokeHandlers.get(channel);
|
|
||||||
if (!handler) {
|
|
||||||
throw new Error(`No ipcMain handler registered for '${channel}'`);
|
|
||||||
}
|
|
||||||
return new Promise<void>(resolve => {
|
|
||||||
ipcMainWH._invokeHandlers.set(channel, async (e, ...args) => {
|
|
||||||
ipcMainWH._invokeHandlers.set(channel, handler);
|
|
||||||
resolve();
|
|
||||||
return handler(e, ...args);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
{ channel }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user