diff --git a/browser/main/TopBar/TopBar.styl b/browser/main/TopBar/TopBar.styl index dafe6a54..b2cfef67 100644 --- a/browser/main/TopBar/TopBar.styl +++ b/browser/main/TopBar/TopBar.styl @@ -15,10 +15,13 @@ $control-height = 34px border $ui-border border-radius 20px overflow hidden + display flex + .control-search - absolute top left bottom - right 40px + height 32px + flex 1 background-color white + position relative .control-search-icon absolute top bottom left @@ -76,10 +79,24 @@ $control-height = 34px color $ui-inactive-text-color line-height 150px text-align center + +.control-contextButton + display block + width 20px + height $control-height - 2 + navButtonColor() + border-left $ui-border + font-size 14px + line-height 28px + padding 0 + &:active + border-color $ui-button--active-backgroundColor + &:hover .control-newPostButton-tooltip + opacity 1 + .control-newPostButton display block - absolute top right bottom - width 40px + width 36px height $control-height - 2 navButtonColor() border-left $ui-border @@ -143,10 +160,9 @@ body[data-theme="dark"] color $ui-inactive-text-color padding-right 3px .control-search-optionList-empty - height 150px color $ui-inactive-text-color - line-height 150px - text-align center + + .control-contextButton, .control-newPostButton colorDarkDefaultButton() border-color $ui-dark-borderColor @@ -155,12 +171,3 @@ body[data-theme="dark"] .control-newPostButton-tooltip darkTooltip() - position fixed - pointer-events none - top 45px - left 385px - z-index 10 - padding 5px - line-height normal - opacity 0 - transition 0.1s diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index f6433581..1f156bdc 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -6,8 +6,12 @@ import modal from 'browser/main/lib/modal' import NewNoteModal from 'browser/main/modals/NewNoteModal' import { hashHistory } from 'react-router' import ee from 'browser/main/lib/eventEmitter' +import ConfigManager from 'browser/main/lib/ConfigManager' +import dataApi from 'browser/main/lib/dataApi' const OSX = window.process.platform === 'darwin' +const { remote } = require('electron') +const { Menu, MenuItem } = remote class TopBar extends React.Component { constructor (props) { @@ -33,7 +37,30 @@ class TopBar extends React.Component { } handleNewPostButtonClick (e) { - let { data, params, dispatch, location } = this.props + let { config } = this.props + + switch (config.ui.defaultNote) { + case 'MARKDOWN_NOTE': + this.createNote('MARKDOWN_NOTE') + break + case 'SNIPPET_NOTE': + this.createNote('SNIPPET_NOTE') + break + case 'ALWAYS_ASK': + let { dispatch, location } = this.props + let { storage, folder } = this.resolveTargetFolder() + + modal.open(NewNoteModal, { + storage: storage.key, + folder: folder.key, + dispatch, + location + }) + } + } + + resolveTargetFolder () { + let { data, params } = this.props let storage = data.storageMap.get(params.storageKey) // Find first storage @@ -48,12 +75,10 @@ class TopBar extends React.Component { if (folder == null) folder = storage.folders[0] if (folder == null) throw new Error('No folder to craete a note') - modal.open(NewNoteModal, { - storage: storage.key, - folder: folder.key, - dispatch, - location - }) + return { + storage, + folder + } } handleSearchChange (e) { @@ -135,6 +160,101 @@ class TopBar extends React.Component { } } + handleContextButtonClick (e) { + let { config } = this.props + + let menu = new Menu() + menu.append(new MenuItem({ + label: 'Create Markdown Note', + click: (e) => this.createNote('MARKDOWN_NOTE') + })) + menu.append(new MenuItem({ + label: 'Create Snippet Note', + click: (e) => this.createNote('SNIPPET_NOTE') + })) + menu.append(new MenuItem({ + type: 'separator' + })) + menu.append(new MenuItem({ + label: 'Change Default Note', + submenu: [ + { + type: 'radio', + label: 'Markdown Note', + checked: config .ui.defaultNote === 'MARKDOWN_NOTE', + click: (e) => this.setDefaultNote('MARKDOWN_NOTE') + }, + { + type: 'radio', + label: 'Snippet Note', + checked: config.ui.defaultNote === 'SNIPPET_NOTE', + click: (e) => this.setDefaultNote('SNIPPET_NOTE') + }, + { + type: 'radio', + label: 'Always Ask', + checked: config.ui.defaultNote === 'ALWAYS_ASK', + click: (e) => this.setDefaultNote('ALWAYS_ASK') + } + ] + })) + menu.popup(remote.getCurrentWindow()) + } + + createNote (noteType) { + let { dispatch, location } = this.props + if (noteType !== 'MARKDOWN_NOTE' && noteType !== 'SNIPPET_NOTE') throw new Error('Invalid note type.') + + let { storage, folder } = this.resolveTargetFolder() + + let newNote = noteType === 'MARKDOWN_NOTE' + ? { + type: 'MARKDOWN_NOTE', + folder: folder.key, + title: '', + content: '' + } + : { + type: 'SNIPPET_NOTE', + folder: folder.key, + title: '', + description: '', + snippets: [{ + name: '', + mode: 'text', + content: '' + }] + } + + dataApi + .createNote(storage.key, newNote) + .then((note) => { + dispatch({ + type: 'UPDATE_NOTE', + note: note + }) + hashHistory.push({ + pathname: location.pathname, + query: {key: note.storage + '-' + note.key} + }) + ee.emit('detail:focus') + }) + } + + setDefaultNote (defaultNote) { + let { config, dispatch } = this.props + let ui = Object.assign(config.ui) + ui.defaultNote = defaultNote + ConfigManager.set({ + ui + }) + + dispatch({ + type: 'SET_UI', + config: ConfigManager.get() + }) + } + render () { let { config, style, data } = this.props let searchOptionList = this.getOptions() @@ -204,6 +324,11 @@ class TopBar extends React.Component { New Note {OSX ? '⌘' : '^'} + n + ) diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 53d907ae..0fe9dbc8 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -15,7 +15,8 @@ const defaultConfig = { }, ui: { theme: 'default', - disableDirectWrite: false + disableDirectWrite: false, + defaultNote: 'ALWAYS_ASK' // 'ALWAYS_ASK', 'SNIPPET_NOTE', 'MARKDOWN_NOTE' }, editor: { theme: 'xcode',