From 9b54272f8e748edfdb4f7a0af65c26b5f0850b5f Mon Sep 17 00:00:00 2001 From: Georges Indrianjafy Date: Sun, 4 Feb 2018 13:57:00 +0200 Subject: [PATCH 01/34] feat(code-editor): fetch title when pasting url --- browser/components/CodeEditor.js | 66 +++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 5d799935..2b6cfafc 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -226,26 +226,56 @@ export default class CodeEditor extends React.Component { } handlePaste (editor, e) { - const dataTransferItem = e.clipboardData.items[0] - if (!dataTransferItem.type.match('image')) return + const clipboardData = e.clipboardData + const dataTransferItem = clipboardData.items[0] + const pasteTxt = clipboardData.getData('text') + const isURL = (str) => { + const matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/ + return matcher.test(str) + } + if (dataTransferItem.type.match('image')) { + const blob = dataTransferItem.getAsFile() + const reader = new FileReader() + let base64data - const blob = dataTransferItem.getAsFile() - const reader = new FileReader() - let base64data + reader.readAsDataURL(blob) + reader.onloadend = () => { + base64data = reader.result.replace(/^data:image\/png;base64,/, '') + base64data += base64data.replace('+', ' ') + const binaryData = new Buffer(base64data, 'base64').toString('binary') + const imageName = Math.random().toString(36).slice(-16) + const storagePath = findStorage(this.props.storageKey).path + const imageDir = path.join(storagePath, 'images') + if (!fs.existsSync(imageDir)) fs.mkdirSync(imageDir) + const imagePath = path.join(imageDir, `${imageName}.png`) + fs.writeFile(imagePath, binaryData, 'binary') + const imageMd = `![${imageName}](${path.join('/:storage', `${imageName}.png`)})` + this.insertImageMd(imageMd) + } + } else if (this.props.fetchUrlTitle && isURL(pasteTxt)) { + e.preventDefault() + const taggedUrl = '[' + pasteTxt + ']' + editor.replaceSelection(taggedUrl) - reader.readAsDataURL(blob) - reader.onloadend = () => { - base64data = reader.result.replace(/^data:image\/png;base64,/, '') - base64data += base64data.replace('+', ' ') - const binaryData = new Buffer(base64data, 'base64').toString('binary') - const imageName = Math.random().toString(36).slice(-16) - const storagePath = findStorage(this.props.storageKey).path - const imageDir = path.join(storagePath, 'images') - if (!fs.existsSync(imageDir)) fs.mkdirSync(imageDir) - const imagePath = path.join(imageDir, `${imageName}.png`) - fs.writeFile(imagePath, binaryData, 'binary') - const imageMd = `![${imageName}](${path.join('/:storage', `${imageName}.png`)})` - this.insertImageMd(imageMd) + fetch(pasteTxt, { + method: 'get' + }).then((response) => { + return (response.text()) + }).then((response) => { + const parsedResponse = (new window.DOMParser()).parseFromString(response, 'text/html') + const value = editor.getValue() + const cursor = editor.getCursor() + const LinkWithTitle = `[${parsedResponse.title}](${pasteTxt})` + const newValue = value.replace(taggedUrl, LinkWithTitle) + editor.setValue(newValue) + editor.setCursor(cursor) + }).catch((e) => { + const value = editor.getValue() + const newValue = value.replace(taggedUrl, pasteTxt) + const cursor = editor.getCursor() + editor.setValue(newValue) + editor.setCursor(cursor) + }) } } From 56d6eb7077d1effc927a6a50c38cb7083f293431 Mon Sep 17 00:00:00 2001 From: Georges Indrianjafy Date: Sun, 4 Feb 2018 13:58:02 +0200 Subject: [PATCH 02/34] feat(config): add ablility to opt out of fetch url --- browser/components/MarkdownEditor.js | 1 + browser/components/MarkdownSplitEditor.js | 1 + browser/finder/NoteDetail.js | 1 + browser/main/Detail/SnippetNoteDetail.js | 1 + browser/main/lib/ConfigManager.js | 3 ++- browser/main/modals/PreferencesModal/UiTab.js | 14 +++++++++++++- 6 files changed, 19 insertions(+), 2 deletions(-) diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index 1b44166c..62c4414a 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -244,6 +244,7 @@ class MarkdownEditor extends React.Component { indentSize={editorIndentSize} scrollPastEnd={config.editor.scrollPastEnd} storageKey={storageKey} + fetchUrlTitle={config.editor.fetchUrlTitle} onChange={(e) => this.handleChange(e)} onBlur={(e) => this.handleBlur(e)} /> diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index d0a3eb27..15498662 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -65,6 +65,7 @@ class MarkdownSplitEditor extends React.Component { indentType={config.editor.indentType} indentSize={editorIndentSize} scrollPastEnd={config.editor.scrollPastEnd} + fetchUrlTitle={config.editor.fetchUrlTitle} storageKey={storageKey} onChange={this.handleOnChange.bind(this)} /> diff --git a/browser/finder/NoteDetail.js b/browser/finder/NoteDetail.js index 3b9121d7..1325e87f 100644 --- a/browser/finder/NoteDetail.js +++ b/browser/finder/NoteDetail.js @@ -159,6 +159,7 @@ class NoteDetail extends React.Component { indentSize={editorIndentSize} keyMap={config.editor.keyMap} scrollPastEnd={config.editor.scrollPastEnd} + fetchUrlTitle={config.editor.fetchUrlTitle} readOnly ref={'code-' + index} /> diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index af8c178e..44c36492 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -566,6 +566,7 @@ class SnippetNoteDetail extends React.Component { indentSize={editorIndentSize} keyMap={config.editor.keyMap} scrollPastEnd={config.editor.scrollPastEnd} + fetchUrlTitle={config.editor.fetchUrlTitle} onChange={(e) => this.handleCodeChange(index)(e)} ref={'code-' + index} /> diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 834646b4..4c0d410f 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -36,7 +36,8 @@ export const DEFAULT_CONFIG = { indentSize: '2', switchPreview: 'BLUR', // Available value: RIGHTCLICK, BLUR scrollPastEnd: false, - type: 'SPLIT' + type: 'SPLIT', + fetchUrlTitle: true }, preview: { fontSize: '14', diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index ed633c7d..d4afd2a6 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -75,7 +75,8 @@ class UiTab extends React.Component { indentSize: this.refs.editorIndentSize.value, switchPreview: this.refs.editorSwitchPreview.value, keyMap: this.refs.editorKeyMap.value, - scrollPastEnd: this.refs.scrollPastEnd.checked + scrollPastEnd: this.refs.scrollPastEnd.checked, + fetchUrlTitle: this.refs.editorFetchUrlTitle.checked, }, preview: { fontSize: this.refs.previewFontSize.value, @@ -315,6 +316,17 @@ class UiTab extends React.Component { +
+ +
+
Preview
From 10daf2599db79b3d5606126155336059075d7a9c Mon Sep 17 00:00:00 2001 From: Georges Indrianjafy Date: Sun, 4 Feb 2018 17:39:32 +0200 Subject: [PATCH 03/34] chore: fix lint isues --- browser/main/modals/PreferencesModal/UiTab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index d4afd2a6..86f8fa2a 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -76,7 +76,7 @@ class UiTab extends React.Component { switchPreview: this.refs.editorSwitchPreview.value, keyMap: this.refs.editorKeyMap.value, scrollPastEnd: this.refs.scrollPastEnd.checked, - fetchUrlTitle: this.refs.editorFetchUrlTitle.checked, + fetchUrlTitle: this.refs.editorFetchUrlTitle.checked }, preview: { fontSize: this.refs.previewFontSize.value, From 3e2b876c591575f0bae54b6d45a2f66ca71e2a19 Mon Sep 17 00:00:00 2001 From: Georges Indrianjafy Date: Sun, 4 Feb 2018 17:49:23 +0200 Subject: [PATCH 04/34] fix(config): refrase --- browser/main/modals/PreferencesModal/UiTab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 86f8fa2a..dc161514 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -323,7 +323,7 @@ class UiTab extends React.Component { ref='editorFetchUrlTitle' type='checkbox' />  - Allow editor to fetch url titles on when pasting url + Bring in web page title when pasting URL on editor
From d9d46cda1cabf1d81fbe0e5e04fa4f8c29bbca83 Mon Sep 17 00:00:00 2001 From: Georges Indrianjafy Date: Mon, 5 Feb 2018 10:59:36 +0200 Subject: [PATCH 05/34] feat(editor): extract pasting url method --- browser/components/CodeEditor.js | 54 +++++++++++++++++--------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 2b6cfafc..ccc70b8a 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -228,7 +228,7 @@ export default class CodeEditor extends React.Component { handlePaste (editor, e) { const clipboardData = e.clipboardData const dataTransferItem = clipboardData.items[0] - const pasteTxt = clipboardData.getData('text') + const pastedTxt = clipboardData.getData('text') const isURL = (str) => { const matcher = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/ return matcher.test(str) @@ -252,33 +252,37 @@ export default class CodeEditor extends React.Component { const imageMd = `![${imageName}](${path.join('/:storage', `${imageName}.png`)})` this.insertImageMd(imageMd) } - } else if (this.props.fetchUrlTitle && isURL(pasteTxt)) { - e.preventDefault() - const taggedUrl = '[' + pasteTxt + ']' - editor.replaceSelection(taggedUrl) - - fetch(pasteTxt, { - method: 'get' - }).then((response) => { - return (response.text()) - }).then((response) => { - const parsedResponse = (new window.DOMParser()).parseFromString(response, 'text/html') - const value = editor.getValue() - const cursor = editor.getCursor() - const LinkWithTitle = `[${parsedResponse.title}](${pasteTxt})` - const newValue = value.replace(taggedUrl, LinkWithTitle) - editor.setValue(newValue) - editor.setCursor(cursor) - }).catch((e) => { - const value = editor.getValue() - const newValue = value.replace(taggedUrl, pasteTxt) - const cursor = editor.getCursor() - editor.setValue(newValue) - editor.setCursor(cursor) - }) + } else if (this.props.fetchUrlTitle && isURL(pastedTxt)) { + this.handlePasteUrl(e, editor, pastedTxt) } } + handlePasteUrl(e, editor, pastedTxt){ + e.preventDefault() + const taggedUrl = '[' + pastedTxt + ']' + editor.replaceSelection(taggedUrl) + + fetch(pastedTxt, { + method: 'get' + }).then((response) => { + return (response.text()) + }).then((response) => { + const parsedResponse = (new window.DOMParser()).parseFromString(response, 'text/html') + const value = editor.getValue() + const cursor = editor.getCursor() + const LinkWithTitle = `[${parsedResponse.title}](${pastedTxt})` + const newValue = value.replace(taggedUrl, LinkWithTitle) + editor.setValue(newValue) + editor.setCursor(cursor) + }).catch((e) => { + const value = editor.getValue() + const newValue = value.replace(taggedUrl, pastedTxt) + const cursor = editor.getCursor() + editor.setValue(newValue) + editor.setCursor(cursor) + }) + } + render () { const { className, fontSize } = this.props let fontFamily = this.props.fontFamily From c42ac1df1b21e96ab977dd6a9526494ef6e44e2b Mon Sep 17 00:00:00 2001 From: Georges Indrianjafy Date: Mon, 5 Feb 2018 11:00:56 +0200 Subject: [PATCH 06/34] chore(editor): resolve lint issues --- browser/components/CodeEditor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index ccc70b8a..d50f3d8e 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -257,7 +257,7 @@ export default class CodeEditor extends React.Component { } } - handlePasteUrl(e, editor, pastedTxt){ + handlePasteUrl (e, editor, pastedTxt) { e.preventDefault() const taggedUrl = '[' + pastedTxt + ']' editor.replaceSelection(taggedUrl) From a676ebf46cbd474477f6a1f3c237248fa43bac65 Mon Sep 17 00:00:00 2001 From: Georges Indrianjafy Date: Tue, 6 Feb 2018 18:35:11 +0200 Subject: [PATCH 07/34] fix(editor): replace [] with <> --- browser/components/CodeEditor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 7e59ea65..adc51321 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -264,7 +264,7 @@ export default class CodeEditor extends React.Component { handlePasteUrl (e, editor, pastedTxt) { e.preventDefault() - const taggedUrl = '[' + pastedTxt + ']' + const taggedUrl = '<' + pastedTxt + '>' editor.replaceSelection(taggedUrl) fetch(pastedTxt, { From dc1b059a9da5a4998a46f82bb2a5dbb252620043 Mon Sep 17 00:00:00 2001 From: Georges Indrianjafy Date: Tue, 6 Feb 2018 19:12:25 +0200 Subject: [PATCH 08/34] clean up --- browser/components/CodeEditor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index adc51321..75baffb3 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -264,7 +264,7 @@ export default class CodeEditor extends React.Component { handlePasteUrl (e, editor, pastedTxt) { e.preventDefault() - const taggedUrl = '<' + pastedTxt + '>' + const taggedUrl = `<${pastedTxt}>` editor.replaceSelection(taggedUrl) fetch(pastedTxt, { From 7b920348f3023f203bd32818691aa12e4622035b Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Sat, 10 Feb 2018 01:21:52 +0100 Subject: [PATCH 09/34] UX: Keep selection synced with note visibility --- browser/main/NoteList/index.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 30317095..bb583128 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -109,14 +109,27 @@ class NoteList extends React.Component { componentDidUpdate (prevProps) { const { location } = this.props + const { selectedNoteKeys } = this.state + const visibleNoteKeys = this.notes.map(note => `${note.storage}-${note.key}`) + const note = this.notes[0] + const prevKey = prevProps.location.query.key + const noteKey = visibleNoteKeys.includes(prevKey) ? prevKey : note && `${note.storage}-${note.key}` - if (this.notes.length > 0 && location.query.key == null) { + if (note && location.query.key == null) { const { router } = this.context if (!location.pathname.match(/\/searched/)) this.contextNotes = this.getContextNotes() + + // A visible note is an active note + if (!selectedNoteKeys.includes(noteKey)) { + if (selectedNoteKeys.length === 1) selectedNoteKeys.pop() + selectedNoteKeys.push(noteKey) + ee.emit('list:moved') + } + router.replace({ pathname: location.pathname, query: { - key: this.notes[0].storage + '-' + this.notes[0].key + key: noteKey } }) return From c43589fe6af135c86f3a839a0c639cf6ba7c5ab6 Mon Sep 17 00:00:00 2001 From: Masahide Morio Date: Sun, 11 Feb 2018 02:28:03 +0900 Subject: [PATCH 10/34] Add file name and any first line number in code block (fixed) --- browser/components/markdown.styl | 8 ++++++++ browser/lib/markdown.js | 16 ++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index d1d306e9..b64af56c 100644 --- a/browser/components/markdown.styl +++ b/browser/components/markdown.styl @@ -220,6 +220,7 @@ pre background-color white &.CodeMirror height initial + flex-wrap wrap &>code flex 1 overflow-x auto @@ -229,6 +230,13 @@ pre padding 0 border none border-radius 0 + &>span.filename + width 100% + border-radius: 5px 0px 0px 0px + margin -8px 100% 8px -8px + padding 0px 6px + background-color #777; + color white &>span.lineNumber display none font-size 1em diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index c3510f89..e6ba46d6 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -9,10 +9,11 @@ import {lastFindInArray} from './utils' const katex = window.katex const config = ConfigManager.get() -function createGutter (str) { - const lc = (str.match(/\n/g) || []).length +function createGutter (str, fc) { + if(Number.isNaN(fc)) fc = 1 + const lc = (str.match(/\n/g) || []).length + fc - 1 const lines = [] - for (let i = 1; i <= lc; i++) { + for (let i = fc; i <= lc; i++) { lines.push('' + i + '') } return '' + lines.join('') + '' @@ -25,6 +26,12 @@ var md = markdownit({ xhtmlOut: true, breaks: true, highlight: function (str, lang) { + let delimiter = ":"; + let langinfo = lang.split(delimiter); + let lang = langinfo[0]; + let filename = langinfo[1] || ""; + let fc = parseInt(langinfo[2],10); + if (lang === 'flowchart') { return `
${str}
` } @@ -32,7 +39,8 @@ var md = markdownit({ return `
${str}
` } return '
' +
-      createGutter(str) +
+      '' + filename + '' +
+      createGutter(str, fc) +
       '' +
       str +
       '
' From 5e07c7b3e1573cecabb917c10675cc0952b66bce Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Mon, 12 Feb 2018 18:15:05 +0100 Subject: [PATCH 11/34] Update selection on new note; closes #1507 --- browser/main/modals/NewNoteModal.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/browser/main/modals/NewNoteModal.js b/browser/main/modals/NewNoteModal.js index 24b150cb..8322d99f 100644 --- a/browser/main/modals/NewNoteModal.js +++ b/browser/main/modals/NewNoteModal.js @@ -35,14 +35,16 @@ class NewNoteModal extends React.Component { content: '' }) .then((note) => { + const noteHash = `${note.storage}-${note.key}` dispatch({ type: 'UPDATE_NOTE', note: note }) hashHistory.push({ pathname: location.pathname, - query: {key: note.storage + '-' + note.key} + query: {key: noteHash} }) + ee.emit('list:jump', noteHash) ee.emit('detail:focus') this.props.close() }) @@ -73,14 +75,16 @@ class NewNoteModal extends React.Component { }] }) .then((note) => { + const noteHash = `${note.storage}-${note.key}` dispatch({ type: 'UPDATE_NOTE', note: note }) hashHistory.push({ pathname: location.pathname, - query: {key: note.storage + '-' + note.key} + query: {key: noteHash} }) + ee.emit('list:jump', noteHash) ee.emit('detail:focus') this.props.close() }) From 67ddff736c4fa4fc2679abf69c40238c649a65be Mon Sep 17 00:00:00 2001 From: Nikolay Lopin Date: Tue, 13 Feb 2018 23:43:11 +0300 Subject: [PATCH 12/34] Switch from preview to edit by double click User want to click markdown to work with text (for example copy). If they have "Switch to Preview" setting in "When Editor Blurred", they enter edit mode after click. To fix that issue I introduced new value to the "Switch to Preview" setting that do that thing. User can enter edit mode by double click on the editor and leave it on blur. Unfortunately, it's impossible to switch both ways by double click because the editor mode is listening for double click event. #1523 --- browser/components/MarkdownEditor.js | 21 +++++++++++++++++-- browser/components/MarkdownPreview.js | 7 +++++++ browser/main/modals/PreferencesModal/UiTab.js | 1 + 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index 52ab2873..8d79629d 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -5,7 +5,7 @@ import styles from './MarkdownEditor.styl' import CodeEditor from 'browser/components/CodeEditor' import MarkdownPreview from 'browser/components/MarkdownPreview' import eventEmitter from 'browser/main/lib/eventEmitter' -import { findStorage } from 'browser/lib/findStorage' +import {findStorage} from 'browser/lib/findStorage' class MarkdownEditor extends React.Component { constructor (props) { @@ -92,7 +92,9 @@ class MarkdownEditor extends React.Component { if (this.state.isLocked) return this.setState({ keyPressed: new Set() }) const { config } = this.props - if (config.editor.switchPreview === 'BLUR') { + if (config.editor.switchPreview === 'BLUR' || + (config.editor.switchPreview === 'DBL_CLICK' && this.state.status === 'CODE') + ) { const cursorPosition = this.refs.code.editor.getCursor() this.setState({ status: 'PREVIEW' @@ -104,6 +106,20 @@ class MarkdownEditor extends React.Component { } } + handleDoubleClick (e) { + if (this.state.isLocked) return + this.setState({keyPressed: new Set()}) + const { config } = this.props + if (config.editor.switchPreview === 'DBL_CLICK') { + this.setState({ + status: 'CODE' + }, () => { + this.refs.code.focus() + eventEmitter.emit('topbar:togglelockbutton', this.state.status) + }) + } + } + handlePreviewMouseDown (e) { this.previewMouseDownedAt = new Date() } @@ -264,6 +280,7 @@ class MarkdownEditor extends React.Component { scrollPastEnd={config.preview.scrollPastEnd} ref='preview' onContextMenu={(e) => this.handleContextMenu(e)} + onDoubleClick={(e) => this.handleDoubleClick(e)} tabIndex='0' value={this.state.renderValue} onMouseUp={(e) => this.handlePreviewMouseUp(e)} diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index ecaff1b8..1d0f7513 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -120,6 +120,7 @@ export default class MarkdownPreview extends React.Component { this.contextMenuHandler = (e) => this.handleContextMenu(e) this.mouseDownHandler = (e) => this.handleMouseDown(e) this.mouseUpHandler = (e) => this.handleMouseUp(e) + this.DoubleClickHandler = (e) => this.handleDoubleClick(e) this.anchorClickHandler = (e) => this.handlePreviewAnchorClick(e) this.checkboxClickHandler = (e) => this.handleCheckboxClick(e) this.saveAsTextHandler = () => this.handleSaveAsText() @@ -154,6 +155,10 @@ export default class MarkdownPreview extends React.Component { this.props.onContextMenu(e) } + handleDoubleClick (e) { + if (this.props.onDoubleClick != null) this.props.onDoubleClick(e) + } + handleMouseDown (e) { if (e.target != null) { switch (e.target.tagName) { @@ -271,6 +276,7 @@ export default class MarkdownPreview extends React.Component { this.refs.root.contentWindow.document.addEventListener('mousedown', this.mouseDownHandler) this.refs.root.contentWindow.document.addEventListener('mouseup', this.mouseUpHandler) + this.refs.root.contentWindow.document.addEventListener('dblclick', this.DoubleClickHandler) this.refs.root.contentWindow.document.addEventListener('drop', this.preventImageDroppedHandler) this.refs.root.contentWindow.document.addEventListener('dragover', this.preventImageDroppedHandler) eventEmitter.on('export:save-text', this.saveAsTextHandler) @@ -283,6 +289,7 @@ export default class MarkdownPreview extends React.Component { this.refs.root.contentWindow.document.body.removeEventListener('contextmenu', this.contextMenuHandler) this.refs.root.contentWindow.document.removeEventListener('mousedown', this.mouseDownHandler) this.refs.root.contentWindow.document.removeEventListener('mouseup', this.mouseUpHandler) + this.refs.root.contentWindow.document.removeEventListener('dblclick', this.DoubleClickHandler) this.refs.root.contentWindow.document.removeEventListener('drop', this.preventImageDroppedHandler) this.refs.root.contentWindow.document.removeEventListener('dragover', this.preventImageDroppedHandler) eventEmitter.off('export:save-text', this.saveAsTextHandler) diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index df35e260..654e1dfd 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -283,6 +283,7 @@ class UiTab extends React.Component { onChange={(e) => this.handleUIChange(e)} > +
From 55e9441547ad4a1a909a034602f7baa293e4597a Mon Sep 17 00:00:00 2001 From: Nikolay Lopin Date: Sat, 17 Feb 2018 00:37:36 +0300 Subject: [PATCH 13/34] Introduce RestoreButton component instead of plain JSX --- browser/main/Detail/MarkdownNoteDetail.js | 6 ++---- browser/main/Detail/RestoreButton.js | 21 +++++++++++++++++++++ browser/main/Detail/RestoreButton.styl | 22 ++++++++++++++++++++++ browser/main/Detail/SnippetNoteDetail.js | 6 ++---- 4 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 browser/main/Detail/RestoreButton.js create mode 100644 browser/main/Detail/RestoreButton.styl diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index bb76b8f3..19a3f034 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -19,6 +19,7 @@ import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' import ConfigManager from 'browser/main/lib/ConfigManager' import TrashButton from './TrashButton' import FullscreenButton from './FullscreenButton' +import RestoreButton from './RestoreButton' import PermanentDeleteButton from './PermanentDeleteButton' import InfoButton from './InfoButton' import ToggleModeButton from './ToggleModeButton' @@ -324,10 +325,7 @@ class MarkdownNoteDetail extends React.Component { const trashTopBar =
- this.handleUndoButtonClick(e)} - /> + this.handleUndoButtonClick(e)} />
this.handleTrashButtonClick(e)} /> diff --git a/browser/main/Detail/RestoreButton.js b/browser/main/Detail/RestoreButton.js new file mode 100644 index 00000000..cb1ccec2 --- /dev/null +++ b/browser/main/Detail/RestoreButton.js @@ -0,0 +1,21 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './RestoreButton.styl' + +const RestoreButton = ({ + onClick +}) => ( + +) + +RestoreButton.propTypes = { + onClick: PropTypes.func.isRequired +} + +export default CSSModules(RestoreButton, styles) diff --git a/browser/main/Detail/RestoreButton.styl b/browser/main/Detail/RestoreButton.styl new file mode 100644 index 00000000..58ce745d --- /dev/null +++ b/browser/main/Detail/RestoreButton.styl @@ -0,0 +1,22 @@ +.control-restoreButton + top 115px + topBarButtonRight() + &:hover .tooltip + opacity 1 + +.tooltip + tooltip() + position absolute + pointer-events none + top 50px + left 25px + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s + +body[data-theme="dark"] + .control-restoreButton + topBarButtonDark() diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index 366c785b..8eb85970 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -20,6 +20,7 @@ import _ from 'lodash' import { findNoteTitle } from 'browser/lib/findNoteTitle' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' import TrashButton from './TrashButton' +import RestoreButton from './RestoreButton' import PermanentDeleteButton from './PermanentDeleteButton' import InfoButton from './InfoButton' import InfoPanel from './InfoPanel' @@ -588,10 +589,7 @@ class SnippetNoteDetail extends React.Component { const trashTopBar =
- this.handleUndoButtonClick(e)} - /> + this.handleUndoButtonClick(e)} />
this.handleTrashButtonClick(e)} /> From 419a4c6b2d440c3b69d798a8a7d59f95d0ce6216 Mon Sep 17 00:00:00 2001 From: Nikolay Lopin Date: Sat, 17 Feb 2018 00:38:19 +0300 Subject: [PATCH 14/34] Add "Restore note" item to menu in Trash view. --- browser/main/NoteList/index.js | 60 ++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 7dd28340..ea7a0a8d 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -66,6 +66,7 @@ class NoteList extends React.Component { this.deleteNote = this.deleteNote.bind(this) this.focusNote = this.focusNote.bind(this) this.pinToTop = this.pinToTop.bind(this) + this.restoreNote = this.restoreNote.bind(this) // TODO: not Selected noteKeys but SelectedNote(for reusing) this.state = { @@ -440,6 +441,7 @@ class NoteList extends React.Component { const pinLabel = note.isPinned ? 'Remove pin' : 'Pin to Top' const deleteLabel = 'Delete Note' const cloneNote = 'Clone Note' + const restoreNote = 'Restore Note' const menu = new Menu() if (!location.pathname.match(/\/starred|\/trash/)) { @@ -448,6 +450,14 @@ class NoteList extends React.Component { click: this.pinToTop })) } + + if (location.pathname.match(/\/trash/)) { + menu.append(new MenuItem({ + label: restoreNote, + click: this.restoreNote + })) + } + menu.append(new MenuItem({ label: deleteLabel, click: this.deleteNote @@ -459,28 +469,50 @@ class NoteList extends React.Component { menu.popup() } - pinToTop () { + updateSelectedNotes (updateFunc, cleanSelection = true) { const { selectedNoteKeys } = this.state const { dispatch } = this.props const notes = this.notes.map((note) => Object.assign({}, note)) const selectedNotes = findNotesByKeys(notes, selectedNoteKeys) + if (!_.isFunction(updateFunc)) { + console.warn('Update function is not defined. No update will happen') + updateFunc = (note) => { return note } + } + Promise.all( - selectedNotes.map((note) => { - note.isPinned = !note.isPinned - return dataApi - .updateNote(note.storage, note.key, note) - }) - ) - .then((updatedNotes) => { - updatedNotes.forEach((note) => { - dispatch({ - type: 'UPDATE_NOTE', - note + selectedNotes.map((note) => { + note = updateFunc(note) + return dataApi + .updateNote(note.storage, note.key, note) }) - }) + ) + .then((updatedNotes) => { + updatedNotes.forEach((note) => { + dispatch({ + type: 'UPDATE_NOTE', + note + }) + }) + }) + + if (cleanSelection) { + this.selectNextNote() + } + } + + pinToTop () { + this.updateSelectedNotes((note) => { + note.isPinned = !note.isPinned + return note + }) + } + + restoreNote () { + this.updateSelectedNotes((note) => { + note.isTrashed = false + return note }) - this.setState({ selectedNoteKeys: [] }) } deleteNote () { From 0fdfb385a4afc16592b590747dea04d15c841a0e Mon Sep 17 00:00:00 2001 From: Kazu Yokomizo Date: Mon, 19 Feb 2018 15:01:08 +0900 Subject: [PATCH 15/34] Change blog to Boostlog from Medium --- browser/main/modals/PreferencesModal/InfoTab.js | 2 +- readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/main/modals/PreferencesModal/InfoTab.js b/browser/main/modals/PreferencesModal/InfoTab.js index 892b6ee2..25c0b255 100644 --- a/browser/main/modals/PreferencesModal/InfoTab.js +++ b/browser/main/modals/PreferencesModal/InfoTab.js @@ -83,7 +83,7 @@ class InfoTab extends React.Component { >GitHub
  • - this.handleLinkClick(e)} >Blog
  • diff --git a/readme.md b/readme.md index 40012652..67a5689d 100644 --- a/readme.md +++ b/readme.md @@ -26,7 +26,7 @@ Boostnote is an open source project. It's an independent project with its ongoin - [Facebook Group](https://www.facebook.com/groups/boostnote/) - [Twitter](https://twitter.com/boostnoteapp) - [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMzAzMjI1MTIyNTQ3LTc2MjNiYWU3NTc1YjZlMTk3NzFmOWE1ZWU1MGRhMzBkMGIwMWFjOWMxMDRiM2I2NzkzYzc4OGZhNmVhZjYzZTM) -- [Blog](https://medium.com/boostnote) +- [Blog](https://boostlog.io/@junp1234) - [Reddit](https://www.reddit.com/r/Boostnote/) From 3194a7b1a2f108111a44da7c897065b3209d3b7d Mon Sep 17 00:00:00 2001 From: Masahide Morio Date: Mon, 19 Feb 2018 23:02:25 +0900 Subject: [PATCH 16/34] followed eslintrc --- browser/lib/markdown.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index e6ba46d6..003dd58d 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -10,7 +10,7 @@ const katex = window.katex const config = ConfigManager.get() function createGutter (str, fc) { - if(Number.isNaN(fc)) fc = 1 + if (Number.isNaN(fc)) fc = 1 const lc = (str.match(/\n/g) || []).length + fc - 1 const lines = [] for (let i = fc; i <= lc; i++) { @@ -26,22 +26,22 @@ var md = markdownit({ xhtmlOut: true, breaks: true, highlight: function (str, lang) { - let delimiter = ":"; - let langinfo = lang.split(delimiter); - let lang = langinfo[0]; - let filename = langinfo[1] || ""; - let fc = parseInt(langinfo[2],10); + const delimiter = ':' + const langInfo = lang.split(delimiter) + const langType = langInfo[0] + const fileName = langInfo[1] || '' + const fc = parseInt(langInfo[2], 10) - if (lang === 'flowchart') { + if (langType === 'flowchart') { return `
    ${str}
    ` } - if (lang === 'sequence') { + if (langType === 'sequence') { return `
    ${str}
    ` } return '
    ' +
    -      '' + filename + '' +
    +      '' + fileName + '' +
           createGutter(str, fc) +
    -      '' +
    +      '' +
           str +
           '
    ' } From 129ef6766b064fdacab2319929ae965bc235969a Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Mon, 19 Feb 2018 10:17:36 -0800 Subject: [PATCH 17/34] Add storage labels to 'All Notes' Added storage labelings to 'All Notes' in Default and Compressed views --- browser/components/NoteItem.js | 53 ++++++++++++++++++-------- browser/components/NoteItem.styl | 33 +++++++++++----- browser/components/NoteItemSimple.js | 22 +++++++++-- browser/components/NoteItemSimple.styl | 11 ++++-- browser/main/NoteList/index.js | 9 +++++ 5 files changed, 96 insertions(+), 32 deletions(-) diff --git a/browser/components/NoteItem.js b/browser/components/NoteItem.js index 31769abf..e55db70a 100644 --- a/browser/components/NoteItem.js +++ b/browser/components/NoteItem.js @@ -46,11 +46,21 @@ const TagElementList = (tags) => { * @param {Function} handleDragStart * @param {string} dateDisplay */ -const NoteItem = ({ isActive, note, dateDisplay, handleNoteClick, handleNoteContextMenu, handleDragStart, pathname }) => ( +const NoteItem = ({ + isActive, + isAllNotesView, + note, + dateDisplay, + handleNoteClick, + handleNoteContextMenu, + handleDragStart, + pathname, + storage +}) => (
    handleNoteClick(e, `${note.storage}-${note.key}`)} onContextMenu={e => handleNoteContextMenu(e, `${note.storage}-${note.key}`)} @@ -68,23 +78,34 @@ const NoteItem = ({ isActive, note, dateDisplay, handleNoteClick, handleNoteCont : Empty }
    + {isAllNotesView &&
    +
    {dateDisplay}
    +
    +
    + + {storage.name} + +
    +
    +
    } -
    {dateDisplay}
    - {note.isStarred - ? : '' - } - {note.isPinned && !pathname.match(/\/starred|\/trash/) - ? : '' - } - {note.type === 'MARKDOWN_NOTE' - ? - : '' - }
    {note.tags.length > 0 ? TagElementList(note.tags) - : + : No tags + } +
    +
    + {note.isStarred + ? : '' + } + {note.isPinned && !pathname.match(/\/home|\/starred|\/trash/) + ? : '' + } + {note.type === 'MARKDOWN_NOTE' + ? + : '' }
    diff --git a/browser/components/NoteItem.styl b/browser/components/NoteItem.styl index c57908b0..5a8be3c5 100644 --- a/browser/components/NoteItem.styl +++ b/browser/components/NoteItem.styl @@ -90,6 +90,25 @@ $control-height = 30px font-weight normal color $ui-inactive-text-color +.item-middle + font-size 13px + padding-left 2px + padding-bottom 2px + +.item-middle-time + color $ui-inactive-text-color + display inline-block + +.item-middle-app-meta + display inline-block + float right + opacity 0.8 + +.item-middle-app-meta-label + color $ui-inactive-text-color + opacity 0.6 + padding 0 3px + .item-bottom position relative bottom 0px @@ -124,9 +143,7 @@ $control-height = 30px padding-bottom 2px .item-star - position absolute - right -6px - bottom 23px + position relative width 16px height 16px color alpha($ui-favorite-star-button-color, 60%) @@ -135,9 +152,7 @@ $control-height = 30px border-radius 17px .item-pin - position absolute - right 0px - bottom 2px + position relative width 34px height 34px color #E54D42 @@ -192,7 +207,7 @@ body[data-theme="dark"] .item-bottom-tagList-item transition 0.15s background-color alpha(white, 10%) - color $ui-dark-text-color + color $ui-dark-text-color .item-wrapper border-color alpha($ui-dark-button--active-backgroundColor, 60%) @@ -266,7 +281,7 @@ body[data-theme="solarized-dark"] .item-bottom-tagList-item transition 0.15s background-color alpha($ui-solarized-dark-noteList-backgroundColor, 10%) - color $ui-solarized-dark-text-color + color $ui-solarized-dark-text-color .item-wrapper border-color alpha($ui-solarized-dark-button--active-backgroundColor, 60%) @@ -304,4 +319,4 @@ body[data-theme="solarized-dark"] .item-bottom-tagList-empty color $ui-inactive-text-color - vertical-align middle \ No newline at end of file + vertical-align middle diff --git a/browser/components/NoteItemSimple.js b/browser/components/NoteItemSimple.js index 6b0dd4e0..0d2465e9 100644 --- a/browser/components/NoteItemSimple.js +++ b/browser/components/NoteItemSimple.js @@ -14,11 +14,20 @@ import styles from './NoteItemSimple.styl' * @param {Function} handleNoteContextMenu * @param {Function} handleDragStart */ -const NoteItemSimple = ({ isActive, note, handleNoteClick, handleNoteContextMenu, handleDragStart, pathname }) => ( +const NoteItemSimple = ({ + isActive, + isAllNotesView, + note, + handleNoteClick, + handleNoteContextMenu, + handleDragStart, + pathname, + storage +}) => (
    handleNoteClick(e, `${note.storage}-${note.key}`)} onContextMenu={e => handleNoteContextMenu(e, `${note.storage}-${note.key}`)} @@ -38,6 +47,11 @@ const NoteItemSimple = ({ isActive, note, handleNoteClick, handleNoteContextMenu ? note.title : Empty } + {isAllNotesView &&
    + + {storage.name} + +
    }
    ) diff --git a/browser/components/NoteItemSimple.styl b/browser/components/NoteItemSimple.styl index fdf0c2e3..3097b82c 100644 --- a/browser/components/NoteItemSimple.styl +++ b/browser/components/NoteItemSimple.styl @@ -124,7 +124,7 @@ body[data-theme="dark"] .item-simple-bottom-tagList-item transition 0.15s background-color alpha(white, 10%) - color $ui-dark-text-color + color $ui-dark-text-color .item-simple--active border-color $ui-dark-borderColor @@ -188,7 +188,7 @@ body[data-theme="solarized-dark"] .item-simple-bottom-tagList-item transition 0.15s background-color alpha(white, 10%) - color $ui-solarized-dark-text-color + color $ui-solarized-dark-text-color .item-simple--active border-color $ui-solarized-dark-borderColor @@ -206,4 +206,9 @@ body[data-theme="solarized-dark"] // background-color alpha($ui-dark-button--active-backgroundColor, 60%) color #c0392b .item-simple-bottom-tagList-item - background-color alpha(#fff, 20%) \ No newline at end of file + background-color alpha(#fff, 20%) +.item-simple-right + float right + .item-simple-right-storageName + padding-left 4px + opacity 0.4 diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index cb71ac07..8ec64ec8 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -66,6 +66,7 @@ class NoteList extends React.Component { this.deleteNote = this.deleteNote.bind(this) this.focusNote = this.focusNote.bind(this) this.pinToTop = this.pinToTop.bind(this) + this.getNoteStorage = this.getNoteStorage.bind(this) // TODO: not Selected noteKeys but SelectedNote(for reusing) this.state = { @@ -691,6 +692,10 @@ class NoteList extends React.Component { }) } + getNoteStorage (note) { // note.storage = storage key + return this.props.data.storageMap.toJS()[note.storage] + } + render () { const { location, config } = this.props let { notes } = this.props @@ -745,6 +750,7 @@ class NoteList extends React.Component { return ( ) } @@ -759,12 +766,14 @@ class NoteList extends React.Component { return ( ) }) From e6ae45f13381a08009e17d90c7c8180321e1614e Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Mon, 19 Feb 2018 12:27:04 -0800 Subject: [PATCH 18/34] Added option Empty Trash --- browser/components/SideNavFilter.js | 22 +++++++++---------- browser/main/SideNav/index.js | 34 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/browser/components/SideNavFilter.js b/browser/components/SideNavFilter.js index dba26f92..2f839a84 100644 --- a/browser/components/SideNavFilter.js +++ b/browser/components/SideNavFilter.js @@ -17,7 +17,7 @@ import styles from './SideNavFilter.styl' const SideNavFilter = ({ isFolded, isHomeActive, handleAllNotesButtonClick, isStarredActive, handleStarredButtonClick, isTrashedActive, handleTrashedButtonClick, counterDelNote, - counterTotalNote, counterStarredNote + counterTotalNote, counterStarredNote, handleFilterButtonContextMenu }) => (
    @@ -26,9 +26,9 @@ const SideNavFilter = ({ >
    All Notes @@ -40,9 +40,9 @@ const SideNavFilter = ({ >
    Starred @@ -54,12 +54,12 @@ const SideNavFilter = ({ >
    - Trash + Trash {counterDelNote} diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 9b95ae3e..3ae13e58 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -1,6 +1,9 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' +const { remote } = require('electron') +const { Menu } = remote +import dataApi from 'browser/main/lib/dataApi' import styles from './SideNav.styl' import { openModal } from 'browser/main/lib/modal' import PreferencesModal from '../modals/PreferencesModal' @@ -89,6 +92,7 @@ class SideNav extends React.Component { counterTotalNote={data.noteMap._map.size - data.trashedSet._set.size} counterStarredNote={data.starredSet._set.size} counterDelNote={data.trashedSet._set.size} + handleFilterButtonContextMenu={this.handleFilterButtonContextMenu.bind(this)} /> @@ -139,6 +143,36 @@ class SideNav extends React.Component { router.push(`/tags/${name}`) } + emptyTrash (entries) { + const { dispatch } = this.props + const deletionPromises = entries.map((storageAndNoteKey) => { + const storageKey = storageAndNoteKey.split('-')[0] + const noteKey = storageAndNoteKey.split('-')[1] + return dataApi.deleteNote(storageKey, noteKey) + }) + Promise.all(deletionPromises) + .then((arrayOfStorageAndNoteKeys) => { + arrayOfStorageAndNoteKeys.forEach(({ storageKey, noteKey }) => { + dispatch({ type: 'DELETE_NOTE', storageKey, noteKey }) + }) + }) + .catch((err) => { + console.error('Cannot Delete note: ' + err) + }) + console.log('Trash emptied') + } + + handleFilterButtonContextMenu (event) { + const { location, data } = this.props + if (location.pathname === '/trashed') { + const entries = data.trashedSet.toJS() + const menu = Menu.buildFromTemplate([ + { label: 'Empty Trash', click: () => this.emptyTrash(entries) } + ]) + menu.popup() + } + } + render () { const { data, location, config, dispatch } = this.props From c2afdba6592aa959dadafab897f383e67e118831 Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Mon, 19 Feb 2018 12:41:36 -0800 Subject: [PATCH 19/34] Removed useless url route check --- browser/main/SideNav/index.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 3ae13e58..2120220b 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -163,14 +163,12 @@ class SideNav extends React.Component { } handleFilterButtonContextMenu (event) { - const { location, data } = this.props - if (location.pathname === '/trashed') { - const entries = data.trashedSet.toJS() - const menu = Menu.buildFromTemplate([ - { label: 'Empty Trash', click: () => this.emptyTrash(entries) } - ]) - menu.popup() - } + const { data } = this.props + const entries = data.trashedSet.toJS() + const menu = Menu.buildFromTemplate([ + { label: 'Empty Trash', click: () => this.emptyTrash(entries) } + ]) + menu.popup() } render () { From 74af199afce600db94d47e94bc6395a1f555b3af Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Mon, 19 Feb 2018 13:08:09 -0800 Subject: [PATCH 20/34] Added note counts to tags view in side nav --- browser/components/TagListItem.js | 3 ++- browser/components/TagListItem.styl | 9 ++++++++- browser/main/SideNav/index.js | 23 +++++++++++++---------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/browser/components/TagListItem.js b/browser/components/TagListItem.js index 2625412a..ebef7df4 100644 --- a/browser/components/TagListItem.js +++ b/browser/components/TagListItem.js @@ -12,10 +12,11 @@ import CSSModules from 'browser/lib/CSSModules' * @param {bool} isActive */ -const TagListItem = ({name, handleClickTagListItem, isActive}) => ( +const TagListItem = ({name, handleClickTagListItem, isActive, count}) => ( ) diff --git a/browser/components/TagListItem.styl b/browser/components/TagListItem.styl index cd3a5387..b35b30cf 100644 --- a/browser/components/TagListItem.styl +++ b/browser/components/TagListItem.styl @@ -48,6 +48,9 @@ overflow hidden text-overflow ellipsis +.tagList-item-count + padding 0 3px + body[data-theme="white"] .tagList-item color $ui-inactive-text-color @@ -63,6 +66,8 @@ body[data-theme="white"] color $ui-text-color &:hover background-color alpha($ui-button--active-backgroundColor, 60%) + .tagList-item-count + color $ui-text-color body[data-theme="dark"] .tagList-item @@ -81,4 +86,6 @@ body[data-theme="dark"] background-color alpha($ui-dark-button--active-backgroundColor, 50%) &:hover color $ui-dark-text-color - background-color alpha($ui-dark-button--active-backgroundColor, 50%) \ No newline at end of file + background-color alpha($ui-dark-button--active-backgroundColor, 50%) + .tagList-item-count + color $ui-dark-button--active-color diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 9b95ae3e..c31f39af 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -113,18 +113,21 @@ class SideNav extends React.Component { tagListComponent () { const { data, location } = this.props - const tagList = data.tagNoteMap.map((tag, key) => { - return key + const tagList = data.tagNoteMap.map((tag, name) => { + return { name, size: tag.size } }) return ( - tagList.map(tag => ( - - )) + tagList.map(tag => { + return ( + + ) + }) ) } From c82eba05d19c522bafd965fdd5fd7d833be8aa8d Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Fri, 9 Feb 2018 03:19:04 +0100 Subject: [PATCH 21/34] Sync Split Editor scroll position --- browser/components/CodeEditor.js | 9 +++++ browser/components/MarkdownPreview.js | 9 +++++ browser/components/MarkdownSplitEditor.js | 44 +++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 00dc1f6d..20ad3185 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -47,6 +47,7 @@ export default class CodeEditor extends React.Component { this.loadStyleHandler = (e) => { this.editor.refresh() } + this.scrollHandler = _.debounce(this.handleScroll.bind(this), 100, {leading: false, trailing: true}) } componentDidMount () { @@ -107,6 +108,7 @@ export default class CodeEditor extends React.Component { this.editor.on('blur', this.blurHandler) this.editor.on('change', this.changeHandler) this.editor.on('paste', this.pasteHandler) + this.editor.on('scroll', this.scrollHandler) const editorTheme = document.getElementById('editorTheme') editorTheme.addEventListener('load', this.loadStyleHandler) @@ -126,6 +128,7 @@ export default class CodeEditor extends React.Component { this.editor.off('blur', this.blurHandler) this.editor.off('change', this.changeHandler) this.editor.off('paste', this.pasteHandler) + this.editor.off('scroll', this.scrollHandler) const editorTheme = document.getElementById('editorTheme') editorTheme.removeEventListener('load', this.loadStyleHandler) } @@ -254,6 +257,12 @@ export default class CodeEditor extends React.Component { } } + handleScroll (e) { + if (this.props.onScroll) { + this.props.onScroll(e) + } + } + render () { const { className, fontSize } = this.props let fontFamily = this.props.fontFamily diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index 1d0f7513..c5b0355d 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -121,6 +121,7 @@ export default class MarkdownPreview extends React.Component { this.mouseDownHandler = (e) => this.handleMouseDown(e) this.mouseUpHandler = (e) => this.handleMouseUp(e) this.DoubleClickHandler = (e) => this.handleDoubleClick(e) + this.scrollHandler = _.debounce(this.handleScroll.bind(this), 100, {leading: false, trailing: true}) this.anchorClickHandler = (e) => this.handlePreviewAnchorClick(e) this.checkboxClickHandler = (e) => this.handleCheckboxClick(e) this.saveAsTextHandler = () => this.handleSaveAsText() @@ -151,6 +152,12 @@ export default class MarkdownPreview extends React.Component { this.props.onCheckboxClick(e) } + handleScroll (e) { + if (this.props.onScroll) { + this.props.onScroll(e) + } + } + handleContextMenu (e) { this.props.onContextMenu(e) } @@ -279,6 +286,7 @@ export default class MarkdownPreview extends React.Component { this.refs.root.contentWindow.document.addEventListener('dblclick', this.DoubleClickHandler) this.refs.root.contentWindow.document.addEventListener('drop', this.preventImageDroppedHandler) this.refs.root.contentWindow.document.addEventListener('dragover', this.preventImageDroppedHandler) + this.refs.root.contentWindow.document.addEventListener('scroll', this.scrollHandler) eventEmitter.on('export:save-text', this.saveAsTextHandler) eventEmitter.on('export:save-md', this.saveAsMdHandler) eventEmitter.on('export:save-html', this.saveAsHtmlHandler) @@ -292,6 +300,7 @@ export default class MarkdownPreview extends React.Component { this.refs.root.contentWindow.document.removeEventListener('dblclick', this.DoubleClickHandler) this.refs.root.contentWindow.document.removeEventListener('drop', this.preventImageDroppedHandler) this.refs.root.contentWindow.document.removeEventListener('dragover', this.preventImageDroppedHandler) + this.refs.root.contentWindow.document.removeEventListener('scroll', this.scrollHandler) eventEmitter.off('export:save-text', this.saveAsTextHandler) eventEmitter.off('export:save-md', this.saveAsMdHandler) eventEmitter.off('export:save-html', this.saveAsHtmlHandler) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 2cf8e322..deae403a 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -2,6 +2,7 @@ import React from 'react' import CodeEditor from 'browser/components/CodeEditor' import MarkdownPreview from 'browser/components/MarkdownPreview' import { findStorage } from 'browser/lib/findStorage' +import _ from 'lodash' import styles from './MarkdownSplitEditor.styl' import CSSModules from 'browser/lib/CSSModules' @@ -12,6 +13,7 @@ class MarkdownSplitEditor extends React.Component { this.value = props.value this.focus = () => this.refs.code.focus() this.reload = () => this.refs.code.reload() + this.userScroll = true } handleOnChange () { @@ -19,6 +21,46 @@ class MarkdownSplitEditor extends React.Component { this.props.onChange() } + handleScroll (e) { + const previewDoc = _.get(this, 'refs.preview.refs.root.contentWindow.document') + const codeDoc = _.get(this, 'refs.code.editor.doc') + let srcTop, srcHeight, targetTop, targetHeight + + if (this.userScroll) { + if (e.doc) { + srcTop = _.get(e, 'doc.scrollTop') + srcHeight = _.get(e, 'doc.height') + targetTop = _.get(previewDoc, 'body.scrollTop') + targetHeight = _.get(previewDoc, 'body.scrollHeight') + } else { + srcTop = _.get(previewDoc, 'body.scrollTop') + srcHeight = _.get(previewDoc, 'body.scrollHeight') + targetTop = _.get(codeDoc, 'scrollTop') + targetHeight = _.get(codeDoc, 'height') + } + + const factor = srcTop / srcHeight + const previewTarget = targetHeight * factor + const distance = previewTarget - targetTop + + this.userScroll = false + const s = 20 + let i = s + let f, t + const timer = setInterval(() => { + t = (s - i) / s + f = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t + if (e.doc) _.set(previewDoc, 'body.scrollTop', targetTop + f * distance) + else _.get(this, 'refs.code.editor').scrollTo(0, targetTop + f * distance) + if (!i) { + clearInterval(timer) + setTimeout(() => { this.userScroll = true }, 400) + } + i -= 1 + }, 1000 / 60) + } + } + handleCheckboxClick (e) { e.preventDefault() e.stopPropagation() @@ -68,6 +110,7 @@ class MarkdownSplitEditor extends React.Component { scrollPastEnd={config.editor.scrollPastEnd} storageKey={storageKey} onChange={this.handleOnChange.bind(this)} + onScroll={this.handleScroll.bind(this)} /> this.handleCheckboxClick(e)} + onScroll={this.handleScroll.bind(this)} showCopyNotification={config.ui.showCopyNotification} storagePath={storage.path} /> From 051ccad29aebd67e15485b87a74a2bb41b98e030 Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Tue, 20 Feb 2018 22:28:12 +0100 Subject: [PATCH 22/34] Rename variables --- browser/components/MarkdownSplitEditor.js | 31 +++++++++++++---------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index deae403a..ea1a7b1e 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -39,25 +39,28 @@ class MarkdownSplitEditor extends React.Component { targetHeight = _.get(codeDoc, 'height') } - const factor = srcTop / srcHeight - const previewTarget = targetHeight * factor - const distance = previewTarget - targetTop + const distance = (targetHeight * srcTop / srcHeight) - targetTop + const framerate = 1000 / 60 + const frames = 20 + const refractory = frames * framerate this.userScroll = false - const s = 20 - let i = s - let f, t + + let frame = 0 + let scrollPos, time const timer = setInterval(() => { - t = (s - i) / s - f = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t - if (e.doc) _.set(previewDoc, 'body.scrollTop', targetTop + f * distance) - else _.get(this, 'refs.code.editor').scrollTo(0, targetTop + f * distance) - if (!i) { + time = frame / frames + scrollPos = time < 0.5 + ? 2 * time * time // ease in + : -1 + (4 - 2 * time) * time // ease out + if (e.doc) _.set(previewDoc, 'body.scrollTop', targetTop + scrollPos * distance) + else _.get(this, 'refs.code.editor').scrollTo(0, targetTop + scrollPos * distance) + if (frame >= frames) { clearInterval(timer) - setTimeout(() => { this.userScroll = true }, 400) + setTimeout(() => { this.userScroll = true }, refractory) } - i -= 1 - }, 1000 / 60) + frame++ + }, framerate) } } From 3b524f6aba10bb5a49bec9d109ea15798c0bed16 Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Fri, 9 Feb 2018 20:03:07 +0100 Subject: [PATCH 23/34] Highlight global search matches on code editor --- browser/components/CodeEditor.js | 38 ++++++++++++++++++++++++++++++++ browser/main/TopBar/index.js | 12 +++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 00dc1f6d..1e0a1ff5 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -7,6 +7,7 @@ import path from 'path' 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' CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' @@ -47,6 +48,39 @@ export default class CodeEditor extends React.Component { this.loadStyleHandler = (e) => { this.editor.refresh() } + this.searchHandler = (e, msg) => this.handleSearch(msg) + this.searchState = null + } + + handleSearch (msg) { + const cm = this.editor + const component = this + + if (component.searchState) cm.removeOverlay(component.searchState) + if (msg.length < 3) return + + cm.operation(function () { + component.searchState = makeOverlay(msg, 'searching') + cm.addOverlay(component.searchState) + + function makeOverlay (query, style) { + query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'), 'gi') + return { + token: function (stream) { + query.lastIndex = stream.pos + var match = query.exec(stream.string) + if (match && match.index === stream.pos) { + stream.pos += match[0].length || 1 + return style + } else if (match) { + stream.pos = match.index + } else { + stream.skipToEnd() + } + } + } + } + }) } componentDidMount () { @@ -107,6 +141,9 @@ export default class CodeEditor extends React.Component { this.editor.on('blur', this.blurHandler) this.editor.on('change', this.changeHandler) this.editor.on('paste', this.pasteHandler) + eventEmitter.on('top:search', this.searchHandler) + + eventEmitter.emit('code:init') const editorTheme = document.getElementById('editorTheme') editorTheme.addEventListener('load', this.loadStyleHandler) @@ -126,6 +163,7 @@ export default class CodeEditor extends React.Component { this.editor.off('blur', this.blurHandler) this.editor.off('change', this.changeHandler) this.editor.off('paste', this.pasteHandler) + eventEmitter.off('top:search', this.searchHandler) const editorTheme = document.getElementById('editorTheme') editorTheme.removeEventListener('load', this.loadStyleHandler) } diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index 11d31abd..6b4a118e 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -22,14 +22,18 @@ class TopBar extends React.Component { this.focusSearchHandler = () => { this.handleOnSearchFocus() } + + this.codeInitHandler = this.handleCodeInit.bind(this) } componentDidMount () { ee.on('top:focus-search', this.focusSearchHandler) + ee.on('code:init', this.codeInitHandler) } componentWillUnmount () { ee.off('top:focus-search', this.focusSearchHandler) + ee.off('code:init', this.codeInitHandler) } handleKeyDown (e) { @@ -73,14 +77,16 @@ class TopBar extends React.Component { handleSearchChange (e) { const { router } = this.context + const keyword = this.refs.searchInput.value if (this.state.isAlphabet || this.state.isConfirmTranslation) { router.push('/searched') } else { e.preventDefault() } this.setState({ - search: this.refs.searchInput.value + search: keyword }) + ee.emit('top:search', keyword) } handleSearchFocus (e) { @@ -115,6 +121,10 @@ class TopBar extends React.Component { } } + handleCodeInit () { + ee.emit('top:search', this.refs.searchInput.value) + } + render () { const { config, style, location } = this.props return ( From 4f15cc3f0853af0e410722dddcd7793ba793d34d Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Tue, 20 Feb 2018 21:09:43 -0800 Subject: [PATCH 24/34] Fixed ToggleMode button overlapping CSS issue The absolute positioning of the toggle mode button was creating a static overlapping position issue with the top bar. This fix solves that problem by removing the static positioning and coupling the button component with the buttons to the right --- browser/main/Detail/MarkdownNoteDetail.js | 4 +--- browser/main/Detail/MarkdownNoteDetail.styl | 3 ++- browser/main/Detail/ToggleModeButton.styl | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index bb76b8f3..1c1cfcc5 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -362,12 +362,10 @@ class MarkdownNoteDetail extends React.Component { value={this.state.note.tags} onChange={this.handleUpdateTag.bind(this)} /> - - this.handleSwitchMode(e)} editorType={editorType} /> -
    + this.handleSwitchMode(e)} editorType={editorType} /> this.handleStarButtonClick(e)} isActive={note.isStarred} diff --git a/browser/main/Detail/MarkdownNoteDetail.styl b/browser/main/Detail/MarkdownNoteDetail.styl index 652532c7..ad20f0f2 100644 --- a/browser/main/Detail/MarkdownNoteDetail.styl +++ b/browser/main/Detail/MarkdownNoteDetail.styl @@ -7,6 +7,7 @@ background-color $ui-noteDetail-backgroundColor box-shadow none padding 20px 40px + overflow hidden .lock-button padding-bottom 3px @@ -44,7 +45,7 @@ margin 0 30px .body-noteEditor absolute top bottom left right - + body[data-theme="white"] .root box-shadow $note-detail-box-shadow diff --git a/browser/main/Detail/ToggleModeButton.styl b/browser/main/Detail/ToggleModeButton.styl index c69401f8..185a780c 100644 --- a/browser/main/Detail/ToggleModeButton.styl +++ b/browser/main/Detail/ToggleModeButton.styl @@ -5,8 +5,8 @@ width 52px display flex align-items center - position absolute - right 165px + position: relative + top 2px .active background-color #1EC38B width 33px @@ -55,4 +55,4 @@ body[data-theme="solarized-dark"] background-color #002B36 .active background-color #1EC38B - box-shadow 2px 0px 7px #222222 \ No newline at end of file + box-shadow 2px 0px 7px #222222 From 90473203011ce21e11ab9f275164bffeea728376 Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Wed, 21 Feb 2018 19:17:38 +0100 Subject: [PATCH 25/34] Update CodeEditor.js - Forgot curly brace Forgot curly brace when merging master --- browser/components/CodeEditor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 27f983b4..3d27c1c3 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -269,6 +269,7 @@ export default class CodeEditor extends React.Component { if (this.props.onScroll) { this.props.onScroll(e) } + } handlePasteUrl (e, editor, pastedTxt) { e.preventDefault() From deab34abd6bdf28ee427b79fc0466d0a3533f189 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 22 Feb 2018 09:39:56 +0900 Subject: [PATCH 26/34] Fix memory lick --- browser/main/Detail/MarkdownNoteDetail.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index bb76b8f3..7694f1e7 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -68,11 +68,8 @@ class MarkdownNoteDetail extends React.Component { } componentWillUnmount () { - if (this.saveQueue != null) this.saveNow() - } - - componentDidUnmount () { ee.off('topbar:togglelockbutton', this.toggleLockButton) + if (this.saveQueue != null) this.saveNow() } handleUpdateTag () { From c3586372e0e054d1cdfcbba188f42b91a5e62cde Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 22 Feb 2018 10:49:59 +0900 Subject: [PATCH 27/34] Rename variables --- browser/lib/markdown.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index 003dd58d..ce511c0b 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -9,11 +9,11 @@ import {lastFindInArray} from './utils' const katex = window.katex const config = ConfigManager.get() -function createGutter (str, fc) { - if (Number.isNaN(fc)) fc = 1 - const lc = (str.match(/\n/g) || []).length + fc - 1 +function createGutter (str, firstLineNumber) { + if (Number.isNaN(firstLineNumber)) firstLineNumber = 1 + const lastLineNumber = (str.match(/\n/g) || []).length + firstLineNumber - 1 const lines = [] - for (let i = fc; i <= lc; i++) { + for (let i = firstLineNumber; i <= lastLineNumber; i++) { lines.push('' + i + '') } return '' + lines.join('') + '' From e4fbdb35a3226e3b9f23c9a743cbeb80463849d7 Mon Sep 17 00:00:00 2001 From: Junyoung Choi Date: Thu, 22 Feb 2018 10:54:12 +0900 Subject: [PATCH 28/34] Rename a variable name again --- browser/lib/markdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index ce511c0b..d0801a1b 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -30,7 +30,7 @@ var md = markdownit({ const langInfo = lang.split(delimiter) const langType = langInfo[0] const fileName = langInfo[1] || '' - const fc = parseInt(langInfo[2], 10) + const firstLineNumber = parseInt(langInfo[2], 10) if (langType === 'flowchart') { return `
    ${str}
    ` @@ -40,7 +40,7 @@ var md = markdownit({ } return '
    ' +
           '' + fileName + '' +
    -      createGutter(str, fc) +
    +      createGutter(str, firstLineNumber) +
           '' +
           str +
           '
    ' From 2a26e8a010dc1c505cf0562c06ceeb51b944b8bc Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Thu, 22 Feb 2018 17:31:31 -0800 Subject: [PATCH 29/34] Added folder labels to note items when viewing a specific storage --- browser/components/NoteItem.js | 10 ++++++---- browser/main/NoteList/index.js | 26 ++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/browser/components/NoteItem.js b/browser/components/NoteItem.js index e55db70a..7abb86b9 100644 --- a/browser/components/NoteItem.js +++ b/browser/components/NoteItem.js @@ -48,14 +48,15 @@ const TagElementList = (tags) => { */ const NoteItem = ({ isActive, - isAllNotesView, note, dateDisplay, handleNoteClick, handleNoteContextMenu, handleDragStart, pathname, - storage + storageName, + folderName, + viewType }) => (
    Empty }
    - {isAllNotesView &&
    + {['ALL', 'STORAGE'].includes(viewType) &&
    {dateDisplay}
    - {storage.name} + {viewType === 'ALL' && storageName} + {viewType === 'STORAGE' && folderName}
    diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 8ec64ec8..6ba45faa 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -67,6 +67,8 @@ class NoteList extends React.Component { this.focusNote = this.focusNote.bind(this) this.pinToTop = this.pinToTop.bind(this) this.getNoteStorage = this.getNoteStorage.bind(this) + this.getNoteFolder = this.getNoteFolder.bind(this) + this.getViewType = this.getViewType.bind(this) // TODO: not Selected noteKeys but SelectedNote(for reusing) this.state = { @@ -696,6 +698,20 @@ class NoteList extends React.Component { return this.props.data.storageMap.toJS()[note.storage] } + getNoteFolder (note) { // note.folder = folder key + return _.find(this.getNoteStorage(note).folders, ({ key }) => key === note.folder) + } + + getViewType () { + const { pathname } = this.props.location + const folder = /\/folders\/[a-zA-Z0-9]+/.test(pathname) + const storage = /\/storages\/[a-zA-Z0-9]+/.test(pathname) && !folder + const allNotes = pathname === '/home' + if (allNotes) return 'ALL' + if (folder) return 'FOLDER' + if (storage) return 'STORAGE' + } + render () { const { location, config } = this.props let { notes } = this.props @@ -750,7 +766,6 @@ class NoteList extends React.Component { return ( ) } @@ -766,14 +783,15 @@ class NoteList extends React.Component { return ( ) }) From 77542597f5d5c7f6460e1efd9c7cc2144a190ed6 Mon Sep 17 00:00:00 2001 From: Nikolay Lopin Date: Fri, 23 Feb 2018 10:26:48 +0300 Subject: [PATCH 30/34] onClick listener fix --- browser/main/Detail/RestoreButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/Detail/RestoreButton.js b/browser/main/Detail/RestoreButton.js index cb1ccec2..0f9c992e 100644 --- a/browser/main/Detail/RestoreButton.js +++ b/browser/main/Detail/RestoreButton.js @@ -7,7 +7,7 @@ const RestoreButton = ({ onClick }) => (