Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { invokeMainEvent, onRendererEvent, sendMainEvent } from './utils';
/**
* The Gitify Bridge API exposed to the renderer via `contextBridge`.
*
* All renderer↔main IPC communication must go through this object.
* It is available on `window.gitify` inside the renderer process.
* Provides a safe, sandboxed interface for IPC communication between renderer and main.
* Accessible as `window.gitify` in the renderer.
*/
export const api = {
/**
Expand Down Expand Up @@ -118,7 +118,6 @@ export const api = {
*/
twemojiDirectory: () => invokeMainEvent(EVENTS.TWEMOJI_DIRECTORY),

/** Platform detection helpers. */
/** Platform detection helpers. */
platform: {
/** Returns `true` when running on Linux. */
Expand Down Expand Up @@ -161,7 +160,7 @@ export const api = {
},
},

/** Electron web frame zoom controls. */
/** Electron `webFrame` zoom controls. */
zoom: {
/**
* Return the current Electron zoom level.
Expand Down Expand Up @@ -231,8 +230,10 @@ export const api = {
},
};

// Use `contextBridge` APIs to expose Electron APIs to renderer
// Context isolation is always enabled in this app
/**
* Use `contextBridge` APIs to expose Electron APIs to renderer.
* Context isolation is always enabled in this app
*/
try {
contextBridge.exposeInMainWorld('gitify', api);
} catch (error) {
Expand Down
3 changes: 3 additions & 0 deletions src/preload/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { ipcRenderer } from 'electron';
describe('preload/utils', () => {
it('sendMainEvent forwards to ipcRenderer.send', () => {
sendMainEvent(EVENTS.WINDOW_SHOW);

expect(ipcRenderer.send).toHaveBeenCalledWith(
EVENTS.WINDOW_SHOW,
undefined,
Expand All @@ -39,6 +40,7 @@ describe('preload/utils', () => {

it('invokeMainEvent forwards and resolves', async () => {
const result = await invokeMainEvent(EVENTS.VERSION, 'data');

expect(ipcRenderer.invoke).toHaveBeenCalledWith(EVENTS.VERSION, 'data');
expect(result).toBe('response');
});
Expand All @@ -57,6 +59,7 @@ describe('preload/utils', () => {
__emit: (channel: string, ...a: unknown[]) => void;
}
).__emit(EVENTS.UPDATE_ICON_TITLE, 'payload');

expect(ipcRenderer.on).toHaveBeenCalledWith(
EVENTS.UPDATE_ICON_TITLE,
handlerMock,
Expand Down
10 changes: 8 additions & 2 deletions src/preload/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ export function sendMainEvent(event: EventType, data?: EventData): void {
* @param data - Optional string payload to include with the event.
* @returns A promise that resolves to the string response from the main process.
*/
export function invokeMainEvent(
export async function invokeMainEvent(
event: EventType,
data?: string,
): Promise<string> {
return ipcRenderer.invoke(event, data);
try {
return await ipcRenderer.invoke(event, data);
} catch (err) {
// biome-ignore lint/suspicious/noConsole: preload environment is strictly sandboxed
console.error(`[IPC] invoke failed: ${event}`, err);
throw err;
}
}

/**
Expand Down
Loading