1
0
Fork 0
mirror of https://github.com/anyproto/anytype-ts.git synced 2025-06-08 05:57:02 +09:00
anytype-ts/electron/js/window.js
Andrew Simachev e632abc2eb
JS-7062: fix
2025-05-31 21:57:16 +02:00

267 lines
6.5 KiB
JavaScript

const { app, BrowserWindow, nativeImage, dialog } = require('electron');
const { is, fixPathForAsarUnpack } = require('electron-util');
const path = require('path');
const windowStateKeeper = require('electron-window-state');
const remote = require('@electron/remote/main');
const port = process.env.SERVER_PORT;
const ConfigManager = require('./config.js');
const UpdateManager = require('./update.js');
const MenuManager = require('./menu.js');
const Util = require('./util.js');
const DEFAULT_WIDTH = 1024;
const DEFAULT_HEIGHT = 768;
const MIN_WIDTH = 640;
const MIN_HEIGHT = 480;
const NEW_WINDOW_SHIFT = 30;
class WindowManager {
list = new Set();
create (options, param) {
const { showMenuBar } = ConfigManager.config;
param = Object.assign({
backgroundColor: Util.getBgColor('dark'),
show: false,
titleBarStyle: 'hidden-inset',
webPreferences: {
preload: fixPathForAsarUnpack(path.join(Util.electronPath(), 'js', 'preload.cjs')),
},
}, param);
param.webPreferences = Object.assign({
nativeWindowOpen: true,
contextIsolation: true,
nodeIntegration: false,
spellcheck: true,
sandbox: false,
}, param.webPreferences);
let win = new BrowserWindow(param);
remote.enable(win.webContents);
win = Object.assign(win, options);
win.windowId = win.id;
this.list.add(win);
win.on('close', () => {
Util.send(win, 'will-close-window', win.id);
});
win.on('closed', () => {
this.list.delete(win);
win = null;
});
win.on('focus', () => {
UpdateManager.setWindow(win);
MenuManager.setWindow(win);
});
win.on('enter-full-screen', () => Util.send(win, 'enter-full-screen'));
win.on('leave-full-screen', () => Util.send(win, 'leave-full-screen'));
win.webContents.on('context-menu', (e, param) => {
Util.send(win, 'spellcheck', param.misspelledWord, param.dictionarySuggestions, param.x, param.y, param.selectionRect);
});
win.setMenuBarVisibility(showMenuBar);
win.setAutoHideMenuBar(!showMenuBar);
return win;
};
createMain (options) {
const { isChild } = options;
const image = nativeImage.createFromPath(path.join(Util.imagePath(), 'icons', '512x512.png'));
let state = {};
let param = {
minWidth: MIN_WIDTH,
minHeight: MIN_HEIGHT,
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
};
if (is.macos) {
app.dock.setIcon(image);
param.frame = false;
param.titleBarStyle = 'hidden';
param.icon = path.join(Util.imagePath(), 'icon.icns');
param.trafficLightPosition = { x: 10, y: 18 };
} else
if (is.windows) {
param.icon = path.join(Util.imagePath(), 'icons', '256x256.ico');
} else
if (is.linux) {
param.icon = image;
};
if (!isChild) {
try {
state = windowStateKeeper({ defaultWidth: DEFAULT_WIDTH, defaultHeight: DEFAULT_HEIGHT });
param = Object.assign(param, {
x: state.x,
y: state.y,
width: state.width,
height: state.height,
});
} catch (e) {};
} else {
const { width, height } = this.getScreenSize();
param = Object.assign(param, this.getWindowPosition(param, width, height));
};
const win = this.create(options, param);
if (!isChild) {
state.manage(win);
};
win.loadURL(is.development ? `http://localhost:${port}` : 'file://' + path.join(Util.appPath, 'dist', 'index.html'));
win.once('ready-to-show', () => win.show());
win.on('enter-full-screen', () => MenuManager.initMenu());
win.on('leave-full-screen', () => MenuManager.initMenu());
if (is.development) {
win.toggleDevTools();
};
return win;
};
createChallenge (options) {
const { width, height } = this.getScreenSize();
const win = this.create({ ...options, isChallenge: true }, {
backgroundColor: '',
width: 424,
height: 232,
x: Math.floor(width / 2 - 212),
y: Math.floor(height - 282),
titleBarStyle: 'hidden',
alwaysOnTop: true,
focusable: true,
skipTaskbar: true,
});
win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
win.loadURL('file://' + path.join(Util.appPath, 'dist', 'challenge', 'index.html'));
win.setMenu(null);
win.showInactive(); // show inactive to prevent focus loose from other app
win.webContents.once('did-finish-load', () => {
win.webContents.postMessage('challenge', options);
});
setTimeout(() => this.closeChallenge(options), 30000);
return win;
};
getScreenSize () {
const ret = { width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT };
try {
const { screen } = require('electron');
const primaryDisplay = screen.getPrimaryDisplay();
const { width, height } = primaryDisplay.workAreaSize;
ret.width = width;
ret.height = height;
} catch (e) {};
return ret;
};
closeChallenge (options) {
for (const win of this.list) {
if (win && win.isChallenge && (win.challenge == options.challenge) && !win.isDestroyed()) {
win.close();
};
};
};
command (win, cmd, param) {
param = param || {};
switch (cmd) {
case 'menu':
MenuManager.menu.popup({ x: 16, y: 38 });
break;
case 'minimize':
win.minimize();
break;
case 'maximize':
win.isMaximized() ? win.unmaximize() : win.maximize();
break;
case 'close':
win.hide();
break;
case 'printHtml':
case 'printPdf':
const ext = cmd.replace(/print/, '').toLowerCase();
dialog.showSaveDialog(win, {
buttonLabel: 'Export',
fileFilter: { extensions: [ ext ] },
defaultPath: `${app.getPath('documents')}/${param.name}.${ext}`,
properties: [ 'createDirectory', 'showOverwriteConfirmation' ],
}).then((result) => {
const fp = result.filePath;
if (!fp) {
Util.send(win, 'commandGlobal', 'saveAsHTMLSuccess');
} else {
Util[cmd](win, path.dirname(fp), path.basename(fp), param.options);
};
});
break;
};
};
getWindowPosition (param, displayWidth, displayHeight) {
const currentWindow = BrowserWindow.getFocusedWindow();
let x = Math.round(displayWidth / 2 - param.width / 2);
let y = Math.round(displayHeight / 2 - param.height / 2 + 20);
if (currentWindow) {
const [ xPos, yPos ] = currentWindow.getPosition();
x = xPos + NEW_WINDOW_SHIFT;
y = yPos + NEW_WINDOW_SHIFT;
const xLimit = x + param.width > displayWidth;
const yLimit = y + param.height > displayHeight;
if (xLimit || yLimit) {
x = 0;
y = 0;
};
};
return { x, y };
};
sendToAll () {
const args = [ ...arguments ];
this.list.forEach(it => Util.send.apply(this, [ it ].concat(args)));
};
reloadAll () {
this.sendToAll('reload');
};
};
module.exports = new WindowManager();