OpenAsar/core/src/app/notificationScreen.js

192 lines
6.0 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.NOTIFICATION_CLICK = void 0;
exports.close = close;
exports.hasInit = exports.events = void 0;
exports.init = init;
exports.setMainWindow = setMainWindow;
var _electron = require("electron");
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _events = require("events");
var _url = _interopRequireDefault(require("url"));
var _ipcMain = _interopRequireDefault(require("./ipcMain"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// TODO: transparency detection?
// TODO: SHQueryUserNotificationState
// ipcMain events
const IPC_NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
const IPC_NOTIFICATION_SHOW = 'NOTIFICATION_SHOW';
const IPC_NOTIFICATION_CLICK = 'NOTIFICATION_CLICK';
const IPC_NOTIFICATION_CLOSE = 'NOTIFICATION_CLOSE';
// events
const events = new _events.EventEmitter();
exports.events = events;
const NOTIFICATION_CLICK = 'notification-click';
exports.NOTIFICATION_CLICK = NOTIFICATION_CLICK;
let hasInit = false;
exports.hasInit = hasInit;
const variablesFilePath = _path.default.join(__dirname, 'notifications', 'variables.json');
let mainWindow;
let title;
let maxVisible;
let screenPosition;
let notifications;
let hideTimeout;
let notificationWindow;
let VARIABLES;
function webContentsSend(win, event, ...args) {
if (win != null && win.webContents != null) {
win.webContents.send(`DISCORD_${event}`, ...args);
}
}
function init({
mainWindow: _mainWindow,
title: _title,
maxVisible: _maxVisible,
screenPosition: _screenPosition
}) {
if (hasInit) {
console.warn('notificationScreen: Has already init! Cancelling init.');
return;
}
exports.hasInit = hasInit = true;
VARIABLES = JSON.parse(_fs.default.readFileSync(variablesFilePath));
mainWindow = _mainWindow;
title = _title;
maxVisible = _maxVisible;
screenPosition = _screenPosition;
notifications = [];
hideTimeout = null;
_ipcMain.default.on(IPC_NOTIFICATIONS_CLEAR, handleNotificationsClear);
_ipcMain.default.on(IPC_NOTIFICATION_SHOW, handleNotificationShow);
_ipcMain.default.on(IPC_NOTIFICATION_CLICK, handleNotificationClick);
_ipcMain.default.on(IPC_NOTIFICATION_CLOSE, handleNotificationClose);
}
function destroyWindow() {
if (notificationWindow == null) return;
notificationWindow.hide();
notificationWindow.close();
notificationWindow = null;
}
function close() {
mainWindow = null;
destroyWindow();
_ipcMain.default.removeListener(IPC_NOTIFICATIONS_CLEAR, handleNotificationsClear);
_ipcMain.default.removeListener(IPC_NOTIFICATION_SHOW, handleNotificationShow);
_ipcMain.default.removeListener(IPC_NOTIFICATION_CLICK, handleNotificationClick);
_ipcMain.default.removeListener(IPC_NOTIFICATION_CLOSE, handleNotificationClose);
}
function setMainWindow(_mainWindow) {
mainWindow = _mainWindow;
}
function handleNotificationsClear() {
notifications = [];
updateNotifications();
}
function handleNotificationShow(e, notification) {
notifications.push(notification);
updateNotifications();
}
function handleNotificationClick(e, notificationId) {
webContentsSend(mainWindow, IPC_NOTIFICATION_CLICK, notificationId);
events.emit(NOTIFICATION_CLICK);
}
function handleNotificationClose(e, notificationId) {
if (notificationWindow) {
webContentsSend(notificationWindow, 'FADE_OUT', notificationId);
}
setTimeout(() => {
notifications = notifications.filter(notification => notification.id !== notificationId);
updateNotifications();
}, VARIABLES.outDuration);
}
function updateNotifications() {
if (notifications.length > 0) {
clearTimeout(hideTimeout);
hideTimeout = null;
if (notificationWindow != null) {
const {
width,
height,
x,
y
} = calculateBoundingBox();
// [adill] this order is important. if you setPosition before you setSize electron
// incorrectly computes the window size. i haven't investigated the root cause
// further than this observation.
notificationWindow.setSize(width, height);
notificationWindow.setPosition(x, y);
notificationWindow.showInactive();
} else {
createWindow();
return;
}
} else if (hideTimeout == null) {
hideTimeout = setTimeout(() => destroyWindow(), VARIABLES.outDuration * 1.1);
}
if (notificationWindow != null) {
webContentsSend(notificationWindow, 'UPDATE', notifications.slice(0, maxVisible));
}
}
function calculateBoundingBox() {
const [positionX, positionY] = mainWindow.getPosition();
const [windowWidth, windowHeight] = mainWindow.getSize();
const centerPoint = {
x: Math.round(positionX + windowWidth / 2),
y: Math.round(positionY + windowHeight / 2)
};
const activeDisplay = _electron.screen.getDisplayNearestPoint(centerPoint) || _electron.screen.getPrimaryDisplay();
const workArea = activeDisplay.workArea;
const width = VARIABLES.width;
const height = maxVisible * VARIABLES.height;
const x = workArea.x + workArea.width - width;
let y;
switch (screenPosition) {
case 'top':
y = workArea.y;
break;
case 'bottom':
y = workArea.y + workArea.height - height;
break;
}
return {
x,
y,
width,
height
};
}
function createWindow() {
if (notificationWindow != null) {
return;
}
notificationWindow = new _electron.BrowserWindow({
title: title,
frame: false,
resizable: false,
show: false,
acceptFirstMouse: true,
alwaysOnTop: true,
skipTaskbar: true,
transparent: true,
webPreferences: {
nodeIntegration: false,
preload: _path.default.join(__dirname, 'notificationScreenPreload.js'),
enableRemoteModule: false,
contextIsolation: true
}
});
const notificationUrl = _url.default.format({
protocol: 'file',
slashes: true,
pathname: _path.default.join(__dirname, 'notifications', 'index.html')
});
notificationWindow.loadURL(notificationUrl);
notificationWindow.webContents.on('did-finish-load', () => updateNotifications());
}