Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion browser/main/Detail/MarkdownNoteDetail.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ class MarkdownNoteDetail extends React.Component {
componentWillReceiveProps (nextProps) {
const isNewNote = nextProps.note.key !== this.props.note.key
const hasDeletedTags = nextProps.note.tags.length < this.props.note.tags.length
if (!this.state.isMovingNote && (isNewNote || hasDeletedTags)) {
const updateContent = nextProps.note.content !== this.props.note.content
if (!this.state.isMovingNote && (isNewNote || hasDeletedTags || updateContent)) {
if (this.saveQueue != null) this.saveNow()
this.setState({
note: Object.assign({linesHighlighted: []}, nextProps.note)
Expand Down
84 changes: 79 additions & 5 deletions browser/main/NoteList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import context from 'browser/lib/context'
const { remote } = require('electron')
const { dialog } = remote
const WP_POST_PATH = '/wp/v2/posts'
const CSON = require('@rokt33r/season')

function sortByCreatedAt (a, b) {
return new Date(b.createdAt) - new Date(a.createdAt)
Expand Down Expand Up @@ -66,6 +67,7 @@ class NoteList extends React.Component {
this.alertIfSnippetHandler = (event, msg) => {
this.alertIfSnippet(msg)
}
this.openFileHandler = this.openFile.bind(this)
this.importFromFileHandler = this.importFromFile.bind(this)
this.jumpNoteByHash = this.jumpNoteByHashHandler.bind(this)
this.handleNoteListKeyUp = this.handleNoteListKeyUp.bind(this)
Expand All @@ -90,6 +92,8 @@ class NoteList extends React.Component {
}

this.contextNotes = []

this.fsWatcher = null
}

componentDidMount () {
Expand All @@ -100,6 +104,7 @@ class NoteList extends React.Component {
ee.on('list:focus', this.focusHandler)
ee.on('list:isMarkdownNote', this.alertIfSnippetHandler)
ee.on('import:file', this.importFromFileHandler)
ee.on('open:file', this.openFileHandler)
ee.on('list:jump', this.jumpNoteByHash)
ee.on('list:navigate', this.navigate)
}
Expand Down Expand Up @@ -127,13 +132,66 @@ class NoteList extends React.Component {
}

componentDidUpdate (prevProps) {
const { location } = this.props
const { location, dispatch } = this.props
const { storage } = this.resolveTargetFolder()
const { selectedNoteKeys } = this.state
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.key

if (location.query.key !== prevKey) {
let focusNote = findNoteByKey(this.notes, location.query.key)

if (focusNote.filepath !== undefined) {
try {
if (this.fsWatcher != null) {
this.fsWatcher.close()
this.fsWatcher = null
}
} catch (err) {
console.error('File watcher does not exist: ' + err)
}

if (fs.existsSync(focusNote.filepath) && fs.lstatSync(focusNote.filepath).isFile()) {
this.fsWatcher = fs.watch(focusNote.filepath)

this.fsWatcher.on('change', (event, filename) => {
let updatedNote = Object.assign({}, focusNote)

switch (event) {
case 'change' :
updatedNote.content = fs.readFileSync(updatedNote.filepath, 'utf8')
updatedNote.contentSynced = true
break

case 'rename':
updatedNote.filepath = undefined
try {
this.fsWatcher.close()
} catch (err) {
console.error('File watcher does not exist: ' + err)
}
const notePath = path.join(storage.path, 'notes', noteKey + '.cson')
CSON.writeFileSync(notePath, _.omit(updatedNote, ['key', 'storage']))
break

default: break
}

dataApi
.updateNote(storage.key, focusNote.key, updatedNote)
.then((note) => {
dispatch({
type: 'UPDATE_NOTE',
note: note
})
})
})
}
}
}

if (note && location.query.key == null) {
const { router } = this.context
if (!location.pathname.match(/\/searched/)) this.contextNotes = this.getContextNotes()
Expand Down Expand Up @@ -856,6 +914,19 @@ class NoteList extends React.Component {
shell.openExternal(note.blog.blogLink)
}

openFile () {
const options = {
filters: [
{ name: 'Documents', extensions: ['md', 'txt'] }
],
properties: ['openFile']
}

dialog.showOpenDialog(remote.getCurrentWindow(), options, (filepaths) => {
this.addNotesFromFiles(filepaths, 'LINK')
})
}

importFromFile () {
const options = {
filters: [
Expand All @@ -865,19 +936,19 @@ class NoteList extends React.Component {
}

dialog.showOpenDialog(remote.getCurrentWindow(), options, (filepaths) => {
this.addNotesFromFiles(filepaths)
this.addNotesFromFiles(filepaths, 'COPY')
})
}

handleDrop (e) {
e.preventDefault()
const { location } = this.props
const filepaths = Array.from(e.dataTransfer.files).map(file => { return file.path })
if (!location.pathname.match(/\/trashed/)) this.addNotesFromFiles(filepaths)
if (!location.pathname.match(/\/trashed/)) this.addNotesFromFiles(filepaths, 'COPY')
}

// Add notes to the current folder
addNotesFromFiles (filepaths) {
addNotesFromFiles (filepaths, linktype) {
const { dispatch, location } = this.props
const { storage, folder } = this.resolveTargetFolder()

Expand All @@ -896,7 +967,8 @@ class NoteList extends React.Component {
title: path.basename(filepath, path.extname(filepath)),
type: 'MARKDOWN_NOTE',
createdAt: birthtime,
updatedAt: mtime
updatedAt: mtime,
filepath: (linktype === 'LINK' ? filepath : undefined)
}
dataApi.createNote(storage.key, newNote)
.then((note) => {
Expand All @@ -908,6 +980,8 @@ class NoteList extends React.Component {
pathname: location.pathname,
query: {key: getNoteKey(note)}
})
ee.emit('list:jump', getNoteKey(note))
ee.emit('detail:focus')
})
})
})
Expand Down
7 changes: 7 additions & 0 deletions browser/main/lib/dataApi/updateNote.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const resolveStorageData = require('./resolveStorageData')
const _ = require('lodash')
const path = require('path')
const CSON = require('@rokt33r/season')
const fs = require('fs-plus')
const { findStorage } = require('browser/lib/findStorage')

function validateInput (input) {
Expand Down Expand Up @@ -78,6 +79,7 @@ function updateNote (storageKey, noteKey, input) {
let targetStorage
try {
if (input == null) throw new Error('No input found.')
var contentSynced = input.contentSynced
input = validateInput(input)

targetStorage = findStorage(storageKey)
Expand Down Expand Up @@ -132,6 +134,11 @@ function updateNote (storageKey, noteKey, input) {

CSON.writeFileSync(path.join(storage.path, 'notes', noteKey + '.cson'), _.omit(noteData, ['key', 'storage']))

if (noteData.filepath !== undefined) {
if (!contentSynced && !noteData.isTrashed) {
fs.writeFileSync(noteData.filepath, noteData.content)
}
}
return noteData
})
}
Expand Down
6 changes: 6 additions & 0 deletions lib/main-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ const boost = macOS
const file = {
label: 'File',
submenu: [
{
label: 'Open File...',
click () {
mainWindow.webContents.send('open:file')
}
},
{
label: 'New Note',
accelerator: 'CommandOrControl+N',
Expand Down
35 changes: 33 additions & 2 deletions tests/dataApi/updateNote-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const TestDummy = require('../fixtures/TestDummy')
const sander = require('sander')
const os = require('os')
const CSON = require('@rokt33r/season')
const fs = require('fs')
const faker = require('faker')

const storagePath = path.join(os.tmpdir(), 'test/update-note')
Expand Down Expand Up @@ -73,25 +74,45 @@ test.serial('Update a note', (t) => {
}
input4.title = input4.content.split('\n').shift()

const input5 = {
type: 'MARKDOWN_NOTE',
content: faker.lorem.lines(),
tags: faker.lorem.words().split(' '),
folder: folderKey,
filepath: path.join(storagePath, 'test', 'test' + '.txt')
}
input5.title = input5.content.split('\n').shift()

const input6 = {
type: 'MARKDOWN_NOTE',
content: faker.lorem.lines(),
tags: faker.lorem.words().split(' ')
}
input6.title = input6.content.split('\n').shift()

return Promise.resolve()
.then(function doTest () {
return Promise
.all([
createNote(storageKey, input1),
createNote(storageKey, input2)
createNote(storageKey, input2),
createNote(storageKey, input5)
])
.then(function updateNotes (data) {
const data1 = data[0]
const data2 = data[1]
const data3 = data[2]
return Promise.all([
updateNote(data1.storage, data1.key, input3),
updateNote(data1.storage, data2.key, input4)
updateNote(data1.storage, data2.key, input4),
updateNote(data1.storage, data3.key, input6)
])
})
})
.then(function assert (data) {
const data1 = data[0]
const data2 = data[1]
const data3 = data[2]

const jsonData1 = CSON.readFileSync(path.join(storagePath, 'notes', data1.key + '.cson'))
t.is(input3.title, data1.title)
Expand All @@ -118,6 +139,16 @@ test.serial('Update a note', (t) => {
t.is(input4.tags.length, jsonData2.tags.length)
t.deepEqual(input4.linesHighlighted, data2.linesHighlighted)
t.deepEqual(input4.linesHighlighted, jsonData2.linesHighlighted)

const fileData3 = fs.readFileSync(path.join(storagePath, 'test', 'test' + '.txt'), 'utf8')
const jsonData3 = CSON.readFileSync(path.join(storagePath, 'notes', data3.key + '.cson'))
t.is(input6.title, data3.title)
t.is(input6.title, jsonData3.title)
t.is(input6.content, data3.content)
t.is(input6.content, jsonData3.content)
t.is(input6.tags.length, data3.tags.length)
t.is(input6.tags.length, data3.tags.length)
t.is(fileData3, data3.content)
})
})

Expand Down
17 changes: 14 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4337,6 +4337,11 @@ he@^1.1.1:
version "1.1.1"
resolved "http://registry.npm.taobao.org/he/download/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"

highlight.js@^9.13.1:
version "9.13.1"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==

highlight.js@^9.3.0:
version "9.12.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
Expand Down Expand Up @@ -4652,6 +4657,11 @@ invariant@^2.0.0, invariant@^2.2.1, invariant@^2.2.2:
dependencies:
loose-envify "^1.0.0"

invert-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/invert-color/-/invert-color-2.0.0.tgz#894ab1f7494a6e45f5e74c2f99ec042cd67dd23e"
integrity sha512-9s6IATlhOAr0/0MPUpLdMpk81ixIu8IqwPwORssXBauFT/4ff/iyEOcojd0UYuPwkDbJvL1+blIZGhqVIaAm5Q==

invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
Expand Down Expand Up @@ -6316,9 +6326,10 @@ mousetrap-global-bind@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mousetrap-global-bind/-/mousetrap-global-bind-1.1.0.tgz#cd7de9222bd0646fa2e010d54c84a74c26a88edd"

mousetrap@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.1.tgz#2a085f5c751294c75e7e81f6ec2545b29cbf42d9"
mousetrap@^1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.2.tgz#caadd9cf886db0986fb2fee59a82f6bd37527587"
integrity sha512-jDjhi7wlHwdO6q6DS7YRmSHcuI+RVxadBkLt3KHrhd3C2b+w5pKefg3oj5beTcHZyVFA9Aksf+yEE1y5jxUjVA==

[email protected]:
version "2.0.0"
Expand Down