From b4a7b547f0f9fd1476bae2729a60c1bc44300be6 Mon Sep 17 00:00:00 2001 From: Paul Rosset Date: Fri, 1 Dec 2017 15:23:23 +0000 Subject: [PATCH 01/50] Add notification when not saved --- .../modals/PreferencesModal/ConfigTab.styl | 4 +-- .../main/modals/PreferencesModal/HotkeyTab.js | 17 +++++++++++- .../PreferencesModal/PreferencesModal.styl | 8 ++++++ browser/main/modals/PreferencesModal/UiTab.js | 26 ++++++++++++++++--- browser/main/modals/PreferencesModal/index.js | 14 +++++++--- 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/browser/main/modals/PreferencesModal/ConfigTab.styl b/browser/main/modals/PreferencesModal/ConfigTab.styl index f9115c62..a488c4b3 100644 --- a/browser/main/modals/PreferencesModal/ConfigTab.styl +++ b/browser/main/modals/PreferencesModal/ConfigTab.styl @@ -76,8 +76,8 @@ color #1EC38B .error color red - - + .warning + color #FFA500 .group-control-leftButton colorDefaultButton() diff --git a/browser/main/modals/PreferencesModal/HotkeyTab.js b/browser/main/modals/PreferencesModal/HotkeyTab.js index 9a15e79f..cfd45d96 100644 --- a/browser/main/modals/PreferencesModal/HotkeyTab.js +++ b/browser/main/modals/PreferencesModal/HotkeyTab.js @@ -32,6 +32,10 @@ class HotkeyTab extends React.Component { message: err.message != null ? err.message : 'Error occurs!' }}) } + if (JSON.parse(localStorage.getItem('config'))) { + const {hotkey} = JSON.parse(localStorage.getItem('config')) + this.hotkey = hotkey + } ipc.addListener('APP_SETTING_DONE', this.handleSettingDone) ipc.addListener('APP_SETTING_ERROR', this.handleSettingError) } @@ -53,6 +57,7 @@ class HotkeyTab extends React.Component { config: newConfig }) this.clearMessage() + this.props.haveToSave(null) } handleHintToggleButtonClick (e) { @@ -70,6 +75,15 @@ class HotkeyTab extends React.Component { this.setState({ config }) + if (JSON.stringify(this.hotkey) === JSON.stringify(config.hotkey)) { + this.props.haveToSave(null) + } else { + this.props.haveToSave({ + tab: "Hotkey", + type: 'warning', + message: 'You have to save!' + }) + } } clearMessage () { @@ -161,7 +175,8 @@ class HotkeyTab extends React.Component { } HotkeyTab.propTypes = { - dispatch: PropTypes.func + dispatch: PropTypes.func, + haveToSave: PropTypes.func } export default CSSModules(HotkeyTab, styles) diff --git a/browser/main/modals/PreferencesModal/PreferencesModal.styl b/browser/main/modals/PreferencesModal/PreferencesModal.styl index b0d89312..6c1ad2d9 100644 --- a/browser/main/modals/PreferencesModal/PreferencesModal.styl +++ b/browser/main/modals/PreferencesModal/PreferencesModal.styl @@ -42,6 +42,10 @@ top-bar--height = 50px background-color transparent color $ui-text-color font-size 16px + .saving--warning + color #FFA500 + font-size 10px + margin-top 3px .nav-button--active @extend .nav-button @@ -49,6 +53,10 @@ top-bar--height = 50px background-color $ui-button--active-backgroundColor &:hover color $ui-text-color + .saving--warning + color #FFA500 + font-size 10px + margin-top 3px .nav-button-icon display block diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index eebb2e0c..79314608 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -20,7 +20,8 @@ class UiTab extends React.Component { super(props) this.state = { config: props.config, - codemirrorTheme: props.config.editor.theme + codemirrorTheme: props.config.editor.theme, + haveToSave: null } } @@ -37,12 +38,16 @@ class UiTab extends React.Component { message: err.message != null ? err.message : 'Error occurs!' }}) } + if (JSON.parse(localStorage.getItem('config'))) { + const {ui, editor, preview} = JSON.parse(localStorage.getItem('config')) + this.currentConfig = {ui, editor, preview} + } ipc.addListener('APP_SETTING_DONE', this.handleSettingDone) ipc.addListener('APP_SETTING_ERROR', this.handleSettingError) } componentWillMount () { - CodeMirror.autoLoadMode(ReactCodeMirror, 'javascript') + CodeMirror.autoLoadMode(ReactCodeMirror, 'javascript') } componentWillUnmount () { @@ -92,7 +97,18 @@ class UiTab extends React.Component { checkHighLight.setAttribute('href', `../node_modules/codemirror/theme/${newCodemirrorTheme.split(' ')[0]}.css`) } - this.setState({ config: newConfig, codemirrorTheme: newCodemirrorTheme }) + this.setState({ config: newConfig, codemirrorTheme: newCodemirrorTheme }, + () => { + if (JSON.stringify(this.currentConfig) === JSON.stringify(this.state.config)) { + this.props.haveToSave(null) + } else { + this.props.haveToSave({ + tab: "UI", + type: 'warning', + message: 'You have to save!' + }) + } + }) } handleSaveUIClick (e) { @@ -109,6 +125,7 @@ class UiTab extends React.Component { config: newConfig }) this.clearMessage() + this.props.haveToSave(null) } clearMessage () { @@ -346,7 +363,8 @@ UiTab.propTypes = { user: PropTypes.shape({ name: PropTypes.string }), - dispatch: PropTypes.func + dispatch: PropTypes.func, + haveToSave: PropTypes.func } export default CSSModules(UiTab, styles) diff --git a/browser/main/modals/PreferencesModal/index.js b/browser/main/modals/PreferencesModal/index.js index 2fff0364..f478f913 100644 --- a/browser/main/modals/PreferencesModal/index.js +++ b/browser/main/modals/PreferencesModal/index.js @@ -17,7 +17,9 @@ class Preferences extends React.Component { super(props) this.state = { - currentTab: 'STORAGES' + currentTab: 'STORAGES', + UI: null, + Hotkey: null } } @@ -58,6 +60,7 @@ class Preferences extends React.Component { this.setState({Hotkey: msg})} /> ) case 'UI': @@ -65,6 +68,7 @@ class Preferences extends React.Component { this.setState({UI: msg})} /> ) case 'CROWDFUNDING': @@ -99,14 +103,15 @@ class Preferences extends React.Component { const tabs = [ {target: 'STORAGES', label: 'Storages'}, - {target: 'HOTKEY', label: 'Hotkey'}, - {target: 'UI', label: 'UI'}, + {target: 'HOTKEY', label: 'Hotkey', Hotkey: this.state.Hotkey}, + {target: 'UI', label: 'UI', UI: this.state.UI}, {target: 'INFO', label: 'Community / Info'}, {target: 'CROWDFUNDING', label: 'Crowdfunding'} ] const navButtons = tabs.map((tab) => { const isActive = this.state.currentTab === tab.target + const isOk = typeof tab[tab.label] !== "undefined" && tab[tab.label] !== null return ( ) }) From d1e5781c24276618c13588352964d0b440060460 Mon Sep 17 00:00:00 2001 From: Paul Rosset Date: Fri, 1 Dec 2017 19:03:04 +0000 Subject: [PATCH 02/50] Correction UiTab --- browser/main/StatusBar/index.js | 2 +- .../main/modals/PreferencesModal/HotkeyTab.js | 6 +++--- browser/main/modals/PreferencesModal/UiTab.js | 16 +++++++--------- browser/main/modals/PreferencesModal/index.js | 6 ++---- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/browser/main/StatusBar/index.js b/browser/main/StatusBar/index.js index 2106a230..49c1b40c 100644 --- a/browser/main/StatusBar/index.js +++ b/browser/main/StatusBar/index.js @@ -63,7 +63,7 @@ class StatusBar extends React.Component { {status.updateReady ? + : null } diff --git a/browser/main/modals/PreferencesModal/HotkeyTab.js b/browser/main/modals/PreferencesModal/HotkeyTab.js index cfd45d96..586faf04 100644 --- a/browser/main/modals/PreferencesModal/HotkeyTab.js +++ b/browser/main/modals/PreferencesModal/HotkeyTab.js @@ -79,9 +79,9 @@ class HotkeyTab extends React.Component { this.props.haveToSave(null) } else { this.props.haveToSave({ - tab: "Hotkey", - type: 'warning', - message: 'You have to save!' + tab: 'Hotkey', + type: 'warning', + message: 'You have to save!' }) } } diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 79314608..dcb9f6bc 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -38,16 +38,12 @@ class UiTab extends React.Component { message: err.message != null ? err.message : 'Error occurs!' }}) } - if (JSON.parse(localStorage.getItem('config'))) { - const {ui, editor, preview} = JSON.parse(localStorage.getItem('config')) - this.currentConfig = {ui, editor, preview} - } ipc.addListener('APP_SETTING_DONE', this.handleSettingDone) ipc.addListener('APP_SETTING_ERROR', this.handleSettingError) } componentWillMount () { - CodeMirror.autoLoadMode(ReactCodeMirror, 'javascript') + CodeMirror.autoLoadMode(ReactCodeMirror, 'javascript') } componentWillUnmount () { @@ -96,18 +92,20 @@ class UiTab extends React.Component { if (newCodemirrorTheme !== codemirrorTheme) { checkHighLight.setAttribute('href', `../node_modules/codemirror/theme/${newCodemirrorTheme.split(' ')[0]}.css`) } - - this.setState({ config: newConfig, codemirrorTheme: newCodemirrorTheme }, - () => { + this.setState({ config: newConfig, codemirrorTheme: newCodemirrorTheme }, () => { + if (JSON.parse(localStorage.getItem('config'))) { + const {ui, editor, preview} = JSON.parse(localStorage.getItem('config')) + this.currentConfig = {ui, editor, preview} if (JSON.stringify(this.currentConfig) === JSON.stringify(this.state.config)) { this.props.haveToSave(null) } else { this.props.haveToSave({ - tab: "UI", + tab: 'UI', type: 'warning', message: 'You have to save!' }) } + } }) } diff --git a/browser/main/modals/PreferencesModal/index.js b/browser/main/modals/PreferencesModal/index.js index f478f913..adf1e0d4 100644 --- a/browser/main/modals/PreferencesModal/index.js +++ b/browser/main/modals/PreferencesModal/index.js @@ -111,7 +111,7 @@ class Preferences extends React.Component { const navButtons = tabs.map((tab) => { const isActive = this.state.currentTab === tab.target - const isOk = typeof tab[tab.label] !== "undefined" && tab[tab.label] !== null + const isOk = typeof tab[tab.label] !== 'undefined' && tab[tab.label] !== null return ( ) }) From f4fd131100bac3561e044a9e4fe1904f29354e7d Mon Sep 17 00:00:00 2001 From: Paul Rosset Date: Tue, 5 Dec 2017 18:16:42 +0000 Subject: [PATCH 03/50] Requested Review --- .../main/modals/PreferencesModal/HotkeyTab.js | 11 +++----- .../PreferencesModal/PreferencesModal.styl | 8 ++---- browser/main/modals/PreferencesModal/Tab.styl | 5 ++++ browser/main/modals/PreferencesModal/UiTab.js | 27 +++++++++---------- browser/main/modals/PreferencesModal/index.js | 22 +++++++++------ 5 files changed, 37 insertions(+), 36 deletions(-) diff --git a/browser/main/modals/PreferencesModal/HotkeyTab.js b/browser/main/modals/PreferencesModal/HotkeyTab.js index 586faf04..93d2993c 100644 --- a/browser/main/modals/PreferencesModal/HotkeyTab.js +++ b/browser/main/modals/PreferencesModal/HotkeyTab.js @@ -32,10 +32,7 @@ class HotkeyTab extends React.Component { message: err.message != null ? err.message : 'Error occurs!' }}) } - if (JSON.parse(localStorage.getItem('config'))) { - const {hotkey} = JSON.parse(localStorage.getItem('config')) - this.hotkey = hotkey - } + this.oldHotkey = this.state.config.hotkey ipc.addListener('APP_SETTING_DONE', this.handleSettingDone) ipc.addListener('APP_SETTING_ERROR', this.handleSettingError) } @@ -57,7 +54,7 @@ class HotkeyTab extends React.Component { config: newConfig }) this.clearMessage() - this.props.haveToSave(null) + this.props.haveToSave() } handleHintToggleButtonClick (e) { @@ -75,8 +72,8 @@ class HotkeyTab extends React.Component { this.setState({ config }) - if (JSON.stringify(this.hotkey) === JSON.stringify(config.hotkey)) { - this.props.haveToSave(null) + if (JSON.stringify(this.oldHotkey) === JSON.stringify(config.hotkey)) { + this.props.haveToSave() } else { this.props.haveToSave({ tab: 'Hotkey', diff --git a/browser/main/modals/PreferencesModal/PreferencesModal.styl b/browser/main/modals/PreferencesModal/PreferencesModal.styl index 6c1ad2d9..697fb50d 100644 --- a/browser/main/modals/PreferencesModal/PreferencesModal.styl +++ b/browser/main/modals/PreferencesModal/PreferencesModal.styl @@ -43,9 +43,7 @@ top-bar--height = 50px color $ui-text-color font-size 16px .saving--warning - color #FFA500 - font-size 10px - margin-top 3px + haveToSave() .nav-button--active @extend .nav-button @@ -54,9 +52,7 @@ top-bar--height = 50px &:hover color $ui-text-color .saving--warning - color #FFA500 - font-size 10px - margin-top 3px + haveToSave() .nav-button-icon display block diff --git a/browser/main/modals/PreferencesModal/Tab.styl b/browser/main/modals/PreferencesModal/Tab.styl index e5fc48da..a316f3eb 100644 --- a/browser/main/modals/PreferencesModal/Tab.styl +++ b/browser/main/modals/PreferencesModal/Tab.styl @@ -20,3 +20,8 @@ $tab--dark-text-color = #E5E5E5 body[data-theme="dark"] .header color $tab--dark-text-color + +haveToSave() + color #FFA500 + font-size 10px + margin-top 3px \ No newline at end of file diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index dcb9f6bc..73ec68da 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -20,8 +20,7 @@ class UiTab extends React.Component { super(props) this.state = { config: props.config, - codemirrorTheme: props.config.editor.theme, - haveToSave: null + codemirrorTheme: props.config.editor.theme } } @@ -93,18 +92,16 @@ class UiTab extends React.Component { checkHighLight.setAttribute('href', `../node_modules/codemirror/theme/${newCodemirrorTheme.split(' ')[0]}.css`) } this.setState({ config: newConfig, codemirrorTheme: newCodemirrorTheme }, () => { - if (JSON.parse(localStorage.getItem('config'))) { - const {ui, editor, preview} = JSON.parse(localStorage.getItem('config')) - this.currentConfig = {ui, editor, preview} - if (JSON.stringify(this.currentConfig) === JSON.stringify(this.state.config)) { - this.props.haveToSave(null) - } else { - this.props.haveToSave({ - tab: 'UI', - type: 'warning', - message: 'You have to save!' - }) - } + const {ui, editor, preview} = this.props.config + this.currentConfig = {ui, editor, preview} + if (JSON.stringify(this.currentConfig) === JSON.stringify(this.state.config)) { + this.props.haveToSave() + } else { + this.props.haveToSave({ + tab: 'UI', + type: 'warning', + message: 'You have to save!' + }) } }) } @@ -123,7 +120,7 @@ class UiTab extends React.Component { config: newConfig }) this.clearMessage() - this.props.haveToSave(null) + this.props.haveToSave() } clearMessage () { diff --git a/browser/main/modals/PreferencesModal/index.js b/browser/main/modals/PreferencesModal/index.js index adf1e0d4..bf330e78 100644 --- a/browser/main/modals/PreferencesModal/index.js +++ b/browser/main/modals/PreferencesModal/index.js @@ -18,8 +18,8 @@ class Preferences extends React.Component { this.state = { currentTab: 'STORAGES', - UI: null, - Hotkey: null + UIAlert: '', + HotkeyAlert: '' } } @@ -60,7 +60,7 @@ class Preferences extends React.Component { this.setState({Hotkey: msg})} + haveToSave={msg => this.setState({HotkeyAlert: msg})} /> ) case 'UI': @@ -68,7 +68,7 @@ class Preferences extends React.Component { this.setState({UI: msg})} + haveToSave={msg => this.setState({UIAlert: msg})} /> ) case 'CROWDFUNDING': @@ -97,21 +97,27 @@ class Preferences extends React.Component { const node = ReactDOM.findDOMNode(this.refs.content) return node.getBoundingClientRect() } + + haveToSaveNotif (tab) { + return ( +

{tab[tab.label].message}

+ ) + } render () { const content = this.renderContent() const tabs = [ {target: 'STORAGES', label: 'Storages'}, - {target: 'HOTKEY', label: 'Hotkey', Hotkey: this.state.Hotkey}, - {target: 'UI', label: 'UI', UI: this.state.UI}, + {target: 'HOTKEY', label: 'Hotkey', Hotkey: this.state.HotkeyAlert}, + {target: 'UI', label: 'UI', UI: this.state.UIAlert}, {target: 'INFO', label: 'Community / Info'}, {target: 'CROWDFUNDING', label: 'Crowdfunding'} ] const navButtons = tabs.map((tab) => { const isActive = this.state.currentTab === tab.target - const isOk = typeof tab[tab.label] !== 'undefined' && tab[tab.label] !== null + const isUiHotkeyTab = _.isObject(tab[tab.label]) && tab.label === tab[tab.label].tab return ( ) }) From 83910b55d2a3784967188a3bc2be342fa49d709c Mon Sep 17 00:00:00 2001 From: Paul Rosset Date: Tue, 5 Dec 2017 18:18:12 +0000 Subject: [PATCH 04/50] Correction eslint code format --- browser/main/modals/PreferencesModal/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/modals/PreferencesModal/index.js b/browser/main/modals/PreferencesModal/index.js index bf330e78..d7542821 100644 --- a/browser/main/modals/PreferencesModal/index.js +++ b/browser/main/modals/PreferencesModal/index.js @@ -97,7 +97,7 @@ class Preferences extends React.Component { const node = ReactDOM.findDOMNode(this.refs.content) return node.getBoundingClientRect() } - + haveToSaveNotif (tab) { return (

{tab[tab.label].message}

From 125a49340071103e5a2a8ad1270bd536189ec002 Mon Sep 17 00:00:00 2001 From: Paul Rosset Date: Tue, 5 Dec 2017 18:24:30 +0000 Subject: [PATCH 05/50] Change name for state --- browser/main/modals/PreferencesModal/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/main/modals/PreferencesModal/index.js b/browser/main/modals/PreferencesModal/index.js index d7542821..882428b5 100644 --- a/browser/main/modals/PreferencesModal/index.js +++ b/browser/main/modals/PreferencesModal/index.js @@ -60,7 +60,7 @@ class Preferences extends React.Component { this.setState({HotkeyAlert: msg})} + haveToSave={alert => this.setState({HotkeyAlert: alert})} /> ) case 'UI': @@ -68,7 +68,7 @@ class Preferences extends React.Component { this.setState({UIAlert: msg})} + haveToSave={alert => this.setState({UIAlert: alert})} /> ) case 'CROWDFUNDING': From cb59458c79d7409effb235f8307c10938ce308c4 Mon Sep 17 00:00:00 2001 From: Paul Rosset Date: Tue, 5 Dec 2017 18:28:59 +0000 Subject: [PATCH 06/50] refactor --- browser/main/modals/PreferencesModal/UiTab.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 73ec68da..9f9ee73f 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -7,11 +7,10 @@ import store from 'browser/main/store' import consts from 'browser/lib/consts' import ReactCodeMirror from 'react-codemirror' import CodeMirror from 'codemirror' +import _ from 'lodash' const OSX = global.process.platform === 'darwin' -import _ from 'lodash' - const electron = require('electron') const ipc = electron.ipcRenderer From 6a9d4ae0fdb7425ab7ef0b97f886054a298b2ba4 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Fri, 8 Dec 2017 11:43:12 +0100 Subject: [PATCH 07/50] first attempt to export html --- browser/components/MarkdownPreview.js | 15 +++++++++++++-- browser/main/Detail/InfoPanel.js | 14 ++++++++++---- browser/main/Detail/InfoPanelTrashed.js | 16 +++++++++++----- browser/main/Detail/MarkdownNoteDetail.js | 6 ++++++ browser/main/Detail/SnippetNoteDetail.js | 1 + lib/main-menu.js | 7 +++++++ 6 files changed, 48 insertions(+), 11 deletions(-) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index a3e7bb93..a69e11fb 100644 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -118,6 +118,7 @@ export default class MarkdownPreview extends React.Component { this.checkboxClickHandler = (e) => this.handleCheckboxClick(e) this.saveAsTextHandler = () => this.handleSaveAsText() this.saveAsMdHandler = () => this.handleSaveAsMd() + this.saveAsHtmlHandler = () => this.handleSaveAsHtml() this.printHandler = () => this.handlePrint() this.linkClickHandler = this.handlelinkClick.bind(this) @@ -173,21 +174,29 @@ export default class MarkdownPreview extends React.Component { this.exportAsDocument('md') } + handleSaveAsHtml () { + this.exportAsDocument('html', function formatHtml (value) { + return this.refs.root.contentWindow.document.documentElement.outerHTML + }) + } + handlePrint () { this.refs.root.contentWindow.print() } - exportAsDocument (fileType) { + exportAsDocument (fileType, formatter) { const options = { filters: [ { name: 'Documents', extensions: [fileType] } ], properties: ['openFile', 'createDirectory'] } + var value = formatter ? formatter.call(this, this.props.value) : this.props.value + dialog.showSaveDialog(remote.getCurrentWindow(), options, (filename) => { if (filename) { - fs.writeFile(filename, this.props.value, (err) => { + fs.writeFile(filename, value, (err) => { if (err) throw err }) } @@ -223,6 +232,7 @@ export default class MarkdownPreview extends React.Component { this.refs.root.contentWindow.document.addEventListener('dragover', this.preventImageDroppedHandler) eventEmitter.on('export:save-text', this.saveAsTextHandler) eventEmitter.on('export:save-md', this.saveAsMdHandler) + eventEmitter.on('export:save-html', this.saveAsHtmlHandler) eventEmitter.on('print', this.printHandler) } @@ -234,6 +244,7 @@ export default class MarkdownPreview extends React.Component { this.refs.root.contentWindow.document.removeEventListener('dragover', this.preventImageDroppedHandler) eventEmitter.off('export:save-text', this.saveAsTextHandler) eventEmitter.off('export:save-md', this.saveAsMdHandler) + eventEmitter.off('export:save-html', this.saveAsHtmlHandler) eventEmitter.off('print', this.printHandler) } diff --git a/browser/main/Detail/InfoPanel.js b/browser/main/Detail/InfoPanel.js index e718fbf3..a5202e71 100644 --- a/browser/main/Detail/InfoPanel.js +++ b/browser/main/Detail/InfoPanel.js @@ -4,7 +4,7 @@ import CSSModules from 'browser/lib/CSSModules' import styles from './InfoPanel.styl' const InfoPanel = ({ - storageName, folderName, noteLink, updatedAt, createdAt, exportAsMd, exportAsTxt, wordCount, letterCount, type, print + storageName, folderName, noteLink, updatedAt, createdAt, exportAsMd, exportAsTxt, exportAsHtml, wordCount, letterCount, type, print }) => (
@@ -57,17 +57,22 @@ const InfoPanel = ({
+ +
@@ -82,6 +87,7 @@ InfoPanel.propTypes = { createdAt: PropTypes.string.isRequired, exportAsMd: PropTypes.func.isRequired, exportAsTxt: PropTypes.func.isRequired, + exportAsHtml: PropTypes.func.isRequired, wordCount: PropTypes.number, letterCount: PropTypes.number, type: PropTypes.string.isRequired, diff --git a/browser/main/Detail/InfoPanelTrashed.js b/browser/main/Detail/InfoPanelTrashed.js index 77ecea22..6e86b884 100644 --- a/browser/main/Detail/InfoPanelTrashed.js +++ b/browser/main/Detail/InfoPanelTrashed.js @@ -4,7 +4,7 @@ import CSSModules from 'browser/lib/CSSModules' import styles from './InfoPanel.styl' const InfoPanelTrashed = ({ - storageName, folderName, updatedAt, createdAt, exportAsMd, exportAsTxt + storageName, folderName, updatedAt, createdAt, exportAsMd, exportAsTxt, exportAsHtml }) => (
@@ -31,17 +31,22 @@ const InfoPanelTrashed = ({
+ +
@@ -54,7 +59,8 @@ InfoPanelTrashed.propTypes = { updatedAt: PropTypes.string.isRequired, createdAt: PropTypes.string.isRequired, exportAsMd: PropTypes.func.isRequired, - exportAsTxt: PropTypes.func.isRequired + exportAsTxt: PropTypes.func.isRequired, + exportAsHtml: PropTypes.func.isRequired } export default CSSModules(InfoPanelTrashed, styles) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index f4c805c1..5dd0d765 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -170,6 +170,10 @@ class MarkdownNoteDetail extends React.Component { ee.emit('export:save-text') } + exportAsHtml () { + ee.emit('export:save-html') + } + handleTrashButtonClick (e) { const { note } = this.state const { isTrashed } = note @@ -296,6 +300,7 @@ class MarkdownNoteDetail extends React.Component { folderName={currentOption.folder.name} updatedAt={formatDate(note.updatedAt)} createdAt={formatDate(note.createdAt)} + exportAsHtml={this.exportAsHtml} exportAsMd={this.exportAsMd} exportAsTxt={this.exportAsTxt} /> @@ -363,6 +368,7 @@ class MarkdownNoteDetail extends React.Component { createdAt={formatDate(note.createdAt)} exportAsMd={this.exportAsMd} exportAsTxt={this.exportAsTxt} + exportAsHtml={this.exportAsHtml} wordCount={note.content.split(' ').length} letterCount={note.content.replace(/\r?\n/g, '').length} type={note.type} diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index 51f14fae..5a1b7f51 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -579,6 +579,7 @@ class SnippetNoteDetail extends React.Component { createdAt={formatDate(note.createdAt)} exportAsMd={this.showWarning} exportAsTxt={this.showWarning} + exportAsHtml={this.showWarning} />
diff --git a/lib/main-menu.js b/lib/main-menu.js index 3adc323e..19ccc965 100644 --- a/lib/main-menu.js +++ b/lib/main-menu.js @@ -106,6 +106,13 @@ const file = { mainWindow.webContents.send('list:isMarkdownNote') mainWindow.webContents.send('export:save-md') } + }, + { + label: 'Html (.html)', + click () { + mainWindow.webContents.send('list:isMarkdownNote') + mainWindow.webContents.send('export:save-html') + } } ] }, From 959b75bdddfcab3838641e503c40e9e9732d0a4a Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Mon, 20 Nov 2017 17:33:17 +0100 Subject: [PATCH 08/50] export folder as md or text --- .gitignore | 4 +- browser/main/SideNav/StorageItem.js | 94 ++++++++++++++++++------ browser/main/lib/dataApi/exportFolder.js | 64 ++++++++++++++++ browser/main/lib/dataApi/index.js | 1 + browser/main/store.js | 7 ++ tests/dataApi/exportFolder-test.js | 62 ++++++++++++++++ 6 files changed, 206 insertions(+), 26 deletions(-) create mode 100644 browser/main/lib/dataApi/exportFolder.js create mode 100644 tests/dataApi/exportFolder-test.js diff --git a/.gitignore b/.gitignore index 9f75dd1b..ace5316c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,5 @@ node_modules/* /compiled /secret *.log -.vscode -.idea \ No newline at end of file +.idea +.vscode \ No newline at end of file diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index 4379a76c..c955b171 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -10,6 +10,7 @@ import dataApi from 'browser/main/lib/dataApi' import StorageItemChild from 'browser/components/StorageItem' import eventEmitter from 'browser/main/lib/eventEmitter' import _ from 'lodash' +const path = require('path') const { remote } = require('electron') const { Menu, MenuItem, dialog } = remote @@ -24,18 +25,20 @@ class StorageItem extends React.Component { } handleHeaderContextMenu (e) { - const menu = new Menu() - menu.append(new MenuItem({ - label: 'Add Folder', - click: (e) => this.handleAddFolderButtonClick(e) - })) - menu.append(new MenuItem({ - type: 'separator' - })) - menu.append(new MenuItem({ - label: 'Unlink Storage', - click: (e) => this.handleUnlinkStorageClick(e) - })) + let menu = Menu.buildFromTemplate([ + { + label: 'Add Folder', + click: (e) => this.handleAddFolderButtonClick(e) + }, + { + type: 'separator' + }, + { + label: 'Unlink Storage', + click: (e) => this.handleUnlinkStorageClick(e) + } + ]) + menu.popup() } @@ -89,18 +92,36 @@ class StorageItem extends React.Component { } handleFolderButtonContextMenu (e, folder) { - const menu = new Menu() - menu.append(new MenuItem({ - label: 'Rename Folder', - click: (e) => this.handleRenameFolderClick(e, folder) - })) - menu.append(new MenuItem({ - type: 'separator' - })) - menu.append(new MenuItem({ - label: 'Delete Folder', - click: (e) => this.handleFolderDeleteClick(e, folder) - })) + const menu = Menu.buildFromTemplate([ + { + label: 'Rename Folder', + click: (e) => this.handleRenameFolderClick(e, folder) + }, + { + type: 'separator' + }, + { + label: 'Export Folder', + submenu: [ + { + label: 'Export as txt', + click: (e) => this.handleExportFolderClick(e, folder, 'txt') + }, + { + label: 'Export as md', + click: (e) => this.handleExportFolderClick(e, folder, 'md') + } + ] + }, + { + type: 'separator' + }, + { + label: 'Delete Folder', + click: (e) => this.handleFolderDeleteClick(e, folder) + } + ]) + menu.popup() } @@ -112,6 +133,31 @@ class StorageItem extends React.Component { }) } + handleExportFolderClick (e, folder, fileType) { + const options = { + properties: ['openDirectory', 'createDirectory'], + buttonLabel: 'Select directory', + title: 'Select a folder to export the files to', + multiSelections: false + } + dialog.showOpenDialog(remote.getCurrentWindow(), options, + (paths) => { + if (paths && paths.length === 1) { + const { storage, dispatch } = this.props + dataApi + .exportFolder(storage.key, folder.key, fileType, paths[0]) + .then((data) => { + dispatch({ + type: 'EXPORT_FOLDER', + storage: data.storage, + folderKey: data.folderKey, + fileType: data.fileType + }) + }) + } + }) + } + handleFolderDeleteClick (e, folder) { const index = dialog.showMessageBox(remote.getCurrentWindow(), { type: 'warning', diff --git a/browser/main/lib/dataApi/exportFolder.js b/browser/main/lib/dataApi/exportFolder.js new file mode 100644 index 00000000..dead4880 --- /dev/null +++ b/browser/main/lib/dataApi/exportFolder.js @@ -0,0 +1,64 @@ +const { findStorage } = require('browser/lib/findStorage') +const resolveStorageData = require('./resolveStorageData') +const resolveStorageNotes = require('./resolveStorageNotes') +const path = require('path') +const fs = require('fs') + +/** + * @param {String} storageKey + * @param {String} folderKey + * @param {String} fileType + * @param {String} exportDir + * + * @return {Object} + * ``` + * { + * storage: Object, + * folderKey: String, + * fileType: String, + * exportDir: String + * } + * ``` + */ + +function exportFolder (storageKey, folderKey, fileType, exportDir) { + let targetStorage + try { + targetStorage = findStorage(storageKey) + } catch (e) { + return Promise.reject(e) + } + + return resolveStorageData(targetStorage) + .then(function assignNotes (storage) { + return resolveStorageNotes(storage) + .then((notes) => { + return { + storage, + notes + } + }) + }) + .then(function exportNotes (data) { + const { storage, notes } = data + + notes + .filter(note => note.folder === folderKey && note.isTrashed === false && note.type === 'MARKDOWN_NOTE') + .forEach(snippet => { + const notePath = path.join(exportDir, `${snippet.title}.${fileType}`) + console.log(notePath) + fs.writeFile(notePath, snippet.content, (err) => { + if (err) throw err + }) + }) + + return { + storage, + folderKey, + fileType, + exportDir + } + }) +} + +module.exports = exportFolder diff --git a/browser/main/lib/dataApi/index.js b/browser/main/lib/dataApi/index.js index 768dfe32..311ca2f3 100644 --- a/browser/main/lib/dataApi/index.js +++ b/browser/main/lib/dataApi/index.js @@ -7,6 +7,7 @@ const dataApi = { updateFolder: require('./updateFolder'), deleteFolder: require('./deleteFolder'), reorderFolder: require('./reorderFolder'), + exportFolder: require('./exportFolder'), createNote: require('./createNote'), updateNote: require('./updateNote'), deleteNote: require('./deleteNote'), diff --git a/browser/main/store.js b/browser/main/store.js index 647d0ac9..f63a67c7 100644 --- a/browser/main/store.js +++ b/browser/main/store.js @@ -349,6 +349,13 @@ function data (state = defaultDataMap(), action) { state.storageMap = new Map(state.storageMap) state.storageMap.set(action.storage.key, action.storage) return state + case 'EXPORT_FOLDER': + { + state = Object.assign({}, state) + state.storageMap = new Map(state.storageMap) + state.storageMap.set(action.storage.key, action.storage) + } + return state case 'DELETE_FOLDER': { state = Object.assign({}, state) diff --git a/tests/dataApi/exportFolder-test.js b/tests/dataApi/exportFolder-test.js new file mode 100644 index 00000000..ee6fb898 --- /dev/null +++ b/tests/dataApi/exportFolder-test.js @@ -0,0 +1,62 @@ +const test = require('ava') +const exportFolder = require('browser/main/lib/dataApi/exportFolder') +const createNote = require('browser/main/lib/dataApi/createNote') + +global.document = require('jsdom').jsdom('') +global.window = document.defaultView +global.navigator = window.navigator + +const Storage = require('dom-storage') +const localStorage = window.localStorage = global.localStorage = new Storage(null, { strict: true }) +const path = require('path') +const TestDummy = require('../fixtures/TestDummy') +const os = require('os') +const faker = require('faker') +const fs = require('fs') + +const storagePath = path.join(os.tmpdir(), 'test/export-note') + +test.beforeEach((t) => { + t.context.storage = TestDummy.dummyStorage(storagePath) + localStorage.setItem('storages', JSON.stringify([t.context.storage.cache])) +}) + +test.serial('Export a folder', (t) => { + const storageKey = t.context.storage.cache.key + const folderKey = t.context.storage.json.folders[0].key + + const input1 = { + type: 'MARKDOWN_NOTE', + description: '*Some* markdown text', + tags: faker.lorem.words().split(' '), + folder: folderKey + } + input1.title = 'input1' + + const input2 = { + type: 'SNIPPET_NOTE', + description: 'Some normal text', + snippets: [{ + name: faker.system.fileName(), + mode: 'text', + content: faker.lorem.lines() + }], + tags: faker.lorem.words().split(' '), + folder: folderKey + } + input2.title = 'input2' + + return createNote(storageKey, input1) + .then(function () { + return createNote(storageKey, input2) + }) + .then(function () { + return exportFolder(storageKey, folderKey, 'md', storagePath) + }) + .then(function assert () { + let filePath = path.join(storagePath, 'input1.md') + t.true(fs.existsSync(filePath)) + filePath = path.join(storagePath, 'input2.md') + t.false(fs.existsSync(filePath)) + }) +}) From 8c8a0ab46d0799648238d3884a79e855e982871d Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Mon, 20 Nov 2017 19:17:03 +0100 Subject: [PATCH 09/50] forgot to run lint --- browser/main/SideNav/StorageItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index c955b171..62591598 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -95,7 +95,7 @@ class StorageItem extends React.Component { const menu = Menu.buildFromTemplate([ { label: 'Rename Folder', - click: (e) => this.handleRenameFolderClick(e, folder) + click: (e) => this.handleRenameFolderClick(e, folder) }, { type: 'separator' From 5d46adf8fd0fa620cd6a44e7bbe046e414e15880 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Wed, 13 Dec 2017 17:11:43 +0100 Subject: [PATCH 10/50] fixed review comments --- browser/main/SideNav/StorageItem.js | 4 ++-- browser/main/lib/dataApi/exportFolder.js | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index 62591598..2bcbe050 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -10,7 +10,7 @@ import dataApi from 'browser/main/lib/dataApi' import StorageItemChild from 'browser/components/StorageItem' import eventEmitter from 'browser/main/lib/eventEmitter' import _ from 'lodash' -const path = require('path') +import * as path from 'path' const { remote } = require('electron') const { Menu, MenuItem, dialog } = remote @@ -25,7 +25,7 @@ class StorageItem extends React.Component { } handleHeaderContextMenu (e) { - let menu = Menu.buildFromTemplate([ + const menu = Menu.buildFromTemplate([ { label: 'Add Folder', click: (e) => this.handleAddFolderButtonClick(e) diff --git a/browser/main/lib/dataApi/exportFolder.js b/browser/main/lib/dataApi/exportFolder.js index dead4880..75dba959 100644 --- a/browser/main/lib/dataApi/exportFolder.js +++ b/browser/main/lib/dataApi/exportFolder.js @@ -1,8 +1,8 @@ -const { findStorage } = require('browser/lib/findStorage') -const resolveStorageData = require('./resolveStorageData') -const resolveStorageNotes = require('./resolveStorageNotes') -const path = require('path') -const fs = require('fs') +import { findStorage } from 'browser/lib/findStorage' +import resolveStorageData from './resolveStorageData' +import resolveStorageNotes from './resolveStorageNotes' +import * as path from 'path' +import * as fs from 'fs' /** * @param {String} storageKey @@ -46,8 +46,7 @@ function exportFolder (storageKey, folderKey, fileType, exportDir) { .filter(note => note.folder === folderKey && note.isTrashed === false && note.type === 'MARKDOWN_NOTE') .forEach(snippet => { const notePath = path.join(exportDir, `${snippet.title}.${fileType}`) - console.log(notePath) - fs.writeFile(notePath, snippet.content, (err) => { + fs.writeFileSync(notePath, snippet.content, (err) => { if (err) throw err }) }) From 6fba62d062933735980d9f5911819d4880eb226e Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Wed, 13 Dec 2017 17:20:22 +0100 Subject: [PATCH 11/50] fixed review comments --- browser/components/MarkdownPreview.js | 4 ++-- lib/main-menu.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index a69e11fb..5346e0a6 100644 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -175,7 +175,7 @@ export default class MarkdownPreview extends React.Component { } handleSaveAsHtml () { - this.exportAsDocument('html', function formatHtml (value) { + this.exportAsDocument('html', (value) => { return this.refs.root.contentWindow.document.documentElement.outerHTML }) } @@ -191,7 +191,7 @@ export default class MarkdownPreview extends React.Component { ], properties: ['openFile', 'createDirectory'] } - var value = formatter ? formatter.call(this, this.props.value) : this.props.value + const value = formatter ? formatter.call(this, this.props.value) : this.props.value dialog.showSaveDialog(remote.getCurrentWindow(), options, (filename) => { diff --git a/lib/main-menu.js b/lib/main-menu.js index 19ccc965..b948c52d 100644 --- a/lib/main-menu.js +++ b/lib/main-menu.js @@ -108,7 +108,7 @@ const file = { } }, { - label: 'Html (.html)', + label: 'HTML (.html)', click () { mainWindow.webContents.send('list:isMarkdownNote') mainWindow.webContents.send('export:save-html') From 795fe8ae1da7debfecd9e47cace59abfc189edf2 Mon Sep 17 00:00:00 2001 From: Paul Rosset Date: Thu, 14 Dec 2017 12:26:05 +0000 Subject: [PATCH 12/50] Add isEqual and changing haveToSaveNotif method --- browser/main/modals/PreferencesModal/HotkeyTab.js | 2 +- browser/main/modals/PreferencesModal/UiTab.js | 2 +- browser/main/modals/PreferencesModal/index.js | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/browser/main/modals/PreferencesModal/HotkeyTab.js b/browser/main/modals/PreferencesModal/HotkeyTab.js index 93d2993c..4b4a3060 100644 --- a/browser/main/modals/PreferencesModal/HotkeyTab.js +++ b/browser/main/modals/PreferencesModal/HotkeyTab.js @@ -72,7 +72,7 @@ class HotkeyTab extends React.Component { this.setState({ config }) - if (JSON.stringify(this.oldHotkey) === JSON.stringify(config.hotkey)) { + if (_.isEqual(this.oldHotkey, config.hotkey)) { this.props.haveToSave() } else { this.props.haveToSave({ diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 9f9ee73f..d5d54b75 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -93,7 +93,7 @@ class UiTab extends React.Component { this.setState({ config: newConfig, codemirrorTheme: newCodemirrorTheme }, () => { const {ui, editor, preview} = this.props.config this.currentConfig = {ui, editor, preview} - if (JSON.stringify(this.currentConfig) === JSON.stringify(this.state.config)) { + if (_.isEqual(this.currentConfig, this.state.config)) { this.props.haveToSave() } else { this.props.haveToSave({ diff --git a/browser/main/modals/PreferencesModal/index.js b/browser/main/modals/PreferencesModal/index.js index 882428b5..09885e1c 100644 --- a/browser/main/modals/PreferencesModal/index.js +++ b/browser/main/modals/PreferencesModal/index.js @@ -98,9 +98,9 @@ class Preferences extends React.Component { return node.getBoundingClientRect() } - haveToSaveNotif (tab) { + haveToSaveNotif (type, message) { return ( -

{tab[tab.label].message}

+

{message}

) } @@ -129,7 +129,7 @@ class Preferences extends React.Component { {tab.label} - {isUiHotkeyTab ? this.haveToSaveNotif(tab) : null} + {isUiHotkeyTab ? this.haveToSaveNotif(tab[tab.label].type, tab[tab.label].message) : null} ) }) From 775200bdd643a6a9a827349a73f27b28aa772736 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Fri, 15 Dec 2017 12:57:18 +0100 Subject: [PATCH 13/50] fixed opening finder on Windows and Linux fixes #1291 - tested on Ubuntu Linux Mate and Windows 10 --- lib/main-app.js | 251 ++++++++++++++++++++++++------------------------ 1 file changed, 125 insertions(+), 126 deletions(-) diff --git a/lib/main-app.js b/lib/main-app.js index 2c55ba97..13f22f80 100644 --- a/lib/main-app.js +++ b/lib/main-app.js @@ -1,126 +1,125 @@ -const electron = require('electron') -const app = electron.app -const Menu = electron.Menu -const ipc = electron.ipcMain -const path = require('path') -const ChildProcess = require('child_process') -const _ = require('lodash') -const GhReleases = require('electron-gh-releases') -// electron.crashReporter.start() -var ipcServer = null - -var mainWindow = null - -var shouldQuit = app.makeSingleInstance(function (commandLine, workingDirectory) { - if (mainWindow) { - if (process.platform === 'win32') { - mainWindow.minimize() - mainWindow.restore() - } - mainWindow.focus() - } - return true -}) - -if (shouldQuit) { - app.quit() -} - -var isUpdateReady = false - -var ghReleasesOpts = { - repo: 'BoostIO/boost-releases', - currentVersion: app.getVersion() -} - -const updater = new GhReleases(ghReleasesOpts) - -// Check for updates -// `status` returns true if there is a new update available -function checkUpdate () { - if (process.platform === 'linux' || isUpdateReady) { - return true - } - updater.check((err, status) => { - if (err) { - var isLatest = err.message === 'There is no newer version.' - if (!isLatest) console.error('Updater error! %s', err.message) - return - } - if (status) { - mainWindow.webContents.send('update-found', 'Update available!') - updater.download() - } - }) -} - -updater.on('update-downloaded', (info) => { - if (mainWindow != null) { - mainWindow.webContents.send('update-ready', 'Update available!') - isUpdateReady = true - } -}) - -updater.autoUpdater.on('error', (err) => { - console.log(err) -}) - -ipc.on('update-check', function (event, msg) { - if (isUpdateReady) { - mainWindow.webContents.send('update-ready', 'Update available!') - } else { - checkUpdate() - } -}) - -ipc.on('update-app-confirm', function (event, msg) { - if (isUpdateReady) { - mainWindow.removeAllListeners() - updater.install() - } -}) - -function spawnFinder () { - var finderArgv = [path.join(__dirname, 'finder-app.js'), '--finder'] - if (_.find(process.argv, a => a === '--hot')) finderArgv.push('--hot') - var finderProcess = ChildProcess - .execFile(process.execPath, finderArgv) - - app.on('before-quit', function () { - finderProcess.kill() - }) -} - -app.on('ready', function () { - mainWindow = require('./main-window') - - var template = require('./main-menu') - var menu = Menu.buildFromTemplate(template) - switch (process.platform) { - case 'darwin': - spawnFinder() - Menu.setApplicationMenu(menu) - break - case 'win32': - /* eslint-disable */ - finderWindow = require('./finder-window') - /* eslint-disable */ - mainWindow.setMenu(menu) - break - case 'linux': - Menu.setApplicationMenu(menu) - mainWindow.setMenu(menu) - } - - // Check update every hour - setInterval(function () { - checkUpdate() - }, 1000 * 60 * 60) - - checkUpdate() - ipcServer = require('./ipcServer') - ipcServer.server.start() -}) - -module.exports = app - +const electron = require('electron') +const app = electron.app +const Menu = electron.Menu +const ipc = electron.ipcMain +const path = require('path') +const ChildProcess = require('child_process') +const _ = require('lodash') +const GhReleases = require('electron-gh-releases') +// electron.crashReporter.start() +var ipcServer = null + +var mainWindow = null + +var shouldQuit = app.makeSingleInstance(function (commandLine, workingDirectory) { + if (mainWindow) { + if (process.platform === 'win32') { + mainWindow.minimize() + mainWindow.restore() + } + mainWindow.focus() + } + return true +}) + +if (shouldQuit) { + app.quit() +} + +var isUpdateReady = false + +var ghReleasesOpts = { + repo: 'BoostIO/boost-releases', + currentVersion: app.getVersion() +} + +const updater = new GhReleases(ghReleasesOpts) + +// Check for updates +// `status` returns true if there is a new update available +function checkUpdate () { + if (process.platform === 'linux' || isUpdateReady) { + return true + } + updater.check((err, status) => { + if (err) { + var isLatest = err.message === 'There is no newer version.' + if (!isLatest) console.error('Updater error! %s', err.message) + return + } + if (status) { + mainWindow.webContents.send('update-found', 'Update available!') + updater.download() + } + }) +} + +updater.on('update-downloaded', (info) => { + if (mainWindow != null) { + mainWindow.webContents.send('update-ready', 'Update available!') + isUpdateReady = true + } +}) + +updater.autoUpdater.on('error', (err) => { + console.log(err) +}) + +ipc.on('update-check', function (event, msg) { + if (isUpdateReady) { + mainWindow.webContents.send('update-ready', 'Update available!') + } else { + checkUpdate() + } +}) + +ipc.on('update-app-confirm', function (event, msg) { + if (isUpdateReady) { + mainWindow.removeAllListeners() + updater.install() + } +}) + +function spawnFinder () { + var finderArgv = [path.join(__dirname, 'finder-app.js'), '--finder'] + if (_.find(process.argv, a => a === '--hot')) finderArgv.push('--hot') + var finderProcess = ChildProcess + .execFile(process.execPath, finderArgv) + + app.on('before-quit', function () { + finderProcess.kill() + }) +} + +app.on('ready', function () { + mainWindow = require('./main-window') + + var template = require('./main-menu') + var menu = Menu.buildFromTemplate(template) + switch (process.platform) { + case 'darwin': + spawnFinder() + Menu.setApplicationMenu(menu) + break + case 'win32': + require('./finder-window') + mainWindow.setMenu(menu) + break + case 'linux': + require('./finder-window') + Menu.setApplicationMenu(menu) + mainWindow.setMenu(menu) + } + + // Check update every hour + setInterval(function () { + checkUpdate() + }, 1000 * 60 * 60) + + checkUpdate() + ipcServer = require('./ipcServer') + ipcServer.server.start() +}) + +module.exports = app + From f54b49db1aee2a98e3d00bf89f273f000ef70cfb Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Tue, 5 Dec 2017 18:23:18 +0900 Subject: [PATCH 14/50] detect internet disconnection --- browser/main/Main.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/browser/main/Main.js b/browser/main/Main.js index 3fefdb45..90dbbebf 100644 --- a/browser/main/Main.js +++ b/browser/main/Main.js @@ -20,7 +20,9 @@ class Main extends React.Component { constructor (props) { super(props) - if (process.env.NODE_ENV === 'production') { + const isOnline = window.navigator.onLine + + if (process.env.NODE_ENV === 'production' && isOnline) { mobileAnalytics.initAwsMobileAnalytics() } From bdb3406dcb6e3c448bf1864701c32acbe5753b28 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Tue, 5 Dec 2017 19:23:49 +0900 Subject: [PATCH 15/50] modify: change the file where detect Internet disconnection --- browser/main/Main.js | 4 +--- browser/main/lib/AwsMobileAnalyticsConfig.js | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/browser/main/Main.js b/browser/main/Main.js index 90dbbebf..3fefdb45 100644 --- a/browser/main/Main.js +++ b/browser/main/Main.js @@ -20,9 +20,7 @@ class Main extends React.Component { constructor (props) { super(props) - const isOnline = window.navigator.onLine - - if (process.env.NODE_ENV === 'production' && isOnline) { + if (process.env.NODE_ENV === 'production') { mobileAnalytics.initAwsMobileAnalytics() } diff --git a/browser/main/lib/AwsMobileAnalyticsConfig.js b/browser/main/lib/AwsMobileAnalyticsConfig.js index f10d0b66..e6d028dc 100644 --- a/browser/main/lib/AwsMobileAnalyticsConfig.js +++ b/browser/main/lib/AwsMobileAnalyticsConfig.js @@ -7,7 +7,7 @@ const os = require('os') let mobileAnalyticsClient AWS.config.region = 'us-east-1' -if (process.env.NODE_ENV === 'production' && ConfigManager.default.get().amaEnabled) { +if (process.env.NODE_ENV === 'production' && ConfigManager.default.get().amaEnabled && window.navigator.onLine) { AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:xxxxxxxxxxxxxxxxxxxxxxxxx' }) From d09f8dff18878f3b8040e167a2a7141d283d09ad Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Tue, 5 Dec 2017 19:28:42 +0900 Subject: [PATCH 16/50] detect internet connection when send events --- browser/main/lib/AwsMobileAnalyticsConfig.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/main/lib/AwsMobileAnalyticsConfig.js b/browser/main/lib/AwsMobileAnalyticsConfig.js index e6d028dc..4a6c58ad 100644 --- a/browser/main/lib/AwsMobileAnalyticsConfig.js +++ b/browser/main/lib/AwsMobileAnalyticsConfig.js @@ -35,7 +35,7 @@ function convertPlatformName (platformName) { } function initAwsMobileAnalytics () { - if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled) return + if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled || !window.navigator.onLine) return AWS.config.credentials.get((err) => { if (!err) { console.log('Cognito Identity ID: ' + AWS.config.credentials.identityId) @@ -46,7 +46,7 @@ function initAwsMobileAnalytics () { } function recordDynamicCustomEvent (type, options = {}) { - if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled) return + if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled || !window.navigator.onLine) return try { mobileAnalyticsClient.recordEvent(type, options) } catch (analyticsError) { @@ -57,7 +57,7 @@ function recordDynamicCustomEvent (type, options = {}) { } function recordStaticCustomEvent () { - if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled) return + if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled || !window.navigator.onLine) return try { mobileAnalyticsClient.recordEvent('UI_COLOR_THEME', { uiColorTheme: ConfigManager.default.get().ui.theme From b5e2d21f33b9ca1addc94e45ccfde6ae9d70f305 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Tue, 5 Dec 2017 20:54:06 +0900 Subject: [PATCH 17/50] split to function send event conditions --- browser/main/lib/AwsMobileAnalyticsConfig.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/browser/main/lib/AwsMobileAnalyticsConfig.js b/browser/main/lib/AwsMobileAnalyticsConfig.js index 4a6c58ad..a19774f8 100644 --- a/browser/main/lib/AwsMobileAnalyticsConfig.js +++ b/browser/main/lib/AwsMobileAnalyticsConfig.js @@ -34,8 +34,15 @@ function convertPlatformName (platformName) { } } +function getSendEventCond () { + const isDev = process.env.NODE_ENV !== 'production' + const isDisable = !ConfigManager.default.get().amaEnabled + const isOffline = !window.navigator.onLine + return isDev || isDisable || isOffline +} + function initAwsMobileAnalytics () { - if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled || !window.navigator.onLine) return + if (getSendEventCond()) return AWS.config.credentials.get((err) => { if (!err) { console.log('Cognito Identity ID: ' + AWS.config.credentials.identityId) @@ -46,7 +53,7 @@ function initAwsMobileAnalytics () { } function recordDynamicCustomEvent (type, options = {}) { - if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled || !window.navigator.onLine) return + if (getSendEventCond()) return try { mobileAnalyticsClient.recordEvent(type, options) } catch (analyticsError) { @@ -57,7 +64,7 @@ function recordDynamicCustomEvent (type, options = {}) { } function recordStaticCustomEvent () { - if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled || !window.navigator.onLine) return + if (getSendEventCond()) return try { mobileAnalyticsClient.recordEvent('UI_COLOR_THEME', { uiColorTheme: ConfigManager.default.get().ui.theme From a17ddf6d54b64a9f9ee6eb0331ba34a5fd087b16 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 16 Dec 2017 14:25:18 +0900 Subject: [PATCH 18/50] use getSendEventCond func --- browser/main/lib/AwsMobileAnalyticsConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/lib/AwsMobileAnalyticsConfig.js b/browser/main/lib/AwsMobileAnalyticsConfig.js index a19774f8..1ef4f8da 100644 --- a/browser/main/lib/AwsMobileAnalyticsConfig.js +++ b/browser/main/lib/AwsMobileAnalyticsConfig.js @@ -7,7 +7,7 @@ const os = require('os') let mobileAnalyticsClient AWS.config.region = 'us-east-1' -if (process.env.NODE_ENV === 'production' && ConfigManager.default.get().amaEnabled && window.navigator.onLine) { +if (!getSendEventCond()) { AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: 'us-east-1:xxxxxxxxxxxxxxxxxxxxxxxxx' }) From 25810916524f94a5699d4252a7be6b831e0a4d6b Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 16 Dec 2017 23:17:45 +0900 Subject: [PATCH 19/50] add editorType into ConfigManager --- browser/main/lib/ConfigManager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index fc9b4ee9..4e04ad70 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -35,7 +35,8 @@ export const DEFAULT_CONFIG = { indentType: 'space', indentSize: '2', switchPreview: 'BLUR', // Available value: RIGHTCLICK, BLUR - scrollPastEnd: false + scrollPastEnd: false, + type: 'default' }, preview: { fontSize: '14', From 8ba0d10f40ed971eb939af34d46e6468f834cc3e Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 17 Dec 2017 02:02:19 +0900 Subject: [PATCH 20/50] set editorType into Config and state --- browser/main/Detail/MarkdownNoteDetail.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 25c993d0..469fc7ab 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -15,6 +15,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 +40,8 @@ class MarkdownNoteDetail extends React.Component { content: '' }, props.note), isLockButtonShown: false, - isLocked: false + isLocked: false, + editorType: props.config.editor.type } this.dispatchTimer = null @@ -262,6 +264,14 @@ class MarkdownNoteDetail extends React.Component { ee.emit('print') } + handleSwitchMode (type) { + this.setState({ editorType: type }, () => { + const newConfig = Object.assign({}, this.props.config) + newConfig.editor.type = type + ConfigManager.set(newConfig) + }) + } + render () { const { data, config, location } = this.props const { note } = this.state @@ -320,10 +330,10 @@ class MarkdownNoteDetail extends React.Component { />
-
+
this.handleSwitchMode('SPLIT')}>
-
+
this.handleSwitchMode('DEFAULT')}>
From 977e80c82931502888f513fb605cbe9092fc4f14 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sun, 17 Dec 2017 02:07:07 +0900 Subject: [PATCH 21/50] apply switching style --- browser/main/Detail/MarkdownNoteDetail.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 469fc7ab..baaf63f9 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -274,7 +274,7 @@ class MarkdownNoteDetail extends React.Component { render () { const { data, config, location } = this.props - const { note } = this.state + const { note, editorType } = this.state const storageKey = note.storage const folderKey = note.folder @@ -330,10 +330,10 @@ class MarkdownNoteDetail extends React.Component { />
-
this.handleSwitchMode('SPLIT')}> +
this.handleSwitchMode('SPLIT')}>
-
this.handleSwitchMode('DEFAULT')}> +
this.handleSwitchMode('DEFAULT')}>
From 8e81609a39aa3368c1a743caa4fe1a09a0058de3 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 18 Dec 2017 17:40:06 +0900 Subject: [PATCH 22/50] implement minimun splitEditor --- browser/components/MarkdownSplitEditor.js | 21 +++++++++++++++ browser/components/MarkdownSplitEditor.styl | 9 +++++++ browser/main/Detail/MarkdownNoteDetail.js | 29 ++++++++++++++------- 3 files changed, 50 insertions(+), 9 deletions(-) create mode 100644 browser/components/MarkdownSplitEditor.js create mode 100644 browser/components/MarkdownSplitEditor.styl diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js new file mode 100644 index 00000000..7118c059 --- /dev/null +++ b/browser/components/MarkdownSplitEditor.js @@ -0,0 +1,21 @@ +import React from 'react' + +import styles from './MarkdownSplitEditor.styl' +import CSSModules from 'browser/lib/CSSModules' + +class MarkdownSplitEditor extends React.Component { + render () { + return ( +
+
+

editor

+
+
+

preview

+
+
+ ) + } +} + +export default CSSModules(MarkdownSplitEditor, styles) diff --git a/browser/components/MarkdownSplitEditor.styl b/browser/components/MarkdownSplitEditor.styl new file mode 100644 index 00000000..c439bed9 --- /dev/null +++ b/browser/components/MarkdownSplitEditor.styl @@ -0,0 +1,9 @@ +.root + width 100% + height 100% + font-size 30px + display flex + .editor + width 50% + .preview + width 50% diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index baaf63f9..39db6c3c 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' @@ -272,6 +273,24 @@ class MarkdownNoteDetail extends React.Component { }) } + renderEditor () { + const { config, ignorePreviewPointerEvents } = this.props + const { note } = this.state + if (this.state.editorType === 'SPLIT') { + return + } else { + return this.handleChange(e)} + ignorePreviewPointerEvents={ignorePreviewPointerEvents} + /> + } + } + render () { const { data, config, location } = this.props const { note, editorType } = this.state @@ -400,15 +419,7 @@ class MarkdownNoteDetail extends React.Component { {location.pathname === '/trashed' ? trashTopBar : detailTopBar}
- this.handleChange(e)} - ignorePreviewPointerEvents={this.props.ignorePreviewPointerEvents} - /> + {this.renderEditor()}
Date: Mon, 18 Dec 2017 18:26:25 +0900 Subject: [PATCH 23/50] implement splitEditor --- browser/components/MarkdownSplitEditor.js | 55 ++++++++++++++++++++++- browser/main/Detail/MarkdownNoteDetail.js | 8 +++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 7118c059..8dcf0835 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -1,17 +1,68 @@ 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.state = { + value: props.value + } + this.value = props.value + this.focus = () => this.refs.code.focus() + this.reload = () => this.refs.code.reload() + } + + componentWillReceiveProps (props) { + this.setState({ value: props.value }) + } + + handleOnChange (e) { + const value = this.refs.code.value + this.setState({ value }, () => { + this.value = value + this.props.onChange() + }) + } + render () { + const { config, storageKey } = this.props + const { value } = this.state + const storage = findStorage(storageKey) return (
-

editor

+ this.handleOnChange(e)} + />
-

preview

+
) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 39db6c3c..e49dff83 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -277,7 +277,13 @@ class MarkdownNoteDetail extends React.Component { const { config, ignorePreviewPointerEvents } = this.props const { note } = this.state if (this.state.editorType === 'SPLIT') { - return + return this.handleChange(e)} + /> } else { return Date: Mon, 18 Dec 2017 18:39:40 +0900 Subject: [PATCH 24/50] fix style --- browser/components/MarkdownSplitEditor.js | 56 ++++++++++----------- browser/components/MarkdownSplitEditor.styl | 2 +- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 8dcf0835..84f31af3 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -35,35 +35,33 @@ class MarkdownSplitEditor extends React.Component { const storage = findStorage(storageKey) return (
-
- this.handleOnChange(e)} - /> -
-
- -
+ this.handleOnChange(e)} + /> +
) } diff --git a/browser/components/MarkdownSplitEditor.styl b/browser/components/MarkdownSplitEditor.styl index c439bed9..c9afd22f 100644 --- a/browser/components/MarkdownSplitEditor.styl +++ b/browser/components/MarkdownSplitEditor.styl @@ -3,7 +3,7 @@ height 100% font-size 30px display flex - .editor + .codeEditor width 50% .preview width 50% From caaa7a9e74c772bcbf1bdde928aa97fdadf2e045 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 18 Dec 2017 18:42:35 +0900 Subject: [PATCH 25/50] implement checkbox --- browser/components/MarkdownSplitEditor.js | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 84f31af3..92ae0ce5 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -29,6 +29,29 @@ class MarkdownSplitEditor extends React.Component { }) } + 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, storageKey } = this.props const { value } = this.state @@ -59,6 +82,7 @@ class MarkdownSplitEditor extends React.Component { ref='preview' tabInde='0' value={value} + onCheckboxClick={(e) => this.handleCheckboxClick(e)} showCopyNotification={config.ui.showCopyNotification} storagePath={storage.path} /> From e682ee8541a6c01d73a6cd89b51440334d5fe711 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 18 Dec 2017 18:52:33 +0900 Subject: [PATCH 26/50] avoid handling events for not split editor --- browser/components/MarkdownPreview.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index a3e7bb93..c9d3d963 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 } From f5ccaa7b4808e953baebc4bb2f10fac425b4af9f Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 18 Dec 2017 18:52:59 +0900 Subject: [PATCH 27/50] fix word-wrap --- browser/components/markdown.styl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index 53e93574..0600d9ab 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 From 50d89a8ec91596f4884f29db484ac98ac5cda7c7 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 18 Dec 2017 19:21:52 +0900 Subject: [PATCH 28/50] fix to apply fontSize and fontFamily --- browser/components/MarkdownSplitEditor.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 92ae0ce5..712010c4 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -75,7 +75,8 @@ class MarkdownSplitEditor extends React.Component { styleName='preview' theme={config.ui.theme} keyMap={config.editor.keyMap} - fontSize={config.preview.fontFamily} + fontSize={config.preview.fontSize} + fontFamily={config.preview.fontFamily} codeBlockTheme={config.preview.codeBlockTheme} codeBlockFontFamily={config.editor.fontFamily} lineNumber={config.preview.lineNumber} From c80bdb8d0c2ca732003ecda61d0eae9cbd585ef7 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 18 Dec 2017 19:28:42 +0900 Subject: [PATCH 29/50] apply ignorePreviewPointerEvents --- browser/components/MarkdownSplitEditor.js | 3 +++ browser/main/Detail/MarkdownNoteDetail.js | 1 + 2 files changed, 4 insertions(+) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 712010c4..bf6ca304 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -56,6 +56,8 @@ class MarkdownSplitEditor extends React.Component { const { config, storageKey } = this.props const { value } = this.state const storage = findStorage(storageKey) + const previewStyle = {} + if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none' return (
this.handleOnChange(e)} /> this.handleChange(e)} + ignorePreviewPointerEvents={ignorePreviewPointerEvents} /> } else { return Date: Mon, 18 Dec 2017 19:31:43 +0900 Subject: [PATCH 30/50] remove an unnecessary valiable --- browser/main/Detail/MarkdownNoteDetail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 8c2c29a2..ed1762b1 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -299,7 +299,7 @@ class MarkdownNoteDetail extends React.Component { } render () { - const { data, config, location } = this.props + const { data, location } = this.props const { note, editorType } = this.state const storageKey = note.storage const folderKey = note.folder From 0e0e779cbe0f6ef34622005b2d4bf56f78a73e48 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Mon, 18 Dec 2017 21:38:58 +0900 Subject: [PATCH 31/50] remove unnecessary arg --- browser/components/MarkdownSplitEditor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index bf6ca304..f114d37d 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -21,7 +21,7 @@ class MarkdownSplitEditor extends React.Component { this.setState({ value: props.value }) } - handleOnChange (e) { + handleOnChange () { const value = this.refs.code.value this.setState({ value }, () => { this.value = value @@ -71,7 +71,7 @@ class MarkdownSplitEditor extends React.Component { indentType={config.editor.indentType} scrollPastEnd={config.editor.scrollPastEnd} storageKey={storageKey} - onChange={e => this.handleOnChange(e)} + onChange={this.handleOnChange.bind(this)} /> Date: Tue, 19 Dec 2017 03:46:20 +0900 Subject: [PATCH 32/50] remove unnecesarry state --- browser/components/MarkdownSplitEditor.js | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index f114d37d..b77c0b6b 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -9,24 +9,14 @@ import CSSModules from 'browser/lib/CSSModules' class MarkdownSplitEditor extends React.Component { constructor (props) { super(props) - this.state = { - value: props.value - } this.value = props.value this.focus = () => this.refs.code.focus() this.reload = () => this.refs.code.reload() } - componentWillReceiveProps (props) { - this.setState({ value: props.value }) - } - handleOnChange () { - const value = this.refs.code.value - this.setState({ value }, () => { - this.value = value - this.props.onChange() - }) + this.value = this.refs.code.value + this.props.onChange() } handleCheckboxClick (e) { @@ -53,8 +43,7 @@ class MarkdownSplitEditor extends React.Component { } render () { - const { config, storageKey } = this.props - const { value } = this.state + const { config, value, storageKey } = this.props const storage = findStorage(storageKey) const previewStyle = {} if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none' From 72b450d5268eaf18344754f8ff6f128483b6a940 Mon Sep 17 00:00:00 2001 From: Yutaka Ishii Date: Tue, 19 Dec 2017 10:21:01 +0900 Subject: [PATCH 33/50] icon updated --- browser/main/Detail/MarkdownNoteDetail.js | 8 +++--- browser/main/Detail/MarkdownNoteDetail.styl | 2 -- resources/icon/icon-WYSIWYG-off.svg | 27 --------------------- resources/icon/icon-WYSIWYG-on.svg | 16 ------------ resources/icon/icon-edit.svg | 21 ++++++++++++---- resources/icon/icon-full.svg | 15 ++++++++++++ resources/icon/icon-mode-markdown-off.svg | 23 ++++++++++++++++++ resources/icon/icon-mode-split-on.svg | 27 +++++++++++++++++++++ resources/icon/icon-previewoff-off.svg | 13 ++++++++++ resources/icon/icon-previewoff-on.svg | 13 ++++++++++ 10 files changed, 111 insertions(+), 54 deletions(-) delete mode 100644 resources/icon/icon-WYSIWYG-off.svg delete mode 100644 resources/icon/icon-WYSIWYG-on.svg create mode 100644 resources/icon/icon-full.svg create mode 100644 resources/icon/icon-mode-markdown-off.svg create mode 100644 resources/icon/icon-mode-split-on.svg create mode 100644 resources/icon/icon-previewoff-off.svg create mode 100644 resources/icon/icon-previewoff-on.svg diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index ed1762b1..558d0e11 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -236,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) { @@ -357,10 +357,10 @@ class MarkdownNoteDetail extends React.Component {
this.handleSwitchMode('SPLIT')}> - +
this.handleSwitchMode('DEFAULT')}> - +
@@ -396,7 +396,7 @@ class MarkdownNoteDetail extends React.Component { this.handleTrashButtonClick(e)} /> diff --git a/browser/main/Detail/MarkdownNoteDetail.styl b/browser/main/Detail/MarkdownNoteDetail.styl index 9425e723..c2c189f9 100644 --- a/browser/main/Detail/MarkdownNoteDetail.styl +++ b/browser/main/Detail/MarkdownNoteDetail.styl @@ -48,8 +48,6 @@ cursor pointer &:first-child border-right 1px solid #eee - img - transform scale(0.7) .active background-color #fff box-shadow 2px 0px 7px #eee diff --git a/resources/icon/icon-WYSIWYG-off.svg b/resources/icon/icon-WYSIWYG-off.svg deleted file mode 100644 index ffd6088a..00000000 --- a/resources/icon/icon-WYSIWYG-off.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - 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 b8ee9489..00000000 --- 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 3707c6fe..cb7d92cc 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 00000000..621ebacc --- /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 00000000..7f6a0235 --- /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 00000000..338d2bd7 --- /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 00000000..b0e720e7 --- /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 00000000..8a6c5d7e --- /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 From df13ca3c9289e1ce9fb6c8cc061ec14eb3f27c52 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Wed, 20 Dec 2017 18:11:01 +0900 Subject: [PATCH 34/50] make splitMode Default --- browser/main/Detail/MarkdownNoteDetail.js | 10 +++++----- browser/main/lib/ConfigManager.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 558d0e11..8d3acea9 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -276,9 +276,10 @@ class MarkdownNoteDetail extends React.Component { renderEditor () { const { config, ignorePreviewPointerEvents } = this.props const { note } = this.state - if (this.state.editorType === 'SPLIT') { - return } else { - return this.handleSwitchMode('SPLIT')}>
-
this.handleSwitchMode('DEFAULT')}> +
this.handleSwitchMode('EDITOR_PREVIEW')}>
diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 4e04ad70..3d70a7a3 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -36,7 +36,7 @@ export const DEFAULT_CONFIG = { indentSize: '2', switchPreview: 'BLUR', // Available value: RIGHTCLICK, BLUR scrollPastEnd: false, - type: 'default' + type: 'SPLIT' }, preview: { fontSize: '14', From 7ccc5eb9b8df675b7dd378cf6dc4b756caef7b59 Mon Sep 17 00:00:00 2001 From: Kazu Yokomizo Date: Wed, 20 Dec 2017 18:50:53 +0900 Subject: [PATCH 35/50] Fix switch button layout --- browser/main/Detail/MarkdownNoteDetail.js | 4 +-- browser/main/Detail/MarkdownNoteDetail.styl | 24 +++++++++++++++-- .../icon/icon-mode-markdown-off-active.svg | 23 ++++++++++++++++ resources/icon/icon-mode-split-on-active.svg | 27 +++++++++++++++++++ resources/icon/icon-mode-split-on.svg | 2 +- 5 files changed, 75 insertions(+), 5 deletions(-) create mode 100644 resources/icon/icon-mode-markdown-off-active.svg create mode 100644 resources/icon/icon-mode-split-on-active.svg diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 8d3acea9..6b7b8fd4 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -357,10 +357,10 @@ class MarkdownNoteDetail extends React.Component {
this.handleSwitchMode('SPLIT')}> - +
this.handleSwitchMode('EDITOR_PREVIEW')}> - +
diff --git a/browser/main/Detail/MarkdownNoteDetail.styl b/browser/main/Detail/MarkdownNoteDetail.styl index c2c189f9..7032e36f 100644 --- a/browser/main/Detail/MarkdownNoteDetail.styl +++ b/browser/main/Detail/MarkdownNoteDetail.styl @@ -39,7 +39,7 @@ display flex align-items center div - width 100px + width 40px height 100% background-color #f9f9f9 display flex @@ -73,7 +73,27 @@ body[data-theme="dark"] .control-fullScreenButton topBarButtonDark() + .mode-tab + border 1px solid #444444 + div + background-color $ui-dark-noteDetail-backgroundColor + &:first-child + border-right 1px solid #444444 + .active + background-color #3A404C + box-shadow 2px 0px 7px #444444 + body[data-theme="solarized-dark"] .root border-left 1px solid $ui-solarized-dark-borderColor - background-color $ui-solarized-dark-noteDetail-backgroundColor \ No newline at end of file + background-color $ui-solarized-dark-noteDetail-backgroundColor + + .mode-tab + border 1px solid #586E75 + div + background-color $ui-solarized-dark-noteDetail-backgroundColor + &:first-child + border-right 1px solid #586E75 + .active + background-color #002B36 + box-shadow 2px 0px 7px #222222 \ No newline at end of file diff --git a/resources/icon/icon-mode-markdown-off-active.svg b/resources/icon/icon-mode-markdown-off-active.svg new file mode 100644 index 00000000..0159836b --- /dev/null +++ b/resources/icon/icon-mode-markdown-off-active.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-active.svg b/resources/icon/icon-mode-split-on-active.svg new file mode 100644 index 00000000..338d2bd7 --- /dev/null +++ b/resources/icon/icon-mode-split-on-active.svg @@ -0,0 +1,27 @@ + + + + icon-mode-split-on + 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 index 338d2bd7..c212d7f2 100644 --- a/resources/icon/icon-mode-split-on.svg +++ b/resources/icon/icon-mode-split-on.svg @@ -17,7 +17,7 @@ - + From 9367a404eff4db7e1a17ef8f45351251f2ea0644 Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Thu, 21 Dec 2017 09:37:17 +0100 Subject: [PATCH 36/50] converted line-endings back to lf --- lib/main-app.js | 250 ++++++++++++++++++++++++------------------------ 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/lib/main-app.js b/lib/main-app.js index 13f22f80..02b38a04 100644 --- a/lib/main-app.js +++ b/lib/main-app.js @@ -1,125 +1,125 @@ -const electron = require('electron') -const app = electron.app -const Menu = electron.Menu -const ipc = electron.ipcMain -const path = require('path') -const ChildProcess = require('child_process') -const _ = require('lodash') -const GhReleases = require('electron-gh-releases') -// electron.crashReporter.start() -var ipcServer = null - -var mainWindow = null - -var shouldQuit = app.makeSingleInstance(function (commandLine, workingDirectory) { - if (mainWindow) { - if (process.platform === 'win32') { - mainWindow.minimize() - mainWindow.restore() - } - mainWindow.focus() - } - return true -}) - -if (shouldQuit) { - app.quit() -} - -var isUpdateReady = false - -var ghReleasesOpts = { - repo: 'BoostIO/boost-releases', - currentVersion: app.getVersion() -} - -const updater = new GhReleases(ghReleasesOpts) - -// Check for updates -// `status` returns true if there is a new update available -function checkUpdate () { - if (process.platform === 'linux' || isUpdateReady) { - return true - } - updater.check((err, status) => { - if (err) { - var isLatest = err.message === 'There is no newer version.' - if (!isLatest) console.error('Updater error! %s', err.message) - return - } - if (status) { - mainWindow.webContents.send('update-found', 'Update available!') - updater.download() - } - }) -} - -updater.on('update-downloaded', (info) => { - if (mainWindow != null) { - mainWindow.webContents.send('update-ready', 'Update available!') - isUpdateReady = true - } -}) - -updater.autoUpdater.on('error', (err) => { - console.log(err) -}) - -ipc.on('update-check', function (event, msg) { - if (isUpdateReady) { - mainWindow.webContents.send('update-ready', 'Update available!') - } else { - checkUpdate() - } -}) - -ipc.on('update-app-confirm', function (event, msg) { - if (isUpdateReady) { - mainWindow.removeAllListeners() - updater.install() - } -}) - -function spawnFinder () { - var finderArgv = [path.join(__dirname, 'finder-app.js'), '--finder'] - if (_.find(process.argv, a => a === '--hot')) finderArgv.push('--hot') - var finderProcess = ChildProcess - .execFile(process.execPath, finderArgv) - - app.on('before-quit', function () { - finderProcess.kill() - }) -} - -app.on('ready', function () { - mainWindow = require('./main-window') - - var template = require('./main-menu') - var menu = Menu.buildFromTemplate(template) - switch (process.platform) { - case 'darwin': - spawnFinder() - Menu.setApplicationMenu(menu) - break - case 'win32': - require('./finder-window') - mainWindow.setMenu(menu) - break - case 'linux': - require('./finder-window') - Menu.setApplicationMenu(menu) - mainWindow.setMenu(menu) - } - - // Check update every hour - setInterval(function () { - checkUpdate() - }, 1000 * 60 * 60) - - checkUpdate() - ipcServer = require('./ipcServer') - ipcServer.server.start() -}) - -module.exports = app - +const electron = require('electron') +const app = electron.app +const Menu = electron.Menu +const ipc = electron.ipcMain +const path = require('path') +const ChildProcess = require('child_process') +const _ = require('lodash') +const GhReleases = require('electron-gh-releases') +// electron.crashReporter.start() +var ipcServer = null + +var mainWindow = null + +var shouldQuit = app.makeSingleInstance(function (commandLine, workingDirectory) { + if (mainWindow) { + if (process.platform === 'win32') { + mainWindow.minimize() + mainWindow.restore() + } + mainWindow.focus() + } + return true +}) + +if (shouldQuit) { + app.quit() +} + +var isUpdateReady = false + +var ghReleasesOpts = { + repo: 'BoostIO/boost-releases', + currentVersion: app.getVersion() +} + +const updater = new GhReleases(ghReleasesOpts) + +// Check for updates +// `status` returns true if there is a new update available +function checkUpdate () { + if (process.platform === 'linux' || isUpdateReady) { + return true + } + updater.check((err, status) => { + if (err) { + var isLatest = err.message === 'There is no newer version.' + if (!isLatest) console.error('Updater error! %s', err.message) + return + } + if (status) { + mainWindow.webContents.send('update-found', 'Update available!') + updater.download() + } + }) +} + +updater.on('update-downloaded', (info) => { + if (mainWindow != null) { + mainWindow.webContents.send('update-ready', 'Update available!') + isUpdateReady = true + } +}) + +updater.autoUpdater.on('error', (err) => { + console.log(err) +}) + +ipc.on('update-check', function (event, msg) { + if (isUpdateReady) { + mainWindow.webContents.send('update-ready', 'Update available!') + } else { + checkUpdate() + } +}) + +ipc.on('update-app-confirm', function (event, msg) { + if (isUpdateReady) { + mainWindow.removeAllListeners() + updater.install() + } +}) + +function spawnFinder () { + var finderArgv = [path.join(__dirname, 'finder-app.js'), '--finder'] + if (_.find(process.argv, a => a === '--hot')) finderArgv.push('--hot') + var finderProcess = ChildProcess + .execFile(process.execPath, finderArgv) + + app.on('before-quit', function () { + finderProcess.kill() + }) +} + +app.on('ready', function () { + mainWindow = require('./main-window') + + var template = require('./main-menu') + var menu = Menu.buildFromTemplate(template) + switch (process.platform) { + case 'darwin': + spawnFinder() + Menu.setApplicationMenu(menu) + break + case 'win32': + require('./finder-window') + mainWindow.setMenu(menu) + break + case 'linux': + require('./finder-window') + Menu.setApplicationMenu(menu) + mainWindow.setMenu(menu) + } + + // Check update every hour + setInterval(function () { + checkUpdate() + }, 1000 * 60 * 60) + + checkUpdate() + ipcServer = require('./ipcServer') + ipcServer.server.start() +}) + +module.exports = app + From 6ce1922fb3bc3a30feabc9d67c04cecdb6f1d8fb Mon Sep 17 00:00:00 2001 From: Maurits Lourens Date: Thu, 21 Dec 2017 15:23:13 +0100 Subject: [PATCH 37/50] added tooltips like the new note button (and consequently extracted some buttons and styles) --- browser/main/Detail/FullscreenButton.js | 19 +++++ browser/main/Detail/FullscreenButton.styl | 22 ++++++ browser/main/Detail/InfoButton.js | 1 + browser/main/Detail/InfoButton.styl | 15 ++++ browser/main/Detail/MarkdownNoteDetail.js | 21 ++---- browser/main/Detail/MarkdownNoteDetail.styl | 24 ------- browser/main/Detail/PermanentDeleteButton.js | 1 + browser/main/Detail/SnippetNoteDetail.js | 2 +- browser/main/Detail/StarButton.js | 4 +- browser/main/Detail/StarButton.styl | 16 +++++ browser/main/Detail/ToggleModeButton.js | 25 +++++++ browser/main/Detail/ToggleModeButton.styl | 41 +++++++++++ browser/main/Detail/TrashButton.js | 1 + browser/main/Detail/TrashButton.styl | 15 ++++ browser/main/SideNav/ListButton.js | 24 +++++++ browser/main/SideNav/PreferenceButton.js | 19 +++++ browser/main/SideNav/PreferenceButton.styl | 51 ++++++++++++++ browser/main/SideNav/SideNav.styl | 73 -------------------- browser/main/SideNav/SwitchButton.styl | 59 ++++++++++++++++ browser/main/SideNav/TagButton.js | 24 +++++++ browser/main/SideNav/index.js | 25 ++----- 21 files changed, 347 insertions(+), 135 deletions(-) create mode 100644 browser/main/Detail/FullscreenButton.js create mode 100644 browser/main/Detail/FullscreenButton.styl create mode 100644 browser/main/Detail/ToggleModeButton.js create mode 100644 browser/main/Detail/ToggleModeButton.styl create mode 100644 browser/main/SideNav/ListButton.js create mode 100644 browser/main/SideNav/PreferenceButton.js create mode 100644 browser/main/SideNav/PreferenceButton.styl create mode 100644 browser/main/SideNav/SwitchButton.styl create mode 100644 browser/main/SideNav/TagButton.js diff --git a/browser/main/Detail/FullscreenButton.js b/browser/main/Detail/FullscreenButton.js new file mode 100644 index 00000000..a0e8c790 --- /dev/null +++ b/browser/main/Detail/FullscreenButton.js @@ -0,0 +1,19 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './FullscreenButton.styl' + +const FullscreenButton = ({ + onClick +}) => ( + +) + +FullscreenButton.propTypes = { + onClick: PropTypes.func.isRequired +} + +export default CSSModules(FullscreenButton, styles) diff --git a/browser/main/Detail/FullscreenButton.styl b/browser/main/Detail/FullscreenButton.styl new file mode 100644 index 00000000..7cee4faa --- /dev/null +++ b/browser/main/Detail/FullscreenButton.styl @@ -0,0 +1,22 @@ +.control-fullScreenButton + top 80px + topBarButtonRight() + &:hover .tooltip + opacity 1 + +.tooltip + tooltip() + position absolute + pointer-events none + top 26px + right 0 + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s + +body[data-theme="dark"] + .control-fullScreenButton + topBarButtonDark() \ No newline at end of file diff --git a/browser/main/Detail/InfoButton.js b/browser/main/Detail/InfoButton.js index 02d8dfe4..8a78ab4e 100644 --- a/browser/main/Detail/InfoButton.js +++ b/browser/main/Detail/InfoButton.js @@ -10,6 +10,7 @@ const InfoButton = ({ onClick={(e) => onClick(e)} > + Info ) diff --git a/browser/main/Detail/InfoButton.styl b/browser/main/Detail/InfoButton.styl index 9a2604df..a1c302f0 100644 --- a/browser/main/Detail/InfoButton.styl +++ b/browser/main/Detail/InfoButton.styl @@ -1,6 +1,21 @@ .control-infoButton top 10px topBarButtonRight() + &:hover .tooltip + opacity 1 + +.tooltip + tooltip() + position absolute + pointer-events none + top 26px + right 0 + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s .infoButton padding 0px diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index 6b7b8fd4..37e3963d 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -18,8 +18,10 @@ 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 FullscreenButton from './FullscreenButton' import PermanentDeleteButton from './PermanentDeleteButton' import InfoButton from './InfoButton' +import ToggleModeButton from './ToggleModeButton' import InfoPanel from './InfoPanel' import InfoPanelTrashed from './InfoPanelTrashed' import { formatDate } from 'browser/lib/date-formatter' @@ -355,18 +357,9 @@ class MarkdownNoteDetail extends React.Component { onChange={(e) => this.handleChange(e)} /> -
-
this.handleSwitchMode('SPLIT')}> - -
-
this.handleSwitchMode('EDITOR_PREVIEW')}> - -
-
+ this.handleSwitchMode(e)} editorType={editorType} /> - +
this.handleFullScreenButton(e)} - > - - + this.handleFullScreenButton(e)} /> this.handleTrashButtonClick(e)} /> diff --git a/browser/main/Detail/MarkdownNoteDetail.styl b/browser/main/Detail/MarkdownNoteDetail.styl index 7032e36f..3357c6ef 100644 --- a/browser/main/Detail/MarkdownNoteDetail.styl +++ b/browser/main/Detail/MarkdownNoteDetail.styl @@ -19,10 +19,6 @@ top 40px position relative -.control-fullScreenButton - top 80px - topBarButtonRight() - .body absolute left right left 0 @@ -32,26 +28,6 @@ margin 0 45px .body-noteEditor absolute top bottom left right - -.mode-tab - border 1px solid #eee - height 34px - display flex - align-items center - div - width 40px - height 100% - background-color #f9f9f9 - display flex - align-items center - justify-content center - cursor pointer - &:first-child - border-right 1px solid #eee - .active - background-color #fff - box-shadow 2px 0px 7px #eee - z-index 1 body[data-theme="white"] .root diff --git a/browser/main/Detail/PermanentDeleteButton.js b/browser/main/Detail/PermanentDeleteButton.js index f0b10009..fd5c731b 100644 --- a/browser/main/Detail/PermanentDeleteButton.js +++ b/browser/main/Detail/PermanentDeleteButton.js @@ -10,6 +10,7 @@ const PermanentDeleteButton = ({ onClick={(e) => onClick(e)} > + Permanent Delete ) diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index bec6573b..f12f224d 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -634,7 +634,7 @@ class SnippetNoteDetail extends React.Component { isActive={note.isStarred} /> - diff --git a/browser/main/Detail/StarButton.js b/browser/main/Detail/StarButton.js index 0616a1e0..57ba79c8 100644 --- a/browser/main/Detail/StarButton.js +++ b/browser/main/Detail/StarButton.js @@ -46,14 +46,14 @@ class StarButton extends React.Component { onMouseDown={(e) => this.handleMouseDown(e)} onMouseUp={(e) => this.handleMouseUp(e)} onMouseLeave={(e) => this.handleMouseLeave(e)} - onClick={this.props.onClick} - > + onClick={this.props.onClick}> + Star ) } diff --git a/browser/main/Detail/StarButton.styl b/browser/main/Detail/StarButton.styl index 1e5bf239..647f3f23 100644 --- a/browser/main/Detail/StarButton.styl +++ b/browser/main/Detail/StarButton.styl @@ -4,6 +4,22 @@ &:hover transition 0.2s color alpha($ui-favorite-star-button-color, 0.6) + &:hover .tooltip + opacity 1 + +.tooltip + tooltip() + position absolute + pointer-events none + top 26px + right 0 + width 100% + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s .root--active @extend .root diff --git a/browser/main/Detail/ToggleModeButton.js b/browser/main/Detail/ToggleModeButton.js new file mode 100644 index 00000000..5a78cc51 --- /dev/null +++ b/browser/main/Detail/ToggleModeButton.js @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './ToggleModeButton.styl' + +const ToggleModeButton = ({ + onClick, editorType +}) => ( +
+
onClick('SPLIT')}> + +
+
onClick('EDITOR_PREVIEW')}> + +
+ Toggle Mode +
+) + +ToggleModeButton.propTypes = { + onClick: PropTypes.func.isRequired, + editorType: PropTypes.string.Required +} + +export default CSSModules(ToggleModeButton, styles) diff --git a/browser/main/Detail/ToggleModeButton.styl b/browser/main/Detail/ToggleModeButton.styl new file mode 100644 index 00000000..de4303f2 --- /dev/null +++ b/browser/main/Detail/ToggleModeButton.styl @@ -0,0 +1,41 @@ +.control-toggleModeButton + + border 1px solid #eee + height 34px + display flex + align-items center + + div + width 40px + height 100% + background-color #f9f9f9 + display flex + align-items center + justify-content center + cursor pointer + + &:first-child + border-right 1px solid #eee + .active + background-color #fff + box-shadow 2px 0px 7px #eee + z-index 1 + &:hover .tooltip + opacity 1 + +.tooltip + tooltip() + position absolute + pointer-events none + top 47px + right 11px + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s + +body[data-theme="dark"] + .control-fullScreenButton + topBarButtonDark() \ No newline at end of file diff --git a/browser/main/Detail/TrashButton.js b/browser/main/Detail/TrashButton.js index bfaafe1e..474eb9e5 100644 --- a/browser/main/Detail/TrashButton.js +++ b/browser/main/Detail/TrashButton.js @@ -10,6 +10,7 @@ const TrashButton = ({ onClick={(e) => onClick(e)} > + Trash ) diff --git a/browser/main/Detail/TrashButton.styl b/browser/main/Detail/TrashButton.styl index 0acd60a5..455d36a6 100644 --- a/browser/main/Detail/TrashButton.styl +++ b/browser/main/Detail/TrashButton.styl @@ -1,6 +1,21 @@ .control-trashButton top 115px topBarButtonRight() + &:hover .tooltip + opacity 1 + +.tooltip + tooltip() + position absolute + pointer-events none + top 26px + right 0 + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s .control-trashButton--in-trash top 60px diff --git a/browser/main/SideNav/ListButton.js b/browser/main/SideNav/ListButton.js new file mode 100644 index 00000000..1365c4cb --- /dev/null +++ b/browser/main/SideNav/ListButton.js @@ -0,0 +1,24 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './SwitchButton.styl' + +const ListButton = ({ + onClick, isTagActive +}) => ( + +) + +ListButton.propTypes = { + onClick: PropTypes.func.isRequired, + isTagActive: PropTypes.bool.isRequired +} + +export default CSSModules(ListButton, styles) diff --git a/browser/main/SideNav/PreferenceButton.js b/browser/main/SideNav/PreferenceButton.js new file mode 100644 index 00000000..9f483a28 --- /dev/null +++ b/browser/main/SideNav/PreferenceButton.js @@ -0,0 +1,19 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './PreferenceButton.styl' + +const PreferenceButton = ({ + onClick +}) => ( + +) + +PreferenceButton.propTypes = { + onClick: PropTypes.func.isRequired +} + +export default CSSModules(PreferenceButton, styles) diff --git a/browser/main/SideNav/PreferenceButton.styl b/browser/main/SideNav/PreferenceButton.styl new file mode 100644 index 00000000..97a48982 --- /dev/null +++ b/browser/main/SideNav/PreferenceButton.styl @@ -0,0 +1,51 @@ +.top-menu-preference + navButtonColor() + position absolute + top 22px + right 10px + width 2em + background-color transparent + &:hover + color $ui-button-default--active-backgroundColor + background-color transparent + .tooltip + opacity 1 + &:active, &:active:hover + color $ui-button-default--active-backgroundColor + +body[data-theme="white"] + .top-menu-preference + navWhiteButtonColor() + background-color transparent + &:hover + color #0B99F1 + background-color transparent + &:active, &:active:hover + color #0B99F1 + background-color transparent + +body[data-theme="dark"] + .top-menu-preference + navDarkButtonColor() + background-color transparent + &:active + background-color alpha($ui-dark-button--active-backgroundColor, 20%) + background-color transparent + &:hover + background-color alpha($ui-dark-button--active-backgroundColor, 20%) + background-color transparent + + + +.tooltip + tooltip() + position absolute + pointer-events none + top 26px + left -20px + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s \ No newline at end of file diff --git a/browser/main/SideNav/SideNav.styl b/browser/main/SideNav/SideNav.styl index 474b1af3..a0ffb2e7 100644 --- a/browser/main/SideNav/SideNav.styl +++ b/browser/main/SideNav/SideNav.styl @@ -11,19 +11,6 @@ .top padding-bottom 15px -.top-menu-preference - navButtonColor() - position absolute - top 22px - right 10px - width 2em - background-color transparent - &:hover - color $ui-button-default--active-backgroundColor - background-color transparent - &:active, &:active:hover - color $ui-button-default--active-backgroundColor - .switch-buttons background-color transparent border 0 @@ -31,21 +18,7 @@ display flex text-align center -.non-active-button - color $ui-inactive-text-color - font-size 16px - border 0 - background-color transparent - transition 0.2s - display flex - text-align center - margin-right 4px; - &:hover - color alpha(#239F86, 60%) -.active-button - @extend .non-active-button - color $ui-button-default--active-backgroundColor .top-menu-label margin-left 5px @@ -109,33 +82,6 @@ body[data-theme="white"] background-color #f9f9f9 color $ui-text-color - .top-menu-preference - navWhiteButtonColor() - background-color transparent - &:hover - color #0B99F1 - background-color transparent - &:active, &:active:hover - color #0B99F1 - background-color transparent - - .non-active-button - color $ui-inactive-text-color - &:hover - color alpha(#0B99F1, 60%) - - .tag-title - p - color $ui-text-color - - .non-active-button - &:hover - color alpha(#0B99F1, 60%) - - .active-button - @extend .non-active-button - color #0B99F1 - body[data-theme="dark"] .root, .root--folded border-right 1px solid $ui-dark-borderColor @@ -145,25 +91,6 @@ body[data-theme="dark"] .top border-color $ui-dark-borderColor - .top-menu-preference - navDarkButtonColor() - background-color transparent - &:active - background-color alpha($ui-dark-button--active-backgroundColor, 20%) - background-color transparent - &:hover - background-color alpha($ui-dark-button--active-backgroundColor, 20%) - background-color transparent - - .non-active-button - color alpha($ui-dark-text-color, 60%) - &:hover - color alpha(#0B99F1, 60%) - - .tag-title - p - color alpha($ui-dark-text-color, 60%) - body[data-theme="solarized-dark"] .root, .root--folded background-color $ui-solarized-dark-backgroundColor diff --git a/browser/main/SideNav/SwitchButton.styl b/browser/main/SideNav/SwitchButton.styl new file mode 100644 index 00000000..54e21b03 --- /dev/null +++ b/browser/main/SideNav/SwitchButton.styl @@ -0,0 +1,59 @@ +.non-active-button + color $ui-inactive-text-color + font-size 16px + border 0 + background-color transparent + transition 0.2s + display flex + text-align center + margin-right 4px + position relative + &:hover + color alpha(#239F86, 60%) + .tooltip + opacity 1 + +.active-button + @extend .non-active-button + color $ui-button-default--active-backgroundColor + +.tooltip + tooltip() + position absolute + pointer-events none + top 22px + left -2px + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s + +body[data-theme="white"] + .non-active-button + color $ui-inactive-text-color + &:hover + color alpha(#0B99F1, 60%) + + .tag-title + p + color $ui-text-color + + .non-active-button + &:hover + color alpha(#0B99F1, 60%) + + .active-button + @extend .non-active-button + color #0B99F1 + +body[data-theme="dark"] + .non-active-button + color alpha($ui-dark-text-color, 60%) + &:hover + color alpha(#0B99F1, 60%) + + .tag-title + p + color alpha($ui-dark-text-color, 60%) \ No newline at end of file diff --git a/browser/main/SideNav/TagButton.js b/browser/main/SideNav/TagButton.js new file mode 100644 index 00000000..87d92c49 --- /dev/null +++ b/browser/main/SideNav/TagButton.js @@ -0,0 +1,24 @@ +import PropTypes from 'prop-types' +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './SwitchButton.styl' + +const TagButton = ({ + onClick, isTagActive +}) => ( + +) + +TagButton.propTypes = { + onClick: PropTypes.func.isRequired, + isTagActive: PropTypes.bool.isRequired +} + +export default CSSModules(TagButton, styles) diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 05361ea4..4c162f1e 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -11,6 +11,9 @@ import SideNavFilter from 'browser/components/SideNavFilter' import StorageList from 'browser/components/StorageList' import NavToggleButton from 'browser/components/NavToggleButton' import EventEmitter from 'browser/main/lib/eventEmitter' +import PreferenceButton from './PreferenceButton' +import ListButton from './ListButton' +import TagButton from './TagButton' class SideNav extends React.Component { // TODO: should not use electron stuff v0.7 @@ -162,27 +165,11 @@ class SideNav extends React.Component { >
- - + +
- +
{this.SideNavComponent(isFolded, storageList)} From bdf55568c7039f6dfe2ddb4a7adf387741512644 Mon Sep 17 00:00:00 2001 From: Kohei TAKATA Date: Sat, 23 Dec 2017 12:03:28 +0900 Subject: [PATCH 38/50] v0.8.19 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f1f8aa0c..0b16a7ab 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "boost", "productName": "Boostnote", - "version": "0.8.18", + "version": "0.8.19", "main": "index.js", "description": "Boostnote", "license": "GPL-3.0", From 974a1a1e7d99770f015ef9de885e7aef0ce98184 Mon Sep 17 00:00:00 2001 From: Kazu Yokomizo Date: Sat, 23 Dec 2017 15:18:16 +0900 Subject: [PATCH 39/50] Fix style --- browser/main/Detail/ToggleModeButton.styl | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/browser/main/Detail/ToggleModeButton.styl b/browser/main/Detail/ToggleModeButton.styl index de4303f2..b9d3cc6c 100644 --- a/browser/main/Detail/ToggleModeButton.styl +++ b/browser/main/Detail/ToggleModeButton.styl @@ -1,5 +1,4 @@ .control-toggleModeButton - border 1px solid #eee height 34px display flex @@ -38,4 +37,25 @@ body[data-theme="dark"] .control-fullScreenButton - topBarButtonDark() \ No newline at end of file + topBarButtonDark() + + .control-toggleModeButton + border 1px solid #444444 + div + background-color $ui-dark-noteDetail-backgroundColor + &:first-child + border-right 1px solid #444444 + .active + background-color #3A404C + box-shadow 2px 0px 7px #444444 + +body[data-theme="solarized-dark"] + .control-toggleModeButton + border 1px solid #586E75 + div + background-color $ui-solarized-dark-noteDetail-backgroundColor + &:first-child + border-right 1px solid #586E75 + .active + background-color #002B36 + box-shadow 2px 0px 7px #222222 \ No newline at end of file From 04ffbe945b09412b145b3b1b1317b3e020c18daa Mon Sep 17 00:00:00 2001 From: Kazu Yokomizo Date: Sat, 23 Dec 2017 15:25:45 +0900 Subject: [PATCH 40/50] Delete unnecessary style --- browser/main/Detail/MarkdownNoteDetail.styl | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/browser/main/Detail/MarkdownNoteDetail.styl b/browser/main/Detail/MarkdownNoteDetail.styl index 3357c6ef..25b6f2da 100644 --- a/browser/main/Detail/MarkdownNoteDetail.styl +++ b/browser/main/Detail/MarkdownNoteDetail.styl @@ -49,27 +49,8 @@ body[data-theme="dark"] .control-fullScreenButton topBarButtonDark() - .mode-tab - border 1px solid #444444 - div - background-color $ui-dark-noteDetail-backgroundColor - &:first-child - border-right 1px solid #444444 - .active - background-color #3A404C - box-shadow 2px 0px 7px #444444 body[data-theme="solarized-dark"] .root border-left 1px solid $ui-solarized-dark-borderColor background-color $ui-solarized-dark-noteDetail-backgroundColor - - .mode-tab - border 1px solid #586E75 - div - background-color $ui-solarized-dark-noteDetail-backgroundColor - &:first-child - border-right 1px solid #586E75 - .active - background-color #002B36 - box-shadow 2px 0px 7px #222222 \ No newline at end of file From 4f7026969f757349b183b51d58ccae54aabbaf6d Mon Sep 17 00:00:00 2001 From: Rob Weber Date: Sat, 23 Dec 2017 01:33:03 -0800 Subject: [PATCH 41/50] Fix linking to other notes --- browser/main/NoteList/index.js | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index b54b0661..083eb75f 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -235,18 +235,8 @@ class NoteList extends React.Component { return } - const { router } = this.context - const { location } = this.props - - let targetIndex = this.getTargetIndex() - - if (targetIndex < 0) targetIndex = 0 - - const selectedNoteKeys = [] - const nextNoteKey = this.getNoteKeyFromTargetIndex(targetIndex) - selectedNoteKeys.push(nextNoteKey) - - this.focusNote(selectedNoteKeys, nextNoteKey) + const selectedNoteKeys = [noteHash] + this.focusNote(selectedNoteKeys, noteHash) ee.emit('list:moved') } From bf781c6b50b5664362a872d33241637a10a03c49 Mon Sep 17 00:00:00 2001 From: Niko Caron Date: Sat, 23 Dec 2017 18:17:48 -0400 Subject: [PATCH 42/50] Fix starred item count * Deleting a starred item will now update the starred count in the side nav. (delete from starred set) * Restoring a starred item will add it the the starred set again. Fix: #1326 --- browser/main/store.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/browser/main/store.js b/browser/main/store.js index 647d0ac9..038b2b53 100644 --- a/browser/main/store.js +++ b/browser/main/store.js @@ -87,8 +87,13 @@ function data (state = defaultDataMap(), action) { state.trashedSet = new Set(state.trashedSet) if (note.isTrashed) { state.trashedSet.add(uniqueKey) + state.starredSet.delete(uniqueKey) } else { state.trashedSet.delete(uniqueKey) + + if (note.isStarred) { + state.starredSet.add(uniqueKey) + } } } From e82e2c71f149a6e20e071b39a22fca200fd6eaa8 Mon Sep 17 00:00:00 2001 From: Kazz Yokomizo Date: Thu, 28 Dec 2017 10:44:07 +0900 Subject: [PATCH 43/50] Update readme --- readme.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/readme.md b/readme.md index 9d64bf5d..4b571fa0 100644 --- a/readme.md +++ b/readme.md @@ -1,6 +1,4 @@ -New:zap: - -Open sourcing our [Android and iOS apps](https://github.com/BoostIO/Boostnote-mobile)! +:mega: Open sourcing our [Android and iOS apps](https://github.com/BoostIO/Boostnote-mobile)! ![Boostnote app screenshot](./resources/repository/top.png) @@ -12,7 +10,6 @@ Open sourcing our [Android and iOS apps](https://github.com/BoostIO/Boostnote-mo ## Authors & Maintainers - [Rokt33r](https://github.com/rokt33r) -- [sota1235](https://github.com/sota1235) - [Kohei TAKATA](https://github.com/kohei-takata) - [Sosuke](https://github.com/sosukesuzuki) - [Kazz](https://github.com/kazup01) @@ -29,7 +26,7 @@ Boostnote is an open source project. It's an independent project with its ongoin ## Community - [Facebook Group](https://www.facebook.com/groups/boostnote/) - [Twitter](https://twitter.com/boostnoteapp) -- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMjc2MDM0MDEyODk2LThlZDlhYmYwMjdkMmJjMGM5MGFiMGJmNzk5ZTdhNzFhMmNmMDFlY2M2YTE1MTZkOThiOGZmNTI3YzJiOTBhMTQ) +- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMjkxMzMwODYxMDI1LTgwZmRiODg0NzA5MWRmOTJjNzBjZjAwMmMyZGQ4Y2RkOGE0MDg0YjcyMjA5OGUzMmZhNmFiNTMzOTlkYWNlMTM) - [Blog](https://medium.com/boostnote) - [Reddit](https://www.reddit.com/r/Boostnote/) From ed1eab7fcce3ec8e47a4880cb38d929f0f722e48 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Thu, 28 Dec 2017 22:48:59 +0900 Subject: [PATCH 44/50] add table style in solarized-dark-theme --- browser/components/markdown.styl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl index 0600d9ab..5ff05941 100644 --- a/browser/components/markdown.styl +++ b/browser/components/markdown.styl @@ -336,8 +336,29 @@ body[data-theme="dark"] background-color themeDarkBorder color themeDarkText +themeSolarizedDarkTableOdd = $ui-solarized-dark-noteDetail-backgroundColor +themeSolarizedDarkTableEven = darken($ui-solarized-dark-noteDetail-backgroundColor, 10%) +themeSolarizedDarkTableHead = themeSolarizedDarkTableEven +themeSolarizedDarkTableBorder = themeDarkBorder body[data-theme="solarized-dark"] color $ui-solarized-dark-text-color border-color themeDarkBorder background-color $ui-solarized-dark-noteDetail-backgroundColor + table + thead + tr + background-color themeSolarizedDarkTableHead + th + border-color themeSolarizedDarkTableBorder + &:last-child + border-right solid 1px themeSolarizedDarkTableBorder + tbody + tr:nth-child(2n + 1) + background-color themeSolarizedDarkTableOdd + tr:nth-child(2n) + background-color themeSolarizedDarkTableEven + td + border-color themeSolarizedDarkTableBorder + &:last-child + border-right solid 1px themeSolarizedDarkTableBorder From d732d195f3c29ab92e506f5152fb7229d382f22b Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Fri, 29 Dec 2017 21:38:40 +0900 Subject: [PATCH 45/50] fix style --- browser/main/Detail/InfoPanel.styl | 56 +++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/browser/main/Detail/InfoPanel.styl b/browser/main/Detail/InfoPanel.styl index a115d108..72b07c87 100644 --- a/browser/main/Detail/InfoPanel.styl +++ b/browser/main/Detail/InfoPanel.styl @@ -41,12 +41,12 @@ box-shadow 2px 12px 15px 2px rgba(0, 0, 0, 0.1), 2px 1px 50px 2px rgba(0, 0, 0, 0.1) border-radius 2px -.count-wrap +.count-wrap display flex position relative width 100% -.count-number +.count-number position relative display block width 50% @@ -81,15 +81,15 @@ margin-bottom 6px .infoPanel-trash - color #EA4447 - font-weight 600 + color #EA4447 + font-weight 600 font-size 14px width 70px background-color rgba(226,33,113,0.1) - border none + border none outline none - border-radius 2px - margin-right 5px + border-radius 2px + margin-right 5px padding 2px 5px [id=export-wrap] @@ -160,4 +160,44 @@ body[data-theme="dark"] p color $ui-dark-inactive-text-color &:hover - color $ui-dark-text-color \ No newline at end of file + color $ui-dark-text-color + +body[data-theme="solarized-dark"] + .control-infoButton-panel + background-color $ui-solarized-dark-noteList-backgroundColor + + .control-infoButton-panel-trash + background-color $ui-solarized-ark-noteList-backgroundColor + + .modification-date + color $ui-solarized-ark-text-color + + .modification-date-desc + color $ui-inactive-text-color + + .infoPanel-defaul-count + color $ui-solarized-dark-text-color + + .infoPanel-sub-count + color $ui-inactive-text-color + + .infoPanel-default + color $ui-solarized-ark-text-color + + .infoPanel-sub + color $ui-inactive-text-color + + .infoPanel-noteLink + background-color alpha($ui-solarized-dark-borderColor, 20%) + color $ui-solarized-dark-text-color + + [id=export-wrap] + button + color $ui-dark-inactive-text-color + &:hover + background-color alpha($ui-solarized-dark-borderColor, 20%) + color $ui-solarized-ark-text-color + p + color $ui-dark-inactive-text-color + &:hover + color $ui-solarized-ark-text-color From c8b97ffde3172a36892e43f72e9532a99428e556 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Sat, 30 Dec 2017 11:04:13 +0900 Subject: [PATCH 46/50] pass fontSize and indentSize to CodeEditor as props --- browser/components/MarkdownSplitEditor.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index b77c0b6b..0ea41a44 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -45,6 +45,10 @@ class MarkdownSplitEditor extends React.Component { render () { const { config, value, storageKey } = this.props const storage = findStorage(storageKey) + let editorFontSize = parseInt(config.editor.fontSize, 10) + if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14 + let editorIndentSize = parseInt(config.editor.indentSize, 10) + if (!(editorFontSize > 0 && editorFontSize < 132)) editorIndentSize = 4 const previewStyle = {} if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none' return ( @@ -57,7 +61,9 @@ class MarkdownSplitEditor extends React.Component { theme={config.editor.theme} keyMap={config.editor.keyMap} fontFamily={config.editor.fontFamily} + fontSize={editorFontSize} indentType={config.editor.indentType} + indentSize={editorIndentSize} scrollPastEnd={config.editor.scrollPastEnd} storageKey={storageKey} onChange={this.handleOnChange.bind(this)} From b4e138e21bde4a3b84d72a8ba1305cfaf53b8847 Mon Sep 17 00:00:00 2001 From: Anthony Graham Date: Mon, 1 Jan 2018 14:20:23 +0000 Subject: [PATCH 47/50] Elixir Syntax Highlighting --- browser/components/CodeEditor.js | 1 + browser/components/MarkdownPreview.js | 1 + browser/finder/NoteDetail.js | 1 + browser/lib/customMeta.js | 2 ++ browser/main/Detail/SnippetNoteDetail.js | 3 ++- browser/main/modals/PreferencesModal/UiTab.js | 1 + lib/finder.html | 1 + lib/main.html | 1 + package.json | 1 + 9 files changed, 11 insertions(+), 1 deletion(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index b5e06a66..a6a96a74 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types' import React from 'react' import _ from 'lodash' import CodeMirror from 'codemirror' +import 'codemirror-mode-elixir' import path from 'path' import copyImage from 'browser/main/lib/dataApi/copyImage' import { findStorage } from 'browser/lib/findStorage' diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index 06354b37..c1be9ef1 100644 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -3,6 +3,7 @@ import React from 'react' import markdown from 'browser/lib/markdown' import _ from 'lodash' import CodeMirror from 'codemirror' +import 'codemirror-mode-elixir' import consts from 'browser/lib/consts' import Raphael from 'raphael' import flowchart from 'flowchart' diff --git a/browser/finder/NoteDetail.js b/browser/finder/NoteDetail.js index 4c59ea30..3b9121d7 100644 --- a/browser/finder/NoteDetail.js +++ b/browser/finder/NoteDetail.js @@ -5,6 +5,7 @@ import MarkdownPreview from 'browser/components/MarkdownPreview' import MarkdownEditor from 'browser/components/MarkdownEditor' import CodeEditor from 'browser/components/CodeEditor' import CodeMirror from 'codemirror' +import 'codemirror-mode-elixir' import { findStorage } from 'browser/lib/findStorage' const electron = require('electron') diff --git a/browser/lib/customMeta.js b/browser/lib/customMeta.js index 855e00af..0d4ee1e3 100644 --- a/browser/lib/customMeta.js +++ b/browser/lib/customMeta.js @@ -1,3 +1,5 @@ import CodeMirror from 'codemirror' +import 'codemirror-mode-elixir' CodeMirror.modeInfo.push({name: 'Stylus', mime: 'text/x-styl', mode: 'stylus', ext: ['styl'], alias: ['styl']}) +CodeMirror.modeInfo.push({name: 'Elixir', mime: 'text/x-elixir', mode: 'elixir', ext: ['ex']}) diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index 5a346fc7..218b4f87 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -11,6 +11,7 @@ import dataApi from 'browser/main/lib/dataApi' import { hashHistory } from 'react-router' import ee from 'browser/main/lib/eventEmitter' import CodeMirror from 'codemirror' +import 'codemirror-mode-elixir' import SnippetTab from 'browser/components/SnippetTab' import StatusBar from '../StatusBar' import context from 'browser/lib/context' @@ -380,7 +381,7 @@ class SnippetNoteDetail extends React.Component { handleModeButtonClick (e, index) { const menu = new Menu() - CodeMirror.modeInfo.forEach((mode) => { + CodeMirror.modeInfo.sort(function (a, b) { return a.name.localeCompare(b.name) }).forEach((mode) => { menu.append(new MenuItem({ label: mode.name, click: (e) => this.handleModeOptionClick(index, mode.name)(e) diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index a1bab45b..c79329d0 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -7,6 +7,7 @@ import store from 'browser/main/store' import consts from 'browser/lib/consts' import ReactCodeMirror from 'react-codemirror' import CodeMirror from 'codemirror' +import 'codemirror-mode-elixir' import _ from 'lodash' const OSX = global.process.platform === 'darwin' diff --git a/lib/finder.html b/lib/finder.html index f0ac3df5..c6ad502e 100644 --- a/lib/finder.html +++ b/lib/finder.html @@ -28,6 +28,7 @@ + diff --git a/lib/main.html b/lib/main.html index 69a47900..d7936628 100644 --- a/lib/main.html +++ b/lib/main.html @@ -69,6 +69,7 @@ + diff --git a/package.json b/package.json index 0b16a7ab..f38e8958 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "aws-sdk": "^2.48.0", "aws-sdk-mobile-analytics": "^0.9.2", "codemirror": "^5.19.0", + "codemirror-mode-elixir": "^1.1.1", "electron-config": "^0.2.1", "electron-gh-releases": "^2.0.2", "flowchart.js": "^1.6.5", From 297b4346c5070167ec1b03efe50323b6b5450c88 Mon Sep 17 00:00:00 2001 From: Kazu Yokomizo Date: Thu, 4 Jan 2018 03:51:49 +0900 Subject: [PATCH 48/50] Fix CI error at #1147 --- browser/main/SideNav/StorageItem.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index 2bcbe050..bbf87306 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -10,7 +10,7 @@ import dataApi from 'browser/main/lib/dataApi' import StorageItemChild from 'browser/components/StorageItem' import eventEmitter from 'browser/main/lib/eventEmitter' import _ from 'lodash' -import * as path from 'path' +import * as path from 'path' const { remote } = require('electron') const { Menu, MenuItem, dialog } = remote From e4e8c2205ea4885504198cc9d3d601a2875d3eb3 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Thu, 4 Jan 2018 18:12:27 +0900 Subject: [PATCH 49/50] splid update functions --- browser/main/Detail/MarkdownNoteDetail.js | 27 ++++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index e513696b..15c584d4 100644 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -79,17 +79,22 @@ class MarkdownNoteDetail extends React.Component { ee.off('topbar:togglelockbutton', this.toggleLockButton) } - handleChange (e) { + handleUpdateTag () { const { note } = this.state - - note.content = this.refs.content.value if (this.refs.tags) note.tags = this.refs.tags.value - note.title = markdown.strip(striptags(findNoteTitle(note.content))) - note.updatedAt = new Date() + this.updateNote(note) + } - this.setState({ - note - }, () => { + handleUpdateContent () { + const { note } = this.state + note.content = this.refs.content.value + note.title = markdown.strip(striptags(findNoteTitle(note.content))) + this.updateNote(note) + } + + updateNote (note) { + note.updatedAt = new Date() + this.setState({note}, () => { this.save() }) } @@ -289,7 +294,7 @@ class MarkdownNoteDetail extends React.Component { config={config} value={note.content} storageKey={note.storage} - onChange={(e) => this.handleChange(e)} + onChange={this.handleUpdateContent.bind(this)} ignorePreviewPointerEvents={ignorePreviewPointerEvents} /> } else { @@ -298,7 +303,7 @@ class MarkdownNoteDetail extends React.Component { config={config} value={note.content} storageKey={note.storage} - onChange={(e) => this.handleChange(e)} + onChange={this.handleUpdateContent.bind(this)} ignorePreviewPointerEvents={ignorePreviewPointerEvents} /> } @@ -359,7 +364,7 @@ class MarkdownNoteDetail extends React.Component { this.handleChange(e)} + onChange={this.handleUpdateTag.bind(this)} /> this.handleSwitchMode(e)} editorType={editorType} /> From 9cd1d4b466905e586d5336a367a56b73304af88d Mon Sep 17 00:00:00 2001 From: Marcus Stenbeck Date: Fri, 5 Jan 2018 10:54:48 +0100 Subject: [PATCH 50/50] fix(code-editor): use correct prop for font family --- 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 a6a96a74..28fc9b1f 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -250,7 +250,7 @@ export default class CodeEditor extends React.Component { render () { const { className, fontSize } = this.props - let fontFamily = this.props.className + let fontFamily = this.props.fontFamily fontFamily = _.isString(fontFamily) && fontFamily.length > 0 ? [fontFamily].concat(defaultEditorFontFamily) : defaultEditorFontFamily