From 56eb9c76ae793db166f9b11bc60d5c071f2feab0 Mon Sep 17 00:00:00 2001 From: asmsuechan Date: Sun, 13 Aug 2017 22:39:17 +0900 Subject: [PATCH 1/9] Componentnize NewNoteButton --- browser/main/NewNoteButton/NewNoteButton.styl | 68 +++++++ browser/main/NewNoteButton/index.js | 182 ++++++++++++++++++ browser/main/TopBar/index.js | 153 +-------------- 3 files changed, 260 insertions(+), 143 deletions(-) create mode 100644 browser/main/NewNoteButton/NewNoteButton.styl create mode 100644 browser/main/NewNoteButton/index.js diff --git a/browser/main/NewNoteButton/NewNoteButton.styl b/browser/main/NewNoteButton/NewNoteButton.styl new file mode 100644 index 000000000..db5b4ca84 --- /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-newPostButton + 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-newPostButton-tooltip + opacity 1 + +.control-newPostButton-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-newPostButton + 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-newPostButton-tooltip + darkTooltip() diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js new file mode 100644 index 000000000..6e8674d73 --- /dev/null +++ b/browser/main/NewNoteButton/index.js @@ -0,0 +1,182 @@ +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 ee from 'browser/main/lib/eventEmitter' +import ConfigManager from 'browser/main/lib/ConfigManager' +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.handleNewPostButtonClick() + } + + } + + componentDidMount () { + ee.on('top:new-note', this.newNoteHandler) + } + + componentWillUnmount () { + ee.off('top:new-note', this.newNoteHandler) + } + + 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 + } + } + + 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 + return ( +
+
+ +
+
+ ) + } +} + +NewNoteButton.contextTypes = { + router: PropTypes.shape({ + push: PropTypes.func + }) +} + +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..b969af17f 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() @@ -242,14 +107,16 @@ class TopBar extends React.Component { } - + ) } From 8985062d3489cc423891bdcae8769e033b072d3d Mon Sep 17 00:00:00 2001 From: asmsuechan Date: Mon, 14 Aug 2017 09:14:51 +0900 Subject: [PATCH 2/9] :recycle: Refactor --- browser/main/NewNoteButton/NewNoteButton.styl | 10 +- browser/main/NewNoteButton/index.js | 139 ++++-------------- 2 files changed, 35 insertions(+), 114 deletions(-) diff --git a/browser/main/NewNoteButton/NewNoteButton.styl b/browser/main/NewNoteButton/NewNoteButton.styl index db5b4ca84..b53ff892c 100644 --- a/browser/main/NewNoteButton/NewNoteButton.styl +++ b/browser/main/NewNoteButton/NewNoteButton.styl @@ -20,7 +20,7 @@ $control-height = 34px overflow hidden display flex -.control-newPostButton +.control-newNoteButton display block width 32px height $control-height - 2 @@ -30,10 +30,10 @@ $control-height = 34px padding 0 &:active border-color $ui-button--active-backgroundColor - &:hover .control-newPostButton-tooltip + &:hover .control-newNoteButton-tooltip opacity 1 -.control-newPostButton-tooltip +.control-newNoteButton-tooltip tooltip() position fixed pointer-events none @@ -53,7 +53,7 @@ body[data-theme="dark"] .control border-color $ui-dark-borderColor - .control-newPostButton + .control-newNoteButton color $ui-inactive-text-color border-color $ui-dark-borderColor background-color $ui-dark-noteList-backgroundColor @@ -64,5 +64,5 @@ body[data-theme="dark"] background-color alpha($ui-dark-button--active-backgroundColor, 20%) border-color $ui-dark-button--active-backgroundColor - .control-newPostButton-tooltip + .control-newNoteButton-tooltip darkTooltip() diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js index 6e8674d73..d2269fa00 100644 --- a/browser/main/NewNoteButton/index.js +++ b/browser/main/NewNoteButton/index.js @@ -6,7 +6,6 @@ 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 { remote } = require('electron') @@ -22,7 +21,7 @@ class NewNoteButton extends React.Component { } this.newNoteHandler = () => { - this.handleNewPostButtonClick() + this.handleNewNoteButtonClick() } } @@ -35,38 +34,16 @@ class NewNoteButton extends React.Component { ee.off('top:new-note', this.newNoteHandler) } - 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 - } + handleNewNoteButtonClick (e) { + let { config, location, dispatch } = this.props + let { storage, folder } = this.resolveTargetFolder() - 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 - }) - } + modal.open(NewNoteModal, { + storage: storage.key, + folder: folder.key, + dispatch, + location + }) } resolveTargetFolder () { @@ -91,87 +68,31 @@ class NewNoteButton 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() - }) - } - render () { - let { config, style, data } = this.props - return ( -
-
- + let { config, style, data, location } = this.props + if (location.pathname === '/trashed') { + return '' + } else { + return ( +
+
+ +
-
- ) + ) + } } } -NewNoteButton.contextTypes = { - router: PropTypes.shape({ - push: PropTypes.func - }) -} - NewNoteButton.propTypes = { dispatch: PropTypes.func, config: PropTypes.shape({ From a5fa3e9e7a8c498bdbc644ca029da74a9090982d Mon Sep 17 00:00:00 2001 From: asmsuechan Date: Mon, 14 Aug 2017 09:17:12 +0900 Subject: [PATCH 3/9] :wastebasket: Remove unused file --- browser/main/modals/DeleteArticleModal.js | 51 ----------------------- 1 file changed, 51 deletions(-) delete mode 100644 browser/main/modals/DeleteArticleModal.js 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 -} From 169e30e0291a1888a49a6e194a5279b25bc84575 Mon Sep 17 00:00:00 2001 From: asmsuechan Date: Mon, 14 Aug 2017 09:37:54 +0900 Subject: [PATCH 4/9] Fix by lint --- browser/main/NewNoteButton/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js index d2269fa00..27f2039e8 100644 --- a/browser/main/NewNoteButton/index.js +++ b/browser/main/NewNoteButton/index.js @@ -23,7 +23,6 @@ class NewNoteButton extends React.Component { this.newNoteHandler = () => { this.handleNewNoteButtonClick() } - } componentDidMount () { From 105119e1a4d22dbe5f7fc8cb63cf48e5401f0d25 Mon Sep 17 00:00:00 2001 From: asmsuechan Date: Mon, 14 Aug 2017 09:48:18 +0900 Subject: [PATCH 5/9] Change let to const --- browser/main/NewNoteButton/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js index 27f2039e8..f41bca447 100644 --- a/browser/main/NewNoteButton/index.js +++ b/browser/main/NewNoteButton/index.js @@ -34,8 +34,8 @@ class NewNoteButton extends React.Component { } handleNewNoteButtonClick (e) { - let { config, location, dispatch } = this.props - let { storage, folder } = this.resolveTargetFolder() + const { config, location, dispatch } = this.props + const { storage, folder } = this.resolveTargetFolder() modal.open(NewNoteModal, { storage: storage.key, @@ -46,7 +46,7 @@ class NewNoteButton extends React.Component { } resolveTargetFolder () { - let { data, params } = this.props + const { data, params } = this.props let storage = data.storageMap.get(params.storageKey) // Find first storage @@ -68,7 +68,7 @@ class NewNoteButton extends React.Component { } render () { - let { config, style, data, location } = this.props + const { config, style, data, location } = this.props if (location.pathname === '/trashed') { return '' } else { From 7f52eed4d5d2376fa5f58f555d8508c0c5f0cb1b Mon Sep 17 00:00:00 2001 From: asmsuechan Date: Mon, 14 Aug 2017 10:07:20 +0900 Subject: [PATCH 6/9] Move condition of trash or not --- browser/main/NewNoteButton/index.js | 36 +++++++++++++---------------- browser/main/TopBar/index.js | 7 +++--- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js index f41bca447..5dd7eb207 100644 --- a/browser/main/NewNoteButton/index.js +++ b/browser/main/NewNoteButton/index.js @@ -68,27 +68,23 @@ class NewNoteButton extends React.Component { } render () { - const { config, style, data, location } = this.props - if (location.pathname === '/trashed') { - return '' - } else { - return ( -
-
- -
+ const { config, style, data } = this.props + return ( +
+
+
- ) - } +
+ ) } } diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index b969af17f..c469adb4e 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -75,7 +75,7 @@ class TopBar extends React.Component { } render () { - let { config, style, data } = this.props + let { config, style, data, location } = this.props return (
- + />}
) } From 70a6a3acb8b57171113bff308336311209953178 Mon Sep 17 00:00:00 2001 From: asmsuechan Date: Mon, 14 Aug 2017 10:11:04 +0900 Subject: [PATCH 7/9] Remove unused variable --- browser/main/NewNoteButton/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js index 5dd7eb207..aedcba21a 100644 --- a/browser/main/NewNoteButton/index.js +++ b/browser/main/NewNoteButton/index.js @@ -68,7 +68,7 @@ class NewNoteButton extends React.Component { } render () { - const { config, style, data } = this.props + const { config, style } = this.props return (
Date: Mon, 14 Aug 2017 10:43:28 +0900 Subject: [PATCH 8/9] Change ee to eventEmitter --- browser/main/NewNoteButton/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js index aedcba21a..cf4e511b6 100644 --- a/browser/main/NewNoteButton/index.js +++ b/browser/main/NewNoteButton/index.js @@ -5,7 +5,7 @@ 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 eventEmitter from 'browser/main/lib/eventEmitter' import dataApi from 'browser/main/lib/dataApi' const { remote } = require('electron') @@ -26,11 +26,11 @@ class NewNoteButton extends React.Component { } componentDidMount () { - ee.on('top:new-note', this.newNoteHandler) + eventEmitter.on('top:new-note', this.newNoteHandler) } componentWillUnmount () { - ee.off('top:new-note', this.newNoteHandler) + eventEmitter.off('top:new-note', this.newNoteHandler) } handleNewNoteButtonClick (e) { From a7527307184d8e273b8591fba247e13a7e5cba41 Mon Sep 17 00:00:00 2001 From: asmsuechan Date: Mon, 14 Aug 2017 11:39:06 +0900 Subject: [PATCH 9/9] Change to use sdialog.showMEssageBox() instead of window.alert --- browser/main/NewNoteButton/index.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js index cf4e511b6..6b09e8784 100644 --- a/browser/main/NewNoteButton/index.js +++ b/browser/main/NewNoteButton/index.js @@ -56,10 +56,11 @@ class NewNoteButton extends React.Component { 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') + + 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, @@ -67,6 +68,14 @@ class NewNoteButton extends React.Component { } } + showMessageBox (message) { + dialog.showMessageBox(remote.getCurrentWindow(), { + type: 'warning', + message: message, + buttons: ['OK'] + }) + } + render () { const { config, style } = this.props return (