Skip to content
Open
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
7 changes: 6 additions & 1 deletion beforeBuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ const electronRebuild = require('electron-rebuild');

module.exports = async (context) => {
const { appDir, electronVersion, arch } = context;
await electronRebuild.rebuild({ buildPath: appDir, electronVersion, arch });
// Force compilation from source so native modules are built against the
// exact Electron V8 headers rather than using a generic prebuilt. Without
// this, prebuild-install downloads an Electron-v116 prebuilt compiled for
// Electron 24 (V8 11.0) which segfaults under Electron 25+ (V8 11.4).
process.env.npm_config_build_from_source = 'true';
await electronRebuild.rebuild({ buildPath: appDir, electronVersion, arch, force: true });

return false;
};
26 changes: 18 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@
"detect-port": "^1.3.0",
"dotenv": "^10.0.0",
"dotenv-webpack": "^7.0.3",
"electron": "^23.3.13",
"electron": "^25.0.0",
"electron-builder": "^23.6.0",
"electron-debug": "^3.2.0",
"electron-fetch": "^1.9.1",
Expand Down Expand Up @@ -225,4 +225,4 @@
"engines": {
"node": ">=18.0.0 <19.0.0"
}
}
}
47 changes: 7 additions & 40 deletions src/apps/main/tray/tray-menu.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
trayHandlers.clear();
});

it('should initialize the tray in loading state', () => {
it('should initialize the tray with context menu in loading state', () => {
// Given
const onClick = vi.fn();
const onQuit = vi.fn();
Expand All @@ -54,58 +54,25 @@

// Then
expect(TrayMock).toBeCalledWith('/icons/loading.png');
expect(trayInstance.setIgnoreDoubleClickEvents).toBeCalledWith(true);
expect(createFromPathMock).toBeCalledWith('/icons/loading.png');
expect(trayInstance.setImage).toBeCalledWith({ imagePath: '/icons/loading.png' });
expect(trayInstance.setToolTip).toBeCalledWith('Loading Internxt...');
expect(buildFromTemplateMock).toBeCalledWith([{ label: 'Open app', click: expect.any(Function) }]);

Check failure on line 60 in src/apps/main/tray/tray-menu.test.ts

View workflow job for this annotation

GitHub Actions / 🧪 Test Main Process

src/apps/main/tray/tray-menu.test.ts > tray-menu > should initialize the tray with context menu in loading state

AssertionError: expected "spy" to be called with arguments: [ [ { label: 'Open app', …(1) } ] ] Received: 1st spy call: [ [ { - "click": Any<Function>, - "label": "Open app", + "click": [Function click], + "label": "Internxt 2.6.0", + }, + { + "click": [Function click], + "label": "Quit", }, ], ] Number of calls: 1 ❯ src/apps/main/tray/tray-menu.test.ts:60:35
expect(trayInstance.setContextMenu).toBeCalledWith({ template: [{ label: 'Open app', click: expect.any(Function) }] });
});

it('should invoke onClick and clear the context menu on tray click', async () => {
it('should invoke onClick when the context menu Open app item is clicked', async () => {
// Given
const onClick = vi.fn().mockResolvedValue(undefined);
const onQuit = vi.fn();
new TrayMenu('/icons', onClick, onQuit);

// When
await trayHandlers.get('click')?.();
// When – simulate clicking the first (only) menu item
const [[menuTemplate]] = buildFromTemplateMock.mock.calls as [[Electron.MenuItemConstructorOptions[]]];
await (menuTemplate[0].click as () => Promise<void>)();

// Then
expect(onClick).toBeCalled();
expect(trayInstance.setContextMenu).toBeCalledWith(null);
});

it('should build and set the tray context menu', () => {
// Given
const onClick = vi.fn().mockResolvedValue(undefined);
const onQuit = vi.fn();
const trayMenu = new TrayMenu('/icons', onClick, onQuit);

// When
trayMenu.updateContextMenu();

// Then
expect(buildFromTemplateMock).toBeCalledWith([
{
label: 'Show/Hide',
click: expect.any(Function),
},
{
label: 'Quit',
click: onQuit,
},
]);
expect(trayInstance.setContextMenu).toBeCalledWith({
template: [
{
label: 'Show/Hide',
click: expect.any(Function),
},
{
label: 'Quit',
click: onQuit,
},
],
});
});

it('should update the tooltip for idle state', () => {
Expand Down
32 changes: 9 additions & 23 deletions src/apps/main/tray/tray-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,25 @@ export class TrayMenu {

this.setState('LOADING');

this.tray.setIgnoreDoubleClickEvents(true);

this.tray.on('click', async () => {
await this.onClick();
this.tray.setContextMenu(null);
});
}

getIconPath(state: TrayMenuState) {
return path.join(this.iconsPath, `${state.toLowerCase()}.png`);
}

generateContextMenu() {
const contextMenuTemplate: Electron.MenuItemConstructorOptions[] = [];
contextMenuTemplate.push(
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show/Hide',
label: `Internxt ${PackageJson.version}`,
click: () => {
this.onClick();
},
},
{
label: 'Quit',
click: this.onQuit,
click: () => {
this.onQuit();
},
},
);

return Menu.buildFromTemplate(contextMenuTemplate);
]);
this.tray.setContextMenu(contextMenu);
}

updateContextMenu() {
const ctxMenu = this.generateContextMenu();
this.tray.setContextMenu(ctxMenu);
getIconPath(state: TrayMenuState) {
return path.join(this.iconsPath, `${state.toLowerCase()}.png`);
}

setState(state: TrayMenuState) {
Expand Down
3 changes: 2 additions & 1 deletion src/apps/main/windows/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BrowserWindow } from 'electron';
import { app, BrowserWindow } from 'electron';

import { preloadPath, resolveHtmlPath } from '../util';
import { setUpCommonWindowHandlers } from '.';
Expand Down Expand Up @@ -41,6 +41,7 @@ export const createAuthWindow = async () => {

authWindow.on('closed', () => {
authWindow = null;
if (!getIsLoggedIn()) app.quit();
});
authWindow.on('blur', () => {
const isLoggedIn = getIsLoggedIn();
Expand Down
Loading