Skip to content

Commit 36934bc

Browse files
committed
refactor(main): organize main structure
Signed-off-by: Adam Setch <adam.setch@outlook.com>
1 parent 98ea71b commit 36934bc

21 files changed

Lines changed: 229 additions & 79 deletions

src/main/events.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,40 +25,48 @@ describe('main/events', () => {
2525

2626
it('onMainEvent registers ipcMain.on listener', () => {
2727
const listenerMock = vi.fn();
28+
2829
onMainEvent(
2930
EVENTS.WINDOW_SHOW,
3031
listenerMock as unknown as (e: Electron.IpcMainEvent, d: unknown) => void,
3132
);
33+
3234
expect(onMock).toHaveBeenCalledWith(EVENTS.WINDOW_SHOW, listenerMock);
3335
});
3436

3537
it('handleMainEvent registers ipcMain.handle listener', () => {
3638
const listenerMock = vi.fn();
39+
3740
handleMainEvent(
3841
EVENTS.VERSION,
3942
listenerMock as unknown as (
4043
e: Electron.IpcMainInvokeEvent,
4144
d: unknown,
4245
) => void,
4346
);
47+
4448
expect(handleMock).toHaveBeenCalledWith(EVENTS.VERSION, listenerMock);
4549
});
4650

4751
it('sendRendererEvent forwards event to webContents with data', () => {
4852
const sendMock = vi.fn();
4953
const mb: MockMenubar = { window: { webContents: { send: sendMock } } };
54+
5055
sendRendererEvent(
5156
mb as unknown as Menubar,
5257
EVENTS.UPDATE_ICON_TITLE,
5358
'title',
5459
);
60+
5561
expect(sendMock).toHaveBeenCalledWith(EVENTS.UPDATE_ICON_TITLE, 'title');
5662
});
5763

5864
it('sendRendererEvent forwards event without data', () => {
5965
const sendMock = vi.fn();
6066
const mb: MockMenubar = { window: { webContents: { send: sendMock } } };
67+
6168
sendRendererEvent(mb as unknown as Menubar, EVENTS.RESET_APP);
69+
6270
expect(sendMock).toHaveBeenCalledWith(EVENTS.RESET_APP, undefined);
6371
});
6472
});

src/main/events.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import type { Menubar } from 'menubar';
44
import type { EventData, EventType } from '../shared/events';
55

66
/**
7-
* Handle main event without expecting a response
8-
* @param event
9-
* @param listener
7+
* Register a fire-and-forget IPC listener on the main process (ipcMain.on).
8+
* Use this when the renderer sends a one-way message and no return value is needed.
9+
*
10+
* @param event - The IPC channel/event name to listen on.
11+
* @param listener - Callback invoked when the event is received.
1012
*/
1113
export function onMainEvent(
1214
event: EventType,
@@ -16,9 +18,11 @@ export function onMainEvent(
1618
}
1719

1820
/**
19-
* Handle main event and return a response
20-
* @param event
21-
* @param listener
21+
* Register a request/response IPC handler on the main process (ipcMain.handle).
22+
* Use this when the renderer invokes a channel and expects a value back.
23+
*
24+
* @param event - The IPC channel/event name to handle.
25+
* @param listener - Callback whose return value is sent back to the renderer.
2226
*/
2327
export function handleMainEvent(
2428
event: EventType,
@@ -28,10 +32,11 @@ export function handleMainEvent(
2832
}
2933

3034
/**
31-
* Send main event to renderer
32-
* @param mb the menubar instance
33-
* @param event the type of event to send
34-
* @param data the data to send with the event
35+
* Push an event from the main process to the renderer via webContents.
36+
*
37+
* @param mb - The menubar instance whose window receives the event.
38+
* @param event - The IPC channel/event name to emit.
39+
* @param data - Optional payload sent with the event.
3540
*/
3641
export function sendRendererEvent(
3742
mb: Menubar,

src/main/handlers/app.test.ts

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,27 @@ describe('main/handlers/app.ts', () => {
3737
} as unknown as Menubar;
3838
});
3939

40-
it('registers handlers without throwing', () => {
41-
expect(() => registerAppHandlers(menubar)).not.toThrow();
42-
});
43-
44-
it('registers VERSION, NOTIFICATION_SOUND_PATH, TWEMOJI_DIRECTORY, WINDOW_SHOW, WINDOW_HIDE, and QUIT handlers', () => {
45-
registerAppHandlers(menubar);
46-
47-
const registeredHandlers = handleMock.mock.calls.map(
48-
(call: [string]) => call[0],
49-
);
50-
const registeredEvents = onMock.mock.calls.map((call: [string]) => call[0]);
51-
52-
expect(registeredHandlers).toContain(EVENTS.VERSION);
53-
expect(registeredHandlers).toContain(EVENTS.NOTIFICATION_SOUND_PATH);
54-
expect(registeredHandlers).toContain(EVENTS.TWEMOJI_DIRECTORY);
55-
expect(registeredEvents).toContain(EVENTS.WINDOW_SHOW);
56-
expect(registeredEvents).toContain(EVENTS.WINDOW_HIDE);
57-
expect(registeredEvents).toContain(EVENTS.QUIT);
40+
describe('registerAppHandlers', () => {
41+
it('registers handlers without throwing', () => {
42+
expect(() => registerAppHandlers(menubar)).not.toThrow();
43+
});
44+
45+
it('registers expected app IPC event handlers', () => {
46+
registerAppHandlers(menubar);
47+
48+
const registeredHandlers = handleMock.mock.calls.map(
49+
(call: [string]) => call[0],
50+
);
51+
const registeredEvents = onMock.mock.calls.map(
52+
(call: [string]) => call[0],
53+
);
54+
55+
expect(registeredHandlers).toContain(EVENTS.VERSION);
56+
expect(registeredHandlers).toContain(EVENTS.NOTIFICATION_SOUND_PATH);
57+
expect(registeredHandlers).toContain(EVENTS.TWEMOJI_DIRECTORY);
58+
expect(registeredEvents).toContain(EVENTS.WINDOW_SHOW);
59+
expect(registeredEvents).toContain(EVENTS.WINDOW_HIDE);
60+
expect(registeredEvents).toContain(EVENTS.QUIT);
61+
});
5862
});
5963
});

src/main/handlers/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export * from './app';
2+
export * from './storage';
3+
export * from './system';
4+
export * from './tray';

src/main/handlers/storage.test.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,20 @@ describe('main/handlers/storage.ts', () => {
2424
vi.clearAllMocks();
2525
});
2626

27-
it('registers handlers without throwing', () => {
28-
expect(() => registerStorageHandlers()).not.toThrow();
29-
});
27+
describe('registerStorageHandlers', () => {
28+
it('registers handlers without throwing', () => {
29+
expect(() => registerStorageHandlers()).not.toThrow();
30+
});
3031

31-
it('registers SAFE_STORAGE_ENCRYPT and SAFE_STORAGE_DECRYPT handlers', () => {
32-
registerStorageHandlers();
32+
it('registers expected storage IPC event handlers', () => {
33+
registerStorageHandlers();
3334

34-
const registeredHandlers = handleMock.mock.calls.map(
35-
(call: [string]) => call[0],
36-
);
35+
const registeredHandlers = handleMock.mock.calls.map(
36+
(call: [string]) => call[0],
37+
);
3738

38-
expect(registeredHandlers).toContain(EVENTS.SAFE_STORAGE_ENCRYPT);
39-
expect(registeredHandlers).toContain(EVENTS.SAFE_STORAGE_DECRYPT);
39+
expect(registeredHandlers).toContain(EVENTS.SAFE_STORAGE_ENCRYPT);
40+
expect(registeredHandlers).toContain(EVENTS.SAFE_STORAGE_DECRYPT);
41+
});
4042
});
4143
});

src/main/handlers/system.test.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,21 @@ describe('main/handlers/system.ts', () => {
3737
} as unknown as Menubar;
3838
});
3939

40-
it('registers handlers without throwing', () => {
41-
expect(() => registerSystemHandlers(menubar)).not.toThrow();
42-
});
43-
44-
it('registers expected IPC event handlers', () => {
45-
registerSystemHandlers(menubar);
46-
47-
const registeredEvents = onMock.mock.calls.map((call: [string]) => call[0]);
48-
49-
expect(registeredEvents).toContain(EVENTS.OPEN_EXTERNAL);
50-
expect(registeredEvents).toContain(EVENTS.UPDATE_KEYBOARD_SHORTCUT);
51-
expect(registeredEvents).toContain(EVENTS.UPDATE_AUTO_LAUNCH);
40+
describe('registerSystemHandlers', () => {
41+
it('registers handlers without throwing', () => {
42+
expect(() => registerSystemHandlers(menubar)).not.toThrow();
43+
});
44+
45+
it('registers expected system IPC event handlers', () => {
46+
registerSystemHandlers(menubar);
47+
48+
const registeredEvents = onMock.mock.calls.map(
49+
(call: [string]) => call[0],
50+
);
51+
52+
expect(registeredEvents).toContain(EVENTS.OPEN_EXTERNAL);
53+
expect(registeredEvents).toContain(EVENTS.UPDATE_KEYBOARD_SHORTCUT);
54+
expect(registeredEvents).toContain(EVENTS.UPDATE_AUTO_LAUNCH);
55+
});
5256
});
5357
});

src/main/handlers/tray.test.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,23 @@ describe('main/handlers/tray.ts', () => {
3131
} as unknown as Menubar;
3232
});
3333

34-
it('registers handlers without throwing', () => {
35-
expect(() => registerTrayHandlers(menubar)).not.toThrow();
36-
});
37-
38-
it('registers expected IPC event handlers', () => {
39-
registerTrayHandlers(menubar);
40-
41-
const registeredEvents = onMock.mock.calls.map((call: [string]) => call[0]);
42-
43-
expect(registeredEvents).toContain(EVENTS.USE_ALTERNATE_IDLE_ICON);
44-
expect(registeredEvents).toContain(EVENTS.USE_UNREAD_ACTIVE_ICON);
45-
expect(registeredEvents).toContain(EVENTS.UPDATE_ICON_COLOR);
46-
expect(registeredEvents).toContain(EVENTS.UPDATE_ICON_TITLE);
34+
describe('registerTrayHandlers', () => {
35+
it('registers handlers without throwing', () => {
36+
expect(() => registerTrayHandlers(menubar)).not.toThrow();
37+
});
38+
39+
it('registers expected tray IPC event handlers', () => {
40+
registerTrayHandlers(menubar);
41+
42+
const registeredEvents = onMock.mock.calls.map(
43+
(call: [string]) => call[0],
44+
);
45+
46+
expect(registeredEvents).toContain(EVENTS.USE_ALTERNATE_IDLE_ICON);
47+
expect(registeredEvents).toContain(EVENTS.USE_UNREAD_ACTIVE_ICON);
48+
expect(registeredEvents).toContain(EVENTS.UPDATE_ICON_COLOR);
49+
expect(registeredEvents).toContain(EVENTS.UPDATE_ICON_TITLE);
50+
});
4751
});
4852

4953
it('skips tray updates when tray is destroyed', () => {

src/main/handlers/tray.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { TrayIcons } from '../icons';
99
let shouldUseAlternateIdleIcon = false;
1010
let shouldUseUnreadActiveIcon = true;
1111

12+
// TODO: Refactor to use ITrayColorUpdate type
1213
function setIdleIcon(mb: Menubar): void {
1314
if (shouldUseAlternateIdleIcon) {
1415
mb.tray.setImage(TrayIcons.idleAlternate);

src/main/icons.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ export const TrayIcons = {
99
};
1010

1111
function getIconPath(iconName: string) {
12-
return path.join(__dirname, '..', 'assets', 'images', iconName);
12+
return path.resolve(__dirname, 'assets', 'images', iconName);
1313
}

src/main/index.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,19 @@ import log from 'electron-log';
33
import { menubar } from 'menubar';
44

55
import { Paths, WindowConfig } from './config';
6-
import { registerAppHandlers } from './handlers/app';
7-
import { registerStorageHandlers } from './handlers/storage';
8-
import { registerSystemHandlers } from './handlers/system';
9-
import { registerTrayHandlers } from './handlers/tray';
6+
import {
7+
registerAppHandlers,
8+
registerStorageHandlers,
9+
registerSystemHandlers,
10+
registerTrayHandlers,
11+
} from './handlers';
1012
import { TrayIcons } from './icons';
11-
import { onFirstRunMaybe } from './lifecycle/first-run';
12-
import { handleProtocolURL, initializeAppLifecycle } from './lifecycle/startup';
13-
import { configureWindowEvents } from './lifecycle/window';
13+
import {
14+
configureWindowEvents,
15+
handleProtocolURL,
16+
initializeAppLifecycle,
17+
onFirstRunMaybe,
18+
} from './lifecycle';
1419
import MenuBuilder from './menu';
1520
import AppUpdater from './updater';
1621
import { isDevMode } from './utils';

0 commit comments

Comments
 (0)