1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-22 06:01:45 +00:00

Merge branch 'master' into theme-nord

This commit is contained in:
Baptiste Augrain
2020-01-30 19:14:58 +01:00
159 changed files with 8277 additions and 4690 deletions

View File

@@ -14,23 +14,42 @@ import NoteItemSimple from 'browser/components/NoteItemSimple'
import searchFromNotes from 'browser/lib/search'
import fs from 'fs'
import path from 'path'
import { hashHistory } from 'react-router'
import { push, replace } from 'connected-react-router'
import copy from 'copy-to-clipboard'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
import Markdown from '../../lib/markdown'
import i18n from 'browser/lib/i18n'
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
import context from 'browser/lib/context'
import queryString from 'query-string'
const { remote } = require('electron')
const { dialog } = remote
const WP_POST_PATH = '/wp/v2/posts'
const regexMatchStartingTitleNumber = new RegExp('^([0-9]*\.?[0-9]+).*$')
function sortByCreatedAt (a, b) {
return new Date(b.createdAt) - new Date(a.createdAt)
}
function sortByAlphabetical (a, b) {
const matchA = regexMatchStartingTitleNumber.exec(a.title)
const matchB = regexMatchStartingTitleNumber.exec(b.title)
if (matchA && matchA.length === 2 && matchB && matchB.length === 2) {
// Both note titles are starting with a float. We will compare it now.
const floatA = parseFloat(matchA[1])
const floatB = parseFloat(matchB[1])
const diff = floatA - floatB
if (diff !== 0) {
return diff
}
// The float values are equal. We will compare the full title.
}
return a.title.localeCompare(b.title)
}
@@ -69,6 +88,7 @@ class NoteList extends React.Component {
this.importFromFileHandler = this.importFromFile.bind(this)
this.jumpNoteByHash = this.jumpNoteByHashHandler.bind(this)
this.handleNoteListKeyUp = this.handleNoteListKeyUp.bind(this)
this.handleNoteListBlur = this.handleNoteListBlur.bind(this)
this.getNoteKeyFromTargetIndex = this.getNoteKeyFromTargetIndex.bind(this)
this.cloneNote = this.cloneNote.bind(this)
this.deleteNote = this.deleteNote.bind(this)
@@ -127,15 +147,15 @@ class NoteList extends React.Component {
}
componentDidUpdate (prevProps) {
const { location } = this.props
const { dispatch, location } = this.props
const { selectedNoteKeys } = this.state
const visibleNoteKeys = this.notes.map(note => note.key)
const note = this.notes[0]
const prevKey = prevProps.location.query.key
const visibleNoteKeys = this.notes && this.notes.map(note => note.key)
const note = this.notes && this.notes[0]
const key = location.search && queryString.parse(location.search).key
const prevKey = prevProps.location.search && queryString.parse(prevProps.location.search).key
const noteKey = visibleNoteKeys.includes(prevKey) ? prevKey : note && note.key
if (note && location.query.key == null) {
const { router } = this.context
if (note && location.search === '') {
if (!location.pathname.match(/\/searched/)) this.contextNotes = this.getContextNotes()
// A visible note is an active note
@@ -145,17 +165,17 @@ class NoteList extends React.Component {
ee.emit('list:moved')
}
router.replace({
dispatch(replace({ // was passed with context - we can use connected router here
pathname: location.pathname,
query: {
search: queryString.stringify({
key: noteKey
}
})
})
}))
return
}
// Auto scroll
if (_.isString(location.query.key) && prevProps.location.query.key === location.query.key) {
if (_.isString(key) && prevKey === key) {
const targetIndex = this.getTargetIndex()
if (targetIndex > -1) {
const list = this.refs.list
@@ -176,18 +196,18 @@ class NoteList extends React.Component {
}
focusNote (selectedNoteKeys, noteKey, pathname) {
const { router } = this.context
const { dispatch } = this.props
this.setState({
selectedNoteKeys
})
router.push({
dispatch(push({
pathname,
query: {
search: queryString.stringify({
key: noteKey
}
})
})
}))
}
getNoteKeyFromTargetIndex (targetIndex) {
@@ -259,13 +279,22 @@ class NoteList extends React.Component {
}
jumpNoteByHashHandler (event, noteHash) {
const { data } = this.props
// first argument event isn't used.
if (this.notes === null || this.notes.length === 0) {
return
}
const selectedNoteKeys = [noteHash]
this.focusNote(selectedNoteKeys, noteHash, '/home')
let locationToSelect = '/home'
const noteByHash = data.noteMap.map((note) => note).find(note => note.key === noteHash)
if (noteByHash !== undefined) {
locationToSelect = '/storages/' + noteByHash.storage + '/folders/' + noteByHash.folder
}
this.focusNote(selectedNoteKeys, noteHash, locationToSelect)
ee.emit('list:moved')
}
@@ -320,9 +349,15 @@ class NoteList extends React.Component {
}
}
getNotes () {
const { data, params, location } = this.props
handleNoteListBlur () {
this.setState({
shiftKeyDown: false,
ctrlKeyDown: false
})
}
getNotes () {
const { data, match: { params }, location } = this.props
if (location.pathname.match(/\/home/) || location.pathname.match(/alltags/)) {
const allNotes = data.noteMap.map((note) => note)
this.contextNotes = allNotes
@@ -363,7 +398,7 @@ class NoteList extends React.Component {
// get notes in the current folder
getContextNotes () {
const { data, params } = this.props
const { data, match: { params } } = this.props
const storageKey = params.storageKey
const folderKey = params.folderKey
const storage = data.storageMap.get(storageKey)
@@ -403,8 +438,7 @@ class NoteList extends React.Component {
}
handleNoteClick (e, uniqueKey) {
const { router } = this.context
const { location } = this.props
const { dispatch, location } = this.props
let { selectedNoteKeys, prevShiftNoteIndex } = this.state
const { ctrlKeyDown, shiftKeyDown } = this.state
const hasSelectedNoteKey = selectedNoteKeys.length > 0
@@ -455,16 +489,16 @@ class NoteList extends React.Component {
prevShiftNoteIndex
})
router.push({
dispatch(push({
pathname: location.pathname,
query: {
search: queryString.stringify({
key: uniqueKey
}
})
})
}))
}
handleSortByChange (e) {
const { dispatch, params: { folderKey } } = this.props
const { dispatch, match: { params: { folderKey } } } = this.props
const config = {
[folderKey]: { sortBy: e.target.value }
@@ -496,6 +530,7 @@ class NoteList extends React.Component {
'export-txt': 'Text export',
'export-md': 'Markdown export',
'export-html': 'HTML export',
'export-pdf': 'PDF export',
'print': 'Print'
})[msg]
@@ -716,7 +751,11 @@ class NoteList extends React.Component {
folder: folder.key,
title: firstNote.title + ' ' + i18n.__('copy'),
content: firstNote.content,
linesHighlighted: firstNote.linesHighlighted
linesHighlighted: firstNote.linesHighlighted,
description: firstNote.description,
snippets: firstNote.snippets,
tags: firstNote.tags,
isStarred: firstNote.isStarred
})
.then((note) => {
attachmentManagement.cloneAttachments(firstNote, note)
@@ -732,10 +771,10 @@ class NoteList extends React.Component {
selectedNoteKeys: [note.key]
})
hashHistory.push({
dispatch(push({
pathname: location.pathname,
query: {key: note.key}
})
search: queryString.stringify({key: note.key})
}))
})
}
@@ -745,13 +784,13 @@ class NoteList extends React.Component {
}
navigate (sender, pathname) {
const { router } = this.context
router.push({
const { dispatch } = this.props
dispatch(push({
pathname,
query: {
search: queryString.stringify({
// key: noteKey
}
})
})
}))
}
save (note) {
@@ -881,7 +920,7 @@ class NoteList extends React.Component {
if (!location.pathname.match(/\/trashed/)) this.addNotesFromFiles(filepaths)
}
// Add notes to the current folder
// Add notes to the current folder
addNotesFromFiles (filepaths) {
const { dispatch, location } = this.props
const { storage, folder } = this.resolveTargetFolder()
@@ -905,13 +944,20 @@ class NoteList extends React.Component {
}
dataApi.createNote(storage.key, newNote)
.then((note) => {
dispatch({
type: 'UPDATE_NOTE',
note: note
})
hashHistory.push({
pathname: location.pathname,
query: {key: getNoteKey(note)}
attachmentManagement.importAttachments(note.content, filepath, storage.key, note.key)
.then((newcontent) => {
note.content = newcontent
dataApi.updateNote(storage.key, note.key, note)
dispatch({
type: 'UPDATE_NOTE',
note: note
})
dispatch(push({
pathname: location.pathname,
search: queryString.stringify({key: getNoteKey(note)})
}))
})
})
})
@@ -921,14 +967,15 @@ class NoteList extends React.Component {
getTargetIndex () {
const { location } = this.props
const key = queryString.parse(location.search).key
const targetIndex = _.findIndex(this.notes, (note) => {
return getNoteKey(note) === location.query.key
return getNoteKey(note) === key
})
return targetIndex
}
resolveTargetFolder () {
const { data, params } = this.props
const { data, match: { params } } = this.props
let storage = data.storageMap.get(params.storageKey)
// Find first storage
@@ -976,7 +1023,7 @@ class NoteList extends React.Component {
}
render () {
const { location, config, params: { folderKey } } = this.props
const { location, config, match: { params: { folderKey } } } = this.props
let { notes } = this.props
const { selectedNoteKeys } = this.state
const sortBy = _.get(config, [folderKey, 'sortBy'], config.sortBy.default)
@@ -1099,7 +1146,7 @@ class NoteList extends React.Component {
}
onClick={(e) => this.handleListStyleButtonClick(e, 'DEFAULT')}
>
<img styleName='iconTag' src='../resources/icon/icon-column.svg' />
<img src='../resources/icon/icon-column.svg' />
</button>
<button title={i18n.__('Compressed View')} styleName={config.listStyle === 'SMALL'
? 'control-button--active'
@@ -1107,7 +1154,7 @@ class NoteList extends React.Component {
}
onClick={(e) => this.handleListStyleButtonClick(e, 'SMALL')}
>
<img styleName='iconTag' src='../resources/icon/icon-column-list.svg' />
<img src='../resources/icon/icon-column-list.svg' />
</button>
</div>
</div>
@@ -1116,6 +1163,7 @@ class NoteList extends React.Component {
tabIndex='-1'
onKeyDown={(e) => this.handleNoteListKeyDown(e)}
onKeyUp={this.handleNoteListKeyUp}
onBlur={this.handleNoteListBlur}
>
{noteList}
</div>