mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
ELECTRON-483 (Implement a functionality to display snack bar) (#390)
- Implement a functionality to display snack bar - Localize snack bar - Move key press logic to windowMgr - Center snackbar - Add functionality to remove snackbar on leave-full-screen event - Add safety check - optimize code to listen keydown event only if the window is in full screen
This commit is contained in:
committed by
Vishwas Shashidhar
parent
131076c2b0
commit
cc39f43ee7
@@ -23,6 +23,7 @@ const cmds = keyMirror({
|
||||
optimizeMemoryConsumption: null,
|
||||
setIsInMeeting: null,
|
||||
setLocale: null,
|
||||
keyPress: null,
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
|
@@ -164,6 +164,11 @@ electron.ipcMain.on(apiName, (event, arg) => {
|
||||
eventEmitter.emit('language-changed', { language: arg.locale });
|
||||
}
|
||||
break;
|
||||
case apiCmds.keyPress:
|
||||
if (typeof arg.keyCode === 'number') {
|
||||
windowMgr.handleKeyPress(arg.keyCode);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
|
@@ -23,16 +23,13 @@ const { TitleBar, updateContentHeight } = require('../windowsTitlebar');
|
||||
const titleBar = new TitleBar();
|
||||
const { buildNumber } = require('../../package.json');
|
||||
const memoryMonitorInterval = 1000 * 60 * 60;
|
||||
const SnackBar = require('../snackBar').SnackBar;
|
||||
const KeyCodes = {
|
||||
Esc: 27,
|
||||
};
|
||||
|
||||
require('../downloadManager');
|
||||
|
||||
// bug in electron preventing us from using spellchecker in pop outs
|
||||
// https://github.com/electron/electron/issues/4025
|
||||
// so loading the spellchecker in try catch so that we don't
|
||||
// block other method from loading
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
loadSpellChecker();
|
||||
});
|
||||
let snackBar;
|
||||
|
||||
/**
|
||||
* Loads up the spell checker module
|
||||
@@ -72,6 +69,14 @@ const throttledSetIsInMeetingStatus = throttle(1000, function(isInMeeting) {
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* an event triggered by the main process onload event
|
||||
*/
|
||||
local.ipcRenderer.on('on-page-load', () => {
|
||||
loadSpellChecker();
|
||||
snackBar = new SnackBar();
|
||||
});
|
||||
|
||||
// Gathers renderer process memory
|
||||
setInterval(() => {
|
||||
const memory = process.getProcessMemoryInfo();
|
||||
@@ -430,6 +435,28 @@ function createAPI() {
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* an event triggered by the main process when
|
||||
* the window enters full screen
|
||||
*/
|
||||
local.ipcRenderer.on('window-enter-full-screen', (event, arg) => {
|
||||
window.addEventListener('keydown', throttledKeyDown, true);
|
||||
if (snackBar && typeof arg === 'object' && arg.snackBar) {
|
||||
setTimeout(() => snackBar.showSnackBar(arg.snackBar), 500);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* an event triggered by the main process when
|
||||
* the window leave full screen
|
||||
*/
|
||||
local.ipcRenderer.on('window-leave-full-screen', () => {
|
||||
window.removeEventListener('keydown', throttledKeyDown, true);
|
||||
if (snackBar) {
|
||||
snackBar.removeSnackBar();
|
||||
}
|
||||
});
|
||||
|
||||
function updateOnlineStatus() {
|
||||
local.ipcRenderer.send(apiName, {
|
||||
cmd: apiCmds.isOnline,
|
||||
@@ -445,6 +472,15 @@ function createAPI() {
|
||||
});
|
||||
}
|
||||
|
||||
const throttledKeyDown = throttle(1000, (event) => {
|
||||
if (event.keyCode === KeyCodes.Esc) {
|
||||
local.ipcRenderer.send(apiName, {
|
||||
cmd: apiCmds.keyPress,
|
||||
keyCode: KeyCodes.Esc
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('offline', updateOnlineStatus, false);
|
||||
window.addEventListener('online', updateOnlineStatus, false);
|
||||
window.addEventListener('beforeunload', sanitize, false);
|
||||
|
11
js/snackBar/content.js
Normal file
11
js/snackBar/content.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const snackBarContent = (
|
||||
`<div id="snackbar">
|
||||
<span data-i18n-text="Press "></span>
|
||||
<span id="snackbar-esc" data-i18n-text="esc"></span>
|
||||
<span data-i18n-text=" to exit full screen"></span>
|
||||
</div>`
|
||||
);
|
||||
|
||||
module.exports = {
|
||||
snackBarContent
|
||||
};
|
54
js/snackBar/index.js
Normal file
54
js/snackBar/index.js
Normal file
@@ -0,0 +1,54 @@
|
||||
const snackBarContent = require('./content').snackBarContent;
|
||||
|
||||
class SnackBar {
|
||||
|
||||
constructor() {
|
||||
this.body = document.getElementsByTagName('body');
|
||||
this.domParser = new DOMParser();
|
||||
|
||||
const snackBar = this.domParser.parseFromString(snackBarContent, 'text/html');
|
||||
this.snackBar = snackBar.getElementById('snackbar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that displays a snack bar for 3 sec
|
||||
*/
|
||||
showSnackBar(content) {
|
||||
if (content && typeof content === 'object') {
|
||||
const i18nNodes = this.snackBar.querySelectorAll('[data-i18n-text]');
|
||||
|
||||
for (let node of i18nNodes) {
|
||||
if (node.attributes['data-i18n-text'] && node.attributes['data-i18n-text'].value) {
|
||||
node.innerText = content[node.attributes['data-i18n-text'].value] || node.attributes['data-i18n-text'].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.body && this.body.length > 0 && this.snackBar) {
|
||||
this.body[0].appendChild(this.snackBar);
|
||||
this.snackBar.className = "show";
|
||||
this.snackBarTimmer = setTimeout(() => {
|
||||
this.body[0].removeChild(this.snackBar);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that removes snack bar from the DOM
|
||||
*/
|
||||
removeSnackBar() {
|
||||
if (this.body && this.body.length > 0 && this.snackBar) {
|
||||
if (document.getElementById('snackbar')) {
|
||||
this.body[0].removeChild(this.snackBar);
|
||||
if (this.snackBarTimmer) {
|
||||
clearTimeout(this.snackBarTimmer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
SnackBar,
|
||||
};
|
51
js/snackBar/style.css
Normal file
51
js/snackBar/style.css
Normal file
@@ -0,0 +1,51 @@
|
||||
#snackbar {
|
||||
visibility: hidden;
|
||||
min-width: 250px;
|
||||
margin-left: -135px;
|
||||
background-color: rgba(51,51,51, 1);
|
||||
color: rgba(255,255,255, 1);
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
padding: 16px;
|
||||
position: fixed;
|
||||
z-index: 2147483647;
|
||||
left: 50%;
|
||||
top: 30px;
|
||||
font-size: 14px;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#snackbar-esc {
|
||||
padding: 5px;
|
||||
border: 0.5px solid rgba(51,51,51, 1);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#snackbar.show {
|
||||
visibility: visible;
|
||||
-webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
|
||||
animation: fadein 0.5s, fadeout 0.5s 2.5s;
|
||||
}
|
||||
|
||||
#snackbar-esc {
|
||||
border: 2px solid white;
|
||||
background-color: rgba(51,51,51, 1);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadein {
|
||||
from {
|
||||
top: 0; opacity: 0;
|
||||
}
|
||||
to {
|
||||
top: 30px; opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes fadeout {
|
||||
from {
|
||||
top: 30px; opacity: 1;
|
||||
}
|
||||
to {
|
||||
top: 0; opacity: 0;
|
||||
}
|
||||
}
|
@@ -45,6 +45,10 @@ let display;
|
||||
let sandboxed = false;
|
||||
let isAutoReload = false;
|
||||
|
||||
const KeyCodes = {
|
||||
Esc: 27,
|
||||
};
|
||||
|
||||
// Application menu
|
||||
let menu;
|
||||
let lang;
|
||||
@@ -197,6 +201,15 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
let throttledMainWinBoundsChange = throttle(1000, saveMainWinBounds);
|
||||
mainWindow.on('move', throttledMainWinBoundsChange);
|
||||
mainWindow.on('resize', throttledMainWinBoundsChange);
|
||||
mainWindow.on('enter-full-screen', () => {
|
||||
const snackBarContent = i18n.getMessageFor('SnackBar');
|
||||
// event sent to renderer process to show snack bar
|
||||
mainWindow.webContents.send('window-enter-full-screen', { snackBar: snackBarContent });
|
||||
});
|
||||
mainWindow.on('leave-full-screen', () => {
|
||||
// event sent to renderer process to remove snack bar
|
||||
mainWindow.webContents.send('window-leave-full-screen');
|
||||
});
|
||||
|
||||
if (initialBounds && !isNodeEnv) {
|
||||
// maximizes the application if previously maximized
|
||||
@@ -229,6 +242,9 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
initCrashReporterRenderer(mainWindow, { process: 'render | main window' });
|
||||
|
||||
url = mainWindow.webContents.getURL();
|
||||
mainWindow.webContents.send('on-page-load');
|
||||
// initializes and applies styles required for snack bar
|
||||
mainWindow.webContents.insertCSS(fs.readFileSync(path.join(__dirname, '/snackBar/style.css'), 'utf8').toString());
|
||||
if (isCustomTitleBarEnabled || isWindows10()) {
|
||||
mainWindow.webContents.insertCSS(fs.readFileSync(path.join(__dirname, '/windowsTitleBar/style.css'), 'utf8').toString());
|
||||
// This is required to initiate Windows title bar only after insertCSS
|
||||
@@ -421,6 +437,9 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
// setMenu is currently only supported on Windows and Linux
|
||||
browserWin.setMenu(null);
|
||||
}
|
||||
browserWin.webContents.send('on-page-load');
|
||||
// applies styles required for snack bar
|
||||
browserWin.webContents.insertCSS(fs.readFileSync(path.join(__dirname, '/snackBar/style.css'), 'utf8').toString());
|
||||
|
||||
initCrashReporterMain({ process: 'pop-out window' });
|
||||
initCrashReporterRenderer(browserWin, { process: 'render | pop-out window' });
|
||||
@@ -462,16 +481,29 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
// issue https://perzoinc.atlassian.net/browse/ELECTRON-172
|
||||
sendChildWinBoundsChange(browserWin);
|
||||
|
||||
// throttle full screen
|
||||
let throttledFullScreen = throttle(1000,
|
||||
handleChildWindowFullScreen.bind(null, browserWin));
|
||||
|
||||
// throttle leave full screen
|
||||
let throttledLeaveFullScreen = throttle(1000,
|
||||
handleChildWindowLeaveFullScreen.bind(null, browserWin));
|
||||
|
||||
// throttle changes so we don't flood client.
|
||||
let throttledBoundsChange = throttle(1000,
|
||||
sendChildWinBoundsChange.bind(null, browserWin));
|
||||
|
||||
browserWin.on('move', throttledBoundsChange);
|
||||
browserWin.on('resize', throttledBoundsChange);
|
||||
|
||||
browserWin.on('enter-full-screen', throttledFullScreen);
|
||||
browserWin.on('leave-full-screen', throttledLeaveFullScreen);
|
||||
|
||||
let handleChildWindowClosed = () => {
|
||||
removeWindowKey(newWinKey);
|
||||
browserWin.removeListener('move', throttledBoundsChange);
|
||||
browserWin.removeListener('resize', throttledBoundsChange);
|
||||
browserWin.removeListener('enter-full-screen', throttledFullScreen);
|
||||
browserWin.removeListener('leave-full-screen', throttledLeaveFullScreen);
|
||||
};
|
||||
|
||||
browserWin.on('close', () => {
|
||||
@@ -513,15 +545,23 @@ function doCreateMainWindow(initialUrl, initialBounds, isCustomTitleBar) {
|
||||
* Register shortcuts for the app
|
||||
*/
|
||||
function registerShortcuts() {
|
||||
|
||||
// Register dev tools shortcut
|
||||
globalShortcut.register(isMac ? 'Alt+Command+I' : 'Ctrl+Shift+I', () => {
|
||||
let focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
|
||||
function devTools() {
|
||||
const focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
|
||||
if (focusedWindow && !focusedWindow.isDestroyed()) {
|
||||
focusedWindow.webContents.toggleDevTools();
|
||||
}
|
||||
}
|
||||
|
||||
app.on('browser-window-focus', function () {
|
||||
globalShortcut.register(isMac ? 'Cmd+Alt+I' : 'Ctrl+Shift+I', devTools);
|
||||
});
|
||||
|
||||
|
||||
app.on('browser-window-blur', function () {
|
||||
globalShortcut.unregister(isMac ? 'Cmd+Alt+I' : 'Ctrl+Shift+I');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -799,6 +839,21 @@ function sendChildWinBoundsChange(window) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the child window is set to full screen
|
||||
*/
|
||||
function handleChildWindowFullScreen(browserWindow) {
|
||||
const snackBarContent = i18n.getMessageFor('SnackBar');
|
||||
browserWindow.webContents.send('window-enter-full-screen', { snackBar: snackBarContent });
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the child window left full screen
|
||||
*/
|
||||
function handleChildWindowLeaveFullScreen(browserWindow) {
|
||||
browserWindow.webContents.send('window-leave-full-screen');
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an external url in the system's default browser
|
||||
* @param urlToOpen
|
||||
@@ -974,6 +1029,26 @@ function repositionMainWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that handles key press
|
||||
* @param keyCode {number}
|
||||
*/
|
||||
function handleKeyPress(keyCode) {
|
||||
switch (keyCode) {
|
||||
case KeyCodes.Esc: {
|
||||
const focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
|
||||
if (focusedWindow && !focusedWindow.isDestroyed() && focusedWindow.isFullScreen()) {
|
||||
focusedWindow.setFullScreen(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
createMainWindow: createMainWindow,
|
||||
getMainWindow: getMainWindow,
|
||||
@@ -985,5 +1060,6 @@ module.exports = {
|
||||
setBoundsChangeWindow: setBoundsChangeWindow,
|
||||
verifyDisplays: verifyDisplays,
|
||||
getMenu: getMenu,
|
||||
setIsAutoReload: setIsAutoReload
|
||||
setIsAutoReload: setIsAutoReload,
|
||||
handleKeyPress: handleKeyPress
|
||||
};
|
||||
|
@@ -73,6 +73,11 @@
|
||||
"Show crash dump in Finder": "Show crash dump in Finder",
|
||||
"Show Logs in Finder": "Show Logs in Finder",
|
||||
"Show Logs in Explorer": "Show Logs in Explorer",
|
||||
"SnackBar": {
|
||||
"Press ": "Press ",
|
||||
"esc": "esc",
|
||||
" to exit full screen": " to exit full screen"
|
||||
},
|
||||
"Speech": "Speech",
|
||||
"Start Speaking": "Start Speaking",
|
||||
"Stop Speaking": "Stop Speaking",
|
||||
|
@@ -73,6 +73,11 @@
|
||||
"Show crash dump in Finder": "Show crash dump in Finder",
|
||||
"Show Logs in Finder": "Show Logs in Finder",
|
||||
"Show Logs in Explorer": "Show Logs in Explorer",
|
||||
"SnackBar": {
|
||||
"Press ": "Press ",
|
||||
"esc": "esc",
|
||||
" to exit full screen": " to exit full screen"
|
||||
},
|
||||
"Speech": "Speech",
|
||||
"Start Speaking": "Start Speaking",
|
||||
"Stop Speaking": "Stop Speaking",
|
||||
|
@@ -73,6 +73,11 @@
|
||||
"Show crash dump in Finder": "ファインダーにクラッシュダンプを表示",
|
||||
"Show Logs in Finder": "ファインダーにログを表示",
|
||||
"Show Logs in Explorer": "Explorerにログを表示",
|
||||
"SnackBar": {
|
||||
"Press ": "全画面表示を終了するには ",
|
||||
"esc": "esc",
|
||||
" to exit full screen": " を押します"
|
||||
},
|
||||
"Speech": "スピーチ",
|
||||
"Start Speaking": "スピーチを開始",
|
||||
"Stop Speaking": "スピーチを終了",
|
||||
|
@@ -73,6 +73,11 @@
|
||||
"Show crash dump in Finder": "ファインダーにクラッシュダンプを表示",
|
||||
"Show Logs in Finder": "ファインダーにログを表示",
|
||||
"Show Logs in Explorer": "Explorerにログを表示",
|
||||
"SnackBar": {
|
||||
"Press ": "全画面表示を終了するには ",
|
||||
"esc": "esc",
|
||||
" to exit full screen": " を押します"
|
||||
},
|
||||
"Speech": "スピーチ",
|
||||
"Start Speaking": "スピーチを開始",
|
||||
"Stop Speaking": "スピーチを終了",
|
||||
|
Reference in New Issue
Block a user