Skip to content

Commit c13746f

Browse files
committed
Merge branch 'master' into create-note-with-tags
2 parents 70b8690 + ae840ea commit c13746f

File tree

15 files changed

+332
-166
lines changed

15 files changed

+332
-166
lines changed

.vscode/launch.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
8+
{
9+
"type": "node",
10+
"request": "launch",
11+
"name": "BoostNote Main",
12+
"protocol": "inspector",
13+
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
14+
"runtimeArgs": [
15+
"--remote-debugging-port=9223",
16+
"--hot",
17+
"${workspaceFolder}/index.js"
18+
],
19+
"windows": {
20+
"runtimeExecutable": "${workspaceFolder}/node_modeules/.bin/electron.cmd"
21+
}
22+
},
23+
{
24+
"type": "chrome",
25+
"request": "attach",
26+
"name": "BoostNote Renderer",
27+
"port": 9223,
28+
"webRoot": "${workspaceFolder}",
29+
"sourceMapPathOverrides": {
30+
"webpack:///./~/*": "${webRoot}/node_modules/*",
31+
"webpack:///*": "${webRoot}/*"
32+
}
33+
}
34+
],
35+
"compounds": [
36+
{
37+
"name": "BostNote All",
38+
"configurations": ["BoostNote Main", "BoostNote Renderer"]
39+
}
40+
]
41+
}

.vscode/tasks.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
// See https://go.microsoft.com/fwlink/?LinkId=733558
3+
// for the documentation about the tasks.json format
4+
"version": "2.0.0",
5+
"tasks": [
6+
{
7+
"label": "Build Boostnote",
8+
"group": "build",
9+
"type": "npm",
10+
"script": "watch",
11+
"isBackground": true,
12+
"presentation": {
13+
"reveal": "always",
14+
},
15+
"problemMatcher": {
16+
"pattern":[
17+
{
18+
"regexp": "^([^\\\\s].*)\\\\((\\\\d+,\\\\d+)\\\\):\\\\s*(.*)$",
19+
"file": 1,
20+
"location": 2,
21+
"message": 3
22+
}
23+
]
24+
}
25+
}
26+
]
27+
}

browser/components/CodeEditor.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export default class CodeEditor extends React.Component {
6363

6464
this.formatTable = () => this.handleFormatTable()
6565
this.editorActivityHandler = () => this.handleEditorActivity()
66+
67+
this.turndownService = new TurndownService()
6668
}
6769

6870
handleSearch (msg) {
@@ -315,22 +317,28 @@ export default class CodeEditor extends React.Component {
315317
const snippetLines = snippets[i].content.split('\n')
316318
let cursorLineNumber = 0
317319
let cursorLinePosition = 0
320+
321+
let cursorIndex
318322
for (let j = 0; j < snippetLines.length; j++) {
319-
const cursorIndex = snippetLines[j].indexOf(templateCursorString)
323+
cursorIndex = snippetLines[j].indexOf(templateCursorString)
324+
320325
if (cursorIndex !== -1) {
321326
cursorLineNumber = j
322327
cursorLinePosition = cursorIndex
323-
cm.replaceRange(
324-
snippets[i].content.replace(templateCursorString, ''),
325-
wordBeforeCursor.range.from,
326-
wordBeforeCursor.range.to
327-
)
328-
cm.setCursor({
329-
line: cursor.line + cursorLineNumber,
330-
ch: cursorLinePosition
331-
})
328+
329+
break
332330
}
333331
}
332+
333+
cm.replaceRange(
334+
snippets[i].content.replace(templateCursorString, ''),
335+
wordBeforeCursor.range.from,
336+
wordBeforeCursor.range.to
337+
)
338+
cm.setCursor({
339+
line: cursor.line + cursorLineNumber,
340+
ch: cursorLinePosition + cursor.ch - wordBeforeCursor.text.length
341+
})
334342
} else {
335343
cm.replaceRange(
336344
snippets[i].content,

browser/components/MarkdownEditor.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,8 @@ class MarkdownEditor extends React.Component {
147147
e.preventDefault()
148148
e.stopPropagation()
149149
const idMatch = /checkbox-([0-9]+)/
150-
const checkedMatch = /\[x\]/i
151-
const uncheckedMatch = /\[ \]/
150+
const checkedMatch = /^\s*[\+\-\*] \[x\]/i
151+
const uncheckedMatch = /^\s*[\+\-\*] \[ \]/
152152
if (idMatch.test(e.target.getAttribute('id'))) {
153153
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
154154
const lines = this.refs.code.value
@@ -157,10 +157,10 @@ class MarkdownEditor extends React.Component {
157157
const targetLine = lines[lineIndex]
158158

159159
if (targetLine.match(checkedMatch)) {
160-
lines[lineIndex] = targetLine.replace(checkedMatch, '[ ]')
160+
lines[lineIndex] = targetLine.replace(checkedMatch, '- [ ]')
161161
}
162162
if (targetLine.match(uncheckedMatch)) {
163-
lines[lineIndex] = targetLine.replace(uncheckedMatch, '[x]')
163+
lines[lineIndex] = targetLine.replace(uncheckedMatch, '- [x]')
164164
}
165165
this.refs.code.setValue(lines.join('\n'))
166166
}

browser/components/MarkdownSplitEditor.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ class MarkdownSplitEditor extends React.Component {
7878
e.preventDefault()
7979
e.stopPropagation()
8080
const idMatch = /checkbox-([0-9]+)/
81-
const checkedMatch = /\[x\]/i
82-
const uncheckedMatch = /\[ \]/
81+
const checkedMatch = /^\s*[\+\-\*] \[x\]/i
82+
const uncheckedMatch = /^\s*[\+\-\*] \[ \]/
8383
if (idMatch.test(e.target.getAttribute('id'))) {
8484
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
8585
const lines = this.refs.code.value
@@ -88,10 +88,10 @@ class MarkdownSplitEditor extends React.Component {
8888
const targetLine = lines[lineIndex]
8989

9090
if (targetLine.match(checkedMatch)) {
91-
lines[lineIndex] = targetLine.replace(checkedMatch, '[ ]')
91+
lines[lineIndex] = targetLine.replace(checkedMatch, '- [ ]')
9292
}
9393
if (targetLine.match(uncheckedMatch)) {
94-
lines[lineIndex] = targetLine.replace(uncheckedMatch, '[x]')
94+
lines[lineIndex] = targetLine.replace(uncheckedMatch, '- [x]')
9595
}
9696
this.refs.code.setValue(lines.join('\n'))
9797
}

browser/lib/Languages.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,13 @@ const languages = [
4848
locale: 'pl'
4949
},
5050
{
51-
name: 'Portuguese',
51+
name: 'Portuguese (PT-BR)',
5252
locale: 'pt-BR'
5353
},
54+
{
55+
name: 'Portuguese (PT-PT)',
56+
locale: 'pt-PT'
57+
},
5458
{
5559
name: 'Russian',
5660
locale: 'ru'

browser/main/Main.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ class Main extends React.Component {
167167
}
168168
})
169169

170+
delete CodeMirror.keyMap.emacs['Ctrl-V']
171+
170172
eventEmitter.on('editor:fullscreen', this.toggleFullScreen)
171173
}
172174

browser/main/NoteList/index.js

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ class NoteList extends React.Component {
8383

8484
// TODO: not Selected noteKeys but SelectedNote(for reusing)
8585
this.state = {
86+
ctrlKeyDown: false,
8687
shiftKeyDown: false,
88+
prevShiftNoteIndex: -1,
8789
selectedNoteKeys: []
8890
}
8991

@@ -266,7 +268,7 @@ class NoteList extends React.Component {
266268
}
267269

268270
handleNoteListKeyDown (e) {
269-
if (e.metaKey || e.ctrlKey) return true
271+
if (e.metaKey) return true
270272

271273
// A key
272274
if (e.keyCode === 65 && !e.shiftKey) {
@@ -306,13 +308,19 @@ class NoteList extends React.Component {
306308

307309
if (e.shiftKey) {
308310
this.setState({ shiftKeyDown: true })
311+
} else if (e.ctrlKey) {
312+
this.setState({ ctrlKeyDown: true })
309313
}
310314
}
311315

312316
handleNoteListKeyUp (e) {
313317
if (!e.shiftKey) {
314318
this.setState({ shiftKeyDown: false })
315319
}
320+
321+
if (!e.ctrlKey) {
322+
this.setState({ ctrlKeyDown: false })
323+
}
316324
}
317325

318326
getNotes () {
@@ -389,25 +397,65 @@ class NoteList extends React.Component {
389397
return pinnedNotes.concat(unpinnedNotes)
390398
}
391399

400+
getNoteIndexByKey (noteKey) {
401+
return this.notes.findIndex((note) => {
402+
if (!note) return -1
403+
404+
return note.key === noteKey
405+
})
406+
}
407+
392408
handleNoteClick (e, uniqueKey) {
393409
const { router } = this.context
394410
const { location } = this.props
395-
let { selectedNoteKeys } = this.state
396-
const { shiftKeyDown } = this.state
411+
let { selectedNoteKeys, prevShiftNoteIndex } = this.state
412+
const { ctrlKeyDown, shiftKeyDown } = this.state
413+
const hasSelectedNoteKey = selectedNoteKeys.length > 0
397414

398-
if (shiftKeyDown && selectedNoteKeys.includes(uniqueKey)) {
415+
if (ctrlKeyDown && selectedNoteKeys.includes(uniqueKey)) {
399416
const newSelectedNoteKeys = selectedNoteKeys.filter((noteKey) => noteKey !== uniqueKey)
400417
this.setState({
401418
selectedNoteKeys: newSelectedNoteKeys
402419
})
403420
return
404421
}
405-
if (!shiftKeyDown) {
422+
if (!ctrlKeyDown && !shiftKeyDown) {
406423
selectedNoteKeys = []
407424
}
425+
426+
if (!shiftKeyDown) {
427+
prevShiftNoteIndex = -1
428+
}
429+
408430
selectedNoteKeys.push(uniqueKey)
431+
432+
if (shiftKeyDown && hasSelectedNoteKey) {
433+
let firstShiftNoteIndex = this.getNoteIndexByKey(selectedNoteKeys[0])
434+
// Shift selection can either start from first note in the exisiting selectedNoteKeys
435+
// or previous first shift note index
436+
firstShiftNoteIndex = firstShiftNoteIndex > prevShiftNoteIndex
437+
? firstShiftNoteIndex : prevShiftNoteIndex
438+
439+
const lastShiftNoteIndex = this.getNoteIndexByKey(uniqueKey)
440+
441+
const startIndex = firstShiftNoteIndex < lastShiftNoteIndex
442+
? firstShiftNoteIndex : lastShiftNoteIndex
443+
const endIndex = firstShiftNoteIndex > lastShiftNoteIndex
444+
? firstShiftNoteIndex : lastShiftNoteIndex
445+
446+
selectedNoteKeys = []
447+
for (let i = startIndex; i <= endIndex; i++) {
448+
selectedNoteKeys.push(this.notes[i].key)
449+
}
450+
451+
if (prevShiftNoteIndex < 0) {
452+
prevShiftNoteIndex = firstShiftNoteIndex
453+
}
454+
}
455+
409456
this.setState({
410-
selectedNoteKeys
457+
selectedNoteKeys,
458+
prevShiftNoteIndex
411459
})
412460

413461
router.push({

browser/main/SideNav/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {SortableContainer} from 'react-sortable-hoc'
1919
import i18n from 'browser/lib/i18n'
2020
import context from 'browser/lib/context'
2121
import { remote } from 'electron'
22+
import { confirmDeleteNote } from 'browser/lib/confirmDeleteNote'
2223

2324
function matchActiveTags (tags, activeTags) {
2425
return _.every(activeTags, v => tags.indexOf(v) >= 0)
@@ -269,7 +270,7 @@ class SideNav extends React.Component {
269270
const tags = pathSegments[pathSegments.length - 1]
270271
return (tags === 'alltags')
271272
? []
272-
: tags.split(' ').map(tag => decodeURIComponent(tag))
273+
: decodeURIComponent(tags).split(' ')
273274
}
274275

275276
handleClickTagListItem (name) {
@@ -301,14 +302,16 @@ class SideNav extends React.Component {
301302
} else {
302303
listOfTags.push(tag)
303304
}
304-
router.push(`/tags/${listOfTags.map(tag => encodeURIComponent(tag)).join(' ')}`)
305+
router.push(`/tags/${encodeURIComponent(listOfTags.join(' '))}`)
305306
}
306307

307308
emptyTrash (entries) {
308309
const { dispatch } = this.props
309310
const deletionPromises = entries.map((note) => {
310311
return dataApi.deleteNote(note.storage, note.key)
311312
})
313+
const { confirmDeletion } = this.props.config.ui
314+
if (!confirmDeleteNote(confirmDeletion, true)) return
312315
Promise.all(deletionPromises)
313316
.then((arrayOfStorageAndNoteKeys) => {
314317
arrayOfStorageAndNoteKeys.forEach(({ storageKey, noteKey }) => {

docs/debug.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# How to debug Boostnote (Electron app)
2+
23
This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md) and [German](https://github.com/BoostIO/Boostnote/blob/master/docs/de/debug.md).
34

5+
## Debug with Google Chrome developer Tools
46
Boostnote is an Electron app so it's based on Chromium; developers can use `Developer Tools` just like Google Chrome.
57

68
You can toggle the `Developer Tools` like this:
@@ -11,12 +13,24 @@ The `Developer Tools` will look like this:
1113

1214
When errors occur, the error messages are displayed at the `console`.
1315

14-
## Debugging
16+
### Debugging
1517
For example, you can use the `debugger` to set a breakpoint in the code like this:
1618

1719
![debugger](https://cloud.githubusercontent.com/assets/11307908/24343879/9459efea-127d-11e7-9943-f60bf7f66d4a.png)
1820

1921
This is just an illustrative example, you should find a way to debug which fits your style.
2022

21-
## References
23+
### References
2224
* [Official document of Google Chrome about debugging](https://developer.chrome.com/devtools)
25+
26+
## Debug with Visual Studio Code
27+
28+
1. Install **[Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome "Install Debugger for Chrome")** plugin for Visual Studio Code. Then restart it.
29+
2. Pressing **Shift+Command+B** or running **Run Build Task** from the global **Terminal** menu, then pick the task named **Build Boostnote**. Or run `yarn run watch` from the terminal.
30+
3. When above task is running, open **Debug view** in **Activity Bar** on the side of VS Code or use shortcut **Shift+Command+D**.
31+
4. Select the configuration named **Boostnote All** from the **Debug configuration**, then click the green arrow button or press **F5** to start debugging.
32+
5. Now you should find **Boostnote** is running. You will see two processes running, one named **Boostnote Main** and the other named **Boostnote Renderer**. Now you can set **debug breakpoints** in vscode. If you find your **breakpoints** is unverified, you need to switch to the appropriate process between **Boostnote Renderer** and **Boostnote Main**.
33+
34+
### References
35+
* [Electron application debugging](https://electronjs.org/docs/tutorial/application-debugging)
36+
* [Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome)

0 commit comments

Comments
 (0)