UNPKG

@jitsi/electron-sdk

Version:
247 lines (215 loc) 7.42 kB
const Store = require('electron-store'); const electron = require('electron'); const os = require('os'); const log = require('@jitsi/logger'); const { SIZE, ASPECT_RATIO, STORAGE } = require('../constants'); /** * Stores the current size of the AOT during the conference * @type {{width: number, height: number}} */ let size = Object.assign({}, SIZE); /** * Keeps the old size of the window between resize handler calls */ let oldSize; /** * The logger instance */ let logger; /** * The electron-store instance to store last position of the aot window. */ const store = new Store(); /** * Changes the window resize functionality to respect the passed aspect ratio. * * @param {BrowserWindow} win - The target window. * @param {number} aspectRatio - The aspect ratio to be set. * @returns {void} */ const setAspectRatioToResizeableWindow = (win, aspectRatio = ASPECT_RATIO) => { //for macOS we use the built-in setAspectRatio on resize, for other we use custom implementation if (os.type() === 'Darwin') { win.setAspectRatio(aspectRatio); win.on('resize', () => { const [ width, height ] = win.getSize(); size.width = width; size.height = height; }); } else { win.on('will-resize', (e, newBounds) => { oldSize = win.getSize(); const mousePos = electron.screen.getCursorScreenPoint(); const windowBottomRightPos = { x: newBounds.x + newBounds.width - 16, y: newBounds.y + newBounds.height - 16, }; //prevent resize from bottom right corner as it is buggy. if (mousePos.x >= windowBottomRightPos.x && mousePos.y >= windowBottomRightPos.y) { e.preventDefault(); } }); win.on('resize', () => { if (!Array.isArray(oldSize) || oldSize.length !== 2) { // Adding this check because of reports for JS errors that oldSize is undefined. return; } let [ width, height ] = win.getSize(); //we scale either width or height according to the other by checking which of the 2 //changed the most since last resize. if (Math.abs(oldSize[0] - width) >= Math.abs(oldSize[1] - height)) { height = Math.round(width / aspectRatio); } else { width = Math.round(height * aspectRatio); } win.setSize(width, height); size.width = width; size.height = height; }); } }; /** * Calculates the coordinates for a window (based on its current coordinates and * size) to place it in the boundaries of a given screen. * * @param {Rectangle} windowRectangle - The current position and dimensions of * the window. * @param {Rectangle} screenRectangle - The position and dimensions of the * screen. * @returns {Point} - The new coordinates for the window. * * NOTE: All x and y coordinates are representing the top-left corner of the * window or screen. */ const positionWindowWithinScreenBoundaries = (windowRectangle, screenRectangle) => { // The min value for y coordinate of the window in order to place it within // the boundaries of the screen. This will be the use case where the top // edge of the window is exactly on the top boundary of the screen. const minY = screenRectangle.y; // The min value for x coordinate of the window in order to place it within // the boundaries of the screen. This will be the use case where the left // edge of the window is exactly on the left boundary of the screen. const minX = screenRectangle.x; // The max value for y coordinate of the window in order to place it within // the boundaries of the screen. This will be the use case where the bottom // edge of the window is exactly on the bottom boundary of the screen. const maxY = screenRectangle.y + screenRectangle.height - windowRectangle.height; // The max value for x coordinate of the window in order to place it within // the boundaries of the screen. This will be the use case where the right // edge of the window is exactly on the right boundary of the screen. const maxX = screenRectangle.x + screenRectangle.width - windowRectangle.width; return { x: Math.min(Math.max(windowRectangle.x, minX), maxX), y: Math.min(Math.max(windowRectangle.y, minY), maxY) }; }; const setLogger = loggerTransports => { logger = log.getLogger('AOT', loggerTransports || []); }; /** * Wrapper over the loger's info * * @param {string} info - The info text */ const logInfo = info => { if (!logger) { return; } logger.info(`[MAIN] ${info}`); }; /** * Wrapper over the loger's error * * @param {Object} err - the error object */ const logError = err => { if (!logger) { return; } logger.error({ err }, '[MAIN ERROR]'); }; /** * Returns the stored coordinates for the always on top window of its previous * location or if the last location is unknown returns coordinates to display * the window in the top right corner of the screen. * * @returns {{x: number, y: number}} */ const getPosition = () => { const Screen = electron.screen; const position = { x: store.get(STORAGE.AOT_X), y: store.get(STORAGE.AOT_Y) }; if (typeof position.x === 'number' && typeof position.y === 'number') { // Position the window within the screen boundaries. This is needed // only for windows. On Mac and Linux it is working as expected without // changing the coordinates. if (os.platform() === 'win32') { const windowRectangle = Object.assign({}, position, size); const matchingScreen = Screen.getDisplayMatching(windowRectangle); if (matchingScreen) { return positionWindowWithinScreenBoundaries( windowRectangle, matchingScreen.workArea); } } return position; } const { x, y, width } = Screen.getDisplayNearestPoint(Screen.getCursorScreenPoint()).workArea; return { x: x + width - size.width, y }; }; /** * Saves window position * @param {BrowserWindow} browserWindow - the aot window */ const savePosition = aotWindow => { if (!windowExists(aotWindow)) { return; } const [x, y] = aotWindow.getPosition(); store.set(STORAGE.AOT_X, x); store.set(STORAGE.AOT_Y, y); }; /** * Gets the size to be set to the new AOT window. * This is used in order to preserve the size on close and open of AOT during the same meeting * @returns {{width: number, height: number}} */ const getSize = () => { if (typeof size.width === 'number' && typeof size.height === 'number') { return size; } return SIZE; }; const resetSize = () => { size = Object.assign({}, SIZE); }; /** * Checks whether the window exists * @param {BrowserWindow} win * @returns */ const windowExists = browserWindow => { return browserWindow && !browserWindow.isDestroyed(); }; module.exports = { getPosition, getSize, logError, logInfo, resetSize, savePosition, setAspectRatioToResizeableWindow, setLogger, windowExists, };