diff --git a/browser/main/NewNoteButton/NewNoteButton.styl b/browser/main/NewNoteButton/NewNoteButton.styl new file mode 100644 index 000000000..b53ff892c --- /dev/null +++ b/browser/main/NewNoteButton/NewNoteButton.styl @@ -0,0 +1,68 @@ +.root + position relative + background-color $ui-noteList-backgroundColor + height $topBar-height - 1 + margin-left: auto; + width: 64px; + margin-right: -15px; + +.root--expanded + @extend .root + +$control-height = 34px + +.control + position absolute + top 13px + left 8px + right 8px + height $control-height + overflow hidden + display flex + +.control-newNoteButton + display block + width 32px + height $control-height - 2 + navButtonColor() + font-size 16px + line-height 28px + padding 0 + &:active + border-color $ui-button--active-backgroundColor + &:hover .control-newNoteButton-tooltip + opacity 1 + +.control-newNoteButton-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 + +body[data-theme="dark"] + .root, .root--expanded + background-color $ui-dark-noteList-backgroundColor + + .control + border-color $ui-dark-borderColor + + .control-newNoteButton + color $ui-inactive-text-color + border-color $ui-dark-borderColor + background-color $ui-dark-noteList-backgroundColor + &:hover + transition 0.15s + color $ui-dark-text-color + &:active + background-color alpha($ui-dark-button--active-backgroundColor, 20%) + border-color $ui-dark-button--active-backgroundColor + + .control-newNoteButton-tooltip + darkTooltip() diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js new file mode 100644 index 000000000..6b09e8784 --- /dev/null +++ b/browser/main/NewNoteButton/index.js @@ -0,0 +1,107 @@ +import React, { PropTypes } from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './NewNoteButton.styl' +import _ from 'lodash' +import modal from 'browser/main/lib/modal' +import NewNoteModal from 'browser/main/modals/NewNoteModal' +import { hashHistory } from 'react-router' +import eventEmitter from 'browser/main/lib/eventEmitter' +import dataApi from 'browser/main/lib/dataApi' + +const { remote } = require('electron') +const { dialog } = remote + +const OSX = window.process.platform === 'darwin' + +class NewNoteButton extends React.Component { + constructor (props) { + super(props) + + this.state = { + } + + this.newNoteHandler = () => { + this.handleNewNoteButtonClick() + } + } + + componentDidMount () { + eventEmitter.on('top:new-note', this.newNoteHandler) + } + + componentWillUnmount () { + eventEmitter.off('top:new-note', this.newNoteHandler) + } + + handleNewNoteButtonClick (e) { + const { config, location, dispatch } = this.props + const { storage, folder } = this.resolveTargetFolder() + + modal.open(NewNoteModal, { + storage: storage.key, + folder: folder.key, + dispatch, + location + }) + } + + resolveTargetFolder () { + const { data, params } = this.props + let storage = data.storageMap.get(params.storageKey) + + // Find first storage + if (storage == null) { + for (let kv of data.storageMap) { + storage = kv[1] + break + } + } + + if (storage == null) this.showMessageBox('No storage to create a note') + let folder = storage.folders[0] + folder = _.find(storage.folders, {key: params.folderKey}) + if (folder == null) this.showMessageBox('No folder to create a note') + + return { + storage, + folder + } + } + + showMessageBox (message) { + dialog.showMessageBox(remote.getCurrentWindow(), { + type: 'warning', + message: message, + buttons: ['OK'] + }) + } + + render () { + const { config, style } = this.props + return ( +
+
+ +
+
+ ) + } +} + +NewNoteButton.propTypes = { + dispatch: PropTypes.func, + config: PropTypes.shape({ + isSideNavFolded: PropTypes.bool + }) +} + +export default CSSModules(NewNoteButton, styles) diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index 5e56bedea..c469adb4e 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -2,12 +2,9 @@ import React, { PropTypes } from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './TopBar.styl' import _ from 'lodash' -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' +import NewNoteButton from 'browser/main/NewNoteButton' const { remote } = require('electron') const { dialog } = remote @@ -24,81 +21,19 @@ class TopBar extends React.Component { isSearching: false } - this.newNoteHandler = () => { - this.handleNewPostButtonClick() - } - this.focusSearchHandler = () => { this.handleOnSearchFocus() } } componentDidMount () { - ee.on('top:new-note', this.newNoteHandler) ee.on('top:focus-search', this.focusSearchHandler) } componentWillUnmount () { - ee.off('top:new-note', this.newNoteHandler) ee.off('top:focus-search', this.focusSearchHandler) } - handleNewPostButtonClick (e) { - let { config, location } = this.props - - if (location.pathname === '/trashed') { - dialog.showMessageBox(remote.getCurrentWindow(), { - type: 'warning', - message: 'Cannot create new note', - detail: 'You cannot create new note in trash box.', - buttons: ['OK'] - }) - return - } - - switch (config.ui.defaultNote) { - case 'MARKDOWN_NOTE': - this.createNote('MARKDOWN_NOTE') - break - case 'SNIPPET_NOTE': - this.createNote('SNIPPET_NOTE') - break - case 'ALWAYS_ASK': - default: - 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 - if (storage == null) { - for (let kv of data.storageMap) { - storage = kv[1] - break - } - } - if (storage == null) window.alert('No storage to create a note') - let folder = _.find(storage.folders, {key: params.folderKey}) - if (folder == null) folder = storage.folders[0] - if (folder == null) window.alert('No folder to create a note') - - return { - storage, - folder - } - } - handleSearchChange (e) { let { router } = this.context router.push('/searched') @@ -107,22 +42,6 @@ class TopBar extends React.Component { }) } - handleOptionClick (uniqueKey) { - return (e) => { - this.setState({ - isSearching: false - }, () => { - let { location } = this.props - hashHistory.push({ - pathname: location.pathname, - query: { - key: uniqueKey - } - }) - }) - } - } - handleSearchFocus (e) { this.setState({ isSearching: true @@ -147,60 +66,6 @@ class TopBar extends React.Component { } } - 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() - }) - } - handleOnSearchFocus () { if (this.state.isSearching) { this.refs.search.childNodes[0].blur() @@ -210,7 +75,7 @@ class TopBar extends React.Component { } render () { - let { config, style, data } = this.props + let { config, style, data, location } = this.props return (
-
+ {location.pathname === '/trashed' ? '' + : } ) } diff --git a/browser/main/modals/DeleteArticleModal.js b/browser/main/modals/DeleteArticleModal.js deleted file mode 100644 index 5069cda08..000000000 --- a/browser/main/modals/DeleteArticleModal.js +++ /dev/null @@ -1,51 +0,0 @@ -import React, { PropTypes } from 'react' -import ReactDOM from 'react-dom' - -const electron = require('electron') -const ipc = electron.ipcRenderer - -export default class DeleteArticleModal extends React.Component { - constructor (props) { - super(props) - - this.confirmHandler = (e) => this.handleYesButtonClick() - } - - componentDidMount () { - ReactDOM.findDOMNode(this.refs.no).focus() - ipc.on('modal-confirm', this.confirmHandler) - } - - componentWillUnmount () { - ipc.removeListener('modal-confirm', this.confirmHandler) - } - - handleNoButtonClick (e) { - this.props.close() - } - - handleYesButtonClick (e) { - this.props.close() - } - - render () { - return ( -
-
Delete an article.
- -
Do you really want to delete?
- -
- - -
-
- ) - } -} - -DeleteArticleModal.propTypes = { - action: PropTypes.object, - articleKey: PropTypes.string, - close: PropTypes.func -}