From 6dfd46f79cd3683b1710d1a454764dc02157a468 Mon Sep 17 00:00:00 2001 From: yarray <08to09@gmail.com> Date: Sat, 18 Apr 2020 21:31:57 +0800 Subject: [PATCH 1/3] add floating mode for MacOS --- app/config.js | 3 ++- app/index.js | 17 ++++++++++++++--- app/menu.js | 10 +++++++++- app/static/tray-mac.png | Bin 0 -> 2145 bytes app/static/tray-mac@2x.png | Bin 0 -> 2456 bytes app/tray.js | 38 +++++++++++++++++++++++++++++++------ 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 app/static/tray-mac.png create mode 100644 app/static/tray-mac@2x.png diff --git a/app/config.js b/app/config.js index c60f4f3..00fe27e 100644 --- a/app/config.js +++ b/app/config.js @@ -9,6 +9,7 @@ module.exports = new Config({ shortcut: { toggleApp: null }, - mode: 'dark' + mode: 'dark', + floating: false } }) diff --git a/app/index.js b/app/index.js index 89fcf51..03ae8ea 100644 --- a/app/index.js +++ b/app/index.js @@ -75,7 +75,12 @@ function createMainWindow() { e.preventDefault() if (process.platform === 'darwin') { - app.hide() + if (config.get('floating')) { + // if app is floating, app.hide will not work + win.hide() + } else { + app.hide() + } } else { win.hide() } @@ -108,10 +113,16 @@ app.on('ready', () => { Menu.setApplicationMenu( createMenu({ toggleWindow - }) + }, app) ) mainWindow = createMainWindow() - tray.create(mainWindow) + if (config.get('floating') && process.platform === 'darwin') { + app.dock.hide() + mainWindow.setAlwaysOnTop(true, 'floating') + mainWindow.setVisibleOnAllWorkspaces(true) + mainWindow.setFullScreenable(false) + } + tray.create(mainWindow, app) mainWindow.once('ready-to-show', () => { mainWindow.show() diff --git a/app/menu.js b/app/menu.js index a682e3b..f6628c7 100644 --- a/app/menu.js +++ b/app/menu.js @@ -25,7 +25,7 @@ function updateMenu(opts) { Menu.setApplicationMenu(createMenu(opts)) } -function createMenu(opts) { +function createMenu(opts, app) { const toggleAppAccelerator = config.get('shortcut.toggleApp') || 'CmdOrCtrl+Shift+D' const toggleAppAcceleratorRegistered = globalShortcut.isRegistered( @@ -48,6 +48,14 @@ function createMenu(opts) { shell.openItem(configDir('custom.js')) } }, + { + label: 'Turn On Floating Mode', + click() { + config.set('floating', true) + app.relaunch() + app.exit() + } + }, { label: `${ toggleAppAcceleratorRegistered ? 'Disable' : 'Enable' diff --git a/app/static/tray-mac.png b/app/static/tray-mac.png new file mode 100644 index 0000000000000000000000000000000000000000..b5f9e35e4a1dffd7d2b63a31dca2ff844492d632 GIT binary patch literal 2145 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 literal 0 HcmV?d00001 diff --git a/app/tray.js b/app/tray.js index 3818591..007d4d8 100644 --- a/app/tray.js +++ b/app/tray.js @@ -1,14 +1,24 @@ const path = require('path') const { app, Menu, Tray } = require('electron') +const config = require('./config') let tray = null -exports.create = win => { - if (process.platform === 'darwin' || tray) { +exports.create = (win, app) => { + if (tray) { return } - const iconPath = path.join(__dirname, 'static/tray.png') + let iconPath; + if (process.platform === 'darwin') { + if (config.get('floating')) { + iconPath = path.join(__dirname, 'static/tray-mac.png') + } else { + return + } + } else { + iconPath = path.join(__dirname, 'static/tray.png') + } const toggleWin = () => { if (win.isVisible()) { @@ -18,13 +28,27 @@ exports.create = win => { } } - const contextMenu = Menu.buildFromTemplate([ + let menuItems = [ { - label: 'Toggle', + label: 'Toggle Window', click() { toggleWin() } - }, + } + ]; + if (process.platform === 'darwin') { + menuItems = menuItems.concat([ + { + label: 'Turn Off Floating Mode', + click() { + config.set('floating', false) + app.relaunch() + app.exit() + } + }, + ]) + } + menuItems = menuItems.concat([ { type: 'separator' }, @@ -33,6 +57,8 @@ exports.create = win => { } ]) + const contextMenu = Menu.buildFromTemplate(menuItems) + tray = new Tray(iconPath) tray.setToolTip(`${app.getName()}`) tray.setContextMenu(contextMenu) From b38fbeba412783d5dd4aaf41af1b8b8d44996e3f Mon Sep 17 00:00:00 2001 From: yarray <08to09@gmail.com> Date: Sun, 19 Apr 2020 12:15:04 +0800 Subject: [PATCH 2/3] add pin icon in header --- app/renderer/main.js | 21 +++++++++++++++++++- app/renderer/pin.js | 44 ++++++++++++++++++++++++++++++++++++++++++ app/renderer/style.css | 12 ++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 app/renderer/pin.js diff --git a/app/renderer/main.js b/app/renderer/main.js index 8d822ed..e444f21 100644 --- a/app/renderer/main.js +++ b/app/renderer/main.js @@ -26,7 +26,15 @@ function ensureCustomFiles() { function createHeader() { const header = document.createElement('header') header.className = 'header' - header.innerHTML = '

Loading DevDocs...

' + header.innerHTML = ` +

Loading DevDocs...

+ + + + + + + ` header.addEventListener('dblclick', () => { win.maximize() }) @@ -34,6 +42,17 @@ function createHeader() { webview.focus() }) + const pin = header.querySelector('.pin') + if (config.get('floating')) { + pin.classList.add('pinned') + } + pin.addEventListener('click', () => { + const app = remote.app + config.set('floating', !config.get('floating')) + app.relaunch() + app.exit() + }) + document.body.append(header) } diff --git a/app/renderer/pin.js b/app/renderer/pin.js new file mode 100644 index 0000000..8dcab4a --- /dev/null +++ b/app/renderer/pin.js @@ -0,0 +1,44 @@ +const { remote } = require('electron') +const EventEmitter = require('events') + +module.exports = class Pin extends EventEmitter { + constructor(target) { + super() + this.target = target + } + + toggle() { + return this.pinned ? this.unpin() : this.pin() + } + + pin() { + // TODO: make floating + this.$pinBtn.classList.remove('pinned') + this.emit('pin') + } + + unpin() { + // TODO: make unfloating + this.$pinBtn.classList.remove('pinned') + this.emit('unpin') + } + + initialize() { + const header = document.querySelector('header') + this.$pinBtn = document.createElement('div') + $pinBtn.innerHTML = ` + + ` + header.appendChild($pinBtn) + this.$pinBtn.addEventListener('click', () => { + this.toggle() + }) + this.emit('initialized') + } +} diff --git a/app/renderer/style.css b/app/renderer/style.css index f14a32d..41596b3 100644 --- a/app/renderer/style.css +++ b/app/renderer/style.css @@ -72,9 +72,21 @@ body { .header .app-title { font-size: 12px; font-weight: 400; + text-align: center; margin: 0; } +.header .pin { + font-size: 12px; + margin: 0; + margin-left: 3px; + fill: #666666; +} + +.header .pin.pinned { + fill: #2C70F4; +} + .is-darwin .header { display: flex; } From cd483b63af907086c7910b9226bdab7bd2f0716e Mon Sep 17 00:00:00 2001 From: yarray <08to09@gmail.com> Date: Sun, 19 Apr 2020 15:26:57 +0800 Subject: [PATCH 3/3] delete unused file --- app/renderer/pin.js | 44 -------------------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 app/renderer/pin.js diff --git a/app/renderer/pin.js b/app/renderer/pin.js deleted file mode 100644 index 8dcab4a..0000000 --- a/app/renderer/pin.js +++ /dev/null @@ -1,44 +0,0 @@ -const { remote } = require('electron') -const EventEmitter = require('events') - -module.exports = class Pin extends EventEmitter { - constructor(target) { - super() - this.target = target - } - - toggle() { - return this.pinned ? this.unpin() : this.pin() - } - - pin() { - // TODO: make floating - this.$pinBtn.classList.remove('pinned') - this.emit('pin') - } - - unpin() { - // TODO: make unfloating - this.$pinBtn.classList.remove('pinned') - this.emit('unpin') - } - - initialize() { - const header = document.querySelector('header') - this.$pinBtn = document.createElement('div') - $pinBtn.innerHTML = ` - - ` - header.appendChild($pinBtn) - this.$pinBtn.addEventListener('click', () => { - this.toggle() - }) - this.emit('initialized') - } -}