1
0
mirror of https://github.com/BoostIo/Boostnote synced 2025-12-14 18:26:26 +00:00

Compare commits

..

57 Commits

Author SHA1 Message Date
Kohei TAKATA
a7a5b789fa Merge pull request #1230 from BoostIO/feature-v0-8-18
v0.8.18
2017-12-03 11:51:11 +09:00
Kohei TAKATA
10b7d58dc6 v0.8.18 2017-12-03 11:08:06 +09:00
Kazz Yokomizo
16f0e95e32 Merge pull request #1226 from BoostIO/add-newsletter
Add newsletter link to preference modal
2017-12-02 15:45:36 +09:00
Kazu Yokomizo
55395d3a2d Add newsletter link to preference modal 2017-12-02 15:41:43 +09:00
Kazz Yokomizo
4e0fa63fad Merge pull request #1225 from BoostIO/fix-finder-layout
Fix finder layout
2017-12-02 15:33:55 +09:00
Kazu Yokomizo
b9ea7696d8 Fix finder layout 2017-12-02 15:20:16 +09:00
Kazz Yokomizo
7de3308f52 Merge pull request #1223 from BoostIO/fixbug-cannot-open-finder
fix bug cannot open finder.
2017-12-02 15:07:19 +09:00
Kazz Yokomizo
b2b2373c7b Merge pull request #1218 from PaulRosset/fixbug-react-code-mirror
Fixbug react code mirror
2017-12-02 15:03:19 +09:00
Sosuke Suzuki
1c54f40a28 require ipcClient 2017-12-02 14:07:11 +09:00
Paul Rosset
4735992835 Fix 2017-12-01 17:24:28 +00:00
Paul Rosset
cba3519458 Fix 2017-12-01 17:19:21 +00:00
Paul Rosset
c64a5e1cca Correction eslint purpose 2017-12-01 17:10:04 +00:00
Paul Rosset
47ee8b8ce7 Fix bug on UI Tab in relation to React CodeMirror 2017-12-01 16:56:43 +00:00
Kazz Yokomizo
455b424429 Merge pull request #1211 from yosmoc/tagconfirm_onblur
confirm tag at onBlur event
2017-12-01 15:11:47 +09:00
Kazz Yokomizo
7d67ac3f12 Merge pull request #1212 from PaulRosset/correct-notification-area
Correction Notification top-left
2017-12-01 15:04:40 +09:00
Paul Rosset
34f377eb5c Correction Notification top-left 2017-11-30 21:32:28 +00:00
yosmoc
b7f4af8c78 confirm tag at onBlur event
When user inputs the tag and leave the tag input box without fixing(enter or tab key), tag string is still there, but it is not stored as a tag.

This changes solved this problem. When the cursol is out of the tag input, it registers the input as a tag.
2017-11-30 22:04:56 +01:00
Kazz Yokomizo
a6c7dde194 Merge pull request #1202 from BoostIO/fix-folded-layout
Fix folded layout
2017-11-29 16:51:28 +09:00
Kazu Yokomizo
43ebe4ecfd FIx folded layout 2017-11-29 16:43:26 +09:00
Kazz Yokomizo
1d38f1abb4 Merge pull request #1197 from BoostIO/fix-initialmodal-layout
Fix layout at initial modal
2017-11-28 16:44:07 +09:00
Kazu Yokomizo
061a0cd219 Fix layout at initial modal 2017-11-28 16:27:12 +09:00
Kazz Yokomizo
f0ed20ee2c Merge pull request #1184 from cormoran/fix/SideNavFoldEmoji
Fix surrogate pairs garbling on folded SideNav
2017-11-28 12:42:41 +09:00
Kazz Yokomizo
edfc8d95c8 Merge pull request #1070 from voidsatisfaction/feature/add_multiselect_notes_delete
Feature multiselect notes delete and move to another folder
2017-11-28 12:39:12 +09:00
voidSatisfaction
c33f9d8307 fix: from let to const 2017-11-27 14:31:11 +09:00
voidSatisfaction
eee212f5b8 Merge with master resolve conflict 2017-11-27 14:05:26 +09:00
Kazz Yokomizo
b690147b0b Merge pull request #1187 from BoostIO/fix-note-list
Fix note list layout
2017-11-27 11:26:27 +09:00
Kazu Yokomizo
10879d0f67 Fix note list layout 2017-11-27 11:22:21 +09:00
Kazz Yokomizo
b48b8f39fc Merge pull request #1144 from whizark/store-window-size-on-linux
store correct window size on Linux
2017-11-27 11:06:56 +09:00
cormoran
3d0b3e759b Fix surrogate pairs garbling on folded SideNav 2017-11-27 06:04:24 +09:00
Kazz Yokomizo
3e7f4a41e2 Merge pull request #1183 from BoostIO/update-backers
Update Backers
2017-11-27 03:03:57 +09:00
Kazz Yokomizo
b89b888129 Update Backers 2017-11-27 02:57:17 +09:00
Kazz Yokomizo
cba9afc9ba Merge pull request #1180 from romainwn/fix/SideNavFilter-Hover
SideNavItem: add background when hover
2017-11-26 19:33:16 +09:00
Unknown
a66a11b81e SideNavItem: add background when hover 2017-11-26 11:21:49 +01:00
Kazz Yokomizo
22cc2791b6 Merge pull request #1179 from BoostIO/fix-margin-notedetail
Fix Margin at Note Detail
2017-11-26 16:24:36 +09:00
Kazu Yokomizo
369cf16b68 Fix Margin at Note Detail 2017-11-26 16:14:52 +09:00
Kazz Yokomizo
0d38baf194 Merge pull request #1176 from yosmoc/initmodal_exit_fix
fix anykey can close the initmodal window issue
2017-11-26 16:05:38 +09:00
Kazz Yokomizo
5b63c95f40 Merge pull request #1178 from BoostIO/fix-typo
Fix typo
2017-11-26 15:57:36 +09:00
Kazu Yokomizo
52497999a0 Fix typo 2017-11-26 15:50:45 +09:00
Kohei TAKATA
6bab108a35 Merge pull request #1113 from yosmoc/react_proptypes_deprecated
React.PropTypes is deprecated from React 15.5
2017-11-26 09:22:38 +09:00
yosmoc
eec22e6b7d fix anykey can close the initmodal issue
this change makes only ESC key can close the initmodal window.
2017-11-25 23:39:59 +01:00
yosmoc
edaa0713e8 React.PropTypes is deprecated from React 15.5
Migrated by react-codemod + minor fix by hand.
2017-11-25 22:27:04 +01:00
Kohei TAKATA
6b6a415dd5 Merge pull request #1170 from mslourens/reduce-lint-errors
fixed eslint warnings
2017-11-25 17:43:13 +09:00
Maurits Lourens
3fbc749395 fixed eslint warnings 2017-11-24 17:00:03 +01:00
Whizark
460437397f store window size on Linux 2017-11-19 21:10:53 +09:00
voidSatisfaction
a36e779980 refactor: add new function and fix problems from feedbacks 2017-11-15 23:19:47 +09:00
voidSatisfaction
84f18ced47 fix: pintotop error 2017-11-07 23:07:39 +09:00
voidSatisfaction
037ff2e749 Merge branch 'master' into feature/add_multiselect_notes_delete 2017-11-07 22:53:14 +09:00
voidSatisfaction
f0f23ede3d Merge branch 'master' into feature/add_multiselect_notes_delete 2017-11-07 22:48:50 +09:00
voidSatisfaction
c8763063c0 resolve conflict with master 2017-11-07 22:47:08 +09:00
voidSatisfaction
e57fef2413 refactor: add utils 2017-11-07 22:38:28 +09:00
voidSatisfaction
9095fe934d add multi selection with arrow short cut 2017-11-07 00:01:50 +09:00
voidSatisfaction
9139495f02 feat: add multiple pin to top and rename activateNote to focusNote 2017-11-06 21:53:31 +09:00
voidSatisfaction
bcb1fb4331 feat multi drag and drop for changing folder 2017-11-05 21:18:39 +09:00
voidSatisfaction
70b69a3bc9 refactor: inner codes 2017-11-05 19:22:55 +09:00
voidSatisfaction
a7e458b784 feat change name and add deletion logic 2017-11-05 19:00:03 +09:00
voidSatisfaction
a504a45d99 fix up and down key rendering problems 2017-11-05 18:45:09 +09:00
voidSatisfaction
2d0e14c1cc feat: add shiftkey multiselect notes and delete 2017-11-05 18:11:08 +09:00
102 changed files with 860 additions and 615 deletions

View File

@@ -12,5 +12,10 @@
"react/no-find-dom-node": "warn",
"react/no-render-return-value": "warn",
"react/no-deprecated": "warn"
},
"globals": {
"FileReader": true,
"localStorage": true,
"fetch": true
}
}

View File

@@ -1,27 +1,50 @@
<h1 align="center">Sponsors &amp; Backers</h1>
Boostnote is an open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [backers](https://github.com/BoostIO/Boostnote/blob/master/Backers.md). If you'd like to join them, please consider:
Boostnote is an open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome backers. If you'd like to join them, please consider:
- [Become a backer or sponsor on Open Collective.](https://opencollective.com/boostnoteio)
---
## Backers via OpenCollective
<a href="https://opencollective.com/boostnoteio#backers" target="_blank"><img src="https://opencollective.com/boostnoteio/backers.svg?width=890"></a>
- [Ralph03](https://opencollective.com/ralph03) - $24
### [Gold Sponsors / $1,000 per month](https://opencollective.com/boostnoteio/order/2259)
- Get your logo on our Readme.md on GitHub and the frontpage of https://boostnote.io/.
- [Nikolas Dan](https://opencollective.com/nikolas-dan) - $20
### [Silver Sponsors / $250 per month](https://opencollective.com/boostnoteio/order/2257)
- Get your logo on our Readme.md on GitHub and the frontpage of https://boostnote.io/.
- [tatoosh11](https://twitter.com/ta11) - $10
### [Bronze Sponsors / $50 per month](https://opencollective.com/boostnoteio/order/2258)
- Get your name and Url (or E-mail) on Readme.md on GitHub.
- [Alexander Borovkov](https://opencollective.com/alexander-borovkov) - $10
### [Backers3 / $10 per month](https://opencollective.com/boostnoteio/order/2176)
- [Ralph03](https://opencollective.com/ralph03)
- [Yeojong Kim](https://twitter.com/yeojoy) - $5
- [Nikolas Dan](https://opencollective.com/nikolas-dan)
- [Scotia Draven](https://opencollective.com/scotia-draven) - $5
### [Backers2 / $5 per month](https://opencollective.com/boostnoteio/order/2175)
- [Yeojong Kim](https://twitter.com/yeojoy)
- [spoonhoop](https://opencollective.com/spoonhoop) - $5
- [Scotia Draven](https://opencollective.com/scotia-draven)
- [A. J. Vargas](https://opencollective.com/aj-vargas)
### [Backers1](https://opencollective.com/boostnoteio/order/2563) and One-time sponsors
- Ryosuke Tamura - $30
- tatoosh11 - $10
- Alexander Borovkov - $10
- spoonhoop - $5
- Drew Williams - $2
- Andy Shaw - $2
- mysafesky -$2
---
## Backers via Bountysource
https://salt.bountysource.com/teams/boostnote

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import _ from 'lodash'
import CodeMirror from 'codemirror'
import path from 'path'
@@ -103,7 +104,7 @@ export default class CodeEditor extends React.Component {
this.editor.on('change', this.changeHandler)
this.editor.on('paste', this.pasteHandler)
let editorTheme = document.getElementById('editorTheme')
const editorTheme = document.getElementById('editorTheme')
editorTheme.addEventListener('load', this.loadStyleHandler)
CodeMirror.Vim.defineEx('quit', 'q', this.quitEditor)
@@ -121,7 +122,7 @@ export default class CodeEditor extends React.Component {
this.editor.off('blur', this.blurHandler)
this.editor.off('change', this.changeHandler)
this.editor.off('paste', this.pasteHandler)
let editorTheme = document.getElementById('editorTheme')
const editorTheme = document.getElementById('editorTheme')
editorTheme.removeEventListener('load', this.loadStyleHandler)
}
@@ -197,7 +198,7 @@ export default class CodeEditor extends React.Component {
}
setValue (value) {
let cursor = this.editor.getCursor()
const cursor = this.editor.getCursor()
this.editor.setValue(value)
this.editor.setCursor(cursor)
}
@@ -222,7 +223,7 @@ export default class CodeEditor extends React.Component {
if (!dataTransferItem.type.match('image')) return
const blob = dataTransferItem.getAsFile()
let reader = new FileReader()
const reader = new FileReader()
let base64data
reader.readAsDataURL(blob)
@@ -242,7 +243,8 @@ export default class CodeEditor extends React.Component {
}
render () {
let { className, fontFamily, fontSize } = this.props
const { className, fontSize } = this.props
let fontFamily = this.props.className
fontFamily = _.isString(fontFamily) && fontFamily.length > 0
? [fontFamily].concat(defaultEditorFontFamily)
: defaultEditorFontFamily

View File

@@ -1,11 +1,11 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './MarkdownEditor.styl'
import CodeEditor from 'browser/components/CodeEditor'
import MarkdownPreview from 'browser/components/MarkdownPreview'
import eventEmitter from 'browser/main/lib/eventEmitter'
import { findStorage } from 'browser/lib/findStorage'
const _ = require('lodash')
class MarkdownEditor extends React.Component {
constructor (props) {
@@ -70,9 +70,9 @@ class MarkdownEditor extends React.Component {
}
handleContextMenu (e) {
let { config } = this.props
const { config } = this.props
if (config.editor.switchPreview === 'RIGHTCLICK') {
let newStatus = this.state.status === 'PREVIEW'
const newStatus = this.state.status === 'PREVIEW'
? 'CODE'
: 'PREVIEW'
this.setState({
@@ -91,9 +91,9 @@ class MarkdownEditor extends React.Component {
handleBlur (e) {
if (this.state.isLocked) return
this.setState({ keyPressed: new Set() })
let { config } = this.props
const { config } = this.props
if (config.editor.switchPreview === 'BLUR') {
let cursorPosition = this.refs.code.editor.getCursor()
const cursorPosition = this.refs.code.editor.getCursor()
this.setState({
status: 'PREVIEW'
}, () => {
@@ -109,7 +109,7 @@ class MarkdownEditor extends React.Component {
}
handlePreviewMouseUp (e) {
let { config } = this.props
const { config } = this.props
if (config.editor.switchPreview === 'BLUR' && new Date() - this.previewMouseDownedAt < 200) {
this.setState({
status: 'CODE'
@@ -123,15 +123,15 @@ class MarkdownEditor extends React.Component {
handleCheckboxClick (e) {
e.preventDefault()
e.stopPropagation()
let idMatch = /checkbox-([0-9]+)/
let checkedMatch = /\[x\]/i
let uncheckedMatch = /\[ \]/
const idMatch = /checkbox-([0-9]+)/
const checkedMatch = /\[x\]/i
const uncheckedMatch = /\[ \]/
if (idMatch.test(e.target.getAttribute('id'))) {
let lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
let lines = this.refs.code.value
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
const lines = this.refs.code.value
.split('\n')
let targetLine = lines[lineIndex]
const targetLine = lines[lineIndex]
if (targetLine.match(checkedMatch)) {
lines[lineIndex] = targetLine.replace(checkedMatch, '[ ]')
@@ -163,12 +163,12 @@ class MarkdownEditor extends React.Component {
}
handleKeyDown (e) {
let { config } = this.props
const { config } = this.props
if (this.state.status !== 'CODE') return false
const keyPressed = this.state.keyPressed
keyPressed.add(e.keyCode)
this.setState({ keyPressed })
let isNoteHandlerKey = (el) => { return keyPressed.has(el) }
const isNoteHandlerKey = (el) => { return keyPressed.has(el) }
// These conditions are for ctrl-e and ctrl-w
if (keyPressed.size === this.escapeFromEditor.length &&
!this.state.isLocked && this.state.status === 'CODE' &&
@@ -207,14 +207,14 @@ class MarkdownEditor extends React.Component {
}
render () {
let { className, value, config, storageKey } = this.props
const { className, value, config, storageKey } = this.props
let editorFontSize = parseInt(config.editor.fontSize, 10)
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
let editorIndentSize = parseInt(config.editor.indentSize, 10)
if (!(editorFontSize > 0 && editorFontSize < 132)) editorIndentSize = 4
let previewStyle = {}
const previewStyle = {}
if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none'
const storage = findStorage(storageKey)

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import markdown from 'browser/lib/markdown'
import _ from 'lodash'
import CodeMirror from 'codemirror'
@@ -126,10 +127,10 @@ export default class MarkdownPreview extends React.Component {
e.preventDefault()
e.stopPropagation()
let anchor = e.target.closest('a')
let href = anchor.getAttribute('href')
const anchor = e.target.closest('a')
const href = anchor.getAttribute('href')
if (_.isString(href) && href.match(/^#/)) {
let targetElement = this.refs.root.contentWindow.document.getElementById(href.substring(1, href.length))
const targetElement = this.refs.root.contentWindow.document.getElementById(href.substring(1, href.length))
if (targetElement != null) {
this.getWindow().scrollTo(0, targetElement.offsetTop)
}
@@ -251,7 +252,8 @@ export default class MarkdownPreview extends React.Component {
}
applyStyle () {
let { fontFamily, fontSize, codeBlockFontFamily, lineNumber, codeBlockTheme } = this.props
const { fontSize, lineNumber, codeBlockTheme } = this.props
let { fontFamily, codeBlockFontFamily } = this.props
fontFamily = _.isString(fontFamily) && fontFamily.trim().length > 0
? [fontFamily].concat(defaultFontFamily)
: defaultFontFamily
@@ -284,7 +286,8 @@ export default class MarkdownPreview extends React.Component {
el.removeEventListener('click', this.linkClickHandler)
})
let { value, theme, indentSize, codeBlockTheme, showCopyNotification, storagePath } = this.props
const { theme, indentSize, showCopyNotification, storagePath } = this.props
let { value, codeBlockTheme } = this.props
this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme)
@@ -327,7 +330,7 @@ export default class MarkdownPreview extends React.Component {
let syntax = CodeMirror.findModeByName(el.className)
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
CodeMirror.requireMode(syntax.mode, () => {
let content = htmlTextHelper.decodeEntities(el.innerHTML)
const content = htmlTextHelper.decodeEntities(el.innerHTML)
const copyIcon = document.createElement('i')
copyIcon.innerHTML = '<button class="clipboardButton"><svg width="13" height="13" viewBox="0 0 1792 1792" ><path d="M768 1664h896v-640h-416q-40 0-68-28t-28-68v-416h-384v1152zm256-1440v-64q0-13-9.5-22.5t-22.5-9.5h-704q-13 0-22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h704q13 0 22.5-9.5t9.5-22.5zm256 672h299l-299-299v299zm512 128v672q0 40-28 68t-68 28h-960q-40 0-68-28t-28-68v-160h-544q-40 0-68-28t-28-68v-1344q0-40 28-68t68-28h1088q40 0 68 28t28 68v328q21 13 36 28l408 408q28 28 48 76t20 88z"/></svg></button>'
copyIcon.onclick = (e) => {
@@ -352,7 +355,7 @@ export default class MarkdownPreview extends React.Component {
})
})
})
let opts = {}
const opts = {}
// if (this.props.theme === 'dark') {
// opts['font-color'] = '#DDD'
// opts['line-color'] = '#DDD'
@@ -362,7 +365,7 @@ export default class MarkdownPreview extends React.Component {
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.flowchart'), (el) => {
Raphael.setWindow(this.getWindow())
try {
let diagram = flowchart.parse(htmlTextHelper.decodeEntities(el.innerHTML))
const diagram = flowchart.parse(htmlTextHelper.decodeEntities(el.innerHTML))
el.innerHTML = ''
diagram.drawSVG(el, opts)
_.forEach(el.querySelectorAll('a'), (el) => {
@@ -378,7 +381,7 @@ export default class MarkdownPreview extends React.Component {
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.sequence'), (el) => {
Raphael.setWindow(this.getWindow())
try {
let diagram = SequenceDiagram.parse(htmlTextHelper.decodeEntities(el.innerHTML))
const diagram = SequenceDiagram.parse(htmlTextHelper.decodeEntities(el.innerHTML))
el.innerHTML = ''
diagram.drawSVG(el, {theme: 'simple'})
_.forEach(el.querySelectorAll('a'), (el) => {
@@ -401,11 +404,11 @@ export default class MarkdownPreview extends React.Component {
}
scrollTo (targetRow) {
let blocks = this.getWindow().document.querySelectorAll('body>[data-line]')
const blocks = this.getWindow().document.querySelectorAll('body>[data-line]')
for (let index = 0; index < blocks.length; index++) {
let block = blocks[index]
let row = parseInt(block.getAttribute('data-line'))
const row = parseInt(block.getAttribute('data-line'))
if (row > targetRow || index === blocks.length - 1) {
block = blocks[index - 1]
block != null && this.getWindow().scrollTo(0, block.offsetTop)
@@ -435,7 +438,7 @@ export default class MarkdownPreview extends React.Component {
}
render () {
let { className, style, tabIndex } = this.props
const { className, style, tabIndex } = this.props
return (
<iframe className={className != null
? 'MarkdownPreview ' + className

View File

@@ -1,4 +1,5 @@
import React, {PropTypes} from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './ModalEscButton.styl'

View File

@@ -1,7 +1,8 @@
/**
* @fileoverview Micro component for toggle SideNav
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import styles from './NavToggleButton.styl'
import CSSModules from 'browser/lib/CSSModules'

View File

@@ -1,7 +1,8 @@
/**
* @fileoverview Note item component.
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import { isArray } from 'lodash'
import CSSModules from 'browser/lib/CSSModules'
import { getTodoStatus } from 'browser/lib/getTodoStatus'

View File

@@ -73,6 +73,7 @@ $control-height = 30px
position relative
font-size 12px
color $ui-inactive-text-color
top 2px
.item-title
font-size 15px
@@ -80,8 +81,8 @@ $control-height = 30px
position relative
top -12px
left 20px
padding-right 15px
padding-bottom 4px
padding 0px 15px 0px 0px
margin-bottom 4px
overflow ellipsis
color $ui-inactive-text-color

View File

@@ -1,7 +1,8 @@
/**
* @fileoverview Note item component with simple display mode.
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './NoteItemSimple.styl'

View File

@@ -1,4 +1,4 @@
import React, { PropTypes } from 'react'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './RealtimeNotification.styl'

View File

@@ -1,11 +1,8 @@
.notification-area
z-index 1000
font-size 12px
position absolute
bottom 20px
width 100%
float left
height 30px
position: relative
top: 12px
background-color none
.notification-link

View File

@@ -1,7 +1,8 @@
/**
* @fileoverview Filter for all notes.
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './SideNavFilter.styl'

View File

@@ -57,9 +57,13 @@
@extend .menu
.menu-button, .menu-button--active
text-align center
padding 0 12px
&:hover .menu-button-label
transition opacity 0.15s
opacity 1
color $ui-tooltip-text-color
background-color $ui-tooltip-backgroundColor
.menu-button-label
position fixed

View File

@@ -86,7 +86,7 @@ class SnippetTab extends React.Component {
}
render () {
let { isActive, snippet, isDeletable } = this.props
const { isActive, snippet, isDeletable } = this.props
return (
<div styleName={isActive
? 'root--active'

View File

@@ -1,10 +1,11 @@
/**
* @fileoverview Micro component for showing storage.
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import styles from './StorageItem.styl'
import CSSModules from 'browser/lib/CSSModules'
import { isNumber } from 'lodash'
import _ from 'lodash'
/**
* @param {boolean} isActive
@@ -36,9 +37,9 @@ const StorageItem = ({
<span styleName={isFolded
? 'folderList-item-name--folded' : 'folderList-item-name'
}>
<text style={{color: folderColor, paddingRight: '10px'}}>{isActive ? <i className='fa fa-folder-open-o' /> : <i className='fa fa-folder-o' />}</text>{isFolded ? folderName.substring(0, 1) : folderName}
<text style={{color: folderColor, paddingRight: '10px'}}>{isActive ? <i className='fa fa-folder-open-o' /> : <i className='fa fa-folder-o' />}</text>{isFolded ? _.truncate(folderName, {length: 1, omission: ''}) : folderName}
</span>
{(!isFolded && isNumber(noteCount)) &&
{(!isFolded && _.isNumber(noteCount)) &&
<span styleName='folderList-item-noteCount'>{noteCount}</span>
}
{isFolded &&

View File

@@ -68,9 +68,9 @@
.folderList-item-name--folded
@extend .folderList-item-name
padding-left 17px
padding-left 7px
text
display none
font-size 9px
body[data-theme="white"]
.folderList-item

View File

@@ -1,7 +1,8 @@
/**
* @fileoverview Micro component for showing StorageList
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import styles from './StorageList.styl'
import CSSModules from 'browser/lib/CSSModules'

View File

@@ -1,7 +1,8 @@
/**
* @fileoverview Micro component for showing TagList.
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import styles from './TagListItem.styl'
import CSSModules from 'browser/lib/CSSModules'

View File

@@ -2,7 +2,8 @@
* @fileoverview Percentage of todo achievement.
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './TodoListPercentage.styl'

View File

@@ -2,7 +2,8 @@
* @fileoverview Percentage of todo achievement.
*/
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './TodoProcess.styl'

View File

@@ -56,7 +56,7 @@ class NoteDetail extends React.Component {
}
selectPriorSnippet () {
let { note } = this.props
const { note } = this.props
if (note.type === 'SNIPPET_NOTE' && note.snippets.length > 1) {
this.setState({
snippetIndex: (this.state.snippetIndex + note.snippets.length - 1) % note.snippets.length
@@ -65,7 +65,7 @@ class NoteDetail extends React.Component {
}
selectNextSnippet () {
let { note } = this.props
const { note } = this.props
if (note.type === 'SNIPPET_NOTE' && note.snippets.length > 1) {
this.setState({
snippetIndex: (this.state.snippetIndex + 1) % note.snippets.length
@@ -74,7 +74,7 @@ class NoteDetail extends React.Component {
}
saveToClipboard () {
let { note } = this.props
const { note } = this.props
if (note.type === 'MARKDOWN_NOTE') {
clipboard.writeText(note.content)
@@ -95,7 +95,7 @@ class NoteDetail extends React.Component {
}
render () {
let { note, config } = this.props
const { note, config } = this.props
if (note == null) {
return (
<div styleName='root' />
@@ -110,8 +110,8 @@ class NoteDetail extends React.Component {
const storage = findStorage(note.storage)
if (note.type === 'SNIPPET_NOTE') {
let tabList = note.snippets.map((snippet, index) => {
let isActive = this.state.snippetIndex === index
const tabList = note.snippets.map((snippet, index) => {
const isActive = this.state.snippetIndex === index
return <div styleName={isActive
? 'tabList-item--active'
: 'tabList-item'
@@ -131,8 +131,8 @@ class NoteDetail extends React.Component {
</div>
})
let viewList = note.snippets.map((snippet, index) => {
let isActive = this.state.snippetIndex === index
const viewList = note.snippets.map((snippet, index) => {
const isActive = this.state.snippetIndex === index
let syntax = CodeMirror.findModeByName(pass(snippet.mode))
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')

View File

@@ -3,8 +3,7 @@
.root
absolute top bottom left right
bottom 30px
left $note-detail-left-margin
right $note-detail-right-margin
margin 0 25px
height 100%
width 365px
background-color $ui-noteDetail-backgroundColor

View File

@@ -18,18 +18,18 @@ class NoteList extends React.Component {
}
componentDidUpdate () {
let { index } = this.props
const { index } = this.props
if (index > -1) {
let list = this.refs.root
let item = list.childNodes[index]
const list = this.refs.root
const item = list.childNodes[index]
if (item == null) return null
let overflowBelow = item.offsetTop + item.clientHeight - list.clientHeight - list.scrollTop > 0
const overflowBelow = item.offsetTop + item.clientHeight - list.clientHeight - list.scrollTop > 0
if (overflowBelow) {
list.scrollTop = item.offsetTop + item.clientHeight - list.clientHeight
}
let overflowAbove = list.scrollTop > item.offsetTop
const overflowAbove = list.scrollTop > item.offsetTop
if (overflowAbove) {
list.scrollTop = item.offsetTop
}
@@ -44,7 +44,7 @@ class NoteList extends React.Component {
}
handleScroll (e) {
let { notes } = this.props
const { notes } = this.props
if (e.target.offsetHeight + e.target.scrollTop > e.target.scrollHeight - 100 && notes.length > this.state.range * 10 + 10) {
this.setState({
@@ -54,9 +54,9 @@ class NoteList extends React.Component {
}
render () {
let { notes, index } = this.props
const { notes, index } = this.props
let notesList = notes
const notesList = notes
.slice(0, 10 + 10 * this.state.range)
.map((note, _index) => {
const isActive = (index === _index)

View File

@@ -19,18 +19,18 @@ class StorageSection extends React.Component {
}
handleHeaderClick (e) {
let { storage } = this.props
const { storage } = this.props
this.props.handleStorageButtonClick(e, storage.key)
}
handleFolderClick (e, folder) {
let { storage } = this.props
const { storage } = this.props
this.props.handleFolderButtonClick(e, storage.key, folder.key)
}
render () {
let { storage, filter } = this.props
let folderList = storage.folders
const { storage, filter } = this.props
const folderList = storage.folders
.map(folder => (
<StorageItem
key={folder.key}

View File

@@ -1,8 +1,8 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import ReactDOM from 'react-dom'
import { connect, Provider } from 'react-redux'
import _ from 'lodash'
import ipc from './ipcClient'
import store from './store'
import CSSModules from 'browser/lib/CSSModules'
import styles from './FinderMain.styl'
@@ -13,13 +13,14 @@ import SideNavFilter from 'browser/components/SideNavFilter'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
require('!!style!css!stylus?sourceMap!../main/global.styl')
require('../lib/customMeta')
require('./ipcClient.js')
const electron = require('electron')
const { remote } = electron
const { Menu } = remote
function hideFinder () {
let finderWindow = remote.getCurrentWindow()
const finderWindow = remote.getCurrentWindow()
if (global.process.platform === 'win32') {
finderWindow.blur()
finderWindow.hide()
@@ -136,7 +137,7 @@ class FinderMain extends React.Component {
}
handleOnlySnippetCheckboxChange (e) {
let { filter } = this.state
const { filter } = this.state
filter.includeSnippet = e.target.checked
this.setState({
filter: filter,
@@ -147,7 +148,7 @@ class FinderMain extends React.Component {
}
handleOnlyMarkdownCheckboxChange (e) {
let { filter } = this.state
const { filter } = this.state
filter.includeMarkdown = e.target.checked
this.refs.list.resetScroll()
this.setState({
@@ -159,7 +160,7 @@ class FinderMain extends React.Component {
}
handleAllNotesButtonClick (e) {
let { filter } = this.state
const { filter } = this.state
filter.type = 'ALL'
this.refs.list.resetScroll()
this.setState({
@@ -171,7 +172,7 @@ class FinderMain extends React.Component {
}
handleStarredButtonClick (e) {
let { filter } = this.state
const { filter } = this.state
filter.type = 'STARRED'
this.refs.list.resetScroll()
this.setState({
@@ -183,7 +184,7 @@ class FinderMain extends React.Component {
}
handleStorageButtonClick (e, storage) {
let { filter } = this.state
const { filter } = this.state
filter.type = 'STORAGE'
filter.storage = storage
this.refs.list.resetScroll()
@@ -196,7 +197,7 @@ class FinderMain extends React.Component {
}
handleFolderButtonClick (e, storage, folder) {
let { filter } = this.state
const { filter } = this.state
filter.type = 'FOLDER'
filter.storage = storage
filter.folder = folder
@@ -218,12 +219,12 @@ class FinderMain extends React.Component {
}
render () {
let { data, config } = this.props
let { filter, search } = this.state
let storageList = []
for (let key in data.storageMap) {
let storage = data.storageMap[key]
let item = (
const { data, config } = this.props
const { filter, search } = this.state
const storageList = []
for (const key in data.storageMap) {
const storage = data.storageMap[key]
const item = (
<StorageSection
filter={filter}
storage={storage}
@@ -252,7 +253,7 @@ class FinderMain extends React.Component {
notes.push(data.noteMap[id])
})
} else {
for (let key in data.noteMap) {
for (const key in data.noteMap) {
notes.push(data.noteMap[key])
}
}
@@ -264,13 +265,13 @@ class FinderMain extends React.Component {
}
if (search.trim().length > 0) {
let needle = new RegExp(_.escapeRegExp(search.trim()), 'i')
const needle = new RegExp(_.escapeRegExp(search.trim()), 'i')
notes = notes.filter((note) => note.title.match(needle))
}
notes = notes
.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt))
let activeNote = notes[this.state.index]
const activeNote = notes[this.state.index]
this.noteCount = notes.length
return (

View File

@@ -10,7 +10,7 @@ nodeIpc.config.retry = 1500
nodeIpc.config.silent = true
function killFinder () {
let finderWindow = remote.getCurrentWindow()
const finderWindow = remote.getCurrentWindow()
finderWindow.removeAllListeners()
if (global.process.platform === 'darwin') {
// Only OSX has another app process.
@@ -21,7 +21,7 @@ function killFinder () {
}
function toggleFinder () {
let finderWindow = remote.getCurrentWindow()
const finderWindow = remote.getCurrentWindow()
if (global.process.platform === 'darwin') {
if (finderWindow.isVisible()) {
finderWindow.hide()

View File

@@ -2,7 +2,7 @@ import { combineReducers, createStore } from 'redux'
import { routerReducer } from 'react-router-redux'
import { DEFAULT_CONFIG } from 'browser/main/lib/ConfigManager'
let defaultData = {
const defaultData = {
storageMap: {},
noteMap: {},
starredSet: [],
@@ -40,12 +40,12 @@ function config (state = DEFAULT_CONFIG, action) {
return state
}
let reducer = combineReducers({
const reducer = combineReducers({
data,
config,
routing: routerReducer
})
let store = createStore(reducer)
const store = createStore(reducer)
export default store

View File

@@ -38,15 +38,15 @@ class MutableMap {
}
map (cb) {
let result = []
for (let [key, value] of this._map) {
const result = []
for (const [key, value] of this._map) {
result.push(cb(value, key))
}
return result
}
toJS () {
let result = {}
const result = {}
for (let [key, value] of this._map) {
if (value instanceof MutableSet || value instanceof MutableMap) {
value = value.toJS()
@@ -85,7 +85,7 @@ class MutableSet {
}
map (cb) {
let result = []
const result = []
this._set.forEach(function (value, key) {
result.push(cb(value, key))
})

View File

@@ -1,11 +1,11 @@
export function findNoteTitle (value) {
let splitted = value.split('\n')
const splitted = value.split('\n')
let title = null
let isInsideCodeBlock = false
splitted.some((line, index) => {
let trimmedLine = line.trim()
let trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
const trimmedLine = line.trim()
const trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
if (trimmedLine.match('```')) {
isInsideCodeBlock = !isInsideCodeBlock
}

View File

@@ -1,10 +1,10 @@
export function getTodoStatus (content) {
let splitted = content.split('\n')
const splitted = content.split('\n')
let numberOfTodo = 0
let numberOfCompletedTodo = 0
splitted.forEach((line) => {
let trimmedLine = line.trim()
const trimmedLine = line.trim()
if (trimmedLine.match(/^[\+\-\*] \[\s|x\] ./)) {
numberOfTodo++
}

View File

@@ -7,8 +7,8 @@ import _ from 'lodash'
const katex = window.katex
function createGutter (str) {
let lc = (str.match(/\n/g) || []).length
let lines = []
const lc = (str.match(/\n/g) || []).length
const lines = []
for (let i = 1; i <= lc; i++) {
lines.push('<span class="CodeMirror-linenumber">' + i + '</span>')
}
@@ -76,8 +76,8 @@ md.use(require('markdown-it-plantuml'))
md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
let content, terminate, i, l, token
let nextLine = startLine + 1
let terminatorRules = state.md.block.ruler.getRules('paragraph')
let endLine = state.lineMax
const terminatorRules = state.md.block.ruler.getRules('paragraph')
const endLine = state.lineMax
// jump line-by-line until empty one or EOF
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
@@ -107,7 +107,7 @@ md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
token.map = [ startLine, state.line ]
if (state.parentType === 'list') {
let match = content.match(/^\[( |x)\] ?(.+)/i)
const match = content.match(/^\[( |x)\] ?(.+)/i)
if (match) {
content = `<label class='taskListItem' for='checkbox-${startLine + 1}'><input type='checkbox'${match[1] !== ' ' ? ' checked' : ''} id='checkbox-${startLine + 1}'/> ${content.substring(4, content.length)}</label>`
}
@@ -124,7 +124,7 @@ md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
})
// Add line number attribute for scrolling
let originalRender = md.renderer.render
const originalRender = md.renderer.render
md.renderer.render = function render (tokens, options, env) {
tokens.forEach((token) => {
switch (token.type) {
@@ -135,7 +135,7 @@ md.renderer.render = function render (tokens, options, env) {
token.attrPush(['data-line', token.map[0]])
}
})
let result = originalRender.call(md.renderer, tokens, options, env)
const result = originalRender.call(md.renderer, tokens, options, env)
return result
}
// FIXME We should not depend on global variable.

View File

@@ -16,7 +16,7 @@ export default function searchFromNotes (notes, search) {
function findByTag (notes, block) {
const tag = block.match(/#(.+)/)[1]
let regExp = new RegExp(_.escapeRegExp(tag), 'i')
const regExp = new RegExp(_.escapeRegExp(tag), 'i')
return notes.filter((note) => {
if (!_.isArray(note.tags)) return false
return note.tags.some((_tag) => {
@@ -26,7 +26,7 @@ function findByTag (notes, block) {
}
function findByWord (notes, block) {
let regExp = new RegExp(_.escapeRegExp(block), 'i')
const regExp = new RegExp(_.escapeRegExp(block), 'i')
return notes.filter((note) => {
if (_.isArray(note.tags) && note.tags.some((_tag) => {
return _tag.match(regExp)

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './FolderSelect.styl'
import _ from 'lodash'
@@ -73,8 +74,8 @@ class FolderSelect extends React.Component {
case 9:
if (e.shiftKey) {
e.preventDefault()
let tabbable = document.querySelectorAll('a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])')
let previousEl = tabbable[Array.prototype.indexOf.call(tabbable, this.refs.root) - 1]
const tabbable = document.querySelectorAll('a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])')
const previousEl = tabbable[Array.prototype.indexOf.call(tabbable, this.refs.root) - 1]
if (previousEl != null) previousEl.focus()
}
}
@@ -89,9 +90,9 @@ class FolderSelect extends React.Component {
}
handleSearchInputChange (e) {
let { folders } = this.props
let search = this.refs.search.value
let optionIndex = search.length > 0
const { folders } = this.props
const search = this.refs.search.value
const optionIndex = search.length > 0
? _.findIndex(folders, (folder) => {
return folder.name.match(new RegExp('^' + _.escapeRegExp(search), 'i'))
})
@@ -129,7 +130,7 @@ class FolderSelect extends React.Component {
nextOption () {
let { optionIndex } = this.state
let { folders } = this.props
const { folders } = this.props
optionIndex++
if (optionIndex >= folders.length) optionIndex = 0
@@ -140,7 +141,7 @@ class FolderSelect extends React.Component {
}
previousOption () {
let { folders } = this.props
const { folders } = this.props
let { optionIndex } = this.state
optionIndex--
@@ -152,10 +153,10 @@ class FolderSelect extends React.Component {
}
selectOption () {
let { folders } = this.props
let optionIndex = this.state.optionIndex
const { folders } = this.props
const optionIndex = this.state.optionIndex
let folder = folders[optionIndex]
const folder = folders[optionIndex]
if (folder != null) {
this.setState({
status: 'FOCUS'
@@ -184,10 +185,10 @@ class FolderSelect extends React.Component {
}
render () {
let { className, data, value } = this.props
let splitted = value.split('-')
let storageKey = splitted.shift()
let folderKey = splitted.shift()
const { className, data, value } = this.props
const splitted = value.split('-')
const storageKey = splitted.shift()
const folderKey = splitted.shift()
let options = []
data.storageMap.forEach((storage, index) => {
storage.folders.forEach((folder) => {
@@ -198,14 +199,14 @@ class FolderSelect extends React.Component {
})
})
let currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]
const currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]
if (this.state.search.trim().length > 0) {
let filter = new RegExp('^' + _.escapeRegExp(this.state.search), 'i')
const filter = new RegExp('^' + _.escapeRegExp(this.state.search), 'i')
options = options.filter((option) => filter.test(option.folder.name))
}
let optionList = options
const optionList = options
.map((option, index) => {
return (
<div styleName={index === this.state.optionIndex

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './InfoButton.styl'

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './InfoPanel.styl'

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './InfoPanel.styl'

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './MarkdownNoteDetail.styl'
import MarkdownEditor from 'browser/components/MarkdownEditor'
@@ -25,7 +26,7 @@ import striptags from 'striptags'
const electron = require('electron')
const { remote } = electron
const { Menu, MenuItem, dialog } = remote
const { dialog } = remote
class MarkdownNoteDetail extends React.Component {
constructor (props) {
@@ -74,7 +75,7 @@ class MarkdownNoteDetail extends React.Component {
}
handleChange (e) {
let { note } = this.state
const { note } = this.state
note.content = this.refs.content.value
if (this.refs.tags) note.tags = this.refs.tags.value
@@ -96,7 +97,7 @@ class MarkdownNoteDetail extends React.Component {
}
saveNow () {
let { note, dispatch } = this.props
const { note, dispatch } = this.props
clearTimeout(this.saveQueue)
this.saveQueue = null
@@ -112,11 +113,11 @@ class MarkdownNoteDetail extends React.Component {
}
handleFolderChange (e) {
let { note } = this.state
let value = this.refs.folder.value
let splitted = value.split('-')
let newStorageKey = splitted.shift()
let newFolderKey = splitted.shift()
const { note } = this.state
const value = this.refs.folder.value
const splitted = value.split('-')
const newStorageKey = splitted.shift()
const newFolderKey = splitted.shift()
dataApi
.moveNote(note.storage, note.key, newStorageKey, newFolderKey)
@@ -125,7 +126,7 @@ class MarkdownNoteDetail extends React.Component {
isMovingNote: true,
note: Object.assign({}, newNote)
}, () => {
let { dispatch, location } = this.props
const { dispatch, location } = this.props
dispatch({
type: 'MOVE_NOTE',
originNote: note,
@@ -145,7 +146,7 @@ class MarkdownNoteDetail extends React.Component {
}
handleStarButtonClick (e) {
let { note } = this.state
const { note } = this.state
if (!note.isStarred) AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_STAR')
note.isStarred = !note.isStarred
@@ -170,22 +171,22 @@ class MarkdownNoteDetail extends React.Component {
}
handleTrashButtonClick (e) {
let { note } = this.state
const { note } = this.state
const { isTrashed } = note
if (isTrashed) {
let dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Confirm note deletion',
detail: 'This will permanently remove this note.',
buttons: ['Confirm', 'Cancel']
})
if (dialogueButtonIndex === 1) return
let { note, dispatch } = this.props
const { note, dispatch } = this.props
dataApi
.deleteNote(note.storage, note.key)
.then((data) => {
let dispatchHandler = () => {
const dispatchHandler = () => {
dispatch({
type: 'DELETE_NOTE',
storageKey: data.storageKey,
@@ -207,7 +208,7 @@ class MarkdownNoteDetail extends React.Component {
}
handleUndoButtonClick (e) {
let { note } = this.state
const { note } = this.state
note.isTrashed = false
@@ -262,12 +263,12 @@ class MarkdownNoteDetail extends React.Component {
}
render () {
let { data, config, location } = this.props
let { note } = this.state
let storageKey = note.storage
let folderKey = note.folder
const { data, config, location } = this.props
const { note } = this.state
const storageKey = note.storage
const folderKey = note.folder
let options = []
const options = []
data.storageMap.forEach((storage, index) => {
storage.folders.forEach((folder) => {
options.push({
@@ -276,7 +277,7 @@ class MarkdownNoteDetail extends React.Component {
})
})
})
let currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]
const currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]
const trashTopBar = <div styleName='info'>
<div styleName='info-left'>

View File

@@ -30,8 +30,7 @@
right 0
top $info-height + $info-margin-under-border
bottom $statusBar-height
max-width 600px
margin 0 auto
margin 0 45px
.body-noteEditor
absolute top bottom left right

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './TrashButton.styl'

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './SnippetNoteDetail.styl'
import CodeEditor from 'browser/components/CodeEditor'
@@ -61,7 +62,7 @@ class SnippetNoteDetail extends React.Component {
componentWillReceiveProps (nextProps) {
if (nextProps.note.key !== this.props.note.key && !this.isMovingNote) {
if (this.saveQueue != null) this.saveNow()
let nextNote = Object.assign({
const nextNote = Object.assign({
description: ''
}, nextProps.note, {
snippets: nextProps.note.snippets.map((snippet) => Object.assign({}, snippet))
@@ -70,7 +71,7 @@ class SnippetNoteDetail extends React.Component {
snippetIndex: 0,
note: nextNote
}, () => {
let { snippets } = this.state.note
const { snippets } = this.state.note
snippets.forEach((snippet, index) => {
this.refs['code-' + index].reload()
})
@@ -84,7 +85,7 @@ class SnippetNoteDetail extends React.Component {
}
handleChange (e) {
let { note } = this.state
const { note } = this.state
if (this.refs.tags) note.tags = this.refs.tags.value
note.description = this.refs.description.value
@@ -106,7 +107,7 @@ class SnippetNoteDetail extends React.Component {
}
saveNow () {
let { note, dispatch } = this.props
const { note, dispatch } = this.props
clearTimeout(this.saveQueue)
this.saveQueue = null
@@ -122,11 +123,11 @@ class SnippetNoteDetail extends React.Component {
}
handleFolderChange (e) {
let { note } = this.state
let value = this.refs.folder.value
let splitted = value.split('-')
let newStorageKey = splitted.shift()
let newFolderKey = splitted.shift()
const { note } = this.state
const value = this.refs.folder.value
const splitted = value.split('-')
const newStorageKey = splitted.shift()
const newFolderKey = splitted.shift()
dataApi
.moveNote(note.storage, note.key, newStorageKey, newFolderKey)
@@ -135,7 +136,7 @@ class SnippetNoteDetail extends React.Component {
isMovingNote: true,
note: Object.assign({}, newNote)
}, () => {
let { dispatch, location } = this.props
const { dispatch, location } = this.props
dispatch({
type: 'MOVE_NOTE',
originNote: note,
@@ -155,7 +156,7 @@ class SnippetNoteDetail extends React.Component {
}
handleStarButtonClick (e) {
let { note } = this.state
const { note } = this.state
if (!note.isStarred) AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_STAR')
note.isStarred = !note.isStarred
@@ -172,22 +173,22 @@ class SnippetNoteDetail extends React.Component {
}
handleTrashButtonClick (e) {
let { note } = this.state
const { note } = this.state
const { isTrashed } = note
if (isTrashed) {
let dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Confirm note deletion',
detail: 'This will permanently remove this note.',
buttons: ['Confirm', 'Cancel']
})
if (dialogueButtonIndex === 1) return
let { note, dispatch } = this.props
const { note, dispatch } = this.props
dataApi
.deleteNote(note.storage, note.key)
.then((data) => {
let dispatchHandler = () => {
const dispatchHandler = () => {
dispatch({
type: 'DELETE_NOTE',
storageKey: data.storageKey,
@@ -209,7 +210,7 @@ class SnippetNoteDetail extends React.Component {
}
handleUndoButtonClick (e) {
let { note } = this.state
const { note } = this.state
note.isTrashed = false
@@ -238,7 +239,7 @@ class SnippetNoteDetail extends React.Component {
handleTabDeleteButtonClick (e, index) {
if (this.state.note.snippets.length > 1) {
if (this.state.note.snippets[index].content.trim().length > 0) {
let dialogIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
const dialogIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Delete a snippet',
detail: 'This work cannot be undone.',
@@ -288,7 +289,7 @@ class SnippetNoteDetail extends React.Component {
handleModeOptionClick (index, name) {
return (e) => {
let snippets = this.state.note.snippets.slice()
const snippets = this.state.note.snippets.slice()
snippets[index].mode = name
this.setState({note: Object.assign(this.state.note, {snippets: snippets})})
@@ -306,7 +307,7 @@ class SnippetNoteDetail extends React.Component {
handleCodeChange (index) {
return (e) => {
let snippets = this.state.note.snippets.slice()
const snippets = this.state.note.snippets.slice()
snippets[index].content = this.refs['code-' + index].value
this.setState({note: Object.assign(this.state.note, {snippets: snippets})})
this.setState({
@@ -333,7 +334,7 @@ class SnippetNoteDetail extends React.Component {
break
case 76:
{
let isSuper = global.process.platform === 'darwin'
const isSuper = global.process.platform === 'darwin'
? e.metaKey
: e.ctrlKey
if (isSuper) {
@@ -344,7 +345,7 @@ class SnippetNoteDetail extends React.Component {
break
case 84:
{
let isSuper = global.process.platform === 'darwin'
const isSuper = global.process.platform === 'darwin'
? e.metaKey
: e.ctrlKey
if (isSuper) {
@@ -357,7 +358,7 @@ class SnippetNoteDetail extends React.Component {
}
handleModeButtonClick (e, index) {
let menu = new Menu()
const menu = new Menu()
CodeMirror.modeInfo.forEach((mode) => {
menu.append(new MenuItem({
label: mode.name,
@@ -398,8 +399,8 @@ class SnippetNoteDetail extends React.Component {
}
handleIndentSizeItemClick (e, indentSize) {
let { config, dispatch } = this.props
let editor = Object.assign({}, config.editor, {
const { config, dispatch } = this.props
const editor = Object.assign({}, config.editor, {
indentSize
})
ConfigManager.set({
@@ -414,8 +415,8 @@ class SnippetNoteDetail extends React.Component {
}
handleIndentTypeItemClick (e, indentType) {
let { config, dispatch } = this.props
let editor = Object.assign({}, config.editor, {
const { config, dispatch } = this.props
const editor = Object.assign({}, config.editor, {
indentType
})
ConfigManager.set({
@@ -434,14 +435,14 @@ class SnippetNoteDetail extends React.Component {
}
addSnippet () {
let { note } = this.state
const { note } = this.state
note.snippets = note.snippets.concat([{
name: '',
mode: 'Plain Text',
content: ''
}])
let snippetIndex = note.snippets.length - 1
const snippetIndex = note.snippets.length - 1
this.setState({
note,
@@ -487,19 +488,19 @@ class SnippetNoteDetail extends React.Component {
}
render () {
let { data, config, location } = this.props
let { note } = this.state
const { data, config, location } = this.props
const { note } = this.state
let storageKey = note.storage
let folderKey = note.folder
const storageKey = note.storage
const folderKey = note.folder
let editorFontSize = parseInt(config.editor.fontSize, 10)
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
let editorIndentSize = parseInt(config.editor.indentSize, 10)
if (!(editorFontSize > 0 && editorFontSize < 132)) editorIndentSize = 4
let tabList = note.snippets.map((snippet, index) => {
let isActive = this.state.snippetIndex === index
const tabList = note.snippets.map((snippet, index) => {
const isActive = this.state.snippetIndex === index
return <SnippetTab
key={index}
@@ -513,8 +514,8 @@ class SnippetNoteDetail extends React.Component {
/>
})
let viewList = note.snippets.map((snippet, index) => {
let isActive = this.state.snippetIndex === index
const viewList = note.snippets.map((snippet, index) => {
const isActive = this.state.snippetIndex === index
let syntax = CodeMirror.findModeByName(pass(snippet.mode))
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
@@ -548,7 +549,7 @@ class SnippetNoteDetail extends React.Component {
</div>
})
let options = []
const options = []
data.storageMap.forEach((storage, index) => {
storage.folders.forEach((folder) => {
options.push({
@@ -557,7 +558,7 @@ class SnippetNoteDetail extends React.Component {
})
})
})
let currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]
const currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]
const trashTopBar = <div styleName='info'>
<div styleName='info-left'>

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './StarButton.styl'
import _ from 'lodash'
@@ -31,7 +32,7 @@ class StarButton extends React.Component {
}
render () {
let { className } = this.props
const { className } = this.props
return (
<button className={_.isString(className)

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './TagSelect.styl'
import _ from 'lodash'
@@ -37,6 +38,10 @@ class TagSelect extends React.Component {
}
}
handleNewTagBlur (e) {
this.submitTag()
}
removeLastTag () {
let { value } = this.props
@@ -59,7 +64,7 @@ class TagSelect extends React.Component {
submitTag () {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_TAG')
let { value } = this.props
let newTag = this.refs.newTag.value.trim().replace(/ +/g, '_')
const newTag = this.refs.newTag.value.trim().replace(/ +/g, '_')
if (newTag.length <= 0) {
this.setState({
@@ -101,9 +106,9 @@ class TagSelect extends React.Component {
}
render () {
let { value, className } = this.props
const { value, className } = this.props
let tagList = _.isArray(value)
const tagList = _.isArray(value)
? value.map((tag) => {
return (
<span styleName='tag'
@@ -134,6 +139,7 @@ class TagSelect extends React.Component {
placeholder='Add tag...'
onChange={(e) => this.handleNewTagInputChange(e)}
onKeyDown={(e) => this.handleNewTagInputKeyDown(e)}
onBlur={(e) => this.handleNewTagBlur(e)}
/>
</div>
)

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './TrashButton.styl'

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './Detail.styl'
import _ from 'lodash'
@@ -32,12 +33,12 @@ class Detail extends React.Component {
}
render () {
let { location, data, config } = this.props
const { location, data, config } = this.props
let note = null
if (location.query.key != null) {
let splitted = location.query.key.split('-')
let storageKey = splitted.shift()
let noteKey = splitted.shift()
const splitted = location.query.key.split('-')
const storageKey = splitted.shift()
const noteKey = splitted.shift()
note = data.noteMap.get(storageKey + '-' + noteKey)
}

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './Main.styl'
import { connect } from 'react-redux'
@@ -23,7 +24,7 @@ class Main extends React.Component {
mobileAnalytics.initAwsMobileAnalytics()
}
let { config } = props
const { config } = props
this.state = {
isRightSliderFocused: false,
@@ -39,7 +40,7 @@ class Main extends React.Component {
}
getChildContext () {
let { status, config } = this.props
const { status, config } = this.props
return {
status,
@@ -48,7 +49,7 @@ class Main extends React.Component {
}
componentDidMount () {
let { dispatch, config } = this.props
const { dispatch, config } = this.props
if (config.ui.theme === 'dark') {
document.body.setAttribute('data-theme', 'dark')
@@ -99,8 +100,8 @@ class Main extends React.Component {
this.setState({
isRightSliderFocused: false
}, () => {
let { dispatch } = this.props
let newListWidth = this.state.listWidth
const { dispatch } = this.props
const newListWidth = this.state.listWidth
// TODO: ConfigManager should dispatch itself.
ConfigManager.set({listWidth: newListWidth})
dispatch({
@@ -115,8 +116,8 @@ class Main extends React.Component {
this.setState({
isLeftSliderFocused: false
}, () => {
let { dispatch } = this.props
let navWidth = this.state.navWidth
const { dispatch } = this.props
const navWidth = this.state.navWidth
// TODO: ConfigManager should dispatch itself.
ConfigManager.set({ navWidth })
dispatch({
@@ -129,7 +130,7 @@ class Main extends React.Component {
handleMouseMove (e) {
if (this.state.isRightSliderFocused) {
let offset = this.refs.body.getBoundingClientRect().left
const offset = this.refs.body.getBoundingClientRect().left
let newListWidth = e.pageX - offset
if (newListWidth < 10) {
newListWidth = 10
@@ -182,7 +183,7 @@ class Main extends React.Component {
}
render () {
let { config } = this.props
const { config } = this.props
// the width of the navigation bar when it is folded/collapsed
const foldedNavigationWidth = 44

View File

@@ -1,12 +1,11 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './NewNoteButton.styl'
import _ from 'lodash'
import modal from 'browser/main/lib/modal'
import NewNoteModal from 'browser/main/modals/NewNoteModal'
import { hashHistory } from 'react-router'
import eventEmitter from 'browser/main/lib/eventEmitter'
import dataApi from 'browser/main/lib/dataApi'
const { remote } = require('electron')
const { dialog } = remote
@@ -34,7 +33,7 @@ class NewNoteButton extends React.Component {
}
handleNewNoteButtonClick (e) {
const { config, location, dispatch } = this.props
const { location, dispatch } = this.props
const { storage, folder } = this.resolveTargetFolder()
modal.open(NewNoteModal, {
@@ -51,7 +50,7 @@ class NewNoteButton extends React.Component {
// Find first storage
if (storage == null) {
for (let kv of data.storageMap) {
for (const kv of data.storageMap) {
storage = kv[1]
break
}

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './NoteList.styl'
import moment from 'moment'
@@ -13,8 +14,8 @@ import fs from 'fs'
import { hashHistory } from 'react-router'
import markdown from 'browser/lib/markdown'
import { findNoteTitle } from 'browser/lib/findNoteTitle'
import stripgtags from 'striptags'
import store from 'browser/main/store'
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
const { remote } = require('electron')
const { Menu, MenuItem, dialog } = remote
@@ -31,6 +32,18 @@ function sortByUpdatedAt (a, b) {
return new Date(b.updatedAt) - new Date(a.updatedAt)
}
function findNoteByKey (notes, noteKey) {
return notes.find((note) => `${note.storage}-${note.key}` === noteKey)
}
function findNotesByKeys (notes, noteKeys) {
return notes.filter((note) => noteKeys.includes(getNoteKey(note)))
}
function getNoteKey (note) {
return `${note.storage}-${note.key}`
}
class NoteList extends React.Component {
constructor (props) {
super(props)
@@ -50,8 +63,16 @@ class NoteList extends React.Component {
}
this.importFromFileHandler = this.importFromFile.bind(this)
this.jumpNoteByHash = this.jumpNoteByHashHandler.bind(this)
this.handleNoteListKeyUp = this.handleNoteListKeyUp.bind(this)
this.getNoteKeyFromTargetIndex = this.getNoteKeyFromTargetIndex.bind(this)
this.deleteNote = this.deleteNote.bind(this)
this.focusNote = this.focusNote.bind(this)
this.pinToTop = this.pinToTop.bind(this)
// TODO: not Selected noteKeys but SelectedNote(for reusing)
this.state = {
shiftKeyDown: false,
selectedNoteKeys: []
}
this.contextNotes = []
@@ -89,10 +110,10 @@ class NoteList extends React.Component {
}
componentDidUpdate (prevProps) {
let { location } = this.props
const { location } = this.props
if (this.notes.length > 0 && location.query.key == null) {
let { router } = this.context
const { router } = this.context
if (!location.pathname.match(/\/searched/)) this.contextNotes = this.getContextNotes()
router.replace({
pathname: location.pathname,
@@ -107,16 +128,16 @@ class NoteList extends React.Component {
if (_.isString(location.query.key) && prevProps.location.query.key === location.query.key) {
const targetIndex = this.getTargetIndex()
if (targetIndex > -1) {
let list = this.refs.list
let item = list.childNodes[targetIndex]
const list = this.refs.list
const item = list.childNodes[targetIndex]
if (item == null) return false
let overflowBelow = item.offsetTop + item.clientHeight - list.clientHeight - list.scrollTop > 0
const overflowBelow = item.offsetTop + item.clientHeight - list.clientHeight - list.scrollTop > 0
if (overflowBelow) {
list.scrollTop = item.offsetTop + item.clientHeight - list.clientHeight
}
let overflowAbove = list.scrollTop > item.offsetTop
const overflowAbove = list.scrollTop > item.offsetTop
if (overflowAbove) {
list.scrollTop = item.offsetTop
}
@@ -124,12 +145,35 @@ class NoteList extends React.Component {
}
}
focusNote (selectedNoteKeys, noteKey) {
const { router } = this.context
const { location } = this.props
this.setState({
selectedNoteKeys
})
router.push({
pathname: location.pathname,
query: {
key: noteKey
}
})
}
getNoteKeyFromTargetIndex (targetIndex) {
const note = Object.assign({}, this.notes[targetIndex])
const noteKey = getNoteKey(note)
return noteKey
}
selectPriorNote () {
if (this.notes == null || this.notes.length === 0) {
return
}
let { router } = this.context
let { location } = this.props
let { selectedNoteKeys, shiftKeyDown } = this.state
let targetIndex = this.getTargetIndex()
@@ -137,14 +181,18 @@ class NoteList extends React.Component {
return
}
targetIndex--
if (targetIndex < 0) targetIndex = 0
router.push({
pathname: location.pathname,
query: {
key: this.notes[targetIndex].storage + '-' + this.notes[targetIndex].key
}
})
if (!shiftKeyDown) { selectedNoteKeys = [] }
const priorNoteKey = this.getNoteKeyFromTargetIndex(targetIndex)
if (selectedNoteKeys.includes(priorNoteKey)) {
selectedNoteKeys.pop()
} else {
selectedNoteKeys.push(priorNoteKey)
}
this.focusNote(selectedNoteKeys, priorNoteKey)
ee.emit('list:moved')
}
selectNextNote () {
@@ -153,23 +201,31 @@ class NoteList extends React.Component {
}
let { router } = this.context
let { location } = this.props
let { selectedNoteKeys, shiftKeyDown } = this.state
let targetIndex = this.getTargetIndex()
const isTargetLastNote = targetIndex === this.notes.length - 1
if (targetIndex === this.notes.length - 1) {
if (isTargetLastNote && shiftKeyDown) {
return
} else if (isTargetLastNote) {
targetIndex = 0
} else {
targetIndex++
if (targetIndex < 0) targetIndex = 0
else if (targetIndex > this.notes.length - 1) targetIndex === this.notes.length - 1
else if (targetIndex > this.notes.length - 1) targetIndex = this.notes.length - 1
}
router.push({
pathname: location.pathname,
query: {
key: this.notes[targetIndex].storage + '-' + this.notes[targetIndex].key
}
})
if (!shiftKeyDown) { selectedNoteKeys = [] }
const nextNoteKey = this.getNoteKeyFromTargetIndex(targetIndex)
if (selectedNoteKeys.includes(nextNoteKey)) {
selectedNoteKeys.pop()
} else {
selectedNoteKeys.push(nextNoteKey)
}
this.focusNote(selectedNoteKeys, nextNoteKey)
ee.emit('list:moved')
}
@@ -186,17 +242,17 @@ class NoteList extends React.Component {
if (targetIndex < 0) targetIndex = 0
router.push({
pathname: location.pathname,
query: {
key: this.notes[targetIndex].storage + '-' + this.notes[targetIndex].key
}
})
const selectedNoteKeys = []
const nextNoteKey = this.getNoteKeyFromTargetIndex(targetIndex)
selectedNoteKeys.push(nextNoteKey)
this.focusNote(selectedNoteKeys, nextNoteKey)
ee.emit('list:moved')
}
handleNoteListKeyDown (e) {
const { shiftKeyDown } = this.state
if (e.metaKey || e.ctrlKey) return true
if (e.keyCode === 65 && !e.shiftKey) {
@@ -206,7 +262,7 @@ class NoteList extends React.Component {
if (e.keyCode === 68) {
e.preventDefault()
ee.emit('detail:delete')
this.deleteNote()
}
if (e.keyCode === 69) {
@@ -223,11 +279,20 @@ class NoteList extends React.Component {
e.preventDefault()
this.selectNextNote()
}
if (e.shiftKey) {
this.setState({ shiftKeyDown: true })
}
}
handleNoteListKeyUp (e) {
if (!e.shiftKey) {
this.setState({ shiftKeyDown: false })
}
}
getNotes () {
let { data, params, location } = this.props
let { router } = this.context
const { data, params, location } = this.props
if (location.pathname.match(/\/home/) || location.pathname.match(/\alltags/)) {
const allNotes = data.noteMap.map((note) => note)
@@ -302,6 +367,22 @@ class NoteList extends React.Component {
handleNoteClick (e, uniqueKey) {
let { router } = this.context
let { location } = this.props
let { shiftKeyDown, selectedNoteKeys } = this.state
if (shiftKeyDown && selectedNoteKeys.includes(uniqueKey)) {
const newSelectedNoteKeys = selectedNoteKeys.filter((noteKey) => noteKey !== uniqueKey)
this.setState({
selectedNoteKeys: newSelectedNoteKeys
})
return
}
if (!shiftKeyDown) {
selectedNoteKeys = []
}
selectedNoteKeys.push(uniqueKey)
this.setState({
selectedNoteKeys
})
router.push({
pathname: location.pathname,
@@ -312,9 +393,9 @@ class NoteList extends React.Component {
}
handleSortByChange (e) {
let { dispatch } = this.props
const { dispatch } = this.props
let config = {
const config = {
sortBy: e.target.value
}
@@ -326,9 +407,9 @@ class NoteList extends React.Component {
}
handleListStyleButtonClick (e, style) {
let { dispatch } = this.props
const { dispatch } = this.props
let config = {
const config = {
listStyle: style
}
@@ -352,16 +433,23 @@ class NoteList extends React.Component {
}
handleDragStart (e, note) {
const noteData = JSON.stringify(note)
const { selectedNoteKeys } = this.state
const notes = this.notes.map((note) => Object.assign({}, note))
const selectedNotes = findNotesByKeys(notes, selectedNoteKeys)
const noteData = JSON.stringify(selectedNotes)
e.dataTransfer.setData('note', noteData)
this.setState({ selectedNoteKeys: [] })
}
handleNoteContextMenu (e, uniqueKey) {
const { location } = this.props
const note = this.notes.find((note) => {
const noteKey = `${note.storage}-${note.key}`
return noteKey === uniqueKey
})
const { selectedNoteKeys } = this.state
const note = findNoteByKey(this.notes, uniqueKey)
const noteKey = getNoteKey(note)
if (selectedNoteKeys.length === 0 || !selectedNoteKeys.includes(noteKey)) {
this.handleNoteClick(e, uniqueKey)
}
const pinLabel = note.isPinned ? 'Remove pin' : 'Pin to Top'
const deleteLabel = 'Delete Note'
@@ -370,47 +458,104 @@ class NoteList extends React.Component {
if (!location.pathname.match(/\/home|\/starred|\/trash/)) {
menu.append(new MenuItem({
label: pinLabel,
click: (e) => this.pinToTop(e, uniqueKey)
click: this.pinToTop
}))
}
menu.append(new MenuItem({
label: deleteLabel,
click: (e) => this.deleteNote(e, uniqueKey)
click: this.deleteNote
}))
menu.popup()
}
pinToTop (e, uniqueKey) {
const { data, params } = this.props
const storageKey = params.storageKey
const folderKey = params.folderKey
pinToTop () {
const { selectedNoteKeys } = this.state
const { dispatch } = this.props
const notes = this.notes.map((note) => Object.assign({}, note))
const selectedNotes = findNotesByKeys(notes, selectedNoteKeys)
const currentStorage = data.storageMap.get(storageKey)
const currentFolder = _.find(currentStorage.folders, {key: folderKey})
this.handleNoteClick(e, uniqueKey)
const targetIndex = this.getTargetIndex()
let note = this.notes[targetIndex]
note.isPinned = !note.isPinned
dataApi
.updateNote(note.storage, note.key, note)
.then((note) => {
store.dispatch({
Promise.all(
selectedNotes.map((note) => {
note.isPinned = !note.isPinned
return dataApi
.updateNote(note.storage, note.key, note)
})
)
.then((updatedNotes) => {
updatedNotes.forEach((note) => {
dispatch({
type: 'UPDATE_NOTE',
note: note
note
})
})
})
this.setState({ selectedNoteKeys: [] })
}
deleteNote (e, uniqueKey) {
this.handleNoteClick(e, uniqueKey)
ee.emit('detail:delete')
deleteNote () {
const { dispatch } = this.props
const { selectedNoteKeys } = this.state
const notes = this.notes.map((note) => Object.assign({}, note))
const selectedNotes = findNotesByKeys(notes, selectedNoteKeys)
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(
selectedNoteKeys.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({ selectedNoteKeys: [] })
}
importFromFile () {
const { dispatch, location } = this.props
const options = {
filters: [
{ name: 'Documents', extensions: ['md', 'txt'] }
@@ -454,7 +599,7 @@ class NoteList extends React.Component {
})
hashHistory.push({
pathname: location.pathname,
query: {key: `${note.storage}-${note.key}`}
query: {key: getNoteKey(note)}
})
})
})
@@ -464,7 +609,7 @@ class NoteList extends React.Component {
getTargetIndex () {
const { location } = this.props
const targetIndex = _.findIndex(this.notes, (note) => {
return `${note.storage}-${note.key}` === location.query.key
return getNoteKey(note) === location.query.key
})
return targetIndex
}
@@ -475,7 +620,7 @@ class NoteList extends React.Component {
// Find first storage
if (storage == null) {
for (let kv of data.storageMap) {
for (const kv of data.storageMap) {
storage = kv[1]
break
}
@@ -501,6 +646,7 @@ class NoteList extends React.Component {
render () {
let { location, notes, config, dispatch } = this.props
let { selectedNoteKeys } = this.state
let sortFunc = config.sortBy === 'CREATED_AT'
? sortByCreatedAt
: config.sortBy === 'ALPHABETICAL'
@@ -533,14 +679,15 @@ class NoteList extends React.Component {
}
})
let noteList = notes
const noteList = notes
.map(note => {
if (note == null) {
return null
}
const isDefault = config.listStyle === 'DEFAULT'
const isActive = location.query.key === note.storage + '-' + note.key
const uniqueKey = getNoteKey(note)
const isActive = selectedNoteKeys.includes(uniqueKey)
const dateDisplay = moment(
config.sortBy === 'CREATED_AT'
? note.createdAt : note.updatedAt
@@ -553,7 +700,7 @@ class NoteList extends React.Component {
isActive={isActive}
note={note}
dateDisplay={dateDisplay}
key={key}
key={uniqueKey}
handleNoteContextMenu={this.handleNoteContextMenu.bind(this)}
handleNoteClick={this.handleNoteClick.bind(this)}
handleDragStart={this.handleDragStart.bind(this)}
@@ -566,7 +713,7 @@ class NoteList extends React.Component {
<NoteItemSimple
isActive={isActive}
note={note}
key={key}
key={uniqueKey}
handleNoteContextMenu={this.handleNoteContextMenu.bind(this)}
handleNoteClick={this.handleNoteClick.bind(this)}
handleDragStart={this.handleDragStart.bind(this)}
@@ -615,6 +762,7 @@ class NoteList extends React.Component {
ref='list'
tabIndex='-1'
onKeyDown={(e) => this.handleNoteListKeyDown(e)}
onKeyUp={this.handleNoteListKeyUp}
>
{noteList}
</div>

View File

@@ -102,7 +102,7 @@
font-size 13px
.top-menu-preference
position absolute
left 11px
left 7px
body[data-theme="white"]
.root, .root--folded

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './StorageItem.styl'
import { hashHistory } from 'react-router'
@@ -8,6 +9,7 @@ import RenameFolderModal from 'browser/main/modals/RenameFolderModal'
import dataApi from 'browser/main/lib/dataApi'
import StorageItemChild from 'browser/components/StorageItem'
import eventEmitter from 'browser/main/lib/eventEmitter'
import _ from 'lodash'
const { remote } = require('electron')
const { Menu, MenuItem, dialog } = remote
@@ -22,7 +24,7 @@ class StorageItem extends React.Component {
}
handleHeaderContextMenu (e) {
let menu = new Menu()
const menu = new Menu()
menu.append(new MenuItem({
label: 'Add Folder',
click: (e) => this.handleAddFolderButtonClick(e)
@@ -38,7 +40,7 @@ class StorageItem extends React.Component {
}
handleUnlinkStorageClick (e) {
let index = dialog.showMessageBox(remote.getCurrentWindow(), {
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Unlink Storage',
detail: 'This work will just detatches a storage from Boostnote. (Any data won\'t be deleted.)',
@@ -46,7 +48,7 @@ class StorageItem extends React.Component {
})
if (index === 0) {
let { storage, dispatch } = this.props
const { storage, dispatch } = this.props
dataApi.removeStorage(storage.key)
.then(() => {
dispatch({
@@ -67,7 +69,7 @@ class StorageItem extends React.Component {
}
handleAddFolderButtonClick (e) {
let { storage } = this.props
const { storage } = this.props
modal.open(CreateFolderModal, {
storage
@@ -75,19 +77,19 @@ class StorageItem extends React.Component {
}
handleHeaderInfoClick (e) {
let { storage } = this.props
const { storage } = this.props
hashHistory.push('/storages/' + storage.key)
}
handleFolderButtonClick (folderKey) {
return (e) => {
let { storage } = this.props
const { storage } = this.props
hashHistory.push('/storages/' + storage.key + '/folders/' + folderKey)
}
}
handleFolderButtonContextMenu (e, folder) {
let menu = new Menu()
const menu = new Menu()
menu.append(new MenuItem({
label: 'Rename Folder',
click: (e) => this.handleRenameFolderClick(e, folder)
@@ -103,7 +105,7 @@ class StorageItem extends React.Component {
}
handleRenameFolderClick (e, folder) {
let { storage } = this.props
const { storage } = this.props
modal.open(RenameFolderModal, {
storage,
folder
@@ -111,7 +113,7 @@ class StorageItem extends React.Component {
}
handleFolderDeleteClick (e, folder) {
let index = dialog.showMessageBox(remote.getCurrentWindow(), {
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Delete Folder',
detail: 'This will delete all notes in the folder and can not be undone.',
@@ -119,7 +121,7 @@ class StorageItem extends React.Component {
})
if (index === 0) {
let { storage, dispatch } = this.props
const { storage, dispatch } = this.props
dataApi
.deleteFolder(storage.key, folder.key)
.then((data) => {
@@ -142,48 +144,57 @@ class StorageItem extends React.Component {
e.target.style.backgroundColor = e.dataTransfer.getData('defaultColor')
}
dropNote (storage, folder, dispatch, location, noteData) {
noteData = noteData.filter((note) => folder.key !== note.folder)
if (noteData.length === 0) return
const newNoteData = noteData.map((note) => Object.assign({}, note, {storage: storage, folder: folder.key}))
Promise.all(
newNoteData.map((note) => dataApi.createNote(storage.key, note))
)
.then((createdNoteData) => {
createdNoteData.forEach((note) => {
dispatch({
type: 'UPDATE_NOTE',
note: note
})
})
})
.catch((err) => {
console.error(`error on create notes: ${err}`)
})
.then(() => {
return Promise.all(
noteData.map((note) => dataApi.deleteNote(note.storage, note.key))
)
})
.then((deletedNoteData) => {
deletedNoteData.forEach((note) => {
dispatch({
type: 'DELETE_NOTE',
storageKey: note.storageKey,
noteKey: note.noteKey
})
})
})
.catch((err) => {
console.error(`error on delete notes: ${err}`)
})
}
handleDrop (e, storage, folder, dispatch, location) {
e.target.style.opacity = '1'
e.target.style.backgroundColor = e.dataTransfer.getData('defaultColor')
const noteData = JSON.parse(e.dataTransfer.getData('note'))
const newNoteData = Object.assign({}, noteData, {storage: storage, folder: folder.key})
if (folder.key === noteData.folder) return
dataApi
.createNote(storage.key, newNoteData)
.then((note) => {
dataApi
.deleteNote(noteData.storage, noteData.key)
.then((data) => {
let dispatchHandler = () => {
dispatch({
type: 'DELETE_NOTE',
storageKey: data.storageKey,
noteKey: data.noteKey
})
}
eventEmitter.once('list:moved', dispatchHandler)
eventEmitter.emit('list:next')
})
.catch((err) => {
console.error(err)
})
dispatch({
type: 'UPDATE_NOTE',
note: note
})
hashHistory.push({
pathname: location.pathname,
query: {key: `${note.storage}-${note.key}`}
})
})
this.dropNote(storage, folder, dispatch, location, noteData)
}
render () {
let { storage, location, isFolded, data, dispatch } = this.props
let { folderNoteMap, trashedSet } = data
let folderList = storage.folders.map((folder) => {
let isActive = !!(location.pathname.match(new RegExp('\/storages\/' + storage.key + '\/folders\/' + folder.key)))
let noteSet = folderNoteMap.get(storage.key + '-' + folder.key)
const { storage, location, isFolded, data, dispatch } = this.props
const { folderNoteMap, trashedSet } = data
const folderList = storage.folders.map((folder) => {
const isActive = !!(location.pathname.match(new RegExp('\/storages\/' + storage.key + '\/folders\/' + folder.key)))
const noteSet = folderNoteMap.get(storage.key + '-' + folder.key)
let noteCount = 0
if (noteSet) {
@@ -211,7 +222,7 @@ class StorageItem extends React.Component {
)
})
let isActive = location.pathname.match(new RegExp('\/storages\/' + storage.key + '$'))
const isActive = location.pathname.match(new RegExp('\/storages\/' + storage.key + '$'))
return (
<div styleName={isFolded ? 'root--folded' : 'root'}
@@ -227,8 +238,8 @@ class StorageItem extends React.Component {
onMouseDown={(e) => this.handleToggleButtonClick(e)}
>
<img src={this.state.isOpen
? '../resources/icon/icon-down.svg'
: '../resources/icon/icon-right.svg'
? '../resources/icon/icon-down.svg'
: '../resources/icon/icon-right.svg'
}
/>
</button>
@@ -245,7 +256,7 @@ class StorageItem extends React.Component {
onClick={(e) => this.handleHeaderInfoClick(e)}
>
<span styleName='header-info-name'>
{isFolded ? storage.name.substring(0, 1) : storage.name}
{isFolded ? _.truncate(storage.name, {length: 1, omission: ''}) : storage.name}
</span>
{isFolded &&
<span styleName='header-info--folded-tooltip'>

View File

@@ -80,6 +80,7 @@
@extend .root
.header
width 100%
padding-left 5px
.header-info
overflow ellipsis
padding 0 0 0 18px
@@ -89,6 +90,7 @@
display none
.header-toggleButton
width 15px
padding-left 9px
.header-info--folded-tooltip
tooltip()
position fixed

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './SideNav.styl'
import { openModal } from 'browser/main/lib/modal'
@@ -27,17 +28,17 @@ class SideNav extends React.Component {
}
handleHomeButtonClick (e) {
let { router } = this.context
const { router } = this.context
router.push('/home')
}
handleStarredButtonClick (e) {
let { router } = this.context
const { router } = this.context
router.push('/starred')
}
handleToggleButtonClick (e) {
let { dispatch, config } = this.props
const { dispatch, config } = this.props
ConfigManager.set({isSideNavFolded: !config.isSideNavFolded})
dispatch({
@@ -47,7 +48,7 @@ class SideNav extends React.Component {
}
handleTrashedButtonClick (e) {
let { router } = this.context
const { router } = this.context
router.push('/trashed')
}
@@ -62,7 +63,7 @@ class SideNav extends React.Component {
}
SideNavComponent (isFolded, storageList) {
let { location, data } = this.props
const { location, data } = this.props
const isHomeActive = !!location.pathname.match(/^\/home$/)
const isStarredActive = !!location.pathname.match(/^\/starred$/)
@@ -109,7 +110,7 @@ class SideNav extends React.Component {
tagListComponent () {
const { data, location } = this.props
let tagList = data.tagNoteMap.map((tag, key) => {
const tagList = data.tagNoteMap.map((tag, key) => {
return key
})
return (
@@ -136,11 +137,11 @@ class SideNav extends React.Component {
}
render () {
let { data, location, config, dispatch } = this.props
const { data, location, config, dispatch } = this.props
let isFolded = config.isSideNavFolded
const isFolded = config.isSideNavFolded
let storageList = data.storageMap.map((storage, key) => {
const storageList = data.storageMap.map((storage, key) => {
return <StorageItem
key={storage.key}
storage={storage}
@@ -150,7 +151,7 @@ class SideNav extends React.Component {
dispatch={dispatch}
/>
})
let style = {}
const style = {}
if (!isFolded) style.width = this.props.width
const isTagActive = location.pathname.match(/tag/)
return (

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './StatusBar.styl'
import ZoomManager from 'browser/main/lib/ZoomManager'
@@ -11,7 +12,7 @@ const zoomOptions = [0.8, 0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2
class StatusBar extends React.Component {
updateApp () {
let index = dialog.showMessageBox(remote.getCurrentWindow(), {
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Update Boostnote',
detail: 'New Boostnote is ready to be installed.',
@@ -24,7 +25,7 @@ class StatusBar extends React.Component {
}
handleZoomButtonClick (e) {
let menu = new Menu()
const menu = new Menu()
zoomOptions.forEach((zoom) => {
menu.append(new MenuItem({
@@ -37,7 +38,7 @@ class StatusBar extends React.Component {
}
handleZoomMenuItemClick (zoomFactor) {
let { dispatch } = this.props
const { dispatch } = this.props
ZoomManager.setZoom(zoomFactor)
dispatch({
type: 'SET_ZOOM',
@@ -46,7 +47,7 @@ class StatusBar extends React.Component {
}
render () {
let { config, status } = this.context
const { config, status } = this.context
return (
<div className='StatusBar'

View File

@@ -1,16 +1,11 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './TopBar.styl'
import _ from 'lodash'
import NewNoteModal from 'browser/main/modals/NewNoteModal'
import ee from 'browser/main/lib/eventEmitter'
import NewNoteButton from 'browser/main/NewNoteButton'
const { remote } = require('electron')
const { dialog } = remote
const OSX = window.process.platform === 'darwin'
class TopBar extends React.Component {
constructor (props) {
super(props)
@@ -121,7 +116,7 @@ class TopBar extends React.Component {
}
render () {
let { config, style, data, location } = this.props
const { config, style, location } = this.props
return (
<div className='TopBar'
styleName={config.isSideNavFolded ? 'root--expanded' : 'root'}

View File

@@ -36,7 +36,7 @@ document.addEventListener('click', function (e) {
if (infoPanel) infoPanel.style.display = 'none'
})
let el = document.getElementById('content')
const el = document.getElementById('content')
const history = syncHistoryWithStore(hashHistory, store)
function notify (...args) {
@@ -44,7 +44,7 @@ function notify (...args) {
}
function updateApp () {
let index = dialog.showMessageBox(remote.getCurrentWindow(), {
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Update Boostnote',
detail: 'New Boostnote is ready to be installed.',
@@ -81,7 +81,7 @@ ReactDOM.render((
</Router>
</Provider>
), el, function () {
let loadingCover = document.getElementById('loadingCover')
const loadingCover = document.getElementById('loadingCover')
loadingCover.parentNode.removeChild(loadingCover)
ipcRenderer.on('update-ready', function () {

View File

@@ -4,6 +4,7 @@ const ConfigManager = require('browser/main/lib/ConfigManager')
const remote = require('electron').remote
const os = require('os')
let mobileAnalyticsClient
AWS.config.region = 'us-east-1'
if (process.env.NODE_ENV === 'production' && ConfigManager.default.get().amaEnabled) {
@@ -13,7 +14,7 @@ if (process.env.NODE_ENV === 'production' && ConfigManager.default.get().amaEnab
const validPlatformName = convertPlatformName(os.platform())
const mobileAnalyticsClient = new AMA.Manager({
mobileAnalyticsClient = new AMA.Manager({
appId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
appTitle: 'xxxxxxxxxx',
appVersionName: remote.app.getVersion().toString(),

View File

@@ -13,10 +13,10 @@ function release (el) {
function fire (command) {
console.info('COMMAND >>', command)
let splitted = command.split(':')
let target = splitted[0]
let targetCommand = splitted[1]
let targetCallees = callees
const splitted = command.split(':')
const target = splitted[0]
const targetCommand = splitted[1]
const targetCallees = callees
.filter((callee) => callee.name === target)
targetCallees.forEach((callee) => {

View File

@@ -6,8 +6,6 @@ const win = global.process.platform === 'win32'
const electron = require('electron')
const { ipcRenderer } = electron
const consts = require('browser/lib/consts')
const path = require('path')
const fs = require('fs')
let isInitialized = false
@@ -103,8 +101,8 @@ function get () {
}
function set (updates) {
let currentConfig = get()
let newConfig = Object.assign({}, DEFAULT_CONFIG, currentConfig, updates)
const currentConfig = get()
const newConfig = Object.assign({}, DEFAULT_CONFIG, currentConfig, updates)
if (!validate(newConfig)) throw new Error('INVALID CONFIG')
_save(newConfig)
@@ -123,7 +121,7 @@ function set (updates) {
editorTheme.setAttribute('rel', 'stylesheet')
document.head.appendChild(editorTheme)
}
let newTheme = consts.THEMES.some((theme) => theme === newConfig.editor.theme)
const newTheme = consts.THEMES.some((theme) => theme === newConfig.editor.theme)
? newConfig.editor.theme
: 'default'
@@ -141,7 +139,7 @@ function set (updates) {
}
function assignConfigValues (originalConfig, rcConfig) {
let config = Object.assign({}, DEFAULT_CONFIG, originalConfig, rcConfig)
const config = Object.assign({}, DEFAULT_CONFIG, originalConfig, rcConfig)
config.hotkey = Object.assign({}, DEFAULT_CONFIG.hotkey, originalConfig.hotkey, rcConfig.hotkey)
config.ui = Object.assign({}, DEFAULT_CONFIG.ui, originalConfig.ui, rcConfig.ui)
config.editor = Object.assign({}, DEFAULT_CONFIG.editor, originalConfig.editor, rcConfig.editor)

View File

@@ -19,7 +19,7 @@ function setZoom (zoomFactor, noSave = false) {
}
function getZoom () {
let config = ConfigManager.get()
const config = ConfigManager.get()
return config.zoom
}

View File

@@ -1,7 +1,5 @@
const fs = require('fs')
const path = require('path')
const _ = require('lodash')
const sander = require('sander')
const { findStorage } = require('browser/lib/findStorage')
/**

View File

@@ -23,7 +23,6 @@ const { findStorage } = require('browser/lib/findStorage')
* ```
*/
function createFolder (storageKey, input) {
let rawStorages
let targetStorage
try {
if (input == null) throw new Error('No input found.')
@@ -41,7 +40,7 @@ function createFolder (storageKey, input) {
while (storage.folders.some((folder) => folder.key === key)) {
key = keygen()
}
let newFolder = {
const newFolder = {
key,
color: input.color,
name: input.name

View File

@@ -66,7 +66,7 @@ function createNote (storageKey, input) {
}
}
}
let noteData = Object.assign({}, input, {
const noteData = Object.assign({}, input, {
key,
createdAt: new Date(),
updatedAt: new Date(),

View File

@@ -19,7 +19,6 @@ const { findStorage } = require('browser/lib/findStorage')
* ```
*/
function deleteFolder (storageKey, folderKey) {
let rawStorages
let targetStorage
try {
targetStorage = findStorage(storageKey)
@@ -38,17 +37,17 @@ function deleteFolder (storageKey, folderKey) {
})
})
.then(function deleteFolderAndNotes (data) {
let { storage, notes } = data
const { storage, notes } = data
storage.folders = storage.folders
.filter(function excludeTargetFolder (folder) {
return folder.key !== folderKey
})
let targetNotes = notes.filter(function filterTargetNotes (note) {
const targetNotes = notes.filter(function filterTargetNotes (note) {
return note.folder === folderKey
})
let deleteAllNotes = targetNotes
const deleteAllNotes = targetNotes
.map(function deleteNote (note) {
const notePath = path.join(storage.path, 'notes', note.key + '.cson')
return sander.unlink(notePath)

View File

@@ -1,5 +1,4 @@
const resolveStorageData = require('./resolveStorageData')
const _ = require('lodash')
const path = require('path')
const sander = require('sander')
const { findStorage } = require('browser/lib/findStorage')
@@ -14,7 +13,7 @@ function deleteNote (storageKey, noteKey) {
return resolveStorageData(targetStorage)
.then(function deleteNoteFile (storage) {
let notePath = path.join(storage.path, 'notes', noteKey + '.cson')
const notePath = path.join(storage.path, 'notes', noteKey + '.cson')
try {
sander.unlinkSync(notePath)

View File

@@ -20,7 +20,7 @@ const CSON = require('@rokt33r/season')
* 3. empty directory
*/
function init () {
let fetchStorages = function () {
const fetchStorages = function () {
let rawStorages
try {
rawStorages = JSON.parse(window.localStorage.getItem('storages'))
@@ -34,8 +34,8 @@ function init () {
.map(resolveStorageData))
}
let fetchNotes = function (storages) {
let findNotesFromEachStorage = storages
const fetchNotes = function (storages) {
const findNotesFromEachStorage = storages
.map((storage) => {
return resolveStorageNotes(storage)
.then((notes) => {

View File

@@ -9,7 +9,7 @@ const sander = require('sander')
function migrateFromV5Storage (storageKey, data) {
let targetStorage
try {
let cachedStorageList = JSON.parse(localStorage.getItem('storages'))
const cachedStorageList = JSON.parse(localStorage.getItem('storages'))
if (!_.isArray(cachedStorageList)) throw new Error('Target storage doesn\'t exist.')
targetStorage = _.find(cachedStorageList, {key: storageKey})
@@ -24,15 +24,15 @@ function migrateFromV5Storage (storageKey, data) {
}
function importAll (storage, data) {
let oldArticles = data.articles
let notes = []
const oldArticles = data.articles
const notes = []
data.folders
.forEach(function (oldFolder) {
let folderKey = keygen()
while (storage.folders.some((folder) => folder.key === folderKey)) {
folderKey = keygen()
}
let newFolder = {
const newFolder = {
key: folderKey,
name: oldFolder.name,
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
@@ -40,7 +40,7 @@ function importAll (storage, data) {
storage.folders.push(newFolder)
let articles = oldArticles.filter((article) => article.FolderKey === oldFolder.key)
const articles = oldArticles.filter((article) => article.FolderKey === oldFolder.key)
articles.forEach((article) => {
let noteKey = keygen()
let isUnique = false
@@ -59,7 +59,7 @@ function importAll (storage, data) {
}
if (article.mode === 'markdown') {
let newNote = {
const newNote = {
tags: article.tags,
createdAt: article.createdAt,
updatedAt: article.updatedAt,
@@ -73,7 +73,7 @@ function importAll (storage, data) {
}
notes.push(newNote)
} else {
let newNote = {
const newNote = {
tags: article.tags,
createdAt: article.createdAt,
updatedAt: article.updatedAt,

View File

@@ -20,7 +20,7 @@ function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) {
.then(function saveNote (_oldStorage) {
oldStorage = _oldStorage
let noteData
let notePath = path.join(oldStorage.path, 'notes', noteKey + '.cson')
const notePath = path.join(oldStorage.path, 'notes', noteKey + '.cson')
try {
noteData = CSON.readFileSync(notePath)
} catch (err) {

View File

@@ -1,6 +1,5 @@
const _ = require('lodash')
const resolveStorageData = require('./resolveStorageData')
const { findStorage } = require('browser/lib/findStorage')
/**
* @param {String} key
@@ -19,7 +18,7 @@ function renameStorage (key, name) {
console.error(err)
return Promise.reject(err)
}
let targetStorage = _.find(cachedStorageList, {key: key})
const targetStorage = _.find(cachedStorageList, {key: key})
if (targetStorage == null) return Promise.reject('Storage')
targetStorage.name = name

View File

@@ -18,7 +18,6 @@ const { findStorage } = require('browser/lib/findStorage')
* ```
*/
function reorderFolder (storageKey, oldIndex, newIndex) {
let rawStorages
let targetStorage
try {
if (!_.isNumber(oldIndex)) throw new Error('oldIndex must be a number.')

View File

@@ -4,7 +4,7 @@ const CSON = require('@rokt33r/season')
const migrateFromV6Storage = require('./migrateFromV6Storage')
function resolveStorageData (storageCache) {
let storage = {
const storage = {
key: storageCache.key,
name: storageCache.name,
type: storageCache.type,
@@ -13,7 +13,7 @@ function resolveStorageData (storageCache) {
const boostnoteJSONPath = path.join(storageCache.path, 'boostnote.json')
try {
let jsonData = CSON.readFileSync(boostnoteJSONPath)
const jsonData = CSON.readFileSync(boostnoteJSONPath)
if (!_.isArray(jsonData.folders)) throw new Error('folders should be an array.')
storage.folders = jsonData.folders
storage.version = jsonData.version
@@ -28,7 +28,7 @@ function resolveStorageData (storageCache) {
storage.version = '1.0'
}
let version = parseInt(storage.version, 10)
const version = parseInt(storage.version, 10)
if (version >= 1) {
if (version > 1) {
console.log('The repository version is newer than one of current app.')

View File

@@ -16,13 +16,13 @@ function resolveStorageNotes (storage) {
}
notePathList = []
}
let notes = notePathList
const notes = notePathList
.filter(function filterOnlyCSONFile (notePath) {
return /\.cson$/.test(notePath)
})
.map(function parseCSONFile (notePath) {
try {
let data = CSON.readFileSync(path.join(notesDirPath, notePath))
const data = CSON.readFileSync(path.join(notesDirPath, notePath))
data.key = path.basename(notePath, '.cson')
data.storage = storage.key
return data

View File

@@ -23,7 +23,6 @@ const { findStorage } = require('browser/lib/findStorage')
* ```
*/
function updateFolder (storageKey, folderKey, input) {
let rawStorages
let targetStorage
try {
if (input == null) throw new Error('No input found.')
@@ -37,7 +36,7 @@ function updateFolder (storageKey, folderKey, input) {
return resolveStorageData(targetStorage)
.then(function updateFolder (storage) {
let targetFolder = _.find(storage.folders, {key: folderKey})
const targetFolder = _.find(storage.folders, {key: folderKey})
if (targetFolder == null) throw new Error('Target folder doesn\'t exist.')
targetFolder.name = input.name
targetFolder.color = input.color

View File

@@ -5,7 +5,7 @@ const CSON = require('@rokt33r/season')
const { findStorage } = require('browser/lib/findStorage')
function validateInput (input) {
let validatedInput = {}
const validatedInput = {}
if (input.tags != null) {
if (!_.isArray(input.tags)) validatedInput.tags = []
@@ -81,7 +81,7 @@ function updateNote (storageKey, noteKey, input) {
return resolveStorageData(targetStorage)
.then(function saveNote (storage) {
let noteData
let notePath = path.join(storage.path, 'notes', noteKey + '.cson')
const notePath = path.join(storage.path, 'notes', noteKey + '.cson')
try {
noteData = CSON.readFileSync(notePath)
} catch (err) {

View File

@@ -16,7 +16,7 @@ class ModalBase extends React.Component {
close () {
if (modalBase != null) modalBase.setState({component: null, componentProps: null, isHidden: true})
// Toggle overflow style on NoteList
let list = document.querySelector('.NoteList__list___browser-main-NoteList-')
const list = document.querySelector('.NoteList__list___browser-main-NoteList-')
list.style.overflow = 'auto'
}
@@ -34,14 +34,14 @@ class ModalBase extends React.Component {
}
}
let el = document.createElement('div')
const el = document.createElement('div')
document.body.appendChild(el)
let modalBase = ReactDOM.render(<ModalBase />, el)
const modalBase = ReactDOM.render(<ModalBase />, el)
export function openModal (component, props) {
if (modalBase == null) { return }
// Hide scrollbar by removing overflow when modal opens
let list = document.querySelector('.NoteList__list___browser-main-NoteList-')
const list = document.querySelector('.NoteList__list___browser-main-NoteList-')
list.style.overflow = 'hidden'
document.body.setAttribute('data-modal', 'open')
modalBase.setState({component: component, componentProps: props, isHidden: false})

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './CreateFolderModal.styl'
import dataApi from 'browser/main/lib/dataApi'
@@ -51,8 +52,8 @@ class CreateFolderModal extends React.Component {
confirm () {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_FOLDER')
if (this.state.name.trim().length > 0) {
let { storage } = this.props
let input = {
const { storage } = this.props
const input = {
name: this.state.name.trim(),
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
}

View File

@@ -5,7 +5,6 @@ import dataApi from 'browser/main/lib/dataApi'
import store from 'browser/main/store'
import { hashHistory } from 'react-router'
import _ from 'lodash'
import ModalEscButton from 'browser/components/ModalEscButton'
const CSON = require('@rokt33r/season')
const path = require('path')
@@ -13,9 +12,9 @@ const electron = require('electron')
const { remote } = electron
function browseFolder () {
let dialog = remote.dialog
const dialog = remote.dialog
let defaultPath = remote.app.getPath('home')
const defaultPath = remote.app.getPath('home')
return new Promise((resolve, reject) => {
dialog.showOpenDialog({
title: 'Select Directory',
@@ -55,7 +54,7 @@ class InitModal extends React.Component {
} catch (err) {
console.error(err)
}
let newState = {
const newState = {
isLoading: false
}
if (data != null) {
@@ -122,7 +121,7 @@ class InitModal extends React.Component {
notes: data.notes
})
let defaultSnippetNote = dataApi
const defaultSnippetNote = dataApi
.createNote(data.storage.key, {
type: 'SNIPPET_NOTE',
folder: data.storage.folders[0].key,
@@ -147,7 +146,7 @@ class InitModal extends React.Component {
note: note
})
})
let defaultMarkdownNote = dataApi
const defaultMarkdownNote = dataApi
.createNote(data.storage.key, {
type: 'MARKDOWN_NOTE',
folder: data.storage.folders[0].key,
@@ -184,6 +183,12 @@ class InitModal extends React.Component {
})
}
handleKeyDown (e) {
if (e.keyCode === 27) {
this.props.close()
}
}
render () {
if (this.state.isLoading) {
return <div styleName='root--loading'>
@@ -194,19 +199,14 @@ class InitModal extends React.Component {
return (
<div styleName='root'
tabIndex='-1'
onKeyDown={this.props.close}
onKeyDown={(e) => this.handleKeyDown(e)}
>
<div styleName='header'>
<div styleName='header-title'>Initialize Storage</div>
</div>
<ModalEscButton handleEscButtonClick={this.props.close} />
<div styleName='body'>
<div styleName='body-welcome'>
Welcome!
Welcome to Boostnote!
</div>
<div styleName='body-description'>
Please select a directory for Boostnote storage.
Please select a directory for data storage.
</div>
<div styleName='body-path'>
<input styleName='body-path-input'
@@ -237,7 +237,7 @@ class InitModal extends React.Component {
? <span>
<i className='fa fa-spin fa-spinner' /> Loading...
</span>
: 'Let\'s Go!'
: 'CREATE'
}
</button>
</div>

View File

@@ -1,7 +1,11 @@
.root
modal()
max-width 540px
background-color #fff
max-width 100vw
max-height 100vh
overflow hidden
margin 0
padding 150px 0
position relative
.root--loading
@extend .root
@@ -13,14 +17,6 @@
.loadingMessage
color $ui-text-color
margin 15px auto 35px
.header
height 50px
font-size 18px
line-height 50px
padding 0 15px
background-color $ui-backgroundColor
border-bottom solid 1px $ui-borderColor
color $ui-text-color
.body
padding 30px
@@ -32,20 +28,20 @@
color $ui-text-color
.body-description
font-size 14px
font-size 16px
color $ui-text-color
text-align center
margin-bottom 25px
.body-path
margin 0 auto 25px
width 280px
width 330px
.body-path-input
height 30px
height 40px
vertical-align middle
width 250px
font-size 12px
width 300px
font-size 14px
border-style solid
border-width 1px 0 1px 1px
border-color $border-color
@@ -54,7 +50,10 @@
padding 0 5px
.body-path-button
height 30px
height 42px
width 30px
font-size 16px
font-weight 600
border none
border-top-right-radius 2px
border-bottom-right-radius 2px
@@ -69,6 +68,8 @@
.body-control-createButton
colorPrimaryButton()
font-size 14px
font-weight 600
border none
border-radius 2px
height 40px

View File

@@ -26,7 +26,7 @@ class NewNoteModal extends React.Component {
handleMarkdownNoteButtonClick (e) {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_MARKDOWN')
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
let { storage, folder, dispatch, location } = this.props
const { storage, folder, dispatch, location } = this.props
dataApi
.createNote(storage, {
type: 'MARKDOWN_NOTE',
@@ -58,7 +58,7 @@ class NewNoteModal extends React.Component {
handleSnippetNoteButtonClick (e) {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_SNIPPET')
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
let { storage, folder, dispatch, location } = this.props
const { storage, folder, dispatch, location } = this.props
dataApi
.createNote(storage, {

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import ReactDOM from 'react-dom'
import styles from './FolderItem.styl'
@@ -23,7 +24,7 @@ class FolderItem extends React.Component {
}
handleEditChange (e) {
let { folder } = this.state
const { folder } = this.state
folder.name = this.refs.nameInput.value
this.setState({
@@ -36,7 +37,7 @@ class FolderItem extends React.Component {
}
confirm () {
let { storage, folder } = this.props
const { storage, folder } = this.props
dataApi
.updateFolder(storage.key, folder.key, {
color: this.state.folder.color,
@@ -162,7 +163,7 @@ class FolderItem extends React.Component {
}
handleDeleteConfirmButtonClick (e) {
let { storage, folder } = this.props
const { storage, folder } = this.props
dataApi
.deleteFolder(storage.key, folder.key)
.then((data) => {
@@ -197,8 +198,8 @@ class FolderItem extends React.Component {
}
handleEditButtonClick (e) {
let { folder: propsFolder } = this.props
let { folder: stateFolder } = this.state
const { folder: propsFolder } = this.props
const { folder: stateFolder } = this.state
const folder = Object.assign({}, stateFolder, propsFolder)
this.setState({
status: 'EDIT',
@@ -215,7 +216,7 @@ class FolderItem extends React.Component {
}
renderIdle () {
let { folder } = this.props
const { folder } = this.props
return (
<div styleName='folderItem'
onDoubleClick={(e) => this.handleEditButtonClick(e)}

View File

@@ -1,16 +1,17 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import dataApi from 'browser/main/lib/dataApi'
import styles from './FolderList.styl'
import store from 'browser/main/store'
import FolderItem from './FolderItem'
import { SortableContainer, arrayMove } from 'react-sortable-hoc'
import { SortableContainer } from 'react-sortable-hoc'
class FolderList extends React.Component {
render () {
let { storage, hostBoundingBox } = this.props
const { storage, hostBoundingBox } = this.props
let folderList = storage.folders.map((folder, index) => {
const folderList = storage.folders.map((folder, index) => {
return <FolderItem key={folder.key}
folder={folder}
storage={storage}
@@ -53,7 +54,7 @@ class SortableFolderListComponent extends React.Component {
constructor (props) {
super(props)
this.onSortEnd = ({oldIndex, newIndex}) => {
let { storage } = this.props
const { storage } = this.props
dataApi
.reorderFolder(storage.key, oldIndex, newIndex)
.then((data) => {

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './ConfigTab.styl'
import ConfigManager from 'browser/main/lib/ConfigManager'
@@ -41,7 +42,7 @@ class HotkeyTab extends React.Component {
}
handleSaveButtonClick (e) {
let newConfig = {
const newConfig = {
hotkey: this.state.config.hotkey
}
@@ -61,7 +62,7 @@ class HotkeyTab extends React.Component {
}
handleHotkeyChange (e) {
let { config } = this.state
const { config } = this.state
config.hotkey = {
toggleFinder: this.refs.toggleFinder.value,
toggleMain: this.refs.toggleMain.value
@@ -80,13 +81,13 @@ class HotkeyTab extends React.Component {
}
render () {
let keymapAlert = this.state.keymapAlert
let keymapAlertElement = keymapAlert != null
const keymapAlert = this.state.keymapAlert
const keymapAlertElement = keymapAlert != null
? <p className={`alert ${keymapAlert.type}`}>
{keymapAlert.message}
</p>
: null
let { config } = this.state
const { config } = this.state
return (
<div styleName='root'>

View File

@@ -72,6 +72,11 @@ class InfoTab extends React.Component {
<div styleName='header--sub'>Community</div>
<div styleName='top'>
<ul styleName='list'>
<li>
<a href='https://boostnote.io/#subscribe'
onClick={(e) => this.handleLinkClick(e)}
>Subscribe to Newsletter</a>
</li>
<li>
<a href='https://github.com/BoostIO/Boostnote/issues'
onClick={(e) => this.handleLinkClick(e)}
@@ -82,11 +87,6 @@ class InfoTab extends React.Component {
onClick={(e) => this.handleLinkClick(e)}
>Blog</a>
</li>
<li>
<a href='https://www.reddit.com/r/Boostnote/'
onClick={(e) => this.handleLinkClick(e)}
>Reddit</a>
</li>
<li>
<a href='https://www.facebook.com/groups/boostnote'
onClick={(e) => this.handleLinkClick(e)}

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './StorageItem.styl'
import consts from 'browser/lib/consts'
@@ -19,8 +20,8 @@ class StorageItem extends React.Component {
}
handleNewFolderButtonClick (e) {
let { storage } = this.props
let input = {
const { storage } = this.props
const input = {
name: 'Untitled',
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
}
@@ -38,12 +39,12 @@ class StorageItem extends React.Component {
}
handleExternalButtonClick () {
let { storage } = this.props
const { storage } = this.props
shell.showItemInFolder(storage.path)
}
handleUnlinkButtonClick (e) {
let index = dialog.showMessageBox(remote.getCurrentWindow(), {
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
type: 'warning',
message: 'Unlink Storage',
detail: 'Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.',
@@ -51,7 +52,7 @@ class StorageItem extends React.Component {
})
if (index === 0) {
let { storage } = this.props
const { storage } = this.props
dataApi.removeStorage(storage.key)
.then(() => {
store.dispatch({
@@ -66,7 +67,7 @@ class StorageItem extends React.Component {
}
handleLabelClick (e) {
let { storage } = this.props
const { storage } = this.props
this.setState({
isLabelEditing: true,
name: storage.name
@@ -81,7 +82,7 @@ class StorageItem extends React.Component {
}
handleLabelBlur (e) {
let { storage } = this.props
const { storage } = this.props
dataApi
.renameStorage(storage.key, this.state.name)
.then((_storage) => {
@@ -96,7 +97,7 @@ class StorageItem extends React.Component {
}
render () {
let { storage, hostBoundingBox } = this.props
const { storage, hostBoundingBox } = this.props
return (
<div styleName='root' key={storage.key}>

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './StoragesTab.styl'
import dataApi from 'browser/main/lib/dataApi'
@@ -8,9 +9,9 @@ const electron = require('electron')
const { shell, remote } = electron
function browseFolder () {
let dialog = remote.dialog
const dialog = remote.dialog
let defaultPath = remote.app.getPath('home')
const defaultPath = remote.app.getPath('home')
return new Promise((resolve, reject) => {
dialog.showOpenDialog({
title: 'Select Directory',
@@ -56,10 +57,10 @@ class StoragesTab extends React.Component {
}
renderList () {
let { data, boundingBox } = this.props
const { data, boundingBox } = this.props
if (!boundingBox) { return null }
let storageList = data.storageMap.map((storage) => {
const storageList = data.storageMap.map((storage) => {
return <StorageItem
key={storage.key}
storage={storage}
@@ -88,7 +89,7 @@ class StoragesTab extends React.Component {
browseFolder()
.then((targetPath) => {
if (targetPath.length > 0) {
let { newStorage } = this.state
const { newStorage } = this.state
newStorage.path = targetPath
this.setState({
newStorage
@@ -102,7 +103,7 @@ class StoragesTab extends React.Component {
}
handleAddStorageChange (e) {
let { newStorage } = this.state
const { newStorage } = this.state
newStorage.name = this.refs.addStorageName.value
newStorage.path = this.refs.addStoragePath.value
this.setState({
@@ -117,7 +118,7 @@ class StoragesTab extends React.Component {
path: this.state.newStorage.path
})
.then((data) => {
let { dispatch } = this.props
const { dispatch } = this.props
dispatch({
type: 'ADD_STORAGE',
storage: data.storage,

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './ConfigTab.styl'
import ConfigManager from 'browser/main/lib/ConfigManager'
@@ -24,6 +25,7 @@ class UiTab extends React.Component {
}
componentDidMount () {
CodeMirror.autoLoadMode(this.codeMirrorInstance.getCodeMirror(), 'javascript')
this.handleSettingDone = () => {
this.setState({UiAlert: {
type: 'success',
@@ -40,10 +42,6 @@ class UiTab extends React.Component {
ipc.addListener('APP_SETTING_ERROR', this.handleSettingError)
}
componentWillMount () {
CodeMirror.autoLoadMode(ReactCodeMirror, 'javascript')
}
componentWillUnmount () {
ipc.removeListener('APP_SETTING_DONE', this.handleSettingDone)
ipc.removeListener('APP_SETTING_ERROR', this.handleSettingError)
@@ -119,8 +117,8 @@ class UiTab extends React.Component {
}
render () {
let UiAlert = this.state.UiAlert
let UiAlertElement = UiAlert != null
const UiAlert = this.state.UiAlert
const UiAlertElement = UiAlert != null
? <p className={`alert ${UiAlert.type}`}>
{UiAlert.message}
</p>
@@ -190,7 +188,7 @@ class UiTab extends React.Component {
}
</select>
<div styleName='code-mirror'>
<ReactCodeMirror value={codemirrorSampleCode} options={{ lineNumbers: true, readOnly: true, mode: 'javascript', theme: codemirrorTheme }} />
<ReactCodeMirror ref={e => (this.codeMirrorInstance = e)} value={codemirrorSampleCode} options={{ lineNumbers: true, readOnly: true, mode: 'javascript', theme: codemirrorTheme }} />
</div>
</div>
</div>

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import ReactDOM from 'react-dom'
import { connect } from 'react-redux'
import HotkeyTab from './HotkeyTab'
@@ -42,7 +43,7 @@ class Preferences extends React.Component {
renderContent () {
const { boundingBox } = this.state
let { dispatch, config, data } = this.props
const { dispatch, config, data } = this.props
switch (this.state.currentTab) {
case 'INFO':
@@ -94,9 +95,9 @@ class Preferences extends React.Component {
}
render () {
let content = this.renderContent()
const content = this.renderContent()
let tabs = [
const tabs = [
{target: 'STORAGES', label: 'Storages'},
{target: 'HOTKEY', label: 'Hotkey'},
{target: 'UI', label: 'UI'},
@@ -104,8 +105,8 @@ class Preferences extends React.Component {
{target: 'CROWDFUNDING', label: 'Crowdfunding'}
]
let navButtons = tabs.map((tab) => {
let isActive = this.state.currentTab === tab.target
const navButtons = tabs.map((tab) => {
const isActive = this.state.currentTab === tab.target
return (
<button styleName={isActive
? 'nav-button--active'

View File

@@ -1,4 +1,5 @@
import React, { PropTypes } from 'react'
import PropTypes from 'prop-types'
import React from 'react'
import CSSModules from 'browser/lib/CSSModules'
import styles from './RenameFolderModal.styl'
import dataApi from 'browser/main/lib/dataApi'
@@ -48,7 +49,7 @@ class RenameFolderModal extends React.Component {
confirm () {
if (this.state.name.trim().length > 0) {
let { storage, folder } = this.props
const { storage, folder } = this.props
dataApi
.updateFolder(storage.key, folder.key, {
name: this.state.name,

View File

@@ -27,8 +27,8 @@ function data (state = defaultDataMap(), action) {
action.notes.some((note) => {
if (note === undefined) return true
let uniqueKey = note.storage + '-' + note.key
let folderKey = note.storage + '-' + note.folder
const uniqueKey = note.storage + '-' + note.key
const folderKey = note.storage + '-' + note.folder
state.noteMap.set(uniqueKey, note)
if (note.isStarred) {
@@ -65,10 +65,10 @@ function data (state = defaultDataMap(), action) {
return state
case 'UPDATE_NOTE':
{
let note = action.note
let uniqueKey = note.storage + '-' + note.key
let folderKey = note.storage + '-' + note.folder
let oldNote = state.noteMap.get(uniqueKey)
const note = action.note
const uniqueKey = note.storage + '-' + note.key
const folderKey = note.storage + '-' + note.folder
const oldNote = state.noteMap.get(uniqueKey)
state = Object.assign({}, state)
state.noteMap = new Map(state.noteMap)
@@ -110,7 +110,7 @@ function data (state = defaultDataMap(), action) {
state.folderNoteMap.set(folderKey, folderNoteSet)
if (oldNote != null) {
let oldFolderKey = oldNote.storage + '-' + oldNote.folder
const oldFolderKey = oldNote.storage + '-' + oldNote.folder
let oldFolderNoteList = state.folderNoteMap.get(oldFolderKey)
oldFolderNoteList = new Set(oldFolderNoteList)
oldFolderNoteList.delete(uniqueKey)
@@ -119,8 +119,8 @@ function data (state = defaultDataMap(), action) {
}
if (oldNote != null) {
let discardedTags = _.difference(oldNote.tags, note.tags)
let addedTags = _.difference(note.tags, oldNote.tags)
const discardedTags = _.difference(oldNote.tags, note.tags)
const addedTags = _.difference(note.tags, oldNote.tags)
if (discardedTags.length + addedTags.length > 0) {
state.tagNoteMap = new Map(state.tagNoteMap)
@@ -156,12 +156,12 @@ function data (state = defaultDataMap(), action) {
}
case 'MOVE_NOTE':
{
let originNote = action.originNote
let originKey = originNote.storage + '-' + originNote.key
let note = action.note
let uniqueKey = note.storage + '-' + note.key
let folderKey = note.storage + '-' + note.folder
let oldNote = state.noteMap.get(uniqueKey)
const originNote = action.originNote
const originKey = originNote.storage + '-' + originNote.key
const note = action.note
const uniqueKey = note.storage + '-' + note.key
const folderKey = note.storage + '-' + note.folder
const oldNote = state.noteMap.get(uniqueKey)
state = Object.assign({}, state)
state.noteMap = new Map(state.noteMap)
@@ -191,7 +191,7 @@ function data (state = defaultDataMap(), action) {
// From folderNoteMap
state.folderNoteMap = new Map(state.folderNoteMap)
let originFolderKey = originNote.storage + '-' + originNote.folder
const originFolderKey = originNote.storage + '-' + originNote.folder
let originFolderList = state.folderNoteMap.get(originFolderKey)
originFolderList = new Set(originFolderList)
originFolderList.delete(originKey)
@@ -245,7 +245,7 @@ function data (state = defaultDataMap(), action) {
state.folderNoteMap.set(folderKey, folderNoteList)
if (oldNote != null) {
let oldFolderKey = oldNote.storage + '-' + oldNote.folder
const oldFolderKey = oldNote.storage + '-' + oldNote.folder
let oldFolderNoteList = state.folderNoteMap.get(oldFolderKey)
oldFolderNoteList = new Set(oldFolderNoteList)
oldFolderNoteList.delete(uniqueKey)
@@ -255,8 +255,8 @@ function data (state = defaultDataMap(), action) {
// Remove from old folder map
if (oldNote != null) {
let discardedTags = _.difference(oldNote.tags, note.tags)
let addedTags = _.difference(note.tags, oldNote.tags)
const discardedTags = _.difference(oldNote.tags, note.tags)
const addedTags = _.difference(note.tags, oldNote.tags)
if (discardedTags.length + addedTags.length > 0) {
state.tagNoteMap = new Map(state.tagNoteMap)
@@ -292,8 +292,8 @@ function data (state = defaultDataMap(), action) {
}
case 'DELETE_NOTE':
{
let uniqueKey = action.storageKey + '-' + action.noteKey
let targetNote = state.noteMap.get(uniqueKey)
const uniqueKey = action.storageKey + '-' + action.noteKey
const targetNote = state.noteMap.get(uniqueKey)
state = Object.assign({}, state)
@@ -317,7 +317,7 @@ function data (state = defaultDataMap(), action) {
}
// From folderNoteMap
let folderKey = targetNote.storage + '-' + targetNote.folder
const folderKey = targetNote.storage + '-' + targetNote.folder
state.folderNoteMap = new Map(state.folderNoteMap)
let folderSet = state.folderNoteMap.get(folderKey)
folderSet = new Set(folderSet)
@@ -340,18 +340,14 @@ function data (state = defaultDataMap(), action) {
return state
}
case 'UPDATE_FOLDER':
{
state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap)
state.storageMap.set(action.storage.key, action.storage)
}
state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap)
state.storageMap.set(action.storage.key, action.storage)
return state
case 'REORDER_FOLDER':
{
state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap)
state.storageMap.set(action.storage.key, action.storage)
}
state = Object.assign({}, state)
state.storageMap = new Map(state.storageMap)
state.storageMap.set(action.storage.key, action.storage)
return state
case 'DELETE_FOLDER':
{
@@ -361,8 +357,8 @@ function data (state = defaultDataMap(), action) {
// Get note list from folder-note map
// and delete note set from folder-note map
let folderKey = action.storage.key + '-' + action.folderKey
let noteSet = state.folderNoteMap.get(folderKey)
const folderKey = action.storage.key + '-' + action.folderKey
const noteSet = state.folderNoteMap.get(folderKey)
state.folderNoteMap = new Map(state.folderNoteMap)
state.folderNoteMap.delete(folderKey)
@@ -375,7 +371,7 @@ function data (state = defaultDataMap(), action) {
if (noteSet != null) {
noteSet.forEach(function handleNoteKey (noteKey) {
// Get note from noteMap
let note = state.noteMap.get(noteKey)
const note = state.noteMap.get(noteKey)
if (note != null) {
state.noteMap.delete(noteKey)
@@ -417,8 +413,8 @@ function data (state = defaultDataMap(), action) {
state.folderNoteMap = new Map(state.folderNoteMap)
state.tagNoteMap = new Map(state.tagNoteMap)
action.notes.forEach((note) => {
let uniqueKey = note.storage + '-' + note.key
let folderKey = note.storage + '-' + note.folder
const uniqueKey = note.storage + '-' + note.key
const folderKey = note.storage + '-' + note.folder
state.noteMap.set(uniqueKey, note)
if (note.isStarred) {
@@ -451,7 +447,7 @@ function data (state = defaultDataMap(), action) {
return state
case 'REMOVE_STORAGE':
state = Object.assign({}, state)
let storage = state.storageMap.get(action.storageKey)
const storage = state.storageMap.get(action.storageKey)
state.storageMap = new Map(state.storageMap)
state.storageMap.delete(action.storageKey)
@@ -459,17 +455,17 @@ function data (state = defaultDataMap(), action) {
if (storage != null) {
state.folderMap = new Map(state.folderMap)
storage.folders.forEach((folder) => {
let folderKey = storage.key + '-' + folder.key
const folderKey = storage.key + '-' + folder.key
state.folderMap.delete(folderKey)
})
}
// Remove notes from noteMap and tagNoteMap
let storageNoteSet = state.storageNoteMap.get(action.storageKey)
const storageNoteSet = state.storageNoteMap.get(action.storageKey)
state.storageNoteMap = new Map(state.storageNoteMap)
state.storageNoteMap.delete(action.storageKey)
if (storageNoteSet != null) {
let notes = storageNoteSet
const notes = storageNoteSet
.map((noteKey) => state.noteMap.get(noteKey))
.filter((note) => note != null)
@@ -477,7 +473,7 @@ function data (state = defaultDataMap(), action) {
state.tagNoteMap = new Map(state.tagNoteMap)
state.starredSet = new Set(state.starredSet)
notes.forEach((note) => {
let noteKey = storage.key + '-' + note.key
const noteKey = storage.key + '-' + note.key
state.noteMap.delete(noteKey)
state.starredSet.delete(noteKey)
note.tags.forEach((tag) => {
@@ -535,13 +531,13 @@ function status (state = defaultStatus, action) {
return state
}
let reducer = combineReducers({
const reducer = combineReducers({
data,
config,
status,
routing: routerReducer
})
let store = createStore(reducer)
const store = createStore(reducer)
export default store

View File

@@ -86,6 +86,7 @@ colorPrimaryButton()
color $ui-text-color
background-color $default-button-background--hover
&:hover
transition 0.2s
background-color $default-button-background--active
&:active
&:active:hover

View File

@@ -61,8 +61,12 @@ if (process.platform !== 'linux' || process.env.DESKTOP_SESSION === 'cinnamon')
mainWindow.removeAllListeners()
})
} else {
mainWindow.on('close', function () {
storeWindowSize()
})
app.on('window-all-closed', function () {
quitApp()
app.quit()
})
}

View File

@@ -1,7 +1,7 @@
{
"name": "boost",
"productName": "Boostnote",
"version": "0.8.17",
"version": "0.8.18",
"main": "index.js",
"description": "Boostnote",
"license": "GPL-3.0",
@@ -76,7 +76,7 @@
"moment": "^2.10.3",
"node-ipc": "^8.1.0",
"raphael": "^2.2.7",
"react": "^15.0.2",
"react": "^15.5.4",
"react-codemirror": "^0.3.0",
"react-dom": "^15.0.2",
"react-redux": "^4.4.5",

View File

@@ -36,7 +36,7 @@ test.serial('Add Storage', (t) => {
return addStorage(input)
})
.then(function validateResult (data) {
let { storage, notes } = data
const { storage, notes } = data
// Check data.storage
t.true(_.isString(storage.key))
@@ -53,13 +53,13 @@ test.serial('Add Storage', (t) => {
})
// Check localStorage
let cacheData = _.find(JSON.parse(localStorage.getItem('storages')), {key: data.storage.key})
const cacheData = _.find(JSON.parse(localStorage.getItem('storages')), {key: data.storage.key})
t.is(cacheData.name, input.name)
t.is(cacheData.type, input.type)
t.is(cacheData.path, input.path)
// Check boostnote.json
let jsonData = CSON.readFileSync(path.join(storage.path, 'boostnote.json'))
const jsonData = CSON.readFileSync(path.join(storage.path, 'boostnote.json'))
t.true(_.isArray(jsonData.folders))
t.is(jsonData.version, '1.0')
t.is(jsonData.folders.length, t.context.v1StorageData.json.folders.length)

View File

@@ -33,7 +33,7 @@ test.serial('Create a folder', (t) => {
})
.then(function assert (data) {
t.true(_.find(data.storage.folders, input) != null)
let jsonData = CSON.readFileSync(path.join(data.storage.path, 'boostnote.json'))
const jsonData = CSON.readFileSync(path.join(data.storage.path, 'boostnote.json'))
console.log(path.join(data.storage.path, 'boostnote.json'))
t.true(_.find(jsonData.folders, input) != null)
})

View File

@@ -54,11 +54,11 @@ test.serial('Create a note', (t) => {
])
})
.then(function assert (data) {
let data1 = data[0]
let data2 = data[1]
const data1 = data[0]
const data2 = data[1]
t.is(storageKey, data1.storage)
let jsonData1 = CSON.readFileSync(path.join(storagePath, 'notes', data1.key + '.cson'))
const jsonData1 = CSON.readFileSync(path.join(storagePath, 'notes', data1.key + '.cson'))
t.is(input1.title, data1.title)
t.is(input1.title, jsonData1.title)
t.is(input1.description, data1.description)
@@ -73,7 +73,7 @@ test.serial('Create a note', (t) => {
t.is(input1.snippets[0].name, jsonData1.snippets[0].name)
t.is(storageKey, data2.storage)
let jsonData2 = CSON.readFileSync(path.join(storagePath, 'notes', data2.key + '.cson'))
const jsonData2 = CSON.readFileSync(path.join(storagePath, 'notes', data2.key + '.cson'))
t.is(input2.title, data2.title)
t.is(input2.title, jsonData2.title)
t.is(input2.content, data2.content)

View File

@@ -31,10 +31,10 @@ test.serial('Delete a folder', (t) => {
})
.then(function assert (data) {
t.true(_.find(data.storage.folders, {key: folderKey}) == null)
let jsonData = CSON.readFileSync(path.join(data.storage.path, 'boostnote.json'))
const jsonData = CSON.readFileSync(path.join(data.storage.path, 'boostnote.json'))
t.true(_.find(jsonData.folders, {key: folderKey}) == null)
let notePaths = sander.readdirSync(data.storage.path, 'notes')
const notePaths = sander.readdirSync(data.storage.path, 'notes')
t.is(notePaths.length, t.context.storage.notes.filter((note) => note.folder !== folderKey).length)
})
})

View File

@@ -17,7 +17,7 @@ const os = require('os')
const dummyStoragePath = path.join(os.tmpdir(), 'test/migrate-test-storage')
test.beforeEach((t) => {
let dummyData = t.context.dummyData = TestDummy.dummyLegacyStorage(dummyStoragePath)
const dummyData = t.context.dummyData = TestDummy.dummyLegacyStorage(dummyStoragePath)
console.log('init count', dummyData.notes.length)
localStorage.setItem('storages', JSON.stringify([dummyData.cache]))
})
@@ -32,11 +32,11 @@ test.serial('Migrate legacy storage into v1 storage', (t) => {
t.true(data)
// Check all notes migrated.
let dummyData = t.context.dummyData
let noteDirPath = path.join(dummyStoragePath, 'notes')
let fileList = sander.readdirSync(noteDirPath)
const dummyData = t.context.dummyData
const noteDirPath = path.join(dummyStoragePath, 'notes')
const fileList = sander.readdirSync(noteDirPath)
t.is(dummyData.notes.length, fileList.length)
let noteMap = fileList
const noteMap = fileList
.map((filePath) => {
return CSON.readFileSync(path.join(noteDirPath, filePath))
})

View File

@@ -38,15 +38,15 @@ test.serial('Move a note', (t) => {
])
})
.then(function assert (data) {
let data1 = data[0]
let data2 = data[1]
const data1 = data[0]
const data2 = data[1]
let jsonData1 = CSON.readFileSync(path.join(storagePath, 'notes', data1.key + '.cson'))
const jsonData1 = CSON.readFileSync(path.join(storagePath, 'notes', data1.key + '.cson'))
t.is(jsonData1.folder, folderKey1)
t.is(jsonData1.title, note1.title)
let jsonData2 = CSON.readFileSync(path.join(storagePath2, 'notes', data2.key + '.cson'))
const jsonData2 = CSON.readFileSync(path.join(storagePath2, 'notes', data2.key + '.cson'))
t.is(jsonData2.folder, folderKey2)
t.is(jsonData2.title, note2.title)
try {

View File

@@ -27,7 +27,7 @@ test.serial('Rename a storage', (t) => {
return renameStorage(storageKey, 'changed')
})
.then(function assert (data) {
let cachedStorageList = JSON.parse(localStorage.getItem('storages'))
const cachedStorageList = JSON.parse(localStorage.getItem('storages'))
t.true(_.find(cachedStorageList, {key: storageKey}).name === 'changed')
})
})

View File

@@ -34,8 +34,7 @@ test.serial('Reorder a folder', (t) => {
t.true(_.nth(data.storage.folders, 0).key === secondFolderKey)
t.true(_.nth(data.storage.folders, 1).key === firstFolderKey)
let jsonData = CSON.readFileSync(path.join(data.storage.path, 'boostnote.json'))
console.log(path.join(data.storage.path, 'boostnote.json'))
const jsonData = CSON.readFileSync(path.join(data.storage.path, 'boostnote.json'))
t.true(_.nth(jsonData.folders, 0).key === secondFolderKey)
t.true(_.nth(jsonData.folders, 1).key === firstFolderKey)

View File

@@ -34,7 +34,7 @@ test.serial('Update a folder', (t) => {
})
.then(function assert (data) {
t.true(_.find(data.storage.folders, input) != null)
let jsonData = CSON.readFileSync(path.join(data.storage.path, 'boostnote.json'))
const jsonData = CSON.readFileSync(path.join(data.storage.path, 'boostnote.json'))
console.log(path.join(data.storage.path, 'boostnote.json'))
t.true(_.find(jsonData.folders, input) != null)
})

Some files were not shown because too many files have changed in this diff Show More