mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-16 11:15:12 +00:00
feat: add shiftkey multiselect notes and delete
This commit is contained in:
@@ -15,6 +15,7 @@ import markdown from 'browser/lib/markdown'
|
|||||||
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
||||||
import stripgtags from 'striptags'
|
import stripgtags from 'striptags'
|
||||||
import store from 'browser/main/store'
|
import store from 'browser/main/store'
|
||||||
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { Menu, MenuItem, dialog } = remote
|
const { Menu, MenuItem, dialog } = remote
|
||||||
@@ -50,8 +51,12 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
this.importFromFileHandler = this.importFromFile.bind(this)
|
this.importFromFileHandler = this.importFromFile.bind(this)
|
||||||
this.jumpNoteByHash = this.jumpNoteByHashHandler.bind(this)
|
this.jumpNoteByHash = this.jumpNoteByHashHandler.bind(this)
|
||||||
|
this.handleNoteListKeyUp = this.handleNoteListKeyUp.bind(this)
|
||||||
|
this.deleteNote = this.deleteNote.bind(this)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
shiftKeyDown: false,
|
||||||
|
selectedNoteIds: []
|
||||||
}
|
}
|
||||||
|
|
||||||
this.contextNotes = []
|
this.contextNotes = []
|
||||||
@@ -197,6 +202,10 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleNoteListKeyDown (e) {
|
handleNoteListKeyDown (e) {
|
||||||
|
if (e.shiftKey) {
|
||||||
|
this.setState({ shiftKeyDown: true })
|
||||||
|
}
|
||||||
|
|
||||||
if (e.metaKey || e.ctrlKey) return true
|
if (e.metaKey || e.ctrlKey) return true
|
||||||
|
|
||||||
if (e.keyCode === 65 && !e.shiftKey) {
|
if (e.keyCode === 65 && !e.shiftKey) {
|
||||||
@@ -225,6 +234,12 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleNoteListKeyUp (e) {
|
||||||
|
if (!e.shiftKey) {
|
||||||
|
this.setState({ shiftKeyDown: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getNotes () {
|
getNotes () {
|
||||||
let { data, params, location } = this.props
|
let { data, params, location } = this.props
|
||||||
let { router } = this.context
|
let { router } = this.context
|
||||||
@@ -302,7 +317,21 @@ class NoteList extends React.Component {
|
|||||||
handleNoteClick (e, uniqueKey) {
|
handleNoteClick (e, uniqueKey) {
|
||||||
let { router } = this.context
|
let { router } = this.context
|
||||||
let { location } = this.props
|
let { location } = this.props
|
||||||
|
let { shiftKeyDown, selectedNoteIds } = this.state
|
||||||
|
|
||||||
|
if (shiftKeyDown && !selectedNoteIds.includes(uniqueKey)) {
|
||||||
|
selectedNoteIds.push(uniqueKey)
|
||||||
|
this.setState({
|
||||||
|
selectedNoteIds
|
||||||
|
})
|
||||||
|
} else if (shiftKeyDown) {
|
||||||
|
this.setState({
|
||||||
|
selectedNoteIds: [...selectedNoteIds].filter((item) => item !== uniqueKey)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
selectedNoteIds: [uniqueKey]
|
||||||
|
})
|
||||||
router.push({
|
router.push({
|
||||||
pathname: location.pathname,
|
pathname: location.pathname,
|
||||||
query: {
|
query: {
|
||||||
@@ -310,6 +339,7 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
handleSortByChange (e) {
|
handleSortByChange (e) {
|
||||||
let { dispatch } = this.props
|
let { dispatch } = this.props
|
||||||
@@ -358,11 +388,16 @@ class NoteList extends React.Component {
|
|||||||
|
|
||||||
handleNoteContextMenu (e, uniqueKey) {
|
handleNoteContextMenu (e, uniqueKey) {
|
||||||
const { location } = this.props
|
const { location } = this.props
|
||||||
|
const { selectedNoteIds } = this.state
|
||||||
const note = this.notes.find((note) => {
|
const note = this.notes.find((note) => {
|
||||||
const noteKey = `${note.storage}-${note.key}`
|
const noteKey = `${note.storage}-${note.key}`
|
||||||
return noteKey === uniqueKey
|
return noteKey === uniqueKey
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (selectedNoteIds.length === 0) {
|
||||||
|
this.handleNoteClick(e, uniqueKey)
|
||||||
|
}
|
||||||
|
|
||||||
const pinLabel = note.isPinned ? 'Remove pin' : 'Pin to Top'
|
const pinLabel = note.isPinned ? 'Remove pin' : 'Pin to Top'
|
||||||
const deleteLabel = 'Delete Note'
|
const deleteLabel = 'Delete Note'
|
||||||
|
|
||||||
@@ -375,7 +410,7 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
label: deleteLabel,
|
label: deleteLabel,
|
||||||
click: (e) => this.deleteNote(e, uniqueKey)
|
click: this.deleteNote
|
||||||
}))
|
}))
|
||||||
menu.popup()
|
menu.popup()
|
||||||
}
|
}
|
||||||
@@ -403,9 +438,68 @@ class NoteList extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteNote (e, uniqueKey) {
|
deleteNote () {
|
||||||
this.handleNoteClick(e, uniqueKey)
|
const { dispatch } = this.props
|
||||||
ee.emit('detail:delete')
|
const { selectedNoteIds } = this.state
|
||||||
|
// not to change objects of this.notes
|
||||||
|
const notes = this.notes.map((note) => Object.assign({}, note))
|
||||||
|
const selectedNotes = notes.filter((note) => selectedNoteIds.includes(`${note.storage}-${note.key}`))
|
||||||
|
const firstNote = selectedNotes[0]
|
||||||
|
|
||||||
|
if (firstNote.isTrashed) {
|
||||||
|
const noteExp = selectedNotes.length > 1 ? 'notes' : 'note'
|
||||||
|
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Confirm note deletion',
|
||||||
|
detail: `This will permanently remove ${selectedNotes.length} ${noteExp}.`,
|
||||||
|
buttons: ['Confirm', 'Cancel']
|
||||||
|
})
|
||||||
|
if (dialogueButtonIndex === 1) return
|
||||||
|
Promise.all(
|
||||||
|
selectedNoteIds.map((uniqueKey) => {
|
||||||
|
const storageKey = uniqueKey.split('-')[0]
|
||||||
|
const noteKey = uniqueKey.split('-')[1]
|
||||||
|
return dataApi
|
||||||
|
.deleteNote(storageKey, noteKey)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then((data) => {
|
||||||
|
data.forEach((item) => {
|
||||||
|
dispatch({
|
||||||
|
type: 'DELETE_NOTE',
|
||||||
|
storageKey: item.storageKey,
|
||||||
|
noteKey: item.noteKey
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Cannot Delete note: ' + err)
|
||||||
|
})
|
||||||
|
console.log('Notes were all deleted')
|
||||||
|
} else {
|
||||||
|
Promise.all(
|
||||||
|
selectedNotes.map((note) => {
|
||||||
|
note.isTrashed = true
|
||||||
|
|
||||||
|
return dataApi
|
||||||
|
.updateNote(note.storage, note.key, note)
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then((newNotes) => {
|
||||||
|
newNotes.forEach((newNote) => {
|
||||||
|
dispatch({
|
||||||
|
type: 'UPDATE_NOTE',
|
||||||
|
note: newNote
|
||||||
|
})
|
||||||
|
})
|
||||||
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('EDIT_NOTE')
|
||||||
|
console.log('Notes went to trash')
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Notes could not go to trash: ' + err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.setState({ selectedNoteIds: [] })
|
||||||
}
|
}
|
||||||
|
|
||||||
importFromFile () {
|
importFromFile () {
|
||||||
@@ -475,6 +569,7 @@ class NoteList extends React.Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { location, notes, config, dispatch } = this.props
|
let { location, notes, config, dispatch } = this.props
|
||||||
|
let { selectedNoteIds } = this.state
|
||||||
let sortFunc = config.sortBy === 'CREATED_AT'
|
let sortFunc = config.sortBy === 'CREATED_AT'
|
||||||
? sortByCreatedAt
|
? sortByCreatedAt
|
||||||
: config.sortBy === 'ALPHABETICAL'
|
: config.sortBy === 'ALPHABETICAL'
|
||||||
@@ -495,7 +590,8 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isDefault = config.listStyle === 'DEFAULT'
|
const isDefault = config.listStyle === 'DEFAULT'
|
||||||
const isActive = location.query.key === note.storage + '-' + note.key
|
const uniqueKey = note.storage + '-' + note.key
|
||||||
|
const isActive = selectedNoteIds.includes(uniqueKey)
|
||||||
const dateDisplay = moment(
|
const dateDisplay = moment(
|
||||||
config.sortBy === 'CREATED_AT'
|
config.sortBy === 'CREATED_AT'
|
||||||
? note.createdAt : note.updatedAt
|
? note.createdAt : note.updatedAt
|
||||||
@@ -570,6 +666,7 @@ class NoteList extends React.Component {
|
|||||||
ref='list'
|
ref='list'
|
||||||
tabIndex='-1'
|
tabIndex='-1'
|
||||||
onKeyDown={(e) => this.handleNoteListKeyDown(e)}
|
onKeyDown={(e) => this.handleNoteListKeyDown(e)}
|
||||||
|
onKeyUp={this.handleNoteListKeyUp}
|
||||||
>
|
>
|
||||||
{noteList}
|
{noteList}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user