diff --git a/browser/main/Main.js b/browser/main/Main.js index fae596552..100827f35 100644 --- a/browser/main/Main.js +++ b/browser/main/Main.js @@ -44,6 +44,7 @@ class Main extends React.Component { } this.toggleFullScreen = () => this.handleFullScreenButton() + this.probeTrayClose = () => this.handleTrayCloseProbe() } getChildContext() { @@ -177,6 +178,11 @@ class Main extends React.Component { delete CodeMirror.keyMap.emacs['Ctrl-V'] eventEmitter.on('editor:fullscreen', this.toggleFullScreen) + eventEmitter.on('tray:probe-close', this.probeTrayClose) + eventEmitter.on( + 'menubar:togglemenubar', + this.toggleMenuBarVisible.bind(this) + ) eventEmitter.on( 'menubar:togglemenubar', this.toggleMenuBarVisible.bind(this) @@ -185,6 +191,7 @@ class Main extends React.Component { componentWillUnmount() { eventEmitter.off('editor:fullscreen', this.toggleFullScreen) + eventEmitter.off('tray:probe-close', this.probeTrayClose) eventEmitter.off( 'menubar:togglemenubar', this.toggleMenuBarVisible.bind(this) @@ -294,6 +301,14 @@ class Main extends React.Component { }) } + handleTrayCloseProbe(e) { + const { config } = this.props + if (!config.ui.closeToTray) { + console.log('handleTrayClose') + eventEmitter.emitIpc('tray:quit') + } + } + hideLeftLists(noteDetail, noteList, mainBody) { this.setState({ noteDetailWidth: noteDetail.style.left }) this.setState({ mainBodyWidth: mainBody.style.left }) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 9b9b7de03..d02e955ee 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -147,7 +147,7 @@ class NoteList extends React.Component { } componentDidUpdate(prevProps) { - const { dispatch, location } = this.props + const { data, dispatch, location } = this.props const { selectedNoteKeys } = this.state const visibleNoteKeys = this.notes && this.notes.map(note => note.key) const note = this.notes && this.notes[0] @@ -159,6 +159,16 @@ class NoteList extends React.Component { ? prevKey : note && note.key + console.log('tray:update trigger', data) + ee.emitIpc( + 'tray:update', + data.noteMap + .map(note => note) + .sort(sortByUpdatedAt) + .slice(0, 10) + .filter(note => note.title !== '' && !note.isTrashed) + ) + if (note && location.search === '') { if (!location.pathname.match(/\/searched/)) this.contextNotes = this.getContextNotes() diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 6a950af11..8488de428 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -46,6 +46,7 @@ export const DEFAULT_CONFIG = { ui: { language: 'en', theme: 'default', + closeToTray: true, showCopyNotification: true, disableDirectWrite: false, defaultNote: 'ALWAYS_ASK', // 'ALWAYS_ASK', 'SNIPPET_NOTE', 'MARKDOWN_NOTE' diff --git a/browser/main/lib/eventEmitter.js b/browser/main/lib/eventEmitter.js index 370ea3a90..015926e9d 100644 --- a/browser/main/lib/eventEmitter.js +++ b/browser/main/lib/eventEmitter.js @@ -17,9 +17,14 @@ function emit(name, ...args) { remote.getCurrentWindow().webContents.send(name, ...args) } +function emitIpc(name, ...args) { + ipcRenderer.send(name, ...args) +} + export default { emit, on, off, - once + once, + emitIpc } diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index e043397de..f1acc43f5 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -84,6 +84,7 @@ class UiTab extends React.Component { const newConfig = { ui: { theme: this.refs.uiTheme.value, + closeToTray: this.refs.closeToTray.checked, language: this.refs.uiLanguage.value, defaultNote: this.refs.defaultNote.value, tagNewNoteWithFilteringTags: this.refs.tagNewNoteWithFilteringTags @@ -351,6 +352,17 @@ class UiTab extends React.Component { ) : null} +
+ +
Tags
diff --git a/lib/main-window.js b/lib/main-window.js index e6b0cb297..611dd7cea 100644 --- a/lib/main-window.js +++ b/lib/main-window.js @@ -1,11 +1,13 @@ const electron = require('electron') -const app = electron.app -const BrowserWindow = electron.BrowserWindow +const { app, BrowserWindow, Menu, MenuItem, Tray, ipcMain } = electron const path = require('path') const Config = require('electron-config') const config = new Config() const _ = require('lodash') +const manifest = require('../package.json') +const product = `${manifest.productName} ${manifest.version}` +var menu // set up some chrome extensions if (process.env.NODE_ENV === 'development') { const { @@ -78,7 +80,10 @@ mainWindow.webContents.sendInputEvent({ keyCode: '\u0008' }) -if (process.platform === 'darwin') { +if ( + process.platform === 'darwin' || + process.env.DESKTOP_SESSION === 'cinnamon' +) { mainWindow.on('close', function(e) { e.preventDefault() if (mainWindow.isFullScreen()) { @@ -91,11 +96,17 @@ if (process.platform === 'darwin') { } }) - app.on('before-quit', function(e) { - mainWindow.removeAllListeners() - }) + mainWindow.webContents.send('tray:probe-close') } +app.on('before-quit', function(e) { + mainWindow.removeAllListeners() +}) + +app.on('window-all-closed', function() { + app.quit() +}) + mainWindow.on('resize', _.throttle(storeWindowSize, 500)) mainWindow.on('move', _.throttle(storeWindowSize, 500)) @@ -113,4 +124,70 @@ app.on('activate', function() { mainWindow.show() }) +ipcMain.on('tray:update', handleTrayUpdate) + +ipcMain.on('tray:quit', function(e, notes) { + ipcMain.removeListener('tray:update', handleTrayUpdate) + menu = null + app.quit() +}) + +function handleTrayUpdate(e, notes) { + updateTray(notes) +} + +function updateTray(notes) { + const menu = new Menu() + + menu.append( + new MenuItem({ + label: `Open ${product}`, + click: function() { + mainWindow.show() + } + }) + ) + + if (notes && notes.length) { + menu.append(new MenuItem({ type: 'separator' })) + notes.forEach(note => { + menu.append( + new MenuItem({ + label: note.title, + click: function() { + mainWindow.webContents.send('list:jump', note.key) + mainWindow.show() + } + }) + ) + }) + menu.append(new MenuItem({ type: 'separator' })) + } + + menu.append( + new MenuItem({ + label: 'Quit', + click: function() { + app.quit() + } + }) + ) + + tray.setContextMenu(menu) + + return menu +} + +const tray = new Tray( + path.join(__dirname, '../resources/tray-icon-dark@2x.png') +) +menu = updateTray() +const displayTray = function(e) { + e.preventDefault() + tray.popUpContextMenu(menu) +} + +tray.setToolTip(product) +tray.on('click', displayTray) + module.exports = mainWindow diff --git a/tests/lib/boostnoterc/.boostnoterc.all b/tests/lib/boostnoterc/.boostnoterc.all index a7981f7f9..3f39039c3 100644 --- a/tests/lib/boostnoterc/.boostnoterc.all +++ b/tests/lib/boostnoterc/.boostnoterc.all @@ -25,6 +25,7 @@ "sortBy": "UPDATED_AT", "sortTagsBy": "ALPHABETICAL", "ui": { + "closeToTray": false, "defaultNote": "ALWAYS_ASK", "disableDirectWrite": false, "theme": "default"