diff --git a/browser/main/lib/dataApi/createSnippet.js b/browser/main/lib/dataApi/createSnippet.js index d2847ae4..0c6cd648 100644 --- a/browser/main/lib/dataApi/createSnippet.js +++ b/browser/main/lib/dataApi/createSnippet.js @@ -1,19 +1,22 @@ import fs from 'fs' import crypto from 'crypto' import consts from 'browser/lib/consts' +import fetchSnippet from 'browser/main/lib/dataApi/fetchSnippet' -function createSnippet (snippets) { +function createSnippet () { return new Promise((resolve, reject) => { - const newSnippet = { - id: crypto.randomBytes(16).toString('hex'), - name: 'Unnamed snippet', - prefix: [], - content: '' - } - snippets.push(newSnippet) - fs.writeFile(consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => { - if (err) reject(err) - resolve(snippets) + fetchSnippet().then((snippets) => { + const newSnippet = { + id: crypto.randomBytes(16).toString('hex'), + name: 'Unnamed snippet', + prefix: [], + content: '' + } + snippets.push(newSnippet) + fs.writeFile(consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => { + if (err) reject(err) + resolve(newSnippet) + }) }) }) } diff --git a/browser/main/lib/dataApi/deleteSnippet.js b/browser/main/lib/dataApi/deleteSnippet.js index 17587b5f..d8d9c68a 100644 --- a/browser/main/lib/dataApi/deleteSnippet.js +++ b/browser/main/lib/dataApi/deleteSnippet.js @@ -1,17 +1,16 @@ import fs from 'fs' import consts from 'browser/lib/consts' +import fetchSnippet from 'browser/main/lib/dataApi/fetchSnippet' -function deleteSnippet (snippets, snippetId) { +function deleteSnippet (snippet) { return new Promise((resolve, reject) => { - for (let i = 0; i < snippets.length; i++) { - if (snippets[i].id === snippetId) { - snippets.splice(i, 1) - fs.writeFile(consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => { - if (err) reject(err) - resolve(snippets) - }) - } - } + fetchSnippet().then((snippets) => { + snippets = snippets.filter(currentSnippet => currentSnippet.id !== snippet.id) + fs.writeFile(consts.SNIPPET_FILE, JSON.stringify(snippets, null, 4), (err) => { + if (err) reject(err) + resolve(snippet) + }) + }) }) } diff --git a/browser/main/lib/dataApi/fetchSnippet.js b/browser/main/lib/dataApi/fetchSnippet.js new file mode 100644 index 00000000..ff5d86d5 --- /dev/null +++ b/browser/main/lib/dataApi/fetchSnippet.js @@ -0,0 +1,21 @@ +import fs from 'fs' +import crypto from 'crypto' +import consts from 'browser/lib/consts' + +function fetchSnippet (id) { + return new Promise((resolve, reject) => { + fs.readFile(consts.SNIPPET_FILE, 'utf8', (err, data) => { + if (err) { + reject(err) + } + const snippets = JSON.parse(data) + if (id) { + const snippet = snippets.find(snippet => { return snippet.id === id }) + resolve(snippet) + } + resolve(snippets) + }) + }) +} + +module.exports = fetchSnippet \ No newline at end of file diff --git a/browser/main/lib/dataApi/index.js b/browser/main/lib/dataApi/index.js index bf42e8ec..7c57e016 100644 --- a/browser/main/lib/dataApi/index.js +++ b/browser/main/lib/dataApi/index.js @@ -16,6 +16,7 @@ const dataApi = { createSnippet: require('./createSnippet'), deleteSnippet: require('./deleteSnippet'), updateSnippet: require('./updateSnippet'), + fetchSnippet: require('./fetchSnippet'), _migrateFromV6Storage: require('./migrateFromV6Storage'), _resolveStorageData: require('./resolveStorageData'), diff --git a/browser/main/modals/PreferencesModal/SnippetEditor.js b/browser/main/modals/PreferencesModal/SnippetEditor.js index 20b1f66a..f0368c5d 100644 --- a/browser/main/modals/PreferencesModal/SnippetEditor.js +++ b/browser/main/modals/PreferencesModal/SnippetEditor.js @@ -12,6 +12,7 @@ const buildCMRulers = (rulers, enableRulers) => export default class SnippetEditor extends React.Component { componentDidMount () { + this.props.onRef(this) const { rulers, enableRulers } = this.props this.cm = CodeMirror(this.refs.root, { rulers: buildCMRulers(rulers, enableRulers), @@ -29,9 +30,6 @@ export default class SnippetEditor extends React.Component { autoCloseBrackets: true }) this.cm.setSize('100%', '100%') - this.snippet = this.props.snippet - const snippetId = this.snippet.id - this.loadSnippet(snippetId) let changeDelay = null this.cm.on('change', () => { @@ -44,32 +42,25 @@ export default class SnippetEditor extends React.Component { }) } + componentWillUnmount () { + this.props.onRef(undefined) + } + + onSnippetChanged (newSnippet) { + this.snippet = newSnippet + this.cm.setValue(this.snippet.content) + } + + onSnippetNameOrPrefixChanged (newSnippet) { + this.snippet.name = newSnippet.name + this.snippet.prefix = newSnippet.prefix.toString().replace(/\s/g, '').split(',') + this.saveSnippet() + } + saveSnippet () { dataApi.updateSnippet(this.snippet).catch((err) => { throw err }) } - loadSnippet (snippetId) { - const snippets = JSON.parse(fs.readFileSync(consts.SNIPPET_FILE, 'utf8')) - - for (let i = 0; i < snippets.length; i++) { - if (snippets[i].id === snippetId) { - this.cm.setValue(snippets[i].content) - } - } - } - - componentWillReceiveProps (newProps) { - if (this.snippet.id !== newProps.snippet.id) { - // when user changed to a new snippet on the snippetList.js - this.loadSnippet(newProps.snippet.id) - } else { - // when snippet name or prefix being changed from snippetTab.js - this.snippet.name = newProps.snippet.name - this.snippet.prefix = newProps.snippet.prefix.replace(/\s/g, '').split(/\,/).filter(val => val) - this.saveSnippet() - } - } - render () { const { fontSize } = this.props let fontFamily = this.props.fontFamily diff --git a/browser/main/modals/PreferencesModal/SnippetTab.js b/browser/main/modals/PreferencesModal/SnippetTab.js index 9cb870e4..d2bf80e2 100644 --- a/browser/main/modals/PreferencesModal/SnippetTab.js +++ b/browser/main/modals/PreferencesModal/SnippetTab.js @@ -19,18 +19,30 @@ class SnippetTab extends React.Component { snippets: [], currentSnippet: null } + this.changeDelay = null } componentDidMount () { - this.snippets = JSON.parse(fs.readFileSync(consts.SNIPPET_FILE, 'utf8')) - - this.setState({snippets: this.snippets}) + this.reloadSnippetList() } handleSnippetClick (snippet) { - const currentSnippet = Object.assign({}, snippet) - currentSnippet.prefix = currentSnippet.prefix.join(', ') - this.setState({currentSnippet}) + if (this.state.currentSnippet === null || this.state.currentSnippet.id !== snippet.id) { + dataApi.fetchSnippet(snippet.id).then(changedSnippet => { + // notify the snippet editor to load the content of the new snippet + this.snippetEditor.onSnippetChanged(changedSnippet) + this.setState({currentSnippet: changedSnippet}) + }) + } + } + + handleSnippetNameOrPrefixChange () { + clearTimeout(this.changeDelay) + this.changeDelay = setTimeout(() => { + // notify the snippet editor that the name or prefix of snippet has been changed + this.snippetEditor.onSnippetNameOrPrefixChanged(this.state.currentSnippet) + this.reloadSnippetList() + }, 500) } handleSnippetContextMenu (snippet) { @@ -38,23 +50,25 @@ class SnippetTab extends React.Component { menu.append(new MenuItem({ label: i18n.__('Delete snippet'), click: () => { - this.deleteSnippet(snippet.id) + this.deleteSnippet(snippet) } })) menu.popup() } - deleteSnippet (id) { - dataApi.deleteSnippet(this.snippets, id).then((snippets) => { - this.snippets = snippets - this.setState(this.snippets) + reloadSnippetList () { + dataApi.fetchSnippet().then(snippets => this.setState({snippets})) + } + + deleteSnippet (snippet) { + dataApi.deleteSnippet(snippet).then(() => { + this.reloadSnippetList() }).catch(err => { throw err }) } createSnippet () { - dataApi.createSnippet(this.snippets).then((snippets) => { - this.snippets = snippets - this.setState(this.snippets) + dataApi.createSnippet().then(() => { + this.reloadSnippetList() // scroll to end of list when added new snippet const snippetList = document.getElementById('snippets') snippetList.scrollTop = snippetList.scrollHeight @@ -100,17 +114,18 @@ class SnippetTab extends React.Component { {this.renderSnippetList()} - {this.state.currentSnippet ?
+
{i18n.__('Snippet name')}
{ const newSnippet = Object.assign({}, this.state.currentSnippet) newSnippet.name = e.target.value this.setState({ currentSnippet: newSnippet }) + this.handleSnippetNameOrPrefixChange() }} type='text' />
@@ -120,11 +135,12 @@ class SnippetTab extends React.Component {
{ const newSnippet = Object.assign({}, this.state.currentSnippet) newSnippet.prefix = e.target.value this.setState({ currentSnippet: newSnippet }) + this.handleSnippetNameOrPrefixChange() }} type='text' />
@@ -142,10 +158,9 @@ class SnippetTab extends React.Component { rulers={config.editor.rulers} displayLineNumbers={config.editor.displayLineNumbers} scrollPastEnd={config.editor.scrollPastEnd} - snippet={this.state.currentSnippet} /> + onRef={ref => this.snippetEditor = ref} />
- : ''}
) }