hamsket icon indicating copy to clipboard operation
hamsket copied to clipboard

Screen sharing on Teams

Open ngoonee opened this issue 3 years ago • 10 comments

Currently Hamsket doesn't support this. I was going to write this down to being Electron-linked, but then I realised the Chrome browser is able to screen share using WebRTC (on Wayland, and with the WebRTC Pipewire support enabled in chrome://flags).

Does this mean Hamsket could potentially enable pipewire support (and hence Teams screenshare support) as well?

ngoonee avatar Nov 02 '20 03:11 ngoonee

To be honest, this would be more of a question for the Electron team. I'm happy to wire up anything they put out, but they have to actually release the functionality first.

It's part of the reason I keep wishing that Servo was a good embedding alternative. Chrome and Electron move in mysterious ways, and often not toward the ways that would make me any happier as a developer, or as a user of my own software. :)

TheGoddessInari avatar Nov 03 '20 03:11 TheGoddessInari

Am sure you know better what's going on internally. Any idea who I can annoy about this (and does hamsket pin to a particular version of electron, and does electron track specific versions/features of chromium?)

ngoonee avatar Nov 03 '20 04:11 ngoonee

I'm mostly following whatever the latest stable version is, as long as nothing appears to break. I'm not closely following how Electron does or doesn't follow Chromium features, because it doesn't really matter.

Electron throws stuff downstream, I get to see if it can work or not, hope for fixes and improvements to things that are have been impacted negatively in the past.

If I had any chance, I'd have been trying to get patches accepted upstream, but that's much less of a thing in the JavaScript community, I learned, which is the whole reason why Hamsket even exists. If upstream was responsive, there never would've been a fork. It's just that now, there's a different (unresponsive) upstream, but at least I can make improvements to the code wherever I can. I can't just go and "fix all that's wrong with Electron", too.

If I ever got enough time, peace, & money, I'd do whatever it takes to make my own stable Embedding Interface for Servo (instead of Chromium), rewrite Hamsket in that, and we'd all get better security, performance, and everything else.

Servo, for one thing, has demonstrated an active willingness to deal with problems. They really do try to do things The Right Way, and they even accept patches, even from developers like me who don't "know anybody". :>

TheGoddessInari avatar Nov 03 '20 05:11 TheGoddessInari

Just to add to this issue: it seems that the rambox team is onto something, maybe their efforts on this issue should be followed: https://github.com/ramboxapp/community-edition/issues/2655

PauloGDPeixoto avatar Mar 11 '21 15:03 PauloGDPeixoto

https://github.com/ramboxapp/community-edition/pull/3102/files

mikk150 avatar Nov 09 '21 10:11 mikk150

So, it seems that rambox has solved this issue. Is this fix going to be backported here too?

teras avatar Mar 14 '22 19:03 teras

Hi what's the update on this? Is it only a matter of someone having to do it? I may be able to backport by copy-pasting, but I have no knowledge on actually fixing the issue if there is a wider problem.

DhruvaSambrani avatar Jul 11 '22 13:07 DhruvaSambrani

Is it only a matter of someone having to do it?

More or less. I'm attempting to get to more stuff this week. I'll put this on the tracking board, either way. There are other similar selection boxes that need implementing. If someone's going to start tackling this anyway, get in touch with me directly so we get on the same page?

I'll be trying to work on things.

TheGoddessInari avatar Jul 11 '22 15:07 TheGoddessInari

Hi I tried the following patch -

diff --git a/.sencha/app/codegen.json b/.sencha/app/codegen.json
index 3ec29309..d0913519 100644
--- a/.sencha/app/codegen.json
+++ b/.sencha/app/codegen.json
@@ -32,24 +32,24 @@
       "parameters": {
         "appControllers": "",
         "appModels": "",
-        "appName": "Rambox",
+        "appName": "Hamsket",
         "appStores": "",
         "appViews": "",
         "controllerFileName": "Main",
         "controllerName": "Main",
-        "controllerNamespace": "Rambox.controller",
+        "controllerNamespace": "Hamsket.controller",
         "frameworkKey": "ext",
         "frameworkName": "ext",
         "frameworkPath": "ext",
-        "modelNamespace": "Rambox.model",
-        "name": "Rambox",
+        "modelNamespace": "Hamsket.model",
+        "name": "Hamsket",
         "packagesRelPath": "ext/packages",
         "senchadir": ".sencha",
         "themeName": "default",
         "uniqueId": "0f59c907-ae2e-485e-8a8d-cc2f7f60c1ed",
         "viewFileName": "Main",
         "viewName": "Main",
-        "viewNamespace": "Rambox.view"
+        "viewNamespace": "Hamsket.view"
       }
     },
     ".sencha/app/development.properties": {
@@ -58,24 +58,24 @@
       "parameters": {
         "appControllers": "",
         "appModels": "",
-        "appName": "Rambox",
+        "appName": "Hamsket",
         "appStores": "",
         "appViews": "",
         "controllerFileName": "Main",
         "controllerName": "Main",
-        "controllerNamespace": "Rambox.controller",
+        "controllerNamespace": "Hamsket.controller",
         "frameworkKey": "ext",
         "frameworkName": "ext",
         "frameworkPath": "ext",
-        "modelNamespace": "Rambox.model",
-        "name": "Rambox",
+        "modelNamespace": "Hamsket.model",
+        "name": "Hamsket",
         "packagesRelPath": "ext/packages",
         "senchadir": ".sencha",
         "themeName": "default",
         "uniqueId": "0f59c907-ae2e-485e-8a8d-cc2f7f60c1ed",
         "viewFileName": "Main",
         "viewName": "Main",
-        "viewNamespace": "Rambox.view"
+        "viewNamespace": "Hamsket.view"
       }
     },
     ".sencha/app/native.properties": {
@@ -84,24 +84,24 @@
       "parameters": {
         "appControllers": "",
         "appModels": "",
-        "appName": "Rambox",
+        "appName": "Hamsket",
         "appStores": "",
         "appViews": "",
         "controllerFileName": "Main",
         "controllerName": "Main",
-        "controllerNamespace": "Rambox.controller",
+        "controllerNamespace": "Hamsket.controller",
         "frameworkKey": "ext",
         "frameworkName": "ext",
         "frameworkPath": "ext",
-        "modelNamespace": "Rambox.model",
-        "name": "Rambox",
+        "modelNamespace": "Hamsket.model",
+        "name": "Hamsket",
         "packagesRelPath": "ext/packages",
         "senchadir": ".sencha",
         "themeName": "default",
         "uniqueId": "0f59c907-ae2e-485e-8a8d-cc2f7f60c1ed",
         "viewFileName": "Main",
         "viewName": "Main",
-        "viewNamespace": "Rambox.view"
+        "viewNamespace": "Hamsket.view"
       }
     },
     ".sencha/app/package.properties": {
@@ -110,24 +110,24 @@
       "parameters": {
         "appControllers": "",
         "appModels": "",
-        "appName": "Rambox",
+        "appName": "Hamsket",
         "appStores": "",
         "appViews": "",
         "controllerFileName": "Main",
         "controllerName": "Main",
-        "controllerNamespace": "Rambox.controller",
+        "controllerNamespace": "Hamsket.controller",
         "frameworkKey": "ext",
         "frameworkName": "ext",
         "frameworkPath": "ext",
-        "modelNamespace": "Rambox.model",
-        "name": "Rambox",
+        "modelNamespace": "Hamsket.model",
+        "name": "Hamsket",
         "packagesRelPath": "ext/packages",
         "senchadir": ".sencha",
         "themeName": "default",
         "uniqueId": "0f59c907-ae2e-485e-8a8d-cc2f7f60c1ed",
         "viewFileName": "Main",
         "viewName": "Main",
-        "viewNamespace": "Rambox.view"
+        "viewNamespace": "Hamsket.view"
       }
     },
     ".sencha/app/production.properties": {
@@ -136,24 +136,24 @@
       "parameters": {
         "appControllers": "",
         "appModels": "",
-        "appName": "Rambox",
+        "appName": "Hamsket",
         "appStores": "",
         "appViews": "",
         "controllerFileName": "Main",
         "controllerName": "Main",
-        "controllerNamespace": "Rambox.controller",
+        "controllerNamespace": "Hamsket.controller",
         "frameworkKey": "ext",
         "frameworkName": "ext",
         "frameworkPath": "ext",
-        "modelNamespace": "Rambox.model",
-        "name": "Rambox",
+        "modelNamespace": "Hamsket.model",
+        "name": "Hamsket",
         "packagesRelPath": "ext/packages",
         "senchadir": ".sencha",
         "themeName": "default",
         "uniqueId": "0f59c907-ae2e-485e-8a8d-cc2f7f60c1ed",
         "viewFileName": "Main",
         "viewName": "Main",
-        "viewNamespace": "Rambox.view"
+        "viewNamespace": "Hamsket.view"
       }
     },
     ".sencha/app/sencha.cfg": {
@@ -162,24 +162,24 @@
       "parameters": {
         "appControllers": "",
         "appModels": "",
-        "appName": "Rambox",
+        "appName": "Hamsket",
         "appStores": "",
         "appViews": "",
         "controllerFileName": "Main",
         "controllerName": "Main",
-        "controllerNamespace": "Rambox.controller",
+        "controllerNamespace": "Hamsket.controller",
         "frameworkKey": "ext",
         "frameworkName": "ext",
         "frameworkPath": "ext",
-        "modelNamespace": "Rambox.model",
-        "name": "Rambox",
+        "modelNamespace": "Hamsket.model",
+        "name": "Hamsket",
         "packagesRelPath": "ext/packages",
         "senchadir": ".sencha",
         "themeName": "default",
         "uniqueId": "0f59c907-ae2e-485e-8a8d-cc2f7f60c1ed",
         "viewFileName": "Main",
         "viewName": "Main",
-        "viewNamespace": "Rambox.view"
+        "viewNamespace": "Hamsket.view"
       }
     },
     ".sencha/app/testing.properties": {
@@ -188,24 +188,24 @@
       "parameters": {
         "appControllers": "",
         "appModels": "",
-        "appName": "Rambox",
+        "appName": "Hamsket",
         "appStores": "",
         "appViews": "",
         "controllerFileName": "Main",
         "controllerName": "Main",
-        "controllerNamespace": "Rambox.controller",
+        "controllerNamespace": "Hamsket.controller",
         "frameworkKey": "ext",
         "frameworkName": "ext",
         "frameworkPath": "ext",
-        "modelNamespace": "Rambox.model",
-        "name": "Rambox",
+        "modelNamespace": "Hamsket.model",
+        "name": "Hamsket",
         "packagesRelPath": "ext/packages",
         "senchadir": ".sencha",
         "themeName": "default",
         "uniqueId": "0f59c907-ae2e-485e-8a8d-cc2f7f60c1ed",
         "viewFileName": "Main",
         "viewName": "Main",
-        "viewNamespace": "Rambox.view"
+        "viewNamespace": "Hamsket.view"
       }
     },
     "sass/config.rb": {
@@ -214,24 +214,24 @@
       "parameters": {
         "appControllers": "",
         "appModels": "",
-        "appName": "Rambox",
+        "appName": "Hamsket",
         "appStores": "",
         "appViews": "",
         "controllerFileName": "Main",
         "controllerName": "Main",
-        "controllerNamespace": "Rambox.controller",
+        "controllerNamespace": "Hamsket.controller",
         "frameworkKey": "ext",
         "frameworkName": "ext",
         "frameworkPath": "ext",
-        "modelNamespace": "Rambox.model",
-        "name": "Rambox",
+        "modelNamespace": "Hamsket.model",
+        "name": "Hamsket",
         "packagesRelPath": "ext/packages",
         "senchadir": ".sencha",
         "themeName": "default",
         "uniqueId": "0f59c907-ae2e-485e-8a8d-cc2f7f60c1ed",
         "viewFileName": "Main",
         "viewName": "Main",
-        "viewNamespace": "Rambox.view"
+        "viewNamespace": "Hamsket.view"
       }
     }
   }
diff --git a/.sencha/app/sencha.cfg b/.sencha/app/sencha.cfg
index ef1f3818..76951d22 100644
--- a/.sencha/app/sencha.cfg
+++ b/.sencha/app/sencha.cfg
@@ -1,5 +1,5 @@
 # The name of the application
-app.name=Rambox
+app.name=Hamsket
 
 # The path(s) to application javascript sources (comma separated)
 app.classpath=${app.dir}/app,${app.dir}/app.js
@@ -9,7 +9,7 @@ app.overrides=${app.dir}/overrides
 
 # The root namespace to use when mapping scss resources to js classes
 # in the sass/src and sass/var directories
-app.sass.namespace=Rambox
+app.sass.namespace=Hamsket
 
 # Path to sass rule definition files corresponding to JavaScript classes.
 app.sass.srcpath=${app.dir}/sass/src
@@ -43,4 +43,4 @@ app.resource.paths=${app.dir}/resources
 app.framework.version=5.1.1.451
 
 
-app.cmd.version=6.7.0.37
+app.cmd.version=6.7.0.63
diff --git a/electron/main.js b/electron/main.js
index 18363a71..8d0a05cf 100644
--- a/electron/main.js
+++ b/electron/main.js
@@ -1,6 +1,6 @@
 'use strict';
 
-const {app, protocol, BrowserWindow, dialog, shell, Menu, ipcMain, nativeImage, session} = require('electron');
+const { app, protocol, BrowserWindow, dialog, shell, Menu, ipcMain, nativeImage, session } = require('electron');
 // Tray
 const tray = require('./tray');
 // AutoLaunch
@@ -17,49 +17,49 @@ const contextMenu = require('electron-context-menu');
 // If 'data' folder exists in Hamsket's folder, set userdata, logs, and usercache path to there
 var basepath = app.getAppPath();
 if (fs.existsSync(path.join(basepath, 'data'))) {
-	app.setPath('userData', path.join(basepath, 'data', 'data'));
-	app.setPath('logs', path.join(basepath, 'data', 'logs'));
-	app.setPath('userCache', path.join(basepath, 'data', 'cache'));
+    app.setPath('userData', path.join(basepath, 'data', 'data'));
+    app.setPath('logs', path.join(basepath, 'data', 'logs'));
+    app.setPath('userCache', path.join(basepath, 'data', 'cache'));
 }
 
 // Initial Config
 const config = new Config({
-	 defaults: {
-		 always_on_top: false
-		,hide_menu_bar: false
-		,tabbar_location: 'top'
-		,window_display_behavior: 'taskbar_tray'
-		,auto_launch: false
-		,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
-		,default_service: 'hamsketTab'
-
-		,x: undefined
-		,y: undefined
-		,width: 1000
-		,height: 800
-		,maximized: false
-	}
+    defaults: {
+        always_on_top: false
+        , hide_menu_bar: false
+        , tabbar_location: 'top'
+        , window_display_behavior: 'taskbar_tray'
+        , auto_launch: false
+        , 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
+        , default_service: 'hamsketTab'
+
+        , x: undefined
+        , y: undefined
+        , width: 1000
+        , height: 800
+        , maximized: false
+    }
 });
 
 app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
 
 // 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');
+    app.commandLine.appendSwitch('high-dpi-support', 'true');
+    app.commandLine.appendSwitch('force-device-scale-factor', '1');
 }
 
 // TODO: https://github.com/electron/electron/issues/25469
@@ -69,589 +69,636 @@ app.commandLine.appendSwitch('disable-features', 'CrossOriginOpenerPolicy');
 app.setAppUserModelId('com.thegoddessinari.hamsket');
 
 app.userAgentFallback = app.userAgentFallback
-	.replace(`Electron/${process.versions.electron}`, ``)
-	.replace(`Hamsket/${app.getVersion()}`, ``);
+    .replace(`Electron/${process.versions.electron}`, ``)
+    .replace(`Hamsket/${app.getVersion()}`, ``);
 
 // Menu
 const appMenu = require('./menu')(config);
 
 // Configure AutoLaunch
 const appLauncher = new AutoLaunch({
-	name: 'Hamsket',
-	isHidden: config.get('start_minimized')
+    name: 'Hamsket',
+    isHidden: config.get('start_minimized')
 });
 appLauncher
-	.isEnabled()
-	.then((isEnabled) => {
-		if (config.get('auto_launch') && !isEnabled) {
-			appLauncher.enable();
-		} else if (!config.get('auto_launch') && isEnabled) {
-			appLauncher.disable();
-		}
-		return;
-	})
-	.catch((err) => {
-		console.log(err);
-	});
+    .isEnabled()
+    .then((isEnabled) => {
+        if (config.get('auto_launch') && !isEnabled) {
+            appLauncher.enable();
+        } else if (!config.get('auto_launch') && isEnabled) {
+            appLauncher.disable();
+        }
+        return;
+    })
+    .catch((err) => {
+        console.log(err);
+    });
 
 // Keep a global reference of the window object, if you don't, the window will
 // be closed automatically when the JavaScript object is garbage collected.
 let mainWindow;
 let isQuitting = false;
 
-function createWindow () {
-	// Create the browser window using the state information
-	mainWindow = new BrowserWindow({
-		 title: 'Hamsket'
-		,icon: nativeImage.createFromPath(path.join(app.getAppPath(), '/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: {
-			partition: 'persist:hamsket',
-			nodeIntegration: true,
-			webviewTag: true,
-			contextIsolation: false,
-		}
-	});
-
-	require("@electron/remote/main").enable(mainWindow.webContents);
-
-	if ( !config.get('start_minimized') && config.get('maximized') ) mainWindow.maximize();
-	if (config.get('start_minimized')){
-		if (config.get('window_display_behavior') == 'show_taskbar') {
-			mainWindow.webContents.once('did-finish-load', function(e) {
-				mainWindow.minimize();
-				});
-		}
-		else {
-			mainWindow.webContents.once('did-finish-load', function(e) {
-				mainWindow.hide();
-				});
-		}
-	}
-
-	// 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')]);
-	if ( inBounds ) {
-		mainWindow.setPosition(config.get('x'), config.get('y'));
-	} else {
-		mainWindow.center();
-	}
-
-	process.setMaxListeners(10000);
-
-	// and load the index.html of the app.
-	mainWindow.loadURL('file://' + __dirname + '/../index.html');
-
-	Menu.setApplicationMenu(appMenu);
-
-	tray.create(mainWindow, config);
-
-	if ( fs.existsSync(path.resolve(path.dirname(process.execPath), '..', 'Update.exe')) && 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;
-		switch ( disposition ) {
-			case 'new-window': {
-				e.preventDefault();
-				const win = new BrowserWindow(options);
-				win.once('ready-to-show', () => win.show());
-				win.loadURL(url);
-				e.newGuest = win;
-				break;
-			}
-			case 'foreground-tab': {
-				if (protocol === 'http:' || protocol === 'https:' || protocol === 'mailto:') {
-					e.preventDefault();
-					shell.openExternal(url);
-				}
-				break;
-			}
-			default:
-				break;
-		}
-	});
-
-	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) => {
-		// 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();');
-		// 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();');
-	});
-
-	// Emitted when the window is closed.
-	mainWindow.on('close', function(e) {
-		if ( !isQuitting ) {
-			e.preventDefault();
-
-			switch (process.platform) {
-				case 'darwin':
-					app.hide();
-					break;
-				default:
-					switch (config.get('window_close_behavior')) {
-						case 'keep_in_tray':
-							mainWindow.hide();
-							break;
-						case 'keep_in_tray_and_taskbar':
-							mainWindow.minimize();
-							break;
-						case 'quit':
-							app.quit();
-							break;
-					}
-					break;
-			}
-		}
-	});
-	mainWindow.on('closed', function(e) {
-		mainWindow = null;
-	});
-	mainWindow.once('focus', () => mainWindow.flashFrame(false));
+function createWindow() {
+    // Create the browser window using the state information
+    mainWindow = new BrowserWindow({
+        title: 'Hamsket'
+        , icon: nativeImage.createFromPath(path.join(app.getAppPath(), '/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: {
+            partition: 'persist:hamsket',
+            nodeIntegration: true,
+            webviewTag: true,
+            contextIsolation: false,
+        }
+    });
+
+    require("@electron/remote/main").enable(mainWindow.webContents);
+
+    if (!config.get('start_minimized') && config.get('maximized')) mainWindow.maximize();
+    if (config.get('start_minimized')) {
+        if (config.get('window_display_behavior') == 'show_taskbar') {
+            mainWindow.webContents.once('did-finish-load', function(e) {
+                mainWindow.minimize();
+            });
+        }
+        else {
+            mainWindow.webContents.once('did-finish-load', function(e) {
+                mainWindow.hide();
+            });
+        }
+    }
+
+    // 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')]);
+    if (inBounds) {
+        mainWindow.setPosition(config.get('x'), config.get('y'));
+    } else {
+        mainWindow.center();
+    }
+
+    process.setMaxListeners(10000);
+
+    // and load the index.html of the app.
+    mainWindow.loadURL('file://' + __dirname + '/../index.html');
+
+    Menu.setApplicationMenu(appMenu);
+
+    tray.create(mainWindow, config);
+
+    if (fs.existsSync(path.resolve(path.dirname(process.execPath), '..', 'Update.exe')) && 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;
+        switch (disposition) {
+            case 'new-window': {
+                e.preventDefault();
+                const win = new BrowserWindow(options);
+                win.once('ready-to-show', () => win.show());
+                win.loadURL(url);
+                e.newGuest = win;
+                break;
+            }
+            case 'foreground-tab': {
+                if (protocol === 'http:' || protocol === 'https:' || protocol === 'mailto:') {
+                    e.preventDefault();
+                    shell.openExternal(url);
+                }
+                break;
+            }
+            default:
+                break;
+        }
+    });
+
+    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) => {
+        // 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();');
+        // 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();');
+    });
+
+    // Emitted when the window is closed.
+    mainWindow.on('close', function(e) {
+        if (!isQuitting) {
+            e.preventDefault();
+
+            switch (process.platform) {
+                case 'darwin':
+                    app.hide();
+                    break;
+                default:
+                    switch (config.get('window_close_behavior')) {
+                        case 'keep_in_tray':
+                            mainWindow.hide();
+                            break;
+                        case 'keep_in_tray_and_taskbar':
+                            mainWindow.minimize();
+                            break;
+                        case 'quit':
+                            app.quit();
+                            break;
+                    }
+                    break;
+            }
+        }
+    });
+    mainWindow.on('closed', function(e) {
+        mainWindow = null;
+    });
+    mainWindow.once('focus', () => mainWindow.flashFrame(false));
 }
 
 let mainMasterPasswordWindow;
 function createMasterPasswordWindow() {
-	mainMasterPasswordWindow = new BrowserWindow({
-		 backgroundColor: '#0675A0'
-		,frame: false
-		,webPreferences: {
-			nodeIntegration: true,
-			contextIsolation: false
-		}
-
-	});
-	require("@electron/remote/main").enable(mainMasterPasswordWindow.webContents);
-
-	mainMasterPasswordWindow.loadURL('file://' + __dirname + '/../masterpassword.html');
-	mainMasterPasswordWindow.on('close', function() { mainMasterPasswordWindow = null; });
+    mainMasterPasswordWindow = new BrowserWindow({
+        backgroundColor: '#0675A0'
+        , frame: false
+        , webPreferences: {
+            nodeIntegration: true,
+            contextIsolation: false
+        }
+
+    });
+    require("@electron/remote/main").enable(mainMasterPasswordWindow.webContents);
+
+    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
-	let messageCount = title.match(/\d+/g) ? parseInt(title.match(/\d+/g).join("")) : 0;
-	messageCount = isNaN(messageCount) ? 0 : messageCount;
-	
-	tray.setBadge(messageCount, config.get('systemtray_indicator'));
-
-	if (process.platform === 'win32') { // Windows
-		if (messageCount === 0) {
-			mainWindow.setOverlayIcon(null, "");
-			return;
-		}
-
-		mainWindow.webContents.send('setBadge', messageCount);
-	} else { // macOS & Linux
-		app.badgeCount = messageCount;
-	}
-
-	if ( messageCount > 0 && !mainWindow.isFocused() && !config.get('dont_disturb') && config.get('flash_frame') ) mainWindow.flashFrame(true);
+    title = title.split(" - ")[0]; //Discard service name if present, could also contain digits
+    let messageCount = title.match(/\d+/g) ? parseInt(title.match(/\d+/g).join("")) : 0;
+    messageCount = isNaN(messageCount) ? 0 : messageCount;
+
+    tray.setBadge(messageCount, config.get('systemtray_indicator'));
+
+    if (process.platform === 'win32') { // Windows
+        if (messageCount === 0) {
+            mainWindow.setOverlayIcon(null, "");
+            return;
+        }
+
+        mainWindow.webContents.send('setBadge', messageCount);
+    } else { // macOS & Linux
+        app.badgeCount = messageCount;
+    }
+
+    if (messageCount > 0 && !mainWindow.isFocused() && !config.get('dont_disturb') && config.get('flash_frame')) mainWindow.flashFrame(true);
 }
 
 ipcMain.on('setBadge', function(event, messageCount, value) {
-	const img = nativeImage.createFromDataURL(value);
-	mainWindow.setOverlayIcon(img, messageCount.toString());
+    const img = nativeImage.createFromDataURL(value);
+    mainWindow.setOverlayIcon(img, messageCount.toString());
 });
 
 ipcMain.on('getConfig', function(event, arg) {
-	event.returnValue = config.store;
+    event.returnValue = config.store;
 });
 
 ipcMain.on('setConfig', function(event, values) {
-	config.set(values);
-
-	// hide_menu_bar
-	mainWindow.setAutoHideMenuBar(values.hide_menu_bar);
-	if ( !values.hide_menu_bar ) mainWindow.setMenuBarVisibility(true);
-	// always_on_top
-	mainWindow.setAlwaysOnTop(values.always_on_top);
-	// auto_launch
-	if (values.auto_launch) {
-		appLauncher.enable();
-	} else {
-		appLauncher.disable();
-	}
-	// systemtray_indicator
-	updateBadge(mainWindow.getTitle());
-
-	mainWindow.webContents.executeJavaScript('(function(a){if(a)a.controller.initialize(a)})(Ext.cq1("app-main"))');
-
-	switch ( values.window_display_behavior ) {
-		case 'show_taskbar':
-			mainWindow.setSkipTaskbar(false);
-			tray.destroy();
-			break;
-		case 'show_trayIcon':
-			mainWindow.setSkipTaskbar(true);
-			tray.create(mainWindow, config);
-			break;
-		case 'taskbar_tray':
-			mainWindow.setSkipTaskbar(false);
-			tray.create(mainWindow, config);
-			break;
-		default:
-			break;
-	}
+    config.set(values);
+
+    // hide_menu_bar
+    mainWindow.setAutoHideMenuBar(values.hide_menu_bar);
+    if (!values.hide_menu_bar) mainWindow.setMenuBarVisibility(true);
+    // always_on_top
+    mainWindow.setAlwaysOnTop(values.always_on_top);
+    // auto_launch
+    if (values.auto_launch) {
+        appLauncher.enable();
+    } else {
+        appLauncher.disable();
+    }
+    // systemtray_indicator
+    updateBadge(mainWindow.getTitle());
+
+    mainWindow.webContents.executeJavaScript('(function(a){if(a)a.controller.initialize(a)})(Ext.cq1("app-main"))');
+
+    switch (values.window_display_behavior) {
+        case 'show_taskbar':
+            mainWindow.setSkipTaskbar(false);
+            tray.destroy();
+            break;
+        case 'show_trayIcon':
+            mainWindow.setSkipTaskbar(true);
+            tray.create(mainWindow, config);
+            break;
+        case 'taskbar_tray':
+            mainWindow.setSkipTaskbar(false);
+            tray.create(mainWindow, config);
+            break;
+        default:
+            break;
+    }
 });
 
 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;
-	}
-	event.returnValue = false;
+    if (config.get('master_password') === require('crypto').createHash('md5').update(pass).digest('hex')) {
+        createWindow();
+        mainMasterPasswordWindow.close();
+        event.returnValue = true;
+    }
+    event.returnValue = false;
 });
 
 // Handle Service Notifications
 ipcMain.on('setServiceNotifications', function(event, partition, op) {
-	if (partition) {
-		session.fromPartition(partition).setPermissionRequestHandler(function(webContents, permission, callback) {
-			if (permission === 'notifications') return callback(op);
-			callback(true);
-		});
-	}
+    if (partition) {
+        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);
+    config.set('dont_disturb', arg);
 });
 
 // Reload app
 ipcMain.on('reloadApp', function(event) {
-	mainWindow.reload();
+    mainWindow.reload();
 });
 
 // Relaunch app
 ipcMain.on('relaunchApp', function(event) {
-	app.relaunch();
-	app.quit(0);
+    app.relaunch();
+    app.quit(0);
 });
 
 const haveLock = app.requestSingleInstanceLock();
 app.on('second-instance', (commandLine, workingDirectory) => {
-	// Someone tried to run a second instance, we should focus our window.
-	if (mainWindow) {
-		if (mainWindow.isMinimized()) mainWindow.restore();
-		mainWindow.focus();
-		mainWindow.show();
-		mainWindow.setSkipTaskbar(false);
-		if (app.dock && app.dock.show) app.dock.show();
-	}
+    // Someone tried to run a second instance, we should focus our window.
+    if (mainWindow) {
+        if (mainWindow.isMinimized()) mainWindow.restore();
+        mainWindow.focus();
+        mainWindow.show();
+        mainWindow.setSkipTaskbar(false);
+        if (app.dock && app.dock.show) app.dock.show();
+    }
 });
 
 if (!haveLock) {
-	app.quit();
+    app.quit();
 }
 
 const allowPopUp = [
-	'=?print=true', // esta ultima checkea como anda imprimir un pedf desde gmail, si no va bie sacala
-	'accounts.google.com/AccountChooser',
-	'accounts.google.com/o/oauth2',
-	'api.moo.do',
-	'app.mixmax.com/_oauth/google',
-	'app.slack.com/files/import/dropbox',
-	'app.slack.com/files/import/gdrive',
-	'app.slack.com/free-willy/',
-	'auth.missiveapp.com',
-	'dropbox.com/profile_services/start_auth_flow',
-	'facebook.com/v3.1/dialog/oauth?',
-	'facebook.com/v3.2/dialog/oauth?',
-	'feedly.com/v3/auth/',
-	'figma.com/start_google_sso',
-	'hangouts.google.com/webchat/u/0/frame',
-	'identity.linuxfoundation.org/cas/login',
-	'mail.google.com/mail',
-	'manychat.com/fb?popup',
-	'messenger.com/videocall',
-	'notion.so/googlepopupredirect',
-	'officeapps.live.com',
-	'spikenow.com/s/account',
-	'zoom.us/office365',
+    '=?print=true', // esta ultima checkea como anda imprimir un pedf desde gmail, si no va bie sacala
+    'accounts.google.com/AccountChooser',
+    'accounts.google.com/o/oauth2',
+    'api.moo.do',
+    'app.mixmax.com/_oauth/google',
+    'app.slack.com/files/import/dropbox',
+    'app.slack.com/files/import/gdrive',
+    'app.slack.com/free-willy/',
+    'auth.missiveapp.com',
+    'dropbox.com/profile_services/start_auth_flow',
+    'facebook.com/v3.1/dialog/oauth?',
+    'facebook.com/v3.2/dialog/oauth?',
+    'feedly.com/v3/auth/',
+    'figma.com/start_google_sso',
+    'hangouts.google.com/webchat/u/0/frame',
+    'identity.linuxfoundation.org/cas/login',
+    'mail.google.com/mail',
+    'manychat.com/fb?popup',
+    'messenger.com/videocall',
+    'notion.so/googlepopupredirect',
+    'officeapps.live.com',
+    'spikenow.com/s/account',
+    'zoom.us/office365',
 ];
 
 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.slice(0, 8) === 'slack://' && event.preventDefault()
-	);
-	// New Window handler
-	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)) {
-				event.preventDefault();
-				Object.assign(options, {
-					show: false,
-				});
-				const win = new BrowserWindow(options);
-				win.center();
-				let once = false;
-				win.webContents.on('will-navigate', (e, nextURL) => {
-					if (once) return;
-					if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return;
-					once = true;
-					let allow = false;
-					for (const url of allowPopUp) {
-						if (nextURL.includes(url)) {
-							allow = true;
-							break;
-						}
-					}
-					// If the url is in aboutBlankOnlyWindow we handle this as a popup window
-					if (allow) return win.show();
-					shell.openExternal(nextURL);
-					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;
-			for (const allowed of allowPopUp) {
-				if (url.includes(allowed)) {
-					allow = true;
-					break;
-				}
-			}
-			if (allow) return;
-			shell.openExternal(url);
-			event.preventDefault();
-		}
-	);
-	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;
-		let once = false;
-		win.webContents.on('will-navigate', (e, nextURL) => {
-			if (once) return;
-			if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return;
-			once = true;
-			let allow = false;
-			for (const url of allowPopUp) {
-				if (nextURL.includes(url)) {
-					allow = true;
-					break;
-				}
-			}
-			// If the url is in aboutBlankOnlyWindow we handle this as a popup window
-			if (allow) return win.show();
-			shell.openExternal(url);
-			win.close();
-		});
-	});
+    if (contents.getType() !== 'webview') return;
+    // Block some Deep links to prevent that open its app (Ex: Slack)
+    contents.on(
+        'will-navigate',
+        (event, url) => url.slice(0, 8) === 'slack://' && event.preventDefault()
+    );
+    // New Window handler
+    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)) {
+                event.preventDefault();
+                Object.assign(options, {
+                    show: false,
+                });
+                const win = new BrowserWindow(options);
+                win.center();
+                let once = false;
+                win.webContents.on('will-navigate', (e, nextURL) => {
+                    if (once) return;
+                    if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return;
+                    once = true;
+                    let allow = false;
+                    for (const url of allowPopUp) {
+                        if (nextURL.includes(url)) {
+                            allow = true;
+                            break;
+                        }
+                    }
+                    // If the url is in aboutBlankOnlyWindow we handle this as a popup window
+                    if (allow) return win.show();
+                    shell.openExternal(nextURL);
+                    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;
+            for (const allowed of allowPopUp) {
+                if (url.includes(allowed)) {
+                    allow = true;
+                    break;
+                }
+            }
+            if (allow) return;
+            shell.openExternal(url);
+            event.preventDefault();
+        }
+    );
+    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;
+        let once = false;
+        win.webContents.on('will-navigate', (e, nextURL) => {
+            if (once) return;
+            if (['about:blank', 'about:blank#blocked'].includes(nextURL)) return;
+            once = true;
+            let allow = false;
+            for (const url of allowPopUp) {
+                if (nextURL.includes(url)) {
+                    allow = true;
+                    break;
+                }
+            }
+            // If the url is in aboutBlankOnlyWindow we handle this as a popup window
+            if (allow) return win.show();
+            shell.openExternal(url);
+            win.close();
+        });
+    });
 });
 
 // Code for downloading images as temporal files
 // Credit: Ghetto Skype (https://github.com/stanfieldr/ghetto-skype)
 let imageCache = {};
 ipcMain.on('image:download', function(event, url, partition) {
-	const tmp = require('tmp');
-	const mime = require('mime');
-	let file = imageCache[`${url}`];
-	if (file) {
-		if (file.complete) {
-			shell.openItem(file.path);
-		}
-
-		// Pending downloads intentionally do not proceed
-		return;
-	}
-
-	let tmpWindow = new BrowserWindow({
-		 show: false
-		,webPreferences: {
-			partition: partition
-		}
-	});
-
-	tmpWindow.webContents.session.once('will-download', (event, downloadItem) => {
-		imageCache[`${url}`] = file = {
-			 path: tmp.tmpNameSync() + '.' + mime.getExtension(downloadItem.getMimeType())
-			,complete: false
-		};
-
-		downloadItem.setSavePath(file.path);
-		downloadItem.once('done', () => {
-			tmpWindow.destroy();
-			tmpWindow = null;
-			shell.openItem(file.path);
-			file.complete = true;
-		});
-	});
-
-	tmpWindow.webContents.downloadURL(url);
+    const tmp = require('tmp');
+    const mime = require('mime');
+    let file = imageCache[`${url}`];
+    if (file) {
+        if (file.complete) {
+            shell.openItem(file.path);
+        }
+
+        // Pending downloads intentionally do not proceed
+        return;
+    }
+
+    let tmpWindow = new BrowserWindow({
+        show: false
+        , webPreferences: {
+            partition: partition
+        }
+    });
+
+    tmpWindow.webContents.session.once('will-download', (event, downloadItem) => {
+        imageCache[`${url}`] = file = {
+            path: tmp.tmpNameSync() + '.' + mime.getExtension(downloadItem.getMimeType())
+            , complete: false
+        };
+
+        downloadItem.setSavePath(file.path);
+        downloadItem.once('done', () => {
+            tmpWindow.destroy();
+            tmpWindow = null;
+            shell.openItem(file.path);
+            file.complete = true;
+        });
+    });
+
+    tmpWindow.webContents.downloadURL(url);
 });
 
 // Hangouts
 ipcMain.on('image:popup', function(event, url, partition) {
-	let tmpWindow = new BrowserWindow({
-		 width: mainWindow.getBounds().width
-		,height: mainWindow.getBounds().height
-		,parent: mainWindow
-		,icon: nativeImage.createFromPath(path.join(app.getAppPath(), '/resources/Icon.' + (process.platform === 'linux' ? 'png' : 'ico')))
-		,backgroundColor: '#FFF'
-		,autoHideMenuBar: true
-		,skipTaskbar: true
-		,webPreferences: {
-			partition: partition
-		}
-	});
-
-	tmpWindow.maximize();
-
-	tmpWindow.loadURL(url);
+    let tmpWindow = new BrowserWindow({
+        width: mainWindow.getBounds().width
+        , height: mainWindow.getBounds().height
+        , parent: mainWindow
+        , icon: nativeImage.createFromPath(path.join(app.getAppPath(), '/resources/Icon.' + (process.platform === 'linux' ? 'png' : 'ico')))
+        , backgroundColor: '#FFF'
+        , autoHideMenuBar: true
+        , skipTaskbar: true
+        , webPreferences: {
+            partition: partition
+        }
+    });
+
+    tmpWindow.maximize();
+
+    tmpWindow.loadURL(url);
 });
 
 ipcMain.on('toggleWin', function(event, alwaysShow) {
-	if ( !mainWindow.isMinimized() && mainWindow.isMaximized() && mainWindow.isVisible() ) { // Maximized
-		if (!alwaysShow) {
-			mainWindow.close();
-		} else {
-			mainWindow.show();
-		} 
-	} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Minimized
-		mainWindow.restore();
-	} else if ( !mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible() ) { // Windowed mode
-		if (!alwaysShow) {
-			mainWindow.close();
-		 } else {
-			mainWindow.show();
-		 }
-	} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible() ) { // Closed to taskbar
-		mainWindow.restore();
-	} 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
-		mainWindow.show();
-	} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed minimized to tray
-		mainWindow.restore();
-	} else {
-		mainWindow.show();
-	}
+    if (!mainWindow.isMinimized() && mainWindow.isMaximized() && mainWindow.isVisible()) { // Maximized
+        if (!alwaysShow) {
+            mainWindow.close();
+        } else {
+            mainWindow.show();
+        }
+    } else if (mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible()) { // Minimized
+        mainWindow.restore();
+    } else if (!mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible()) { // Windowed mode
+        if (!alwaysShow) {
+            mainWindow.close();
+        } else {
+            mainWindow.show();
+        }
+    } else if (mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible()) { // Closed to taskbar
+        mainWindow.restore();
+    } 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
+        mainWindow.show();
+    } else if (mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible()) { // Closed minimized to tray
+        mainWindow.restore();
+    } else {
+        mainWindow.show();
+    }
+});
+
+// ScreenShare
+ipcMain.on('screenShare:show', (event, screenList) => {
+    let tmpWindow = new BrowserWindow({
+        width: 600,
+        height: 500,
+        icon: __dirname + '/../resources/Icon.ico',
+        autoHideMenuBar: true,
+        transparent: true,
+        show: true,
+        frame: false,
+        hasShadow: true,
+        webPreferences: {
+            nodeIntegration: true,
+        },
+    });
+
+    const close = () => {
+        tmpWindow.close();
+        tmpWindow = null;
+    };
+
+    const onCancel = () => {
+        console.log("Reached HERE 4")
+        event.sender.send('screenShare:cancel');
+        close();
+    };
+
+    const onShare = (_, shareId) => {
+        console.log("Reached HERE 3")
+        event.sender.send('screenShare:share', shareId);
+        close();
+    };
+
+    ipcMain.handle('screenShare:getSources', () => screenList);
+    ipcMain.on('screenShare:cancelSelection', onCancel);
+    ipcMain.on('screenShare:selectScreen', onShare);
+
+    tmpWindow.on('closed', () => {
+        console.log("Reached HERE 2")
+        ipcMain.removeHandler('screenShare:getSources');
+        ipcMain.removeAllListeners('screenShare:cancelSelection');
+        ipcMain.removeAllListeners('screenShare:selectScreen');
+    });
+    console.log("Reached HERE 1")
+    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;
-
-		event.preventDefault();
-		callback(config.get('proxyLogin'), config.get('proxyPassword'));
-	});
+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'));
+    });
 }
 
 // Disable GPU Acceleration for Linux
 // to prevent White Page bug
 // https://github.com/electron/electron/issues/6139
 // https://github.com/saenzramiro/hamsket/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() {
-	require('@electron/remote/main').initialize();
-	if (config.get('master_password')) {
-		createMasterPasswordWindow();
-	} else {
-		createWindow();
-	}
+    require('@electron/remote/main').initialize();
+    if (config.get('master_password')) {
+        createMasterPasswordWindow();
+    } else {
+        createWindow();
+    }
 });
 
 // Quit when all windows are closed.
-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') {
-		app.quit();
-	}
+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') {
+        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 () {
-	if (mainWindow === null && mainMasterPasswordWindow === null ) {
-		if (config.get('master_password')) {
-			createMasterPasswordWindow();
-		} else {
-			createWindow();
-		}
-	}
-
-	if ( mainWindow !== null ) mainWindow.show();
+app.on('activate', function() {
+    if (mainWindow === null && mainMasterPasswordWindow === null) {
+        if (config.get('master_password')) {
+            createMasterPasswordWindow();
+        } else {
+            createWindow();
+        }
+    }
+
+    if (mainWindow !== null) mainWindow.show();
 });
 
-app.on('before-quit', function () {
-	isQuitting = true;
+app.on('before-quit', function() {
+    isQuitting = true;
 });
 
 // Prevent the ability to create webview with nodeIntegration.
 app.on('web-contents-created', (event, contents) => {
-	require("@electron/remote/main").enable(contents);
-	const contextMenuWebContentsDispose = contextMenu({
-		window: contents,
-		showCopyImageAddress: true,
-		showSaveImage: false,
-		showSaveImageAs: true,
-	});
-
-	contents.session.webRequest.onBeforeSendHeaders(
-		{
-			urls: [
-				'https://accounts.google.com/',
-				'https://accounts.google.com/*'
-			]
-		},
-		(details, callback) => {
-			details.requestHeaders['User-Agent'] =
-				'Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0';
-			callback({ requestHeaders: details.requestHeaders });
-		}
-	);
+    require("@electron/remote/main").enable(contents);
+    const contextMenuWebContentsDispose = contextMenu({
+        window: contents,
+        showCopyImageAddress: true,
+        showSaveImage: false,
+        showSaveImageAs: true,
+    });
+
+    contents.session.webRequest.onBeforeSendHeaders(
+        {
+            urls: [
+                'https://accounts.google.com/',
+                'https://accounts.google.com/*'
+            ]
+        },
+        (details, callback) => {
+            details.requestHeaders['User-Agent'] =
+                'Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0';
+            callback({ requestHeaders: details.requestHeaders });
+        }
+    );
 
     contents.on('will-attach-webview', (event, webPreferences, params) => {
-		// Always prevent node integration
-		webPreferences.nodeIntegration = false;
+        // Always prevent node integration
+        webPreferences.nodeIntegration = false;
 
-	});
-	contents.on('destroyed', function() {
-		contextMenuWebContentsDispose();
-	})
+    });
+    contents.on('destroyed', function() {
+        contextMenuWebContentsDispose();
+    })
 });
diff --git a/resources/js/hamsket-service-api.js b/resources/js/hamsket-service-api.js
index 27d83925..41cbfb67 100644
--- a/resources/js/hamsket-service-api.js
+++ b/resources/js/hamsket-service-api.js
@@ -2,7 +2,7 @@
  * This file is loaded in the service web views to provide a Hamsket API.
  */
 
-const { ipcRenderer } = require('electron');
+const { desktopCapturer, ipcRenderer } = require('electron');
 
 /**
  * Make the Hamsket API available via a global "hamsket" variable.
@@ -19,7 +19,7 @@ window.hamsket.locale = ipcRenderer.sendSync('getConfig').locale;
  * @param {*} count	The unread count
  */
 window.hamsket.setUnreadCount = function(count) {
-	ipcRenderer.sendToHost('hamsket.setUnreadCount', count);
+    ipcRenderer.sendToHost('hamsket.setUnreadCount', count);
 };
 
 /**
@@ -28,19 +28,19 @@ window.hamsket.setUnreadCount = function(count) {
  * @param {*} indirect
  */
 window.hamsket.updateBadge = function(direct, indirect = 0) {
-	ipcRenderer.sendToHost('hamsket.updateBadge', direct, indirect);
+    ipcRenderer.sendToHost('hamsket.updateBadge', direct, indirect);
 };
 
 /**
  * Clears the unread count.
  */
 window.hamsket.clearUnreadCount = function() {
-	ipcRenderer.sendToHost('hamsket.clearUnreadCount');
+    ipcRenderer.sendToHost('hamsket.clearUnreadCount');
 };
 
-window.hamsket.parseIntOrZero = function (n) {
-	const result = Number.parseInt(n, 10);
-	return Number.isNaN(result) ? 0 : result;
+window.hamsket.parseIntOrZero = function(n) {
+    const result = Number.parseInt(n, 10);
+    return Number.isNaN(result) ? 0 : result;
 };
 
 window.hamsket.isInViewport = function(node) {
@@ -52,19 +52,61 @@ window.hamsket.isInViewport = function(node) {
         rect.top < (window.innerHeight || document.documentElement.clientHeight);
 };
 
-
+window.navigator.mediaDevices.getDisplayMedia = () =>
+    new Promise(async (resolve, reject) => {
+        try {
+            const sources = await desktopCapturer.getSources({
+                types: ['screen', 'window'],
+            });
+
+            const unlisten = () => {
+                ipcRenderer.removeAllListeners('screenShare:cancel');
+                ipcRenderer.removeAllListeners('screenShare:share');
+            };
+
+            ipcRenderer.on('screenShare:cancel', () => {
+                unlisten();
+                reject(new Error('Cancelled by user'));
+            });
+
+            ipcRenderer.on('screenShare:share', (_, shareId) => {
+                unlisten();
+                window.navigator.mediaDevices
+                    .getUserMedia({
+                        audio: false,
+                        video: {
+                            mandatory: {
+                                chromeMediaSource: 'desktop',
+                                chromeMediaSourceId: shareId,
+                            },
+                        },
+                    })
+                    .then(stream => resolve(stream));
+            });
+
+            const mappedSources = sources.map(it => ({
+                id: it.id,
+                name: it.name,
+                thumbnail: it.thumbnail.toDataURL(),
+            }));
+
+            ipcRenderer.send('screenShare:show', mappedSources);
+        } catch (err) {
+            reject(err);
+        }
+    })
 /**
  * Override to add notification click event to display Hamsket window and activate service tab
  */
 const NativeNotification = Notification;
 Notification = function(title, options) {
-	const notification = new NativeNotification(title, options);
+    const notification = new NativeNotification(title, options);
 
-	notification.addEventListener('click', function() {
-		ipcRenderer.sendToHost('hamsket.showWindowAndActivateTab');
-	});
+    notification.addEventListener('click', function() {
+        ipcRenderer.sendToHost('hamsket.showWindowAndActivateTab');
+    });
 
-	return notification;
+    return notification;
 };
 
 Notification.prototype = NativeNotification.prototype;
@@ -76,3 +118,5 @@ window.close = function() { location.href = location.origin; };
 // Electron really screwed up here. atob and btoa are broken in recent versions, so override them.
 window.atob = data => Buffer.from(data, "base64").toString("latin1");
 window.btoa = data => Buffer.from(data, "latin1").toString("base64");
+
+

It didn't work and I got nothing on console either when I try to screen share from a Teams meeting

DhruvaSambrani avatar Jul 30 '22 18:07 DhruvaSambrani

With the recent announcement that Microsoft will be dropping the Linux client in favor of a PWA, this issue is evermore urgent.

PauloGDPeixoto avatar Sep 03 '22 10:09 PauloGDPeixoto