diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index a3e7bb93c..c9d3d9636 100644 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -144,10 +144,12 @@ export default class MarkdownPreview extends React.Component { } handleContextMenu (e) { + if (!this.props.onContextMenu) return this.props.onContextMenu(e) } handleMouseDown (e) { + if (!this.props.onMouseDown) return if (e.target != null) { switch (e.target.tagName) { case 'A': @@ -159,6 +161,7 @@ export default class MarkdownPreview extends React.Component { } handleMouseUp (e) { + if (!this.props.onMouseUp) return if (e.target != null && e.target.tagName === 'A') { return null } diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js new file mode 100644 index 000000000..b77c0b6b9 --- /dev/null +++ b/browser/components/MarkdownSplitEditor.js @@ -0,0 +1,87 @@ +import React from 'react' +import CodeEditor from 'browser/components/CodeEditor' +import MarkdownPreview from 'browser/components/MarkdownPreview' +import { findStorage } from 'browser/lib/findStorage' + +import styles from './MarkdownSplitEditor.styl' +import CSSModules from 'browser/lib/CSSModules' + +class MarkdownSplitEditor extends React.Component { + constructor (props) { + super(props) + this.value = props.value + this.focus = () => this.refs.code.focus() + this.reload = () => this.refs.code.reload() + } + + handleOnChange () { + this.value = this.refs.code.value + this.props.onChange() + } + + handleCheckboxClick (e) { + e.preventDefault() + e.stopPropagation() + const idMatch = /checkbox-([0-9]+)/ + const checkedMatch = /\[x\]/i + const uncheckedMatch = /\[ \]/ + if (idMatch.test(e.target.getAttribute('id'))) { + const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1 + const lines = this.refs.code.value + .split('\n') + + const targetLine = lines[lineIndex] + + if (targetLine.match(checkedMatch)) { + lines[lineIndex] = targetLine.replace(checkedMatch, '[ ]') + } + if (targetLine.match(uncheckedMatch)) { + lines[lineIndex] = targetLine.replace(uncheckedMatch, '[x]') + } + this.refs.code.setValue(lines.join('\n')) + } + } + + render () { + const { config, value, storageKey } = this.props + const storage = findStorage(storageKey) + const previewStyle = {} + if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none' + return ( +
+ + this.handleCheckboxClick(e)} + showCopyNotification={config.ui.showCopyNotification} + storagePath={storage.path} + /> +
+ ) + } +} + +export default CSSModules(MarkdownSplitEditor, styles) diff --git a/browser/components/MarkdownSplitEditor.styl b/browser/components/MarkdownSplitEditor.styl new file mode 100644 index 000000000..c9afd22fe --- /dev/null +++ b/browser/components/MarkdownSplitEditor.styl @@ -0,0 +1,9 @@ +.root + width 100% + height 100% + font-size 30px + display flex + .codeEditor + width 50% + .preview + width 50% diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index 53e935745..0600d9abf 100644 --- a/browser/components/markdown.styl +++ b/browser/components/markdown.styl @@ -120,6 +120,7 @@ hr margin 15px 0 h1, h2, h3, h4, h5, h6 font-weight bold + word-wrap break-word h1 font-size 2.55em padding-bottom 0.3em @@ -157,6 +158,7 @@ p line-height 1.6em margin 0 0 1em white-space pre-line + word-wrap break-word img max-width 100% strong, b @@ -338,4 +340,4 @@ body[data-theme="dark"] body[data-theme="solarized-dark"] color $ui-solarized-dark-text-color border-color themeDarkBorder - background-color $ui-solarized-dark-noteDetail-backgroundColor \ No newline at end of file + background-color $ui-solarized-dark-noteDetail-backgroundColor diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 25c993d02..8d3acea9e 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -3,6 +3,7 @@ import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './MarkdownNoteDetail.styl' import MarkdownEditor from 'browser/components/MarkdownEditor' +import MarkdownSplitEditor from 'browser/components/MarkdownSplitEditor' import TodoListPercentage from 'browser/components/TodoListPercentage' import StarButton from './StarButton' import TagSelect from './TagSelect' @@ -15,6 +16,7 @@ import StatusBar from '../StatusBar' import _ from 'lodash' import { findNoteTitle } from 'browser/lib/findNoteTitle' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' +import ConfigManager from 'browser/main/lib/ConfigManager' import TrashButton from './TrashButton' import PermanentDeleteButton from './PermanentDeleteButton' import InfoButton from './InfoButton' @@ -39,7 +41,8 @@ class MarkdownNoteDetail extends React.Component { content: '' }, props.note), isLockButtonShown: false, - isLocked: false + isLocked: false, + editorType: props.config.editor.type } this.dispatchTimer = null @@ -233,7 +236,7 @@ class MarkdownNoteDetail extends React.Component { } getToggleLockButton () { - return this.state.isLocked ? '../resources/icon/icon-edit-lock.svg' : '../resources/icon/icon-edit.svg' + return this.state.isLocked ? '../resources/icon/icon-previewoff-on.svg' : '../resources/icon/icon-previewoff-off.svg' } handleDeleteKeyDown (e) { @@ -262,9 +265,42 @@ class MarkdownNoteDetail extends React.Component { ee.emit('print') } - render () { - const { data, config, location } = this.props + handleSwitchMode (type) { + this.setState({ editorType: type }, () => { + const newConfig = Object.assign({}, this.props.config) + newConfig.editor.type = type + ConfigManager.set(newConfig) + }) + } + + renderEditor () { + const { config, ignorePreviewPointerEvents } = this.props const { note } = this.state + if (this.state.editorType === 'EDITOR_PREVIEW') { + return this.handleChange(e)} + ignorePreviewPointerEvents={ignorePreviewPointerEvents} + /> + } else { + return this.handleChange(e)} + ignorePreviewPointerEvents={ignorePreviewPointerEvents} + /> + } + } + + render () { + const { data, location } = this.props + const { note, editorType } = this.state const storageKey = note.storage const folderKey = note.folder @@ -320,11 +356,11 @@ class MarkdownNoteDetail extends React.Component { />
-
- +
this.handleSwitchMode('SPLIT')}> +
-
- +
this.handleSwitchMode('EDITOR_PREVIEW')}> +
@@ -360,7 +396,7 @@ class MarkdownNoteDetail extends React.Component { this.handleTrashButtonClick(e)} /> @@ -390,15 +426,7 @@ class MarkdownNoteDetail extends React.Component { {location.pathname === '/trashed' ? trashTopBar : detailTopBar}
- this.handleChange(e)} - ignorePreviewPointerEvents={this.props.ignorePreviewPointerEvents} - /> + {this.renderEditor()}
- - - icon-WYSIWYG-off - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/resources/icon/icon-WYSIWYG-on.svg b/resources/icon/icon-WYSIWYG-on.svg deleted file mode 100644 index b8ee94899..000000000 --- a/resources/icon/icon-WYSIWYG-on.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - icon-WYSIWYG-on - Created with Sketch. - - - - - - - - - - - \ No newline at end of file diff --git a/resources/icon/icon-edit.svg b/resources/icon/icon-edit.svg index 3707c6fe2..cb7d92cc3 100644 --- a/resources/icon/icon-edit.svg +++ b/resources/icon/icon-edit.svg @@ -3,11 +3,22 @@ icon-edit Created with Sketch. - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/icon/icon-full.svg b/resources/icon/icon-full.svg new file mode 100644 index 000000000..621ebacc7 --- /dev/null +++ b/resources/icon/icon-full.svg @@ -0,0 +1,15 @@ + + + + icon-full + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/resources/icon/icon-mode-markdown-off.svg b/resources/icon/icon-mode-markdown-off.svg new file mode 100644 index 000000000..7f6a02352 --- /dev/null +++ b/resources/icon/icon-mode-markdown-off.svg @@ -0,0 +1,23 @@ + + + + icon-mode-markdown-off + Created with Sketch. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/icon/icon-mode-split-on.svg b/resources/icon/icon-mode-split-on.svg new file mode 100644 index 000000000..338d2bd71 --- /dev/null +++ b/resources/icon/icon-mode-split-on.svg @@ -0,0 +1,27 @@ + + + + icon-mode-split-on + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/icon/icon-previewoff-off.svg b/resources/icon/icon-previewoff-off.svg new file mode 100644 index 000000000..b0e720e7c --- /dev/null +++ b/resources/icon/icon-previewoff-off.svg @@ -0,0 +1,13 @@ + + + + icon-previewoff-off + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/resources/icon/icon-previewoff-on.svg b/resources/icon/icon-previewoff-on.svg new file mode 100644 index 000000000..8a6c5d7ed --- /dev/null +++ b/resources/icon/icon-previewoff-on.svg @@ -0,0 +1,13 @@ + + + + icon-previewoff-on + Created with Sketch. + + + + + + + + \ No newline at end of file