bloodymary/app/systemTray.js
2020-05-17 12:54:24 +00:00

253 lines
No EOL
7.2 KiB
JavaScript

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.hasInit = undefined;
exports.init = init;
exports.show = show;
exports.displayHowToCloseHint = displayHowToCloseHint;
var _electron = require('electron');
var _utils = require('./utils');
var _appSettings = require('./appSettings');
var _ipcMain = require('./ipcMain');
var _ipcMain2 = _interopRequireDefault(_ipcMain);
var _Constants = require('./Constants');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const settings = (0, _appSettings.getSettings)();
// These are lazy loaded into temp files
const TrayIconNames = {
DEFAULT: 'tray',
UNREAD: 'tray-unread',
CONNECTED: 'tray-connected',
SPEAKING: 'tray-speaking',
MUTED: 'tray-muted',
DEAFENED: 'tray-deafened'
};
const MenuItems = {
SECRET: 'SECRET',
MUTE: 'MUTE',
DEAFEN: 'DEAFEN',
OPEN: 'OPEN',
VOICE_SETTINGS: 'VOICE_SETTINGS',
CHECK_UPDATE: 'CHECK_UPDATE',
QUIT: 'QUIT',
ACKNOWLEDGEMENTS: 'ACKNOWLEDGEMENTS'
};
let hasInit = exports.hasInit = false;
let currentIcon;
let options;
let menuItems;
let contextMenu;
let atomTray;
let trayIcons;
let applications;
function init(_options) {
if (hasInit) {
console.warn('systemTray: Has already init! Cancelling init.');
return;
}
trayIcons = {};
generateTrayIconPaths();
exports.hasInit = hasInit = true;
options = _options;
currentIcon = trayIcons.DEFAULT;
menuItems = {};
applications = [];
contextMenu = [];
initializeMenuItems();
buildContextMenu();
_ipcMain2.default.on('SYSTEM_TRAY_SET_ICON', (evt, icon) => setTrayIcon(icon));
_ipcMain2.default.on('SYSTEM_TRAY_SET_APPLICATIONS', (evt, newApplications) => setApplications(newApplications));
}
function generateTrayIconPaths() {
// Load in the icons for current platform
const resourcePath = `app/images/systemtray/${process.platform}`;
const suffix = process.platform === 'darwin' ? 'Template' : '';
for (const key of Object.keys(TrayIconNames)) {
trayIcons[key] = (0, _utils.exposeModuleResource)(resourcePath, `${TrayIconNames[key]}${suffix}.png`);
}
}
function initializeMenuItems() {
const { onToggleMute, onToggleDeafen, onTrayClicked, onOpenVoiceSettings, onCheckForUpdates } = options;
const voiceConnected = currentIcon !== trayIcons.DEFAULT && currentIcon !== trayIcons.UNREAD;
menuItems[MenuItems.SECRET] = {
label: `Discord`,
icon: trayIcons.DEFAULT,
enabled: false
};
menuItems[MenuItems.MUTE] = {
label: `Mute`,
type: 'checkbox',
checked: currentIcon === trayIcons.MUTED || currentIcon === trayIcons.DEAFENED,
visible: voiceConnected,
click: onToggleMute
};
menuItems[MenuItems.DEAFEN] = {
label: `Deafen`,
type: 'checkbox',
checked: currentIcon === trayIcons.DEAFENED,
visible: voiceConnected,
click: onToggleDeafen
};
menuItems[MenuItems.OPEN] = {
label: `Open ${_Constants.APP_NAME}`,
type: 'normal',
visible: process.platform === 'linux',
click: onTrayClicked
};
menuItems[MenuItems.VOICE_SETTINGS] = {
label: 'Voice / Video Settings',
type: 'normal',
visible: voiceConnected,
click: onOpenVoiceSettings
};
menuItems[MenuItems.CHECK_UPDATE] = {
label: 'Check for Updates...',
type: 'normal',
visible: process.platform !== 'darwin',
click: onCheckForUpdates
};
menuItems[MenuItems.QUIT] = {
label: `Quit ${_Constants.APP_NAME}`,
role: 'quit'
};
menuItems[MenuItems.ACKNOWLEDGEMENTS] = {
label: 'Acknowledgements',
type: 'normal',
visible: process.platform !== 'darwin',
click: () => _electron.shell.openExternal('https://discordapp.com/acknowledgements')
};
}
function buildContextMenu() {
const separator = { type: 'separator' };
const hasApplications = applications != null && applications.length > 0;
contextMenu = [menuItems[MenuItems.SECRET], separator, ...(hasApplications ? [...applications, separator] : []), menuItems[MenuItems.OPEN], menuItems[MenuItems.MUTE], menuItems[MenuItems.DEAFEN], menuItems[MenuItems.VOICE_SETTINGS], menuItems[MenuItems.CHECK_UPDATE], menuItems[MenuItems.ACKNOWLEDGEMENTS], separator, menuItems[MenuItems.QUIT]];
}
function setTrayIcon(icon) {
// Keep track of last set icon
currentIcon = trayIcons[icon];
// If icon is null, hide the tray icon. Otherwise show
// These calls also check for tray existence, so minimal cost.
if (icon == null) {
hide();
return;
} else {
show();
}
// Keep mute/deafen menu items in sync with client, based on icon states
const muteIndex = contextMenu.indexOf(menuItems[MenuItems.MUTE]);
const deafenIndex = contextMenu.indexOf(menuItems[MenuItems.DEAFEN]);
const voiceConnected = contextMenu[muteIndex].visible;
let shouldSetContextMenu = false;
if (currentIcon !== trayIcons.DEFAULT && currentIcon !== trayIcons.UNREAD) {
// Show mute/deaf controls
if (!voiceConnected) {
contextMenu[muteIndex].visible = true;
contextMenu[deafenIndex].visible = true;
shouldSetContextMenu = true;
}
if (currentIcon === trayIcons.DEAFENED) {
contextMenu[muteIndex].checked = true;
contextMenu[deafenIndex].checked = true;
shouldSetContextMenu = true;
} else if (currentIcon === trayIcons.MUTED) {
contextMenu[muteIndex].checked = true;
contextMenu[deafenIndex].checked = false;
shouldSetContextMenu = true;
} else if (contextMenu[muteIndex].checked || contextMenu[deafenIndex].checked) {
contextMenu[muteIndex].checked = false;
contextMenu[deafenIndex].checked = false;
shouldSetContextMenu = true;
}
} else if (voiceConnected) {
contextMenu[muteIndex].visible = false;
contextMenu[deafenIndex].visible = false;
shouldSetContextMenu = true;
}
shouldSetContextMenu && setContextMenu();
atomTray != null && atomTray.setImage(_electron.nativeImage.createFromPath(currentIcon));
}
function launchApplication(applicationId) {
options.onLaunchApplication(applicationId);
}
function setApplications(newApplications) {
applications = newApplications.map(application => ({
type: 'normal',
label: application.name,
click: () => launchApplication(application.id)
}));
buildContextMenu();
setContextMenu();
}
function setContextMenu() {
atomTray != null && atomTray.setContextMenu(_electron.Menu.buildFromTemplate(contextMenu));
}
function show() {
if (atomTray != null) return;
atomTray = new _electron.Tray(_electron.nativeImage.createFromPath(currentIcon)); // Initialize with last set icon
atomTray.setToolTip(_Constants.APP_NAME);
// Set tray context menu
setContextMenu();
// Set Tray click behavior
atomTray.on('click', options.onTrayClicked);
}
function hide() {
if (atomTray == null) {
return;
}
atomTray.destroy();
atomTray = null;
}
function displayHowToCloseHint() {
if (settings.get('trayBalloonShown') != null || atomTray == null) {
return;
}
// TODO: localize
const balloonMessage = 'Hi! Discord will run in the background to keep you in touch with your friends.' + ' You can right-click here to quit.';
settings.set('trayBalloonShown', true);
settings.save();
atomTray.displayBalloon({
title: 'Discord',
content: balloonMessage
});
}