mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 02:06:29 +00:00
Merge with master resolve conflict
This commit is contained in:
@@ -12,5 +12,10 @@
|
|||||||
"react/no-find-dom-node": "warn",
|
"react/no-find-dom-node": "warn",
|
||||||
"react/no-render-return-value": "warn",
|
"react/no-render-return-value": "warn",
|
||||||
"react/no-deprecated": "warn"
|
"react/no-deprecated": "warn"
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"FileReader": true,
|
||||||
|
"localStorage": true,
|
||||||
|
"fetch": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
81
Backers.md
81
Backers.md
@@ -1,43 +1,72 @@
|
|||||||
Dear all,
|
<h1 align="center">Sponsors & Backers</h1>
|
||||||
|
|
||||||
Thanks for your using!
|
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:
|
||||||
Boostnote is used in about 200 countries and regions, it is a awesome developer community.
|
|
||||||
|
|
||||||
To continue supporting this growth, and to satisfy community expectations,
|
- [Become a backer or sponsor on Open Collective.](https://opencollective.com/boostnoteio)
|
||||||
we would like to invest more time in this project.
|
|
||||||
|
|
||||||
If you like this project and see its potential, you can help!
|
|
||||||
|
|
||||||
Thanks,
|
|
||||||
Boostnote maintainers.
|
|
||||||
|
|
||||||
### >> [Support via OpenCollective](https://opencollective.com/boostnoteio)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Backers
|
## Backers via OpenCollective
|
||||||
[Kazz](https://twitter.com/kazup_bot) - $65
|
|
||||||
|
|
||||||
Intense Raiden - $45
|
### [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/.
|
||||||
|
|
||||||
ravy22 - $25
|
### [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/.
|
||||||
|
|
||||||
trentpolack - $20
|
### [Bronze Sponsors / $50 per month](https://opencollective.com/boostnoteio/order/2258)
|
||||||
|
- Get your name and Url (or E-mail) on Readme.md on GitHub.
|
||||||
|
|
||||||
hikariru - $10
|
### [Backers3 / $10 per month](https://opencollective.com/boostnoteio/order/2176)
|
||||||
|
- [Ralph03](https://opencollective.com/ralph03)
|
||||||
|
|
||||||
kolchan11 - $10
|
- [Nikolas Dan](https://opencollective.com/nikolas-dan)
|
||||||
|
|
||||||
RonWalker22 - $10
|
### [Backers2 / $5 per month](https://opencollective.com/boostnoteio/order/2175)
|
||||||
|
- [Yeojong Kim](https://twitter.com/yeojoy)
|
||||||
|
|
||||||
hocchuc - $5
|
- [Scotia Draven](https://opencollective.com/scotia-draven)
|
||||||
|
|
||||||
Adam - $5
|
- [A. J. Vargas](https://opencollective.com/aj-vargas)
|
||||||
|
|
||||||
Steve - $5
|
### [Backers1](https://opencollective.com/boostnoteio/order/2563) and One-time sponsors
|
||||||
|
- Ryosuke Tamura - $30
|
||||||
|
|
||||||
evmin - $5
|
- tatoosh11 - $10
|
||||||
|
|
||||||
[@yeojoy](https://twitter.com/yeojoy) - $5
|
- Alexander Borovkov - $10
|
||||||
|
|
||||||
Scotia Draven - $5
|
- spoonhoop - $5
|
||||||
|
|
||||||
|
- Drew Williams - $2
|
||||||
|
|
||||||
|
- Andy Shaw - $2
|
||||||
|
|
||||||
|
- mysafesky -$2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Backers via Bountysource
|
||||||
|
https://salt.bountysource.com/teams/boostnote
|
||||||
|
|
||||||
|
- Kuzz - $65
|
||||||
|
|
||||||
|
- Intense Raiden - $45
|
||||||
|
|
||||||
|
- ravy22 - $25
|
||||||
|
|
||||||
|
- trentpolack - $20
|
||||||
|
|
||||||
|
- hikariru - $10
|
||||||
|
|
||||||
|
- kolchan11 - $10
|
||||||
|
|
||||||
|
- RonWalker22 - $10
|
||||||
|
|
||||||
|
- hocchuc - $5
|
||||||
|
|
||||||
|
- Adam - $5
|
||||||
|
|
||||||
|
- Steve - $5
|
||||||
|
|
||||||
|
- evmin - $5
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import React, { PropTypes } from 'react'
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
@@ -67,7 +68,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
if (cm.somethingSelected()) cm.indentSelection('add')
|
if (cm.somethingSelected()) cm.indentSelection('add')
|
||||||
else {
|
else {
|
||||||
const tabs = cm.getOption('indentWithTabs')
|
const tabs = cm.getOption('indentWithTabs')
|
||||||
if (line.trimLeft() === '- ' || line.trimLeft() === '* ' || line.trimLeft() === '+ ') {
|
if (line.trimLeft().match(/^(-|\*|\+) (\[( |x)\] )?$/)) {
|
||||||
cm.execCommand('goLineStart')
|
cm.execCommand('goLineStart')
|
||||||
if (tabs) {
|
if (tabs) {
|
||||||
cm.execCommand('insertTab')
|
cm.execCommand('insertTab')
|
||||||
@@ -103,13 +104,14 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.on('change', this.changeHandler)
|
this.editor.on('change', this.changeHandler)
|
||||||
this.editor.on('paste', this.pasteHandler)
|
this.editor.on('paste', this.pasteHandler)
|
||||||
|
|
||||||
let editorTheme = document.getElementById('editorTheme')
|
const editorTheme = document.getElementById('editorTheme')
|
||||||
editorTheme.addEventListener('load', this.loadStyleHandler)
|
editorTheme.addEventListener('load', this.loadStyleHandler)
|
||||||
|
|
||||||
CodeMirror.Vim.defineEx('quit', 'q', this.quitEditor)
|
CodeMirror.Vim.defineEx('quit', 'q', this.quitEditor)
|
||||||
CodeMirror.Vim.defineEx('q!', 'q!', this.quitEditor)
|
CodeMirror.Vim.defineEx('q!', 'q!', this.quitEditor)
|
||||||
CodeMirror.Vim.defineEx('wq', 'wq', this.quitEditor)
|
CodeMirror.Vim.defineEx('wq', 'wq', this.quitEditor)
|
||||||
CodeMirror.Vim.defineEx('qw', 'qw', this.quitEditor)
|
CodeMirror.Vim.defineEx('qw', 'qw', this.quitEditor)
|
||||||
|
CodeMirror.Vim.map('ZZ', ':q', 'normal')
|
||||||
}
|
}
|
||||||
|
|
||||||
quitEditor () {
|
quitEditor () {
|
||||||
@@ -120,7 +122,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.off('blur', this.blurHandler)
|
this.editor.off('blur', this.blurHandler)
|
||||||
this.editor.off('change', this.changeHandler)
|
this.editor.off('change', this.changeHandler)
|
||||||
this.editor.off('paste', this.pasteHandler)
|
this.editor.off('paste', this.pasteHandler)
|
||||||
let editorTheme = document.getElementById('editorTheme')
|
const editorTheme = document.getElementById('editorTheme')
|
||||||
editorTheme.removeEventListener('load', this.loadStyleHandler)
|
editorTheme.removeEventListener('load', this.loadStyleHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +198,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setValue (value) {
|
setValue (value) {
|
||||||
let cursor = this.editor.getCursor()
|
const cursor = this.editor.getCursor()
|
||||||
this.editor.setValue(value)
|
this.editor.setValue(value)
|
||||||
this.editor.setCursor(cursor)
|
this.editor.setCursor(cursor)
|
||||||
}
|
}
|
||||||
@@ -213,9 +215,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
insertImageMd (imageMd) {
|
insertImageMd (imageMd) {
|
||||||
const textarea = this.editor.getInputField()
|
this.editor.replaceSelection(imageMd)
|
||||||
const cm = this.editor
|
|
||||||
cm.replaceSelection(`${textarea.value.substr(0, textarea.selectionStart)}${imageMd}${textarea.value.substr(textarea.selectionEnd)}`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handlePaste (editor, e) {
|
handlePaste (editor, e) {
|
||||||
@@ -223,7 +223,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
if (!dataTransferItem.type.match('image')) return
|
if (!dataTransferItem.type.match('image')) return
|
||||||
|
|
||||||
const blob = dataTransferItem.getAsFile()
|
const blob = dataTransferItem.getAsFile()
|
||||||
let reader = new FileReader()
|
const reader = new FileReader()
|
||||||
let base64data
|
let base64data
|
||||||
|
|
||||||
reader.readAsDataURL(blob)
|
reader.readAsDataURL(blob)
|
||||||
@@ -243,7 +243,8 @@ export default class CodeEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { className, fontFamily, fontSize } = this.props
|
const { className, fontSize } = this.props
|
||||||
|
let fontFamily = this.props.className
|
||||||
fontFamily = _.isString(fontFamily) && fontFamily.length > 0
|
fontFamily = _.isString(fontFamily) && fontFamily.length > 0
|
||||||
? [fontFamily].concat(defaultEditorFontFamily)
|
? [fontFamily].concat(defaultEditorFontFamily)
|
||||||
: defaultEditorFontFamily
|
: defaultEditorFontFamily
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './MarkdownEditor.styl'
|
import styles from './MarkdownEditor.styl'
|
||||||
import CodeEditor from 'browser/components/CodeEditor'
|
import CodeEditor from 'browser/components/CodeEditor'
|
||||||
import MarkdownPreview from 'browser/components/MarkdownPreview'
|
import MarkdownPreview from 'browser/components/MarkdownPreview'
|
||||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||||
import { findStorage } from 'browser/lib/findStorage'
|
import { findStorage } from 'browser/lib/findStorage'
|
||||||
const _ = require('lodash')
|
|
||||||
|
|
||||||
class MarkdownEditor extends React.Component {
|
class MarkdownEditor extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -70,9 +70,9 @@ class MarkdownEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleContextMenu (e) {
|
handleContextMenu (e) {
|
||||||
let { config } = this.props
|
const { config } = this.props
|
||||||
if (config.editor.switchPreview === 'RIGHTCLICK') {
|
if (config.editor.switchPreview === 'RIGHTCLICK') {
|
||||||
let newStatus = this.state.status === 'PREVIEW'
|
const newStatus = this.state.status === 'PREVIEW'
|
||||||
? 'CODE'
|
? 'CODE'
|
||||||
: 'PREVIEW'
|
: 'PREVIEW'
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -91,9 +91,9 @@ class MarkdownEditor extends React.Component {
|
|||||||
handleBlur (e) {
|
handleBlur (e) {
|
||||||
if (this.state.isLocked) return
|
if (this.state.isLocked) return
|
||||||
this.setState({ keyPressed: new Set() })
|
this.setState({ keyPressed: new Set() })
|
||||||
let { config } = this.props
|
const { config } = this.props
|
||||||
if (config.editor.switchPreview === 'BLUR') {
|
if (config.editor.switchPreview === 'BLUR') {
|
||||||
let cursorPosition = this.refs.code.editor.getCursor()
|
const cursorPosition = this.refs.code.editor.getCursor()
|
||||||
this.setState({
|
this.setState({
|
||||||
status: 'PREVIEW'
|
status: 'PREVIEW'
|
||||||
}, () => {
|
}, () => {
|
||||||
@@ -109,7 +109,7 @@ class MarkdownEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handlePreviewMouseUp (e) {
|
handlePreviewMouseUp (e) {
|
||||||
let { config } = this.props
|
const { config } = this.props
|
||||||
if (config.editor.switchPreview === 'BLUR' && new Date() - this.previewMouseDownedAt < 200) {
|
if (config.editor.switchPreview === 'BLUR' && new Date() - this.previewMouseDownedAt < 200) {
|
||||||
this.setState({
|
this.setState({
|
||||||
status: 'CODE'
|
status: 'CODE'
|
||||||
@@ -123,15 +123,15 @@ class MarkdownEditor extends React.Component {
|
|||||||
handleCheckboxClick (e) {
|
handleCheckboxClick (e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
let idMatch = /checkbox-([0-9]+)/
|
const idMatch = /checkbox-([0-9]+)/
|
||||||
let checkedMatch = /\[x\]/i
|
const checkedMatch = /\[x\]/i
|
||||||
let uncheckedMatch = /\[ \]/
|
const uncheckedMatch = /\[ \]/
|
||||||
if (idMatch.test(e.target.getAttribute('id'))) {
|
if (idMatch.test(e.target.getAttribute('id'))) {
|
||||||
let lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
|
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
|
||||||
let lines = this.refs.code.value
|
const lines = this.refs.code.value
|
||||||
.split('\n')
|
.split('\n')
|
||||||
|
|
||||||
let targetLine = lines[lineIndex]
|
const targetLine = lines[lineIndex]
|
||||||
|
|
||||||
if (targetLine.match(checkedMatch)) {
|
if (targetLine.match(checkedMatch)) {
|
||||||
lines[lineIndex] = targetLine.replace(checkedMatch, '[ ]')
|
lines[lineIndex] = targetLine.replace(checkedMatch, '[ ]')
|
||||||
@@ -163,12 +163,12 @@ class MarkdownEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown (e) {
|
handleKeyDown (e) {
|
||||||
let { config } = this.props
|
const { config } = this.props
|
||||||
if (this.state.status !== 'CODE') return false
|
if (this.state.status !== 'CODE') return false
|
||||||
const keyPressed = this.state.keyPressed
|
const keyPressed = this.state.keyPressed
|
||||||
keyPressed.add(e.keyCode)
|
keyPressed.add(e.keyCode)
|
||||||
this.setState({ keyPressed })
|
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
|
// These conditions are for ctrl-e and ctrl-w
|
||||||
if (keyPressed.size === this.escapeFromEditor.length &&
|
if (keyPressed.size === this.escapeFromEditor.length &&
|
||||||
!this.state.isLocked && this.state.status === 'CODE' &&
|
!this.state.isLocked && this.state.status === 'CODE' &&
|
||||||
@@ -207,14 +207,14 @@ class MarkdownEditor extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { className, value, config, storageKey } = this.props
|
const { className, value, config, storageKey } = this.props
|
||||||
|
|
||||||
let editorFontSize = parseInt(config.editor.fontSize, 10)
|
let editorFontSize = parseInt(config.editor.fontSize, 10)
|
||||||
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
|
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
|
||||||
let editorIndentSize = parseInt(config.editor.indentSize, 10)
|
let editorIndentSize = parseInt(config.editor.indentSize, 10)
|
||||||
if (!(editorFontSize > 0 && editorFontSize < 132)) editorIndentSize = 4
|
if (!(editorFontSize > 0 && editorFontSize < 132)) editorIndentSize = 4
|
||||||
|
|
||||||
let previewStyle = {}
|
const previewStyle = {}
|
||||||
if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none'
|
if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none'
|
||||||
|
|
||||||
const storage = findStorage(storageKey)
|
const storage = findStorage(storageKey)
|
||||||
|
|||||||
@@ -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 markdown from 'browser/lib/markdown'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
@@ -33,6 +34,15 @@ function buildStyle (fontFamily, fontSize, codeBlockFontFamily, lineNumber) {
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Lato';
|
||||||
|
src: url('${appPath}/resources/fonts/Lato-Black.woff2') format('woff2'), /* Modern Browsers */
|
||||||
|
url('${appPath}/resources/fonts/Lato-Black.woff') format('woff'), /* Modern Browsers */
|
||||||
|
url('${appPath}/resources/fonts/Lato-Black.ttf') format('truetype');
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 700;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
}
|
||||||
${markdownStyle}
|
${markdownStyle}
|
||||||
body {
|
body {
|
||||||
font-family: '${fontFamily.join("','")}';
|
font-family: '${fontFamily.join("','")}';
|
||||||
@@ -117,10 +127,10 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
|
||||||
let anchor = e.target.closest('a')
|
const anchor = e.target.closest('a')
|
||||||
let href = anchor.getAttribute('href')
|
const href = anchor.getAttribute('href')
|
||||||
if (_.isString(href) && href.match(/^#/)) {
|
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) {
|
if (targetElement != null) {
|
||||||
this.getWindow().scrollTo(0, targetElement.offsetTop)
|
this.getWindow().scrollTo(0, targetElement.offsetTop)
|
||||||
}
|
}
|
||||||
@@ -242,7 +252,8 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
applyStyle () {
|
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 = _.isString(fontFamily) && fontFamily.trim().length > 0
|
||||||
? [fontFamily].concat(defaultFontFamily)
|
? [fontFamily].concat(defaultFontFamily)
|
||||||
: defaultFontFamily
|
: defaultFontFamily
|
||||||
@@ -258,7 +269,9 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
theme = consts.THEMES.some((_theme) => _theme === theme) && theme !== 'default'
|
theme = consts.THEMES.some((_theme) => _theme === theme) && theme !== 'default'
|
||||||
? theme
|
? theme
|
||||||
: 'elegant'
|
: 'elegant'
|
||||||
this.getWindow().document.getElementById('codeTheme').href = `${appPath}/node_modules/codemirror/theme/${theme.split(' ')[0]}.css`
|
this.getWindow().document.getElementById('codeTheme').href = theme.startsWith('solarized')
|
||||||
|
? `${appPath}/node_modules/codemirror/theme/solarized.css`
|
||||||
|
: `${appPath}/node_modules/codemirror/theme/${theme}.css`
|
||||||
}
|
}
|
||||||
|
|
||||||
rewriteIframe () {
|
rewriteIframe () {
|
||||||
@@ -273,7 +286,8 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
el.removeEventListener('click', this.linkClickHandler)
|
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)
|
this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme)
|
||||||
|
|
||||||
@@ -316,7 +330,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
let syntax = CodeMirror.findModeByName(el.className)
|
let syntax = CodeMirror.findModeByName(el.className)
|
||||||
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
||||||
CodeMirror.requireMode(syntax.mode, () => {
|
CodeMirror.requireMode(syntax.mode, () => {
|
||||||
let content = htmlTextHelper.decodeEntities(el.innerHTML)
|
const content = htmlTextHelper.decodeEntities(el.innerHTML)
|
||||||
const copyIcon = document.createElement('i')
|
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.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) => {
|
copyIcon.onclick = (e) => {
|
||||||
@@ -341,7 +355,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
let opts = {}
|
const opts = {}
|
||||||
// if (this.props.theme === 'dark') {
|
// if (this.props.theme === 'dark') {
|
||||||
// opts['font-color'] = '#DDD'
|
// opts['font-color'] = '#DDD'
|
||||||
// opts['line-color'] = '#DDD'
|
// opts['line-color'] = '#DDD'
|
||||||
@@ -351,7 +365,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.flowchart'), (el) => {
|
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.flowchart'), (el) => {
|
||||||
Raphael.setWindow(this.getWindow())
|
Raphael.setWindow(this.getWindow())
|
||||||
try {
|
try {
|
||||||
let diagram = flowchart.parse(htmlTextHelper.decodeEntities(el.innerHTML))
|
const diagram = flowchart.parse(htmlTextHelper.decodeEntities(el.innerHTML))
|
||||||
el.innerHTML = ''
|
el.innerHTML = ''
|
||||||
diagram.drawSVG(el, opts)
|
diagram.drawSVG(el, opts)
|
||||||
_.forEach(el.querySelectorAll('a'), (el) => {
|
_.forEach(el.querySelectorAll('a'), (el) => {
|
||||||
@@ -367,7 +381,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.sequence'), (el) => {
|
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.sequence'), (el) => {
|
||||||
Raphael.setWindow(this.getWindow())
|
Raphael.setWindow(this.getWindow())
|
||||||
try {
|
try {
|
||||||
let diagram = SequenceDiagram.parse(htmlTextHelper.decodeEntities(el.innerHTML))
|
const diagram = SequenceDiagram.parse(htmlTextHelper.decodeEntities(el.innerHTML))
|
||||||
el.innerHTML = ''
|
el.innerHTML = ''
|
||||||
diagram.drawSVG(el, {theme: 'simple'})
|
diagram.drawSVG(el, {theme: 'simple'})
|
||||||
_.forEach(el.querySelectorAll('a'), (el) => {
|
_.forEach(el.querySelectorAll('a'), (el) => {
|
||||||
@@ -390,11 +404,11 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scrollTo (targetRow) {
|
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++) {
|
for (let index = 0; index < blocks.length; index++) {
|
||||||
let block = blocks[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) {
|
if (row > targetRow || index === blocks.length - 1) {
|
||||||
block = blocks[index - 1]
|
block = blocks[index - 1]
|
||||||
block != null && this.getWindow().scrollTo(0, block.offsetTop)
|
block != null && this.getWindow().scrollTo(0, block.offsetTop)
|
||||||
@@ -424,7 +438,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { className, style, tabIndex } = this.props
|
const { className, style, tabIndex } = this.props
|
||||||
return (
|
return (
|
||||||
<iframe className={className != null
|
<iframe className={className != null
|
||||||
? 'MarkdownPreview ' + className
|
? 'MarkdownPreview ' + className
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './ModalEscButton.styl'
|
import styles from './ModalEscButton.styl'
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @fileoverview Micro component for toggle SideNav
|
* @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 styles from './NavToggleButton.styl'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
line-height 32px
|
line-height 32px
|
||||||
padding 0
|
padding 0
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
navWhiteButtonColor()
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.navToggle
|
.navToggle
|
||||||
&:hover
|
&:hover
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @fileoverview Note item component.
|
* @fileoverview Note item component.
|
||||||
*/
|
*/
|
||||||
import React, { PropTypes } from 'react'
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
import { isArray } from 'lodash'
|
import { isArray } from 'lodash'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import { getTodoStatus } from 'browser/lib/getTodoStatus'
|
import { getTodoStatus } from 'browser/lib/getTodoStatus'
|
||||||
@@ -70,7 +71,7 @@ const NoteItem = ({ isActive, note, dateDisplay, handleNoteClick, handleNoteCont
|
|||||||
|
|
||||||
<div styleName='item-bottom-time'>{dateDisplay}</div>
|
<div styleName='item-bottom-time'>{dateDisplay}</div>
|
||||||
{note.isStarred
|
{note.isStarred
|
||||||
? <i styleName='item-star' className='fa fa-star' /> : ''
|
? <img styleName='item-star' src='../resources/icon/icon-starred.svg' /> : ''
|
||||||
}
|
}
|
||||||
{note.isPinned && !pathname.match(/\/home|\/starred|\/trash/)
|
{note.isPinned && !pathname.match(/\/home|\/starred|\/trash/)
|
||||||
? <i styleName='item-pin' className='fa fa-thumb-tack' /> : ''
|
? <i styleName='item-pin' className='fa fa-thumb-tack' /> : ''
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ $control-height = 30px
|
|||||||
user-select none
|
user-select none
|
||||||
cursor pointer
|
cursor pointer
|
||||||
background-color $ui-noteList-backgroundColor
|
background-color $ui-noteList-backgroundColor
|
||||||
transition background-color 0.2s
|
transition 0.2s
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-button--active-backgroundColor, 40%)
|
background-color alpha($ui-button--active-backgroundColor, 20%)
|
||||||
.item-title
|
.item-title
|
||||||
.item-title-icon
|
.item-title-icon
|
||||||
.item-bottom-time
|
.item-bottom-time
|
||||||
@@ -25,7 +25,7 @@ $control-height = 30px
|
|||||||
.item-star
|
.item-star
|
||||||
color $ui-favorite-star-button-color
|
color $ui-favorite-star-button-color
|
||||||
&:active
|
&:active
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color alpha($ui-button--active-backgroundColor, 40%)
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
.item-title
|
.item-title
|
||||||
.item-title-icon
|
.item-title-icon
|
||||||
@@ -43,7 +43,7 @@ $control-height = 30px
|
|||||||
|
|
||||||
.item--active
|
.item--active
|
||||||
@extend .item
|
@extend .item
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color alpha($ui-button--active-backgroundColor, 60%)
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
.item-title
|
.item-title
|
||||||
.item-title-empty
|
.item-title-empty
|
||||||
@@ -59,12 +59,12 @@ $control-height = 30px
|
|||||||
.item-star
|
.item-star
|
||||||
color $ui-favorite-star-button-color
|
color $ui-favorite-star-button-color
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-button--active-backgroundColor, 50%)
|
background-color alpha($ui-button--active-backgroundColor, 40%)
|
||||||
color #e74c3c
|
color #e74c3c
|
||||||
.menu-button-label
|
.menu-button-label
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
&:active, &:active:hover
|
&:active, &:active:hover
|
||||||
background-color alpha($ui-button--active-backgroundColor, 50%)
|
background-color alpha($ui-button--active-backgroundColor, 40%)
|
||||||
color #e74c3c
|
color #e74c3c
|
||||||
.menu-button-label
|
.menu-button-label
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
@@ -73,14 +73,16 @@ $control-height = 30px
|
|||||||
position relative
|
position relative
|
||||||
font-size 12px
|
font-size 12px
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
|
top 2px
|
||||||
|
|
||||||
.item-title
|
.item-title
|
||||||
font-size 14px
|
font-size 15px
|
||||||
|
font-weight 700
|
||||||
position relative
|
position relative
|
||||||
top -12px
|
top -12px
|
||||||
left 20px
|
left 20px
|
||||||
padding-right 15px
|
padding 0px 15px 0px 0px
|
||||||
padding-bottom 4px
|
margin-bottom 4px
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
@@ -91,7 +93,7 @@ $control-height = 30px
|
|||||||
.item-bottom
|
.item-bottom
|
||||||
position relative
|
position relative
|
||||||
bottom 0px
|
bottom 0px
|
||||||
margin-top 2px
|
margin-top 10px
|
||||||
font-size 12px
|
font-size 12px
|
||||||
line-height 20px
|
line-height 20px
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
@@ -100,19 +102,17 @@ $control-height = 30px
|
|||||||
.item-bottom-tagList
|
.item-bottom-tagList
|
||||||
flex 1
|
flex 1
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
line-height 20px
|
line-height 25px
|
||||||
padding-top 7px
|
|
||||||
padding-left 2px
|
padding-left 2px
|
||||||
margin-right 27px
|
margin-right 40px
|
||||||
|
|
||||||
.item-bottom-tagList-item
|
.item-bottom-tagList-item
|
||||||
font-size 11px
|
font-size 11px
|
||||||
margin-right 8px
|
margin-right 8px
|
||||||
padding 0
|
padding 0
|
||||||
height 20px
|
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
padding 1px 2px
|
padding 4px
|
||||||
vertical-align middle
|
vertical-align middle
|
||||||
background-color white
|
background-color white
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
@@ -125,10 +125,10 @@ $control-height = 30px
|
|||||||
|
|
||||||
.item-star
|
.item-star
|
||||||
position absolute
|
position absolute
|
||||||
right -20px
|
right -6px
|
||||||
bottom 2px
|
bottom 23px
|
||||||
width 34px
|
width 16px
|
||||||
height 34px
|
height 16px
|
||||||
color alpha($ui-favorite-star-button-color, 60%)
|
color alpha($ui-favorite-star-button-color, 60%)
|
||||||
font-size 12px
|
font-size 12px
|
||||||
padding 0
|
padding 0
|
||||||
@@ -136,8 +136,8 @@ $control-height = 30px
|
|||||||
|
|
||||||
.item-pin
|
.item-pin
|
||||||
position absolute
|
position absolute
|
||||||
right -21px
|
right 0px
|
||||||
bottom 28px
|
bottom 2px
|
||||||
width 34px
|
width 34px
|
||||||
height 34px
|
height 34px
|
||||||
color #E54D42
|
color #E54D42
|
||||||
@@ -145,6 +145,20 @@ $control-height = 30px
|
|||||||
padding 0
|
padding 0
|
||||||
border-radius 17px
|
border-radius 17px
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.item
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 60%)
|
||||||
|
&:active
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
|
||||||
|
.item--active
|
||||||
|
@extend .item
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 60%)
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
@@ -196,7 +210,7 @@ body[data-theme="dark"]
|
|||||||
background-color alpha(white, 10%)
|
background-color alpha(white, 10%)
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
background-color alpha($ui-dark-button--active-backgroundColor, 60%)
|
||||||
color #c0392b
|
color #c0392b
|
||||||
.item-bottom-tagList-item
|
.item-bottom-tagList-item
|
||||||
background-color alpha(#fff, 20%)
|
background-color alpha(#fff, 20%)
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @fileoverview Note item component with simple display mode.
|
* @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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './NoteItemSimple.styl'
|
import styles from './NoteItemSimple.styl'
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,15 @@ $control-height = 30px
|
|||||||
user-select none
|
user-select none
|
||||||
cursor pointer
|
cursor pointer
|
||||||
background-color $ui-noteList-backgroundColor
|
background-color $ui-noteList-backgroundColor
|
||||||
transition background-color 0.15s
|
transition 0.2s
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-button--active-backgroundColor, 40%)
|
background-color alpha($ui-button--active-backgroundColor, 20%)
|
||||||
.item-simple-title
|
.item-simple-title
|
||||||
.item-simple-title-empty
|
.item-simple-title-empty
|
||||||
.item-simple-title-icon
|
.item-simple-title-icon
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
&:active
|
&:active
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color alpha($ui-button--active-backgroundColor, 40%)
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
.item-simple-title
|
.item-simple-title
|
||||||
.item-simple-title-empty
|
.item-simple-title-empty
|
||||||
@@ -28,7 +28,7 @@ $control-height = 30px
|
|||||||
|
|
||||||
.item-simple--active
|
.item-simple--active
|
||||||
@extend .item-simple
|
@extend .item-simple
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color alpha($ui-button--active-backgroundColor, 60%)
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
.item-simple-title
|
.item-simple-title
|
||||||
.item-simple-title-empty
|
.item-simple-title-empty
|
||||||
@@ -37,12 +37,12 @@ $control-height = 30px
|
|||||||
.item-simple-title-icon
|
.item-simple-title-icon
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-button--active-backgroundColor, 50%)
|
background-color alpha($ui-button--active-backgroundColor, 40%)
|
||||||
color #e74c3c
|
color #e74c3c
|
||||||
.menu-button-label
|
.menu-button-label
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
&:active, &:active:hover
|
&:active, &:active:hover
|
||||||
background-color alpha($ui-button--active-backgroundColor, 50%)
|
background-color alpha($ui-button--active-backgroundColor, 40%)
|
||||||
color #e74c3c
|
color #e74c3c
|
||||||
.menu-button-label
|
.menu-button-label
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
@@ -67,6 +67,20 @@ $control-height = 30px
|
|||||||
font-weight normal
|
font-weight normal
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.item-simple
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 60%)
|
||||||
|
&:active
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
|
||||||
|
.item-simple--active
|
||||||
|
@extend .item-simple
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 60%)
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
@@ -115,7 +129,7 @@ body[data-theme="dark"]
|
|||||||
background-color alpha(white, 10%)
|
background-color alpha(white, 10%)
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
background-color alpha($ui-dark-button--active-backgroundColor, 60%)
|
||||||
color #c0392b
|
color #c0392b
|
||||||
.item-simple-bottom-tagList-item
|
.item-simple-bottom-tagList-item
|
||||||
background-color alpha(#fff, 20%)
|
background-color alpha(#fff, 20%)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { PropTypes } from 'react'
|
import React from 'react'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './RealtimeNotification.styl'
|
import styles from './RealtimeNotification.styl'
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @fileoverview Filter for all notes.
|
* @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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './SideNavFilter.styl'
|
import styles from './SideNavFilter.styl'
|
||||||
|
|
||||||
@@ -15,27 +16,53 @@ import styles from './SideNavFilter.styl'
|
|||||||
*/
|
*/
|
||||||
const SideNavFilter = ({
|
const SideNavFilter = ({
|
||||||
isFolded, isHomeActive, handleAllNotesButtonClick,
|
isFolded, isHomeActive, handleAllNotesButtonClick,
|
||||||
isStarredActive, handleStarredButtonClick, isTrashedActive, handleTrashedButtonClick
|
isStarredActive, handleStarredButtonClick, isTrashedActive, handleTrashedButtonClick, counterDelNote,
|
||||||
|
counterTotalNote, counterStarredNote
|
||||||
}) => (
|
}) => (
|
||||||
<div styleName={isFolded ? 'menu--folded' : 'menu'}>
|
<div styleName={isFolded ? 'menu--folded' : 'menu'}>
|
||||||
|
|
||||||
<button styleName={isHomeActive ? 'menu-button--active' : 'menu-button'}
|
<button styleName={isHomeActive ? 'menu-button--active' : 'menu-button'}
|
||||||
onClick={handleAllNotesButtonClick}
|
onClick={handleAllNotesButtonClick}
|
||||||
>
|
>
|
||||||
<i className='fa fa-archive fa-fw' />
|
<div styleName='iconWrap'>
|
||||||
|
<img src={isHomeActive
|
||||||
|
? '../resources/icon/icon-all-active.svg'
|
||||||
|
: '../resources/icon/icon-all.svg'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<span styleName='menu-button-label'>All Notes</span>
|
<span styleName='menu-button-label'>All Notes</span>
|
||||||
|
<span styleName='counters'>{counterTotalNote}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button styleName={isStarredActive ? 'menu-button-star--active' : 'menu-button'}
|
<button styleName={isStarredActive ? 'menu-button-star--active' : 'menu-button'}
|
||||||
onClick={handleStarredButtonClick}
|
onClick={handleStarredButtonClick}
|
||||||
>
|
>
|
||||||
<i className='fa fa-star fa-fw' />
|
<div styleName='iconWrap'>
|
||||||
|
<img src={isStarredActive
|
||||||
|
? '../resources/icon/icon-star-active.svg'
|
||||||
|
: '../resources/icon/icon-star.svg'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<span styleName='menu-button-label'>Starred</span>
|
<span styleName='menu-button-label'>Starred</span>
|
||||||
|
<span styleName='counters'>{counterStarredNote}</span>
|
||||||
</button>
|
</button>
|
||||||
<button styleName={isTrashedActive ? 'menu-button--active' : 'menu-button'}
|
|
||||||
|
<button styleName={isTrashedActive ? 'menu-button-trash--active' : 'menu-button'}
|
||||||
onClick={handleTrashedButtonClick}
|
onClick={handleTrashedButtonClick}
|
||||||
>
|
>
|
||||||
<i className='fa fa-trash fa-fw' />
|
<div styleName='iconWrap'>
|
||||||
|
<img src={isTrashedActive
|
||||||
|
? '../resources/icon/icon-trash-active.svg'
|
||||||
|
: '../resources/icon/icon-trash.svg'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<span styleName='menu-button-label'>Trash</span>
|
<span styleName='menu-button-label'>Trash</span>
|
||||||
|
<span styleName='counters'>{counterDelNote}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,92 @@
|
|||||||
|
|
||||||
.menu-button
|
.menu-button
|
||||||
navButtonColor()
|
navButtonColor()
|
||||||
height 32px
|
height 36px
|
||||||
padding 0 15px
|
padding 0 15px 0 20px
|
||||||
font-size 13px
|
font-size 14px
|
||||||
width 100%
|
width 100%
|
||||||
text-align left
|
text-align left
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
&:hover, &:active, &:active:hover
|
||||||
|
color #1EC38B
|
||||||
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
|
|
||||||
|
.iconWrap
|
||||||
|
width 20px
|
||||||
|
text-align center
|
||||||
|
|
||||||
|
.counters
|
||||||
|
float right
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.menu-button--active
|
||||||
|
@extend .menu-button
|
||||||
|
SideNavFilter()
|
||||||
|
color #1EC38B
|
||||||
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
|
.menu-button-label, .counters
|
||||||
|
color #1EC38B
|
||||||
|
&:hover
|
||||||
|
color #1EC38B
|
||||||
|
|
||||||
|
.menu-button-star--active
|
||||||
|
@extend .menu-button
|
||||||
|
SideNavFilter()
|
||||||
|
color #1EC38B
|
||||||
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
|
.menu-button-label, .counters
|
||||||
|
color #1EC38B
|
||||||
|
|
||||||
|
.menu-button-trash--active
|
||||||
|
@extend .menu-button
|
||||||
|
SideNavFilter()
|
||||||
|
color #1EC38B
|
||||||
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
|
.menu-button-label, .counters
|
||||||
|
color #1EC38B
|
||||||
|
|
||||||
|
.menu-button-label
|
||||||
|
margin-left 10px
|
||||||
|
flex 1
|
||||||
|
|
||||||
|
.menu--folded
|
||||||
|
@extend .menu
|
||||||
|
.menu-button, .menu-button--active
|
||||||
|
text-align center
|
||||||
|
&: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
|
||||||
|
display inline-block
|
||||||
|
height 32px
|
||||||
|
left 44px
|
||||||
|
padding 0 10px
|
||||||
|
margin-top -8px
|
||||||
|
margin-left 0
|
||||||
|
overflow ellipsis
|
||||||
|
z-index 10
|
||||||
|
line-height 32px
|
||||||
|
border-top-right-radius 2px
|
||||||
|
border-bottom-right-radius 2px
|
||||||
|
pointer-events none
|
||||||
|
opacity 0
|
||||||
|
font-size 13px
|
||||||
|
.counters
|
||||||
|
display none
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.menu-button
|
||||||
|
navWhiteButtonColor()
|
||||||
|
|
||||||
|
.counters
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
.menu-button--active
|
.menu-button--active
|
||||||
@extend .menu-button
|
@extend .menu-button
|
||||||
@@ -44,34 +124,22 @@
|
|||||||
.menu-button-label
|
.menu-button-label
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
|
|
||||||
|
.menu-button-trash--active
|
||||||
|
@extend .menu-button
|
||||||
|
color #5D9E36
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
.menu-button-label
|
.menu-button-label
|
||||||
margin-left 5px
|
color $ui-text-color
|
||||||
|
&:hover
|
||||||
.menu--folded
|
background-color alpha($ui-button--active-backgroundColor, 50%)
|
||||||
@extend .menu
|
color #5D9E36
|
||||||
.menu-button, .menu-button--active
|
|
||||||
text-align center
|
|
||||||
&:hover .menu-button-label
|
|
||||||
transition opacity 0.15s
|
|
||||||
opacity 1
|
|
||||||
.menu-button-label
|
.menu-button-label
|
||||||
position fixed
|
color $ui-text-color
|
||||||
display inline-block
|
&:active, &:active:hover
|
||||||
height 32px
|
background-color alpha($ui-button--active-backgroundColor, 50%)
|
||||||
left 44px
|
color #5D9E36
|
||||||
padding 0 10px
|
.menu-button-label
|
||||||
margin-top -8px
|
color $ui-text-color
|
||||||
margin-left 0
|
|
||||||
overflow ellipsis
|
|
||||||
background-color $ui-tooltip-backgroundColor
|
|
||||||
z-index 10
|
|
||||||
color white
|
|
||||||
line-height 32px
|
|
||||||
border-top-right-radius 2px
|
|
||||||
border-bottom-right-radius 2px
|
|
||||||
pointer-events none
|
|
||||||
opacity 0
|
|
||||||
font-size 13px
|
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.menu-button
|
.menu-button
|
||||||
@@ -103,3 +171,14 @@ body[data-theme="dark"]
|
|||||||
color $ui-favorite-star-button-color
|
color $ui-favorite-star-button-color
|
||||||
.menu-button-label
|
.menu-button-label
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
.menu-button-trash--active
|
||||||
|
color #5D9E36
|
||||||
|
background-color $ui-dark-button--active-backgroundColor
|
||||||
|
.menu-button-label
|
||||||
|
color $ui-dark-text-color
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
||||||
|
color #5D9E36
|
||||||
|
.menu-button-label
|
||||||
|
color $ui-dark-text-color
|
||||||
@@ -86,7 +86,7 @@ class SnippetTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { isActive, snippet, isDeletable } = this.props
|
const { isActive, snippet, isDeletable } = this.props
|
||||||
return (
|
return (
|
||||||
<div styleName={isActive
|
<div styleName={isActive
|
||||||
? 'root--active'
|
? 'root--active'
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @fileoverview Micro component for showing storage.
|
* @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 styles from './StorageItem.styl'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import { isNumber } from 'lodash'
|
import { isNumber } from 'lodash'
|
||||||
|
|||||||
@@ -5,32 +5,31 @@
|
|||||||
.folderList-item
|
.folderList-item
|
||||||
display flex
|
display flex
|
||||||
width 100%
|
width 100%
|
||||||
height 26px
|
height 34px
|
||||||
background-color transparent
|
background-color transparent
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
padding 0
|
padding 0
|
||||||
margin-bottom 5px
|
|
||||||
text-align left
|
text-align left
|
||||||
border none
|
border none
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
font-size 13px
|
font-size 14px
|
||||||
&:first-child
|
&:first-child
|
||||||
margin-top 0
|
margin-top 0
|
||||||
&:hover
|
&:hover
|
||||||
color $ui-text-color
|
color #1EC38B;
|
||||||
background-color alpha($ui-button--active-backgroundColor, 20%)
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
transition background-color 0.15s
|
transition background-color 0.15s
|
||||||
&:active
|
&:active
|
||||||
color $ui-text-color
|
color $$ui-button-default-color
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
|
|
||||||
.folderList-item--active
|
.folderList-item--active
|
||||||
@extend .folderList-item
|
@extend .folderList-item
|
||||||
color $ui-text-color
|
color #1EC38B
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
&:hover
|
&:hover
|
||||||
color $ui-text-color
|
color #1EC38B;
|
||||||
background-color alpha($ui-button--active-backgroundColor, 50%)
|
background-color alpha($ui-button-default--active-backgroundColor, 50%)
|
||||||
|
|
||||||
.folderList-item-name
|
.folderList-item-name
|
||||||
display block
|
display block
|
||||||
@@ -69,8 +68,28 @@
|
|||||||
|
|
||||||
.folderList-item-name--folded
|
.folderList-item-name--folded
|
||||||
@extend .folderList-item-name
|
@extend .folderList-item-name
|
||||||
padding-left 12px
|
padding-left 17px
|
||||||
|
text
|
||||||
|
display none
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.folderList-item
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
&:hover
|
||||||
|
color $ui-text-color
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 20%)
|
||||||
|
transition background-color 0.15s
|
||||||
|
&:active
|
||||||
|
color $ui-text-color
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
|
||||||
|
.folderList-item--active
|
||||||
|
@extend .folderList-item
|
||||||
|
color $ui-text-color
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
&:hover
|
||||||
|
color $ui-text-color
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 50%)
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.folderList-item
|
.folderList-item
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* @fileoverview Micro component for showing StorageList
|
* @fileoverview Micro component for showing StorageList
|
||||||
*/
|
*/
|
||||||
import React, { PropTypes } from 'react'
|
import PropTypes from 'prop-types'
|
||||||
import styles from './StorgaeList.styl'
|
import React from 'react'
|
||||||
|
import styles from './StorageList.styl'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.storageList
|
.storageList
|
||||||
absolute left right
|
absolute left right
|
||||||
bottom 37px
|
bottom 37px
|
||||||
top 160px
|
top 180px
|
||||||
overflow-y auto
|
overflow-y auto
|
||||||
|
|
||||||
.storageList-empty
|
.storageList-empty
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
/**
|
/**
|
||||||
* @fileoverview Micro component for showing TagList.
|
* @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 styles from './TagListItem.styl'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
|
||||||
|
|||||||
@@ -13,15 +13,15 @@
|
|||||||
&:first-child
|
&:first-child
|
||||||
margin-top 0
|
margin-top 0
|
||||||
&:hover
|
&:hover
|
||||||
color $ui-text-color
|
color $ui-button-default-color
|
||||||
background-color alpha($ui-button--active-backgroundColor, 20%)
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
transition background-color 0.15s
|
transition background-color 0.15s
|
||||||
&:active
|
&:active, &:active:hover
|
||||||
color $ui-text-color
|
color $ui-button-default-color
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color $ui-button-default--active-backgroundColor
|
||||||
|
|
||||||
.tagList-item-active
|
.tagList-item-active
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color $ui-button-default--active-backgroundColor
|
||||||
display flex
|
display flex
|
||||||
width 100%
|
width 100%
|
||||||
height 26px
|
height 26px
|
||||||
@@ -31,8 +31,9 @@
|
|||||||
border none
|
border none
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
font-size 13px
|
font-size 13px
|
||||||
|
color $ui-button-default-color
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-button--active-backgroundColor, 60%)
|
background-color alpha($ui-button-default--active-backgroundColor, 60%)
|
||||||
transition 0.2s
|
transition 0.2s
|
||||||
|
|
||||||
.tagList-item-name
|
.tagList-item-name
|
||||||
@@ -47,6 +48,22 @@
|
|||||||
overflow hidden
|
overflow hidden
|
||||||
text-overflow ellipsis
|
text-overflow ellipsis
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.tagList-item
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
&:hover
|
||||||
|
color $ui-text-color
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 20%)
|
||||||
|
&:active
|
||||||
|
color $ui-text-color
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
|
||||||
|
.tagList-item-active
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
color $ui-text-color
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 60%)
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.tagList-item
|
.tagList-item
|
||||||
color $ui-dark-inactive-text-color
|
color $ui-dark-inactive-text-color
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
* @fileoverview Percentage of todo achievement.
|
* @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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './TodoListPercentage.styl'
|
import styles from './TodoListPercentage.styl'
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
.percentageBar
|
.percentageBar
|
||||||
position absolute
|
position absolute
|
||||||
top 58px
|
top 50px
|
||||||
right: 0px
|
right 0px
|
||||||
left 0px
|
left 0px
|
||||||
background-color #DADFE1
|
background-color #DADFE1
|
||||||
width 100%
|
width 100%
|
||||||
height: 15px
|
height: 17px
|
||||||
font-size: 12px
|
font-size: 12px
|
||||||
z-index 100
|
z-index 100
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
|
|
||||||
.progressBar
|
.progressBar
|
||||||
background-color: #6C7A89
|
background-color: #1EC38B
|
||||||
height 15px
|
height 17px
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
transition 0.3s
|
transition 0.4s cubic-bezier(0.4, 0.4, 0, 1)
|
||||||
|
|
||||||
.percentageText
|
.percentageText
|
||||||
color #f4f4f4
|
color #f4f4f4
|
||||||
padding: 2px 43%
|
padding: 2px 43%
|
||||||
|
font-weight 600
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.percentageBar
|
.percentageBar
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
* @fileoverview Percentage of todo achievement.
|
* @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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './TodoProcess.styl'
|
import styles from './TodoProcess.styl'
|
||||||
|
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ hr
|
|||||||
h1, h2, h3, h4, h5, h6
|
h1, h2, h3, h4, h5, h6
|
||||||
font-weight bold
|
font-weight bold
|
||||||
h1
|
h1
|
||||||
font-size 2.25em
|
font-size 2.55em
|
||||||
padding-bottom 0.3em
|
padding-bottom 0.3em
|
||||||
line-height 1.2em
|
line-height 1.2em
|
||||||
border-bottom solid 1px borderColor
|
border-bottom solid 1px borderColor
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ $list-width = 250px
|
|||||||
|
|
||||||
.result-nav-storageList
|
.result-nav-storageList
|
||||||
absolute bottom left right
|
absolute bottom left right
|
||||||
top 110px + 32px + 10px + 10px
|
top 110px + 32px + 10px + 10px + 20px
|
||||||
overflow-y auto
|
overflow-y auto
|
||||||
|
|
||||||
.result-list
|
.result-list
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ class NoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectPriorSnippet () {
|
selectPriorSnippet () {
|
||||||
let { note } = this.props
|
const { note } = this.props
|
||||||
if (note.type === 'SNIPPET_NOTE' && note.snippets.length > 1) {
|
if (note.type === 'SNIPPET_NOTE' && note.snippets.length > 1) {
|
||||||
this.setState({
|
this.setState({
|
||||||
snippetIndex: (this.state.snippetIndex + note.snippets.length - 1) % note.snippets.length
|
snippetIndex: (this.state.snippetIndex + note.snippets.length - 1) % note.snippets.length
|
||||||
@@ -65,7 +65,7 @@ class NoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectNextSnippet () {
|
selectNextSnippet () {
|
||||||
let { note } = this.props
|
const { note } = this.props
|
||||||
if (note.type === 'SNIPPET_NOTE' && note.snippets.length > 1) {
|
if (note.type === 'SNIPPET_NOTE' && note.snippets.length > 1) {
|
||||||
this.setState({
|
this.setState({
|
||||||
snippetIndex: (this.state.snippetIndex + 1) % note.snippets.length
|
snippetIndex: (this.state.snippetIndex + 1) % note.snippets.length
|
||||||
@@ -74,7 +74,7 @@ class NoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveToClipboard () {
|
saveToClipboard () {
|
||||||
let { note } = this.props
|
const { note } = this.props
|
||||||
|
|
||||||
if (note.type === 'MARKDOWN_NOTE') {
|
if (note.type === 'MARKDOWN_NOTE') {
|
||||||
clipboard.writeText(note.content)
|
clipboard.writeText(note.content)
|
||||||
@@ -95,7 +95,7 @@ class NoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { note, config } = this.props
|
const { note, config } = this.props
|
||||||
if (note == null) {
|
if (note == null) {
|
||||||
return (
|
return (
|
||||||
<div styleName='root' />
|
<div styleName='root' />
|
||||||
@@ -110,8 +110,8 @@ class NoteDetail extends React.Component {
|
|||||||
const storage = findStorage(note.storage)
|
const storage = findStorage(note.storage)
|
||||||
|
|
||||||
if (note.type === 'SNIPPET_NOTE') {
|
if (note.type === 'SNIPPET_NOTE') {
|
||||||
let tabList = note.snippets.map((snippet, index) => {
|
const tabList = note.snippets.map((snippet, index) => {
|
||||||
let isActive = this.state.snippetIndex === index
|
const isActive = this.state.snippetIndex === index
|
||||||
return <div styleName={isActive
|
return <div styleName={isActive
|
||||||
? 'tabList-item--active'
|
? 'tabList-item--active'
|
||||||
: 'tabList-item'
|
: 'tabList-item'
|
||||||
@@ -131,8 +131,8 @@ class NoteDetail extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
})
|
})
|
||||||
|
|
||||||
let viewList = note.snippets.map((snippet, index) => {
|
const viewList = note.snippets.map((snippet, index) => {
|
||||||
let isActive = this.state.snippetIndex === index
|
const isActive = this.state.snippetIndex === index
|
||||||
|
|
||||||
let syntax = CodeMirror.findModeByName(pass(snippet.mode))
|
let syntax = CodeMirror.findModeByName(pass(snippet.mode))
|
||||||
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
||||||
|
|||||||
@@ -18,18 +18,18 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate () {
|
componentDidUpdate () {
|
||||||
let { index } = this.props
|
const { index } = this.props
|
||||||
|
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
let list = this.refs.root
|
const list = this.refs.root
|
||||||
let item = list.childNodes[index]
|
const item = list.childNodes[index]
|
||||||
if (item == null) return null
|
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) {
|
if (overflowBelow) {
|
||||||
list.scrollTop = item.offsetTop + item.clientHeight - list.clientHeight
|
list.scrollTop = item.offsetTop + item.clientHeight - list.clientHeight
|
||||||
}
|
}
|
||||||
let overflowAbove = list.scrollTop > item.offsetTop
|
const overflowAbove = list.scrollTop > item.offsetTop
|
||||||
if (overflowAbove) {
|
if (overflowAbove) {
|
||||||
list.scrollTop = item.offsetTop
|
list.scrollTop = item.offsetTop
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleScroll (e) {
|
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) {
|
if (e.target.offsetHeight + e.target.scrollTop > e.target.scrollHeight - 100 && notes.length > this.state.range * 10 + 10) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -54,9 +54,9 @@ class NoteList extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { notes, index } = this.props
|
const { notes, index } = this.props
|
||||||
|
|
||||||
let notesList = notes
|
const notesList = notes
|
||||||
.slice(0, 10 + 10 * this.state.range)
|
.slice(0, 10 + 10 * this.state.range)
|
||||||
.map((note, _index) => {
|
.map((note, _index) => {
|
||||||
const isActive = (index === _index)
|
const isActive = (index === _index)
|
||||||
|
|||||||
@@ -19,18 +19,18 @@ class StorageSection extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleHeaderClick (e) {
|
handleHeaderClick (e) {
|
||||||
let { storage } = this.props
|
const { storage } = this.props
|
||||||
this.props.handleStorageButtonClick(e, storage.key)
|
this.props.handleStorageButtonClick(e, storage.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFolderClick (e, folder) {
|
handleFolderClick (e, folder) {
|
||||||
let { storage } = this.props
|
const { storage } = this.props
|
||||||
this.props.handleFolderButtonClick(e, storage.key, folder.key)
|
this.props.handleFolderButtonClick(e, storage.key, folder.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { storage, filter } = this.props
|
const { storage, filter } = this.props
|
||||||
let folderList = storage.folders
|
const folderList = storage.folders
|
||||||
.map(folder => (
|
.map(folder => (
|
||||||
<StorageItem
|
<StorageItem
|
||||||
key={folder.key}
|
key={folder.key}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import React, { PropTypes } from 'react'
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { connect, Provider } from 'react-redux'
|
import { connect, Provider } from 'react-redux'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import ipc from './ipcClient'
|
|
||||||
import store from './store'
|
import store from './store'
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './FinderMain.styl'
|
import styles from './FinderMain.styl'
|
||||||
@@ -19,7 +19,7 @@ const { remote } = electron
|
|||||||
const { Menu } = remote
|
const { Menu } = remote
|
||||||
|
|
||||||
function hideFinder () {
|
function hideFinder () {
|
||||||
let finderWindow = remote.getCurrentWindow()
|
const finderWindow = remote.getCurrentWindow()
|
||||||
if (global.process.platform === 'win32') {
|
if (global.process.platform === 'win32') {
|
||||||
finderWindow.blur()
|
finderWindow.blur()
|
||||||
finderWindow.hide()
|
finderWindow.hide()
|
||||||
@@ -136,7 +136,7 @@ class FinderMain extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleOnlySnippetCheckboxChange (e) {
|
handleOnlySnippetCheckboxChange (e) {
|
||||||
let { filter } = this.state
|
const { filter } = this.state
|
||||||
filter.includeSnippet = e.target.checked
|
filter.includeSnippet = e.target.checked
|
||||||
this.setState({
|
this.setState({
|
||||||
filter: filter,
|
filter: filter,
|
||||||
@@ -147,7 +147,7 @@ class FinderMain extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleOnlyMarkdownCheckboxChange (e) {
|
handleOnlyMarkdownCheckboxChange (e) {
|
||||||
let { filter } = this.state
|
const { filter } = this.state
|
||||||
filter.includeMarkdown = e.target.checked
|
filter.includeMarkdown = e.target.checked
|
||||||
this.refs.list.resetScroll()
|
this.refs.list.resetScroll()
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -159,7 +159,7 @@ class FinderMain extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleAllNotesButtonClick (e) {
|
handleAllNotesButtonClick (e) {
|
||||||
let { filter } = this.state
|
const { filter } = this.state
|
||||||
filter.type = 'ALL'
|
filter.type = 'ALL'
|
||||||
this.refs.list.resetScroll()
|
this.refs.list.resetScroll()
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -171,7 +171,7 @@ class FinderMain extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleStarredButtonClick (e) {
|
handleStarredButtonClick (e) {
|
||||||
let { filter } = this.state
|
const { filter } = this.state
|
||||||
filter.type = 'STARRED'
|
filter.type = 'STARRED'
|
||||||
this.refs.list.resetScroll()
|
this.refs.list.resetScroll()
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -183,7 +183,7 @@ class FinderMain extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleStorageButtonClick (e, storage) {
|
handleStorageButtonClick (e, storage) {
|
||||||
let { filter } = this.state
|
const { filter } = this.state
|
||||||
filter.type = 'STORAGE'
|
filter.type = 'STORAGE'
|
||||||
filter.storage = storage
|
filter.storage = storage
|
||||||
this.refs.list.resetScroll()
|
this.refs.list.resetScroll()
|
||||||
@@ -196,7 +196,7 @@ class FinderMain extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleFolderButtonClick (e, storage, folder) {
|
handleFolderButtonClick (e, storage, folder) {
|
||||||
let { filter } = this.state
|
const { filter } = this.state
|
||||||
filter.type = 'FOLDER'
|
filter.type = 'FOLDER'
|
||||||
filter.storage = storage
|
filter.storage = storage
|
||||||
filter.folder = folder
|
filter.folder = folder
|
||||||
@@ -218,12 +218,12 @@ class FinderMain extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { data, config } = this.props
|
const { data, config } = this.props
|
||||||
let { filter, search } = this.state
|
const { filter, search } = this.state
|
||||||
let storageList = []
|
const storageList = []
|
||||||
for (let key in data.storageMap) {
|
for (const key in data.storageMap) {
|
||||||
let storage = data.storageMap[key]
|
const storage = data.storageMap[key]
|
||||||
let item = (
|
const item = (
|
||||||
<StorageSection
|
<StorageSection
|
||||||
filter={filter}
|
filter={filter}
|
||||||
storage={storage}
|
storage={storage}
|
||||||
@@ -252,7 +252,7 @@ class FinderMain extends React.Component {
|
|||||||
notes.push(data.noteMap[id])
|
notes.push(data.noteMap[id])
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
for (let key in data.noteMap) {
|
for (const key in data.noteMap) {
|
||||||
notes.push(data.noteMap[key])
|
notes.push(data.noteMap[key])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,13 +264,13 @@ class FinderMain extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (search.trim().length > 0) {
|
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.filter((note) => note.title.match(needle))
|
||||||
}
|
}
|
||||||
notes = notes
|
notes = notes
|
||||||
.sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt))
|
.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
|
this.noteCount = notes.length
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ nodeIpc.config.retry = 1500
|
|||||||
nodeIpc.config.silent = true
|
nodeIpc.config.silent = true
|
||||||
|
|
||||||
function killFinder () {
|
function killFinder () {
|
||||||
let finderWindow = remote.getCurrentWindow()
|
const finderWindow = remote.getCurrentWindow()
|
||||||
finderWindow.removeAllListeners()
|
finderWindow.removeAllListeners()
|
||||||
if (global.process.platform === 'darwin') {
|
if (global.process.platform === 'darwin') {
|
||||||
// Only OSX has another app process.
|
// Only OSX has another app process.
|
||||||
@@ -21,7 +21,7 @@ function killFinder () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function toggleFinder () {
|
function toggleFinder () {
|
||||||
let finderWindow = remote.getCurrentWindow()
|
const finderWindow = remote.getCurrentWindow()
|
||||||
if (global.process.platform === 'darwin') {
|
if (global.process.platform === 'darwin') {
|
||||||
if (finderWindow.isVisible()) {
|
if (finderWindow.isVisible()) {
|
||||||
finderWindow.hide()
|
finderWindow.hide()
|
||||||
@@ -84,6 +84,8 @@ nodeIpc.connectTo(
|
|||||||
const { config } = payload
|
const { config } = payload
|
||||||
if (config.ui.theme === 'dark') {
|
if (config.ui.theme === 'dark') {
|
||||||
document.body.setAttribute('data-theme', 'dark')
|
document.body.setAttribute('data-theme', 'dark')
|
||||||
|
} else if (config.ui.theme === 'white') {
|
||||||
|
document.body.setAttribute('data-theme', 'white')
|
||||||
} else {
|
} else {
|
||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { combineReducers, createStore } from 'redux'
|
|||||||
import { routerReducer } from 'react-router-redux'
|
import { routerReducer } from 'react-router-redux'
|
||||||
import { DEFAULT_CONFIG } from 'browser/main/lib/ConfigManager'
|
import { DEFAULT_CONFIG } from 'browser/main/lib/ConfigManager'
|
||||||
|
|
||||||
let defaultData = {
|
const defaultData = {
|
||||||
storageMap: {},
|
storageMap: {},
|
||||||
noteMap: {},
|
noteMap: {},
|
||||||
starredSet: [],
|
starredSet: [],
|
||||||
@@ -40,12 +40,12 @@ function config (state = DEFAULT_CONFIG, action) {
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
let reducer = combineReducers({
|
const reducer = combineReducers({
|
||||||
data,
|
data,
|
||||||
config,
|
config,
|
||||||
routing: routerReducer
|
routing: routerReducer
|
||||||
})
|
})
|
||||||
|
|
||||||
let store = createStore(reducer)
|
const store = createStore(reducer)
|
||||||
|
|
||||||
export default store
|
export default store
|
||||||
|
|||||||
@@ -38,15 +38,15 @@ class MutableMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
map (cb) {
|
map (cb) {
|
||||||
let result = []
|
const result = []
|
||||||
for (let [key, value] of this._map) {
|
for (const [key, value] of this._map) {
|
||||||
result.push(cb(value, key))
|
result.push(cb(value, key))
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
toJS () {
|
toJS () {
|
||||||
let result = {}
|
const result = {}
|
||||||
for (let [key, value] of this._map) {
|
for (let [key, value] of this._map) {
|
||||||
if (value instanceof MutableSet || value instanceof MutableMap) {
|
if (value instanceof MutableSet || value instanceof MutableMap) {
|
||||||
value = value.toJS()
|
value = value.toJS()
|
||||||
@@ -85,7 +85,7 @@ class MutableSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
map (cb) {
|
map (cb) {
|
||||||
let result = []
|
const result = []
|
||||||
this._set.forEach(function (value, key) {
|
this._set.forEach(function (value, key) {
|
||||||
result.push(cb(value, key))
|
result.push(cb(value, key))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
export function findNoteTitle (value) {
|
export function findNoteTitle (value) {
|
||||||
let splitted = value.split('\n')
|
const splitted = value.split('\n')
|
||||||
let title = null
|
let title = null
|
||||||
let isInsideCodeBlock = false
|
let isInsideCodeBlock = false
|
||||||
|
|
||||||
splitted.some((line, index) => {
|
splitted.some((line, index) => {
|
||||||
let trimmedLine = line.trim()
|
const trimmedLine = line.trim()
|
||||||
let trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
|
const trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
|
||||||
if (trimmedLine.match('```')) {
|
if (trimmedLine.match('```')) {
|
||||||
isInsideCodeBlock = !isInsideCodeBlock
|
isInsideCodeBlock = !isInsideCodeBlock
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
export function getTodoStatus (content) {
|
export function getTodoStatus (content) {
|
||||||
let splitted = content.split('\n')
|
const splitted = content.split('\n')
|
||||||
let numberOfTodo = 0
|
let numberOfTodo = 0
|
||||||
let numberOfCompletedTodo = 0
|
let numberOfCompletedTodo = 0
|
||||||
|
|
||||||
splitted.forEach((line) => {
|
splitted.forEach((line) => {
|
||||||
let trimmedLine = line.trim()
|
const trimmedLine = line.trim()
|
||||||
if (trimmedLine.match(/^[\+\-\*] \[\s|x\] ./)) {
|
if (trimmedLine.match(/^[\+\-\*] \[\s|x\] ./)) {
|
||||||
numberOfTodo++
|
numberOfTodo++
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import emoji from 'markdown-it-emoji'
|
|||||||
import math from '@rokt33r/markdown-it-math'
|
import math from '@rokt33r/markdown-it-math'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
|
// FIXME We should not depend on global variable.
|
||||||
const katex = window.katex
|
const katex = window.katex
|
||||||
|
|
||||||
function createGutter (str) {
|
function createGutter (str) {
|
||||||
let lc = (str.match(/\n/g) || []).length
|
const lc = (str.match(/\n/g) || []).length
|
||||||
let lines = []
|
const lines = []
|
||||||
for (let i = 1; i <= lc; i++) {
|
for (let i = 1; i <= lc; i++) {
|
||||||
lines.push('<span class="CodeMirror-linenumber">' + i + '</span>')
|
lines.push('<span class="CodeMirror-linenumber">' + i + '</span>')
|
||||||
}
|
}
|
||||||
@@ -75,8 +76,8 @@ md.use(require('markdown-it-plantuml'))
|
|||||||
md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
|
md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
|
||||||
let content, terminate, i, l, token
|
let content, terminate, i, l, token
|
||||||
let nextLine = startLine + 1
|
let nextLine = startLine + 1
|
||||||
let terminatorRules = state.md.block.ruler.getRules('paragraph')
|
const terminatorRules = state.md.block.ruler.getRules('paragraph')
|
||||||
let endLine = state.lineMax
|
const endLine = state.lineMax
|
||||||
|
|
||||||
// jump line-by-line until empty one or EOF
|
// jump line-by-line until empty one or EOF
|
||||||
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
||||||
@@ -106,7 +107,7 @@ md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
|
|||||||
token.map = [ startLine, state.line ]
|
token.map = [ startLine, state.line ]
|
||||||
|
|
||||||
if (state.parentType === 'list') {
|
if (state.parentType === 'list') {
|
||||||
let match = content.match(/^\[( |x)\] ?(.+)/i)
|
const match = content.match(/^\[( |x)\] ?(.+)/i)
|
||||||
if (match) {
|
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>`
|
content = `<label class='taskListItem' for='checkbox-${startLine + 1}'><input type='checkbox'${match[1] !== ' ' ? ' checked' : ''} id='checkbox-${startLine + 1}'/> ${content.substring(4, content.length)}</label>`
|
||||||
}
|
}
|
||||||
@@ -123,7 +124,7 @@ md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Add line number attribute for scrolling
|
// Add line number attribute for scrolling
|
||||||
let originalRender = md.renderer.render
|
const originalRender = md.renderer.render
|
||||||
md.renderer.render = function render (tokens, options, env) {
|
md.renderer.render = function render (tokens, options, env) {
|
||||||
tokens.forEach((token) => {
|
tokens.forEach((token) => {
|
||||||
switch (token.type) {
|
switch (token.type) {
|
||||||
@@ -134,40 +135,12 @@ md.renderer.render = function render (tokens, options, env) {
|
|||||||
token.attrPush(['data-line', token.map[0]])
|
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
|
return result
|
||||||
}
|
}
|
||||||
|
// FIXME We should not depend on global variable.
|
||||||
window.md = md
|
window.md = md
|
||||||
|
|
||||||
function strip (input) {
|
|
||||||
var output = input
|
|
||||||
try {
|
|
||||||
output = output
|
|
||||||
.replace(/^([\s\t]*)([\*\-\+]|\d\.)\s+/gm, '$1')
|
|
||||||
.replace(/\n={2,}/g, '\n')
|
|
||||||
.replace(/~~/g, '')
|
|
||||||
.replace(/`{3}.*\n/g, '')
|
|
||||||
.replace(/<(.*?)>/g, '$1')
|
|
||||||
.replace(/^[=\-]{2,}\s*$/g, '')
|
|
||||||
.replace(/\[\^.+?\](: .*?$)?/g, '')
|
|
||||||
.replace(/\s{0,2}\[.*?\]: .*?$/g, '')
|
|
||||||
.replace(/!\[.*?\][\[\(].*?[\]\)]/g, '')
|
|
||||||
.replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1')
|
|
||||||
.replace(/>/g, '')
|
|
||||||
.replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '')
|
|
||||||
.replace(/^#{1,6}\s*([^#]*)\s*(#{1,6})?/gm, '$1')
|
|
||||||
.replace(/([\*_]{1,3})(\S.*?\S)\1/g, '$2')
|
|
||||||
.replace(/(`{3,})(.*?)\1/gm, '$2')
|
|
||||||
.replace(/^-{3,}\s*$/g, '')
|
|
||||||
.replace(/`(.+?)`/g, '$1')
|
|
||||||
.replace(/\n{2,}/g, '\n\n')
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
return input
|
|
||||||
}
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeLinkText (linkText) {
|
function normalizeLinkText (linkText) {
|
||||||
return md.normalizeLinkText(linkText)
|
return md.normalizeLinkText(linkText)
|
||||||
}
|
}
|
||||||
@@ -178,7 +151,7 @@ const markdown = {
|
|||||||
const renderedContent = md.render(content)
|
const renderedContent = md.render(content)
|
||||||
return renderedContent
|
return renderedContent
|
||||||
},
|
},
|
||||||
strip,
|
|
||||||
normalizeLinkText
|
normalizeLinkText
|
||||||
}
|
}
|
||||||
|
|
||||||
export default markdown
|
export default markdown
|
||||||
|
|||||||
39
browser/lib/markdownTextHelper.js
Normal file
39
browser/lib/markdownTextHelper.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* @fileoverview Text trimmer for markdown note.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
export function strip (input) {
|
||||||
|
let output = input
|
||||||
|
try {
|
||||||
|
output = output
|
||||||
|
.replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, '$1')
|
||||||
|
.replace(/\n={2,}/g, '\n')
|
||||||
|
.replace(/~~/g, '')
|
||||||
|
.replace(/`{3}.*\n/g, '')
|
||||||
|
.replace(/<(.*?)>/g, '$1')
|
||||||
|
.replace(/^[=\-]{2,}\s*$/g, '')
|
||||||
|
.replace(/\[\^.+?\](: .*?$)?/g, '')
|
||||||
|
.replace(/\s{0,2}\[.*?\]: .*?$/g, '')
|
||||||
|
.replace(/!\[.*?\][\[\(].*?[\]\)]/g, '')
|
||||||
|
.replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1')
|
||||||
|
.replace(/>/g, '')
|
||||||
|
.replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '')
|
||||||
|
.replace(/^#{1,6}\s*([^#]*)\s*(#{1,6})?/gm, '$1')
|
||||||
|
.replace(/(`{3,})(.*?)\1/gm, '$2')
|
||||||
|
.replace(/^-{3,}\s*$/g, '')
|
||||||
|
.replace(/`(.+?)`/g, '$1')
|
||||||
|
.replace(/\n{2,}/g, '\n\n')
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
strip
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ export default function searchFromNotes (notes, search) {
|
|||||||
|
|
||||||
function findByTag (notes, block) {
|
function findByTag (notes, block) {
|
||||||
const tag = block.match(/#(.+)/)[1]
|
const tag = block.match(/#(.+)/)[1]
|
||||||
let regExp = new RegExp(_.escapeRegExp(tag), 'i')
|
const regExp = new RegExp(_.escapeRegExp(tag), 'i')
|
||||||
return notes.filter((note) => {
|
return notes.filter((note) => {
|
||||||
if (!_.isArray(note.tags)) return false
|
if (!_.isArray(note.tags)) return false
|
||||||
return note.tags.some((_tag) => {
|
return note.tags.some((_tag) => {
|
||||||
@@ -26,7 +26,7 @@ function findByTag (notes, block) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findByWord (notes, block) {
|
function findByWord (notes, block) {
|
||||||
let regExp = new RegExp(_.escapeRegExp(block), 'i')
|
const regExp = new RegExp(_.escapeRegExp(block), 'i')
|
||||||
return notes.filter((note) => {
|
return notes.filter((note) => {
|
||||||
if (_.isArray(note.tags) && note.tags.some((_tag) => {
|
if (_.isArray(note.tags) && note.tags.some((_tag) => {
|
||||||
return _tag.match(regExp)
|
return _tag.match(regExp)
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
.root
|
.root
|
||||||
absolute top bottom right
|
absolute top bottom right
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content center
|
||||||
|
|
||||||
.empty
|
.empty
|
||||||
height 320px
|
height 320px
|
||||||
@@ -8,8 +11,9 @@
|
|||||||
|
|
||||||
.empty-message
|
.empty-message
|
||||||
width 100%
|
width 100%
|
||||||
font-size 42px
|
font-size 36px
|
||||||
line-height 72px
|
font-weight 600
|
||||||
|
line-height 56px
|
||||||
text-align center
|
text-align center
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Margin on the left side and the right side for NoteDetail component.
|
// Margin on the left side and the right side for NoteDetail component.
|
||||||
$note-detail-left-margin = 25px
|
$note-detail-left-margin = 100px
|
||||||
$note-detail-right-margin = 25px
|
$note-detail-right-margin = 120px
|
||||||
|
$snippet-note-detail-left-margin = 60px
|
||||||
|
$snippet-note-detail-right-margin = 80px
|
||||||
|
|
||||||
$note-detail-box-shadow = 2px 0 15px -8px #b1b1b1 inset
|
$note-detail-box-shadow = 2px 0 15px -8px #b1b1b1 inset
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './FolderSelect.styl'
|
import styles from './FolderSelect.styl'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
@@ -73,8 +74,8 @@ class FolderSelect extends React.Component {
|
|||||||
case 9:
|
case 9:
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
let tabbable = document.querySelectorAll('a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])')
|
const 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 previousEl = tabbable[Array.prototype.indexOf.call(tabbable, this.refs.root) - 1]
|
||||||
if (previousEl != null) previousEl.focus()
|
if (previousEl != null) previousEl.focus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,9 +90,9 @@ class FolderSelect extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleSearchInputChange (e) {
|
handleSearchInputChange (e) {
|
||||||
let { folders } = this.props
|
const { folders } = this.props
|
||||||
let search = this.refs.search.value
|
const search = this.refs.search.value
|
||||||
let optionIndex = search.length > 0
|
const optionIndex = search.length > 0
|
||||||
? _.findIndex(folders, (folder) => {
|
? _.findIndex(folders, (folder) => {
|
||||||
return folder.name.match(new RegExp('^' + _.escapeRegExp(search), 'i'))
|
return folder.name.match(new RegExp('^' + _.escapeRegExp(search), 'i'))
|
||||||
})
|
})
|
||||||
@@ -129,7 +130,7 @@ class FolderSelect extends React.Component {
|
|||||||
|
|
||||||
nextOption () {
|
nextOption () {
|
||||||
let { optionIndex } = this.state
|
let { optionIndex } = this.state
|
||||||
let { folders } = this.props
|
const { folders } = this.props
|
||||||
|
|
||||||
optionIndex++
|
optionIndex++
|
||||||
if (optionIndex >= folders.length) optionIndex = 0
|
if (optionIndex >= folders.length) optionIndex = 0
|
||||||
@@ -140,7 +141,7 @@ class FolderSelect extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
previousOption () {
|
previousOption () {
|
||||||
let { folders } = this.props
|
const { folders } = this.props
|
||||||
let { optionIndex } = this.state
|
let { optionIndex } = this.state
|
||||||
|
|
||||||
optionIndex--
|
optionIndex--
|
||||||
@@ -152,10 +153,10 @@ class FolderSelect extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectOption () {
|
selectOption () {
|
||||||
let { folders } = this.props
|
const { folders } = this.props
|
||||||
let optionIndex = this.state.optionIndex
|
const optionIndex = this.state.optionIndex
|
||||||
|
|
||||||
let folder = folders[optionIndex]
|
const folder = folders[optionIndex]
|
||||||
if (folder != null) {
|
if (folder != null) {
|
||||||
this.setState({
|
this.setState({
|
||||||
status: 'FOCUS'
|
status: 'FOCUS'
|
||||||
@@ -184,10 +185,10 @@ class FolderSelect extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { className, data, value } = this.props
|
const { className, data, value } = this.props
|
||||||
let splitted = value.split('-')
|
const splitted = value.split('-')
|
||||||
let storageKey = splitted.shift()
|
const storageKey = splitted.shift()
|
||||||
let folderKey = splitted.shift()
|
const folderKey = splitted.shift()
|
||||||
let options = []
|
let options = []
|
||||||
data.storageMap.forEach((storage, index) => {
|
data.storageMap.forEach((storage, index) => {
|
||||||
storage.folders.forEach((folder) => {
|
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) {
|
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))
|
options = options.filter((option) => filter.test(option.folder.name))
|
||||||
}
|
}
|
||||||
|
|
||||||
let optionList = options
|
const optionList = options
|
||||||
.map((option, index) => {
|
.map((option, index) => {
|
||||||
return (
|
return (
|
||||||
<div styleName={index === this.state.optionIndex
|
<div styleName={index === this.state.optionIndex
|
||||||
@@ -259,12 +260,11 @@ class FolderSelect extends React.Component {
|
|||||||
{optionList}
|
{optionList}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
: <div styleName='idle'>
|
: <div styleName='idle' style={{color: currentOption.folder.color}}>
|
||||||
<div styleName='idle-label'>
|
<div styleName='idle-label'>
|
||||||
<span styleName='idle-label-name'
|
<i className='fa fa-folder' />
|
||||||
style={{color: currentOption.folder.color}}
|
<span styleName='idle-label-name'>
|
||||||
>
|
{currentOption.folder.name}
|
||||||
{currentOption.folder.name} /
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
.root
|
.root
|
||||||
position relative
|
position relative
|
||||||
border solid 1px transparent
|
border solid 1px transparent
|
||||||
line-height 26px
|
|
||||||
vertical-align middle
|
vertical-align middle
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
transition 0.15s
|
transition 0.15s
|
||||||
user-select none
|
user-select none
|
||||||
|
margin-right 10px
|
||||||
&:hover
|
&:hover
|
||||||
background-color $ui-button--hover-backgroundColor
|
background-color $ui-button--hover-backgroundColor
|
||||||
|
|
||||||
.root--search, .root--focus
|
.root--search, .root--focus
|
||||||
@extend .root
|
@extend .root
|
||||||
background-color $ui-noteDetail-backgroundColor = #F4F4F4
|
background-color $ui-noteDetail-backgroundColor = #fff
|
||||||
border-color $ui-input--focus-borderColor
|
border-color $ui-input--focus-borderColor
|
||||||
width 100px
|
width 154px
|
||||||
|
height 30px
|
||||||
&:hover
|
&:hover
|
||||||
border-color $ui-input--focus-borderColor
|
border-color $ui-input--focus-borderColor = #fff
|
||||||
|
|
||||||
.idle
|
.idle
|
||||||
position relative
|
position relative
|
||||||
@@ -24,13 +25,16 @@
|
|||||||
.idle-label
|
.idle-label
|
||||||
right 20px
|
right 20px
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
|
||||||
.idle-label-name
|
.idle-label-name
|
||||||
font-size 14px
|
font-size 13px
|
||||||
padding 2px
|
font-weight 600
|
||||||
|
margin-left 4px
|
||||||
|
|
||||||
.idle-label-name-surfix
|
.idle-label-name-surfix
|
||||||
font-size 10px
|
font-size 15px
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
margin-left 5px
|
margin-left 5px
|
||||||
.idle-caret
|
.idle-caret
|
||||||
@@ -39,35 +43,37 @@
|
|||||||
width 20px
|
width 20px
|
||||||
line-height 34px
|
line-height 34px
|
||||||
|
|
||||||
.search
|
|
||||||
absolute top left right bottom
|
|
||||||
line-height 34px
|
|
||||||
|
|
||||||
.search-input
|
.search-input
|
||||||
vertical-align middle
|
vertical-align middle
|
||||||
position relative
|
position relative
|
||||||
top -2px
|
top 0
|
||||||
|
font-size 14px
|
||||||
outline none
|
outline none
|
||||||
border none
|
border none
|
||||||
height 20px
|
width 100%
|
||||||
line-height 20px
|
|
||||||
background-color transparent
|
background-color transparent
|
||||||
padding 0 10px
|
padding 0 10px
|
||||||
|
|
||||||
.search-optionList
|
.search-optionList
|
||||||
position fixed
|
position absolute
|
||||||
|
top 30px
|
||||||
max-height 450px
|
max-height 450px
|
||||||
|
min-width 150px
|
||||||
overflow auto
|
overflow auto
|
||||||
z-index 200
|
z-index 200
|
||||||
border $ui-border
|
border $ui-border
|
||||||
background-color white
|
background-color white
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
|
padding 10px 6px
|
||||||
|
|
||||||
.search-optionList-item
|
.search-optionList-item
|
||||||
|
width 140px
|
||||||
height 34px
|
height 34px
|
||||||
width 250px
|
display flex
|
||||||
|
align-items center
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
padding 0 5px
|
padding 0
|
||||||
|
margin-bottom 10px
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
cursor pointer
|
cursor pointer
|
||||||
&:hover
|
&:hover
|
||||||
@@ -81,13 +87,17 @@
|
|||||||
background-color $ui-button--active-backgroundColor
|
background-color $ui-button--active-backgroundColor
|
||||||
color $ui-button--active-color
|
color $ui-button--active-color
|
||||||
.search-optionList-item-name
|
.search-optionList-item-name
|
||||||
border-left solid 2px transparent
|
border-left solid 3px transparent
|
||||||
padding 2px 5px
|
padding 6px
|
||||||
.search-optionList-item-name-surfix
|
.search-optionList-item-name-surfix
|
||||||
font-size 10px
|
font-size 10px
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
margin-left 5px
|
margin-left 5px
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './InfoButton.styl'
|
import styles from './InfoButton.styl'
|
||||||
|
|
||||||
@@ -6,9 +7,9 @@ const InfoButton = ({
|
|||||||
onClick
|
onClick
|
||||||
}) => (
|
}) => (
|
||||||
<button styleName='control-infoButton'
|
<button styleName='control-infoButton'
|
||||||
onClick={onClick}
|
onClick={(e) => onClick(e)}
|
||||||
>
|
>
|
||||||
<i className='fa fa-info infoButton' styleName='info-button' />
|
<img className='infoButton' src='../resources/icon/icon-info.svg' />
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,10 @@
|
|||||||
.control-infoButton
|
.control-infoButton
|
||||||
float right
|
top 10px
|
||||||
|
margin-bottom 10px
|
||||||
topBarButtonLight()
|
topBarButtonLight()
|
||||||
|
|
||||||
.control-infoPanel
|
|
||||||
position fixed
|
|
||||||
pointer-events none
|
|
||||||
top 50px
|
|
||||||
z-index 200
|
|
||||||
line-height normal
|
|
||||||
border-radius 2px
|
|
||||||
opacity 0
|
|
||||||
transition 0.1s
|
|
||||||
|
|
||||||
.infoButton
|
.infoButton
|
||||||
padding 0px
|
padding 0px
|
||||||
margin 15px 0
|
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.control-infoButton
|
.control-infoButton
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './InfoPanel.styl'
|
import styles from './InfoPanel.styl'
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
|
|
||||||
.control-infoButton-panel
|
.control-infoButton-panel
|
||||||
z-index 200
|
z-index 200
|
||||||
margin-top 38px
|
margin-top 0px
|
||||||
margin-left -140px
|
right 0
|
||||||
position absolute
|
position absolute
|
||||||
padding 20px 25px 0 25px
|
padding 20px 25px 0 25px
|
||||||
width 300px
|
width 300px
|
||||||
height 500px
|
height 350px
|
||||||
overflow auto
|
overflow auto
|
||||||
background-color $ui-noteList-backgroundColor
|
background-color $ui-noteList-backgroundColor
|
||||||
box-shadow 2px 12px 15px 2px rgba(0, 0, 0, 0.1), 2px 1px 50px 2px rgba(0, 0, 0, 0.1)
|
box-shadow 2px 12px 15px 2px rgba(0, 0, 0, 0.1), 2px 1px 50px 2px rgba(0, 0, 0, 0.1)
|
||||||
@@ -32,8 +32,8 @@
|
|||||||
|
|
||||||
.control-infoButton-panel-trash
|
.control-infoButton-panel-trash
|
||||||
z-index 200
|
z-index 200
|
||||||
margin-top 45px
|
margin-top 0px
|
||||||
margin-left -190px
|
right 0px
|
||||||
position absolute
|
position absolute
|
||||||
padding 20px 25px 0 25px
|
padding 20px 25px 0 25px
|
||||||
width 300px
|
width 300px
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './InfoPanel.styl'
|
import styles from './InfoPanel.styl'
|
||||||
|
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './MarkdownNoteDetail.styl'
|
import styles from './MarkdownNoteDetail.styl'
|
||||||
import MarkdownEditor from 'browser/components/MarkdownEditor'
|
import MarkdownEditor from 'browser/components/MarkdownEditor'
|
||||||
@@ -9,12 +10,13 @@ import FolderSelect from './FolderSelect'
|
|||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import { hashHistory } from 'react-router'
|
import { hashHistory } from 'react-router'
|
||||||
import ee from 'browser/main/lib/eventEmitter'
|
import ee from 'browser/main/lib/eventEmitter'
|
||||||
import markdown from 'browser/lib/markdown'
|
import markdown from 'browser/lib/markdownTextHelper'
|
||||||
import StatusBar from '../StatusBar'
|
import StatusBar from '../StatusBar'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import TrashButton from './TrashButton'
|
import TrashButton from './TrashButton'
|
||||||
|
import PermanentDeleteButton from './PermanentDeleteButton'
|
||||||
import InfoButton from './InfoButton'
|
import InfoButton from './InfoButton'
|
||||||
import InfoPanel from './InfoPanel'
|
import InfoPanel from './InfoPanel'
|
||||||
import InfoPanelTrashed from './InfoPanelTrashed'
|
import InfoPanelTrashed from './InfoPanelTrashed'
|
||||||
@@ -24,7 +26,7 @@ import striptags from 'striptags'
|
|||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { remote } = electron
|
const { remote } = electron
|
||||||
const { Menu, MenuItem, dialog } = remote
|
const { dialog } = remote
|
||||||
|
|
||||||
class MarkdownNoteDetail extends React.Component {
|
class MarkdownNoteDetail extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -73,7 +75,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleChange (e) {
|
handleChange (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
|
|
||||||
note.content = this.refs.content.value
|
note.content = this.refs.content.value
|
||||||
if (this.refs.tags) note.tags = this.refs.tags.value
|
if (this.refs.tags) note.tags = this.refs.tags.value
|
||||||
@@ -95,7 +97,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveNow () {
|
saveNow () {
|
||||||
let { note, dispatch } = this.props
|
const { note, dispatch } = this.props
|
||||||
clearTimeout(this.saveQueue)
|
clearTimeout(this.saveQueue)
|
||||||
this.saveQueue = null
|
this.saveQueue = null
|
||||||
|
|
||||||
@@ -111,11 +113,11 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleFolderChange (e) {
|
handleFolderChange (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
let value = this.refs.folder.value
|
const value = this.refs.folder.value
|
||||||
let splitted = value.split('-')
|
const splitted = value.split('-')
|
||||||
let newStorageKey = splitted.shift()
|
const newStorageKey = splitted.shift()
|
||||||
let newFolderKey = splitted.shift()
|
const newFolderKey = splitted.shift()
|
||||||
|
|
||||||
dataApi
|
dataApi
|
||||||
.moveNote(note.storage, note.key, newStorageKey, newFolderKey)
|
.moveNote(note.storage, note.key, newStorageKey, newFolderKey)
|
||||||
@@ -124,7 +126,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
isMovingNote: true,
|
isMovingNote: true,
|
||||||
note: Object.assign({}, newNote)
|
note: Object.assign({}, newNote)
|
||||||
}, () => {
|
}, () => {
|
||||||
let { dispatch, location } = this.props
|
const { dispatch, location } = this.props
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'MOVE_NOTE',
|
type: 'MOVE_NOTE',
|
||||||
originNote: note,
|
originNote: note,
|
||||||
@@ -144,7 +146,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleStarButtonClick (e) {
|
handleStarButtonClick (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
if (!note.isStarred) AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_STAR')
|
if (!note.isStarred) AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_STAR')
|
||||||
|
|
||||||
note.isStarred = !note.isStarred
|
note.isStarred = !note.isStarred
|
||||||
@@ -169,22 +171,22 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleTrashButtonClick (e) {
|
handleTrashButtonClick (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
const { isTrashed } = note
|
const { isTrashed } = note
|
||||||
|
|
||||||
if (isTrashed) {
|
if (isTrashed) {
|
||||||
let dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: 'Confirm note deletion',
|
message: 'Confirm note deletion',
|
||||||
detail: 'This will permanently remove this note.',
|
detail: 'This will permanently remove this note.',
|
||||||
buttons: ['Confirm', 'Cancel']
|
buttons: ['Confirm', 'Cancel']
|
||||||
})
|
})
|
||||||
if (dialogueButtonIndex === 1) return
|
if (dialogueButtonIndex === 1) return
|
||||||
let { note, dispatch } = this.props
|
const { note, dispatch } = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.deleteNote(note.storage, note.key)
|
.deleteNote(note.storage, note.key)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
let dispatchHandler = () => {
|
const dispatchHandler = () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'DELETE_NOTE',
|
type: 'DELETE_NOTE',
|
||||||
storageKey: data.storageKey,
|
storageKey: data.storageKey,
|
||||||
@@ -206,7 +208,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUndoButtonClick (e) {
|
handleUndoButtonClick (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
|
|
||||||
note.isTrashed = false
|
note.isTrashed = false
|
||||||
|
|
||||||
@@ -231,7 +233,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getToggleLockButton () {
|
getToggleLockButton () {
|
||||||
return this.state.isLocked ? 'fa-lock' : 'fa-unlock'
|
return this.state.isLocked ? '../resources/icon/icon-lock.svg' : '../resources/icon/icon-unlock.svg'
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteKeyDown (e) {
|
handleDeleteKeyDown (e) {
|
||||||
@@ -261,12 +263,12 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { data, config, location } = this.props
|
const { data, config, location } = this.props
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
let storageKey = note.storage
|
const storageKey = note.storage
|
||||||
let folderKey = note.folder
|
const folderKey = note.folder
|
||||||
|
|
||||||
let options = []
|
const options = []
|
||||||
data.storageMap.forEach((storage, index) => {
|
data.storageMap.forEach((storage, index) => {
|
||||||
storage.folders.forEach((folder) => {
|
storage.folders.forEach((folder) => {
|
||||||
options.push({
|
options.push({
|
||||||
@@ -275,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'>
|
const trashTopBar = <div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
@@ -285,7 +287,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
<PermanentDeleteButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
||||||
<InfoButton
|
<InfoButton
|
||||||
onClick={(e) => this.handleInfoButtonClick(e)}
|
onClick={(e) => this.handleInfoButtonClick(e)}
|
||||||
/>
|
/>
|
||||||
@@ -302,10 +304,6 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
|
|
||||||
const detailTopBar = <div styleName='info'>
|
const detailTopBar = <div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
<StarButton styleName='info-left-button'
|
|
||||||
onClick={(e) => this.handleStarButtonClick(e)}
|
|
||||||
isActive={note.isStarred}
|
|
||||||
/>
|
|
||||||
<div styleName='info-left-top'>
|
<div styleName='info-left-top'>
|
||||||
<FolderSelect styleName='info-left-top-folderSelect'
|
<FolderSelect styleName='info-left-top-folderSelect'
|
||||||
value={this.state.note.storage + '-' + this.state.note.folder}
|
value={this.state.note.storage + '-' + this.state.note.folder}
|
||||||
@@ -325,31 +323,38 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
|
<InfoButton
|
||||||
|
onClick={(e) => this.handleInfoButtonClick(e)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<StarButton
|
||||||
|
onClick={(e) => this.handleStarButtonClick(e)}
|
||||||
|
isActive={note.isStarred}
|
||||||
|
/>
|
||||||
|
|
||||||
{(() => {
|
{(() => {
|
||||||
const faClassName = `fa ${this.getToggleLockButton()}`
|
const imgSrc = `${this.getToggleLockButton()}`
|
||||||
const lockButtonComponent =
|
const lockButtonComponent =
|
||||||
<button styleName='control-lockButton'
|
<button styleName='control-lockButton'
|
||||||
onFocus={(e) => this.handleFocus(e)}
|
onFocus={(e) => this.handleFocus(e)}
|
||||||
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
|
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
|
||||||
>
|
>
|
||||||
<i className={faClassName} styleName='lock-button' />
|
<img styleName='iconInfo' src={imgSrc} />
|
||||||
<span styleName='control-lockButton-tooltip'>
|
|
||||||
{this.state.isLocked ? 'Unlock Editor' : 'Keep Editor Locked'}
|
|
||||||
</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
this.state.isLockButtonShown ? lockButtonComponent : ''
|
this.state.isLockButtonShown ? lockButtonComponent : ''
|
||||||
)
|
)
|
||||||
})()}
|
})()}
|
||||||
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
|
||||||
<button styleName='control-fullScreenButton'
|
<button styleName='control-fullScreenButton'
|
||||||
onMouseDown={(e) => this.handleFullScreenButton(e)}
|
onMouseDown={(e) => this.handleFullScreenButton(e)}
|
||||||
>
|
>
|
||||||
<i className='fa fa-window-maximize' styleName='fullScreen-button' />
|
<img styleName='iconInfo' src='../resources/icon/icon-sidebar.svg' />
|
||||||
</button>
|
</button>
|
||||||
<InfoButton
|
|
||||||
onClick={(e) => this.handleInfoButtonClick(e)}
|
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
||||||
/>
|
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
storageName={currentOption.storage.name}
|
storageName={currentOption.storage.name}
|
||||||
folderName={currentOption.folder.name}
|
folderName={currentOption.folder.name}
|
||||||
|
|||||||
@@ -3,47 +3,47 @@
|
|||||||
|
|
||||||
.root
|
.root
|
||||||
absolute top right bottom
|
absolute top right bottom
|
||||||
border-width 0
|
border-left 1px solid alpha(#DEDEDE, 60%)
|
||||||
background-color $ui-noteDetail-backgroundColor
|
background-color $ui-noteDetail-backgroundColor
|
||||||
box-shadow $note-detail-box-shadow
|
box-shadow none
|
||||||
|
padding 20px 40px
|
||||||
|
|
||||||
.lock-button
|
.lock-button
|
||||||
padding-bottom 3px
|
padding-bottom 3px
|
||||||
|
|
||||||
.control-lockButton
|
.control-lockButton
|
||||||
|
top 160px
|
||||||
|
margin-bottom 10px
|
||||||
topBarButtonLight()
|
topBarButtonLight()
|
||||||
|
|
||||||
.control-lockButton-tooltip
|
.trashed-infopanel
|
||||||
tooltip()
|
top 40px
|
||||||
position fixed
|
position relative
|
||||||
pointer-events none
|
|
||||||
top 50px
|
|
||||||
z-index 200
|
|
||||||
padding 5px
|
|
||||||
line-height normal
|
|
||||||
border-radius 2px
|
|
||||||
opacity 0
|
|
||||||
transition 0.1s
|
|
||||||
|
|
||||||
.control-fullScreenButton
|
.control-fullScreenButton
|
||||||
float right
|
top 80px
|
||||||
padding 0 0 2px 0
|
|
||||||
topBarButtonLight()
|
topBarButtonLight()
|
||||||
|
|
||||||
.body
|
.body
|
||||||
absolute left right
|
absolute left right
|
||||||
left $note-detail-left-margin
|
left 0
|
||||||
right $note-detail-right-margin
|
right 0
|
||||||
top $info-height + $info-margin-under-border
|
top $info-height + $info-margin-under-border
|
||||||
bottom $statusBar-height
|
bottom $statusBar-height
|
||||||
|
margin 0 45px
|
||||||
.body-noteEditor
|
.body-noteEditor
|
||||||
absolute top bottom left right
|
absolute top bottom left right
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.root
|
||||||
|
box-shadow $note-detail-box-shadow
|
||||||
|
border none
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
background-color $ui-dark-noteDetail-backgroundColor
|
background-color $ui-dark-noteDetail-backgroundColor
|
||||||
box-shadow none
|
box-shadow none
|
||||||
|
border none
|
||||||
|
|
||||||
.control-lockButton
|
.control-lockButton
|
||||||
topBarButtonDark()
|
topBarButtonDark()
|
||||||
|
|||||||
@@ -1,33 +1,31 @@
|
|||||||
@import('DetailVars')
|
@import('DetailVars')
|
||||||
|
|
||||||
$info-height = 60px
|
$info-height = 50px
|
||||||
$info-margin-under-border = 27px
|
$info-margin-under-border = 30px
|
||||||
|
|
||||||
.info
|
.info
|
||||||
absolute top left right
|
absolute top left right
|
||||||
left $note-detail-left-margin
|
left 0
|
||||||
right $note-detail-right-margin
|
right 0
|
||||||
height $info-height
|
height $info-height
|
||||||
border-bottom $ui-border
|
border-bottom 1px solid #eee
|
||||||
background-color $ui-noteDetail-backgroundColor
|
background-color $ui-noteDetail-backgroundColor
|
||||||
|
width 100%
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
|
||||||
.info-left
|
.info-left
|
||||||
float left
|
padding 0 10px
|
||||||
padding 0 5px
|
width 100%
|
||||||
margin 0px 2px
|
display flex
|
||||||
.info-left-top
|
align-items center
|
||||||
display inline-block
|
|
||||||
height $info-height
|
|
||||||
line-height $info-height
|
|
||||||
|
|
||||||
.info-left-top-folderSelect
|
.info-left-top-folderSelect
|
||||||
padding 0 3px
|
|
||||||
height 34px
|
|
||||||
line-height 26px
|
|
||||||
display flex
|
display flex
|
||||||
align-items center
|
align-items center
|
||||||
justify-content center
|
justify-content center
|
||||||
border-radius 3px
|
|
||||||
.info-left-button
|
.info-left-button
|
||||||
width 34px
|
width 34px
|
||||||
height 34px
|
height 34px
|
||||||
@@ -48,18 +46,18 @@ $info-margin-under-border = 27px
|
|||||||
|
|
||||||
.info-right
|
.info-right
|
||||||
position absolute
|
position absolute
|
||||||
right 0
|
right 40px
|
||||||
top 0
|
top 60px
|
||||||
background $ui-noteDetail-backgroundColor
|
|
||||||
bottom 1px
|
bottom 1px
|
||||||
padding-left 30px
|
padding-left 30px
|
||||||
|
z-index 101
|
||||||
|
|
||||||
.undo-button
|
.undo-button
|
||||||
width 34px
|
width 34px
|
||||||
height 34px
|
height 34px
|
||||||
border-radius 17px
|
border-radius 17px
|
||||||
font-size 14px
|
font-size 14px
|
||||||
margin 15px 7px
|
margin 5px 0px
|
||||||
border none
|
border none
|
||||||
color $ui-button-color
|
color $ui-button-color
|
||||||
display flex
|
display flex
|
||||||
@@ -72,6 +70,7 @@ $info-margin-under-border = 27px
|
|||||||
border-color $ui-button--active-backgroundColor
|
border-color $ui-button--active-backgroundColor
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-button--hover-backgroundColor, 60%)
|
background-color alpha($ui-button--hover-backgroundColor, 60%)
|
||||||
|
transition 0.2s
|
||||||
.control-lockButton-tooltip
|
.control-lockButton-tooltip
|
||||||
opacity 1
|
opacity 1
|
||||||
|
|
||||||
|
|||||||
20
browser/main/Detail/PermanentDeleteButton.js
Normal file
20
browser/main/Detail/PermanentDeleteButton.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './TrashButton.styl'
|
||||||
|
|
||||||
|
const PermanentDeleteButton = ({
|
||||||
|
onClick
|
||||||
|
}) => (
|
||||||
|
<button styleName='control-trashButton--in-trash'
|
||||||
|
onClick={(e) => onClick(e)}
|
||||||
|
>
|
||||||
|
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
PermanentDeleteButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(PermanentDeleteButton, styles)
|
||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './SnippetNoteDetail.styl'
|
import styles from './SnippetNoteDetail.styl'
|
||||||
import CodeEditor from 'browser/components/CodeEditor'
|
import CodeEditor from 'browser/components/CodeEditor'
|
||||||
@@ -18,6 +19,7 @@ import _ from 'lodash'
|
|||||||
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import TrashButton from './TrashButton'
|
import TrashButton from './TrashButton'
|
||||||
|
import PermanentDeleteButton from './PermanentDeleteButton'
|
||||||
import InfoButton from './InfoButton'
|
import InfoButton from './InfoButton'
|
||||||
import InfoPanel from './InfoPanel'
|
import InfoPanel from './InfoPanel'
|
||||||
import InfoPanelTrashed from './InfoPanelTrashed'
|
import InfoPanelTrashed from './InfoPanelTrashed'
|
||||||
@@ -60,7 +62,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
if (nextProps.note.key !== this.props.note.key && !this.isMovingNote) {
|
if (nextProps.note.key !== this.props.note.key && !this.isMovingNote) {
|
||||||
if (this.saveQueue != null) this.saveNow()
|
if (this.saveQueue != null) this.saveNow()
|
||||||
let nextNote = Object.assign({
|
const nextNote = Object.assign({
|
||||||
description: ''
|
description: ''
|
||||||
}, nextProps.note, {
|
}, nextProps.note, {
|
||||||
snippets: nextProps.note.snippets.map((snippet) => Object.assign({}, snippet))
|
snippets: nextProps.note.snippets.map((snippet) => Object.assign({}, snippet))
|
||||||
@@ -69,7 +71,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
snippetIndex: 0,
|
snippetIndex: 0,
|
||||||
note: nextNote
|
note: nextNote
|
||||||
}, () => {
|
}, () => {
|
||||||
let { snippets } = this.state.note
|
const { snippets } = this.state.note
|
||||||
snippets.forEach((snippet, index) => {
|
snippets.forEach((snippet, index) => {
|
||||||
this.refs['code-' + index].reload()
|
this.refs['code-' + index].reload()
|
||||||
})
|
})
|
||||||
@@ -83,7 +85,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleChange (e) {
|
handleChange (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
|
|
||||||
if (this.refs.tags) note.tags = this.refs.tags.value
|
if (this.refs.tags) note.tags = this.refs.tags.value
|
||||||
note.description = this.refs.description.value
|
note.description = this.refs.description.value
|
||||||
@@ -105,7 +107,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
saveNow () {
|
saveNow () {
|
||||||
let { note, dispatch } = this.props
|
const { note, dispatch } = this.props
|
||||||
clearTimeout(this.saveQueue)
|
clearTimeout(this.saveQueue)
|
||||||
this.saveQueue = null
|
this.saveQueue = null
|
||||||
|
|
||||||
@@ -121,11 +123,11 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleFolderChange (e) {
|
handleFolderChange (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
let value = this.refs.folder.value
|
const value = this.refs.folder.value
|
||||||
let splitted = value.split('-')
|
const splitted = value.split('-')
|
||||||
let newStorageKey = splitted.shift()
|
const newStorageKey = splitted.shift()
|
||||||
let newFolderKey = splitted.shift()
|
const newFolderKey = splitted.shift()
|
||||||
|
|
||||||
dataApi
|
dataApi
|
||||||
.moveNote(note.storage, note.key, newStorageKey, newFolderKey)
|
.moveNote(note.storage, note.key, newStorageKey, newFolderKey)
|
||||||
@@ -134,7 +136,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
isMovingNote: true,
|
isMovingNote: true,
|
||||||
note: Object.assign({}, newNote)
|
note: Object.assign({}, newNote)
|
||||||
}, () => {
|
}, () => {
|
||||||
let { dispatch, location } = this.props
|
const { dispatch, location } = this.props
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'MOVE_NOTE',
|
type: 'MOVE_NOTE',
|
||||||
originNote: note,
|
originNote: note,
|
||||||
@@ -154,7 +156,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleStarButtonClick (e) {
|
handleStarButtonClick (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
if (!note.isStarred) AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_STAR')
|
if (!note.isStarred) AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_STAR')
|
||||||
|
|
||||||
note.isStarred = !note.isStarred
|
note.isStarred = !note.isStarred
|
||||||
@@ -171,22 +173,22 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleTrashButtonClick (e) {
|
handleTrashButtonClick (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
const { isTrashed } = note
|
const { isTrashed } = note
|
||||||
|
|
||||||
if (isTrashed) {
|
if (isTrashed) {
|
||||||
let dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: 'Confirm note deletion',
|
message: 'Confirm note deletion',
|
||||||
detail: 'This will permanently remove this note.',
|
detail: 'This will permanently remove this note.',
|
||||||
buttons: ['Confirm', 'Cancel']
|
buttons: ['Confirm', 'Cancel']
|
||||||
})
|
})
|
||||||
if (dialogueButtonIndex === 1) return
|
if (dialogueButtonIndex === 1) return
|
||||||
let { note, dispatch } = this.props
|
const { note, dispatch } = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.deleteNote(note.storage, note.key)
|
.deleteNote(note.storage, note.key)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
let dispatchHandler = () => {
|
const dispatchHandler = () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'DELETE_NOTE',
|
type: 'DELETE_NOTE',
|
||||||
storageKey: data.storageKey,
|
storageKey: data.storageKey,
|
||||||
@@ -208,7 +210,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleUndoButtonClick (e) {
|
handleUndoButtonClick (e) {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
|
|
||||||
note.isTrashed = false
|
note.isTrashed = false
|
||||||
|
|
||||||
@@ -237,7 +239,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
handleTabDeleteButtonClick (e, index) {
|
handleTabDeleteButtonClick (e, index) {
|
||||||
if (this.state.note.snippets.length > 1) {
|
if (this.state.note.snippets.length > 1) {
|
||||||
if (this.state.note.snippets[index].content.trim().length > 0) {
|
if (this.state.note.snippets[index].content.trim().length > 0) {
|
||||||
let dialogIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
const dialogIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: 'Delete a snippet',
|
message: 'Delete a snippet',
|
||||||
detail: 'This work cannot be undone.',
|
detail: 'This work cannot be undone.',
|
||||||
@@ -287,7 +289,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
|
|
||||||
handleModeOptionClick (index, name) {
|
handleModeOptionClick (index, name) {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
let snippets = this.state.note.snippets.slice()
|
const snippets = this.state.note.snippets.slice()
|
||||||
snippets[index].mode = name
|
snippets[index].mode = name
|
||||||
this.setState({note: Object.assign(this.state.note, {snippets: snippets})})
|
this.setState({note: Object.assign(this.state.note, {snippets: snippets})})
|
||||||
|
|
||||||
@@ -305,7 +307,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
|
|
||||||
handleCodeChange (index) {
|
handleCodeChange (index) {
|
||||||
return (e) => {
|
return (e) => {
|
||||||
let snippets = this.state.note.snippets.slice()
|
const snippets = this.state.note.snippets.slice()
|
||||||
snippets[index].content = this.refs['code-' + index].value
|
snippets[index].content = this.refs['code-' + index].value
|
||||||
this.setState({note: Object.assign(this.state.note, {snippets: snippets})})
|
this.setState({note: Object.assign(this.state.note, {snippets: snippets})})
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -332,7 +334,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
break
|
break
|
||||||
case 76:
|
case 76:
|
||||||
{
|
{
|
||||||
let isSuper = global.process.platform === 'darwin'
|
const isSuper = global.process.platform === 'darwin'
|
||||||
? e.metaKey
|
? e.metaKey
|
||||||
: e.ctrlKey
|
: e.ctrlKey
|
||||||
if (isSuper) {
|
if (isSuper) {
|
||||||
@@ -343,7 +345,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
break
|
break
|
||||||
case 84:
|
case 84:
|
||||||
{
|
{
|
||||||
let isSuper = global.process.platform === 'darwin'
|
const isSuper = global.process.platform === 'darwin'
|
||||||
? e.metaKey
|
? e.metaKey
|
||||||
: e.ctrlKey
|
: e.ctrlKey
|
||||||
if (isSuper) {
|
if (isSuper) {
|
||||||
@@ -356,7 +358,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleModeButtonClick (e, index) {
|
handleModeButtonClick (e, index) {
|
||||||
let menu = new Menu()
|
const menu = new Menu()
|
||||||
CodeMirror.modeInfo.forEach((mode) => {
|
CodeMirror.modeInfo.forEach((mode) => {
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
label: mode.name,
|
label: mode.name,
|
||||||
@@ -397,8 +399,8 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleIndentSizeItemClick (e, indentSize) {
|
handleIndentSizeItemClick (e, indentSize) {
|
||||||
let { config, dispatch } = this.props
|
const { config, dispatch } = this.props
|
||||||
let editor = Object.assign({}, config.editor, {
|
const editor = Object.assign({}, config.editor, {
|
||||||
indentSize
|
indentSize
|
||||||
})
|
})
|
||||||
ConfigManager.set({
|
ConfigManager.set({
|
||||||
@@ -413,8 +415,8 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleIndentTypeItemClick (e, indentType) {
|
handleIndentTypeItemClick (e, indentType) {
|
||||||
let { config, dispatch } = this.props
|
const { config, dispatch } = this.props
|
||||||
let editor = Object.assign({}, config.editor, {
|
const editor = Object.assign({}, config.editor, {
|
||||||
indentType
|
indentType
|
||||||
})
|
})
|
||||||
ConfigManager.set({
|
ConfigManager.set({
|
||||||
@@ -433,14 +435,14 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addSnippet () {
|
addSnippet () {
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
|
|
||||||
note.snippets = note.snippets.concat([{
|
note.snippets = note.snippets.concat([{
|
||||||
name: '',
|
name: '',
|
||||||
mode: 'Plain Text',
|
mode: 'Plain Text',
|
||||||
content: ''
|
content: ''
|
||||||
}])
|
}])
|
||||||
let snippetIndex = note.snippets.length - 1
|
const snippetIndex = note.snippets.length - 1
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
note,
|
note,
|
||||||
@@ -486,19 +488,19 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { data, config, location } = this.props
|
const { data, config, location } = this.props
|
||||||
let { note } = this.state
|
const { note } = this.state
|
||||||
|
|
||||||
let storageKey = note.storage
|
const storageKey = note.storage
|
||||||
let folderKey = note.folder
|
const folderKey = note.folder
|
||||||
|
|
||||||
let editorFontSize = parseInt(config.editor.fontSize, 10)
|
let editorFontSize = parseInt(config.editor.fontSize, 10)
|
||||||
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
|
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
|
||||||
let editorIndentSize = parseInt(config.editor.indentSize, 10)
|
let editorIndentSize = parseInt(config.editor.indentSize, 10)
|
||||||
if (!(editorFontSize > 0 && editorFontSize < 132)) editorIndentSize = 4
|
if (!(editorFontSize > 0 && editorFontSize < 132)) editorIndentSize = 4
|
||||||
|
|
||||||
let tabList = note.snippets.map((snippet, index) => {
|
const tabList = note.snippets.map((snippet, index) => {
|
||||||
let isActive = this.state.snippetIndex === index
|
const isActive = this.state.snippetIndex === index
|
||||||
|
|
||||||
return <SnippetTab
|
return <SnippetTab
|
||||||
key={index}
|
key={index}
|
||||||
@@ -512,8 +514,8 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
|
|
||||||
let viewList = note.snippets.map((snippet, index) => {
|
const viewList = note.snippets.map((snippet, index) => {
|
||||||
let isActive = this.state.snippetIndex === index
|
const isActive = this.state.snippetIndex === index
|
||||||
|
|
||||||
let syntax = CodeMirror.findModeByName(pass(snippet.mode))
|
let syntax = CodeMirror.findModeByName(pass(snippet.mode))
|
||||||
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
||||||
@@ -547,7 +549,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
})
|
})
|
||||||
|
|
||||||
let options = []
|
const options = []
|
||||||
data.storageMap.forEach((storage, index) => {
|
data.storageMap.forEach((storage, index) => {
|
||||||
storage.folders.forEach((folder) => {
|
storage.folders.forEach((folder) => {
|
||||||
options.push({
|
options.push({
|
||||||
@@ -556,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'>
|
const trashTopBar = <div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
@@ -566,7 +568,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
<PermanentDeleteButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
||||||
<InfoButton
|
<InfoButton
|
||||||
onClick={(e) => this.handleInfoButtonClick(e)}
|
onClick={(e) => this.handleInfoButtonClick(e)}
|
||||||
/>
|
/>
|
||||||
@@ -583,10 +585,6 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
|
|
||||||
const detailTopBar = <div styleName='info'>
|
const detailTopBar = <div styleName='info'>
|
||||||
<div styleName='info-left'>
|
<div styleName='info-left'>
|
||||||
<StarButton styleName='info-left-button'
|
|
||||||
onClick={(e) => this.handleStarButtonClick(e)}
|
|
||||||
isActive={note.isStarred}
|
|
||||||
/>
|
|
||||||
<div styleName='info-left-top'>
|
<div styleName='info-left-top'>
|
||||||
<FolderSelect styleName='info-left-top-folderSelect'
|
<FolderSelect styleName='info-left-top-folderSelect'
|
||||||
value={this.state.note.storage + '-' + this.state.note.folder}
|
value={this.state.note.storage + '-' + this.state.note.folder}
|
||||||
@@ -603,15 +601,21 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
|
||||||
<button styleName='control-fullScreenButton'
|
|
||||||
onMouseDown={(e) => this.handleFullScreenButton(e)}
|
|
||||||
>
|
|
||||||
<i className='fa fa-window-maximize' styleName='fullScreen-button' />
|
|
||||||
</button>
|
|
||||||
<InfoButton
|
<InfoButton
|
||||||
onClick={(e) => this.handleInfoButtonClick(e)}
|
onClick={(e) => this.handleInfoButtonClick(e)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<StarButton
|
||||||
|
onClick={(e) => this.handleStarButtonClick(e)}
|
||||||
|
isActive={note.isStarred}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button styleName='control-fullScreenButton'
|
||||||
|
onMouseDown={(e) => this.handleFullScreenButton(e)}>
|
||||||
|
<img styleName='iconInfo' src='../resources/icon/icon-sidebar.svg' />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
||||||
<InfoPanel
|
<InfoPanel
|
||||||
storageName={currentOption.storage.name}
|
storageName={currentOption.storage.name}
|
||||||
folderName={currentOption.folder.name}
|
folderName={currentOption.folder.name}
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
|
|
||||||
.root
|
.root
|
||||||
absolute top bottom right
|
absolute top bottom right
|
||||||
border-width 0
|
border-left 1px solid alpha(#DEDEDE, 60%)
|
||||||
background-color $ui-noteDetail-backgroundColor
|
background-color $ui-noteDetail-backgroundColor
|
||||||
box-shadow $note-detail-box-shadow
|
box-shadow none
|
||||||
|
|
||||||
.body
|
.body
|
||||||
absolute left right
|
absolute left right
|
||||||
left $note-detail-left-margin
|
left $snippet-note-detail-left-margin
|
||||||
right $note-detail-right-margin
|
right $snippet-note-detail-right-margin
|
||||||
top $info-height + $info-margin-under-border
|
top $info-height + $info-margin-under-border
|
||||||
bottom $statusBar-height
|
bottom $statusBar-height
|
||||||
background-color $ui-noteDetail-backgroundColor
|
background-color $ui-noteDetail-backgroundColor
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
overflow hidden
|
overflow hidden
|
||||||
|
|
||||||
.tabList .plusButton
|
.tabList .plusButton
|
||||||
navButtonColor()
|
navWhiteButtonColor()
|
||||||
width 30px
|
width 30px
|
||||||
|
|
||||||
.tabView
|
.tabView
|
||||||
@@ -55,24 +55,30 @@
|
|||||||
|
|
||||||
.override
|
.override
|
||||||
absolute bottom left
|
absolute bottom left
|
||||||
bottom 2px
|
bottom 1px
|
||||||
left 60px
|
left 60px
|
||||||
height 23px
|
|
||||||
z-index 101
|
z-index 101
|
||||||
button
|
button
|
||||||
navButtonColor()
|
navButtonColor()
|
||||||
height 24px
|
padding 0 6px
|
||||||
|
&:hover
|
||||||
|
color $ui-active-color
|
||||||
&:active .update-icon
|
&:active .update-icon
|
||||||
color white
|
color $ui-active-color
|
||||||
|
|
||||||
.control-fullScreenButton
|
.control-fullScreenButton
|
||||||
float right
|
top 80px
|
||||||
padding 0 0 2px 0
|
margin-bottom 10px
|
||||||
topBarButtonLight()
|
topBarButtonLight()
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.root
|
||||||
|
box-shadow $note-detail-box-shadow
|
||||||
|
border none
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
border-color $ui-dark-borderColor
|
border none
|
||||||
background-color $ui-dark-noteDetail-backgroundColor
|
background-color $ui-dark-noteDetail-backgroundColor
|
||||||
box-shadow none
|
box-shadow none
|
||||||
|
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './StarButton.styl'
|
import styles from './StarButton.styl'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
@@ -31,7 +32,7 @@ class StarButton extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { className } = this.props
|
const { className } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className={_.isString(className)
|
<button className={_.isString(className)
|
||||||
@@ -47,10 +48,10 @@ class StarButton extends React.Component {
|
|||||||
onMouseLeave={(e) => this.handleMouseLeave(e)}
|
onMouseLeave={(e) => this.handleMouseLeave(e)}
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
>
|
>
|
||||||
<i styleName='icon'
|
<img styleName='icon'
|
||||||
className={this.state.isActive || this.props.isActive
|
src={this.state.isActive || this.props.isActive
|
||||||
? 'fa fa-star'
|
? '../resources/icon/icon-starred.svg'
|
||||||
: 'fa fa-star-o'
|
: '../resources/icon/icon-star.svg'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,47 +1,24 @@
|
|||||||
.root
|
.root
|
||||||
left 7px
|
top 45px
|
||||||
top 0
|
topBarButtonLight()
|
||||||
padding 0
|
|
||||||
color alpha($ui-favorite-star-button-color, 60%)
|
|
||||||
&:hover
|
&:hover
|
||||||
transition 0.15s
|
transition 0.2s
|
||||||
background-color alpha($ui-button--active-backgroundColor, 40%)
|
color alpha($ui-favorite-star-button-color, 0.6)
|
||||||
color $ui-favorite-star-button-color
|
|
||||||
&:active
|
|
||||||
transition 0.15s
|
|
||||||
background-color alpha($ui-button--active-backgroundColor, 40%)
|
|
||||||
color $ui-favorite-star-button-color
|
|
||||||
|
|
||||||
.root--active
|
.root--active
|
||||||
@extend .root
|
@extend .root
|
||||||
|
transition 0.15s
|
||||||
color $ui-favorite-star-button-color
|
color $ui-favorite-star-button-color
|
||||||
&:hover
|
&:hover
|
||||||
transition 0.15s
|
transition 0.2s
|
||||||
color $ui-favorite-star-button-color
|
color alpha($ui-favorite-star-button-color, 0.6)
|
||||||
background-color alpha($ui-button--active-backgroundColor, 40%)
|
|
||||||
&:active
|
|
||||||
transition 0.15s
|
|
||||||
color $ui-favorite-star-button-color
|
|
||||||
background-color alpha($ui-button--active-backgroundColor, 40%)
|
|
||||||
|
|
||||||
.icon
|
.icon
|
||||||
transition transform 0.15s
|
transition transform 0.15s
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
|
topBarButtonDark()
|
||||||
&:hover
|
&:hover
|
||||||
transition 0.15s
|
transition 0.2s
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
color alpha($ui-favorite-star-button-color, 0.6)
|
||||||
color $ui-favorite-star-button-color
|
|
||||||
&:active
|
|
||||||
transition 0.15s
|
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
|
||||||
color $ui-favorite-star-button-color
|
|
||||||
|
|
||||||
.root--active
|
|
||||||
@extend .root
|
|
||||||
color $ui-favorite-star-button-color
|
|
||||||
&:hover
|
|
||||||
transition 0.15s
|
|
||||||
color $ui-favorite-star-button-color
|
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
|
||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './TagSelect.styl'
|
import styles from './TagSelect.styl'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
@@ -59,7 +60,7 @@ class TagSelect extends React.Component {
|
|||||||
submitTag () {
|
submitTag () {
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_TAG')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_TAG')
|
||||||
let { value } = this.props
|
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) {
|
if (newTag.length <= 0) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -101,9 +102,9 @@ class TagSelect extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { value, className } = this.props
|
const { value, className } = this.props
|
||||||
|
|
||||||
let tagList = _.isArray(value)
|
const tagList = _.isArray(value)
|
||||||
? value.map((tag) => {
|
? value.map((tag) => {
|
||||||
return (
|
return (
|
||||||
<span styleName='tag'
|
<span styleName='tag'
|
||||||
@@ -113,7 +114,7 @@ class TagSelect extends React.Component {
|
|||||||
<button styleName='tag-removeButton'
|
<button styleName='tag-removeButton'
|
||||||
onClick={(e) => this.handleTagRemoveButtonClick(tag)(e)}
|
onClick={(e) => this.handleTagRemoveButtonClick(tag)(e)}
|
||||||
>
|
>
|
||||||
<i className='fa fa-times fa-fw tag-removeButton-icon' />
|
<img className='tag-removeButton-icon' src='../resources/icon/icon-x.svg' width='8px' />
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
.root
|
.root
|
||||||
display inline-block
|
display flex
|
||||||
|
align-items center
|
||||||
user-select none
|
user-select none
|
||||||
height 23px
|
|
||||||
vertical-align middle
|
vertical-align middle
|
||||||
width 300px
|
width 100%
|
||||||
overflow-x scroll
|
overflow-x scroll
|
||||||
white-space nowrap
|
white-space nowrap
|
||||||
|
|
||||||
@@ -11,51 +11,42 @@
|
|||||||
display none
|
display none
|
||||||
|
|
||||||
.tag
|
.tag
|
||||||
display inline-block
|
display flex
|
||||||
margin 1px 3px
|
align-items center
|
||||||
padding 0
|
margin 0px 2px
|
||||||
height 20px
|
padding 2px 4px
|
||||||
background-color alpha($ui-tag-backgroundColor, 10%)
|
background-color alpha($ui-tag-backgroundColor, 3%)
|
||||||
border-radius 3px
|
border-radius 4px
|
||||||
overflow hidden
|
position relative
|
||||||
clearfix()
|
clearfix()
|
||||||
|
|
||||||
.tag-removeButton
|
.tag-removeButton
|
||||||
float right
|
|
||||||
height 20px
|
|
||||||
width 18px
|
|
||||||
margin 0
|
margin 0
|
||||||
padding 0
|
padding 0
|
||||||
border-style solid
|
border-style solid
|
||||||
border-width 0
|
border-width 0
|
||||||
border-radius 20px
|
border-radius 20px
|
||||||
line-height 18px
|
|
||||||
background-color transparent
|
background-color transparent
|
||||||
color $ui-button-color
|
color $ui-button-color
|
||||||
|
position absolute
|
||||||
|
right 6px
|
||||||
|
|
||||||
.tag-removeButton-icon
|
.tag-removeButton-icon
|
||||||
width 5px
|
width 5px
|
||||||
padding-right 4px
|
padding-right 4px
|
||||||
|
|
||||||
.tag-label
|
.tag-label
|
||||||
font-size 11px
|
font-size 13px
|
||||||
font-weight 600
|
color: $ui-text-color
|
||||||
color: alpha($ui-text-color, 80%)
|
padding 4px 16px 4px 8px
|
||||||
float left
|
|
||||||
height 20px
|
|
||||||
line-height 20px
|
|
||||||
padding 0 6px
|
|
||||||
|
|
||||||
.newTag
|
.newTag
|
||||||
display inline-block
|
|
||||||
margin 2px 0 15px 2px
|
|
||||||
vertical-align middle
|
|
||||||
height 18px
|
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
border none
|
border none
|
||||||
background-color transparent
|
background-color transparent
|
||||||
outline none
|
outline none
|
||||||
padding 0 4px
|
padding 0 4px
|
||||||
|
font-size 13px
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.tag
|
.tag
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './TrashButton.styl'
|
import styles from './TrashButton.styl'
|
||||||
|
|
||||||
@@ -8,7 +9,7 @@ const TrashButton = ({
|
|||||||
<button styleName='control-trashButton'
|
<button styleName='control-trashButton'
|
||||||
onClick={(e) => onClick(e)}
|
onClick={(e) => onClick(e)}
|
||||||
>
|
>
|
||||||
<i className='fa fa-trash trashButton' styleName='info-button' />
|
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
.control-trashButton
|
.control-trashButton
|
||||||
float right
|
top 120px
|
||||||
|
margin-bottom 10px
|
||||||
|
topBarButtonLight()
|
||||||
|
|
||||||
|
.control-trashButton--in-trash
|
||||||
|
top 60px
|
||||||
topBarButtonLight()
|
topBarButtonLight()
|
||||||
|
|
||||||
.trashButton
|
.trashButton
|
||||||
padding 0px
|
padding 0px
|
||||||
margin 15px 0
|
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.control-trashButton
|
.control-trashButton
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './Detail.styl'
|
import styles from './Detail.styl'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
@@ -32,12 +33,12 @@ class Detail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { location, data, config } = this.props
|
const { location, data, config } = this.props
|
||||||
let note = null
|
let note = null
|
||||||
if (location.query.key != null) {
|
if (location.query.key != null) {
|
||||||
let splitted = location.query.key.split('-')
|
const splitted = location.query.key.split('-')
|
||||||
let storageKey = splitted.shift()
|
const storageKey = splitted.shift()
|
||||||
let noteKey = splitted.shift()
|
const noteKey = splitted.shift()
|
||||||
|
|
||||||
note = data.noteMap.get(storageKey + '-' + noteKey)
|
note = data.noteMap.get(storageKey + '-' + noteKey)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './Main.styl'
|
import styles from './Main.styl'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
@@ -11,14 +12,9 @@ import _ from 'lodash'
|
|||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import modal from 'browser/main/lib/modal'
|
import modal from 'browser/main/lib/modal'
|
||||||
import InitModal from 'browser/main/modals/InitModal'
|
import InitModal from 'browser/main/modals/InitModal'
|
||||||
import mixpanel from 'browser/main/lib/mixpanel'
|
|
||||||
import mobileAnalytics from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import mobileAnalytics from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||||
|
|
||||||
function focused () {
|
|
||||||
mixpanel.track('MAIN_FOCUSED')
|
|
||||||
}
|
|
||||||
|
|
||||||
class Main extends React.Component {
|
class Main extends React.Component {
|
||||||
|
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
@@ -28,7 +24,7 @@ class Main extends React.Component {
|
|||||||
mobileAnalytics.initAwsMobileAnalytics()
|
mobileAnalytics.initAwsMobileAnalytics()
|
||||||
}
|
}
|
||||||
|
|
||||||
let { config } = props
|
const { config } = props
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isRightSliderFocused: false,
|
isRightSliderFocused: false,
|
||||||
@@ -44,7 +40,7 @@ class Main extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getChildContext () {
|
getChildContext () {
|
||||||
let { status, config } = this.props
|
const { status, config } = this.props
|
||||||
|
|
||||||
return {
|
return {
|
||||||
status,
|
status,
|
||||||
@@ -53,10 +49,12 @@ class Main extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
let { dispatch, config } = this.props
|
const { dispatch, config } = this.props
|
||||||
|
|
||||||
if (config.ui.theme === 'dark') {
|
if (config.ui.theme === 'dark') {
|
||||||
document.body.setAttribute('data-theme', 'dark')
|
document.body.setAttribute('data-theme', 'dark')
|
||||||
|
} else if (config.ui.theme === 'white') {
|
||||||
|
document.body.setAttribute('data-theme', 'white')
|
||||||
} else {
|
} else {
|
||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
@@ -76,11 +74,9 @@ class Main extends React.Component {
|
|||||||
})
|
})
|
||||||
|
|
||||||
eventEmitter.on('editor:fullscreen', this.toggleFullScreen)
|
eventEmitter.on('editor:fullscreen', this.toggleFullScreen)
|
||||||
window.addEventListener('focus', focused)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
window.removeEventListener('focus', focused)
|
|
||||||
eventEmitter.off('editor:fullscreen', this.toggleFullScreen)
|
eventEmitter.off('editor:fullscreen', this.toggleFullScreen)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +100,8 @@ class Main extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
isRightSliderFocused: false
|
isRightSliderFocused: false
|
||||||
}, () => {
|
}, () => {
|
||||||
let { dispatch } = this.props
|
const { dispatch } = this.props
|
||||||
let newListWidth = this.state.listWidth
|
const newListWidth = this.state.listWidth
|
||||||
// TODO: ConfigManager should dispatch itself.
|
// TODO: ConfigManager should dispatch itself.
|
||||||
ConfigManager.set({listWidth: newListWidth})
|
ConfigManager.set({listWidth: newListWidth})
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -120,8 +116,8 @@ class Main extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
isLeftSliderFocused: false
|
isLeftSliderFocused: false
|
||||||
}, () => {
|
}, () => {
|
||||||
let { dispatch } = this.props
|
const { dispatch } = this.props
|
||||||
let navWidth = this.state.navWidth
|
const navWidth = this.state.navWidth
|
||||||
// TODO: ConfigManager should dispatch itself.
|
// TODO: ConfigManager should dispatch itself.
|
||||||
ConfigManager.set({ navWidth })
|
ConfigManager.set({ navWidth })
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -134,7 +130,7 @@ class Main extends React.Component {
|
|||||||
|
|
||||||
handleMouseMove (e) {
|
handleMouseMove (e) {
|
||||||
if (this.state.isRightSliderFocused) {
|
if (this.state.isRightSliderFocused) {
|
||||||
let offset = this.refs.body.getBoundingClientRect().left
|
const offset = this.refs.body.getBoundingClientRect().left
|
||||||
let newListWidth = e.pageX - offset
|
let newListWidth = e.pageX - offset
|
||||||
if (newListWidth < 10) {
|
if (newListWidth < 10) {
|
||||||
newListWidth = 10
|
newListWidth = 10
|
||||||
@@ -187,7 +183,7 @@ class Main extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { config } = this.props
|
const { config } = this.props
|
||||||
|
|
||||||
// the width of the navigation bar when it is folded/collapsed
|
// the width of the navigation bar when it is folded/collapsed
|
||||||
const foldedNavigationWidth = 44
|
const foldedNavigationWidth = 44
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ $control-height = 34px
|
|||||||
opacity 0
|
opacity 0
|
||||||
transition 0.1s
|
transition 0.1s
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.root, .root--expanded
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control-newNoteButton
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root, .root--expanded
|
.root, .root--expanded
|
||||||
background-color $ui-dark-noteList-backgroundColor
|
background-color $ui-dark-noteList-backgroundColor
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './NewNoteButton.styl'
|
import styles from './NewNoteButton.styl'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import modal from 'browser/main/lib/modal'
|
import modal from 'browser/main/lib/modal'
|
||||||
import NewNoteModal from 'browser/main/modals/NewNoteModal'
|
import NewNoteModal from 'browser/main/modals/NewNoteModal'
|
||||||
import { hashHistory } from 'react-router'
|
|
||||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { dialog } = remote
|
const { dialog } = remote
|
||||||
@@ -34,7 +33,7 @@ class NewNoteButton extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleNewNoteButtonClick (e) {
|
handleNewNoteButtonClick (e) {
|
||||||
const { config, location, dispatch } = this.props
|
const { location, dispatch } = this.props
|
||||||
const { storage, folder } = this.resolveTargetFolder()
|
const { storage, folder } = this.resolveTargetFolder()
|
||||||
|
|
||||||
modal.open(NewNoteModal, {
|
modal.open(NewNoteModal, {
|
||||||
@@ -51,7 +50,7 @@ class NewNoteButton extends React.Component {
|
|||||||
|
|
||||||
// Find first storage
|
// Find first storage
|
||||||
if (storage == null) {
|
if (storage == null) {
|
||||||
for (let kv of data.storageMap) {
|
for (const kv of data.storageMap) {
|
||||||
storage = kv[1]
|
storage = kv[1]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -85,7 +84,7 @@ class NewNoteButton extends React.Component {
|
|||||||
<div styleName='control'>
|
<div styleName='control'>
|
||||||
<button styleName='control-newNoteButton'
|
<button styleName='control-newNoteButton'
|
||||||
onClick={(e) => this.handleNewNoteButtonClick(e)}>
|
onClick={(e) => this.handleNewNoteButtonClick(e)}>
|
||||||
<i className='fa fa-pencil-square-o' />
|
<img styleName='iconTag' src='../resources/icon/icon-newnote.svg' />
|
||||||
<span styleName='control-newNoteButton-tooltip'>
|
<span styleName='control-newNoteButton-tooltip'>
|
||||||
Make a Note {OSX ? '⌘' : '^'} + n
|
Make a Note {OSX ? '⌘' : '^'} + n
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -21,14 +21,14 @@ $control-height = 30px
|
|||||||
|
|
||||||
.control-sortBy-select
|
.control-sortBy-select
|
||||||
appearance: none;
|
appearance: none;
|
||||||
margin-left 3px
|
margin-left 5px
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
padding 0
|
padding 0
|
||||||
border none
|
border none
|
||||||
background-color transparent
|
background-color transparent
|
||||||
outline none
|
outline none
|
||||||
cursor pointer
|
cursor pointer
|
||||||
font-size 11px
|
font-size 12px
|
||||||
&:hover
|
&:hover
|
||||||
transition 0.2s
|
transition 0.2s
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
@@ -59,6 +59,13 @@ $control-height = 30px
|
|||||||
top $control-height
|
top $control-height
|
||||||
overflow auto
|
overflow auto
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.root
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.root
|
.root
|
||||||
absolute top left bottom
|
absolute top left bottom
|
||||||
width $sideNav-width
|
width $sideNav-width
|
||||||
background-color #f9f9f9
|
background-color #2E3235
|
||||||
user-select none
|
user-select none
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
height: 100vh
|
height: 100vh
|
||||||
@@ -11,24 +11,25 @@
|
|||||||
.top
|
.top
|
||||||
padding-bottom 15px
|
padding-bottom 15px
|
||||||
|
|
||||||
.top-menu
|
.top-menu-preference
|
||||||
navButtonColor()
|
navButtonColor()
|
||||||
position absolute
|
position absolute
|
||||||
top 22px
|
top 22px
|
||||||
right 5px
|
right 10px
|
||||||
height 23px
|
|
||||||
width 2em
|
width 2em
|
||||||
|
background-color transparent
|
||||||
&:hover
|
&:hover
|
||||||
color $ui-text-color
|
color $ui-button-default--active-backgroundColor
|
||||||
|
background-color transparent
|
||||||
&:active, &:active:hover
|
&:active, &:active:hover
|
||||||
color $ui-text-color
|
color $ui-button-default--active-backgroundColor
|
||||||
background-color alpha($ui-button--active-backgroundColor, 20%)
|
|
||||||
|
|
||||||
.switch-buttons
|
.switch-buttons
|
||||||
background-color transparent
|
background-color transparent
|
||||||
border 0
|
border 0
|
||||||
height 25px
|
margin 24px auto 4px 14px
|
||||||
margin 20px auto 0px 8px
|
display flex
|
||||||
|
text-align center
|
||||||
|
|
||||||
.non-active-button
|
.non-active-button
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
@@ -36,12 +37,15 @@
|
|||||||
border 0
|
border 0
|
||||||
background-color transparent
|
background-color transparent
|
||||||
transition 0.2s
|
transition 0.2s
|
||||||
|
display flex
|
||||||
|
text-align center
|
||||||
|
margin-right 4px;
|
||||||
&:hover
|
&:hover
|
||||||
color alpha(#0B99F1, 60%)
|
color alpha(#239F86, 60%)
|
||||||
|
|
||||||
.active-button
|
.active-button
|
||||||
@extend .non-active-button
|
@extend .non-active-button
|
||||||
color #0B99F1
|
color $ui-button-default--active-backgroundColor
|
||||||
|
|
||||||
.top-menu-label
|
.top-menu-label
|
||||||
margin-left 5px
|
margin-left 5px
|
||||||
@@ -57,7 +61,7 @@
|
|||||||
padding-left 15px
|
padding-left 15px
|
||||||
padding-bottom 13px
|
padding-bottom 13px
|
||||||
p
|
p
|
||||||
color $ui-text-color
|
color $ui-button-default-color
|
||||||
|
|
||||||
.tagList
|
.tagList
|
||||||
overflow-y auto
|
overflow-y auto
|
||||||
@@ -66,6 +70,7 @@
|
|||||||
.root--folded
|
.root--folded
|
||||||
height 100vh
|
height 100vh
|
||||||
width $sideNav--folded-width
|
width $sideNav--folded-width
|
||||||
|
background-color #2E3235
|
||||||
.switch-buttons
|
.switch-buttons
|
||||||
display none
|
display none
|
||||||
.top
|
.top
|
||||||
@@ -88,7 +93,6 @@
|
|||||||
opacity 0
|
opacity 0
|
||||||
margin-left 0
|
margin-left 0
|
||||||
overflow hidden
|
overflow hidden
|
||||||
background-color $ui-tooltip-backgroundColor
|
|
||||||
z-index 10
|
z-index 10
|
||||||
color white
|
color white
|
||||||
line-height 30px
|
line-height 30px
|
||||||
@@ -96,6 +100,41 @@
|
|||||||
border-bottom-right-radius 2px
|
border-bottom-right-radius 2px
|
||||||
pointer-events none
|
pointer-events none
|
||||||
font-size 13px
|
font-size 13px
|
||||||
|
.top-menu-preference
|
||||||
|
position absolute
|
||||||
|
left 11px
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.root, .root--folded
|
||||||
|
background-color #f9f9f9
|
||||||
|
color $ui-text-color
|
||||||
|
|
||||||
|
.top-menu-preference
|
||||||
|
navWhiteButtonColor()
|
||||||
|
background-color transparent
|
||||||
|
&:hover
|
||||||
|
color #0B99F1
|
||||||
|
background-color transparent
|
||||||
|
&:active, &:active:hover
|
||||||
|
color #0B99F1
|
||||||
|
background-color transparent
|
||||||
|
|
||||||
|
.non-active-button
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
&:hover
|
||||||
|
color alpha(#0B99F1, 60%)
|
||||||
|
|
||||||
|
.tag-title
|
||||||
|
p
|
||||||
|
color $ui-text-color
|
||||||
|
|
||||||
|
.non-active-button
|
||||||
|
&:hover
|
||||||
|
color alpha(#0B99F1, 60%)
|
||||||
|
|
||||||
|
.active-button
|
||||||
|
@extend .non-active-button
|
||||||
|
color #0B99F1
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root, .root--folded
|
.root, .root--folded
|
||||||
@@ -106,12 +145,15 @@ body[data-theme="dark"]
|
|||||||
.top
|
.top
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
|
|
||||||
.top-menu
|
.top-menu-preference
|
||||||
navDarkButtonColor()
|
navDarkButtonColor()
|
||||||
|
background-color transparent
|
||||||
&:active
|
&:active
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
||||||
|
background-color transparent
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
||||||
|
background-color transparent
|
||||||
|
|
||||||
.non-active-button
|
.non-active-button
|
||||||
color alpha($ui-dark-text-color, 60%)
|
color alpha($ui-dark-text-color, 60%)
|
||||||
|
|||||||
@@ -5,27 +5,23 @@
|
|||||||
|
|
||||||
.header
|
.header
|
||||||
position relative
|
position relative
|
||||||
height 25px
|
height 36px
|
||||||
width 100%
|
width 100%
|
||||||
margin-bottom 5px
|
margin-bottom 5px
|
||||||
transition 0.15s
|
transition 0.15s
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
|
||||||
.header--active
|
.header--active
|
||||||
margin-bottom 5px
|
margin-bottom 5px
|
||||||
background-color $ui-button--active-backgroundColor
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
transition color background-color 0.15s
|
transition color background-color 0.15s
|
||||||
|
display flex
|
||||||
.header--active
|
align-items center
|
||||||
.header-toggleButton
|
.header-toggleButton
|
||||||
color $ui-text-color
|
|
||||||
|
|
||||||
.header--active
|
|
||||||
.header-info
|
.header-info
|
||||||
color $ui-text-color
|
|
||||||
|
|
||||||
.header--active
|
|
||||||
.header-addFolderButton
|
.header-addFolderButton
|
||||||
color $ui-text-color
|
color #1EC38B
|
||||||
|
|
||||||
.header-toggleButton
|
.header-toggleButton
|
||||||
navButtonColor()
|
navButtonColor()
|
||||||
@@ -38,23 +34,31 @@
|
|||||||
border-radius 50%
|
border-radius 50%
|
||||||
&:hover
|
&:hover
|
||||||
transition 0.2s
|
transition 0.2s
|
||||||
background-color alpha($ui-button--active-backgroundColor, 40%)
|
background-color alpha($ui-button-default--hover-backgroundColor, 40%)
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
|
|
||||||
.header-info
|
.header-info
|
||||||
navButtonColor()
|
navButtonColor()
|
||||||
display block
|
display block
|
||||||
width 100%
|
width 100%
|
||||||
height 25px
|
height 36px
|
||||||
padding-left 23px
|
padding-left 25px
|
||||||
padding-right 10px
|
padding-right 15px
|
||||||
line-height 22px
|
line-height 22px
|
||||||
cursor pointer
|
cursor pointer
|
||||||
font-size 13px
|
font-size 14px
|
||||||
border none
|
border none
|
||||||
overflow ellipsis
|
overflow ellipsis
|
||||||
text-align left
|
text-align left
|
||||||
background-color alpha($ui-button--active-backgroundColor, 20%)
|
font-weight 600;
|
||||||
|
background-color transparent
|
||||||
|
&:hover
|
||||||
|
color #1EC38B
|
||||||
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
|
transition background-color 0.15s
|
||||||
|
&:active, &:active:hover
|
||||||
|
color #1EC38B
|
||||||
|
background-color alpha($ui-button-default--active-backgroundColor, 20%)
|
||||||
|
|
||||||
.header-info-path
|
.header-info-path
|
||||||
font-size 10px
|
font-size 10px
|
||||||
@@ -63,17 +67,14 @@
|
|||||||
.header-addFolderButton
|
.header-addFolderButton
|
||||||
navButtonColor()
|
navButtonColor()
|
||||||
position absolute
|
position absolute
|
||||||
right 0
|
right 7px
|
||||||
width 25px
|
width 25px
|
||||||
height 25px
|
height 25px
|
||||||
padding 0
|
padding 0
|
||||||
border none
|
border none
|
||||||
margin-right 5px
|
|
||||||
border-radius 50%
|
border-radius 50%
|
||||||
&:hover
|
&:hover
|
||||||
transition 0.2s
|
transition 0.2s
|
||||||
background-color alpha($ui-button--active-backgroundColor, 40%)
|
|
||||||
color $ui-text-color
|
|
||||||
|
|
||||||
.root--folded
|
.root--folded
|
||||||
@extend .root
|
@extend .root
|
||||||
@@ -102,6 +103,33 @@
|
|||||||
font-size 10px
|
font-size 10px
|
||||||
margin 0 5px
|
margin 0 5px
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.header--active
|
||||||
|
background-color $ui-button--active-backgroundColor
|
||||||
|
transition color background-color 0.15s
|
||||||
|
.header-toggleButton
|
||||||
|
color $ui-text-color
|
||||||
|
.header-info
|
||||||
|
color $ui-text-color
|
||||||
|
.header-addFolderButton
|
||||||
|
color $ui-text-color
|
||||||
|
|
||||||
|
.header-toggleButton
|
||||||
|
navWhiteButtonColor()
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 40%)
|
||||||
|
color $ui-text-color
|
||||||
|
|
||||||
|
.header-info
|
||||||
|
navWhiteButtonColor()
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 20%)
|
||||||
|
|
||||||
|
.header-addFolderButton
|
||||||
|
navWhiteButtonColor()
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-button--active-backgroundColor, 40%)
|
||||||
|
color $ui-text-color
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.header--active
|
.header--active
|
||||||
background-color $ui-dark-button--active-backgroundColor
|
background-color $ui-dark-button--active-backgroundColor
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './SideNav.styl'
|
import styles from './SideNav.styl'
|
||||||
import { openModal } from 'browser/main/lib/modal'
|
import { openModal } from 'browser/main/lib/modal'
|
||||||
@@ -9,25 +10,35 @@ import TagListItem from 'browser/components/TagListItem'
|
|||||||
import SideNavFilter from 'browser/components/SideNavFilter'
|
import SideNavFilter from 'browser/components/SideNavFilter'
|
||||||
import StorageList from 'browser/components/StorageList'
|
import StorageList from 'browser/components/StorageList'
|
||||||
import NavToggleButton from 'browser/components/NavToggleButton'
|
import NavToggleButton from 'browser/components/NavToggleButton'
|
||||||
|
import EventEmitter from 'browser/main/lib/eventEmitter'
|
||||||
|
|
||||||
class SideNav extends React.Component {
|
class SideNav extends React.Component {
|
||||||
// TODO: should not use electron stuff v0.7
|
// TODO: should not use electron stuff v0.7
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
EventEmitter.on('side:preferences', this.handleMenuButtonClick)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount () {
|
||||||
|
EventEmitter.off('side:preferences', this.handleMenuButtonClick)
|
||||||
|
}
|
||||||
|
|
||||||
handleMenuButtonClick (e) {
|
handleMenuButtonClick (e) {
|
||||||
openModal(PreferencesModal)
|
openModal(PreferencesModal)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHomeButtonClick (e) {
|
handleHomeButtonClick (e) {
|
||||||
let { router } = this.context
|
const { router } = this.context
|
||||||
router.push('/home')
|
router.push('/home')
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStarredButtonClick (e) {
|
handleStarredButtonClick (e) {
|
||||||
let { router } = this.context
|
const { router } = this.context
|
||||||
router.push('/starred')
|
router.push('/starred')
|
||||||
}
|
}
|
||||||
|
|
||||||
handleToggleButtonClick (e) {
|
handleToggleButtonClick (e) {
|
||||||
let { dispatch, config } = this.props
|
const { dispatch, config } = this.props
|
||||||
|
|
||||||
ConfigManager.set({isSideNavFolded: !config.isSideNavFolded})
|
ConfigManager.set({isSideNavFolded: !config.isSideNavFolded})
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -37,7 +48,7 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleTrashedButtonClick (e) {
|
handleTrashedButtonClick (e) {
|
||||||
let { router } = this.context
|
const { router } = this.context
|
||||||
router.push('/trashed')
|
router.push('/trashed')
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +63,7 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SideNavComponent (isFolded, storageList) {
|
SideNavComponent (isFolded, storageList) {
|
||||||
let { location, data } = this.props
|
const { location, data } = this.props
|
||||||
|
|
||||||
const isHomeActive = !!location.pathname.match(/^\/home$/)
|
const isHomeActive = !!location.pathname.match(/^\/home$/)
|
||||||
const isStarredActive = !!location.pathname.match(/^\/starred$/)
|
const isStarredActive = !!location.pathname.match(/^\/starred$/)
|
||||||
@@ -72,6 +83,9 @@ class SideNav extends React.Component {
|
|||||||
isTrashedActive={isTrashedActive}
|
isTrashedActive={isTrashedActive}
|
||||||
handleStarredButtonClick={(e) => this.handleStarredButtonClick(e)}
|
handleStarredButtonClick={(e) => this.handleStarredButtonClick(e)}
|
||||||
handleTrashedButtonClick={(e) => this.handleTrashedButtonClick(e)}
|
handleTrashedButtonClick={(e) => this.handleTrashedButtonClick(e)}
|
||||||
|
counterTotalNote={data.noteMap._map.size}
|
||||||
|
counterStarredNote={data.starredSet._set.size}
|
||||||
|
counterDelNote={data.trashedSet._set.size}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<StorageList storageList={storageList} />
|
<StorageList storageList={storageList} />
|
||||||
@@ -96,7 +110,7 @@ class SideNav extends React.Component {
|
|||||||
|
|
||||||
tagListComponent () {
|
tagListComponent () {
|
||||||
const { data, location } = this.props
|
const { data, location } = this.props
|
||||||
let tagList = data.tagNoteMap.map((tag, key) => {
|
const tagList = data.tagNoteMap.map((tag, key) => {
|
||||||
return key
|
return key
|
||||||
})
|
})
|
||||||
return (
|
return (
|
||||||
@@ -123,11 +137,11 @@ class SideNav extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
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
|
return <StorageItem
|
||||||
key={storage.key}
|
key={storage.key}
|
||||||
storage={storage}
|
storage={storage}
|
||||||
@@ -137,7 +151,7 @@ class SideNav extends React.Component {
|
|||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
let style = {}
|
const style = {}
|
||||||
if (!isFolded) style.width = this.props.width
|
if (!isFolded) style.width = this.props.width
|
||||||
const isTagActive = location.pathname.match(/tag/)
|
const isTagActive = location.pathname.match(/tag/)
|
||||||
return (
|
return (
|
||||||
@@ -148,15 +162,26 @@ class SideNav extends React.Component {
|
|||||||
>
|
>
|
||||||
<div styleName='top'>
|
<div styleName='top'>
|
||||||
<div styleName='switch-buttons'>
|
<div styleName='switch-buttons'>
|
||||||
<button styleName={isTagActive ? 'non-active-button' : 'active-button'} onClick={this.handleSwitchFoldersButtonClick.bind(this)}><i className='fa fa-folder fa-fw' /></button>
|
<button styleName={isTagActive ? 'non-active-button' : 'active-button'} onClick={this.handleSwitchFoldersButtonClick.bind(this)}>
|
||||||
<button styleName={isTagActive ? 'active-button' : 'non-active-button'} onClick={this.handleSwitchTagsButtonClick.bind(this)}><i className='fa fa-tags fa-fw' /></button>
|
<img src={isTagActive
|
||||||
|
? '../resources/icon/icon-list.svg'
|
||||||
|
: '../resources/icon/icon-list-active.svg'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
<button styleName={isTagActive ? 'active-button' : 'non-active-button'} onClick={this.handleSwitchTagsButtonClick.bind(this)}>
|
||||||
|
<img src={isTagActive
|
||||||
|
? '../resources/icon/icon-tag-active.svg'
|
||||||
|
: '../resources/icon/icon-tag.svg'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button styleName='top-menu'
|
<button styleName='top-menu-preference'
|
||||||
onClick={(e) => this.handleMenuButtonClick(e)}
|
onClick={(e) => this.handleMenuButtonClick(e)}
|
||||||
>
|
>
|
||||||
<i className='fa fa-wrench fa-fw' />
|
<img styleName='iconTag' src='../resources/icon/icon-setting.svg' />
|
||||||
<span styleName='top-menu-label'>Preferences</span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
@import('../Detail/DetailVars')
|
@import('../Detail/DetailVars')
|
||||||
|
|
||||||
.root
|
.root
|
||||||
absolute bottom left right
|
position absolute
|
||||||
|
bottom 10px
|
||||||
|
right 10px
|
||||||
z-index 100
|
z-index 100
|
||||||
background-color $ui-noteDetail-backgroundColor
|
|
||||||
display flex
|
display flex
|
||||||
|
|
||||||
.blank
|
.blank
|
||||||
@@ -21,7 +22,18 @@
|
|||||||
|
|
||||||
.zoom
|
.zoom
|
||||||
navButtonColor()
|
navButtonColor()
|
||||||
height 24px
|
color rgba(0,0,0,.54)
|
||||||
|
height 20px
|
||||||
|
display flex
|
||||||
|
padding 0
|
||||||
|
align-items center
|
||||||
|
background-color transparent
|
||||||
|
&:hover
|
||||||
|
color $ui-active-color
|
||||||
|
&:active
|
||||||
|
color $ui-active-color
|
||||||
|
span
|
||||||
|
margin-left 5px
|
||||||
|
|
||||||
.update
|
.update
|
||||||
navButtonColor()
|
navButtonColor()
|
||||||
@@ -37,14 +49,14 @@
|
|||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
background-color $ui-dark-noteDetail-backgroundColor
|
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
box-shadow none
|
box-shadow none
|
||||||
|
|
||||||
.zoom
|
.zoom
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
|
background-color transparent
|
||||||
|
color #f9f9f9
|
||||||
&:hover
|
&:hover
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
|
||||||
transition 0.15s
|
transition 0.15s
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './StatusBar.styl'
|
import styles from './StatusBar.styl'
|
||||||
import ZoomManager from 'browser/main/lib/ZoomManager'
|
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 {
|
class StatusBar extends React.Component {
|
||||||
updateApp () {
|
updateApp () {
|
||||||
let index = dialog.showMessageBox(remote.getCurrentWindow(), {
|
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: 'Update Boostnote',
|
message: 'Update Boostnote',
|
||||||
detail: 'New Boostnote is ready to be installed.',
|
detail: 'New Boostnote is ready to be installed.',
|
||||||
@@ -24,7 +25,7 @@ class StatusBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleZoomButtonClick (e) {
|
handleZoomButtonClick (e) {
|
||||||
let menu = new Menu()
|
const menu = new Menu()
|
||||||
|
|
||||||
zoomOptions.forEach((zoom) => {
|
zoomOptions.forEach((zoom) => {
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
@@ -37,7 +38,7 @@ class StatusBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleZoomMenuItemClick (zoomFactor) {
|
handleZoomMenuItemClick (zoomFactor) {
|
||||||
let { dispatch } = this.props
|
const { dispatch } = this.props
|
||||||
ZoomManager.setZoom(zoomFactor)
|
ZoomManager.setZoom(zoomFactor)
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'SET_ZOOM',
|
type: 'SET_ZOOM',
|
||||||
@@ -46,7 +47,7 @@ class StatusBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { config, status } = this.context
|
const { config, status } = this.context
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='StatusBar'
|
<div className='StatusBar'
|
||||||
@@ -55,8 +56,8 @@ class StatusBar extends React.Component {
|
|||||||
<button styleName='zoom'
|
<button styleName='zoom'
|
||||||
onClick={(e) => this.handleZoomButtonClick(e)}
|
onClick={(e) => this.handleZoomButtonClick(e)}
|
||||||
>
|
>
|
||||||
<i className='fa fa-search-plus' />
|
<img src='../resources/icon/icon-zoom.svg' />
|
||||||
{Math.floor(config.zoom * 100)}%
|
<span>{Math.floor(config.zoom * 100)}%</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{status.updateReady
|
{status.updateReady
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ $control-height = 34px
|
|||||||
outline none
|
outline none
|
||||||
border none
|
border none
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
font-size 16px
|
font-size 18px
|
||||||
padding-bottom 2px
|
padding-bottom 2px
|
||||||
background-color $ui-noteList-backgroundColor
|
background-color $ui-noteList-backgroundColor
|
||||||
|
|
||||||
@@ -112,6 +112,21 @@ $control-height = 34px
|
|||||||
opacity 0
|
opacity 0
|
||||||
transition 0.1s
|
transition 0.1s
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.root, .root--expanded
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control
|
||||||
|
border-color $ui-dark-borderColor
|
||||||
|
|
||||||
|
.control-search
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control-search-input
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
input
|
||||||
|
background-color $ui-white-noteList-backgroundColor
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root, .root--expanded
|
.root, .root--expanded
|
||||||
background-color $ui-dark-noteList-backgroundColor
|
background-color $ui-dark-noteList-backgroundColor
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './TopBar.styl'
|
import styles from './TopBar.styl'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import NewNoteModal from 'browser/main/modals/NewNoteModal'
|
|
||||||
import ee from 'browser/main/lib/eventEmitter'
|
import ee from 'browser/main/lib/eventEmitter'
|
||||||
import NewNoteButton from 'browser/main/NewNoteButton'
|
import NewNoteButton from 'browser/main/NewNoteButton'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
|
||||||
const { dialog } = remote
|
|
||||||
|
|
||||||
const OSX = window.process.platform === 'darwin'
|
|
||||||
|
|
||||||
class TopBar extends React.Component {
|
class TopBar extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
@@ -121,7 +116,7 @@ class TopBar extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let { config, style, data, location } = this.props
|
const { config, style, location } = this.props
|
||||||
return (
|
return (
|
||||||
<div className='TopBar'
|
<div className='TopBar'
|
||||||
styleName={config.isSideNavFolded ? 'root--expanded' : 'root'}
|
styleName={config.isSideNavFolded ? 'root--expanded' : 'root'}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ body
|
|||||||
color textColor
|
color textColor
|
||||||
font-size fontSize
|
font-size fontSize
|
||||||
font-weight 200
|
font-weight 200
|
||||||
|
-webkit-font-smoothing antialiased
|
||||||
|
|
||||||
button, input, select, textarea
|
button, input, select, textarea
|
||||||
font-family DEFAULT_FONTS
|
font-family DEFAULT_FONTS
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ document.addEventListener('click', function (e) {
|
|||||||
if (infoPanel) infoPanel.style.display = 'none'
|
if (infoPanel) infoPanel.style.display = 'none'
|
||||||
})
|
})
|
||||||
|
|
||||||
let el = document.getElementById('content')
|
const el = document.getElementById('content')
|
||||||
const history = syncHistoryWithStore(hashHistory, store)
|
const history = syncHistoryWithStore(hashHistory, store)
|
||||||
|
|
||||||
function notify (...args) {
|
function notify (...args) {
|
||||||
@@ -44,7 +44,7 @@ function notify (...args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateApp () {
|
function updateApp () {
|
||||||
let index = dialog.showMessageBox(remote.getCurrentWindow(), {
|
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
message: 'Update Boostnote',
|
message: 'Update Boostnote',
|
||||||
detail: 'New Boostnote is ready to be installed.',
|
detail: 'New Boostnote is ready to be installed.',
|
||||||
@@ -81,7 +81,7 @@ ReactDOM.render((
|
|||||||
</Router>
|
</Router>
|
||||||
</Provider>
|
</Provider>
|
||||||
), el, function () {
|
), el, function () {
|
||||||
let loadingCover = document.getElementById('loadingCover')
|
const loadingCover = document.getElementById('loadingCover')
|
||||||
loadingCover.parentNode.removeChild(loadingCover)
|
loadingCover.parentNode.removeChild(loadingCover)
|
||||||
|
|
||||||
ipcRenderer.on('update-ready', function () {
|
ipcRenderer.on('update-ready', function () {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ const ConfigManager = require('browser/main/lib/ConfigManager')
|
|||||||
|
|
||||||
const remote = require('electron').remote
|
const remote = require('electron').remote
|
||||||
const os = require('os')
|
const os = require('os')
|
||||||
|
let mobileAnalyticsClient
|
||||||
|
|
||||||
AWS.config.region = 'us-east-1'
|
AWS.config.region = 'us-east-1'
|
||||||
if (process.env.NODE_ENV === 'production' && ConfigManager.default.get().amaEnabled) {
|
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 validPlatformName = convertPlatformName(os.platform())
|
||||||
|
|
||||||
const mobileAnalyticsClient = new AMA.Manager({
|
mobileAnalyticsClient = new AMA.Manager({
|
||||||
appId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
|
appId: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
|
||||||
appTitle: 'xxxxxxxxxx',
|
appTitle: 'xxxxxxxxxx',
|
||||||
appVersionName: remote.app.getVersion().toString(),
|
appVersionName: remote.app.getVersion().toString(),
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ function release (el) {
|
|||||||
|
|
||||||
function fire (command) {
|
function fire (command) {
|
||||||
console.info('COMMAND >>', command)
|
console.info('COMMAND >>', command)
|
||||||
let splitted = command.split(':')
|
const splitted = command.split(':')
|
||||||
let target = splitted[0]
|
const target = splitted[0]
|
||||||
let targetCommand = splitted[1]
|
const targetCommand = splitted[1]
|
||||||
let targetCallees = callees
|
const targetCallees = callees
|
||||||
.filter((callee) => callee.name === target)
|
.filter((callee) => callee.name === target)
|
||||||
|
|
||||||
targetCallees.forEach((callee) => {
|
targetCallees.forEach((callee) => {
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ const win = global.process.platform === 'win32'
|
|||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const { ipcRenderer } = electron
|
const { ipcRenderer } = electron
|
||||||
const consts = require('browser/lib/consts')
|
const consts = require('browser/lib/consts')
|
||||||
const path = require('path')
|
|
||||||
const fs = require('fs')
|
|
||||||
|
|
||||||
let isInitialized = false
|
let isInitialized = false
|
||||||
|
|
||||||
@@ -91,21 +89,27 @@ function get () {
|
|||||||
: 'default'
|
: 'default'
|
||||||
|
|
||||||
if (config.editor.theme !== 'default') {
|
if (config.editor.theme !== 'default') {
|
||||||
|
if (config.editor.theme.startsWith('solarized')) {
|
||||||
|
editorTheme.setAttribute('href', '../node_modules/codemirror/theme/solarized.css')
|
||||||
|
} else {
|
||||||
editorTheme.setAttribute('href', '../node_modules/codemirror/theme/' + config.editor.theme + '.css')
|
editorTheme.setAttribute('href', '../node_modules/codemirror/theme/' + config.editor.theme + '.css')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
function set (updates) {
|
function set (updates) {
|
||||||
let currentConfig = get()
|
const currentConfig = get()
|
||||||
let newConfig = Object.assign({}, DEFAULT_CONFIG, currentConfig, updates)
|
const newConfig = Object.assign({}, DEFAULT_CONFIG, currentConfig, updates)
|
||||||
if (!validate(newConfig)) throw new Error('INVALID CONFIG')
|
if (!validate(newConfig)) throw new Error('INVALID CONFIG')
|
||||||
_save(newConfig)
|
_save(newConfig)
|
||||||
|
|
||||||
if (newConfig.ui.theme === 'dark') {
|
if (newConfig.ui.theme === 'dark') {
|
||||||
document.body.setAttribute('data-theme', 'dark')
|
document.body.setAttribute('data-theme', 'dark')
|
||||||
|
} else if (newConfig.ui.theme === 'white') {
|
||||||
|
document.body.setAttribute('data-theme', 'white')
|
||||||
} else {
|
} else {
|
||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
@@ -117,13 +121,17 @@ function set (updates) {
|
|||||||
editorTheme.setAttribute('rel', 'stylesheet')
|
editorTheme.setAttribute('rel', 'stylesheet')
|
||||||
document.head.appendChild(editorTheme)
|
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
|
? newConfig.editor.theme
|
||||||
: 'default'
|
: 'default'
|
||||||
|
|
||||||
if (newTheme !== 'default') {
|
if (newTheme !== 'default') {
|
||||||
|
if (newTheme.startsWith('solarized')) {
|
||||||
|
editorTheme.setAttribute('href', '../node_modules/codemirror/theme/solarized.css')
|
||||||
|
} else {
|
||||||
editorTheme.setAttribute('href', '../node_modules/codemirror/theme/' + newTheme + '.css')
|
editorTheme.setAttribute('href', '../node_modules/codemirror/theme/' + newTheme + '.css')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ipcRenderer.send('config-renew', {
|
ipcRenderer.send('config-renew', {
|
||||||
config: get()
|
config: get()
|
||||||
@@ -131,7 +139,7 @@ function set (updates) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function assignConfigValues (originalConfig, rcConfig) {
|
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.hotkey = Object.assign({}, DEFAULT_CONFIG.hotkey, originalConfig.hotkey, rcConfig.hotkey)
|
||||||
config.ui = Object.assign({}, DEFAULT_CONFIG.ui, originalConfig.ui, rcConfig.ui)
|
config.ui = Object.assign({}, DEFAULT_CONFIG.ui, originalConfig.ui, rcConfig.ui)
|
||||||
config.editor = Object.assign({}, DEFAULT_CONFIG.editor, originalConfig.editor, rcConfig.editor)
|
config.editor = Object.assign({}, DEFAULT_CONFIG.editor, originalConfig.editor, rcConfig.editor)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ function setZoom (zoomFactor, noSave = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getZoom () {
|
function getZoom () {
|
||||||
let config = ConfigManager.get()
|
const config = ConfigManager.get()
|
||||||
|
|
||||||
return config.zoom
|
return config.zoom
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const _ = require('lodash')
|
|
||||||
const sander = require('sander')
|
|
||||||
const { findStorage } = require('browser/lib/findStorage')
|
const { findStorage } = require('browser/lib/findStorage')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ const { findStorage } = require('browser/lib/findStorage')
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
function createFolder (storageKey, input) {
|
function createFolder (storageKey, input) {
|
||||||
let rawStorages
|
|
||||||
let targetStorage
|
let targetStorage
|
||||||
try {
|
try {
|
||||||
if (input == null) throw new Error('No input found.')
|
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)) {
|
while (storage.folders.some((folder) => folder.key === key)) {
|
||||||
key = keygen()
|
key = keygen()
|
||||||
}
|
}
|
||||||
let newFolder = {
|
const newFolder = {
|
||||||
key,
|
key,
|
||||||
color: input.color,
|
color: input.color,
|
||||||
name: input.name
|
name: input.name
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ function createNote (storageKey, input) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let noteData = Object.assign({}, input, {
|
const noteData = Object.assign({}, input, {
|
||||||
key,
|
key,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ const { findStorage } = require('browser/lib/findStorage')
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
function deleteFolder (storageKey, folderKey) {
|
function deleteFolder (storageKey, folderKey) {
|
||||||
let rawStorages
|
|
||||||
let targetStorage
|
let targetStorage
|
||||||
try {
|
try {
|
||||||
targetStorage = findStorage(storageKey)
|
targetStorage = findStorage(storageKey)
|
||||||
@@ -38,17 +37,17 @@ function deleteFolder (storageKey, folderKey) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then(function deleteFolderAndNotes (data) {
|
.then(function deleteFolderAndNotes (data) {
|
||||||
let { storage, notes } = data
|
const { storage, notes } = data
|
||||||
storage.folders = storage.folders
|
storage.folders = storage.folders
|
||||||
.filter(function excludeTargetFolder (folder) {
|
.filter(function excludeTargetFolder (folder) {
|
||||||
return folder.key !== folderKey
|
return folder.key !== folderKey
|
||||||
})
|
})
|
||||||
|
|
||||||
let targetNotes = notes.filter(function filterTargetNotes (note) {
|
const targetNotes = notes.filter(function filterTargetNotes (note) {
|
||||||
return note.folder === folderKey
|
return note.folder === folderKey
|
||||||
})
|
})
|
||||||
|
|
||||||
let deleteAllNotes = targetNotes
|
const deleteAllNotes = targetNotes
|
||||||
.map(function deleteNote (note) {
|
.map(function deleteNote (note) {
|
||||||
const notePath = path.join(storage.path, 'notes', note.key + '.cson')
|
const notePath = path.join(storage.path, 'notes', note.key + '.cson')
|
||||||
return sander.unlink(notePath)
|
return sander.unlink(notePath)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
const resolveStorageData = require('./resolveStorageData')
|
const resolveStorageData = require('./resolveStorageData')
|
||||||
const _ = require('lodash')
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const sander = require('sander')
|
const sander = require('sander')
|
||||||
const { findStorage } = require('browser/lib/findStorage')
|
const { findStorage } = require('browser/lib/findStorage')
|
||||||
@@ -14,7 +13,7 @@ function deleteNote (storageKey, noteKey) {
|
|||||||
|
|
||||||
return resolveStorageData(targetStorage)
|
return resolveStorageData(targetStorage)
|
||||||
.then(function deleteNoteFile (storage) {
|
.then(function deleteNoteFile (storage) {
|
||||||
let notePath = path.join(storage.path, 'notes', noteKey + '.cson')
|
const notePath = path.join(storage.path, 'notes', noteKey + '.cson')
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sander.unlinkSync(notePath)
|
sander.unlinkSync(notePath)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const CSON = require('@rokt33r/season')
|
|||||||
* 3. empty directory
|
* 3. empty directory
|
||||||
*/
|
*/
|
||||||
function init () {
|
function init () {
|
||||||
let fetchStorages = function () {
|
const fetchStorages = function () {
|
||||||
let rawStorages
|
let rawStorages
|
||||||
try {
|
try {
|
||||||
rawStorages = JSON.parse(window.localStorage.getItem('storages'))
|
rawStorages = JSON.parse(window.localStorage.getItem('storages'))
|
||||||
@@ -34,8 +34,8 @@ function init () {
|
|||||||
.map(resolveStorageData))
|
.map(resolveStorageData))
|
||||||
}
|
}
|
||||||
|
|
||||||
let fetchNotes = function (storages) {
|
const fetchNotes = function (storages) {
|
||||||
let findNotesFromEachStorage = storages
|
const findNotesFromEachStorage = storages
|
||||||
.map((storage) => {
|
.map((storage) => {
|
||||||
return resolveStorageNotes(storage)
|
return resolveStorageNotes(storage)
|
||||||
.then((notes) => {
|
.then((notes) => {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const sander = require('sander')
|
|||||||
function migrateFromV5Storage (storageKey, data) {
|
function migrateFromV5Storage (storageKey, data) {
|
||||||
let targetStorage
|
let targetStorage
|
||||||
try {
|
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.')
|
if (!_.isArray(cachedStorageList)) throw new Error('Target storage doesn\'t exist.')
|
||||||
|
|
||||||
targetStorage = _.find(cachedStorageList, {key: storageKey})
|
targetStorage = _.find(cachedStorageList, {key: storageKey})
|
||||||
@@ -24,15 +24,15 @@ function migrateFromV5Storage (storageKey, data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function importAll (storage, data) {
|
function importAll (storage, data) {
|
||||||
let oldArticles = data.articles
|
const oldArticles = data.articles
|
||||||
let notes = []
|
const notes = []
|
||||||
data.folders
|
data.folders
|
||||||
.forEach(function (oldFolder) {
|
.forEach(function (oldFolder) {
|
||||||
let folderKey = keygen()
|
let folderKey = keygen()
|
||||||
while (storage.folders.some((folder) => folder.key === folderKey)) {
|
while (storage.folders.some((folder) => folder.key === folderKey)) {
|
||||||
folderKey = keygen()
|
folderKey = keygen()
|
||||||
}
|
}
|
||||||
let newFolder = {
|
const newFolder = {
|
||||||
key: folderKey,
|
key: folderKey,
|
||||||
name: oldFolder.name,
|
name: oldFolder.name,
|
||||||
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
|
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
|
||||||
@@ -40,7 +40,7 @@ function importAll (storage, data) {
|
|||||||
|
|
||||||
storage.folders.push(newFolder)
|
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) => {
|
articles.forEach((article) => {
|
||||||
let noteKey = keygen()
|
let noteKey = keygen()
|
||||||
let isUnique = false
|
let isUnique = false
|
||||||
@@ -59,7 +59,7 @@ function importAll (storage, data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (article.mode === 'markdown') {
|
if (article.mode === 'markdown') {
|
||||||
let newNote = {
|
const newNote = {
|
||||||
tags: article.tags,
|
tags: article.tags,
|
||||||
createdAt: article.createdAt,
|
createdAt: article.createdAt,
|
||||||
updatedAt: article.updatedAt,
|
updatedAt: article.updatedAt,
|
||||||
@@ -73,7 +73,7 @@ function importAll (storage, data) {
|
|||||||
}
|
}
|
||||||
notes.push(newNote)
|
notes.push(newNote)
|
||||||
} else {
|
} else {
|
||||||
let newNote = {
|
const newNote = {
|
||||||
tags: article.tags,
|
tags: article.tags,
|
||||||
createdAt: article.createdAt,
|
createdAt: article.createdAt,
|
||||||
updatedAt: article.updatedAt,
|
updatedAt: article.updatedAt,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) {
|
|||||||
.then(function saveNote (_oldStorage) {
|
.then(function saveNote (_oldStorage) {
|
||||||
oldStorage = _oldStorage
|
oldStorage = _oldStorage
|
||||||
let noteData
|
let noteData
|
||||||
let notePath = path.join(oldStorage.path, 'notes', noteKey + '.cson')
|
const notePath = path.join(oldStorage.path, 'notes', noteKey + '.cson')
|
||||||
try {
|
try {
|
||||||
noteData = CSON.readFileSync(notePath)
|
noteData = CSON.readFileSync(notePath)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
const resolveStorageData = require('./resolveStorageData')
|
const resolveStorageData = require('./resolveStorageData')
|
||||||
const { findStorage } = require('browser/lib/findStorage')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} key
|
* @param {String} key
|
||||||
@@ -19,7 +18,7 @@ function renameStorage (key, name) {
|
|||||||
console.error(err)
|
console.error(err)
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
}
|
}
|
||||||
let targetStorage = _.find(cachedStorageList, {key: key})
|
const targetStorage = _.find(cachedStorageList, {key: key})
|
||||||
if (targetStorage == null) return Promise.reject('Storage')
|
if (targetStorage == null) return Promise.reject('Storage')
|
||||||
|
|
||||||
targetStorage.name = name
|
targetStorage.name = name
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ const { findStorage } = require('browser/lib/findStorage')
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
function reorderFolder (storageKey, oldIndex, newIndex) {
|
function reorderFolder (storageKey, oldIndex, newIndex) {
|
||||||
let rawStorages
|
|
||||||
let targetStorage
|
let targetStorage
|
||||||
try {
|
try {
|
||||||
if (!_.isNumber(oldIndex)) throw new Error('oldIndex must be a number.')
|
if (!_.isNumber(oldIndex)) throw new Error('oldIndex must be a number.')
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const CSON = require('@rokt33r/season')
|
|||||||
const migrateFromV6Storage = require('./migrateFromV6Storage')
|
const migrateFromV6Storage = require('./migrateFromV6Storage')
|
||||||
|
|
||||||
function resolveStorageData (storageCache) {
|
function resolveStorageData (storageCache) {
|
||||||
let storage = {
|
const storage = {
|
||||||
key: storageCache.key,
|
key: storageCache.key,
|
||||||
name: storageCache.name,
|
name: storageCache.name,
|
||||||
type: storageCache.type,
|
type: storageCache.type,
|
||||||
@@ -13,7 +13,7 @@ function resolveStorageData (storageCache) {
|
|||||||
|
|
||||||
const boostnoteJSONPath = path.join(storageCache.path, 'boostnote.json')
|
const boostnoteJSONPath = path.join(storageCache.path, 'boostnote.json')
|
||||||
try {
|
try {
|
||||||
let jsonData = CSON.readFileSync(boostnoteJSONPath)
|
const jsonData = CSON.readFileSync(boostnoteJSONPath)
|
||||||
if (!_.isArray(jsonData.folders)) throw new Error('folders should be an array.')
|
if (!_.isArray(jsonData.folders)) throw new Error('folders should be an array.')
|
||||||
storage.folders = jsonData.folders
|
storage.folders = jsonData.folders
|
||||||
storage.version = jsonData.version
|
storage.version = jsonData.version
|
||||||
@@ -28,7 +28,7 @@ function resolveStorageData (storageCache) {
|
|||||||
storage.version = '1.0'
|
storage.version = '1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
let version = parseInt(storage.version, 10)
|
const version = parseInt(storage.version, 10)
|
||||||
if (version >= 1) {
|
if (version >= 1) {
|
||||||
if (version > 1) {
|
if (version > 1) {
|
||||||
console.log('The repository version is newer than one of current app.')
|
console.log('The repository version is newer than one of current app.')
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ function resolveStorageNotes (storage) {
|
|||||||
}
|
}
|
||||||
notePathList = []
|
notePathList = []
|
||||||
}
|
}
|
||||||
let notes = notePathList
|
const notes = notePathList
|
||||||
.filter(function filterOnlyCSONFile (notePath) {
|
.filter(function filterOnlyCSONFile (notePath) {
|
||||||
return /\.cson$/.test(notePath)
|
return /\.cson$/.test(notePath)
|
||||||
})
|
})
|
||||||
.map(function parseCSONFile (notePath) {
|
.map(function parseCSONFile (notePath) {
|
||||||
try {
|
try {
|
||||||
let data = CSON.readFileSync(path.join(notesDirPath, notePath))
|
const data = CSON.readFileSync(path.join(notesDirPath, notePath))
|
||||||
data.key = path.basename(notePath, '.cson')
|
data.key = path.basename(notePath, '.cson')
|
||||||
data.storage = storage.key
|
data.storage = storage.key
|
||||||
return data
|
return data
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ const { findStorage } = require('browser/lib/findStorage')
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
function updateFolder (storageKey, folderKey, input) {
|
function updateFolder (storageKey, folderKey, input) {
|
||||||
let rawStorages
|
|
||||||
let targetStorage
|
let targetStorage
|
||||||
try {
|
try {
|
||||||
if (input == null) throw new Error('No input found.')
|
if (input == null) throw new Error('No input found.')
|
||||||
@@ -37,7 +36,7 @@ function updateFolder (storageKey, folderKey, input) {
|
|||||||
|
|
||||||
return resolveStorageData(targetStorage)
|
return resolveStorageData(targetStorage)
|
||||||
.then(function updateFolder (storage) {
|
.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.')
|
if (targetFolder == null) throw new Error('Target folder doesn\'t exist.')
|
||||||
targetFolder.name = input.name
|
targetFolder.name = input.name
|
||||||
targetFolder.color = input.color
|
targetFolder.color = input.color
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const CSON = require('@rokt33r/season')
|
|||||||
const { findStorage } = require('browser/lib/findStorage')
|
const { findStorage } = require('browser/lib/findStorage')
|
||||||
|
|
||||||
function validateInput (input) {
|
function validateInput (input) {
|
||||||
let validatedInput = {}
|
const validatedInput = {}
|
||||||
|
|
||||||
if (input.tags != null) {
|
if (input.tags != null) {
|
||||||
if (!_.isArray(input.tags)) validatedInput.tags = []
|
if (!_.isArray(input.tags)) validatedInput.tags = []
|
||||||
@@ -81,7 +81,7 @@ function updateNote (storageKey, noteKey, input) {
|
|||||||
return resolveStorageData(targetStorage)
|
return resolveStorageData(targetStorage)
|
||||||
.then(function saveNote (storage) {
|
.then(function saveNote (storage) {
|
||||||
let noteData
|
let noteData
|
||||||
let notePath = path.join(storage.path, 'notes', noteKey + '.cson')
|
const notePath = path.join(storage.path, 'notes', noteKey + '.cson')
|
||||||
try {
|
try {
|
||||||
noteData = CSON.readFileSync(notePath)
|
noteData = CSON.readFileSync(notePath)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
import store from 'browser/main/store'
|
|
||||||
|
|
||||||
const _ = require('lodash')
|
|
||||||
const keygen = require('browser/lib/keygen')
|
|
||||||
const Mixpanel = require('mixpanel')
|
|
||||||
const mixpanel = Mixpanel.init('7a0aca437d72dfd07cbcbf58d3b61f27', {key: 'fde4fd23f4d550f1b646bcd7d4374b1f'})
|
|
||||||
const moment = require('moment')
|
|
||||||
const electron = require('electron')
|
|
||||||
|
|
||||||
function _getClientKey () {
|
|
||||||
let clientKey = localStorage.getItem('clientKey')
|
|
||||||
if (!_.isString(clientKey) || clientKey.length !== 40) {
|
|
||||||
clientKey = keygen(20)
|
|
||||||
_setClientKey(clientKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
return clientKey
|
|
||||||
}
|
|
||||||
|
|
||||||
function _setClientKey (newKey) {
|
|
||||||
localStorage.setItem('clientKey', newKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
function _fetch () {
|
|
||||||
let events
|
|
||||||
try {
|
|
||||||
events = JSON.parse(localStorage.getItem('events'))
|
|
||||||
if (!_.isArray(events)) throw new Error('events is not an array.')
|
|
||||||
} catch (err) {
|
|
||||||
console.warn(err)
|
|
||||||
events = []
|
|
||||||
localStorage.setItem('events', JSON.stringify(events))
|
|
||||||
console.info('Events cache initialzed')
|
|
||||||
}
|
|
||||||
return events
|
|
||||||
}
|
|
||||||
|
|
||||||
function _keep (name, properties) {
|
|
||||||
let events = _fetch()
|
|
||||||
properties.time = new Date()
|
|
||||||
events.push({
|
|
||||||
name,
|
|
||||||
properties
|
|
||||||
})
|
|
||||||
localStorage.setItem('events', JSON.stringify(events))
|
|
||||||
}
|
|
||||||
|
|
||||||
function _keepUnique (name, properties) {
|
|
||||||
let events = _fetch()
|
|
||||||
properties.time = new Date()
|
|
||||||
events = events.filter((event) => event.name !== name)
|
|
||||||
events.push({
|
|
||||||
name,
|
|
||||||
properties
|
|
||||||
})
|
|
||||||
localStorage.setItem('events', JSON.stringify(events))
|
|
||||||
}
|
|
||||||
|
|
||||||
function _flush () {
|
|
||||||
let events = _fetch()
|
|
||||||
let spliced = events.splice(0, 50)
|
|
||||||
localStorage.setItem('events', JSON.stringify(events))
|
|
||||||
|
|
||||||
if (spliced.length > 0) {
|
|
||||||
let parsedEvents = spliced
|
|
||||||
.filter((event) => {
|
|
||||||
if (!_.isObject(event)) return false
|
|
||||||
if (!_.isString(event.name)) return false
|
|
||||||
if (!_.isObject(event.properties)) return false
|
|
||||||
if (!moment(event.properties.time).isValid()) return false
|
|
||||||
if (new Date() - moment(event.properties.time).toDate() > 1000 * 3600 * 24 * 3) return false
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
.map((event) => {
|
|
||||||
return {
|
|
||||||
event: event.name,
|
|
||||||
properties: event.properties
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
mixpanel.import_batch(parsedEvents, {}, (errs) => {
|
|
||||||
if (errs.length > 0) {
|
|
||||||
let events = _fetch()
|
|
||||||
events = events.concat(spliced)
|
|
||||||
localStorage.setItem('events', JSON.stringify(events))
|
|
||||||
} else {
|
|
||||||
_flush()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let state = store.getState()
|
|
||||||
mixpanel.people.set(_getClientKey(), {
|
|
||||||
storage_count: state.data.storageMap.size,
|
|
||||||
note_count: state.data.noteMap.size,
|
|
||||||
version: electron.remote.app.getVersion()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setInterval(_flush, 1000 * 60 * 60)
|
|
||||||
|
|
||||||
function track (name, properties) {
|
|
||||||
switch (name) {
|
|
||||||
case 'MAIN_FOCUSED':
|
|
||||||
properties = Object.assign({}, properties, {
|
|
||||||
distinct_id: _getClientKey()
|
|
||||||
})
|
|
||||||
_keepUnique(name, properties)
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
properties = Object.assign({}, properties, {
|
|
||||||
distinct_id: _getClientKey()
|
|
||||||
})
|
|
||||||
_keep(name, properties)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
_mp: mixpanel,
|
|
||||||
track
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,7 @@ class ModalBase extends React.Component {
|
|||||||
close () {
|
close () {
|
||||||
if (modalBase != null) modalBase.setState({component: null, componentProps: null, isHidden: true})
|
if (modalBase != null) modalBase.setState({component: null, componentProps: null, isHidden: true})
|
||||||
// Toggle overflow style on NoteList
|
// 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'
|
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)
|
document.body.appendChild(el)
|
||||||
let modalBase = ReactDOM.render(<ModalBase />, el)
|
const modalBase = ReactDOM.render(<ModalBase />, el)
|
||||||
|
|
||||||
export function openModal (component, props) {
|
export function openModal (component, props) {
|
||||||
if (modalBase == null) { return }
|
if (modalBase == null) { return }
|
||||||
// Hide scrollbar by removing overflow when modal opens
|
// 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'
|
list.style.overflow = 'hidden'
|
||||||
document.body.setAttribute('data-modal', 'open')
|
document.body.setAttribute('data-modal', 'open')
|
||||||
modalBase.setState({component: component, componentProps: props, isHidden: false})
|
modalBase.setState({component: component, componentProps: props, isHidden: false})
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './CreateFolderModal.styl'
|
import styles from './CreateFolderModal.styl'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
@@ -51,8 +52,8 @@ class CreateFolderModal extends React.Component {
|
|||||||
confirm () {
|
confirm () {
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_FOLDER')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_FOLDER')
|
||||||
if (this.state.name.trim().length > 0) {
|
if (this.state.name.trim().length > 0) {
|
||||||
let { storage } = this.props
|
const { storage } = this.props
|
||||||
let input = {
|
const input = {
|
||||||
name: this.state.name.trim(),
|
name: this.state.name.trim(),
|
||||||
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
|
color: consts.FOLDER_COLORS[Math.floor(Math.random() * 7) % 7]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ const electron = require('electron')
|
|||||||
const { remote } = electron
|
const { remote } = electron
|
||||||
|
|
||||||
function browseFolder () {
|
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) => {
|
return new Promise((resolve, reject) => {
|
||||||
dialog.showOpenDialog({
|
dialog.showOpenDialog({
|
||||||
title: 'Select Directory',
|
title: 'Select Directory',
|
||||||
@@ -55,7 +55,7 @@ class InitModal extends React.Component {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
let newState = {
|
const newState = {
|
||||||
isLoading: false
|
isLoading: false
|
||||||
}
|
}
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
@@ -122,7 +122,7 @@ class InitModal extends React.Component {
|
|||||||
notes: data.notes
|
notes: data.notes
|
||||||
})
|
})
|
||||||
|
|
||||||
let defaultSnippetNote = dataApi
|
const defaultSnippetNote = dataApi
|
||||||
.createNote(data.storage.key, {
|
.createNote(data.storage.key, {
|
||||||
type: 'SNIPPET_NOTE',
|
type: 'SNIPPET_NOTE',
|
||||||
folder: data.storage.folders[0].key,
|
folder: data.storage.folders[0].key,
|
||||||
@@ -147,12 +147,12 @@ class InitModal extends React.Component {
|
|||||||
note: note
|
note: note
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
let defaultMarkdownNote = dataApi
|
const defaultMarkdownNote = dataApi
|
||||||
.createNote(data.storage.key, {
|
.createNote(data.storage.key, {
|
||||||
type: 'MARKDOWN_NOTE',
|
type: 'MARKDOWN_NOTE',
|
||||||
folder: data.storage.folders[0].key,
|
folder: data.storage.folders[0].key,
|
||||||
title: 'Welcome to Boostnote!',
|
title: 'Welcome to Boostnote!',
|
||||||
content: '# Welcome to Boostnote! \n### _Click to edit this note._\n\n---\n\nBoostnote is an *open source* note-taking app. \nRepository is published on [GitHub](https://github.com/BoostIO/Boostnote), and tweeting everyday on [@Boostnoteapp](https://twitter.com/boostnoteapp)!\n\n## Features \n- [x] No internet or registration required. \n- [ ] Quick search and copy the content of note. macOS: <kbd>Cmd</kbd> + <kbd>Alt</kbd> + <kbd>S</kbd> / windows: <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>S</kbd> \n- [ ] Markdown & Snippet note. \n- [ ] Available for `vim` and `emacs` mode. \n- [ ] Choose your favorite theme on UI, Editor and Code Block! \n--- \n\n- Copy Codeblock on Markdown Preview.\n```javascript\nvar boostnote = document.getElementById(\'enjoy\').innerHTML\n\nconsole.log(boostnote)\n```'
|
content: '# Welcome to Boostnote!\n## Click here to edit markdown :wave:\n\n<iframe width="560" height="315" src="https://www.youtube.com/embed/L0qNPLsvmyM" frameborder="0" allowfullscreen></iframe>\n\n## Docs :memo:\n- [Boostnote | Boost your happiness, productivity and creativity.](https://hackernoon.com/boostnote-boost-your-happiness-productivity-and-creativity-315034efeebe)\n- [Cloud Syncing & Backups](https://github.com/BoostIO/Boostnote/wiki/Cloud-Syncing-and-Backup)\n- [How to sync your data across Desktop and Mobile apps](https://github.com/BoostIO/Boostnote/wiki/Sync-Data-Across-Desktop-and-Mobile-apps)\n- [Convert data from **Evernote** to Boostnote.](https://github.com/BoostIO/Boostnote/wiki/Evernote)\n- [Keyboard Shortcuts](https://github.com/BoostIO/Boostnote/wiki/Keyboard-Shortcuts)\n- [Keymaps in Editor mode](https://github.com/BoostIO/Boostnote/wiki/Keymaps-in-Editor-mode)\n- [How to set syntax highlight in Snippet note](https://github.com/BoostIO/Boostnote/wiki/Syntax-Highlighting)\n\n---\n\n## Article Archive :books:\n- [Reddit English](http://bit.ly/2mOJPu7)\n- [Reddit Spanish](https://www.reddit.com/r/boostnote_es/)\n- [Reddit Chinese](https://www.reddit.com/r/boostnote_cn/)\n- [Reddit Japanese](https://www.reddit.com/r/boostnote_jp/)\n\n---\n\n## Community :beers:\n- [GitHub](http://bit.ly/2AWWzkD)\n- [Twitter](http://bit.ly/2z8BUJZ)\n- [Facebook Group](http://bit.ly/2jcca8t)'
|
||||||
})
|
})
|
||||||
.then((note) => {
|
.then((note) => {
|
||||||
store.dispatch({
|
store.dispatch({
|
||||||
@@ -184,6 +184,12 @@ class InitModal extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleKeyDown (e) {
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
this.props.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
if (this.state.isLoading) {
|
if (this.state.isLoading) {
|
||||||
return <div styleName='root--loading'>
|
return <div styleName='root--loading'>
|
||||||
@@ -194,7 +200,7 @@ class InitModal extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div styleName='root'
|
<div styleName='root'
|
||||||
tabIndex='-1'
|
tabIndex='-1'
|
||||||
onKeyDown={this.props.close}
|
onKeyDown={(e) => this.handleKeyDown(e)}
|
||||||
>
|
>
|
||||||
|
|
||||||
<div styleName='header'>
|
<div styleName='header'>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class NewNoteModal extends React.Component {
|
|||||||
handleMarkdownNoteButtonClick (e) {
|
handleMarkdownNoteButtonClick (e) {
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_MARKDOWN')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_MARKDOWN')
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
|
||||||
let { storage, folder, dispatch, location } = this.props
|
const { storage, folder, dispatch, location } = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.createNote(storage, {
|
.createNote(storage, {
|
||||||
type: 'MARKDOWN_NOTE',
|
type: 'MARKDOWN_NOTE',
|
||||||
@@ -58,7 +58,7 @@ class NewNoteModal extends React.Component {
|
|||||||
handleSnippetNoteButtonClick (e) {
|
handleSnippetNoteButtonClick (e) {
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_SNIPPET')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_SNIPPET')
|
||||||
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
|
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
|
||||||
let { storage, folder, dispatch, location } = this.props
|
const { storage, folder, dispatch, location } = this.props
|
||||||
|
|
||||||
dataApi
|
dataApi
|
||||||
.createNote(storage, {
|
.createNote(storage, {
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import styles from './FolderItem.styl'
|
import styles from './FolderItem.styl'
|
||||||
@@ -23,7 +24,7 @@ class FolderItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleEditChange (e) {
|
handleEditChange (e) {
|
||||||
let { folder } = this.state
|
const { folder } = this.state
|
||||||
|
|
||||||
folder.name = this.refs.nameInput.value
|
folder.name = this.refs.nameInput.value
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -36,7 +37,7 @@ class FolderItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
confirm () {
|
confirm () {
|
||||||
let { storage, folder } = this.props
|
const { storage, folder } = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.updateFolder(storage.key, folder.key, {
|
.updateFolder(storage.key, folder.key, {
|
||||||
color: this.state.folder.color,
|
color: this.state.folder.color,
|
||||||
@@ -162,7 +163,7 @@ class FolderItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteConfirmButtonClick (e) {
|
handleDeleteConfirmButtonClick (e) {
|
||||||
let { storage, folder } = this.props
|
const { storage, folder } = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.deleteFolder(storage.key, folder.key)
|
.deleteFolder(storage.key, folder.key)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -197,8 +198,8 @@ class FolderItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleEditButtonClick (e) {
|
handleEditButtonClick (e) {
|
||||||
let { folder: propsFolder } = this.props
|
const { folder: propsFolder } = this.props
|
||||||
let { folder: stateFolder } = this.state
|
const { folder: stateFolder } = this.state
|
||||||
const folder = Object.assign({}, stateFolder, propsFolder)
|
const folder = Object.assign({}, stateFolder, propsFolder)
|
||||||
this.setState({
|
this.setState({
|
||||||
status: 'EDIT',
|
status: 'EDIT',
|
||||||
@@ -215,7 +216,7 @@ class FolderItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderIdle () {
|
renderIdle () {
|
||||||
let { folder } = this.props
|
const { folder } = this.props
|
||||||
return (
|
return (
|
||||||
<div styleName='folderItem'
|
<div styleName='folderItem'
|
||||||
onDoubleClick={(e) => this.handleEditButtonClick(e)}
|
onDoubleClick={(e) => this.handleEditButtonClick(e)}
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import styles from './FolderList.styl'
|
import styles from './FolderList.styl'
|
||||||
import store from 'browser/main/store'
|
import store from 'browser/main/store'
|
||||||
import FolderItem from './FolderItem'
|
import FolderItem from './FolderItem'
|
||||||
import { SortableContainer, arrayMove } from 'react-sortable-hoc'
|
import { SortableContainer } from 'react-sortable-hoc'
|
||||||
|
|
||||||
class FolderList extends React.Component {
|
class FolderList extends React.Component {
|
||||||
render () {
|
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}
|
return <FolderItem key={folder.key}
|
||||||
folder={folder}
|
folder={folder}
|
||||||
storage={storage}
|
storage={storage}
|
||||||
@@ -53,7 +54,7 @@ class SortableFolderListComponent extends React.Component {
|
|||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
this.onSortEnd = ({oldIndex, newIndex}) => {
|
this.onSortEnd = ({oldIndex, newIndex}) => {
|
||||||
let { storage } = this.props
|
const { storage } = this.props
|
||||||
dataApi
|
dataApi
|
||||||
.reorderFolder(storage.key, oldIndex, newIndex)
|
.reorderFolder(storage.key, oldIndex, newIndex)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
|
|||||||
@@ -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 CSSModules from 'browser/lib/CSSModules'
|
||||||
import styles from './ConfigTab.styl'
|
import styles from './ConfigTab.styl'
|
||||||
import ConfigManager from 'browser/main/lib/ConfigManager'
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
@@ -41,7 +42,7 @@ class HotkeyTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleSaveButtonClick (e) {
|
handleSaveButtonClick (e) {
|
||||||
let newConfig = {
|
const newConfig = {
|
||||||
hotkey: this.state.config.hotkey
|
hotkey: this.state.config.hotkey
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ class HotkeyTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleHotkeyChange (e) {
|
handleHotkeyChange (e) {
|
||||||
let { config } = this.state
|
const { config } = this.state
|
||||||
config.hotkey = {
|
config.hotkey = {
|
||||||
toggleFinder: this.refs.toggleFinder.value,
|
toggleFinder: this.refs.toggleFinder.value,
|
||||||
toggleMain: this.refs.toggleMain.value
|
toggleMain: this.refs.toggleMain.value
|
||||||
@@ -80,13 +81,13 @@ class HotkeyTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
let keymapAlert = this.state.keymapAlert
|
const keymapAlert = this.state.keymapAlert
|
||||||
let keymapAlertElement = keymapAlert != null
|
const keymapAlertElement = keymapAlert != null
|
||||||
? <p className={`alert ${keymapAlert.type}`}>
|
? <p className={`alert ${keymapAlert.type}`}>
|
||||||
{keymapAlert.message}
|
{keymapAlert.message}
|
||||||
</p>
|
</p>
|
||||||
: null
|
: null
|
||||||
let { config } = this.state
|
const { config } = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div styleName='root'>
|
<div styleName='root'>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user