mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2025-12-05 18:20:39 -08:00
282 lines
7.8 KiB
JavaScript
282 lines
7.8 KiB
JavaScript
const {
|
|
BrowserWindow,
|
|
Menu,
|
|
Tray,
|
|
app,
|
|
ipcMain,
|
|
nativeImage,
|
|
} = require('electron');
|
|
const windowStateKeeper = require('electron-window-state');
|
|
const { menubar } = require('menubar');
|
|
const path = require('path');
|
|
|
|
const { REACT_PATH, isDev } = require('../constants/paths');
|
|
const { getPreference } = require('../libs/preferences');
|
|
const formatBytes = require('../libs/format-bytes');
|
|
|
|
let win;
|
|
let mb = {};
|
|
let attachToMenubar;
|
|
|
|
const get = () => {
|
|
if (attachToMenubar) return mb.window;
|
|
return win;
|
|
};
|
|
|
|
const createAsync = () => new Promise((resolve) => {
|
|
attachToMenubar = getPreference('attachToMenubar');
|
|
if (attachToMenubar) {
|
|
const menubarWindowState = windowStateKeeper({
|
|
file: 'window-state-menubar.json',
|
|
defaultWidth: 400,
|
|
defaultHeight: 400,
|
|
});
|
|
|
|
// setImage after Tray instance is created to avoid
|
|
// "Segmentation fault (core dumped)" bug on Linux
|
|
// https://github.com/electron/electron/issues/22137#issuecomment-586105622
|
|
// https://github.com/atomery/translatium/issues/164
|
|
const tray = new Tray(nativeImage.createEmpty());
|
|
// icon template is not supported on Windows & Linux
|
|
const iconPath = path.resolve(__dirname, '..', process.platform === 'darwin' ? 'menubarTemplate.png' : 'menubar.png');
|
|
tray.setImage(iconPath);
|
|
|
|
mb = menubar({
|
|
index: REACT_PATH,
|
|
tray,
|
|
preloadWindow: true,
|
|
tooltip: 'TiddlyGit',
|
|
browserWindow: {
|
|
x: menubarWindowState.x,
|
|
y: menubarWindowState.y,
|
|
width: menubarWindowState.width,
|
|
height: menubarWindowState.height,
|
|
minHeight: 100,
|
|
minWidth: 250,
|
|
webPreferences: {
|
|
nodeIntegration: false,
|
|
enableRemoteModule: true,
|
|
webSecurity: !isDev,
|
|
contextIsolation: true,
|
|
webSecurity: false,
|
|
preload: path.join(__dirname, '..', 'preload', 'menubar.js'),
|
|
},
|
|
},
|
|
});
|
|
|
|
mb.on('after-create-window', () => {
|
|
menubarWindowState.manage(mb.window);
|
|
|
|
mb.window.on('focus', () => {
|
|
const view = mb.window.getBrowserView();
|
|
if (view && view.webContents) {
|
|
view.webContents.focus();
|
|
}
|
|
});
|
|
});
|
|
|
|
mb.on('ready', () => {
|
|
mb.tray.on('right-click', () => {
|
|
const updaterEnabled = process.env.SNAP == null
|
|
&& !process.mas && !process.windowsStore;
|
|
|
|
const updaterMenuItem = {
|
|
label: 'Check for Updates...',
|
|
click: () => ipcMain.emit('request-check-for-updates'),
|
|
visible: updaterEnabled,
|
|
};
|
|
if (global.updaterObj && global.updaterObj.status === 'update-downloaded') {
|
|
updaterMenuItem.label = 'Restart to Apply Updates...';
|
|
} else if (global.updaterObj && global.updaterObj.status === 'update-available') {
|
|
updaterMenuItem.label = 'Downloading Updates...';
|
|
updaterMenuItem.enabled = false;
|
|
} else if (global.updaterObj && global.updaterObj.status === 'download-progress') {
|
|
const { transferred, total, bytesPerSecond } = global.updaterObj.info;
|
|
updaterMenuItem.label = `Downloading Updates (${formatBytes(transferred)}/${formatBytes(total)} at ${formatBytes(bytesPerSecond)}/s)...`;
|
|
updaterMenuItem.enabled = false;
|
|
} else if (global.updaterObj && global.updaterObj.status === 'checking-for-update') {
|
|
updaterMenuItem.label = 'Checking for Updates...';
|
|
updaterMenuItem.enabled = false;
|
|
}
|
|
|
|
const contextMenu = Menu.buildFromTemplate([
|
|
{
|
|
label: 'Open TiddlyGit',
|
|
click: () => mb.showWindow(),
|
|
},
|
|
{
|
|
type: 'separator',
|
|
},
|
|
{
|
|
label: 'About TiddlyGit',
|
|
click: () => ipcMain.emit('request-show-about-window'),
|
|
},
|
|
{ type: 'separator' },
|
|
updaterMenuItem,
|
|
{ type: 'separator' },
|
|
{
|
|
label: 'Preferences...',
|
|
click: () => ipcMain.emit('request-show-preferences-window'),
|
|
},
|
|
{ type: 'separator' },
|
|
{
|
|
label: 'Notifications...',
|
|
click: () => ipcMain.emit('request-show-notifications-window'),
|
|
},
|
|
{ type: 'separator' },
|
|
{
|
|
label: 'Clear Browsing Data...',
|
|
click: () => ipcMain.emit('request-clear-browsing-data'),
|
|
},
|
|
{ type: 'separator' },
|
|
{
|
|
role: 'quit',
|
|
click: () => {
|
|
mb.app.quit();
|
|
},
|
|
},
|
|
]);
|
|
|
|
mb.tray.popUpContextMenu(contextMenu);
|
|
});
|
|
|
|
resolve();
|
|
});
|
|
return;
|
|
}
|
|
|
|
|
|
const { wasOpenedAsHidden } = app.getLoginItemSettings();
|
|
|
|
const mainWindowState = windowStateKeeper({
|
|
defaultWidth: 1000,
|
|
defaultHeight: 768,
|
|
});
|
|
|
|
win = new BrowserWindow({
|
|
x: mainWindowState.x,
|
|
y: mainWindowState.y,
|
|
width: mainWindowState.width,
|
|
height: mainWindowState.height,
|
|
minHeight: 100,
|
|
minWidth: 350,
|
|
title: 'TiddlyGit',
|
|
titleBarStyle: 'hidden',
|
|
show: false,
|
|
// manually set dock icon for AppImage
|
|
// Snap icon is set correct already so no need to intervene
|
|
icon: process.platform === 'linux' && process.env.SNAP == null ? path.resolve(__dirname, '..', 'icon.png') : undefined,
|
|
webPreferences: {
|
|
nodeIntegration: false,
|
|
enableRemoteModule: true,
|
|
webSecurity: !isDev,
|
|
contextIsolation: true,
|
|
preload: path.join(__dirname, '..', 'preload', 'main.js'),
|
|
},
|
|
});
|
|
if (getPreference('hideMenuBar')) {
|
|
win.setMenuBarVisibility(false);
|
|
}
|
|
|
|
mainWindowState.manage(win);
|
|
|
|
// Enable swipe to navigate
|
|
const swipeToNavigate = getPreference('swipeToNavigate');
|
|
if (swipeToNavigate) {
|
|
win.on('swipe', (e, direction) => {
|
|
const view = win.getBrowserView();
|
|
if (view) {
|
|
if (direction === 'left') {
|
|
view.webContents.goBack();
|
|
} else if (direction === 'right') {
|
|
view.webContents.goForward();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Hide window instead closing on macos
|
|
win.on('close', (e) => {
|
|
if (process.platform === 'darwin' && !win.forceClose) {
|
|
e.preventDefault();
|
|
// https://github.com/electron/electron/issues/6033#issuecomment-242023295
|
|
if (win.isFullScreen()) {
|
|
win.once('leave-full-screen', () => {
|
|
win.hide();
|
|
});
|
|
win.setFullScreen(false);
|
|
} else {
|
|
win.hide();
|
|
}
|
|
}
|
|
});
|
|
|
|
win.on('closed', () => {
|
|
win = null;
|
|
});
|
|
|
|
win.on('focus', () => {
|
|
const view = win.getBrowserView();
|
|
if (view && view.webContents) {
|
|
view.webContents.focus();
|
|
}
|
|
});
|
|
|
|
win.once('ready-to-show', () => {
|
|
if (!wasOpenedAsHidden) {
|
|
win.show();
|
|
}
|
|
|
|
// calling this to redundantly setBounds BrowserView
|
|
// after the UI is fully loaded
|
|
// if not, BrowserView mouseover event won't work correctly
|
|
// https://github.com/atomery/webcatalog/issues/812
|
|
ipcMain.emit('request-realign-active-workspace');
|
|
});
|
|
|
|
win.on('enter-full-screen', () => {
|
|
win.webContents.send('is-fullscreen-updated', true);
|
|
ipcMain.emit('request-realign-active-workspace');
|
|
});
|
|
win.on('leave-full-screen', () => {
|
|
win.webContents.send('is-fullscreen-updated', false);
|
|
ipcMain.emit('request-realign-active-workspace');
|
|
});
|
|
|
|
// ensure redux is loaded first
|
|
// if not, redux might not be able catch changes sent from ipcMain
|
|
win.webContents.once('did-stop-loading', () => {
|
|
resolve();
|
|
});
|
|
|
|
win.loadURL(REACT_PATH);
|
|
});
|
|
|
|
const show = () => {
|
|
if (attachToMenubar) {
|
|
if (mb == null) {
|
|
createAsync();
|
|
} else {
|
|
mb.on('ready', () => {
|
|
mb.showWindow();
|
|
});
|
|
}
|
|
} else if (win == null) {
|
|
createAsync();
|
|
} else {
|
|
win.show();
|
|
}
|
|
};
|
|
|
|
const send = (...args) => {
|
|
if (win !== null) {
|
|
win.webContents.send(...args);
|
|
}
|
|
};
|
|
|
|
module.exports = {
|
|
createAsync,
|
|
get,
|
|
send,
|
|
show,
|
|
};
|