diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index f3913e48..e4298a71 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -517,9 +517,20 @@ export default class MarkdownPreview extends React.Component { handlelinkClick (e) { const noteHash = e.target.href.split('/').pop() - const regexIsNoteLink = /^(.{20})-(.{20})$/ + // this will match the new uuid v4 hash and the old hash + // e.g. + // :note:1c211eb7dcb463de6490 and + // :note:7dd23275-f2b4-49cb-9e93-3454daf1af9c + const regexIsNoteLink = /^:note:([a-zA-Z0-9-]{20,36})$/ if (regexIsNoteLink.test(noteHash)) { - eventEmitter.emit('list:jump', noteHash) + eventEmitter.emit('list:jump', noteHash.replace(':note:', '')) + } + // this will match the old link format storage.key-note.key + // e.g. + // 877f99c3268608328037-1c211eb7dcb463de6490 + const regexIsLegacyNoteLink = /^(.{20})-(.{20})$/ + if (regexIsLegacyNoteLink.test(noteHash)) { + eventEmitter.emit('list:jump', noteHash.split('-')[1]) } } diff --git a/browser/components/NoteItem.js b/browser/components/NoteItem.js index 253faa81..2013cfa0 100644 --- a/browser/components/NoteItem.js +++ b/browser/components/NoteItem.js @@ -62,9 +62,9 @@ const NoteItem = ({ ? 'item--active' : 'item' } - key={`${note.storage}-${note.key}`} - onClick={e => handleNoteClick(e, `${note.storage}-${note.key}`)} - onContextMenu={e => handleNoteContextMenu(e, `${note.storage}-${note.key}`)} + key={note.key} + onClick={e => handleNoteClick(e, note.key)} + onContextMenu={e => handleNoteContextMenu(e, note.key)} onDragStart={e => handleDragStart(e, note)} draggable='true' > diff --git a/browser/components/NoteItemSimple.js b/browser/components/NoteItemSimple.js index 0d2465e9..8262ea1d 100644 --- a/browser/components/NoteItemSimple.js +++ b/browser/components/NoteItemSimple.js @@ -28,9 +28,9 @@ const NoteItemSimple = ({ ? 'item-simple--active' : 'item-simple' } - key={`${note.storage}-${note.key}`} - onClick={e => handleNoteClick(e, `${note.storage}-${note.key}`)} - onContextMenu={e => handleNoteContextMenu(e, `${note.storage}-${note.key}`)} + key={note.key} + onClick={e => handleNoteClick(e, note.key)} + onContextMenu={e => handleNoteContextMenu(e, note.key)} onDragStart={e => handleDragStart(e, note)} draggable='true' > diff --git a/browser/lib/keygen.js b/browser/lib/keygen.js index f4937a83..814efedd 100644 --- a/browser/lib/keygen.js +++ b/browser/lib/keygen.js @@ -1,7 +1,11 @@ const crypto = require('crypto') const _ = require('lodash') +const uuidv4 = require('uuid/v4') -module.exports = function (length) { - if (!_.isFinite(length)) length = 10 +module.exports = function (uuid) { + if (typeof uuid === typeof true && uuid) { + return uuidv4() + } + const length = 10 return crypto.randomBytes(length).toString('hex') } diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index a543a5aa..6821bf2f 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -139,7 +139,7 @@ class MarkdownNoteDetail extends React.Component { hashHistory.replace({ pathname: location.pathname, query: { - key: newNote.storage + '-' + newNote.key + key: newNote.key } }) this.setState({ @@ -393,7 +393,7 @@ class MarkdownNoteDetail extends React.Component { `${note.storage}-${note.key}` === noteKey) + return notes.find((note) => note.key === noteKey) } function findNotesByKeys (notes, noteKeys) { @@ -42,7 +42,7 @@ function findNotesByKeys (notes, noteKeys) { } function getNoteKey (note) { - return `${note.storage}-${note.key}` + return note.key } class NoteList extends React.Component { @@ -118,10 +118,10 @@ class NoteList extends React.Component { componentDidUpdate (prevProps) { const { location } = this.props const { selectedNoteKeys } = this.state - const visibleNoteKeys = this.notes.map(note => `${note.storage}-${note.key}`) + const visibleNoteKeys = this.notes.map(note => note.key) const note = this.notes[0] const prevKey = prevProps.location.query.key - const noteKey = visibleNoteKeys.includes(prevKey) ? prevKey : note && `${note.storage}-${note.key}` + const noteKey = visibleNoteKeys.includes(prevKey) ? prevKey : note && note.key if (note && location.query.key == null) { const { router } = this.context @@ -589,11 +589,9 @@ class NoteList extends React.Component { }) if (dialogueButtonIndex === 1) return Promise.all( - selectedNoteKeys.map((uniqueKey) => { - const storageKey = uniqueKey.split('-')[0] - const noteKey = uniqueKey.split('-')[1] + selectedNotes.map((note) => { return dataApi - .deleteNote(storageKey, noteKey) + .deleteNote(note.storage, note.key) }) ) .then((data) => { @@ -654,19 +652,18 @@ class NoteList extends React.Component { content: firstNote.content }) .then((note) => { - const uniqueKey = note.storage + '-' + note.key dispatch({ type: 'UPDATE_NOTE', note: note }) this.setState({ - selectedNoteKeys: [uniqueKey] + selectedNoteKeys: [note.key] }) hashHistory.push({ pathname: location.pathname, - query: {key: uniqueKey} + query: {key: note.key} }) }) } diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index a7e9890b..5e559c64 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -160,10 +160,8 @@ class SideNav extends React.Component { emptyTrash (entries) { const { dispatch } = this.props - const deletionPromises = entries.map((storageAndNoteKey) => { - const storageKey = storageAndNoteKey.split('-')[0] - const noteKey = storageAndNoteKey.split('-')[1] - return dataApi.deleteNote(storageKey, noteKey) + const deletionPromises = entries.map((note) => { + return dataApi.deleteNote(note.storage, note.key) }) Promise.all(deletionPromises) .then((arrayOfStorageAndNoteKeys) => { @@ -179,9 +177,9 @@ class SideNav extends React.Component { handleFilterButtonContextMenu (event) { const { data } = this.props - const entries = data.trashedSet.toJS() + const trashedNotes = data.trashedSet.toJS().map((uniqueKey) => data.noteMap.get(uniqueKey)) const menu = Menu.buildFromTemplate([ - { label: 'Empty Trash', click: () => this.emptyTrash(entries) } + { label: 'Empty Trash', click: () => this.emptyTrash(trashedNotes) } ]) menu.popup() } diff --git a/browser/main/lib/dataApi/createNote.js b/browser/main/lib/dataApi/createNote.js index 4b667385..e5d44489 100644 --- a/browser/main/lib/dataApi/createNote.js +++ b/browser/main/lib/dataApi/createNote.js @@ -52,12 +52,12 @@ function createNote (storageKey, input) { return storage }) .then(function saveNote (storage) { - let key = keygen() + let key = keygen(true) let isUnique = false while (!isUnique) { try { sander.statSync(path.join(storage.path, 'notes', key + '.cson')) - key = keygen() + key = keygen(true) } catch (err) { if (err.code === 'ENOENT') { isUnique = true diff --git a/browser/main/lib/dataApi/moveNote.js b/browser/main/lib/dataApi/moveNote.js index b37b6ac5..928d331b 100644 --- a/browser/main/lib/dataApi/moveNote.js +++ b/browser/main/lib/dataApi/moveNote.js @@ -39,12 +39,12 @@ function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) { return resolveStorageData(newStorage) .then(function findNewNoteKey (_newStorage) { newStorage = _newStorage - newNoteKey = keygen() + newNoteKey = keygen(true) let isUnique = false while (!isUnique) { try { sander.statSync(path.join(newStorage.path, 'notes', newNoteKey + '.cson')) - newNoteKey = keygen() + newNoteKey = keygen(true) } catch (err) { if (err.code === 'ENOENT') { isUnique = true diff --git a/browser/main/modals/NewNoteModal.js b/browser/main/modals/NewNoteModal.js index 8322d99f..84f510c4 100644 --- a/browser/main/modals/NewNoteModal.js +++ b/browser/main/modals/NewNoteModal.js @@ -35,7 +35,7 @@ class NewNoteModal extends React.Component { content: '' }) .then((note) => { - const noteHash = `${note.storage}-${note.key}` + const noteHash = note.key dispatch({ type: 'UPDATE_NOTE', note: note @@ -75,7 +75,7 @@ class NewNoteModal extends React.Component { }] }) .then((note) => { - const noteHash = `${note.storage}-${note.key}` + const noteHash = note.key dispatch({ type: 'UPDATE_NOTE', note: note diff --git a/browser/main/store.js b/browser/main/store.js index abd34889..f078ad20 100644 --- a/browser/main/store.js +++ b/browser/main/store.js @@ -27,7 +27,7 @@ function data (state = defaultDataMap(), action) { action.notes.some((note) => { if (note === undefined) return true - const uniqueKey = note.storage + '-' + note.key + const uniqueKey = note.key const folderKey = note.storage + '-' + note.folder state.noteMap.set(uniqueKey, note) @@ -66,7 +66,7 @@ function data (state = defaultDataMap(), action) { case 'UPDATE_NOTE': { const note = action.note - const uniqueKey = note.storage + '-' + note.key + const uniqueKey = note.key const folderKey = note.storage + '-' + note.folder const oldNote = state.noteMap.get(uniqueKey) @@ -162,9 +162,9 @@ function data (state = defaultDataMap(), action) { case 'MOVE_NOTE': { const originNote = action.originNote - const originKey = originNote.storage + '-' + originNote.key + const originKey = originNote.key const note = action.note - const uniqueKey = note.storage + '-' + note.key + const uniqueKey = note.key const folderKey = note.storage + '-' + note.folder const oldNote = state.noteMap.get(uniqueKey) @@ -297,7 +297,7 @@ function data (state = defaultDataMap(), action) { } case 'DELETE_NOTE': { - const uniqueKey = action.storageKey + '-' + action.noteKey + const uniqueKey = action.noteKey const targetNote = state.noteMap.get(uniqueKey) state = Object.assign({}, state) @@ -423,7 +423,7 @@ function data (state = defaultDataMap(), action) { state.folderNoteMap = new Map(state.folderNoteMap) state.tagNoteMap = new Map(state.tagNoteMap) action.notes.forEach((note) => { - const uniqueKey = note.storage + '-' + note.key + const uniqueKey = note.key const folderKey = note.storage + '-' + note.folder state.noteMap.set(uniqueKey, note) @@ -483,7 +483,7 @@ function data (state = defaultDataMap(), action) { state.tagNoteMap = new Map(state.tagNoteMap) state.starredSet = new Set(state.starredSet) notes.forEach((note) => { - const noteKey = storage.key + '-' + note.key + const noteKey = note.key state.noteMap.delete(noteKey) state.starredSet.delete(noteKey) note.tags.forEach((tag) => { diff --git a/package.json b/package.json index 04ca2baa..567159c5 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,8 @@ "sanitize-html": "^1.18.2", "striptags": "^2.2.1", "superagent": "^1.2.0", - "superagent-promise": "^1.0.3" + "superagent-promise": "^1.0.3", + "uuid": "^3.2.1" }, "devDependencies": { "ava": "^0.16.0", diff --git a/tests/fixtures/TestDummy.js b/tests/fixtures/TestDummy.js index a1f5d16e..62cae846 100644 --- a/tests/fixtures/TestDummy.js +++ b/tests/fixtures/TestDummy.js @@ -107,9 +107,9 @@ function dummyStorage (storagePath, override = {}) { var notesData = [] var noteCount = Math.floor((Math.random() * 15)) + 2 for (var i = 0; i < noteCount; i++) { - var key = keygen() + var key = keygen(true) while (notesData.some((note) => note.key === key)) { - key = keygen() + key = keygen(true) } var noteData = dummyNote({ @@ -149,9 +149,9 @@ function dummyLegacyStorage (storagePath, override = {}) { var folderNotes = [] var noteCount = Math.floor((Math.random() * 5)) + 1 for (var i = 0; i < noteCount; i++) { - var key = keygen(6) + var key = keygen(true) while (folderNotes.some((note) => note.key === key)) { - key = keygen(6) + key = keygen(true) } var noteData = dummyNote({ diff --git a/yarn.lock b/yarn.lock index f0c81311..84ed3d1c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6795,6 +6795,10 @@ uuid@^2.0.1, uuid@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" +uuid@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + validate-npm-package-license@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"