diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index f2b3d8f1..b2286a9e 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -8,6 +8,7 @@ import copyImage from 'browser/main/lib/dataApi/copyImage' import { findStorage } from 'browser/lib/findStorage' import fs from 'fs' import eventEmitter from 'browser/main/lib/eventEmitter' +const { ipcRenderer } = require('electron') CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' @@ -34,7 +35,11 @@ export default class CodeEditor extends React.Component { this.scrollHandler = _.debounce(this.handleScroll.bind(this), 100, {leading: false, trailing: true}) this.changeHandler = (e) => this.handleChange(e) + this.focusHandler = () => { + ipcRenderer.send('editor:focused', true) + } this.blurHandler = (editor, e) => { + ipcRenderer.send('editor:focused', false) if (e == null) return null let el = e.relatedTarget while (el != null) { @@ -139,6 +144,7 @@ export default class CodeEditor extends React.Component { this.setMode(this.props.mode) + this.editor.on('focus', this.focusHandler) this.editor.on('blur', this.blurHandler) this.editor.on('change', this.changeHandler) this.editor.on('paste', this.pasteHandler) @@ -162,6 +168,7 @@ export default class CodeEditor extends React.Component { } componentWillUnmount () { + this.editor.off('focus', this.focusHandler) this.editor.off('blur', this.blurHandler) this.editor.off('change', this.changeHandler) this.editor.off('paste', this.pasteHandler) diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index dbef37ca..6f8bbb3d 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -343,6 +343,7 @@ class SnippetNoteDetail extends React.Component { handleKeyDown (e) { switch (e.keyCode) { + // tab key case 9: if (e.ctrlKey && !e.shiftKey) { e.preventDefault() @@ -355,6 +356,7 @@ class SnippetNoteDetail extends React.Component { this.focusEditor() } break + // L key case 76: { const isSuper = global.process.platform === 'darwin' @@ -366,6 +368,7 @@ class SnippetNoteDetail extends React.Component { } } break + // T key case 84: { const isSuper = global.process.platform === 'darwin' diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index eb00a324..b1f2d092 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -261,27 +261,38 @@ class NoteList extends React.Component { handleNoteListKeyDown (e) { if (e.metaKey || e.ctrlKey) return true + // A key if (e.keyCode === 65 && !e.shiftKey) { e.preventDefault() ee.emit('top:new-note') } + // D key if (e.keyCode === 68) { e.preventDefault() this.deleteNote() } + // E key if (e.keyCode === 69) { e.preventDefault() ee.emit('detail:focus') } - if (e.keyCode === 38) { + // F or S key + if (e.keyCode === 70 || e.keyCode === 83) { + e.preventDefault() + ee.emit('top:focus-search') + } + + // UP or K key + if (e.keyCode === 38 || e.keyCode === 75) { e.preventDefault() this.selectPriorNote() } - if (e.keyCode === 40) { + // DOWN or J key + if (e.keyCode === 40 || e.keyCode === 74) { e.preventDefault() this.selectNextNote() } diff --git a/browser/main/TopBar/TopBar.styl b/browser/main/TopBar/TopBar.styl index eb0fc12f..0956571f 100644 --- a/browser/main/TopBar/TopBar.styl +++ b/browser/main/TopBar/TopBar.styl @@ -40,6 +40,32 @@ $control-height = 34px padding-bottom 2px background-color $ui-noteList-backgroundColor +.control-search-input-clear + height 16px + width 16px + position absolute + right 40px + top 10px + z-index 300 + border none + background-color transparent + color #999 + &:hover .control-search-input-clear-tooltip + opacity 1 + +.control-search-input-clear-tooltip + tooltip() + position fixed + pointer-events none + top 50px + left 433px + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s + .control-search-optionList position fixed z-index 200 @@ -207,4 +233,4 @@ body[data-theme="solarized-dark"] background-color $ui-solarized-dark-noteList-backgroundColor input background-color $ui-solarized-dark-noteList-backgroundColor - color $ui-solarized-dark-text-color \ No newline at end of file + color $ui-solarized-dark-text-color diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index 6b4a118e..246ef614 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -36,6 +36,17 @@ class TopBar extends React.Component { ee.off('code:init', this.codeInitHandler) } + handleSearchClearButton (e) { + const { router } = this.context + this.setState({ + search: '', + isSearching: false + }) + this.refs.search.childNodes[0].blur + router.push('/searched') + e.preventDefault() + } + handleKeyDown (e) { // reset states this.setState({ @@ -43,6 +54,23 @@ class TopBar extends React.Component { isIME: false }) + // Clear search on ESC + if (e.keyCode === 27) { + return this.handleSearchClearButton(e) + } + + // Next note on DOWN key + if (e.keyCode === 40) { + ee.emit('list:next') + e.preventDefault() + } + + // Prev note on UP key + if (e.keyCode === 38) { + ee.emit('list:prior') + e.preventDefault() + } + // When the key is an alphabet, del, enter or ctr if (e.keyCode <= 90 || e.keyCode >= 186 && e.keyCode <= 222) { this.setState({ @@ -114,10 +142,12 @@ class TopBar extends React.Component { } handleOnSearchFocus () { + const el = this.refs.search.childNodes[0] if (this.state.isSearching) { - this.refs.search.childNodes[0].blur() + el.blur() } else { - this.refs.search.childNodes[0].focus() + el.focus() + el.setSelectionRange(0, el.value.length) } } @@ -150,15 +180,15 @@ class TopBar extends React.Component { type='text' className='searchInput' /> + {this.state.search !== '' && + + } - {this.state.search > 0 && - - } - {location.pathname === '/trashed' ? '' diff --git a/lib/main-menu.js b/lib/main-menu.js index 0d49ab86..81e5fc22 100644 --- a/lib/main-menu.js +++ b/lib/main-menu.js @@ -1,6 +1,7 @@ const electron = require('electron') const BrowserWindow = electron.BrowserWindow const shell = electron.shell +const ipc = electron.ipcMain const mainWindow = require('./main-window') const macOS = process.platform === 'darwin' @@ -259,6 +260,23 @@ const view = { ] } +let editorFocused + +// Define extra shortcut keys +mainWindow.webContents.on('before-input-event', (event, input) => { + // Synonyms for Search (Find) + if (input.control && input.key === 'f' && input.type === 'keyDown') { + if (!editorFocused) { + mainWindow.webContents.send('top:focus-search') + event.preventDefault() + } + } +}) + +ipc.on('editor:focused', (event, isFocused) => { + editorFocused = isFocused +}) + const window = { label: 'Window', submenu: [