diff --git a/src/main/index.js b/src/main/index.js index 7e116cb22..a4c7c0728 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -31,6 +31,7 @@ function runApp() { const isDev = process.env.NODE_ENV === 'development' const isDebug = process.argv.includes('--debug') let mainWindow + let openedWindows = [] let startupUrl // CORS somehow gets re-enabled in Electron v9.0.4 @@ -219,11 +220,11 @@ function runApp() { } } - function createWindow (useProxy = false, proxyUrl = '') { + function createWindow (useProxy = false, proxyUrl = '', replaceMainWindow = true) { /** * Initial window options */ - mainWindow = new BrowserWindow({ + const newWindow = new BrowserWindow({ backgroundColor: '#fff', icon: isDev ? path.join(__dirname, '../../_icons/iconColor.png') @@ -241,14 +242,18 @@ function runApp() { }, show: false }) + openedWindows.push(newWindow) + if (replaceMainWindow) { + mainWindow = newWindow + } - mainWindow.setBounds({ + newWindow.setBounds({ width: 1200, height: 800 }) if (useProxy) { - mainWindow.webContents.session.setProxy({ + newWindow.webContents.session.setProxy({ proxyRules: proxyUrl }) } @@ -260,7 +265,7 @@ function runApp() { 'http://youtube.com', 'https://youtube.com' ].forEach(url => { - mainWindow.webContents.session.cookies.set({ + newWindow.webContents.session.cookies.set({ url: url, name: 'CONSENT', value: 'YES+' @@ -284,7 +289,7 @@ function runApp() { .reduce((accumulator, { size: { width } }) => accumulator + width, 0) if (allDisplaysSummaryWidth >= bounds.x) { - mainWindow.setBounds({ + newWindow.setBounds({ x: bounds.x, y: bounds.y, width: bounds.width, @@ -292,19 +297,23 @@ function runApp() { }) } if (maximized) { - mainWindow.maximize() + newWindow.maximize() } }) - // eslint-disable-next-line - setMenu() + // If called multiple times + // Duplicate menu items will be added + if (replaceMainWindow) { + // eslint-disable-next-line + setMenu() + } // load root file/url if (isDev) { - mainWindow.loadURL('http://localhost:9080') + newWindow.loadURL('http://localhost:9080') } else { /* eslint-disable-next-line */ - mainWindow.loadFile(`${__dirname}/index.html`) + newWindow.loadFile(`${__dirname}/index.html`) global.__static = path .join(__dirname, '/static') @@ -312,74 +321,87 @@ function runApp() { } // Show when loaded - mainWindow.on('ready-to-show', () => { - mainWindow.show() - mainWindow.focus() + newWindow.on('ready-to-show', () => { + newWindow.show() + newWindow.focus() }) - mainWindow.on('closed', () => { + newWindow.on('closed', () => { + // Remove closed window + openedWindows = openedWindows.filter((window) => window !== newWindow) + if (newWindow === mainWindow) { + // Replace mainWindow to avoid accessing `mainWindow.webContents` + // Which raises "Object has been destroyed" error + mainWindow = openedWindows[0] + } + console.log('closed') }) - - ipcMain.on('setBounds', (_e, data) => { - const value = { - ...mainWindow.getNormalBounds(), - maximized: mainWindow.isMaximized() - } - - settingsDb.findOne({ - _id: 'bounds' - }, function (err, doc) { - if (err) { - return - } - if (doc !== null) { - settingsDb.update({ - _id: 'bounds' - }, { - $set: { - value - } - }, {}) - } else { - settingsDb.insert({ - _id: 'bounds', - value - }) - } - }) - }) - - ipcMain.on('appReady', () => { - if (startupUrl) { - mainWindow.webContents.send('openUrl', startupUrl) - } - }) - - ipcMain.on('disableSmoothScrolling', () => { - app.commandLine.appendSwitch('disable-smooth-scrolling') - mainWindow.close() - createWindow() - }) - - ipcMain.on('enableSmoothScrolling', () => { - app.commandLine.appendSwitch('enable-smooth-scrolling') - mainWindow.close() - createWindow() - }) - - ipcMain.on('enableProxy', (event, url) => { - console.log(url) - mainWindow.webContents.session.setProxy({ - proxyRules: url - }) - }) - - ipcMain.on('disableProxy', () => { - mainWindow.webContents.session.setProxy({}) - }) } + // Save closing window bounds & maximized status + ipcMain.on('setBounds', (_e, data) => { + const value = { + ...mainWindow.getNormalBounds(), + maximized: mainWindow.isMaximized() + } + + settingsDb.findOne({ + _id: 'bounds' + }, function (err, doc) { + if (err) { + return + } + if (doc !== null) { + settingsDb.update({ + _id: 'bounds' + }, { + $set: { + value + } + }, {}) + } else { + settingsDb.insert({ + _id: 'bounds', + value + }) + } + }) + }) + + ipcMain.on('appReady', () => { + if (startupUrl) { + mainWindow.webContents.send('openUrl', startupUrl) + } + }) + + ipcMain.on('disableSmoothScrolling', () => { + app.commandLine.appendSwitch('disable-smooth-scrolling') + mainWindow.close() + createWindow() + }) + + ipcMain.on('enableSmoothScrolling', () => { + app.commandLine.appendSwitch('enable-smooth-scrolling') + mainWindow.close() + createWindow() + }) + + ipcMain.on('enableProxy', (event, url) => { + console.log(url) + mainWindow.webContents.session.setProxy({ + proxyRules: url + }) + }) + + ipcMain.on('disableProxy', () => { + mainWindow.webContents.session.setProxy({}) + }) + + ipcMain.on('createNewWindow', () => { + createWindow(false, '', false) + }) + app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() diff --git a/src/renderer/components/top-nav/top-nav.js b/src/renderer/components/top-nav/top-nav.js index 653df6ec3..0eb397160 100644 --- a/src/renderer/components/top-nav/top-nav.js +++ b/src/renderer/components/top-nav/top-nav.js @@ -6,6 +6,7 @@ import $ from 'jquery' import router from '../../router/index.js' import debounce from 'lodash.debounce' import ytSuggest from 'youtube-suggest' +const { ipcRenderer } = require('electron') export default Vue.extend({ name: 'TopNav', @@ -195,6 +196,10 @@ export default Vue.extend({ toggleSideNav: function () { this.$store.commit('toggleSideNav') + }, + + createNewWindow: function () { + ipcRenderer.send('createNewWindow') } } }) diff --git a/src/renderer/components/top-nav/top-nav.sass b/src/renderer/components/top-nav/top-nav.sass index 3197cbcec..018e27f25 100644 --- a/src/renderer/components/top-nav/top-nav.sass +++ b/src/renderer/components/top-nav/top-nav.sass @@ -66,6 +66,11 @@ @media only screen and (min-width: 681px) display: none + .navNewWindowIcon + // Hidden when "History" menu item also hidden + @media only screen and (max-width: 279px) + display: none + .logo // parts that make up the logo display: flex align-items: center diff --git a/src/renderer/components/top-nav/top-nav.vue b/src/renderer/components/top-nav/top-nav.vue index 9a4ed1443..96f638e12 100644 --- a/src/renderer/components/top-nav/top-nav.vue +++ b/src/renderer/components/top-nav/top-nav.vue @@ -24,6 +24,11 @@ icon="search" @click="toggleSearchContainer" /> +