Browse Source

Format 87d48a6

pull/3163/head
prettifier[bot] 4 years ago committed by GitHub
parent
commit
c82d2e3bb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 645
      electron/main.js
  2. 7
      resources/css/screenselector.css
  3. 76
      resources/js/rambox-service-api.js
  4. 80
      resources/js/screenselector.js

645
electron/main.js

@ -1,87 +1,101 @@
'use strict';
const {app, BrowserWindow, shell, Menu, ipcMain, nativeImage, session} = require('electron');
"use strict";
const {
app,
BrowserWindow,
shell,
Menu,
ipcMain,
nativeImage,
session,
} = require("electron");
// Tray
const tray = require('./tray');
const tray = require("./tray");
// AutoLaunch
var AutoLaunch = require('auto-launch-patched');
var AutoLaunch = require("auto-launch-patched");
// Configuration
const Config = require('electron-store');
const Config = require("electron-store");
// Development
const isDev = require('electron-is-dev');
const isDev = require("electron-is-dev");
// Updater
const updater = require('./updater');
const updater = require("./updater");
// File System
var fs = require("fs");
const path = require('path');
const path = require("path");
// Disk usage:
// const disk = require('diskusage');
if ( isDev ) app.getVersion = function() { return require('../package.json').version; }; // FOR DEV ONLY, BECAUSE IN DEV RETURNS ELECTRON'S VERSION
if (isDev)
app.getVersion = function () {
return require("../package.json").version;
}; // FOR DEV ONLY, BECAUSE IN DEV RETURNS ELECTRON'S VERSION
// Initial Config
const config = new Config({
defaults: {
always_on_top: false
,hide_menu_bar: false
,tabbar_location: 'top'
,hide_tabbar_labels: false
,window_display_behavior: 'taskbar_tray'
,auto_launch: !isDev
,flash_frame: true
,window_close_behavior: 'keep_in_tray'
,start_minimized: false
,systemtray_indicator: true
,master_password: false
,dont_disturb: false
,disable_gpu: process.platform === 'linux'
,proxy: false
,proxyHost: ''
,proxyPort: ''
,proxyLogin: ''
,proxyPassword: ''
,locale: 'en'
,enable_hidpi_support: false
,user_agent: ''
,default_service: 'ramboxTab'
,sendStatistics: false
,x: undefined
,y: undefined
,width: 1000
,height: 800
,maximized: false
}
always_on_top: false,
hide_menu_bar: false,
tabbar_location: "top",
hide_tabbar_labels: false,
window_display_behavior: "taskbar_tray",
auto_launch: !isDev,
flash_frame: true,
window_close_behavior: "keep_in_tray",
start_minimized: false,
systemtray_indicator: true,
master_password: false,
dont_disturb: false,
disable_gpu: process.platform === "linux",
proxy: false,
proxyHost: "",
proxyPort: "",
proxyLogin: "",
proxyPassword: "",
locale: "en",
enable_hidpi_support: false,
user_agent: "",
default_service: "ramboxTab",
sendStatistics: false,
x: undefined,
y: undefined,
width: 1000,
height: 800,
maximized: false,
},
});
// Fix issues with HiDPI scaling on Windows platform
if (config.get('enable_hidpi_support') && (process.platform === 'win32')) {
app.commandLine.appendSwitch('high-dpi-support', 'true')
app.commandLine.appendSwitch('force-device-scale-factor', '1')
if (config.get("enable_hidpi_support") && process.platform === "win32") {
app.commandLine.appendSwitch("high-dpi-support", "true");
app.commandLine.appendSwitch("force-device-scale-factor", "1");
}
app.commandLine.appendSwitch('lang', config.get('locale') === 'en' ? 'en-US' : config.get('locale'));
app.commandLine.appendSwitch(
"lang",
config.get("locale") === "en" ? "en-US" : config.get("locale")
);
// Temporary fix to load Twitter and other websites inside webviews
// Bug related with Electron: https://github.com/electron/electron/issues/25469
app.commandLine.appendSwitch('disable-features', 'CrossOriginOpenerPolicy');
app.commandLine.appendSwitch("disable-features", "CrossOriginOpenerPolicy");
// Because we build it using Squirrel, it will assign UserModelId automatically, so we match it here to display notifications correctly.
// https://github.com/electron-userland/electron-builder/issues/362
app.setAppUserModelId('com.grupovrs.ramboxce');
app.setAppUserModelId("com.grupovrs.ramboxce");
// Menu
const appMenu = require('./menu')(config);
const appMenu = require("./menu")(config);
// Configure AutoLaunch
let appLauncher;
if (!isDev) {
appLauncher = new AutoLaunch({
name: 'Rambox'
,isHidden: config.get('start_minimized')
name: "Rambox",
isHidden: config.get("start_minimized"),
});
config.get('auto_launch') ? appLauncher.enable() : appLauncher.disable();
config.get("auto_launch") ? appLauncher.enable() : appLauncher.disable();
}
// Keep a global reference of the window object, if you don't, the window will
@ -92,41 +106,50 @@ let isQuitting = false;
function createWindow() {
// Create the browser window using the state information
mainWindow = new BrowserWindow({
title: 'Rambox'
,icon: __dirname + '/../resources/Icon.' + (process.platform === 'linux' ? 'png' : 'ico')
,backgroundColor: '#FFF'
,x: config.get('x')
,y: config.get('y')
,width: config.get('width')
,height: config.get('height')
,alwaysOnTop: config.get('always_on_top')
,autoHideMenuBar: config.get('hide_menu_bar')
,skipTaskbar: config.get('window_display_behavior') === 'show_trayIcon'
,show: !config.get('start_minimized')
,acceptFirstMouse: true
,webPreferences: {
enableRemoteModule: true
,plugins: true
,partition: 'persist:rambox'
,nodeIntegration: true
,webviewTag: true
,contextIsolation: false
,spellcheck: false
}
title: "Rambox",
icon:
__dirname +
"/../resources/Icon." +
(process.platform === "linux" ? "png" : "ico"),
backgroundColor: "#FFF",
x: config.get("x"),
y: config.get("y"),
width: config.get("width"),
height: config.get("height"),
alwaysOnTop: config.get("always_on_top"),
autoHideMenuBar: config.get("hide_menu_bar"),
skipTaskbar: config.get("window_display_behavior") === "show_trayIcon",
show: !config.get("start_minimized"),
acceptFirstMouse: true,
webPreferences: {
enableRemoteModule: true,
plugins: true,
partition: "persist:rambox",
nodeIntegration: true,
webviewTag: true,
contextIsolation: false,
spellcheck: false,
},
});
// Check if user has defined a custom User-Agent
if ( config.get('user_agent').length > 0 ) mainWindow.webContents.setUserAgent( config.get('user_agent') );
if (config.get("user_agent").length > 0)
mainWindow.webContents.setUserAgent(config.get("user_agent"));
// Wait for the mainWindow.loadURL(..) and the optional mainWindow.webContents.openDevTools()
// to be finished before minimizing
config.get('start_minimized') && mainWindow.webContents.once('did-finish-load', () => config.get('window_display_behavior') === 'show_trayIcon' ? mainWindow.hide() : mainWindow.minimize());
config.get("start_minimized") &&
mainWindow.webContents.once("did-finish-load", () =>
config.get("window_display_behavior") === "show_trayIcon"
? mainWindow.hide()
: mainWindow.minimize()
);
// Check if the window its outside of the view (ex: multi monitor setup)
const { positionOnScreen } = require('./utils/positionOnScreen');
const inBounds = positionOnScreen([config.get('x'), config.get('y')]);
const { positionOnScreen } = require("./utils/positionOnScreen");
const inBounds = positionOnScreen([config.get("x"), config.get("y")]);
if (inBounds) {
mainWindow.setPosition(config.get('x'), config.get('y'));
mainWindow.setPosition(config.get("x"), config.get("y"));
} else {
mainWindow.center();
}
@ -137,28 +160,36 @@ function createWindow () {
if (isDev) mainWindow.webContents.openDevTools();
// and load the index.html of the app.
mainWindow.loadURL('file://' + __dirname + '/../index.html');
mainWindow.loadURL("file://" + __dirname + "/../index.html");
Menu.setApplicationMenu(appMenu);
tray.create(mainWindow, config);
if ( process.argv.indexOf('--without-update') === -1 ) updater.initialize(mainWindow);
if (process.argv.indexOf("--without-update") === -1)
updater.initialize(mainWindow);
// Open links in default browser
mainWindow.webContents.on('new-window', function(e, url, frameName, disposition, options) {
const protocol = require('url').parse(url).protocol;
mainWindow.webContents.on(
"new-window",
function (e, url, frameName, disposition, options) {
const protocol = require("url").parse(url).protocol;
switch (disposition) {
case 'new-window':
case "new-window":
e.preventDefault();
const win = new BrowserWindow(options);
if ( config.get('user_agent').length > 0 ) win.webContents.setUserAgent( config.get('user_agent') );
win.once('ready-to-show', () => win.show());
if (config.get("user_agent").length > 0)
win.webContents.setUserAgent(config.get("user_agent"));
win.once("ready-to-show", () => win.show());
win.loadURL(url);
e.newGuest = win;
break;
case 'foreground-tab':
if (protocol === 'http:' || protocol === 'https:' || protocol === 'mailto:') {
case "foreground-tab":
if (
protocol === "http:" ||
protocol === "https:" ||
protocol === "mailto:"
) {
e.preventDefault();
shell.openExternal(url);
}
@ -166,45 +197,60 @@ function createWindow () {
default:
break;
}
});
}
);
mainWindow.webContents.on('will-navigate', function(event, url) {
mainWindow.webContents.on("will-navigate", function (event, url) {
event.preventDefault();
});
// BrowserWindow events
mainWindow.on('page-title-updated', (e, title) => updateBadge(title));
mainWindow.on('maximize', function(e) { config.set('maximized', true); });
mainWindow.on('unmaximize', function(e) { config.set('maximized', false); });
mainWindow.on('resize', function(e) { if (!mainWindow.isMaximized()) config.set(mainWindow.getBounds()); });
mainWindow.on('move', function(e) { if (!mainWindow.isMaximized()) config.set(mainWindow.getBounds()); });
mainWindow.on('app-command', (e, cmd) => {
mainWindow.on("page-title-updated", (e, title) => updateBadge(title));
mainWindow.on("maximize", function (e) {
config.set("maximized", true);
});
mainWindow.on("unmaximize", function (e) {
config.set("maximized", false);
});
mainWindow.on("resize", function (e) {
if (!mainWindow.isMaximized()) config.set(mainWindow.getBounds());
});
mainWindow.on("move", function (e) {
if (!mainWindow.isMaximized()) config.set(mainWindow.getBounds());
});
mainWindow.on("app-command", (e, cmd) => {
// Navigate the window back when the user hits their mouse back button
if ( cmd === 'browser-backward' ) mainWindow.webContents.executeJavaScript('if(Ext.cq1("app-main")) Ext.cq1("app-main").getActiveTab().goBack();');
if (cmd === "browser-backward")
mainWindow.webContents.executeJavaScript(
'if(Ext.cq1("app-main")) Ext.cq1("app-main").getActiveTab().goBack();'
);
// Navigate the window forward when the user hits their mouse forward button
if ( cmd === 'browser-forward' ) mainWindow.webContents.executeJavaScript('if(Ext.cq1("app-main")) Ext.cq1("app-main").getActiveTab().goForward();');
if (cmd === "browser-forward")
mainWindow.webContents.executeJavaScript(
'if(Ext.cq1("app-main")) Ext.cq1("app-main").getActiveTab().goForward();'
);
});
// Emitted when the window is closed.
mainWindow.on('close', function(e) {
mainWindow.on("close", function (e) {
if (!isQuitting) {
e.preventDefault();
switch (process.platform) {
case 'darwin':
case "darwin":
app.hide();
break;
case 'linux':
case 'win32':
case "linux":
case "win32":
default:
switch (config.get('window_close_behavior')) {
case 'keep_in_tray':
switch (config.get("window_close_behavior")) {
case "keep_in_tray":
mainWindow.hide();
break;
case 'keep_in_tray_and_taskbar':
case "keep_in_tray_and_taskbar":
mainWindow.minimize();
break;
case 'quit':
case "quit":
app.quit();
break;
}
@ -212,65 +258,81 @@ function createWindow () {
}
}
});
mainWindow.on('minimize', function(e) {
if ( config.get('window_display_behavior') === 'show_trayIcon' ) mainWindow.setSkipTaskbar(true);
mainWindow.on("minimize", function (e) {
if (config.get("window_display_behavior") === "show_trayIcon")
mainWindow.setSkipTaskbar(true);
});
mainWindow.on('restore', function(e) {
if ( config.get('window_display_behavior') === 'show_taskbar' ) mainWindow.setSkipTaskbar(false);
mainWindow.on("restore", function (e) {
if (config.get("window_display_behavior") === "show_taskbar")
mainWindow.setSkipTaskbar(false);
});
mainWindow.on('show', function(e) {
if ( config.get('window_display_behavior') !== 'show_trayIcon' ) mainWindow.setSkipTaskbar(false);
mainWindow.on("show", function (e) {
if (config.get("window_display_behavior") !== "show_trayIcon")
mainWindow.setSkipTaskbar(false);
});
mainWindow.on('closed', function(e) {
mainWindow.on("closed", function (e) {
mainWindow = null;
});
mainWindow.once('focus', () => mainWindow.flashFrame(false));
mainWindow.once("focus", () => mainWindow.flashFrame(false));
}
let mainMasterPasswordWindow;
function createMasterPasswordWindow() {
mainMasterPasswordWindow = new BrowserWindow({
backgroundColor: '#0675A0'
,frame: false
,webPreferences: {
nodeIntegration: true
,enableRemoteModule: true
}
backgroundColor: "#0675A0",
frame: false,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
},
});
// Open the DevTools.
if (isDev) mainMasterPasswordWindow.webContents.openDevTools();
mainMasterPasswordWindow.loadURL('file://' + __dirname + '/../masterpassword.html');
mainMasterPasswordWindow.on('close', function() { mainMasterPasswordWindow = null });
mainMasterPasswordWindow.loadURL(
"file://" + __dirname + "/../masterpassword.html"
);
mainMasterPasswordWindow.on("close", function () {
mainMasterPasswordWindow = null;
});
}
function updateBadge(title) {
title = title.split(" - ")[0]; //Discard service name if present, could also contain digits
var messageCount = title.match(/\d+/g) ? parseInt(title.match(/\d+/g).join("")) : 0;
var messageCount = title.match(/\d+/g)
? parseInt(title.match(/\d+/g).join(""))
: 0;
messageCount = isNaN(messageCount) ? 0 : messageCount;
tray.setBadge(messageCount, config.get('systemtray_indicator'));
tray.setBadge(messageCount, config.get("systemtray_indicator"));
if (process.platform === 'win32') {
if (messageCount === 0) return mainWindow.setOverlayIcon(null, '');
mainWindow.webContents.send('setBadge', messageCount);
} else { // macOS & Linux
if (process.platform === "win32") {
if (messageCount === 0) return mainWindow.setOverlayIcon(null, "");
mainWindow.webContents.send("setBadge", messageCount);
} else {
// macOS & Linux
app.setBadgeCount(messageCount);
}
if ( messageCount > 0 && !mainWindow.isFocused() && !config.get('dont_disturb') && config.get('flash_frame') ) mainWindow.flashFrame(true);
if (
messageCount > 0 &&
!mainWindow.isFocused() &&
!config.get("dont_disturb") &&
config.get("flash_frame")
)
mainWindow.flashFrame(true);
}
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
if (bytes === 0) return "0 Bytes";
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
}
/* async function availableSpaceWatchDog() {
@ -295,18 +357,21 @@ function formatBytes(bytes, decimals = 2) {
}
} */
ipcMain.on('setBadge', function(event, messageCount, value) {
mainWindow.setOverlayIcon(nativeImage.createFromDataURL(value), messageCount.toString());
ipcMain.on("setBadge", function (event, messageCount, value) {
mainWindow.setOverlayIcon(
nativeImage.createFromDataURL(value),
messageCount.toString()
);
});
ipcMain.on('getConfig', function(event, arg) {
ipcMain.on("getConfig", function (event, arg) {
event.returnValue = config.store;
});
ipcMain.on('sConfig', function(event, values) {
ipcMain.on("sConfig", function (event, values) {
config.set(values);
event.returnValue = config;
});
ipcMain.on('setConfig', function(event, values) {
ipcMain.on("setConfig", function (event, values) {
config.set(values);
// hide_menu_bar
@ -319,18 +384,20 @@ ipcMain.on('setConfig', function(event, values) {
// systemtray_indicator
updateBadge(mainWindow.getTitle());
mainWindow.webContents.executeJavaScript('(function(a){if(a)a.controller.initialize(a)})(Ext.cq1("app-main"))');
mainWindow.webContents.executeJavaScript(
'(function(a){if(a)a.controller.initialize(a)})(Ext.cq1("app-main"))'
);
switch (values.window_display_behavior) {
case 'show_taskbar':
case "show_taskbar":
mainWindow.setSkipTaskbar(false);
tray.destroy();
break;
case 'show_trayIcon':
case "show_trayIcon":
mainWindow.setSkipTaskbar(true);
tray.create(mainWindow, config);
break;
case 'taskbar_tray':
case "taskbar_tray":
mainWindow.setSkipTaskbar(false);
tray.create(mainWindow, config);
break;
@ -339,12 +406,15 @@ ipcMain.on('setConfig', function(event, values) {
}
});
ipcMain.on('sendStatistics', function(event) {
event.returnValue = config.get('sendStatistics');
ipcMain.on("sendStatistics", function (event) {
event.returnValue = config.get("sendStatistics");
});
ipcMain.on('validateMasterPassword', function(event, pass) {
if ( config.get('master_password') === require('crypto').createHash('md5').update(pass).digest('hex') ) {
ipcMain.on("validateMasterPassword", function (event, pass) {
if (
config.get("master_password") ===
require("crypto").createHash("md5").update(pass).digest("hex")
) {
createWindow();
mainMasterPasswordWindow.close();
event.returnValue = true;
@ -353,25 +423,27 @@ ipcMain.on('validateMasterPassword', function(event, pass) {
});
// Handle Service Notifications
ipcMain.on('setServiceNotifications', function(event, partition, op) {
ipcMain.on("setServiceNotifications", function (event, partition, op) {
if (partition === null) return;
session.fromPartition(partition).setPermissionRequestHandler(function(webContents, permission, callback) {
if (permission === 'notifications') return callback(op);
callback(true)
session
.fromPartition(partition)
.setPermissionRequestHandler(function (webContents, permission, callback) {
if (permission === "notifications") return callback(op);
callback(true);
});
});
ipcMain.on('setDontDisturb', function(event, arg) {
config.set('dont_disturb', arg);
ipcMain.on("setDontDisturb", function (event, arg) {
config.set("dont_disturb", arg);
});
// Reload app
ipcMain.on('reloadApp', function(event) {
ipcMain.on("reloadApp", function (event) {
mainWindow.reload();
});
// Relaunch app
ipcMain.on('relaunchApp', function(event) {
ipcMain.on("relaunchApp", function (event) {
app.relaunch();
app.exit(0);
});
@ -381,7 +453,7 @@ if (!shouldQuit) {
app.quit();
return;
}
app.on('second-instance', (event, commandLine, workingDirectory) => {
app.on("second-instance", (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
@ -394,76 +466,95 @@ app.on('second-instance', (event, commandLine, workingDirectory) => {
// ALLOWED URLS POPUPS
let allowPopUp = [
'feedly.com/v3/auth/',
'identity.linuxfoundation.org/cas/login',
'auth.missiveapp.com',
'accounts.google.com/AccountChooser',
'facebook.com/v3.1/dialog/oauth?',
'accounts.google.com/o/oauth2',
'app.slack.com/files/import/gdrive',
'spikenow.com/s/account',
'app.mixmax.com/_oauth/google',
'officeapps.live.com',
'dropbox.com/profile_services/start_auth_flow',
'facebook.com/v3.2/dialog/oauth?',
'notion.so/googlepopupredirect',
'zoom.us/office365',
'figma.com/start_google_sso',
'mail.google.com/mail',
'app.slack.com/free-willy/',
'messenger.com/videocall',
'api.moo.do',
'manychat.com/fb?popup',
'=?print=true' // esta ultima checkea como anda imprimir un pedf desde gmail, si no va bie sacala
"feedly.com/v3/auth/",
"identity.linuxfoundation.org/cas/login",
"auth.missiveapp.com",
"accounts.google.com/AccountChooser",
"facebook.com/v3.1/dialog/oauth?",
"accounts.google.com/o/oauth2",
"app.slack.com/files/import/gdrive",
"spikenow.com/s/account",
"app.mixmax.com/_oauth/google",
"officeapps.live.com",
"dropbox.com/profile_services/start_auth_flow",
"facebook.com/v3.2/dialog/oauth?",
"notion.so/googlepopupredirect",
"zoom.us/office365",
"figma.com/start_google_sso",
"mail.google.com/mail",
"app.slack.com/free-willy/",
"messenger.com/videocall",
"api.moo.do",
"manychat.com/fb?popup",
"=?print=true", // esta ultima checkea como anda imprimir un pedf desde gmail, si no va bie sacala
];
app.on('web-contents-created', (webContentsCreatedEvent, contents) => {
if (contents.getType() !== 'webview') return;
app.on("web-contents-created", (webContentsCreatedEvent, contents) => {
if (contents.getType() !== "webview") return;
// Block some Deep links to prevent that open its app (Ex: Slack)
contents.on('will-navigate', (event, url) => url.substring(0, 8) === 'slack://' && event.preventDefault());
contents.on(
"will-navigate",
(event, url) => url.substring(0, 8) === "slack://" && event.preventDefault()
);
// New Window handler
contents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures, referrer, postBody) => {
contents.on(
"new-window",
(
event,
url,
frameName,
disposition,
options,
additionalFeatures,
referrer,
postBody
) => {
// If the url is about:blank we allow the window and handle it in 'did-create-window'
if (['about:blank', 'about:blank#blocked'].includes(url)) {
if (["about:blank", "about:blank#blocked"].includes(url)) {
event.preventDefault();
Object.assign(options, { show: false });
const win = new BrowserWindow(options);
win.center();
let once = false;
win.webContents.on('will-navigate', (e, nextURL) => {
win.webContents.on("will-navigate", (e, nextURL) => {
if (once) return;
if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return;
if (["about:blank", "about:blank#blocked"].includes(nextURL)) return;
once = true;
let allow = false;
allowPopUp.forEach(url => nextURL.indexOf(url) > -1 && (allow = true));
allowPopUp.forEach(
(url) => nextURL.indexOf(url) > -1 && (allow = true)
);
// If the url is in aboutBlankOnlyWindow we handle this as a popup window
if (allow) return win.show();
shell.openExternal(nextURL);
win.close()
})
win.close();
});
event.newGuest = win;
return;
}
// We check if url is in the allowPopUpLoginURLs or allowForegroundTabURLs in Firebase to open a as a popup,
// if it is not we send this to the app
let allow = false;
allowPopUp.forEach(allowed => url.indexOf(allowed) > -1 && (allow = true));
allowPopUp.forEach(
(allowed) => url.indexOf(allowed) > -1 && (allow = true)
);
if (allow) return;
shell.openExternal(url);
event.preventDefault();
});
contents.on('did-create-window', (win, details) => {
}
);
contents.on("did-create-window", (win, details) => {
// Here we center the new window.
win.center();
// The following code is for handling the about:blank cases only.
if (!['about:blank', 'about:blank#blocked'].includes(details.url)) return;
if (!["about:blank", "about:blank#blocked"].includes(details.url)) return;
let once = false;
win.webContents.on('will-navigate', (e, nextURL) => {
win.webContents.on("will-navigate", (e, nextURL) => {
if (once) return;
if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return;
if (["about:blank", "about:blank#blocked"].includes(nextURL)) return;
once = true;
let allow = false;
allowPopUp.forEach(url => nextURL.indexOf(url) > -1 && (allow = true));
allowPopUp.forEach((url) => nextURL.indexOf(url) > -1 && (allow = true));
// If the url is in aboutBlankOnlyWindow we handle this as a popup window
if (allow) return win.show();
shell.openExternal(url);
@ -474,10 +565,10 @@ app.on('web-contents-created', (webContentsCreatedEvent, contents) => {
// Code for downloading images as temporal files
// Credit: Ghetto Skype (https://github.com/stanfieldr/ghetto-skype)
const tmp = require('tmp');
const mime = require('mime');
const tmp = require("tmp");
const mime = require("mime");
var imageCache = {};
ipcMain.on('image:download', function(event, url, partition) {
ipcMain.on("image:download", function (event, url, partition) {
let file = imageCache[url];
if (file) {
if (file.complete) {
@ -489,22 +580,24 @@ ipcMain.on('image:download', function(event, url, partition) {
}
let tmpWindow = new BrowserWindow({
show: false
,webPreferences: {
partition: partition
}
show: false,
webPreferences: {
partition: partition,
},
});
if ( config.get('user_agent').length > 0 ) tmpWindow.webContents.setUserAgent( config.get('user_agent') );
if (config.get("user_agent").length > 0)
tmpWindow.webContents.setUserAgent(config.get("user_agent"));
tmpWindow.webContents.session.once('will-download', (event, downloadItem) => {
tmpWindow.webContents.session.once("will-download", (event, downloadItem) => {
imageCache[url] = file = {
path: tmp.tmpNameSync() + '.' + mime.extension(downloadItem.getMimeType())
,complete: false
path:
tmp.tmpNameSync() + "." + mime.extension(downloadItem.getMimeType()),
complete: false,
};
downloadItem.setSavePath(file.path);
downloadItem.once('done', () => {
downloadItem.once("done", () => {
tmpWindow.destroy();
tmpWindow = null;
shell.openItem(file.path);
@ -516,72 +609,109 @@ ipcMain.on('image:download', function(event, url, partition) {
});
// Hangouts
ipcMain.on('image:popup', function(event, url, partition) {
ipcMain.on("image:popup", function (event, url, partition) {
let tmpWindow = new BrowserWindow({
width: mainWindow.getBounds().width
,height: mainWindow.getBounds().height
,parent: mainWindow
,icon: __dirname + '/../resources/Icon.ico'
,backgroundColor: '#FFF'
,autoHideMenuBar: true
,skipTaskbar: true
,webPreferences: {
partition: partition
}
width: mainWindow.getBounds().width,
height: mainWindow.getBounds().height,
parent: mainWindow,
icon: __dirname + "/../resources/Icon.ico",
backgroundColor: "#FFF",
autoHideMenuBar: true,
skipTaskbar: true,
webPreferences: {
partition: partition,
},
});
if ( config.get('user_agent').length > 0 ) tmpWindow.webContents.setUserAgent( config.get('user_agent') );
if (config.get("user_agent").length > 0)
tmpWindow.webContents.setUserAgent(config.get("user_agent"));
tmpWindow.maximize();
tmpWindow.loadURL(url);
});
ipcMain.on('toggleWin', function(event, allwaysShow) {
if ( config.get('window_display_behavior') !== 'show_trayIcon' ) mainWindow.setSkipTaskbar(false);
if ( !mainWindow.isMinimized() && mainWindow.isMaximized() && mainWindow.isVisible() ) { // Maximized
ipcMain.on("toggleWin", function (event, allwaysShow) {
if (config.get("window_display_behavior") !== "show_trayIcon")
mainWindow.setSkipTaskbar(false);
if (
!mainWindow.isMinimized() &&
mainWindow.isMaximized() &&
mainWindow.isVisible()
) {
// Maximized
!allwaysShow ? mainWindow.close() : mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Minimized
if ( process.platform === 'linux' ) {
} else if (
mainWindow.isMinimized() &&
!mainWindow.isMaximized() &&
!mainWindow.isVisible()
) {
// Minimized
if (process.platform === "linux") {
mainWindow.minimize();
mainWindow.restore();
mainWindow.focus();
return
return;
}
mainWindow.restore();
} else if ( !mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible() ) { // Windowed mode
} else if (
!mainWindow.isMinimized() &&
!mainWindow.isMaximized() &&
mainWindow.isVisible()
) {
// Windowed mode
!allwaysShow ? mainWindow.close() : mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible() ) { // Closed to taskbar
if ( process.platform === 'linux' ) {
} else if (
mainWindow.isMinimized() &&
!mainWindow.isMaximized() &&
mainWindow.isVisible()
) {
// Closed to taskbar
if (process.platform === "linux") {
mainWindow.minimize();
mainWindow.restore();
mainWindow.focus();
return
return;
}
mainWindow.restore();
} else if ( !mainWindow.isMinimized() && mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed maximized to tray
} else if (
!mainWindow.isMinimized() &&
mainWindow.isMaximized() &&
!mainWindow.isVisible()
) {
// Closed maximized to tray
mainWindow.show();
} else if ( !mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed windowed to tray
} else if (
!mainWindow.isMinimized() &&
!mainWindow.isMaximized() &&
!mainWindow.isVisible()
) {
// Closed windowed to tray
mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed minimized to tray
} else if (
mainWindow.isMinimized() &&
!mainWindow.isMaximized() &&
!mainWindow.isVisible()
) {
// Closed minimized to tray
mainWindow.show();
} else {
if ( process.platform === 'linux' ) {
if (process.platform === "linux") {
mainWindow.minimize();
mainWindow.maximize();
mainWindow.focus();
return
return;
}
mainWindow.restore();
}
});
// ScreenShare
ipcMain.on('screenShare:show', (event, screenList) => {
ipcMain.on("screenShare:show", (event, screenList) => {
let tmpWindow = new BrowserWindow({
width: 600,
height: 500,
icon: __dirname + '/../resources/Icon.ico',
icon: __dirname + "/../resources/Icon.ico",
autoHideMenuBar: true,
transparent: true,
show: true,
@ -598,67 +728,70 @@ ipcMain.on('screenShare:show', (event, screenList) => {
};
const onCancel = () => {
event.sender.send('screenShare:cancel');
event.sender.send("screenShare:cancel");
close();
};
const onShare = (_, shareId) => {
event.sender.send('screenShare:share', shareId);
event.sender.send("screenShare:share", shareId);
close();
};
ipcMain.handle('screenShare:getSources', () => screenList);
ipcMain.on('screenShare:cancelSelection', onCancel);
ipcMain.on('screenShare:selectScreen', onShare);
ipcMain.handle("screenShare:getSources", () => screenList);
ipcMain.on("screenShare:cancelSelection", onCancel);
ipcMain.on("screenShare:selectScreen", onShare);
tmpWindow.on('closed', () => {
ipcMain.removeHandler('screenShare:getSources');
ipcMain.removeAllListeners('screenShare:cancelSelection');
ipcMain.removeAllListeners('screenShare:selectScreen');
tmpWindow.on("closed", () => {
ipcMain.removeHandler("screenShare:getSources");
ipcMain.removeAllListeners("screenShare:cancelSelection");
ipcMain.removeAllListeners("screenShare:selectScreen");
});
tmpWindow.loadFile(__dirname + '/../screenselector.html');
tmpWindow.loadFile(__dirname + "/../screenselector.html");
});
// Proxy
if ( config.get('proxy') ) {
app.commandLine.appendSwitch('proxy-server', config.get('proxyHost')+':'+config.get('proxyPort'));
app.on('login', (event, webContents, request, authInfo, callback) => {
if(!authInfo.isProxy)
return;
if (config.get("proxy")) {
app.commandLine.appendSwitch(
"proxy-server",
config.get("proxyHost") + ":" + config.get("proxyPort")
);
app.on("login", (event, webContents, request, authInfo, callback) => {
if (!authInfo.isProxy) return;
event.preventDefault();
callback(config.get('proxyLogin'), config.get('proxyPassword'))
})
callback(config.get("proxyLogin"), config.get("proxyPassword"));
});
}
// Disable GPU Acceleration for Linux
// to prevent White Page bug
// https://github.com/electron/electron/issues/6139
// https://github.com/saenzramiro/rambox/issues/181
if ( config.get('disable_gpu') ) app.disableHardwareAcceleration();
if (config.get("disable_gpu")) app.disableHardwareAcceleration();
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
config.get('master_password') ? createMasterPasswordWindow() : createWindow();
app.on("ready", function () {
config.get("master_password") ? createMasterPasswordWindow() : createWindow();
// setInterval(availableSpaceWatchDog, 1000 * 60);
});
// Quit when all windows are closed.
app.on('window-all-closed', function () {
app.on("window-all-closed", function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
if (process.platform !== "darwin") {
app.quit();
}
});
// Only macOS: On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
app.on('activate', function () {
app.on("activate", function () {
if (mainWindow === null && mainMasterPasswordWindow === null) {
config.get('master_password') ? createMasterPasswordWindow() : createWindow();
config.get("master_password")
? createMasterPasswordWindow()
: createWindow();
}
if (mainWindow) {
@ -666,6 +799,6 @@ app.on('activate', function () {
}
});
app.on('before-quit', function () {
app.on("before-quit", function () {
isQuitting = true;
});

7
resources/css/screenselector.css

@ -1,4 +1,5 @@
html, body {
html,
body {
width: 100%;
height: 100%;
margin: 0;
@ -36,7 +37,8 @@ html, body {
-webkit-app-region: no-drag;
}
.screen-selector ul.type li.active, .screen-selector ul.type li:hover {
.screen-selector ul.type li.active,
.screen-selector ul.type li:hover {
color: #426ba3;
border-color: #426ba3;
}
@ -113,7 +115,6 @@ html, body {
display: inline-block;
width: 100%;
border-top: solid 1px #cdcdcd;
}
.screen-selector .footer button {

76
resources/js/rambox-service-api.js

@ -2,8 +2,11 @@
* This file is loaded in the service web views to provide a Rambox API.
*/
const { desktopCapturer, ipcRenderer } = require('electron');
const { ContextMenuBuilder, ContextMenuListener } = require('electron-contextmenu-wrapper');
const { desktopCapturer, ipcRenderer } = require("electron");
const {
ContextMenuBuilder,
ContextMenuListener,
} = require("electron-contextmenu-wrapper");
/**
* Make the Rambox API available via a global "rambox" variable.
@ -18,15 +21,15 @@ window.rambox = {};
* @param {*} count The unread count
*/
window.rambox.setUnreadCount = function (count) {
ipcRenderer.sendToHost('rambox.setUnreadCount', count);
ipcRenderer.sendToHost("rambox.setUnreadCount", count);
};
/**
* Clears the unread count.
*/
window.rambox.clearUnreadCount = function () {
ipcRenderer.sendToHost('rambox.clearUnreadCount');
}
ipcRenderer.sendToHost("rambox.clearUnreadCount");
};
/**
* Override to add notification click event to display Rambox window and activate service tab
@ -35,74 +38,89 @@ var NativeNotification = Notification;
Notification = function (title, options) {
var notification = new NativeNotification(title, options);
notification.addEventListener('click', function() {
ipcRenderer.sendToHost('rambox.showWindowAndActivateTab');
notification.addEventListener("click", function () {
ipcRenderer.sendToHost("rambox.showWindowAndActivateTab");
});
//It seems that gmail is checking if such event handler func are available. Just remplacing them by a void function that is always returning true is making the thing right!
notification.addEventListener = function() {return true};
notification.attachEvent = function() {return true};
notification.addListener = function() {return true};
notification.addEventListener = function () {
return true;
};
notification.attachEvent = function () {
return true;
};
notification.addListener = function () {
return true;
};
return notification;
}
};
Notification.prototype = NativeNotification.prototype;
Notification.permission = NativeNotification.permission;
Notification.requestPermission = NativeNotification.requestPermission.bind(Notification);
Notification.requestPermission = NativeNotification.requestPermission.bind(
Notification
);
window.rambox.contextMenuBuilder = new ContextMenuBuilder();
window.rambox.contextMenuListener = new ContextMenuListener(function(event, info) {
window.rambox.contextMenuListener = new ContextMenuListener(function (
event,
info
) {
window.rambox.contextMenuBuilder.showPopupMenu(info);
});
const mousetrap = require('mousetrap');
mousetrap.bind(process.platform === 'darwin' ? ['command+left', 'command+right'] : ['alt+left', 'alt+right'], e => {
if (location.href.indexOf('slack.com') !== -1) return;
e.key === 'ArrowLeft' ? history.back() : history.forward();
});
const mousetrap = require("mousetrap");
mousetrap.bind(
process.platform === "darwin"
? ["command+left", "command+right"]
: ["alt+left", "alt+right"],
(e) => {
if (location.href.indexOf("slack.com") !== -1) return;
e.key === "ArrowLeft" ? history.back() : history.forward();
}
);
// ScreenShare
window.navigator.mediaDevices.getDisplayMedia = () =>
new Promise(async (resolve, reject) => {
try {
const sources = await desktopCapturer.getSources({
types: ['screen', 'window'],
types: ["screen", "window"],
});
const unlisten = () => {
ipcRenderer.removeAllListeners('screenShare:cancel');
ipcRenderer.removeAllListeners('screenShare:share');
ipcRenderer.removeAllListeners("screenShare:cancel");
ipcRenderer.removeAllListeners("screenShare:share");
};
ipcRenderer.on('screenShare:cancel', () => {
ipcRenderer.on("screenShare:cancel", () => {
unlisten();
reject(new Error('Cancelled by user'));
reject(new Error("Cancelled by user"));
});
ipcRenderer.on('screenShare:share', (_, shareId) => {
ipcRenderer.on("screenShare:share", (_, shareId) => {
unlisten();
window.navigator.mediaDevices
.getUserMedia({
audio: false,
video: {
mandatory: {
chromeMediaSource: 'desktop',
chromeMediaSource: "desktop",
chromeMediaSourceId: shareId,
},
},
})
.then(stream => resolve(stream));
.then((stream) => resolve(stream));
});
const mappedSources = sources.map(it => ({
const mappedSources = sources.map((it) => ({
id: it.id,
name: it.name,
thumbnail: it.thumbnail.toDataURL(),
}));
ipcRenderer.send('screenShare:show', mappedSources);
ipcRenderer.send("screenShare:show", mappedSources);
} catch (err) {
reject(err);
}

80
resources/js/screenselector.js

@ -1,77 +1,91 @@
const { ipcRenderer } = require('electron');
const { ipcRenderer } = require("electron");
let sourceList, contentList, typeButtons, shareButton, cancelButton, activeItem, activeTab = 'screen';
let sourceList,
contentList,
typeButtons,
shareButton,
cancelButton,
activeItem,
activeTab = "screen";
const getItemDOM = item => {
const li = document.createElement('li');
li.setAttribute('data-id', item.id);
const getItemDOM = (item) => {
const li = document.createElement("li");
li.setAttribute("data-id", item.id);
li.innerHTML = `<div class="content"><div class="img-wrapper"><img src="${item.thumbnail}" /></div><span>${item.name}</span></div>`;
li.addEventListener('click', onItemClick, false);
li.addEventListener("click", onItemClick, false);
return li;
};
const updateTab = () => {
const sources = sourceList.filter(it => it.id.indexOf(activeTab) === 0);
contentList.innerHTML = '';
sources.forEach(source => contentList.appendChild(getItemDOM(source)));
const sources = sourceList.filter((it) => it.id.indexOf(activeTab) === 0);
contentList.innerHTML = "";
sources.forEach((source) => contentList.appendChild(getItemDOM(source)));
};
const bindTypeClick = () => {
typeButtons.forEach(it => it.addEventListener('click', onChangeType, false));
typeButtons.forEach((it) =>
it.addEventListener("click", onChangeType, false)
);
};
const bindActionsClick = () => {
shareButton.addEventListener('click', onShareClick, false);
cancelButton.addEventListener('click', onCancelClick, false);
shareButton.addEventListener("click", onShareClick, false);
cancelButton.addEventListener("click", onCancelClick, false);
};
const onChangeType = event => {
const onChangeType = (event) => {
event.preventDefault();
if (!event.target.classList.contains('active')) {
if (!event.target.classList.contains("active")) {
activeTab = event.target.dataset.type;
typeButtons.forEach(it => it.classList.remove('active'));
event.target.classList.add('active');
typeButtons.forEach((it) => it.classList.remove("active"));
event.target.classList.add("active");
updateTab();
}
};
const onItemClick = event => {
const onItemClick = (event) => {
event.preventDefault();
if (!event.currentTarget.classList.contains('active')) {
if (!event.currentTarget.classList.contains("active")) {
activeItem = event.currentTarget.dataset.id;
document.querySelectorAll('.preview li').forEach(it => it.classList.remove('active'));
event.currentTarget.classList.add('active');
document
.querySelectorAll(".preview li")
.forEach((it) => it.classList.remove("active"));
event.currentTarget.classList.add("active");
changeShareState();
}
};
const onCancelClick = event => {
const onCancelClick = (event) => {
event.preventDefault();
ipcRenderer.send('screenShare:cancelSelection');
ipcRenderer.send("screenShare:cancelSelection");
};
const onShareClick = event => {
const onShareClick = (event) => {
event.preventDefault();
if (activeItem) {
ipcRenderer.send('screenShare:selectScreen', activeItem);
ipcRenderer.send("screenShare:selectScreen", activeItem);
}
};
const changeShareState = () => {
if (shareButton.getAttribute('disabled') !== null) {
shareButton.removeAttribute('disabled');
if (shareButton.getAttribute("disabled") !== null) {
shareButton.removeAttribute("disabled");
}
};
window.addEventListener('load', async () => {
sourceList = await ipcRenderer.invoke('screenShare:getSources');
window.addEventListener(
"load",
async () => {
sourceList = await ipcRenderer.invoke("screenShare:getSources");
contentList = document.querySelector('.preview');
typeButtons = document.querySelectorAll('.type li');
shareButton = document.querySelector('#share');
cancelButton = document.querySelector('#cancel');
contentList = document.querySelector(".preview");
typeButtons = document.querySelectorAll(".type li");
shareButton = document.querySelector("#share");
cancelButton = document.querySelector("#cancel");
bindTypeClick();
bindActionsClick();
updateTab();
}, false);
},
false
);

Loading…
Cancel
Save