mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 18:26:26 +00:00
Compare commits
173 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab3ad0eb97 | ||
|
|
2393889028 | ||
|
|
c36ecb1ed1 | ||
|
|
3e9b28ff0c | ||
|
|
d4eec461a9 | ||
|
|
b584f37087 | ||
|
|
5c75644db2 | ||
|
|
72d9e3e00b | ||
|
|
b3d3362f34 | ||
|
|
1cbaf55cee | ||
|
|
7771875d57 | ||
|
|
85937d8e23 | ||
|
|
1480986a3a | ||
|
|
bc968736df | ||
|
|
ad80b8e8b6 | ||
|
|
d44d220c55 | ||
|
|
f6bcef0789 | ||
|
|
a28ec752e8 | ||
|
|
48ea5746d9 | ||
|
|
f473d31970 | ||
|
|
9cd1d4b466 | ||
|
|
4f02065eaf | ||
|
|
4b85e3e8fb | ||
|
|
e4e8c2205e | ||
|
|
18649dd074 | ||
|
|
9f9463f0e8 | ||
|
|
6cf9bc5de2 | ||
|
|
297b4346c5 | ||
|
|
767a203439 | ||
|
|
c564c253b1 | ||
|
|
b4e138e21b | ||
|
|
8ca01921c4 | ||
|
|
c8b97ffde3 | ||
|
|
abc84e5710 | ||
|
|
d732d195f3 | ||
|
|
789975abb0 | ||
|
|
ed1eab7fcc | ||
|
|
29b31c114a | ||
|
|
c8cf353c21 | ||
|
|
e82e2c71f1 | ||
|
|
dd729c406f | ||
|
|
3127e85900 | ||
|
|
304eeb3158 | ||
|
|
bf781c6b50 | ||
|
|
4f7026969f | ||
|
|
16d264ebfa | ||
|
|
04ffbe945b | ||
|
|
974a1a1e7d | ||
|
|
ca2c07244f | ||
|
|
f90786d1c0 | ||
|
|
bdf55568c7 | ||
|
|
e262d2f19b | ||
|
|
aabfe820ac | ||
|
|
3bba5442bd | ||
|
|
6ce1922fb3 | ||
|
|
9367a404ef | ||
|
|
7c8e19c681 | ||
|
|
7ccc5eb9b8 | ||
|
|
b4b6d3d07c | ||
|
|
9007bac7b2 | ||
|
|
df13ca3c92 | ||
|
|
d86935acaa | ||
|
|
72b450d526 | ||
|
|
4b7afeeb4f | ||
|
|
0e0e779cbe | ||
|
|
89b2f48a06 | ||
|
|
c80bdb8d0c | ||
|
|
50d89a8ec9 | ||
|
|
f5ccaa7b48 | ||
|
|
e682ee8541 | ||
|
|
caaa7a9e74 | ||
|
|
6ef0e325e2 | ||
|
|
ea064deeb8 | ||
|
|
8e81609a39 | ||
|
|
977e80c829 | ||
|
|
8ba0d10f40 | ||
|
|
2581091652 | ||
|
|
e72a7ceaea | ||
|
|
a17ddf6d54 | ||
|
|
b5e2d21f33 | ||
|
|
d09f8dff18 | ||
|
|
bdb3406dcb | ||
|
|
f54b49db1a | ||
|
|
0cc9f006c5 | ||
|
|
db1398b65f | ||
|
|
e8192e6c3f | ||
|
|
775200bdd6 | ||
|
|
820a2a093c | ||
|
|
d3995b9b10 | ||
|
|
f6867f9338 | ||
|
|
3e2548fcd5 | ||
|
|
745d250787 | ||
|
|
b1063eb38f | ||
|
|
9032a1debb | ||
|
|
795fe8ae1d | ||
|
|
e5a908af68 | ||
|
|
6ce16c1cc0 | ||
|
|
6ff2a5ac94 | ||
|
|
fcea16e43a | ||
|
|
7b8e42382e | ||
|
|
a372b5ea39 | ||
|
|
1aafee2a7c | ||
|
|
7afe3d5181 | ||
|
|
6fba62d062 | ||
|
|
5d46adf8fd | ||
|
|
eda1f11d42 | ||
|
|
6431a8255d | ||
|
|
48fd1d11e2 | ||
|
|
4c3e62efad | ||
|
|
52a15a5d92 | ||
|
|
57f4aa5995 | ||
|
|
ab9ab004b7 | ||
|
|
ac624eb98f | ||
|
|
1a4c37820d | ||
|
|
685206950b | ||
|
|
eececf8a93 | ||
|
|
9bc3d65554 | ||
|
|
f9b854ce39 | ||
|
|
1416968fe5 | ||
|
|
efc183c709 | ||
|
|
07a2442718 | ||
|
|
f549c50a58 | ||
|
|
8d6ce1a2f7 | ||
|
|
c5b33e025e | ||
|
|
4983605b23 | ||
|
|
9e8d04d806 | ||
|
|
042f935133 | ||
|
|
ed9d3639e2 | ||
|
|
728f105830 | ||
|
|
6f359fa6a8 | ||
|
|
57a88743bc | ||
|
|
667f022086 | ||
|
|
b742a3a4cd | ||
|
|
8d5c9742f8 | ||
|
|
c2a49efe73 | ||
|
|
8c8a0ab46d | ||
|
|
959b75bddd | ||
|
|
d29d5105f1 | ||
|
|
38e82872a5 | ||
|
|
15d9ce1d36 | ||
|
|
67f7cdb36c | ||
|
|
6a9d4ae0fd | ||
|
|
6a761c3fb5 | ||
|
|
3baf97e69f | ||
|
|
694dc60481 | ||
|
|
e3c6f0452c | ||
|
|
ed2401a87b | ||
|
|
cb59458c79 | ||
|
|
125a493400 | ||
|
|
83910b55d2 | ||
|
|
f4fd131100 | ||
|
|
cfdc880d8c | ||
|
|
7303e8bdd2 | ||
|
|
ecde465d9f | ||
|
|
5c5e70a805 | ||
|
|
4e41d9be55 | ||
|
|
d06d94449c | ||
|
|
1af2c83c63 | ||
|
|
6c75136777 | ||
|
|
31351e34e1 | ||
|
|
a058a774e9 | ||
|
|
e6db28485c | ||
|
|
391bb096d6 | ||
|
|
2b496dc2e5 | ||
|
|
a6e0b30576 | ||
|
|
1ac31264b7 | ||
|
|
ca4b8224fd | ||
|
|
d1e5781c24 | ||
|
|
c86e451198 | ||
|
|
b4a7b547f0 | ||
|
|
07b395c24a | ||
|
|
53b9630fa5 | ||
|
|
f820c3089e |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,3 +8,5 @@ node_modules/*
|
|||||||
/compiled
|
/compiled
|
||||||
/secret
|
/secret
|
||||||
*.log
|
*.log
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
|
import 'codemirror-mode-elixir'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import copyImage from 'browser/main/lib/dataApi/copyImage'
|
import copyImage from 'browser/main/lib/dataApi/copyImage'
|
||||||
import { findStorage } from 'browser/lib/findStorage'
|
import { findStorage } from 'browser/lib/findStorage'
|
||||||
@@ -59,8 +60,10 @@ export default class CodeEditor extends React.Component {
|
|||||||
tabSize: this.props.indentSize,
|
tabSize: this.props.indentSize,
|
||||||
indentWithTabs: this.props.indentType !== 'space',
|
indentWithTabs: this.props.indentType !== 'space',
|
||||||
keyMap: this.props.keyMap,
|
keyMap: this.props.keyMap,
|
||||||
|
scrollPastEnd: this.props.scrollPastEnd,
|
||||||
inputStyle: 'textarea',
|
inputStyle: 'textarea',
|
||||||
dragDrop: false,
|
dragDrop: false,
|
||||||
|
autoCloseBrackets: true,
|
||||||
extraKeys: {
|
extraKeys: {
|
||||||
Tab: function (cm) {
|
Tab: function (cm) {
|
||||||
const cursor = cm.getCursor()
|
const cursor = cm.getCursor()
|
||||||
@@ -153,6 +156,10 @@ export default class CodeEditor extends React.Component {
|
|||||||
this.editor.setOption('indentWithTabs', this.props.indentType !== 'space')
|
this.editor.setOption('indentWithTabs', this.props.indentType !== 'space')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prevProps.scrollPastEnd !== this.props.scrollPastEnd) {
|
||||||
|
this.editor.setOption('scrollPastEnd', this.props.scrollPastEnd)
|
||||||
|
}
|
||||||
|
|
||||||
if (needRefresh) {
|
if (needRefresh) {
|
||||||
this.editor.refresh()
|
this.editor.refresh()
|
||||||
}
|
}
|
||||||
@@ -244,7 +251,7 @@ export default class CodeEditor extends React.Component {
|
|||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { className, fontSize } = this.props
|
const { className, fontSize } = this.props
|
||||||
let fontFamily = this.props.className
|
let fontFamily = this.props.fontFamily
|
||||||
fontFamily = _.isString(fontFamily) && fontFamily.length > 0
|
fontFamily = _.isString(fontFamily) && fontFamily.length > 0
|
||||||
? [fontFamily].concat(defaultEditorFontFamily)
|
? [fontFamily].concat(defaultEditorFontFamily)
|
||||||
: defaultEditorFontFamily
|
: defaultEditorFontFamily
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ class MarkdownEditor extends React.Component {
|
|||||||
fontSize={editorFontSize}
|
fontSize={editorFontSize}
|
||||||
indentType={config.editor.indentType}
|
indentType={config.editor.indentType}
|
||||||
indentSize={editorIndentSize}
|
indentSize={editorIndentSize}
|
||||||
|
scrollPastEnd={config.editor.scrollPastEnd}
|
||||||
storageKey={storageKey}
|
storageKey={storageKey}
|
||||||
onChange={(e) => this.handleChange(e)}
|
onChange={(e) => this.handleChange(e)}
|
||||||
onBlur={(e) => this.handleBlur(e)}
|
onBlur={(e) => this.handleBlur(e)}
|
||||||
@@ -259,6 +260,7 @@ class MarkdownEditor extends React.Component {
|
|||||||
codeBlockFontFamily={config.editor.fontFamily}
|
codeBlockFontFamily={config.editor.fontFamily}
|
||||||
lineNumber={config.preview.lineNumber}
|
lineNumber={config.preview.lineNumber}
|
||||||
indentSize={editorIndentSize}
|
indentSize={editorIndentSize}
|
||||||
|
scrollPastEnd={config.editor.scrollPastEnd}
|
||||||
ref='preview'
|
ref='preview'
|
||||||
onContextMenu={(e) => this.handleContextMenu(e)}
|
onContextMenu={(e) => this.handleContextMenu(e)}
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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'
|
||||||
|
import 'codemirror-mode-elixir'
|
||||||
import consts from 'browser/lib/consts'
|
import consts from 'browser/lib/consts'
|
||||||
import Raphael from 'raphael'
|
import Raphael from 'raphael'
|
||||||
import flowchart from 'flowchart'
|
import flowchart from 'flowchart'
|
||||||
@@ -49,12 +50,12 @@ body {
|
|||||||
font-size: ${fontSize}px;
|
font-size: ${fontSize}px;
|
||||||
}
|
}
|
||||||
code {
|
code {
|
||||||
font-family: ${codeBlockFontFamily.join(', ')};
|
font-family: '${codeBlockFontFamily.join("','")}';
|
||||||
background-color: rgba(0,0,0,0.04);
|
background-color: rgba(0,0,0,0.04);
|
||||||
}
|
}
|
||||||
.lineNumber {
|
.lineNumber {
|
||||||
${lineNumber && 'display: block !important;'}
|
${lineNumber && 'display: block !important;'}
|
||||||
font-family: ${codeBlockFontFamily.join(', ')};
|
font-family: '${codeBlockFontFamily.join("','")}';
|
||||||
}
|
}
|
||||||
|
|
||||||
.clipboardButton {
|
.clipboardButton {
|
||||||
@@ -118,6 +119,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
this.checkboxClickHandler = (e) => this.handleCheckboxClick(e)
|
this.checkboxClickHandler = (e) => this.handleCheckboxClick(e)
|
||||||
this.saveAsTextHandler = () => this.handleSaveAsText()
|
this.saveAsTextHandler = () => this.handleSaveAsText()
|
||||||
this.saveAsMdHandler = () => this.handleSaveAsMd()
|
this.saveAsMdHandler = () => this.handleSaveAsMd()
|
||||||
|
this.saveAsHtmlHandler = () => this.handleSaveAsHtml()
|
||||||
this.printHandler = () => this.handlePrint()
|
this.printHandler = () => this.handlePrint()
|
||||||
|
|
||||||
this.linkClickHandler = this.handlelinkClick.bind(this)
|
this.linkClickHandler = this.handlelinkClick.bind(this)
|
||||||
@@ -144,10 +146,12 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleContextMenu (e) {
|
handleContextMenu (e) {
|
||||||
|
if (!this.props.onContextMenu) return
|
||||||
this.props.onContextMenu(e)
|
this.props.onContextMenu(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseDown (e) {
|
handleMouseDown (e) {
|
||||||
|
if (!this.props.onMouseDown) return
|
||||||
if (e.target != null) {
|
if (e.target != null) {
|
||||||
switch (e.target.tagName) {
|
switch (e.target.tagName) {
|
||||||
case 'A':
|
case 'A':
|
||||||
@@ -159,6 +163,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleMouseUp (e) {
|
handleMouseUp (e) {
|
||||||
|
if (!this.props.onMouseUp) return
|
||||||
if (e.target != null && e.target.tagName === 'A') {
|
if (e.target != null && e.target.tagName === 'A') {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -173,21 +178,29 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
this.exportAsDocument('md')
|
this.exportAsDocument('md')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSaveAsHtml () {
|
||||||
|
this.exportAsDocument('html', (value) => {
|
||||||
|
return this.refs.root.contentWindow.document.documentElement.outerHTML
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
handlePrint () {
|
handlePrint () {
|
||||||
this.refs.root.contentWindow.print()
|
this.refs.root.contentWindow.print()
|
||||||
}
|
}
|
||||||
|
|
||||||
exportAsDocument (fileType) {
|
exportAsDocument (fileType, formatter) {
|
||||||
const options = {
|
const options = {
|
||||||
filters: [
|
filters: [
|
||||||
{ name: 'Documents', extensions: [fileType] }
|
{ name: 'Documents', extensions: [fileType] }
|
||||||
],
|
],
|
||||||
properties: ['openFile', 'createDirectory']
|
properties: ['openFile', 'createDirectory']
|
||||||
}
|
}
|
||||||
|
const value = formatter ? formatter.call(this, this.props.value) : this.props.value
|
||||||
|
|
||||||
dialog.showSaveDialog(remote.getCurrentWindow(), options,
|
dialog.showSaveDialog(remote.getCurrentWindow(), options,
|
||||||
(filename) => {
|
(filename) => {
|
||||||
if (filename) {
|
if (filename) {
|
||||||
fs.writeFile(filename, this.props.value, (err) => {
|
fs.writeFile(filename, value, (err) => {
|
||||||
if (err) throw err
|
if (err) throw err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -223,6 +236,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
this.refs.root.contentWindow.document.addEventListener('dragover', this.preventImageDroppedHandler)
|
this.refs.root.contentWindow.document.addEventListener('dragover', this.preventImageDroppedHandler)
|
||||||
eventEmitter.on('export:save-text', this.saveAsTextHandler)
|
eventEmitter.on('export:save-text', this.saveAsTextHandler)
|
||||||
eventEmitter.on('export:save-md', this.saveAsMdHandler)
|
eventEmitter.on('export:save-md', this.saveAsMdHandler)
|
||||||
|
eventEmitter.on('export:save-html', this.saveAsHtmlHandler)
|
||||||
eventEmitter.on('print', this.printHandler)
|
eventEmitter.on('print', this.printHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +248,7 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
this.refs.root.contentWindow.document.removeEventListener('dragover', this.preventImageDroppedHandler)
|
this.refs.root.contentWindow.document.removeEventListener('dragover', this.preventImageDroppedHandler)
|
||||||
eventEmitter.off('export:save-text', this.saveAsTextHandler)
|
eventEmitter.off('export:save-text', this.saveAsTextHandler)
|
||||||
eventEmitter.off('export:save-md', this.saveAsMdHandler)
|
eventEmitter.off('export:save-md', this.saveAsMdHandler)
|
||||||
|
eventEmitter.off('export:save-html', this.saveAsHtmlHandler)
|
||||||
eventEmitter.off('print', this.printHandler)
|
eventEmitter.off('print', this.printHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,10 +270,10 @@ export default class MarkdownPreview extends React.Component {
|
|||||||
const { fontSize, lineNumber, codeBlockTheme } = this.props
|
const { fontSize, lineNumber, codeBlockTheme } = this.props
|
||||||
let { fontFamily, codeBlockFontFamily } = 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.split(',').map(fontName => fontName.trim()).concat(defaultFontFamily)
|
||||||
: defaultFontFamily
|
: defaultFontFamily
|
||||||
codeBlockFontFamily = _.isString(codeBlockFontFamily) && codeBlockFontFamily.trim().length > 0
|
codeBlockFontFamily = _.isString(codeBlockFontFamily) && codeBlockFontFamily.trim().length > 0
|
||||||
? [codeBlockFontFamily].concat(defaultCodeBlockFontFamily)
|
? codeBlockFontFamily.split(',').map(fontName => fontName.trim()).concat(defaultCodeBlockFontFamily)
|
||||||
: defaultCodeBlockFontFamily
|
: defaultCodeBlockFontFamily
|
||||||
|
|
||||||
this.setCodeTheme(codeBlockTheme)
|
this.setCodeTheme(codeBlockTheme)
|
||||||
|
|||||||
93
browser/components/MarkdownSplitEditor.js
Normal file
93
browser/components/MarkdownSplitEditor.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import CodeEditor from 'browser/components/CodeEditor'
|
||||||
|
import MarkdownPreview from 'browser/components/MarkdownPreview'
|
||||||
|
import { findStorage } from 'browser/lib/findStorage'
|
||||||
|
|
||||||
|
import styles from './MarkdownSplitEditor.styl'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
|
||||||
|
class MarkdownSplitEditor extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props)
|
||||||
|
this.value = props.value
|
||||||
|
this.focus = () => this.refs.code.focus()
|
||||||
|
this.reload = () => this.refs.code.reload()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnChange () {
|
||||||
|
this.value = this.refs.code.value
|
||||||
|
this.props.onChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCheckboxClick (e) {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
const idMatch = /checkbox-([0-9]+)/
|
||||||
|
const checkedMatch = /\[x\]/i
|
||||||
|
const uncheckedMatch = /\[ \]/
|
||||||
|
if (idMatch.test(e.target.getAttribute('id'))) {
|
||||||
|
const lineIndex = parseInt(e.target.getAttribute('id').match(idMatch)[1], 10) - 1
|
||||||
|
const lines = this.refs.code.value
|
||||||
|
.split('\n')
|
||||||
|
|
||||||
|
const targetLine = lines[lineIndex]
|
||||||
|
|
||||||
|
if (targetLine.match(checkedMatch)) {
|
||||||
|
lines[lineIndex] = targetLine.replace(checkedMatch, '[ ]')
|
||||||
|
}
|
||||||
|
if (targetLine.match(uncheckedMatch)) {
|
||||||
|
lines[lineIndex] = targetLine.replace(uncheckedMatch, '[x]')
|
||||||
|
}
|
||||||
|
this.refs.code.setValue(lines.join('\n'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { config, value, storageKey } = this.props
|
||||||
|
const storage = findStorage(storageKey)
|
||||||
|
let editorFontSize = parseInt(config.editor.fontSize, 10)
|
||||||
|
if (!(editorFontSize > 0 && editorFontSize < 101)) editorFontSize = 14
|
||||||
|
let editorIndentSize = parseInt(config.editor.indentSize, 10)
|
||||||
|
if (!(editorFontSize > 0 && editorFontSize < 132)) editorIndentSize = 4
|
||||||
|
const previewStyle = {}
|
||||||
|
if (this.props.ignorePreviewPointerEvents) previewStyle.pointerEvents = 'none'
|
||||||
|
return (
|
||||||
|
<div styleName='root'>
|
||||||
|
<CodeEditor
|
||||||
|
styleName='codeEditor'
|
||||||
|
ref='code'
|
||||||
|
mode='GitHub Flavored Markdown'
|
||||||
|
value={value}
|
||||||
|
theme={config.editor.theme}
|
||||||
|
keyMap={config.editor.keyMap}
|
||||||
|
fontFamily={config.editor.fontFamily}
|
||||||
|
fontSize={editorFontSize}
|
||||||
|
indentType={config.editor.indentType}
|
||||||
|
indentSize={editorIndentSize}
|
||||||
|
scrollPastEnd={config.editor.scrollPastEnd}
|
||||||
|
storageKey={storageKey}
|
||||||
|
onChange={this.handleOnChange.bind(this)}
|
||||||
|
/>
|
||||||
|
<MarkdownPreview
|
||||||
|
style={previewStyle}
|
||||||
|
styleName='preview'
|
||||||
|
theme={config.ui.theme}
|
||||||
|
keyMap={config.editor.keyMap}
|
||||||
|
fontSize={config.preview.fontSize}
|
||||||
|
fontFamily={config.preview.fontFamily}
|
||||||
|
codeBlockTheme={config.preview.codeBlockTheme}
|
||||||
|
codeBlockFontFamily={config.editor.fontFamily}
|
||||||
|
lineNumber={config.preview.lineNumber}
|
||||||
|
ref='preview'
|
||||||
|
tabInde='0'
|
||||||
|
value={value}
|
||||||
|
onCheckboxClick={(e) => this.handleCheckboxClick(e)}
|
||||||
|
showCopyNotification={config.ui.showCopyNotification}
|
||||||
|
storagePath={storage.path}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(MarkdownSplitEditor, styles)
|
||||||
9
browser/components/MarkdownSplitEditor.styl
Normal file
9
browser/components/MarkdownSplitEditor.styl
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
.root
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
font-size 30px
|
||||||
|
display flex
|
||||||
|
.codeEditor
|
||||||
|
width 50%
|
||||||
|
.preview
|
||||||
|
width 50%
|
||||||
@@ -9,6 +9,10 @@
|
|||||||
width 34px
|
width 34px
|
||||||
line-height 32px
|
line-height 32px
|
||||||
padding 0
|
padding 0
|
||||||
|
&:hover
|
||||||
|
border: 1px solid #1EC38B;
|
||||||
|
background-color: alpha(#1EC38B, 30%)
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
body[data-theme="white"]
|
body[data-theme="white"]
|
||||||
navWhiteButtonColor()
|
navWhiteButtonColor()
|
||||||
|
|||||||
@@ -231,3 +231,77 @@ body[data-theme="dark"]
|
|||||||
.item-bottom-tagList-empty
|
.item-bottom-tagList-empty
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
vertical-align middle
|
vertical-align middle
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
|
||||||
|
.item
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
&:hover
|
||||||
|
transition 0.15s
|
||||||
|
// background-color alpha($ui-solarized-dark-noteList-backgroundColor, 20%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-title
|
||||||
|
.item-title-icon
|
||||||
|
.item-bottom-time
|
||||||
|
transition 0.15s
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-bottom-tagList-item
|
||||||
|
transition 0.15s
|
||||||
|
background-color alpha($ui-solarized-dark-noteList-backgroundColor, 20%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:active
|
||||||
|
transition 0.15s
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-title
|
||||||
|
.item-title-icon
|
||||||
|
.item-bottom-time
|
||||||
|
transition 0.15s
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-bottom-tagList-item
|
||||||
|
transition 0.15s
|
||||||
|
background-color alpha($ui-solarized-dark-noteList-backgroundColor, 10%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.item-wrapper
|
||||||
|
border-color alpha($ui-solarized-dark-button--active-backgroundColor, 60%)
|
||||||
|
|
||||||
|
.item--active
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
.item-wrapper
|
||||||
|
border-color transparent
|
||||||
|
.item-title
|
||||||
|
.item-title-icon
|
||||||
|
.item-bottom-time
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-bottom-tagList-item
|
||||||
|
background-color alpha(white, 10%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
// background-color alpha($ui-solarized-dark-button--active-backgroundColor, 60%)
|
||||||
|
color #c0392b
|
||||||
|
.item-bottom-tagList-item
|
||||||
|
background-color alpha(#fff, 20%)
|
||||||
|
|
||||||
|
.item-title
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.item-title-icon
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.item-title-empty
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.item-bottom-tagList-item
|
||||||
|
background-color alpha($ui-dark-button--active-backgroundColor, 40%)
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.item-bottom-tagList-empty
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
vertical-align middle
|
||||||
@@ -14,7 +14,7 @@ import styles from './NoteItemSimple.styl'
|
|||||||
* @param {Function} handleNoteContextMenu
|
* @param {Function} handleNoteContextMenu
|
||||||
* @param {Function} handleDragStart
|
* @param {Function} handleDragStart
|
||||||
*/
|
*/
|
||||||
const NoteItemSimple = ({ isActive, note, handleNoteClick, handleNoteContextMenu, handleDragStart }) => (
|
const NoteItemSimple = ({ isActive, note, handleNoteClick, handleNoteContextMenu, handleDragStart, pathname }) => (
|
||||||
<div styleName={isActive
|
<div styleName={isActive
|
||||||
? 'item-simple--active'
|
? 'item-simple--active'
|
||||||
: 'item-simple'
|
: 'item-simple'
|
||||||
@@ -30,6 +30,10 @@ const NoteItemSimple = ({ isActive, note, handleNoteClick, handleNoteContextMenu
|
|||||||
? <i styleName='item-simple-title-icon' className='fa fa-fw fa-code' />
|
? <i styleName='item-simple-title-icon' className='fa fa-fw fa-code' />
|
||||||
: <i styleName='item-simple-title-icon' className='fa fa-fw fa-file-text-o' />
|
: <i styleName='item-simple-title-icon' className='fa fa-fw fa-file-text-o' />
|
||||||
}
|
}
|
||||||
|
{note.isPinned && !pathname.match(/\/home|\/starred|\/trash/)
|
||||||
|
? <i styleName='item-pin' className='fa fa-thumb-tack' />
|
||||||
|
: ''
|
||||||
|
}
|
||||||
{note.title.trim().length > 0
|
{note.title.trim().length > 0
|
||||||
? note.title
|
? note.title
|
||||||
: <span styleName='item-simple-title-empty'>Empty</span>
|
: <span styleName='item-simple-title-empty'>Empty</span>
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ $control-height = 30px
|
|||||||
.item-simple-title
|
.item-simple-title
|
||||||
font-size 13px
|
font-size 13px
|
||||||
height 40px
|
height 40px
|
||||||
|
padding-right 20px
|
||||||
box-sizing border-box
|
box-sizing border-box
|
||||||
line-height 24px
|
line-height 24px
|
||||||
padding-top 8px
|
padding-top 8px
|
||||||
@@ -67,6 +68,15 @@ $control-height = 30px
|
|||||||
font-weight normal
|
font-weight normal
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.item-pin
|
||||||
|
position absolute
|
||||||
|
right 0px
|
||||||
|
top 12px
|
||||||
|
color #E54D42
|
||||||
|
font-size 14px
|
||||||
|
padding 0
|
||||||
|
border-radius 17px
|
||||||
|
|
||||||
body[data-theme="white"]
|
body[data-theme="white"]
|
||||||
.item-simple
|
.item-simple
|
||||||
background-color $ui-white-noteList-backgroundColor
|
background-color $ui-white-noteList-backgroundColor
|
||||||
@@ -143,3 +153,57 @@ body[data-theme="dark"]
|
|||||||
|
|
||||||
.item-simple-title-empty
|
.item-simple-title-empty
|
||||||
color $ui-dark-inactive-text-color
|
color $ui-dark-inactive-text-color
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
|
||||||
|
.item-simple
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
&:hover
|
||||||
|
transition 0.15s
|
||||||
|
// background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-simple-title
|
||||||
|
.item-simple-title-icon
|
||||||
|
.item-simple-bottom-time
|
||||||
|
transition 0.15s
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-simple-bottom-tagList-item
|
||||||
|
transition 0.15s
|
||||||
|
background-color alpha(#fff, 20%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:active
|
||||||
|
transition 0.15s
|
||||||
|
background-color $ui-solarized-dark-button--active-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-simple-title
|
||||||
|
.item-simple-title-icon
|
||||||
|
.item-simple-bottom-time
|
||||||
|
transition 0.15s
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-simple-bottom-tagList-item
|
||||||
|
transition 0.15s
|
||||||
|
background-color alpha(white, 10%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.item-simple--active
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-button--active-backgroundColor
|
||||||
|
.item-simple-wrapper
|
||||||
|
border-color transparent
|
||||||
|
.item-simple-title
|
||||||
|
.item-simple-title-icon
|
||||||
|
.item-simple-bottom-time
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.item-simple-bottom-tagList-item
|
||||||
|
background-color alpha(white, 10%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
// background-color alpha($ui-dark-button--active-backgroundColor, 60%)
|
||||||
|
color #c0392b
|
||||||
|
.item-simple-bottom-tagList-item
|
||||||
|
background-color alpha(#fff, 20%)
|
||||||
@@ -29,3 +29,15 @@ body[data-theme="dark"]
|
|||||||
transition 0.2s
|
transition 0.2s
|
||||||
&:hover
|
&:hover
|
||||||
color #5CB85C
|
color #5CB85C
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.notification-area
|
||||||
|
background-color none
|
||||||
|
|
||||||
|
.notification-link
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
border none
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
&:hover
|
||||||
|
color #5CB85C
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const SideNavFilter = ({
|
|||||||
<div styleName='iconWrap'>
|
<div styleName='iconWrap'>
|
||||||
<img src={isStarredActive
|
<img src={isStarredActive
|
||||||
? '../resources/icon/icon-star-active.svg'
|
? '../resources/icon/icon-star-active.svg'
|
||||||
: '../resources/icon/icon-star.svg'
|
: '../resources/icon/icon-star-sidenav.svg'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,7 +55,7 @@ const SideNavFilter = ({
|
|||||||
<div styleName='iconWrap'>
|
<div styleName='iconWrap'>
|
||||||
<img src={isTrashedActive
|
<img src={isTrashedActive
|
||||||
? '../resources/icon/icon-trash-active.svg'
|
? '../resources/icon/icon-trash-active.svg'
|
||||||
: '../resources/icon/icon-trash.svg'
|
: '../resources/icon/icon-trash-sidenav.svg'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
.menu--folded
|
.menu--folded
|
||||||
@extend .menu
|
@extend .menu
|
||||||
.menu-button, .menu-button--active
|
.menu-button, .menu-button--active, .menu-button-star--active, .menu-button-trash--active
|
||||||
text-align center
|
text-align center
|
||||||
padding 0 12px
|
padding 0 12px
|
||||||
&:hover .menu-button-label
|
&:hover .menu-button-label
|
||||||
@@ -182,4 +182,47 @@ body[data-theme="dark"]
|
|||||||
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
||||||
color #5D9E36
|
color #5D9E36
|
||||||
.menu-button-label
|
.menu-button-label
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.menu-button
|
||||||
|
&:active
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.menu-button--active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
.menu-button-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.menu-button-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.menu-button-star--active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
.menu-button-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.menu-button-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.menu-button-trash--active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
.menu-button-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.menu-button-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
@@ -85,6 +85,15 @@ class SnippetTab extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleDragStart (e) {
|
||||||
|
e.dataTransfer.dropEffect = 'move'
|
||||||
|
this.props.onDragStart(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDrop (e) {
|
||||||
|
this.props.onDrop(e)
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { isActive, snippet, isDeletable } = this.props
|
const { isActive, snippet, isDeletable } = this.props
|
||||||
return (
|
return (
|
||||||
@@ -98,6 +107,9 @@ class SnippetTab extends React.Component {
|
|||||||
onClick={(e) => this.handleClick(e)}
|
onClick={(e) => this.handleClick(e)}
|
||||||
onDoubleClick={(e) => this.handleRenameClick(e)}
|
onDoubleClick={(e) => this.handleRenameClick(e)}
|
||||||
onContextMenu={(e) => this.handleContextMenu(e)}
|
onContextMenu={(e) => this.handleContextMenu(e)}
|
||||||
|
onDragStart={(e) => this.handleDragStart(e)}
|
||||||
|
onDrop={(e) => this.handleDrop(e)}
|
||||||
|
draggable='true'
|
||||||
>
|
>
|
||||||
{snippet.name.trim().length > 0
|
{snippet.name.trim().length > 0
|
||||||
? snippet.name
|
? snippet.name
|
||||||
@@ -127,6 +139,7 @@ class SnippetTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SnippetTab.propTypes = {
|
SnippetTab.propTypes = {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(SnippetTab, styles)
|
export default CSSModules(SnippetTab, styles)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
text-align center
|
text-align center
|
||||||
border none
|
border none
|
||||||
padding 0
|
padding 0
|
||||||
color transparent
|
color $ui-inactive-text-color
|
||||||
background-color transparent
|
background-color transparent
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
|
|
||||||
@@ -89,3 +89,50 @@ body[data-theme="dark"]
|
|||||||
.input
|
.input
|
||||||
background-color $ui-dark-button--hover-backgroundColor
|
background-color $ui-dark-button--hover-backgroundColor
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
.deleteButton
|
||||||
|
color alpha($ui-dark-text-color, 30%)
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
border-color $ui-dark-borderColor
|
||||||
|
&:hover
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
.deleteButton
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
background-color darken($ui-solarized-dark-noteDetail-backgroundColor, 15%)
|
||||||
|
&:active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-dark-button--active-backgroundColor
|
||||||
|
|
||||||
|
.root--active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
&:hover
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
.deleteButton
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
background-color darken($ui-solarized-dark-noteDetail-backgroundColor, 15%)
|
||||||
|
&:active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-dark-button--active-backgroundColor
|
||||||
|
|
||||||
|
.button
|
||||||
|
border none
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color transparent
|
||||||
|
transition color background-color 0.15s
|
||||||
|
border-left 4px solid transparent
|
||||||
|
&:hover
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
|
||||||
|
.input
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.deleteButton
|
||||||
|
color alpha($ui-solarized-dark-text-color, 30%)
|
||||||
@@ -108,4 +108,23 @@ body[data-theme="dark"]
|
|||||||
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
||||||
&:hover
|
&:hover
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
background-color alpha($ui-dark-button--active-backgroundColor, 50%)
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.folderList-item
|
||||||
|
&:hover
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
|
||||||
|
.folderList-item--active
|
||||||
|
@extend .folderList-item
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
&:active
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
&:hover
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
@@ -16,7 +16,9 @@ const TodoListPercentage = ({
|
|||||||
}) => (
|
}) => (
|
||||||
<div styleName='percentageBar' style={{display: isNaN(percentageOfTodo) ? 'none' : ''}}>
|
<div styleName='percentageBar' style={{display: isNaN(percentageOfTodo) ? 'none' : ''}}>
|
||||||
<div styleName='progressBar' style={{width: `${percentageOfTodo}%`}}>
|
<div styleName='progressBar' style={{width: `${percentageOfTodo}%`}}>
|
||||||
<p styleName='percentageText'>{percentageOfTodo}%</p>
|
<div styleName='progressBarInner'>
|
||||||
|
<p styleName='percentageText'>{percentageOfTodo}%</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,17 +16,36 @@
|
|||||||
border-radius 2px
|
border-radius 2px
|
||||||
transition 0.4s cubic-bezier(0.4, 0.4, 0, 1)
|
transition 0.4s cubic-bezier(0.4, 0.4, 0, 1)
|
||||||
|
|
||||||
|
.progressBarInner
|
||||||
|
padding 0 10px
|
||||||
|
min-width 1px
|
||||||
|
height 100%
|
||||||
|
display -webkit-box
|
||||||
|
display box
|
||||||
|
justify-content center
|
||||||
|
align-items center
|
||||||
|
|
||||||
|
|
||||||
.percentageText
|
.percentageText
|
||||||
color #f4f4f4
|
color #f4f4f4
|
||||||
padding: 2px 43%
|
|
||||||
font-weight 600
|
font-weight 600
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.percentageBar
|
.percentageBar
|
||||||
background-color #363A3D
|
background-color #444444
|
||||||
|
|
||||||
.progressBar
|
.progressBar
|
||||||
background-color: alpha(#939395, 50%)
|
background-color: #1EC38B
|
||||||
|
|
||||||
.percentageText
|
.percentageText
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.percentageBar
|
||||||
|
background-color #002b36
|
||||||
|
|
||||||
|
.progressBar
|
||||||
|
background-color: #2aa198
|
||||||
|
|
||||||
|
.percentageText
|
||||||
|
color #fdf6e3
|
||||||
@@ -77,6 +77,9 @@ body
|
|||||||
li
|
li
|
||||||
label.taskListItem
|
label.taskListItem
|
||||||
margin-left -2em
|
margin-left -2em
|
||||||
|
&.checked
|
||||||
|
text-decoration line-through
|
||||||
|
opacity 0.5
|
||||||
div.math-rendered
|
div.math-rendered
|
||||||
text-align center
|
text-align center
|
||||||
.math-failed
|
.math-failed
|
||||||
@@ -117,6 +120,7 @@ hr
|
|||||||
margin 15px 0
|
margin 15px 0
|
||||||
h1, h2, h3, h4, h5, h6
|
h1, h2, h3, h4, h5, h6
|
||||||
font-weight bold
|
font-weight bold
|
||||||
|
word-wrap break-word
|
||||||
h1
|
h1
|
||||||
font-size 2.55em
|
font-size 2.55em
|
||||||
padding-bottom 0.3em
|
padding-bottom 0.3em
|
||||||
@@ -154,6 +158,7 @@ p
|
|||||||
line-height 1.6em
|
line-height 1.6em
|
||||||
margin 0 0 1em
|
margin 0 0 1em
|
||||||
white-space pre-line
|
white-space pre-line
|
||||||
|
word-wrap break-word
|
||||||
img
|
img
|
||||||
max-width 100%
|
max-width 100%
|
||||||
strong, b
|
strong, b
|
||||||
@@ -329,4 +334,31 @@ body[data-theme="dark"]
|
|||||||
border-right solid 1px themeDarkTableBorder
|
border-right solid 1px themeDarkTableBorder
|
||||||
kbd
|
kbd
|
||||||
background-color themeDarkBorder
|
background-color themeDarkBorder
|
||||||
color themeDarkText
|
color themeDarkText
|
||||||
|
|
||||||
|
themeSolarizedDarkTableOdd = $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
themeSolarizedDarkTableEven = darken($ui-solarized-dark-noteDetail-backgroundColor, 10%)
|
||||||
|
themeSolarizedDarkTableHead = themeSolarizedDarkTableEven
|
||||||
|
themeSolarizedDarkTableBorder = themeDarkBorder
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
border-color themeDarkBorder
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
table
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
background-color themeSolarizedDarkTableHead
|
||||||
|
th
|
||||||
|
border-color themeSolarizedDarkTableBorder
|
||||||
|
&:last-child
|
||||||
|
border-right solid 1px themeSolarizedDarkTableBorder
|
||||||
|
tbody
|
||||||
|
tr:nth-child(2n + 1)
|
||||||
|
background-color themeSolarizedDarkTableOdd
|
||||||
|
tr:nth-child(2n)
|
||||||
|
background-color themeSolarizedDarkTableEven
|
||||||
|
td
|
||||||
|
border-color themeSolarizedDarkTableBorder
|
||||||
|
&:last-child
|
||||||
|
border-right solid 1px themeSolarizedDarkTableBorder
|
||||||
|
|||||||
@@ -116,3 +116,41 @@ body[data-theme="dark"]
|
|||||||
absolute top bottom right
|
absolute top bottom right
|
||||||
left $nav-width + $list-width
|
left $nav-width + $list-width
|
||||||
background-color $ui-dark-noteDetail-backgroundColor
|
background-color $ui-dark-noteDetail-backgroundColor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
.search
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
.search-input
|
||||||
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
.result
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
|
||||||
|
.result-nav
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
label
|
||||||
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
.result-nav-menu
|
||||||
|
navDarkButtonColor()
|
||||||
|
|
||||||
|
.result-nav-menu--active
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
color $ui-dark-button--active-color
|
||||||
|
&:hover
|
||||||
|
background-color $ui-dark-button--active-backgroundColor
|
||||||
|
|
||||||
|
.result-list
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
box-shadow none
|
||||||
|
top 0
|
||||||
|
|
||||||
|
.result-detail
|
||||||
|
absolute top bottom right
|
||||||
|
left $nav-width + $list-width
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import MarkdownPreview from 'browser/components/MarkdownPreview'
|
|||||||
import MarkdownEditor from 'browser/components/MarkdownEditor'
|
import MarkdownEditor from 'browser/components/MarkdownEditor'
|
||||||
import CodeEditor from 'browser/components/CodeEditor'
|
import CodeEditor from 'browser/components/CodeEditor'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
|
import 'codemirror-mode-elixir'
|
||||||
import { findStorage } from 'browser/lib/findStorage'
|
import { findStorage } from 'browser/lib/findStorage'
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
@@ -157,6 +158,7 @@ class NoteDetail extends React.Component {
|
|||||||
indentType={config.editor.indentType}
|
indentType={config.editor.indentType}
|
||||||
indentSize={editorIndentSize}
|
indentSize={editorIndentSize}
|
||||||
keyMap={config.editor.keyMap}
|
keyMap={config.editor.keyMap}
|
||||||
|
scrollPastEnd={config.editor.scrollPastEnd}
|
||||||
readOnly
|
readOnly
|
||||||
ref={'code-' + index}
|
ref={'code-' + index}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -95,3 +95,35 @@ body[data-theme="dark"]
|
|||||||
&:hover
|
&:hover
|
||||||
color white
|
color white
|
||||||
background-color $ui-dark-button--hover-backgroundColor
|
background-color $ui-dark-button--hover-backgroundColor
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
|
||||||
|
.description
|
||||||
|
border-color $ui-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
|
||||||
|
.description-textarea
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
color white
|
||||||
|
|
||||||
|
.tabList
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
|
||||||
|
.tabList-item
|
||||||
|
border-color $ui-dark-borderColor
|
||||||
|
&:hover
|
||||||
|
background-color $ui-dark-button--hover-backgroundColor
|
||||||
|
|
||||||
|
.tabList-item-button
|
||||||
|
border none
|
||||||
|
color $ui-dark-text-color
|
||||||
|
background-color transparent
|
||||||
|
transition color background-color 0.15s
|
||||||
|
border-left 4px solid transparent
|
||||||
|
&:hover
|
||||||
|
color white
|
||||||
|
background-color $ui-dark-button--hover-backgroundColor
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ nodeIpc.connectTo(
|
|||||||
document.body.setAttribute('data-theme', 'dark')
|
document.body.setAttribute('data-theme', 'dark')
|
||||||
} else if (config.ui.theme === 'white') {
|
} else if (config.ui.theme === 'white') {
|
||||||
document.body.setAttribute('data-theme', 'white')
|
document.body.setAttribute('data-theme', 'white')
|
||||||
|
} else if (config.ui.theme === 'solarized-dark') {
|
||||||
|
document.body.setAttribute('data-theme', 'solarized-dark')
|
||||||
} else {
|
} else {
|
||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
|
import 'codemirror-mode-elixir'
|
||||||
|
|
||||||
CodeMirror.modeInfo.push({name: 'Stylus', mime: 'text/x-styl', mode: 'stylus', ext: ['styl'], alias: ['styl']})
|
CodeMirror.modeInfo.push({name: 'Stylus', mime: 'text/x-styl', mode: 'stylus', ext: ['styl'], alias: ['styl']})
|
||||||
|
CodeMirror.modeInfo.push({name: 'Elixir', mime: 'text/x-elixir', mode: 'elixir', ext: ['ex']})
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export function getTodoStatus (content) {
|
|||||||
|
|
||||||
splitted.forEach((line) => {
|
splitted.forEach((line) => {
|
||||||
const trimmedLine = line.trim()
|
const trimmedLine = line.trim()
|
||||||
if (trimmedLine.match(/^[\+\-\*] \[\s|x\] ./)) {
|
if (trimmedLine.match(/^[\+\-\*] \[(\s|x)\] ./)) {
|
||||||
numberOfTodo++
|
numberOfTodo++
|
||||||
}
|
}
|
||||||
if (trimmedLine.match(/^[\+\-\*] \[x\] ./)) {
|
if (trimmedLine.match(/^[\+\-\*] \[x\] ./)) {
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ import markdownit from 'markdown-it'
|
|||||||
import emoji from 'markdown-it-emoji'
|
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'
|
||||||
|
import ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
|
|
||||||
// FIXME We should not depend on global variable.
|
// FIXME We should not depend on global variable.
|
||||||
const katex = window.katex
|
const katex = window.katex
|
||||||
|
const config = ConfigManager.get()
|
||||||
|
|
||||||
function createGutter (str) {
|
function createGutter (str) {
|
||||||
const lc = (str.match(/\n/g) || []).length
|
const lc = (str.match(/\n/g) || []).length
|
||||||
@@ -39,6 +41,10 @@ md.use(emoji, {
|
|||||||
shortcuts: {}
|
shortcuts: {}
|
||||||
})
|
})
|
||||||
md.use(math, {
|
md.use(math, {
|
||||||
|
inlineOpen: config.preview.latexInlineOpen,
|
||||||
|
inlineClose: config.preview.latexInlineClose,
|
||||||
|
blockOpen: config.preview.latexBlockOpen,
|
||||||
|
blockClose: config.preview.latexBlockClose,
|
||||||
inlineRenderer: function (str) {
|
inlineRenderer: function (str) {
|
||||||
let output = ''
|
let output = ''
|
||||||
try {
|
try {
|
||||||
@@ -109,7 +115,7 @@ md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
|
|||||||
if (state.parentType === 'list') {
|
if (state.parentType === 'list') {
|
||||||
const 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${match[1] !== ' ' ? ' checked' : ''}' for='checkbox-${startLine + 1}'><input type='checkbox'${match[1] !== ' ' ? ' checked' : ''} id='checkbox-${startLine + 1}'/> ${content.substring(4, content.length)}</label>`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,3 +22,9 @@ body[data-theme="dark"]
|
|||||||
background-color $ui-dark-backgroundColor
|
background-color $ui-dark-backgroundColor
|
||||||
.empty-message
|
.empty-message
|
||||||
color $ui-dark-inactive-text-color
|
color $ui-dark-inactive-text-color
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
.empty-message
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|||||||
19
browser/main/Detail/FullscreenButton.js
Normal file
19
browser/main/Detail/FullscreenButton.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './FullscreenButton.styl'
|
||||||
|
|
||||||
|
const FullscreenButton = ({
|
||||||
|
onClick
|
||||||
|
}) => (
|
||||||
|
<button styleName='control-fullScreenButton' title='Fullscreen' onMouseDown={(e) => onClick(e)}>
|
||||||
|
<img styleName='iconInfo' src='../resources/icon/icon-full.svg' />
|
||||||
|
<span styleName='tooltip'>Fullscreen</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
FullscreenButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(FullscreenButton, styles)
|
||||||
22
browser/main/Detail/FullscreenButton.styl
Normal file
22
browser/main/Detail/FullscreenButton.styl
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
.control-fullScreenButton
|
||||||
|
top 80px
|
||||||
|
topBarButtonRight()
|
||||||
|
&:hover .tooltip
|
||||||
|
opacity 1
|
||||||
|
|
||||||
|
.tooltip
|
||||||
|
tooltip()
|
||||||
|
position absolute
|
||||||
|
pointer-events none
|
||||||
|
top 26px
|
||||||
|
right 0
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
|
body[data-theme="dark"]
|
||||||
|
.control-fullScreenButton
|
||||||
|
topBarButtonDark()
|
||||||
@@ -10,6 +10,7 @@ const InfoButton = ({
|
|||||||
onClick={(e) => onClick(e)}
|
onClick={(e) => onClick(e)}
|
||||||
>
|
>
|
||||||
<img className='infoButton' src='../resources/icon/icon-info.svg' />
|
<img className='infoButton' src='../resources/icon/icon-info.svg' />
|
||||||
|
<span styleName='tooltip'>Info</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
.control-infoButton
|
.control-infoButton
|
||||||
top 10px
|
top 10px
|
||||||
margin-bottom 10px
|
topBarButtonRight()
|
||||||
topBarButtonLight()
|
&:hover .tooltip
|
||||||
|
opacity 1
|
||||||
|
|
||||||
|
.tooltip
|
||||||
|
tooltip()
|
||||||
|
position absolute
|
||||||
|
pointer-events none
|
||||||
|
top 26px
|
||||||
|
right 0
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
.infoButton
|
.infoButton
|
||||||
padding 0px
|
padding 0px
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import CSSModules from 'browser/lib/CSSModules'
|
|||||||
import styles from './InfoPanel.styl'
|
import styles from './InfoPanel.styl'
|
||||||
|
|
||||||
const InfoPanel = ({
|
const InfoPanel = ({
|
||||||
storageName, folderName, noteLink, updatedAt, createdAt, exportAsMd, exportAsTxt, wordCount, letterCount, type, print
|
storageName, folderName, noteLink, updatedAt, createdAt, exportAsMd, exportAsTxt, exportAsHtml, wordCount, letterCount, type, print
|
||||||
}) => (
|
}) => (
|
||||||
<div className='infoPanel' styleName='control-infoButton-panel' style={{display: 'none'}}>
|
<div className='infoPanel' styleName='control-infoButton-panel' style={{display: 'none'}}>
|
||||||
<div>
|
<div>
|
||||||
@@ -57,17 +57,22 @@ const InfoPanel = ({
|
|||||||
|
|
||||||
<div id='export-wrap'>
|
<div id='export-wrap'>
|
||||||
<button styleName='export--enable' onClick={(e) => exportAsMd(e)}>
|
<button styleName='export--enable' onClick={(e) => exportAsMd(e)}>
|
||||||
<i className='fa fa-file-code-o fa-fw' />
|
<i className='fa fa-file-code-o' />
|
||||||
<p>.md</p>
|
<p>.md</p>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button styleName='export--enable' onClick={(e) => exportAsTxt(e)}>
|
<button styleName='export--enable' onClick={(e) => exportAsTxt(e)}>
|
||||||
<i className='fa fa-file-text-o fa-fw' />
|
<i className='fa fa-file-text-o' />
|
||||||
<p>.txt</p>
|
<p>.txt</p>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button styleName='export--enable' onClick={(e) => exportAsHtml(e)}>
|
||||||
|
<i className='fa fa-html5' />
|
||||||
|
<p>.html</p>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button styleName='export--enable' onClick={(e) => print(e)}>
|
<button styleName='export--enable' onClick={(e) => print(e)}>
|
||||||
<i className='fa fa-print fa-fw' />
|
<i className='fa fa-print' />
|
||||||
<p>Print</p>
|
<p>Print</p>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -82,6 +87,7 @@ InfoPanel.propTypes = {
|
|||||||
createdAt: PropTypes.string.isRequired,
|
createdAt: PropTypes.string.isRequired,
|
||||||
exportAsMd: PropTypes.func.isRequired,
|
exportAsMd: PropTypes.func.isRequired,
|
||||||
exportAsTxt: PropTypes.func.isRequired,
|
exportAsTxt: PropTypes.func.isRequired,
|
||||||
|
exportAsHtml: PropTypes.func.isRequired,
|
||||||
wordCount: PropTypes.number,
|
wordCount: PropTypes.number,
|
||||||
letterCount: PropTypes.number,
|
letterCount: PropTypes.number,
|
||||||
type: PropTypes.string.isRequired,
|
type: PropTypes.string.isRequired,
|
||||||
|
|||||||
@@ -41,12 +41,12 @@
|
|||||||
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)
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
|
|
||||||
.count-wrap
|
.count-wrap
|
||||||
display flex
|
display flex
|
||||||
position relative
|
position relative
|
||||||
width 100%
|
width 100%
|
||||||
|
|
||||||
.count-number
|
.count-number
|
||||||
position relative
|
position relative
|
||||||
display block
|
display block
|
||||||
width 50%
|
width 50%
|
||||||
@@ -81,15 +81,15 @@
|
|||||||
margin-bottom 6px
|
margin-bottom 6px
|
||||||
|
|
||||||
.infoPanel-trash
|
.infoPanel-trash
|
||||||
color #EA4447
|
color #EA4447
|
||||||
font-weight 600
|
font-weight 600
|
||||||
font-size 14px
|
font-size 14px
|
||||||
width 70px
|
width 70px
|
||||||
background-color rgba(226,33,113,0.1)
|
background-color rgba(226,33,113,0.1)
|
||||||
border none
|
border none
|
||||||
outline none
|
outline none
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
margin-right 5px
|
margin-right 5px
|
||||||
padding 2px 5px
|
padding 2px 5px
|
||||||
|
|
||||||
[id=export-wrap]
|
[id=export-wrap]
|
||||||
@@ -160,4 +160,44 @@ body[data-theme="dark"]
|
|||||||
p
|
p
|
||||||
color $ui-dark-inactive-text-color
|
color $ui-dark-inactive-text-color
|
||||||
&:hover
|
&:hover
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.control-infoButton-panel
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control-infoButton-panel-trash
|
||||||
|
background-color $ui-solarized-ark-noteList-backgroundColor
|
||||||
|
|
||||||
|
.modification-date
|
||||||
|
color $ui-solarized-ark-text-color
|
||||||
|
|
||||||
|
.modification-date-desc
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.infoPanel-defaul-count
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.infoPanel-sub-count
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.infoPanel-default
|
||||||
|
color $ui-solarized-ark-text-color
|
||||||
|
|
||||||
|
.infoPanel-sub
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.infoPanel-noteLink
|
||||||
|
background-color alpha($ui-solarized-dark-borderColor, 20%)
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
[id=export-wrap]
|
||||||
|
button
|
||||||
|
color $ui-dark-inactive-text-color
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-solarized-dark-borderColor, 20%)
|
||||||
|
color $ui-solarized-ark-text-color
|
||||||
|
p
|
||||||
|
color $ui-dark-inactive-text-color
|
||||||
|
&:hover
|
||||||
|
color $ui-solarized-ark-text-color
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import CSSModules from 'browser/lib/CSSModules'
|
|||||||
import styles from './InfoPanel.styl'
|
import styles from './InfoPanel.styl'
|
||||||
|
|
||||||
const InfoPanelTrashed = ({
|
const InfoPanelTrashed = ({
|
||||||
storageName, folderName, updatedAt, createdAt, exportAsMd, exportAsTxt
|
storageName, folderName, updatedAt, createdAt, exportAsMd, exportAsTxt, exportAsHtml
|
||||||
}) => (
|
}) => (
|
||||||
<div className='infoPanel' styleName='control-infoButton-panel-trash' style={{display: 'none'}}>
|
<div className='infoPanel' styleName='control-infoButton-panel-trash' style={{display: 'none'}}>
|
||||||
<div>
|
<div>
|
||||||
@@ -31,17 +31,22 @@ const InfoPanelTrashed = ({
|
|||||||
|
|
||||||
<div id='export-wrap'>
|
<div id='export-wrap'>
|
||||||
<button styleName='export--enable' onClick={(e) => exportAsMd(e)}>
|
<button styleName='export--enable' onClick={(e) => exportAsMd(e)}>
|
||||||
<i className='fa fa-file-code-o fa-fw' />
|
<i className='fa fa-file-code-o' />
|
||||||
<p>.md</p>
|
<p>.md</p>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button styleName='export--enable' onClick={(e) => exportAsTxt(e)}>
|
<button styleName='export--enable' onClick={(e) => exportAsTxt(e)}>
|
||||||
<i className='fa fa-file-text-o fa-fw' />
|
<i className='fa fa-file-text-o' />
|
||||||
<p>.txt</p>
|
<p>.txt</p>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<button styleName='export--enable' onClick={(e) => exportAsHtml(e)}>
|
||||||
|
<i className='fa fa-html5' />
|
||||||
|
<p>.html</p>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button styleName='export--unable'>
|
<button styleName='export--unable'>
|
||||||
<i className='fa fa-file-pdf-o fa-fw' />
|
<i className='fa fa-file-pdf-o' />
|
||||||
<p>.pdf</p>
|
<p>.pdf</p>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,7 +59,8 @@ InfoPanelTrashed.propTypes = {
|
|||||||
updatedAt: PropTypes.string.isRequired,
|
updatedAt: PropTypes.string.isRequired,
|
||||||
createdAt: PropTypes.string.isRequired,
|
createdAt: PropTypes.string.isRequired,
|
||||||
exportAsMd: PropTypes.func.isRequired,
|
exportAsMd: PropTypes.func.isRequired,
|
||||||
exportAsTxt: PropTypes.func.isRequired
|
exportAsTxt: PropTypes.func.isRequired,
|
||||||
|
exportAsHtml: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(InfoPanelTrashed, styles)
|
export default CSSModules(InfoPanelTrashed, styles)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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'
|
||||||
|
import MarkdownSplitEditor from 'browser/components/MarkdownSplitEditor'
|
||||||
import TodoListPercentage from 'browser/components/TodoListPercentage'
|
import TodoListPercentage from 'browser/components/TodoListPercentage'
|
||||||
import StarButton from './StarButton'
|
import StarButton from './StarButton'
|
||||||
import TagSelect from './TagSelect'
|
import TagSelect from './TagSelect'
|
||||||
@@ -15,19 +16,18 @@ 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 ConfigManager from 'browser/main/lib/ConfigManager'
|
||||||
import TrashButton from './TrashButton'
|
import TrashButton from './TrashButton'
|
||||||
|
import FullscreenButton from './FullscreenButton'
|
||||||
import PermanentDeleteButton from './PermanentDeleteButton'
|
import PermanentDeleteButton from './PermanentDeleteButton'
|
||||||
import InfoButton from './InfoButton'
|
import InfoButton from './InfoButton'
|
||||||
|
import ToggleModeButton from './ToggleModeButton'
|
||||||
import InfoPanel from './InfoPanel'
|
import InfoPanel from './InfoPanel'
|
||||||
import InfoPanelTrashed from './InfoPanelTrashed'
|
import InfoPanelTrashed from './InfoPanelTrashed'
|
||||||
import { formatDate } from 'browser/lib/date-formatter'
|
import { formatDate } from 'browser/lib/date-formatter'
|
||||||
import { getTodoPercentageOfCompleted } from 'browser/lib/getTodoStatus'
|
import { getTodoPercentageOfCompleted } from 'browser/lib/getTodoStatus'
|
||||||
import striptags from 'striptags'
|
import striptags from 'striptags'
|
||||||
|
|
||||||
const electron = require('electron')
|
|
||||||
const { remote } = electron
|
|
||||||
const { dialog } = remote
|
|
||||||
|
|
||||||
class MarkdownNoteDetail extends React.Component {
|
class MarkdownNoteDetail extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props)
|
super(props)
|
||||||
@@ -39,7 +39,8 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
content: ''
|
content: ''
|
||||||
}, props.note),
|
}, props.note),
|
||||||
isLockButtonShown: false,
|
isLockButtonShown: false,
|
||||||
isLocked: false
|
isLocked: false,
|
||||||
|
editorType: props.config.editor.type
|
||||||
}
|
}
|
||||||
this.dispatchTimer = null
|
this.dispatchTimer = null
|
||||||
|
|
||||||
@@ -74,17 +75,22 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
ee.off('topbar:togglelockbutton', this.toggleLockButton)
|
ee.off('topbar:togglelockbutton', this.toggleLockButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleChange (e) {
|
handleUpdateTag () {
|
||||||
const { note } = this.state
|
const { note } = this.state
|
||||||
|
|
||||||
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
|
||||||
note.title = markdown.strip(striptags(findNoteTitle(note.content)))
|
this.updateNote(note)
|
||||||
note.updatedAt = new Date()
|
}
|
||||||
|
|
||||||
this.setState({
|
handleUpdateContent () {
|
||||||
note
|
const { note } = this.state
|
||||||
}, () => {
|
note.content = this.refs.content.value
|
||||||
|
note.title = markdown.strip(striptags(findNoteTitle(note.content)))
|
||||||
|
this.updateNote(note)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateNote (note) {
|
||||||
|
note.updatedAt = new Date()
|
||||||
|
this.setState({note}, () => {
|
||||||
this.save()
|
this.save()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -170,41 +176,44 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
ee.emit('export:save-text')
|
ee.emit('export:save-text')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exportAsHtml () {
|
||||||
|
ee.emit('export:save-html')
|
||||||
|
}
|
||||||
|
|
||||||
handleTrashButtonClick (e) {
|
handleTrashButtonClick (e) {
|
||||||
const { note } = this.state
|
const { note } = this.state
|
||||||
const { isTrashed } = note
|
const { isTrashed } = note
|
||||||
|
const { confirmDeletion } = this.props
|
||||||
|
|
||||||
if (isTrashed) {
|
if (isTrashed) {
|
||||||
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
if (confirmDeletion(true)) {
|
||||||
type: 'warning',
|
const {note, dispatch} = this.props
|
||||||
message: 'Confirm note deletion',
|
dataApi
|
||||||
detail: 'This will permanently remove this note.',
|
.deleteNote(note.storage, note.key)
|
||||||
buttons: ['Confirm', 'Cancel']
|
.then((data) => {
|
||||||
})
|
const dispatchHandler = () => {
|
||||||
if (dialogueButtonIndex === 1) return
|
dispatch({
|
||||||
const { note, dispatch } = this.props
|
type: 'DELETE_NOTE',
|
||||||
dataApi
|
storageKey: data.storageKey,
|
||||||
.deleteNote(note.storage, note.key)
|
noteKey: data.noteKey
|
||||||
.then((data) => {
|
})
|
||||||
const dispatchHandler = () => {
|
}
|
||||||
dispatch({
|
ee.once('list:moved', dispatchHandler)
|
||||||
type: 'DELETE_NOTE',
|
})
|
||||||
storageKey: data.storageKey,
|
}
|
||||||
noteKey: data.noteKey
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ee.once('list:moved', dispatchHandler)
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
note.isTrashed = true
|
if (confirmDeletion()) {
|
||||||
|
note.isTrashed = true
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
note
|
note
|
||||||
}, () => {
|
}, () => {
|
||||||
this.save()
|
this.save()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ee.emit('list:next')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ee.emit('list:next')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleUndoButtonClick (e) {
|
handleUndoButtonClick (e) {
|
||||||
@@ -233,7 +242,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getToggleLockButton () {
|
getToggleLockButton () {
|
||||||
return this.state.isLocked ? '../resources/icon/icon-lock.svg' : '../resources/icon/icon-unlock.svg'
|
return this.state.isLocked ? '../resources/icon/icon-previewoff-on.svg' : '../resources/icon/icon-previewoff-off.svg'
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDeleteKeyDown (e) {
|
handleDeleteKeyDown (e) {
|
||||||
@@ -262,9 +271,42 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
ee.emit('print')
|
ee.emit('print')
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
handleSwitchMode (type) {
|
||||||
const { data, config, location } = this.props
|
this.setState({ editorType: type }, () => {
|
||||||
|
const newConfig = Object.assign({}, this.props.config)
|
||||||
|
newConfig.editor.type = type
|
||||||
|
ConfigManager.set(newConfig)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEditor () {
|
||||||
|
const { config, ignorePreviewPointerEvents } = this.props
|
||||||
const { note } = this.state
|
const { note } = this.state
|
||||||
|
if (this.state.editorType === 'EDITOR_PREVIEW') {
|
||||||
|
return <MarkdownEditor
|
||||||
|
ref='content'
|
||||||
|
styleName='body-noteEditor'
|
||||||
|
config={config}
|
||||||
|
value={note.content}
|
||||||
|
storageKey={note.storage}
|
||||||
|
onChange={this.handleUpdateContent.bind(this)}
|
||||||
|
ignorePreviewPointerEvents={ignorePreviewPointerEvents}
|
||||||
|
/>
|
||||||
|
} else {
|
||||||
|
return <MarkdownSplitEditor
|
||||||
|
ref='content'
|
||||||
|
config={config}
|
||||||
|
value={note.content}
|
||||||
|
storageKey={note.storage}
|
||||||
|
onChange={this.handleUpdateContent.bind(this)}
|
||||||
|
ignorePreviewPointerEvents={ignorePreviewPointerEvents}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { data, location } = this.props
|
||||||
|
const { note, editorType } = this.state
|
||||||
const storageKey = note.storage
|
const storageKey = note.storage
|
||||||
const folderKey = note.folder
|
const folderKey = note.folder
|
||||||
|
|
||||||
@@ -296,6 +338,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
folderName={currentOption.folder.name}
|
folderName={currentOption.folder.name}
|
||||||
updatedAt={formatDate(note.updatedAt)}
|
updatedAt={formatDate(note.updatedAt)}
|
||||||
createdAt={formatDate(note.createdAt)}
|
createdAt={formatDate(note.createdAt)}
|
||||||
|
exportAsHtml={this.exportAsHtml}
|
||||||
exportAsMd={this.exportAsMd}
|
exportAsMd={this.exportAsMd}
|
||||||
exportAsTxt={this.exportAsTxt}
|
exportAsTxt={this.exportAsTxt}
|
||||||
/>
|
/>
|
||||||
@@ -316,11 +359,12 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
<TagSelect
|
<TagSelect
|
||||||
ref='tags'
|
ref='tags'
|
||||||
value={this.state.note.tags}
|
value={this.state.note.tags}
|
||||||
onChange={(e) => this.handleChange(e)}
|
onChange={this.handleUpdateTag.bind(this)}
|
||||||
/>
|
|
||||||
<TodoListPercentage
|
|
||||||
percentageOfTodo={getTodoPercentageOfCompleted(note.content)}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ToggleModeButton onClick={(e) => this.handleSwitchMode(e)} editorType={editorType} />
|
||||||
|
|
||||||
|
<TodoListPercentage percentageOfTodo={getTodoPercentageOfCompleted(note.content)} />
|
||||||
</div>
|
</div>
|
||||||
<div styleName='info-right'>
|
<div styleName='info-right'>
|
||||||
<InfoButton
|
<InfoButton
|
||||||
@@ -347,11 +391,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
)
|
)
|
||||||
})()}
|
})()}
|
||||||
|
|
||||||
<button styleName='control-fullScreenButton'
|
<FullscreenButton onClick={(e) => this.handleFullScreenButton(e)} />
|
||||||
onMouseDown={(e) => this.handleFullScreenButton(e)}
|
|
||||||
>
|
|
||||||
<img styleName='iconInfo' src='../resources/icon/icon-sidebar.svg' />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
<TrashButton onClick={(e) => this.handleTrashButtonClick(e)} />
|
||||||
|
|
||||||
@@ -363,6 +403,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
createdAt={formatDate(note.createdAt)}
|
createdAt={formatDate(note.createdAt)}
|
||||||
exportAsMd={this.exportAsMd}
|
exportAsMd={this.exportAsMd}
|
||||||
exportAsTxt={this.exportAsTxt}
|
exportAsTxt={this.exportAsTxt}
|
||||||
|
exportAsHtml={this.exportAsHtml}
|
||||||
wordCount={note.content.split(' ').length}
|
wordCount={note.content.split(' ').length}
|
||||||
letterCount={note.content.replace(/\r?\n/g, '').length}
|
letterCount={note.content.replace(/\r?\n/g, '').length}
|
||||||
type={note.type}
|
type={note.type}
|
||||||
@@ -380,15 +421,7 @@ class MarkdownNoteDetail extends React.Component {
|
|||||||
{location.pathname === '/trashed' ? trashTopBar : detailTopBar}
|
{location.pathname === '/trashed' ? trashTopBar : detailTopBar}
|
||||||
|
|
||||||
<div styleName='body'>
|
<div styleName='body'>
|
||||||
<MarkdownEditor
|
{this.renderEditor()}
|
||||||
ref='content'
|
|
||||||
styleName='body-noteEditor'
|
|
||||||
config={config}
|
|
||||||
value={this.state.note.content}
|
|
||||||
storageKey={this.state.note.storage}
|
|
||||||
onChange={(e) => this.handleChange(e)}
|
|
||||||
ignorePreviewPointerEvents={this.props.ignorePreviewPointerEvents}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StatusBar
|
<StatusBar
|
||||||
@@ -409,7 +442,8 @@ MarkdownNoteDetail.propTypes = {
|
|||||||
style: PropTypes.shape({
|
style: PropTypes.shape({
|
||||||
left: PropTypes.number
|
left: PropTypes.number
|
||||||
}),
|
}),
|
||||||
ignorePreviewPointerEvents: PropTypes.bool
|
ignorePreviewPointerEvents: PropTypes.bool,
|
||||||
|
confirmDeletion: PropTypes.bool.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(MarkdownNoteDetail, styles)
|
export default CSSModules(MarkdownNoteDetail, styles)
|
||||||
|
|||||||
@@ -12,18 +12,13 @@
|
|||||||
padding-bottom 3px
|
padding-bottom 3px
|
||||||
|
|
||||||
.control-lockButton
|
.control-lockButton
|
||||||
top 160px
|
top 150px
|
||||||
margin-bottom 10px
|
topBarButtonRight()
|
||||||
topBarButtonLight()
|
|
||||||
|
|
||||||
.trashed-infopanel
|
.trashed-infopanel
|
||||||
top 40px
|
top 40px
|
||||||
position relative
|
position relative
|
||||||
|
|
||||||
.control-fullScreenButton
|
|
||||||
top 80px
|
|
||||||
topBarButtonLight()
|
|
||||||
|
|
||||||
.body
|
.body
|
||||||
absolute left right
|
absolute left right
|
||||||
left 0
|
left 0
|
||||||
@@ -33,7 +28,7 @@
|
|||||||
margin 0 45px
|
margin 0 45px
|
||||||
.body-noteEditor
|
.body-noteEditor
|
||||||
absolute top bottom left right
|
absolute top bottom left right
|
||||||
|
|
||||||
body[data-theme="white"]
|
body[data-theme="white"]
|
||||||
.root
|
.root
|
||||||
box-shadow $note-detail-box-shadow
|
box-shadow $note-detail-box-shadow
|
||||||
@@ -43,7 +38,7 @@ 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
|
border-left 1px solid $ui-dark-borderColor
|
||||||
|
|
||||||
.control-lockButton
|
.control-lockButton
|
||||||
topBarButtonDark()
|
topBarButtonDark()
|
||||||
@@ -53,3 +48,9 @@ body[data-theme="dark"]
|
|||||||
|
|
||||||
.control-fullScreenButton
|
.control-fullScreenButton
|
||||||
topBarButtonDark()
|
topBarButtonDark()
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
border-left 1px solid $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
|||||||
@@ -95,4 +95,10 @@ body[data-theme="dark"]
|
|||||||
background-color $ui-dark-noteDetail-backgroundColor
|
background-color $ui-dark-noteDetail-backgroundColor
|
||||||
|
|
||||||
.undo-button
|
.undo-button
|
||||||
topBarButtonDark()
|
topBarButtonDark()
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.info
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const PermanentDeleteButton = ({
|
|||||||
onClick={(e) => onClick(e)}
|
onClick={(e) => onClick(e)}
|
||||||
>
|
>
|
||||||
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
|
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
|
||||||
|
<span styleName='tooltip'>Permanent Delete</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ 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 CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
|
import 'codemirror-mode-elixir'
|
||||||
import SnippetTab from 'browser/components/SnippetTab'
|
import SnippetTab from 'browser/components/SnippetTab'
|
||||||
import StatusBar from '../StatusBar'
|
import StatusBar from '../StatusBar'
|
||||||
import context from 'browser/lib/context'
|
import context from 'browser/lib/context'
|
||||||
@@ -175,38 +176,37 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
handleTrashButtonClick (e) {
|
handleTrashButtonClick (e) {
|
||||||
const { note } = this.state
|
const { note } = this.state
|
||||||
const { isTrashed } = note
|
const { isTrashed } = note
|
||||||
|
const { confirmDeletion } = this.props
|
||||||
|
|
||||||
if (isTrashed) {
|
if (isTrashed) {
|
||||||
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), {
|
if (confirmDeletion(true)) {
|
||||||
type: 'warning',
|
const {note, dispatch} = this.props
|
||||||
message: 'Confirm note deletion',
|
dataApi
|
||||||
detail: 'This will permanently remove this note.',
|
.deleteNote(note.storage, note.key)
|
||||||
buttons: ['Confirm', 'Cancel']
|
.then((data) => {
|
||||||
})
|
const dispatchHandler = () => {
|
||||||
if (dialogueButtonIndex === 1) return
|
dispatch({
|
||||||
const { note, dispatch } = this.props
|
type: 'DELETE_NOTE',
|
||||||
dataApi
|
storageKey: data.storageKey,
|
||||||
.deleteNote(note.storage, note.key)
|
noteKey: data.noteKey
|
||||||
.then((data) => {
|
})
|
||||||
const dispatchHandler = () => {
|
}
|
||||||
dispatch({
|
ee.once('list:moved', dispatchHandler)
|
||||||
type: 'DELETE_NOTE',
|
})
|
||||||
storageKey: data.storageKey,
|
}
|
||||||
noteKey: data.noteKey
|
|
||||||
})
|
|
||||||
}
|
|
||||||
ee.once('list:moved', dispatchHandler)
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
note.isTrashed = true
|
if (confirmDeletion()) {
|
||||||
|
note.isTrashed = true
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
note
|
note
|
||||||
}, () => {
|
}, () => {
|
||||||
this.save()
|
this.save()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ee.emit('list:next')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ee.emit('list:next')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleUndoButtonClick (e) {
|
handleUndoButtonClick (e) {
|
||||||
@@ -236,6 +236,27 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleTabDragStart (e, index) {
|
||||||
|
e.dataTransfer.setData('text/plain', index)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTabDrop (e, index) {
|
||||||
|
const oldIndex = parseInt(e.dataTransfer.getData('text'))
|
||||||
|
|
||||||
|
const snippets = this.state.note.snippets.slice()
|
||||||
|
const draggedSnippet = snippets[oldIndex]
|
||||||
|
snippets[oldIndex] = snippets[index]
|
||||||
|
snippets[index] = draggedSnippet
|
||||||
|
const snippetIndex = index
|
||||||
|
|
||||||
|
const note = Object.assign({}, this.state.note, {snippets})
|
||||||
|
this.setState({ note, snippetIndex }, () => {
|
||||||
|
this.save()
|
||||||
|
this.refs['code-' + index].reload()
|
||||||
|
this.refs['code-' + oldIndex].reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@@ -359,7 +380,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
|
|
||||||
handleModeButtonClick (e, index) {
|
handleModeButtonClick (e, index) {
|
||||||
const menu = new Menu()
|
const menu = new Menu()
|
||||||
CodeMirror.modeInfo.forEach((mode) => {
|
CodeMirror.modeInfo.sort(function (a, b) { return a.name.localeCompare(b.name) }).forEach((mode) => {
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
label: mode.name,
|
label: mode.name,
|
||||||
click: (e) => this.handleModeOptionClick(index, mode.name)(e)
|
click: (e) => this.handleModeOptionClick(index, mode.name)(e)
|
||||||
@@ -511,6 +532,8 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
onDelete={(e) => this.handleTabDeleteButtonClick(e, index)}
|
onDelete={(e) => this.handleTabDeleteButtonClick(e, index)}
|
||||||
onRename={(name) => this.renameSnippetByIndex(index, name)}
|
onRename={(name) => this.renameSnippetByIndex(index, name)}
|
||||||
isDeletable={note.snippets.length > 1}
|
isDeletable={note.snippets.length > 1}
|
||||||
|
onDragStart={(e) => this.handleTabDragStart(e, index)}
|
||||||
|
onDrop={(e) => this.handleTabDrop(e, index)}
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -542,6 +565,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
indentType={config.editor.indentType}
|
indentType={config.editor.indentType}
|
||||||
indentSize={editorIndentSize}
|
indentSize={editorIndentSize}
|
||||||
keyMap={config.editor.keyMap}
|
keyMap={config.editor.keyMap}
|
||||||
|
scrollPastEnd={config.editor.scrollPastEnd}
|
||||||
onChange={(e) => this.handleCodeChange(index)(e)}
|
onChange={(e) => this.handleCodeChange(index)(e)}
|
||||||
ref={'code-' + index}
|
ref={'code-' + index}
|
||||||
/>
|
/>
|
||||||
@@ -579,6 +603,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
createdAt={formatDate(note.createdAt)}
|
createdAt={formatDate(note.createdAt)}
|
||||||
exportAsMd={this.showWarning}
|
exportAsMd={this.showWarning}
|
||||||
exportAsTxt={this.showWarning}
|
exportAsTxt={this.showWarning}
|
||||||
|
exportAsHtml={this.showWarning}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -610,7 +635,7 @@ class SnippetNoteDetail extends React.Component {
|
|||||||
isActive={note.isStarred}
|
isActive={note.isStarred}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button styleName='control-fullScreenButton'
|
<button styleName='control-fullScreenButton' title='Fullscreen'
|
||||||
onMouseDown={(e) => this.handleFullScreenButton(e)}>
|
onMouseDown={(e) => this.handleFullScreenButton(e)}>
|
||||||
<img styleName='iconInfo' src='../resources/icon/icon-sidebar.svg' />
|
<img styleName='iconInfo' src='../resources/icon/icon-sidebar.svg' />
|
||||||
</button>
|
</button>
|
||||||
@@ -705,7 +730,8 @@ SnippetNoteDetail.propTypes = {
|
|||||||
style: PropTypes.shape({
|
style: PropTypes.shape({
|
||||||
left: PropTypes.number
|
left: PropTypes.number
|
||||||
}),
|
}),
|
||||||
ignorePreviewPointerEvents: PropTypes.bool
|
ignorePreviewPointerEvents: PropTypes.bool,
|
||||||
|
confirmDeletion: PropTypes.bool.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(SnippetNoteDetail, styles)
|
export default CSSModules(SnippetNoteDetail, styles)
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
.control-fullScreenButton
|
.control-fullScreenButton
|
||||||
top 80px
|
top 80px
|
||||||
margin-bottom 10px
|
margin-bottom 10px
|
||||||
topBarButtonLight()
|
topBarButtonRight()
|
||||||
|
|
||||||
body[data-theme="white"]
|
body[data-theme="white"]
|
||||||
.root
|
.root
|
||||||
@@ -78,7 +78,7 @@ body[data-theme="white"]
|
|||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
border none
|
border-left 1px solid $ui-dark-borderColor
|
||||||
background-color $ui-dark-noteDetail-backgroundColor
|
background-color $ui-dark-noteDetail-backgroundColor
|
||||||
box-shadow none
|
box-shadow none
|
||||||
|
|
||||||
@@ -109,3 +109,20 @@ body[data-theme="dark"]
|
|||||||
|
|
||||||
.control-fullScreenButton
|
.control-fullScreenButton
|
||||||
topBarButtonDark()
|
topBarButtonDark()
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
border-left 1px solid $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
|
||||||
|
.body
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
|
||||||
|
.body .description textarea
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
border 1px solid $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
.tabList
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
@@ -46,14 +46,14 @@ class StarButton extends React.Component {
|
|||||||
onMouseDown={(e) => this.handleMouseDown(e)}
|
onMouseDown={(e) => this.handleMouseDown(e)}
|
||||||
onMouseUp={(e) => this.handleMouseUp(e)}
|
onMouseUp={(e) => this.handleMouseUp(e)}
|
||||||
onMouseLeave={(e) => this.handleMouseLeave(e)}
|
onMouseLeave={(e) => this.handleMouseLeave(e)}
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}>
|
||||||
>
|
|
||||||
<img styleName='icon'
|
<img styleName='icon'
|
||||||
src={this.state.isActive || this.props.isActive
|
src={this.state.isActive || this.props.isActive
|
||||||
? '../resources/icon/icon-starred.svg'
|
? '../resources/icon/icon-starred.svg'
|
||||||
: '../resources/icon/icon-star.svg'
|
: '../resources/icon/icon-star.svg'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<span styleName='tooltip'>Star</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,25 @@
|
|||||||
.root
|
.root
|
||||||
top 45px
|
top 45px
|
||||||
topBarButtonLight()
|
topBarButtonRight()
|
||||||
&:hover
|
&:hover
|
||||||
transition 0.2s
|
transition 0.2s
|
||||||
color alpha($ui-favorite-star-button-color, 0.6)
|
color alpha($ui-favorite-star-button-color, 0.6)
|
||||||
|
&:hover .tooltip
|
||||||
|
opacity 1
|
||||||
|
|
||||||
|
.tooltip
|
||||||
|
tooltip()
|
||||||
|
position absolute
|
||||||
|
pointer-events none
|
||||||
|
top 26px
|
||||||
|
right 0
|
||||||
|
width 100%
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
.root--active
|
.root--active
|
||||||
@extend .root
|
@extend .root
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
width 100%
|
width 100%
|
||||||
overflow-x scroll
|
overflow-x scroll
|
||||||
white-space nowrap
|
white-space nowrap
|
||||||
|
margin-right 10px
|
||||||
|
|
||||||
.root::-webkit-scrollbar
|
.root::-webkit-scrollbar
|
||||||
display none
|
display none
|
||||||
@@ -63,4 +64,20 @@ body[data-theme="dark"]
|
|||||||
.newTag
|
.newTag
|
||||||
border-color none
|
border-color none
|
||||||
background-color transparent
|
background-color transparent
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.tag
|
||||||
|
background-color $ui-solarized-dark-tag-backgroundColor
|
||||||
|
|
||||||
|
.tag-removeButton
|
||||||
|
border-color $ui-button--focus-borderColor
|
||||||
|
background-color transparent
|
||||||
|
|
||||||
|
.tag-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.newTag
|
||||||
|
border-color none
|
||||||
|
background-color transparent
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
25
browser/main/Detail/ToggleModeButton.js
Normal file
25
browser/main/Detail/ToggleModeButton.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './ToggleModeButton.styl'
|
||||||
|
|
||||||
|
const ToggleModeButton = ({
|
||||||
|
onClick, editorType
|
||||||
|
}) => (
|
||||||
|
<div styleName='control-toggleModeButton'>
|
||||||
|
<div styleName={editorType === 'SPLIT' ? 'active' : 'non-active'} onClick={() => onClick('SPLIT')}>
|
||||||
|
<img styleName='item-star' src={editorType === 'EDITOR_PREVIEW' ? '../resources/icon/icon-mode-split-on.svg' : '../resources/icon/icon-mode-split-on-active.svg'} />
|
||||||
|
</div>
|
||||||
|
<div styleName={editorType === 'EDITOR_PREVIEW' ? 'active' : 'non-active'} onClick={() => onClick('EDITOR_PREVIEW')}>
|
||||||
|
<img styleName='item-star' src={editorType === 'EDITOR_PREVIEW' ? '../resources/icon/icon-mode-markdown-off-active.svg' : '../resources/icon/icon-mode-markdown-off.svg'} />
|
||||||
|
</div>
|
||||||
|
<span styleName='tooltip'>Toggle Mode</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
ToggleModeButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
editorType: PropTypes.string.Required
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(ToggleModeButton, styles)
|
||||||
61
browser/main/Detail/ToggleModeButton.styl
Normal file
61
browser/main/Detail/ToggleModeButton.styl
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
.control-toggleModeButton
|
||||||
|
border 1px solid #eee
|
||||||
|
height 34px
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
|
||||||
|
div
|
||||||
|
width 40px
|
||||||
|
height 100%
|
||||||
|
background-color #f9f9f9
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content center
|
||||||
|
cursor pointer
|
||||||
|
|
||||||
|
&:first-child
|
||||||
|
border-right 1px solid #eee
|
||||||
|
.active
|
||||||
|
background-color #fff
|
||||||
|
box-shadow 2px 0px 7px #eee
|
||||||
|
z-index 1
|
||||||
|
&:hover .tooltip
|
||||||
|
opacity 1
|
||||||
|
|
||||||
|
.tooltip
|
||||||
|
tooltip()
|
||||||
|
position absolute
|
||||||
|
pointer-events none
|
||||||
|
top 47px
|
||||||
|
right 11px
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
|
body[data-theme="dark"]
|
||||||
|
.control-fullScreenButton
|
||||||
|
topBarButtonDark()
|
||||||
|
|
||||||
|
.control-toggleModeButton
|
||||||
|
border 1px solid #444444
|
||||||
|
div
|
||||||
|
background-color $ui-dark-noteDetail-backgroundColor
|
||||||
|
&:first-child
|
||||||
|
border-right 1px solid #444444
|
||||||
|
.active
|
||||||
|
background-color #3A404C
|
||||||
|
box-shadow 2px 0px 7px #444444
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.control-toggleModeButton
|
||||||
|
border 1px solid #586E75
|
||||||
|
div
|
||||||
|
background-color $ui-solarized-dark-noteDetail-backgroundColor
|
||||||
|
&:first-child
|
||||||
|
border-right 1px solid #586E75
|
||||||
|
.active
|
||||||
|
background-color #002B36
|
||||||
|
box-shadow 2px 0px 7px #222222
|
||||||
@@ -10,6 +10,7 @@ const TrashButton = ({
|
|||||||
onClick={(e) => onClick(e)}
|
onClick={(e) => onClick(e)}
|
||||||
>
|
>
|
||||||
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
|
<img styleName='iconInfo' src='../resources/icon/icon-trash.svg' />
|
||||||
|
<span styleName='tooltip'>Trash</span>
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,25 @@
|
|||||||
.control-trashButton
|
.control-trashButton
|
||||||
top 120px
|
top 115px
|
||||||
margin-bottom 10px
|
topBarButtonRight()
|
||||||
topBarButtonLight()
|
&:hover .tooltip
|
||||||
|
opacity 1
|
||||||
|
|
||||||
|
.tooltip
|
||||||
|
tooltip()
|
||||||
|
position absolute
|
||||||
|
pointer-events none
|
||||||
|
top 26px
|
||||||
|
right 0
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
.control-trashButton--in-trash
|
.control-trashButton--in-trash
|
||||||
top 60px
|
top 60px
|
||||||
topBarButtonLight()
|
topBarButtonRight()
|
||||||
|
|
||||||
.trashButton
|
.trashButton
|
||||||
padding 0px
|
padding 0px
|
||||||
|
|||||||
@@ -32,6 +32,26 @@ class Detail extends React.Component {
|
|||||||
ee.off('detail:delete', this.deleteHandler)
|
ee.off('detail:delete', this.deleteHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
confirmDeletion (permanent) {
|
||||||
|
if (this.props.config.ui.confirmDeletion || permanent) {
|
||||||
|
const electron = require('electron')
|
||||||
|
const { remote } = electron
|
||||||
|
const { dialog } = remote
|
||||||
|
|
||||||
|
const alertConfig = {
|
||||||
|
type: 'warning',
|
||||||
|
message: 'Confirm note deletion',
|
||||||
|
detail: 'This will permanently remove this note.',
|
||||||
|
buttons: ['Confirm', 'Cancel']
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), alertConfig)
|
||||||
|
return dialogueButtonIndex === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { location, data, config } = this.props
|
const { location, data, config } = this.props
|
||||||
let note = null
|
let note = null
|
||||||
@@ -64,6 +84,7 @@ class Detail extends React.Component {
|
|||||||
<SnippetNoteDetail
|
<SnippetNoteDetail
|
||||||
note={note}
|
note={note}
|
||||||
config={config}
|
config={config}
|
||||||
|
confirmDeletion={(permanent) => this.confirmDeletion(permanent)}
|
||||||
ref='root'
|
ref='root'
|
||||||
{..._.pick(this.props, [
|
{..._.pick(this.props, [
|
||||||
'dispatch',
|
'dispatch',
|
||||||
@@ -80,6 +101,7 @@ class Detail extends React.Component {
|
|||||||
<MarkdownNoteDetail
|
<MarkdownNoteDetail
|
||||||
note={note}
|
note={note}
|
||||||
config={config}
|
config={config}
|
||||||
|
confirmDeletion={(permanent) => this.confirmDeletion(permanent)}
|
||||||
ref='root'
|
ref='root'
|
||||||
{..._.pick(this.props, [
|
{..._.pick(this.props, [
|
||||||
'dispatch',
|
'dispatch',
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ import Detail from './Detail'
|
|||||||
import dataApi from 'browser/main/lib/dataApi'
|
import dataApi from 'browser/main/lib/dataApi'
|
||||||
import _ from 'lodash'
|
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 InitModal from 'browser/main/modals/InitModal'
|
|
||||||
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'
|
||||||
|
import { hashHistory } from 'react-router'
|
||||||
|
import store from 'browser/main/store'
|
||||||
|
const path = require('path')
|
||||||
|
const electron = require('electron')
|
||||||
|
const { remote } = electron
|
||||||
|
|
||||||
class Main extends React.Component {
|
class Main extends React.Component {
|
||||||
|
|
||||||
@@ -48,6 +51,91 @@ class Main extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init () {
|
||||||
|
dataApi
|
||||||
|
.addStorage({
|
||||||
|
name: 'My Storage',
|
||||||
|
path: path.join(remote.app.getPath('home'), 'Boostnote')
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
return data
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
if (data.storage.folders[0] != null) {
|
||||||
|
return data
|
||||||
|
} else {
|
||||||
|
return dataApi
|
||||||
|
.createFolder(data.storage.key, {
|
||||||
|
color: '#1278BD',
|
||||||
|
name: 'Default'
|
||||||
|
})
|
||||||
|
.then((_data) => {
|
||||||
|
return {
|
||||||
|
storage: _data.storage,
|
||||||
|
notes: data.notes
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
console.log(data)
|
||||||
|
store.dispatch({
|
||||||
|
type: 'ADD_STORAGE',
|
||||||
|
storage: data.storage,
|
||||||
|
notes: data.notes
|
||||||
|
})
|
||||||
|
|
||||||
|
const defaultSnippetNote = dataApi
|
||||||
|
.createNote(data.storage.key, {
|
||||||
|
type: 'SNIPPET_NOTE',
|
||||||
|
folder: data.storage.folders[0].key,
|
||||||
|
title: 'Snippet note example',
|
||||||
|
description: 'Snippet note example\nYou can store a series of snippets as a single note, like Gist.',
|
||||||
|
snippets: [
|
||||||
|
{
|
||||||
|
name: 'example.html',
|
||||||
|
mode: 'html',
|
||||||
|
content: '<html>\n<body>\n<h1 id=\'hello\'>Enjoy Boostnote!</h1>\n</body>\n</html>'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'example.js',
|
||||||
|
mode: 'javascript',
|
||||||
|
content: 'var boostnote = document.getElementById(\'enjoy\').innerHTML\n\nconsole.log(boostnote)'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.then((note) => {
|
||||||
|
store.dispatch({
|
||||||
|
type: 'UPDATE_NOTE',
|
||||||
|
note: note
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const defaultMarkdownNote = dataApi
|
||||||
|
.createNote(data.storage.key, {
|
||||||
|
type: 'MARKDOWN_NOTE',
|
||||||
|
folder: data.storage.folders[0].key,
|
||||||
|
title: 'Welcome to Boostnote!',
|
||||||
|
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) => {
|
||||||
|
store.dispatch({
|
||||||
|
type: 'UPDATE_NOTE',
|
||||||
|
note: note
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return Promise.resolve(defaultSnippetNote)
|
||||||
|
.then(defaultMarkdownNote)
|
||||||
|
.then(() => data.storage)
|
||||||
|
})
|
||||||
|
.then((storage) => {
|
||||||
|
hashHistory.push('/storages/' + storage.key)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { dispatch, config } = this.props
|
const { dispatch, config } = this.props
|
||||||
|
|
||||||
@@ -55,6 +143,8 @@ class Main extends React.Component {
|
|||||||
document.body.setAttribute('data-theme', 'dark')
|
document.body.setAttribute('data-theme', 'dark')
|
||||||
} else if (config.ui.theme === 'white') {
|
} else if (config.ui.theme === 'white') {
|
||||||
document.body.setAttribute('data-theme', 'white')
|
document.body.setAttribute('data-theme', 'white')
|
||||||
|
} else if (config.ui.theme === 'solarized-dark') {
|
||||||
|
document.body.setAttribute('data-theme', 'solarized-dark')
|
||||||
} else {
|
} else {
|
||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
@@ -69,7 +159,7 @@ class Main extends React.Component {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (data.storages.length < 1) {
|
if (data.storages.length < 1) {
|
||||||
modal.open(InitModal)
|
this.init()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -71,3 +71,7 @@ body[data-theme="dark"]
|
|||||||
|
|
||||||
.control-newNoteButton-tooltip
|
.control-newNoteButton-tooltip
|
||||||
darkTooltip()
|
darkTooltip()
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root, .root--expanded
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
@@ -88,4 +88,29 @@ body[data-theme="dark"]
|
|||||||
.control-button--active
|
.control-button--active
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
&:active
|
&:active
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
.control-sortBy-select
|
||||||
|
&:hover
|
||||||
|
transition 0.2s
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.control-button
|
||||||
|
color $ui-solarized-dark-inactive-text-color
|
||||||
|
&:hover
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.control-button--active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:active
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
@@ -12,7 +12,7 @@ import NoteItemSimple from 'browser/components/NoteItemSimple'
|
|||||||
import searchFromNotes from 'browser/lib/search'
|
import searchFromNotes from 'browser/lib/search'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import { hashHistory } from 'react-router'
|
import { hashHistory } from 'react-router'
|
||||||
import markdown from 'browser/lib/markdown'
|
import markdown from 'browser/lib/markdownTextHelper'
|
||||||
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
import { findNoteTitle } from 'browser/lib/findNoteTitle'
|
||||||
import store from 'browser/main/store'
|
import store from 'browser/main/store'
|
||||||
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
|
||||||
@@ -235,18 +235,8 @@ class NoteList extends React.Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { router } = this.context
|
const selectedNoteKeys = [noteHash]
|
||||||
const { location } = this.props
|
this.focusNote(selectedNoteKeys, noteHash)
|
||||||
|
|
||||||
let targetIndex = this.getTargetIndex()
|
|
||||||
|
|
||||||
if (targetIndex < 0) targetIndex = 0
|
|
||||||
|
|
||||||
const selectedNoteKeys = []
|
|
||||||
const nextNoteKey = this.getNoteKeyFromTargetIndex(targetIndex)
|
|
||||||
selectedNoteKeys.push(nextNoteKey)
|
|
||||||
|
|
||||||
this.focusNote(selectedNoteKeys, nextNoteKey)
|
|
||||||
|
|
||||||
ee.emit('list:moved')
|
ee.emit('list:moved')
|
||||||
}
|
}
|
||||||
@@ -584,22 +574,29 @@ class NoteList extends React.Component {
|
|||||||
filepaths.forEach((filepath) => {
|
filepaths.forEach((filepath) => {
|
||||||
fs.readFile(filepath, (err, data) => {
|
fs.readFile(filepath, (err, data) => {
|
||||||
if (err) throw Error('File reading error: ', err)
|
if (err) throw Error('File reading error: ', err)
|
||||||
const content = data.toString()
|
|
||||||
const newNote = {
|
fs.stat(filepath, (err, {mtime, birthtime}) => {
|
||||||
content: content,
|
if (err) throw Error('File stat reading error: ', err)
|
||||||
folder: folder.key,
|
|
||||||
title: markdown.strip(findNoteTitle(content)),
|
const content = data.toString()
|
||||||
type: 'MARKDOWN_NOTE'
|
const newNote = {
|
||||||
}
|
content: content,
|
||||||
dataApi.createNote(storage.key, newNote)
|
folder: folder.key,
|
||||||
.then((note) => {
|
title: markdown.strip(findNoteTitle(content)),
|
||||||
dispatch({
|
type: 'MARKDOWN_NOTE',
|
||||||
type: 'UPDATE_NOTE',
|
createdAt: birthtime,
|
||||||
note: note
|
updatedAt: mtime
|
||||||
})
|
}
|
||||||
hashHistory.push({
|
dataApi.createNote(storage.key, newNote)
|
||||||
pathname: location.pathname,
|
.then((note) => {
|
||||||
query: {key: getNoteKey(note)}
|
dispatch({
|
||||||
|
type: 'UPDATE_NOTE',
|
||||||
|
note: note
|
||||||
|
})
|
||||||
|
hashHistory.push({
|
||||||
|
pathname: location.pathname,
|
||||||
|
query: {key: getNoteKey(note)}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -717,6 +714,7 @@ class NoteList extends React.Component {
|
|||||||
handleNoteContextMenu={this.handleNoteContextMenu.bind(this)}
|
handleNoteContextMenu={this.handleNoteContextMenu.bind(this)}
|
||||||
handleNoteClick={this.handleNoteClick.bind(this)}
|
handleNoteClick={this.handleNoteClick.bind(this)}
|
||||||
handleDragStart={this.handleDragStart.bind(this)}
|
handleDragStart={this.handleDragStart.bind(this)}
|
||||||
|
pathname={location.pathname}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
24
browser/main/SideNav/ListButton.js
Normal file
24
browser/main/SideNav/ListButton.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './SwitchButton.styl'
|
||||||
|
|
||||||
|
const ListButton = ({
|
||||||
|
onClick, isTagActive
|
||||||
|
}) => (
|
||||||
|
<button styleName={isTagActive ? 'non-active-button' : 'active-button'} onClick={onClick}>
|
||||||
|
<img src={isTagActive
|
||||||
|
? '../resources/icon/icon-list.svg'
|
||||||
|
: '../resources/icon/icon-list-active.svg'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span styleName='tooltip'>Notes</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
ListButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
isTagActive: PropTypes.bool.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(ListButton, styles)
|
||||||
19
browser/main/SideNav/PreferenceButton.js
Normal file
19
browser/main/SideNav/PreferenceButton.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './PreferenceButton.styl'
|
||||||
|
|
||||||
|
const PreferenceButton = ({
|
||||||
|
onClick
|
||||||
|
}) => (
|
||||||
|
<button styleName='top-menu-preference' onClick={(e) => onClick(e)}>
|
||||||
|
<img styleName='iconTag' src='../resources/icon/icon-setting.svg' />
|
||||||
|
<span styleName='tooltip'>Preferences</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
PreferenceButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(PreferenceButton, styles)
|
||||||
51
browser/main/SideNav/PreferenceButton.styl
Normal file
51
browser/main/SideNav/PreferenceButton.styl
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
.top-menu-preference
|
||||||
|
navButtonColor()
|
||||||
|
position absolute
|
||||||
|
top 22px
|
||||||
|
right 10px
|
||||||
|
width 2em
|
||||||
|
background-color transparent
|
||||||
|
&:hover
|
||||||
|
color $ui-button-default--active-backgroundColor
|
||||||
|
background-color transparent
|
||||||
|
.tooltip
|
||||||
|
opacity 1
|
||||||
|
&:active, &:active:hover
|
||||||
|
color $ui-button-default--active-backgroundColor
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.top-menu-preference
|
||||||
|
navWhiteButtonColor()
|
||||||
|
background-color transparent
|
||||||
|
&:hover
|
||||||
|
color #0B99F1
|
||||||
|
background-color transparent
|
||||||
|
&:active, &:active:hover
|
||||||
|
color #0B99F1
|
||||||
|
background-color transparent
|
||||||
|
|
||||||
|
body[data-theme="dark"]
|
||||||
|
.top-menu-preference
|
||||||
|
navDarkButtonColor()
|
||||||
|
background-color transparent
|
||||||
|
&:active
|
||||||
|
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
||||||
|
background-color transparent
|
||||||
|
&:hover
|
||||||
|
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
||||||
|
background-color transparent
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.tooltip
|
||||||
|
tooltip()
|
||||||
|
position absolute
|
||||||
|
pointer-events none
|
||||||
|
top 26px
|
||||||
|
left -20px
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
@@ -11,19 +11,6 @@
|
|||||||
.top
|
.top
|
||||||
padding-bottom 15px
|
padding-bottom 15px
|
||||||
|
|
||||||
.top-menu-preference
|
|
||||||
navButtonColor()
|
|
||||||
position absolute
|
|
||||||
top 22px
|
|
||||||
right 10px
|
|
||||||
width 2em
|
|
||||||
background-color transparent
|
|
||||||
&:hover
|
|
||||||
color $ui-button-default--active-backgroundColor
|
|
||||||
background-color transparent
|
|
||||||
&:active, &:active:hover
|
|
||||||
color $ui-button-default--active-backgroundColor
|
|
||||||
|
|
||||||
.switch-buttons
|
.switch-buttons
|
||||||
background-color transparent
|
background-color transparent
|
||||||
border 0
|
border 0
|
||||||
@@ -31,21 +18,7 @@
|
|||||||
display flex
|
display flex
|
||||||
text-align center
|
text-align center
|
||||||
|
|
||||||
.non-active-button
|
|
||||||
color $ui-inactive-text-color
|
|
||||||
font-size 16px
|
|
||||||
border 0
|
|
||||||
background-color transparent
|
|
||||||
transition 0.2s
|
|
||||||
display flex
|
|
||||||
text-align center
|
|
||||||
margin-right 4px;
|
|
||||||
&:hover
|
|
||||||
color alpha(#239F86, 60%)
|
|
||||||
|
|
||||||
.active-button
|
|
||||||
@extend .non-active-button
|
|
||||||
color $ui-button-default--active-backgroundColor
|
|
||||||
|
|
||||||
.top-menu-label
|
.top-menu-label
|
||||||
margin-left 5px
|
margin-left 5px
|
||||||
@@ -109,57 +82,16 @@ body[data-theme="white"]
|
|||||||
background-color #f9f9f9
|
background-color #f9f9f9
|
||||||
color $ui-text-color
|
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
|
||||||
border-color $ui-dark-borderColor
|
border-right 1px solid $ui-dark-borderColor
|
||||||
background-color $ui-dark-backgroundColor
|
background-color $ui-dark-backgroundColor
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
.top
|
.top
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
|
|
||||||
.top-menu-preference
|
body[data-theme="solarized-dark"]
|
||||||
navDarkButtonColor()
|
.root, .root--folded
|
||||||
background-color transparent
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
&:active
|
border-right 1px solid $ui-solarized-dark-borderColor
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
|
||||||
background-color transparent
|
|
||||||
&:hover
|
|
||||||
background-color alpha($ui-dark-button--active-backgroundColor, 20%)
|
|
||||||
background-color transparent
|
|
||||||
|
|
||||||
.non-active-button
|
|
||||||
color alpha($ui-dark-text-color, 60%)
|
|
||||||
&:hover
|
|
||||||
color alpha(#0B99F1, 60%)
|
|
||||||
|
|
||||||
.tag-title
|
|
||||||
p
|
|
||||||
color alpha($ui-dark-text-color, 60%)
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import dataApi from 'browser/main/lib/dataApi'
|
|||||||
import StorageItemChild from 'browser/components/StorageItem'
|
import StorageItemChild from 'browser/components/StorageItem'
|
||||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
const { remote } = require('electron')
|
const { remote } = require('electron')
|
||||||
const { Menu, MenuItem, dialog } = remote
|
const { Menu, MenuItem, dialog } = remote
|
||||||
@@ -24,18 +25,20 @@ class StorageItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleHeaderContextMenu (e) {
|
handleHeaderContextMenu (e) {
|
||||||
const menu = new Menu()
|
const menu = Menu.buildFromTemplate([
|
||||||
menu.append(new MenuItem({
|
{
|
||||||
label: 'Add Folder',
|
label: 'Add Folder',
|
||||||
click: (e) => this.handleAddFolderButtonClick(e)
|
click: (e) => this.handleAddFolderButtonClick(e)
|
||||||
}))
|
},
|
||||||
menu.append(new MenuItem({
|
{
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
}))
|
},
|
||||||
menu.append(new MenuItem({
|
{
|
||||||
label: 'Unlink Storage',
|
label: 'Unlink Storage',
|
||||||
click: (e) => this.handleUnlinkStorageClick(e)
|
click: (e) => this.handleUnlinkStorageClick(e)
|
||||||
}))
|
}
|
||||||
|
])
|
||||||
|
|
||||||
menu.popup()
|
menu.popup()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,18 +92,36 @@ class StorageItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleFolderButtonContextMenu (e, folder) {
|
handleFolderButtonContextMenu (e, folder) {
|
||||||
const menu = new Menu()
|
const menu = Menu.buildFromTemplate([
|
||||||
menu.append(new MenuItem({
|
{
|
||||||
label: 'Rename Folder',
|
label: 'Rename Folder',
|
||||||
click: (e) => this.handleRenameFolderClick(e, folder)
|
click: (e) => this.handleRenameFolderClick(e, folder)
|
||||||
}))
|
},
|
||||||
menu.append(new MenuItem({
|
{
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
}))
|
},
|
||||||
menu.append(new MenuItem({
|
{
|
||||||
label: 'Delete Folder',
|
label: 'Export Folder',
|
||||||
click: (e) => this.handleFolderDeleteClick(e, folder)
|
submenu: [
|
||||||
}))
|
{
|
||||||
|
label: 'Export as txt',
|
||||||
|
click: (e) => this.handleExportFolderClick(e, folder, 'txt')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Export as md',
|
||||||
|
click: (e) => this.handleExportFolderClick(e, folder, 'md')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separator'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Delete Folder',
|
||||||
|
click: (e) => this.handleFolderDeleteClick(e, folder)
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
menu.popup()
|
menu.popup()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +133,31 @@ class StorageItem extends React.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleExportFolderClick (e, folder, fileType) {
|
||||||
|
const options = {
|
||||||
|
properties: ['openDirectory', 'createDirectory'],
|
||||||
|
buttonLabel: 'Select directory',
|
||||||
|
title: 'Select a folder to export the files to',
|
||||||
|
multiSelections: false
|
||||||
|
}
|
||||||
|
dialog.showOpenDialog(remote.getCurrentWindow(), options,
|
||||||
|
(paths) => {
|
||||||
|
if (paths && paths.length === 1) {
|
||||||
|
const { storage, dispatch } = this.props
|
||||||
|
dataApi
|
||||||
|
.exportFolder(storage.key, folder.key, fileType, paths[0])
|
||||||
|
.then((data) => {
|
||||||
|
dispatch({
|
||||||
|
type: 'EXPORT_FOLDER',
|
||||||
|
storage: data.storage,
|
||||||
|
folderKey: data.folderKey,
|
||||||
|
fileType: data.fileType
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
handleFolderDeleteClick (e, folder) {
|
handleFolderDeleteClick (e, folder) {
|
||||||
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
|
const index = dialog.showMessageBox(remote.getCurrentWindow(), {
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
|
|||||||
@@ -179,4 +179,8 @@ body[data-theme="dark"]
|
|||||||
background-color alpha($ui-dark-button--active-backgroundColor, 60%)
|
background-color alpha($ui-dark-button--active-backgroundColor, 60%)
|
||||||
&:active, &:active:hover
|
&:active, &:active:hover
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
background-color $ui-dark-button--active-backgroundColor
|
background-color $ui-dark-button--active-backgroundColor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
59
browser/main/SideNav/SwitchButton.styl
Normal file
59
browser/main/SideNav/SwitchButton.styl
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
.non-active-button
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
font-size 16px
|
||||||
|
border 0
|
||||||
|
background-color transparent
|
||||||
|
transition 0.2s
|
||||||
|
display flex
|
||||||
|
text-align center
|
||||||
|
margin-right 4px
|
||||||
|
position relative
|
||||||
|
&:hover
|
||||||
|
color alpha(#239F86, 60%)
|
||||||
|
.tooltip
|
||||||
|
opacity 1
|
||||||
|
|
||||||
|
.active-button
|
||||||
|
@extend .non-active-button
|
||||||
|
color $ui-button-default--active-backgroundColor
|
||||||
|
|
||||||
|
.tooltip
|
||||||
|
tooltip()
|
||||||
|
position absolute
|
||||||
|
pointer-events none
|
||||||
|
top 22px
|
||||||
|
left -2px
|
||||||
|
z-index 200
|
||||||
|
padding 5px
|
||||||
|
line-height normal
|
||||||
|
border-radius 2px
|
||||||
|
opacity 0
|
||||||
|
transition 0.1s
|
||||||
|
|
||||||
|
body[data-theme="white"]
|
||||||
|
.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"]
|
||||||
|
.non-active-button
|
||||||
|
color alpha($ui-dark-text-color, 60%)
|
||||||
|
&:hover
|
||||||
|
color alpha(#0B99F1, 60%)
|
||||||
|
|
||||||
|
.tag-title
|
||||||
|
p
|
||||||
|
color alpha($ui-dark-text-color, 60%)
|
||||||
24
browser/main/SideNav/TagButton.js
Normal file
24
browser/main/SideNav/TagButton.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import React from 'react'
|
||||||
|
import CSSModules from 'browser/lib/CSSModules'
|
||||||
|
import styles from './SwitchButton.styl'
|
||||||
|
|
||||||
|
const TagButton = ({
|
||||||
|
onClick, isTagActive
|
||||||
|
}) => (
|
||||||
|
<button styleName={isTagActive ? 'active-button' : 'non-active-button'} onClick={onClick}>
|
||||||
|
<img src={isTagActive
|
||||||
|
? '../resources/icon/icon-tag-active.svg'
|
||||||
|
: '../resources/icon/icon-tag.svg'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<span styleName='tooltip'>Tags</span>
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
|
TagButton.propTypes = {
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
isTagActive: PropTypes.bool.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CSSModules(TagButton, styles)
|
||||||
@@ -11,6 +11,9 @@ 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'
|
import EventEmitter from 'browser/main/lib/eventEmitter'
|
||||||
|
import PreferenceButton from './PreferenceButton'
|
||||||
|
import ListButton from './ListButton'
|
||||||
|
import TagButton from './TagButton'
|
||||||
|
|
||||||
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
|
||||||
@@ -162,27 +165,11 @@ 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)}>
|
<ListButton onClick={this.handleSwitchFoldersButtonClick.bind(this)} isTagActive={isTagActive} />
|
||||||
<img src={isTagActive
|
<TagButton onClick={this.handleSwitchTagsButtonClick.bind(this)} isTagActive={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-preference'
|
<PreferenceButton onClick={this.handleMenuButtonClick} />
|
||||||
onClick={(e) => this.handleMenuButtonClick(e)}
|
|
||||||
>
|
|
||||||
<img styleName='iconTag' src='../resources/icon/icon-setting.svg' />
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{this.SideNavComponent(isFolded, storageList)}
|
{this.SideNavComponent(isFolded, storageList)}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ class StatusBar extends React.Component {
|
|||||||
{status.updateReady
|
{status.updateReady
|
||||||
? <button onClick={this.updateApp} styleName='update'>
|
? <button onClick={this.updateApp} styleName='update'>
|
||||||
<i styleName='update-icon' className='fa fa-cloud-download' /> Ready to Update!
|
<i styleName='update-icon' className='fa fa-cloud-download' /> Ready to Update!
|
||||||
</button>
|
</button>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -185,3 +185,26 @@ body[data-theme="dark"]
|
|||||||
|
|
||||||
.control-newPostButton-tooltip
|
.control-newPostButton-tooltip
|
||||||
darkTooltip()
|
darkTooltip()
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root, .root--expanded
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
.control-search
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control-search-icon
|
||||||
|
absolute top bottom left
|
||||||
|
line-height 32px
|
||||||
|
width 35px
|
||||||
|
color $ui-solarized-dark-inactive-text-color
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
|
||||||
|
.control-search-input
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
input
|
||||||
|
background-color $ui-solarized-dark-noteList-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
global-reset()
|
global-reset()
|
||||||
|
@import '../styles/vars.styl'
|
||||||
|
|
||||||
DEFAULT_FONTS = 'OpenSans', helvetica, arial, sans-serif
|
DEFAULT_FONTS = 'OpenSans', helvetica, arial, sans-serif
|
||||||
|
|
||||||
@@ -84,10 +85,14 @@ modalBackColor = white
|
|||||||
absolute top left bottom right
|
absolute top left bottom right
|
||||||
background-color modalBackColor
|
background-color modalBackColor
|
||||||
z-index modalZIndex + 1
|
z-index modalZIndex + 1
|
||||||
|
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.ModalBase
|
.ModalBase
|
||||||
.modalBack
|
.modalBack
|
||||||
background-color $ui-dark-backgroundColor
|
background-color $ui-dark-backgroundColor
|
||||||
|
.sortableItemHelper
|
||||||
|
color: $ui-dark-text-color
|
||||||
|
|
||||||
.CodeMirror
|
.CodeMirror
|
||||||
font-family inherit !important
|
font-family inherit !important
|
||||||
@@ -107,6 +112,11 @@ body[data-theme="dark"]
|
|||||||
.sortableItemHelper
|
.sortableItemHelper
|
||||||
z-index modalZIndex + 5
|
z-index modalZIndex + 5
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="solarized-dark"]
|
||||||
|
.ModalBase
|
||||||
|
.modalBack
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
.sortableItemHelper
|
.sortableItemHelper
|
||||||
color: $ui-dark-text-color
|
color: $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const os = require('os')
|
|||||||
let mobileAnalyticsClient
|
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 (!getSendEventCond()) {
|
||||||
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
|
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
|
||||||
IdentityPoolId: 'us-east-1:xxxxxxxxxxxxxxxxxxxxxxxxx'
|
IdentityPoolId: 'us-east-1:xxxxxxxxxxxxxxxxxxxxxxxxx'
|
||||||
})
|
})
|
||||||
@@ -34,8 +34,15 @@ function convertPlatformName (platformName) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSendEventCond () {
|
||||||
|
const isDev = process.env.NODE_ENV !== 'production'
|
||||||
|
const isDisable = !ConfigManager.default.get().amaEnabled
|
||||||
|
const isOffline = !window.navigator.onLine
|
||||||
|
return isDev || isDisable || isOffline
|
||||||
|
}
|
||||||
|
|
||||||
function initAwsMobileAnalytics () {
|
function initAwsMobileAnalytics () {
|
||||||
if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled) return
|
if (getSendEventCond()) return
|
||||||
AWS.config.credentials.get((err) => {
|
AWS.config.credentials.get((err) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
console.log('Cognito Identity ID: ' + AWS.config.credentials.identityId)
|
console.log('Cognito Identity ID: ' + AWS.config.credentials.identityId)
|
||||||
@@ -46,7 +53,7 @@ function initAwsMobileAnalytics () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function recordDynamicCustomEvent (type, options = {}) {
|
function recordDynamicCustomEvent (type, options = {}) {
|
||||||
if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled) return
|
if (getSendEventCond()) return
|
||||||
try {
|
try {
|
||||||
mobileAnalyticsClient.recordEvent(type, options)
|
mobileAnalyticsClient.recordEvent(type, options)
|
||||||
} catch (analyticsError) {
|
} catch (analyticsError) {
|
||||||
@@ -57,7 +64,7 @@ function recordDynamicCustomEvent (type, options = {}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function recordStaticCustomEvent () {
|
function recordStaticCustomEvent () {
|
||||||
if (process.env.NODE_ENV !== 'production' || !ConfigManager.default.get().amaEnabled) return
|
if (getSendEventCond()) return
|
||||||
try {
|
try {
|
||||||
mobileAnalyticsClient.recordEvent('UI_COLOR_THEME', {
|
mobileAnalyticsClient.recordEvent('UI_COLOR_THEME', {
|
||||||
uiColorTheme: ConfigManager.default.get().ui.theme
|
uiColorTheme: ConfigManager.default.get().ui.theme
|
||||||
|
|||||||
@@ -34,13 +34,19 @@ export const DEFAULT_CONFIG = {
|
|||||||
fontFamily: win ? 'Segoe UI' : 'Monaco, Consolas',
|
fontFamily: win ? 'Segoe UI' : 'Monaco, Consolas',
|
||||||
indentType: 'space',
|
indentType: 'space',
|
||||||
indentSize: '2',
|
indentSize: '2',
|
||||||
switchPreview: 'BLUR' // Available value: RIGHTCLICK, BLUR
|
switchPreview: 'BLUR', // Available value: RIGHTCLICK, BLUR
|
||||||
|
scrollPastEnd: false,
|
||||||
|
type: 'SPLIT'
|
||||||
},
|
},
|
||||||
preview: {
|
preview: {
|
||||||
fontSize: '14',
|
fontSize: '14',
|
||||||
fontFamily: win ? 'Segoe UI' : 'Lato',
|
fontFamily: win ? 'Segoe UI' : 'Lato',
|
||||||
codeBlockTheme: 'dracula',
|
codeBlockTheme: 'dracula',
|
||||||
lineNumber: true
|
lineNumber: true,
|
||||||
|
latexInlineOpen: '$',
|
||||||
|
latexInlineClose: '$',
|
||||||
|
latexBlockOpen: '$$',
|
||||||
|
latexBlockClose: '$$'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +116,8 @@ function set (updates) {
|
|||||||
document.body.setAttribute('data-theme', 'dark')
|
document.body.setAttribute('data-theme', 'dark')
|
||||||
} else if (newConfig.ui.theme === 'white') {
|
} else if (newConfig.ui.theme === 'white') {
|
||||||
document.body.setAttribute('data-theme', 'white')
|
document.body.setAttribute('data-theme', 'white')
|
||||||
|
} else if (newConfig.ui.theme === 'solarized-dark') {
|
||||||
|
document.body.setAttribute('data-theme', 'solarized-dark')
|
||||||
} else {
|
} else {
|
||||||
document.body.setAttribute('data-theme', 'default')
|
document.body.setAttribute('data-theme', 'default')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,12 +66,16 @@ function createNote (storageKey, input) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const noteData = Object.assign({}, input, {
|
const noteData = Object.assign({},
|
||||||
key,
|
{
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date()
|
||||||
storage: storageKey
|
},
|
||||||
})
|
input, // input may contain more accurate dates
|
||||||
|
{
|
||||||
|
key,
|
||||||
|
storage: storageKey
|
||||||
|
})
|
||||||
|
|
||||||
CSON.writeFileSync(path.join(storage.path, 'notes', key + '.cson'), _.omit(noteData, ['key', 'storage']))
|
CSON.writeFileSync(path.join(storage.path, 'notes', key + '.cson'), _.omit(noteData, ['key', 'storage']))
|
||||||
|
|
||||||
|
|||||||
61
browser/main/lib/dataApi/exportFolder.js
Normal file
61
browser/main/lib/dataApi/exportFolder.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import { findStorage } from 'browser/lib/findStorage'
|
||||||
|
import resolveStorageData from './resolveStorageData'
|
||||||
|
import resolveStorageNotes from './resolveStorageNotes'
|
||||||
|
import * as path from 'path'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} storageKey
|
||||||
|
* @param {String} folderKey
|
||||||
|
* @param {String} fileType
|
||||||
|
* @param {String} exportDir
|
||||||
|
*
|
||||||
|
* @return {Object}
|
||||||
|
* ```
|
||||||
|
* {
|
||||||
|
* storage: Object,
|
||||||
|
* folderKey: String,
|
||||||
|
* fileType: String,
|
||||||
|
* exportDir: String
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
|
||||||
|
function exportFolder (storageKey, folderKey, fileType, exportDir) {
|
||||||
|
let targetStorage
|
||||||
|
try {
|
||||||
|
targetStorage = findStorage(storageKey)
|
||||||
|
} catch (e) {
|
||||||
|
return Promise.reject(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolveStorageData(targetStorage)
|
||||||
|
.then(function assignNotes (storage) {
|
||||||
|
return resolveStorageNotes(storage)
|
||||||
|
.then((notes) => {
|
||||||
|
return {
|
||||||
|
storage,
|
||||||
|
notes
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(function exportNotes (data) {
|
||||||
|
const { storage, notes } = data
|
||||||
|
|
||||||
|
notes
|
||||||
|
.filter(note => note.folder === folderKey && note.isTrashed === false && note.type === 'MARKDOWN_NOTE')
|
||||||
|
.forEach(snippet => {
|
||||||
|
const notePath = path.join(exportDir, `${snippet.title}.${fileType}`)
|
||||||
|
fs.writeFileSync(notePath, snippet.content)
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
storage,
|
||||||
|
folderKey,
|
||||||
|
fileType,
|
||||||
|
exportDir
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exportFolder
|
||||||
@@ -7,6 +7,7 @@ const dataApi = {
|
|||||||
updateFolder: require('./updateFolder'),
|
updateFolder: require('./updateFolder'),
|
||||||
deleteFolder: require('./deleteFolder'),
|
deleteFolder: require('./deleteFolder'),
|
||||||
reorderFolder: require('./reorderFolder'),
|
reorderFolder: require('./reorderFolder'),
|
||||||
|
exportFolder: require('./exportFolder'),
|
||||||
createNote: require('./createNote'),
|
createNote: require('./createNote'),
|
||||||
updateNote: require('./updateNote'),
|
updateNote: require('./updateNote'),
|
||||||
deleteNote: require('./deleteNote'),
|
deleteNote: require('./deleteNote'),
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
width 490px
|
width 490px
|
||||||
padding 0 5px
|
padding 0 5px
|
||||||
margin 10px 0
|
margin 10px 0
|
||||||
border 1px solid #C9C9C9 // TODO: use variable.
|
border 1px solid $ui-input--create-folder-modal
|
||||||
border-radius 2px
|
border-radius 2px
|
||||||
background-color transparent
|
background-color transparent
|
||||||
outline none
|
outline none
|
||||||
@@ -68,7 +68,7 @@ body[data-theme="dark"]
|
|||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
.control-folder-input
|
.control-folder-input
|
||||||
border 1px solid #C9C9C9 // TODO: use variable.
|
border 1px solid $ui-input--create-folder-modal
|
||||||
color white
|
color white
|
||||||
|
|
||||||
.description
|
.description
|
||||||
@@ -76,3 +76,29 @@ body[data-theme="dark"]
|
|||||||
|
|
||||||
.control-confirmButton
|
.control-confirmButton
|
||||||
colorDarkPrimaryButton()
|
colorDarkPrimaryButton()
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
modalSolarizedDark()
|
||||||
|
width 500px
|
||||||
|
height 270px
|
||||||
|
overflow hidden
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.header
|
||||||
|
background-color transparent
|
||||||
|
border-color $ui-dark-borderColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.control-folder-label
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.control-folder-input
|
||||||
|
border 1px solid $ui-input--create-folder-modal
|
||||||
|
color white
|
||||||
|
|
||||||
|
.description
|
||||||
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
.control-confirmButton
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
|||||||
@@ -1,254 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import CSSModules from 'browser/lib/CSSModules'
|
|
||||||
import styles from './InitModal.styl'
|
|
||||||
import dataApi from 'browser/main/lib/dataApi'
|
|
||||||
import store from 'browser/main/store'
|
|
||||||
import { hashHistory } from 'react-router'
|
|
||||||
import _ from 'lodash'
|
|
||||||
|
|
||||||
const CSON = require('@rokt33r/season')
|
|
||||||
const path = require('path')
|
|
||||||
const electron = require('electron')
|
|
||||||
const { remote } = electron
|
|
||||||
|
|
||||||
function browseFolder () {
|
|
||||||
const dialog = remote.dialog
|
|
||||||
|
|
||||||
const defaultPath = remote.app.getPath('home')
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
dialog.showOpenDialog({
|
|
||||||
title: 'Select Directory',
|
|
||||||
defaultPath,
|
|
||||||
properties: ['openDirectory', 'createDirectory']
|
|
||||||
}, function (targetPaths) {
|
|
||||||
if (targetPaths == null) return resolve('')
|
|
||||||
resolve(targetPaths[0])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
class InitModal extends React.Component {
|
|
||||||
constructor (props) {
|
|
||||||
super(props)
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
path: path.join(remote.app.getPath('home'), 'Boostnote'),
|
|
||||||
migrationRequested: true,
|
|
||||||
isLoading: true,
|
|
||||||
data: null,
|
|
||||||
legacyStorageExists: false,
|
|
||||||
isSending: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePathChange (e) {
|
|
||||||
this.setState({
|
|
||||||
path: e.target.value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
let data = null
|
|
||||||
try {
|
|
||||||
data = CSON.readFileSync(path.join(remote.app.getPath('userData'), 'local.json'))
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
}
|
|
||||||
const newState = {
|
|
||||||
isLoading: false
|
|
||||||
}
|
|
||||||
if (data != null) {
|
|
||||||
newState.legacyStorageExists = true
|
|
||||||
newState.data = data
|
|
||||||
}
|
|
||||||
this.setState(newState, () => {
|
|
||||||
this.refs.createButton.focus()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePathBrowseButtonClick (e) {
|
|
||||||
browseFolder()
|
|
||||||
.then((targetPath) => {
|
|
||||||
if (targetPath.length > 0) {
|
|
||||||
this.setState({
|
|
||||||
path: targetPath
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error('BrowseFAILED')
|
|
||||||
console.error(err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSubmitButtonClick (e) {
|
|
||||||
this.setState({
|
|
||||||
isSending: true
|
|
||||||
}, () => {
|
|
||||||
dataApi
|
|
||||||
.addStorage({
|
|
||||||
name: 'My Storage',
|
|
||||||
path: this.state.path
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
if (this.state.migrationRequested && _.isObject(this.state.data) && _.isArray(this.state.data.folders) && _.isArray(this.state.data.articles)) {
|
|
||||||
return dataApi.migrateFromV5Storage(data.storage.key, this.state.data)
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
if (data.storage.folders[0] != null) {
|
|
||||||
return data
|
|
||||||
} else {
|
|
||||||
return dataApi
|
|
||||||
.createFolder(data.storage.key, {
|
|
||||||
color: '#1278BD',
|
|
||||||
name: 'Default'
|
|
||||||
})
|
|
||||||
.then((_data) => {
|
|
||||||
return {
|
|
||||||
storage: _data.storage,
|
|
||||||
notes: data.notes
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((data) => {
|
|
||||||
console.log(data)
|
|
||||||
store.dispatch({
|
|
||||||
type: 'ADD_STORAGE',
|
|
||||||
storage: data.storage,
|
|
||||||
notes: data.notes
|
|
||||||
})
|
|
||||||
|
|
||||||
const defaultSnippetNote = dataApi
|
|
||||||
.createNote(data.storage.key, {
|
|
||||||
type: 'SNIPPET_NOTE',
|
|
||||||
folder: data.storage.folders[0].key,
|
|
||||||
title: 'Snippet note example',
|
|
||||||
description: 'Snippet note example\nYou can store a series of snippets as a single note, like Gist.',
|
|
||||||
snippets: [
|
|
||||||
{
|
|
||||||
name: 'example.html',
|
|
||||||
mode: 'html',
|
|
||||||
content: '<html>\n<body>\n<h1 id=\'hello\'>Enjoy Boostnote!</h1>\n</body>\n</html>'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'example.js',
|
|
||||||
mode: 'javascript',
|
|
||||||
content: 'var boostnote = document.getElementById(\'enjoy\').innerHTML\n\nconsole.log(boostnote)'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
.then((note) => {
|
|
||||||
store.dispatch({
|
|
||||||
type: 'UPDATE_NOTE',
|
|
||||||
note: note
|
|
||||||
})
|
|
||||||
})
|
|
||||||
const defaultMarkdownNote = dataApi
|
|
||||||
.createNote(data.storage.key, {
|
|
||||||
type: 'MARKDOWN_NOTE',
|
|
||||||
folder: data.storage.folders[0].key,
|
|
||||||
title: 'Welcome to Boostnote!',
|
|
||||||
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) => {
|
|
||||||
store.dispatch({
|
|
||||||
type: 'UPDATE_NOTE',
|
|
||||||
note: note
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return Promise.resolve(defaultSnippetNote)
|
|
||||||
.then(defaultMarkdownNote)
|
|
||||||
.then(() => data.storage)
|
|
||||||
})
|
|
||||||
.then((storage) => {
|
|
||||||
hashHistory.push('/storages/' + storage.key)
|
|
||||||
this.props.close()
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.setState({
|
|
||||||
isSending: false
|
|
||||||
})
|
|
||||||
throw err
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleMigrationRequestedChange (e) {
|
|
||||||
this.setState({
|
|
||||||
migrationRequested: e.target.checked
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleKeyDown (e) {
|
|
||||||
if (e.keyCode === 27) {
|
|
||||||
this.props.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
if (this.state.isLoading) {
|
|
||||||
return <div styleName='root--loading'>
|
|
||||||
<i styleName='spinner' className='fa fa-spin fa-spinner' />
|
|
||||||
<div styleName='loadingMessage'>Preparing initialization...</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div styleName='root'
|
|
||||||
tabIndex='-1'
|
|
||||||
onKeyDown={(e) => this.handleKeyDown(e)}
|
|
||||||
>
|
|
||||||
<div styleName='body'>
|
|
||||||
<div styleName='body-welcome'>
|
|
||||||
Welcome to Boostnote!
|
|
||||||
</div>
|
|
||||||
<div styleName='body-description'>
|
|
||||||
Please select a directory for data storage.
|
|
||||||
</div>
|
|
||||||
<div styleName='body-path'>
|
|
||||||
<input styleName='body-path-input'
|
|
||||||
placeholder='Select Folder'
|
|
||||||
value={this.state.path}
|
|
||||||
onChange={(e) => this.handlePathChange(e)}
|
|
||||||
/>
|
|
||||||
<button styleName='body-path-button'
|
|
||||||
onClick={(e) => this.handlePathBrowseButtonClick(e)}
|
|
||||||
>
|
|
||||||
...
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{this.state.legacyStorageExists &&
|
|
||||||
<div styleName='body-migration'>
|
|
||||||
<label><input type='checkbox' checked={this.state.migrationRequested} onChange={(e) => this.handleMigrationRequestedChange(e)} /> Migrate old data from the legacy app v0.5</label>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div styleName='body-control'>
|
|
||||||
<button styleName='body-control-createButton'
|
|
||||||
ref='createButton'
|
|
||||||
onClick={(e) => this.handleSubmitButtonClick(e)}
|
|
||||||
disabled={this.state.isSending}
|
|
||||||
>
|
|
||||||
{this.state.isSending
|
|
||||||
? <span>
|
|
||||||
<i className='fa fa-spin fa-spinner' /> Loading...
|
|
||||||
</span>
|
|
||||||
: 'CREATE'
|
|
||||||
}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InitModal.propTypes = {
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CSSModules(InitModal, styles)
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
.root
|
|
||||||
modal()
|
|
||||||
background-color #fff
|
|
||||||
max-width 100vw
|
|
||||||
max-height 100vh
|
|
||||||
overflow hidden
|
|
||||||
margin 0
|
|
||||||
padding 150px 0
|
|
||||||
position relative
|
|
||||||
.root--loading
|
|
||||||
@extend .root
|
|
||||||
text-align center
|
|
||||||
.spinner
|
|
||||||
font-size 100px
|
|
||||||
margin 35px auto
|
|
||||||
color $ui-text-color
|
|
||||||
.loadingMessage
|
|
||||||
color $ui-text-color
|
|
||||||
margin 15px auto 35px
|
|
||||||
|
|
||||||
.body
|
|
||||||
padding 30px
|
|
||||||
|
|
||||||
.body-welcome
|
|
||||||
text-align center
|
|
||||||
margin-bottom 25px
|
|
||||||
font-size 32px
|
|
||||||
color $ui-text-color
|
|
||||||
|
|
||||||
.body-description
|
|
||||||
font-size 16px
|
|
||||||
color $ui-text-color
|
|
||||||
text-align center
|
|
||||||
margin-bottom 25px
|
|
||||||
|
|
||||||
.body-path
|
|
||||||
margin 0 auto 25px
|
|
||||||
width 330px
|
|
||||||
|
|
||||||
.body-path-input
|
|
||||||
height 40px
|
|
||||||
vertical-align middle
|
|
||||||
width 300px
|
|
||||||
font-size 14px
|
|
||||||
border-style solid
|
|
||||||
border-width 1px 0 1px 1px
|
|
||||||
border-color $border-color
|
|
||||||
border-top-left-radius 2px
|
|
||||||
border-bottom-left-radius 2px
|
|
||||||
padding 0 5px
|
|
||||||
|
|
||||||
.body-path-button
|
|
||||||
height 42px
|
|
||||||
width 30px
|
|
||||||
font-size 16px
|
|
||||||
font-weight 600
|
|
||||||
border none
|
|
||||||
border-top-right-radius 2px
|
|
||||||
border-bottom-right-radius 2px
|
|
||||||
colorPrimaryButton()
|
|
||||||
vertical-align middle
|
|
||||||
.body-migration
|
|
||||||
margin 0 auto 25px
|
|
||||||
text-align center
|
|
||||||
|
|
||||||
.body-control
|
|
||||||
text-align center
|
|
||||||
|
|
||||||
.body-control-createButton
|
|
||||||
colorPrimaryButton()
|
|
||||||
font-size 14px
|
|
||||||
font-weight 600
|
|
||||||
border none
|
|
||||||
border-radius 2px
|
|
||||||
height 40px
|
|
||||||
padding 0 25px
|
|
||||||
@@ -64,3 +64,20 @@ body[data-theme="dark"]
|
|||||||
.description
|
.description
|
||||||
color $ui-inactive-text-color
|
color $ui-inactive-text-color
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
background-color transparent
|
||||||
|
|
||||||
|
.header
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.control-button
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color transparent
|
||||||
|
&:focus
|
||||||
|
colorDarkPrimaryButton()
|
||||||
|
|
||||||
|
.description
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,8 @@
|
|||||||
color #1EC38B
|
color #1EC38B
|
||||||
.error
|
.error
|
||||||
color red
|
color red
|
||||||
|
.warning
|
||||||
|
color #FFA500
|
||||||
|
|
||||||
.group-control-leftButton
|
.group-control-leftButton
|
||||||
colorDefaultButton()
|
colorDefaultButton()
|
||||||
@@ -127,6 +127,12 @@ colorDarkControl()
|
|||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
background-color $ui-dark-backgroundColor
|
background-color $ui-dark-backgroundColor
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
colorSolarizedDarkControl()
|
||||||
|
border none
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
@@ -154,3 +160,33 @@ body[data-theme="dark"]
|
|||||||
.group-section-control
|
.group-section-control
|
||||||
select, .group-section-control-input
|
select, .group-section-control-input
|
||||||
colorDarkControl()
|
colorDarkControl()
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.group-header
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
.group-header2
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.group-section-control-input
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
.group-control
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
.group-control-leftButton
|
||||||
|
colorDarkDefaultButton()
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
.group-control-rightButton
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
.group-hint
|
||||||
|
colorSolarizedDarkControl()
|
||||||
|
.group-section-control
|
||||||
|
select, .group-section-control-input
|
||||||
|
colorSolarizedDarkControl()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,4 +27,10 @@ p
|
|||||||
|
|
||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
p
|
p
|
||||||
color $ui-dark-text-color
|
color $ui-dark-text-color
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
p
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
@@ -101,3 +101,28 @@ body[data-theme="dark"]
|
|||||||
|
|
||||||
.folderItem-right-dangerButton
|
.folderItem-right-dangerButton
|
||||||
colorDarkDangerButton()
|
colorDarkDangerButton()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.folderItem
|
||||||
|
&:hover
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
|
||||||
|
.folderItem-left-danger
|
||||||
|
color $danger-color
|
||||||
|
|
||||||
|
.folderItem-left-key
|
||||||
|
color $ui-dark-inactive-text-color
|
||||||
|
|
||||||
|
.folderItem-left-colorButton
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
|
||||||
|
.folderItem-right-button
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
|
||||||
|
.folderItem-right-confirmButton
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
|
||||||
|
.folderItem-right-dangerButton
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class HotkeyTab extends React.Component {
|
|||||||
message: err.message != null ? err.message : 'Error occurs!'
|
message: err.message != null ? err.message : 'Error occurs!'
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
this.oldHotkey = this.state.config.hotkey
|
||||||
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
|
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
|
||||||
ipc.addListener('APP_SETTING_ERROR', this.handleSettingError)
|
ipc.addListener('APP_SETTING_ERROR', this.handleSettingError)
|
||||||
}
|
}
|
||||||
@@ -53,6 +54,7 @@ class HotkeyTab extends React.Component {
|
|||||||
config: newConfig
|
config: newConfig
|
||||||
})
|
})
|
||||||
this.clearMessage()
|
this.clearMessage()
|
||||||
|
this.props.haveToSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
handleHintToggleButtonClick (e) {
|
handleHintToggleButtonClick (e) {
|
||||||
@@ -70,6 +72,15 @@ class HotkeyTab extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
config
|
config
|
||||||
})
|
})
|
||||||
|
if (_.isEqual(this.oldHotkey, config.hotkey)) {
|
||||||
|
this.props.haveToSave()
|
||||||
|
} else {
|
||||||
|
this.props.haveToSave({
|
||||||
|
tab: 'Hotkey',
|
||||||
|
type: 'warning',
|
||||||
|
message: 'You have to save!'
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clearMessage () {
|
clearMessage () {
|
||||||
@@ -161,7 +172,8 @@ class HotkeyTab extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
HotkeyTab.propTypes = {
|
HotkeyTab.propTypes = {
|
||||||
dispatch: PropTypes.func
|
dispatch: PropTypes.func,
|
||||||
|
haveToSave: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(HotkeyTab, styles)
|
export default CSSModules(HotkeyTab, styles)
|
||||||
|
|||||||
@@ -60,3 +60,11 @@
|
|||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.root
|
.root
|
||||||
color alpha($tab--dark-text-color, 80%)
|
color alpha($tab--dark-text-color, 80%)
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.list
|
||||||
|
a
|
||||||
|
color $ui-solarized-dark-active-color
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ top-bar--height = 50px
|
|||||||
background-color transparent
|
background-color transparent
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
font-size 16px
|
font-size 16px
|
||||||
|
.saving--warning
|
||||||
|
haveToSave()
|
||||||
|
|
||||||
.nav-button--active
|
.nav-button--active
|
||||||
@extend .nav-button
|
@extend .nav-button
|
||||||
@@ -49,6 +51,8 @@ top-bar--height = 50px
|
|||||||
background-color $ui-button--active-backgroundColor
|
background-color $ui-button--active-backgroundColor
|
||||||
&:hover
|
&:hover
|
||||||
color $ui-text-color
|
color $ui-text-color
|
||||||
|
.saving--warning
|
||||||
|
haveToSave()
|
||||||
|
|
||||||
.nav-button-icon
|
.nav-button-icon
|
||||||
display block
|
display block
|
||||||
@@ -86,3 +90,29 @@ body[data-theme="dark"]
|
|||||||
background-color $dark-primary-button-background--active
|
background-color $dark-primary-button-background--active
|
||||||
&:hover
|
&:hover
|
||||||
color white
|
color white
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
background-color transparent
|
||||||
|
.top-bar
|
||||||
|
background-color transparent
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
p
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.nav
|
||||||
|
background-color transparent
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
.nav-button
|
||||||
|
background-color transparent
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
&:hover
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.nav-button--active
|
||||||
|
@extend .nav-button
|
||||||
|
color $ui-solarized-dark-button--active-color
|
||||||
|
background-color $ui-solarized-dark-button--active-backgroundColor
|
||||||
|
&:hover
|
||||||
|
color white
|
||||||
|
|
||||||
|
|||||||
@@ -168,9 +168,9 @@ class StoragesTab extends React.Component {
|
|||||||
</select>
|
</select>
|
||||||
<div styleName='addStorage-body-section-type-description'>
|
<div styleName='addStorage-body-section-type-description'>
|
||||||
3rd party cloud integration:
|
3rd party cloud integration:
|
||||||
<a href='https://github.com/BoostIO/Boostnote/wiki/Cloud-Syncing'
|
<a href='https://github.com/BoostIO/Boostnote/wiki/Cloud-Syncing-and-Backup'
|
||||||
onClick={(e) => this.handleLinkClick(e)}
|
onClick={(e) => this.handleLinkClick(e)}
|
||||||
>Cloud-Syncing</a>
|
>Cloud-Syncing-and-Backup</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -158,3 +158,44 @@ body[data-theme="dark"]
|
|||||||
.addStorage-body-control-cancelButton
|
.addStorage-body-control-cancelButton
|
||||||
colorDarkDefaultButton()
|
colorDarkDefaultButton()
|
||||||
border-color $ui-dark-borderColor
|
border-color $ui-dark-borderColor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body[data-theme="solarized-dark"]
|
||||||
|
.root
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.folderList-item
|
||||||
|
border-bottom $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
.folderList-empty
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.list-empty
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
.list-control-addStorageButton
|
||||||
|
border-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.addStorage-header
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
.addStorage-body-section-name-input
|
||||||
|
border-color $$ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
.addStorage-body-section-type-description
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
|
||||||
|
.addStorage-body-section-path-button
|
||||||
|
colorPrimaryButton()
|
||||||
|
.addStorage-body-control
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
.addStorage-body-control-createButton
|
||||||
|
colorDarkPrimaryButton()
|
||||||
|
.addStorage-body-control-cancelButton
|
||||||
|
colorDarkDefaultButton()
|
||||||
|
border-color $ui-solarized-dark-borderColor
|
||||||
|
|
||||||
|
|||||||
@@ -20,3 +20,8 @@ $tab--dark-text-color = #E5E5E5
|
|||||||
body[data-theme="dark"]
|
body[data-theme="dark"]
|
||||||
.header
|
.header
|
||||||
color $tab--dark-text-color
|
color $tab--dark-text-color
|
||||||
|
|
||||||
|
haveToSave()
|
||||||
|
color #FFA500
|
||||||
|
font-size 10px
|
||||||
|
margin-top 3px
|
||||||
@@ -7,11 +7,11 @@ import store from 'browser/main/store'
|
|||||||
import consts from 'browser/lib/consts'
|
import consts from 'browser/lib/consts'
|
||||||
import ReactCodeMirror from 'react-codemirror'
|
import ReactCodeMirror from 'react-codemirror'
|
||||||
import CodeMirror from 'codemirror'
|
import CodeMirror from 'codemirror'
|
||||||
|
import 'codemirror-mode-elixir'
|
||||||
|
import _ from 'lodash'
|
||||||
|
|
||||||
const OSX = global.process.platform === 'darwin'
|
const OSX = global.process.platform === 'darwin'
|
||||||
|
|
||||||
import _ from 'lodash'
|
|
||||||
|
|
||||||
const electron = require('electron')
|
const electron = require('electron')
|
||||||
const ipc = electron.ipcRenderer
|
const ipc = electron.ipcRenderer
|
||||||
|
|
||||||
@@ -62,6 +62,7 @@ class UiTab extends React.Component {
|
|||||||
ui: {
|
ui: {
|
||||||
theme: this.refs.uiTheme.value,
|
theme: this.refs.uiTheme.value,
|
||||||
showCopyNotification: this.refs.showCopyNotification.checked,
|
showCopyNotification: this.refs.showCopyNotification.checked,
|
||||||
|
confirmDeletion: this.refs.confirmDeletion.checked,
|
||||||
disableDirectWrite: this.refs.uiD2w != null
|
disableDirectWrite: this.refs.uiD2w != null
|
||||||
? this.refs.uiD2w.checked
|
? this.refs.uiD2w.checked
|
||||||
: false
|
: false
|
||||||
@@ -73,13 +74,18 @@ class UiTab extends React.Component {
|
|||||||
indentType: this.refs.editorIndentType.value,
|
indentType: this.refs.editorIndentType.value,
|
||||||
indentSize: this.refs.editorIndentSize.value,
|
indentSize: this.refs.editorIndentSize.value,
|
||||||
switchPreview: this.refs.editorSwitchPreview.value,
|
switchPreview: this.refs.editorSwitchPreview.value,
|
||||||
keyMap: this.refs.editorKeyMap.value
|
keyMap: this.refs.editorKeyMap.value,
|
||||||
|
scrollPastEnd: this.refs.scrollPastEnd.checked
|
||||||
},
|
},
|
||||||
preview: {
|
preview: {
|
||||||
fontSize: this.refs.previewFontSize.value,
|
fontSize: this.refs.previewFontSize.value,
|
||||||
fontFamily: this.refs.previewFontFamily.value,
|
fontFamily: this.refs.previewFontFamily.value,
|
||||||
codeBlockTheme: this.refs.previewCodeBlockTheme.value,
|
codeBlockTheme: this.refs.previewCodeBlockTheme.value,
|
||||||
lineNumber: this.refs.previewLineNumber.checked
|
lineNumber: this.refs.previewLineNumber.checked,
|
||||||
|
latexInlineOpen: this.refs.previewLatexInlineOpen.value,
|
||||||
|
latexInlineClose: this.refs.previewLatexInlineClose.value,
|
||||||
|
latexBlockOpen: this.refs.previewLatexBlockOpen.value,
|
||||||
|
latexBlockClose: this.refs.previewLatexBlockClose.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,8 +94,19 @@ class UiTab extends React.Component {
|
|||||||
if (newCodemirrorTheme !== codemirrorTheme) {
|
if (newCodemirrorTheme !== codemirrorTheme) {
|
||||||
checkHighLight.setAttribute('href', `../node_modules/codemirror/theme/${newCodemirrorTheme.split(' ')[0]}.css`)
|
checkHighLight.setAttribute('href', `../node_modules/codemirror/theme/${newCodemirrorTheme.split(' ')[0]}.css`)
|
||||||
}
|
}
|
||||||
|
this.setState({ config: newConfig, codemirrorTheme: newCodemirrorTheme }, () => {
|
||||||
this.setState({ config: newConfig, codemirrorTheme: newCodemirrorTheme })
|
const {ui, editor, preview} = this.props.config
|
||||||
|
this.currentConfig = {ui, editor, preview}
|
||||||
|
if (_.isEqual(this.currentConfig, this.state.config)) {
|
||||||
|
this.props.haveToSave()
|
||||||
|
} else {
|
||||||
|
this.props.haveToSave({
|
||||||
|
tab: 'UI',
|
||||||
|
type: 'warning',
|
||||||
|
message: 'You have to save!'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSaveUIClick (e) {
|
handleSaveUIClick (e) {
|
||||||
@@ -106,6 +123,7 @@ class UiTab extends React.Component {
|
|||||||
config: newConfig
|
config: newConfig
|
||||||
})
|
})
|
||||||
this.clearMessage()
|
this.clearMessage()
|
||||||
|
this.props.haveToSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
clearMessage () {
|
clearMessage () {
|
||||||
@@ -141,6 +159,7 @@ class UiTab extends React.Component {
|
|||||||
>
|
>
|
||||||
<option value='default'>Default</option>
|
<option value='default'>Default</option>
|
||||||
<option value='white'>White</option>
|
<option value='white'>White</option>
|
||||||
|
<option value='solarized-dark'>Solarized Dark</option>
|
||||||
<option value='dark'>Dark</option>
|
<option value='dark'>Dark</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -155,6 +174,16 @@ class UiTab extends React.Component {
|
|||||||
Show "Saved to Clipboard" notification when copying
|
Show "Saved to Clipboard" notification when copying
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='group-checkBoxSection'>
|
||||||
|
<label>
|
||||||
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
|
checked={this.state.config.ui.confirmDeletion}
|
||||||
|
ref='confirmDeletion'
|
||||||
|
type='checkbox'
|
||||||
|
/>
|
||||||
|
Show a confirmation dialog when deleting notes
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
{
|
{
|
||||||
global.process.platform === 'win32'
|
global.process.platform === 'win32'
|
||||||
? <div styleName='group-checkBoxSection'>
|
? <div styleName='group-checkBoxSection'>
|
||||||
@@ -164,7 +193,7 @@ class UiTab extends React.Component {
|
|||||||
refs='uiD2w'
|
refs='uiD2w'
|
||||||
disabled={OSX}
|
disabled={OSX}
|
||||||
type='checkbox'
|
type='checkbox'
|
||||||
/>
|
/>
|
||||||
Disable Direct Write(It will be applied after restarting)
|
Disable Direct Write(It will be applied after restarting)
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -274,6 +303,17 @@ class UiTab extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div styleName='group-checkBoxSection'>
|
||||||
|
<label>
|
||||||
|
<input onChange={(e) => this.handleUIChange(e)}
|
||||||
|
checked={this.state.config.editor.scrollPastEnd}
|
||||||
|
ref='scrollPastEnd'
|
||||||
|
type='checkbox'
|
||||||
|
/>
|
||||||
|
Allow editor to scroll past the last line
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div styleName='group-header2'>Preview</div>
|
<div styleName='group-header2'>Preview</div>
|
||||||
<div styleName='group-section'>
|
<div styleName='group-section'>
|
||||||
<div styleName='group-section-label'>
|
<div styleName='group-section-label'>
|
||||||
@@ -326,6 +366,58 @@ class UiTab extends React.Component {
|
|||||||
Show line numbers for preview code blocks
|
Show line numbers for preview code blocks
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
LaTeX Inline Open Delimiter
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input styleName='group-section-control-input'
|
||||||
|
ref='previewLatexInlineOpen'
|
||||||
|
value={config.preview.latexInlineOpen}
|
||||||
|
onChange={(e) => this.handleUIChange(e)}
|
||||||
|
type='text'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
LaTeX Inline Close Delimiter
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input styleName='group-section-control-input'
|
||||||
|
ref='previewLatexInlineClose'
|
||||||
|
value={config.preview.latexInlineClose}
|
||||||
|
onChange={(e) => this.handleUIChange(e)}
|
||||||
|
type='text'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
LaTeX Block Open Delimiter
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input styleName='group-section-control-input'
|
||||||
|
ref='previewLatexBlockOpen'
|
||||||
|
value={config.preview.latexBlockOpen}
|
||||||
|
onChange={(e) => this.handleUIChange(e)}
|
||||||
|
type='text'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section'>
|
||||||
|
<div styleName='group-section-label'>
|
||||||
|
LaTeX Block Close Delimiter
|
||||||
|
</div>
|
||||||
|
<div styleName='group-section-control'>
|
||||||
|
<input styleName='group-section-control-input'
|
||||||
|
ref='previewLatexBlockClose'
|
||||||
|
value={config.preview.latexBlockClose}
|
||||||
|
onChange={(e) => this.handleUIChange(e)}
|
||||||
|
type='text'
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div styleName='group-control'>
|
<div styleName='group-control'>
|
||||||
<button styleName='group-control-rightButton'
|
<button styleName='group-control-rightButton'
|
||||||
@@ -343,7 +435,8 @@ UiTab.propTypes = {
|
|||||||
user: PropTypes.shape({
|
user: PropTypes.shape({
|
||||||
name: PropTypes.string
|
name: PropTypes.string
|
||||||
}),
|
}),
|
||||||
dispatch: PropTypes.func
|
dispatch: PropTypes.func,
|
||||||
|
haveToSave: PropTypes.func
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CSSModules(UiTab, styles)
|
export default CSSModules(UiTab, styles)
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ class Preferences extends React.Component {
|
|||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
currentTab: 'STORAGES'
|
currentTab: 'STORAGES',
|
||||||
|
UIAlert: '',
|
||||||
|
HotkeyAlert: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,6 +60,7 @@ class Preferences extends React.Component {
|
|||||||
<HotkeyTab
|
<HotkeyTab
|
||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
config={config}
|
config={config}
|
||||||
|
haveToSave={alert => this.setState({HotkeyAlert: alert})}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case 'UI':
|
case 'UI':
|
||||||
@@ -65,6 +68,7 @@ class Preferences extends React.Component {
|
|||||||
<UiTab
|
<UiTab
|
||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
config={config}
|
config={config}
|
||||||
|
haveToSave={alert => this.setState({UIAlert: alert})}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
case 'CROWDFUNDING':
|
case 'CROWDFUNDING':
|
||||||
@@ -94,19 +98,26 @@ class Preferences extends React.Component {
|
|||||||
return node.getBoundingClientRect()
|
return node.getBoundingClientRect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
haveToSaveNotif (type, message) {
|
||||||
|
return (
|
||||||
|
<p styleName={`saving--${type}`}>{message}</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const content = this.renderContent()
|
const content = this.renderContent()
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{target: 'STORAGES', label: 'Storages'},
|
{target: 'STORAGES', label: 'Storages'},
|
||||||
{target: 'HOTKEY', label: 'Hotkey'},
|
{target: 'HOTKEY', label: 'Hotkey', Hotkey: this.state.HotkeyAlert},
|
||||||
{target: 'UI', label: 'UI'},
|
{target: 'UI', label: 'UI', UI: this.state.UIAlert},
|
||||||
{target: 'INFO', label: 'Community / Info'},
|
{target: 'INFO', label: 'Community / Info'},
|
||||||
{target: 'CROWDFUNDING', label: 'Crowdfunding'}
|
{target: 'CROWDFUNDING', label: 'Crowdfunding'}
|
||||||
]
|
]
|
||||||
|
|
||||||
const navButtons = tabs.map((tab) => {
|
const navButtons = tabs.map((tab) => {
|
||||||
const isActive = this.state.currentTab === tab.target
|
const isActive = this.state.currentTab === tab.target
|
||||||
|
const isUiHotkeyTab = _.isObject(tab[tab.label]) && tab.label === tab[tab.label].tab
|
||||||
return (
|
return (
|
||||||
<button styleName={isActive
|
<button styleName={isActive
|
||||||
? 'nav-button--active'
|
? 'nav-button--active'
|
||||||
@@ -118,6 +129,7 @@ class Preferences extends React.Component {
|
|||||||
<span styleName='nav-button-label'>
|
<span styleName='nav-button-label'>
|
||||||
{tab.label}
|
{tab.label}
|
||||||
</span>
|
</span>
|
||||||
|
{isUiHotkeyTab ? this.haveToSaveNotif(tab[tab.label].type, tab[tab.label].message) : null}
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -87,8 +87,13 @@ function data (state = defaultDataMap(), action) {
|
|||||||
state.trashedSet = new Set(state.trashedSet)
|
state.trashedSet = new Set(state.trashedSet)
|
||||||
if (note.isTrashed) {
|
if (note.isTrashed) {
|
||||||
state.trashedSet.add(uniqueKey)
|
state.trashedSet.add(uniqueKey)
|
||||||
|
state.starredSet.delete(uniqueKey)
|
||||||
} else {
|
} else {
|
||||||
state.trashedSet.delete(uniqueKey)
|
state.trashedSet.delete(uniqueKey)
|
||||||
|
|
||||||
|
if (note.isStarred) {
|
||||||
|
state.starredSet.add(uniqueKey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,6 +354,13 @@ function data (state = defaultDataMap(), action) {
|
|||||||
state.storageMap = new Map(state.storageMap)
|
state.storageMap = new Map(state.storageMap)
|
||||||
state.storageMap.set(action.storage.key, action.storage)
|
state.storageMap.set(action.storage.key, action.storage)
|
||||||
return state
|
return state
|
||||||
|
case 'EXPORT_FOLDER':
|
||||||
|
{
|
||||||
|
state = Object.assign({}, state)
|
||||||
|
state.storageMap = new Map(state.storageMap)
|
||||||
|
state.storageMap.set(action.storage.key, action.storage)
|
||||||
|
}
|
||||||
|
return state
|
||||||
case 'DELETE_FOLDER':
|
case 'DELETE_FOLDER':
|
||||||
{
|
{
|
||||||
state = Object.assign({}, state)
|
state = Object.assign({}, state)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ tooltip()
|
|||||||
// UI Input
|
// UI Input
|
||||||
$ui-input--focus-borderColor = #369DCD
|
$ui-input--focus-borderColor = #369DCD
|
||||||
$ui-input--disabled-backgroundColor = #DDD
|
$ui-input--disabled-backgroundColor = #DDD
|
||||||
|
$ui-input--create-folder-modal = #C9C9C9
|
||||||
|
|
||||||
// Parts
|
// Parts
|
||||||
$ui-favorite-star-button-color = #FFC216
|
$ui-favorite-star-button-color = #FFC216
|
||||||
@@ -106,6 +107,18 @@ colorDarkPrimaryButton()
|
|||||||
&:active:hover
|
&:active:hover
|
||||||
background-color $dark-primary-button-background--active
|
background-color $dark-primary-button-background--active
|
||||||
|
|
||||||
|
|
||||||
|
colorSolarizedDarkPrimaryButton()
|
||||||
|
color $ui-solarized-dark-text-color
|
||||||
|
background-color $ui-solarized-dark-button-backgroundColor
|
||||||
|
border none
|
||||||
|
&:hover
|
||||||
|
background-color $dark-primary-button-background--hover
|
||||||
|
&:active
|
||||||
|
&:active:hover
|
||||||
|
background-color $dark-primary-button-background--active
|
||||||
|
|
||||||
|
|
||||||
// Danger button(Brand color)
|
// Danger button(Brand color)
|
||||||
$danger-button-background = #c9302c
|
$danger-button-background = #c9302c
|
||||||
$danger-button-background--hover = darken(#c9302c, 5%)
|
$danger-button-background--hover = darken(#c9302c, 5%)
|
||||||
@@ -174,20 +187,20 @@ modal()
|
|||||||
overflow hidden
|
overflow hidden
|
||||||
border-radius $modal-border-radius
|
border-radius $modal-border-radius
|
||||||
|
|
||||||
topBarButtonLight()
|
topBarButtonRight()
|
||||||
position absolute
|
position absolute
|
||||||
width 34px
|
width 34px
|
||||||
height 34px
|
height 34px
|
||||||
border-radius 17px
|
border-radius 17px
|
||||||
font-size 14px
|
font-size 14px
|
||||||
border none
|
border none
|
||||||
color alpha($ui-button-color, 0.4)
|
color alpha($ui-button-color, 0.2)
|
||||||
fill $ui-button-color
|
fill $ui-button-color
|
||||||
background-color transparent
|
background-color transparent
|
||||||
&:active
|
&:active
|
||||||
border-color $ui-button--active-backgroundColor
|
border-color $ui-button--active-backgroundColor
|
||||||
&:hover
|
&:hover
|
||||||
transform scale(1.1)
|
// transform scale(1.1)
|
||||||
transition 0.4s
|
transition 0.4s
|
||||||
color $ui-button-color
|
color $ui-button-color
|
||||||
.control-lockButton-tooltip
|
.control-lockButton-tooltip
|
||||||
@@ -223,10 +236,11 @@ $ui-button--focus-borderColor = lighten(#369DCD, 25%)
|
|||||||
|
|
||||||
/******* Dark theme ********/
|
/******* Dark theme ********/
|
||||||
$ui-dark-active-color = #3A404C
|
$ui-dark-active-color = #3A404C
|
||||||
$ui-dark-borderColor = lighten(#21252B, 20%)
|
$ui-dark-borderColor = #444444
|
||||||
$ui-dark-backgroundColor = #1E2124
|
$ui-dark-backgroundColor = #2C3033
|
||||||
$ui-dark-noteList-backgroundColor = #282C30
|
$ui-dark-noteList-backgroundColor = #2C3033
|
||||||
$ui-dark-noteDetail-backgroundColor = #2D3033
|
$ui-dark-noteDetail-backgroundColor = #2C3033
|
||||||
|
|
||||||
$ui-dark-tag-backgroundColor = #3A404C
|
$ui-dark-tag-backgroundColor = #3A404C
|
||||||
$dark-background-color = lighten($ui-dark-backgroundColor, 10%)
|
$dark-background-color = lighten($ui-dark-backgroundColor, 10%)
|
||||||
$ui-dark-text-color = #DDDDDD
|
$ui-dark-text-color = #DDDDDD
|
||||||
@@ -249,6 +263,7 @@ colorDarkDefaultButton()
|
|||||||
&:active:hover
|
&:active:hover
|
||||||
background-color $ui-dark-button--active-backgroundColor
|
background-color $ui-dark-button--active-backgroundColor
|
||||||
|
|
||||||
|
|
||||||
$dark-danger-button-background = #c9302c
|
$dark-danger-button-background = #c9302c
|
||||||
$dark-danger-button-background--hover = darken(#c9302c, 5%)
|
$dark-danger-button-background--hover = darken(#c9302c, 5%)
|
||||||
$dark-danger-button-background--active = darken(#c9302c, 10%)
|
$dark-danger-button-background--active = darken(#c9302c, 10%)
|
||||||
@@ -307,3 +322,30 @@ modalDark()
|
|||||||
background-color $ui-dark-backgroundColor
|
background-color $ui-dark-backgroundColor
|
||||||
overflow hidden
|
overflow hidden
|
||||||
border-radius $modal-border-radius
|
border-radius $modal-border-radius
|
||||||
|
|
||||||
|
|
||||||
|
/******* Solarized Dark theme ********/
|
||||||
|
$ui-solarized-dark-backgroundColor = #073642
|
||||||
|
$ui-solarized-dark-noteList-backgroundColor = #073642
|
||||||
|
$ui-solarized-dark-noteDetail-backgroundColor = #073642
|
||||||
|
|
||||||
|
$ui-solarized-dark-text-color = #93a1a1
|
||||||
|
$ui-solarized-dark-active-color = #2aa198
|
||||||
|
|
||||||
|
$ui-solarized-dark-borderColor = #586e75
|
||||||
|
|
||||||
|
$ui-solarized-dark-tag-backgroundColor = #002b36
|
||||||
|
|
||||||
|
$ui-solarized-dark-button-backgroundColor = #002b36
|
||||||
|
$ui-solarized-dark-button--active-color = #93a1a1
|
||||||
|
$ui-solarized-dark-button--active-backgroundColor = #073642
|
||||||
|
$ui-solarized-dark-button--hover-backgroundColor = lighten($ui-dark-backgroundColor, 10%)
|
||||||
|
$ui-solarized-dark-button--focus-borderColor = lighten(#369DCD, 25%)
|
||||||
|
|
||||||
|
modalSolarizedDark()
|
||||||
|
position relative
|
||||||
|
z-index $modal-z-index
|
||||||
|
width 100%
|
||||||
|
background-color $ui-solarized-dark-backgroundColor
|
||||||
|
overflow hidden
|
||||||
|
border-radius $modal-border-radius
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
@import '../vars'
|
|
||||||
@import '../mixins/*'
|
|
||||||
global-reset()
|
|
||||||
@import '../theme/*'
|
|
||||||
|
|
||||||
DEFAULT_FONTS = 'Lato', helvetica, arial, sans-serif
|
|
||||||
|
|
||||||
html, body
|
|
||||||
width 100%
|
|
||||||
height 100%
|
|
||||||
overflow hidden
|
|
||||||
|
|
||||||
body
|
|
||||||
font-family DEFAULT_FONTS
|
|
||||||
color textColor
|
|
||||||
font-size fontSize
|
|
||||||
font-weight 400
|
|
||||||
|
|
||||||
body[data-modal="open"]
|
|
||||||
#content *
|
|
||||||
overflow hidden !important
|
|
||||||
|
|
||||||
button, input, select, textarea
|
|
||||||
font-family DEFAULT_FONTS
|
|
||||||
|
|
||||||
div, span, a, button, input, textarea
|
|
||||||
box-sizing border-box
|
|
||||||
|
|
||||||
a
|
|
||||||
color brandColor
|
|
||||||
&:hover
|
|
||||||
color lighten(brandColor, 5%)
|
|
||||||
&:visited
|
|
||||||
color brandColor
|
|
||||||
|
|
||||||
hr
|
|
||||||
border-top none
|
|
||||||
border-bottom solid 1px borderColor
|
|
||||||
margin 15px 0
|
|
||||||
|
|
||||||
button
|
|
||||||
font-weight 400
|
|
||||||
cursor pointer
|
|
||||||
&:focus, &.focus
|
|
||||||
outline none
|
|
||||||
|
|
||||||
.noSelect
|
|
||||||
noSelect()
|
|
||||||
|
|
||||||
.text-center
|
|
||||||
text-align center
|
|
||||||
|
|
||||||
.form-group
|
|
||||||
margin-bottom 15px
|
|
||||||
&>label
|
|
||||||
display block
|
|
||||||
margin-bottom 5px
|
|
||||||
|
|
||||||
.block-input, .inline-input
|
|
||||||
border solid 1px borderColor
|
|
||||||
padding 0 10px
|
|
||||||
font-size 1em
|
|
||||||
height 33px
|
|
||||||
border-radius 5px
|
|
||||||
box-sizing border-box
|
|
||||||
&:focus, &.focus
|
|
||||||
border solid 1px brandBorderColor
|
|
||||||
outline none
|
|
||||||
&.circleInput
|
|
||||||
border-radius 16.5px
|
|
||||||
|
|
||||||
.block-input
|
|
||||||
display block
|
|
||||||
width 100%
|
|
||||||
|
|
||||||
.inline-input
|
|
||||||
display inline-block
|
|
||||||
margin-right 5px
|
|
||||||
|
|
||||||
.relative
|
|
||||||
position relative
|
|
||||||
|
|
||||||
textarea.block-input
|
|
||||||
resize vertical
|
|
||||||
height 125px
|
|
||||||
border-radius 5px
|
|
||||||
padding 5px 10px
|
|
||||||
|
|
||||||
#content
|
|
||||||
fullsize()
|
|
||||||
|
|
||||||
modalZIndex= 1000
|
|
||||||
modalBackColor = transparentify(black, 65%)
|
|
||||||
|
|
||||||
.ModalBase
|
|
||||||
fixed top left bottom right
|
|
||||||
z-index modalZIndex
|
|
||||||
&.hide
|
|
||||||
display none
|
|
||||||
.modalBack
|
|
||||||
absolute top left bottom right
|
|
||||||
background-color modalBackColor
|
|
||||||
z-index modalZIndex + 1
|
|
||||||
.modal
|
|
||||||
position relative
|
|
||||||
width 650px
|
|
||||||
margin 50px auto 0
|
|
||||||
z-index modalZIndex + 2
|
|
||||||
background-color white
|
|
||||||
padding 15px
|
|
||||||
color #666666
|
|
||||||
border-radius 5px
|
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# Build
|
# Build
|
||||||
This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), and [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md).
|
This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md) and [German](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
|
||||||
|
|
||||||
## Environments
|
## Environments
|
||||||
* npm: 4.x
|
* npm: 4.x
|
||||||
|
|||||||
87
docs/de/build.md
Normal file
87
docs/de/build.md
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# Build
|
||||||
|
Diese Seite ist auch verfügbar in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/build.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/build.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/build.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/build.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/build.md) and [German](https://github.com/BoostIO/Boostnote/blob/master/docs/de/build.md).
|
||||||
|
|
||||||
|
## Umgebungen
|
||||||
|
* npm: 4.x
|
||||||
|
* node: 7.x
|
||||||
|
|
||||||
|
Du solltest `npm v4.x` benutzen weil `$ grunt pre-build` scheitert mit Version `v5.x`.
|
||||||
|
|
||||||
|
## Entwicklung
|
||||||
|
|
||||||
|
Wir verwenden Webpack HMR für die Entwicklung von Boostnote.
|
||||||
|
Durch Ausführen der folgenden Befehle, im root Verzeichnis des Projektes, wird Boostnote mit der Default Konfiguration gestartet.
|
||||||
|
|
||||||
|
Installiere die nötigen Pakete unter Verwendung von yarn.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ yarn
|
||||||
|
```
|
||||||
|
|
||||||
|
Bauen und Ausführen.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ yarn run dev-start
|
||||||
|
```
|
||||||
|
|
||||||
|
Dieser Befehl startet `yarn run webpack` und `yarn run hot` parallel. Es hat den selben Effekt wie beide Befehle separat in zwei Terminals zu starten.
|
||||||
|
|
||||||
|
Das `webpack` überprüft den Code auf Änderungen und wendet diese dann automatisch an.
|
||||||
|
|
||||||
|
Wenn folgender Fehler passiert: `Failed to load resource: net::ERR_CONNECTION_REFUSED`, bitte Boostnote neu starten.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> ### Notiz
|
||||||
|
> Es gibt einige Fälle bei denen die App manuell zu refreshen ist.
|
||||||
|
> 1. Wenn eine "constructor method" einer Komponente manuell editiert wird.
|
||||||
|
> 2. Wenn eine neue CSS Klasse ergänzt wird (ähnlich wie 1: die CSS Klasse wird von jeder Komponenete neu geschrieben. Dieser Prozess passiert in der "Constructor method".)
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
Wir verwenden Grunt um das Deployment zu automatisieren.
|
||||||
|
Du kannst das Programm unter Verwendung von `grunt` bauen. Jedoch empfehlen wir das nicht denn der default task beinhaltet codesign und authenticode.
|
||||||
|
|
||||||
|
Deshalb haben wir ein separates Script vorbereitet welches eine ausführbare Datei erstellt.
|
||||||
|
|
||||||
|
Dieser build funktioniert nicht mit npm v5.3.0. Deshalb musst du für den Build die Version v5.2.0 verwenden.
|
||||||
|
|
||||||
|
```
|
||||||
|
grunt pre-build
|
||||||
|
```
|
||||||
|
Du findest die ausführbare Datein in dem Verzeichnis `dist`. Beachte, der auto updater funktioniert nicht da die app nicht signiert ist.
|
||||||
|
|
||||||
|
Wenn du es für notwendig erachtest, kannst du codesign or authenticode mit dieser ausführbaren Datei verwenden.
|
||||||
|
|
||||||
|
## Erstelle eigene Distributions Pakete (deb, rpm)
|
||||||
|
|
||||||
|
Distributions Pakete können mittels `grunt build` auf Linux Plattformen (e.g. Ubuntu, Fedora) erstellt werden.
|
||||||
|
|
||||||
|
> Beachte: Du kannst bei `.deb` and `.rpm` in der selben Umgebung erstellen.
|
||||||
|
|
||||||
|
Nach der Installation der supporteten Version von `node` and `npm`, installiere auch build dependency packages.
|
||||||
|
|
||||||
|
|
||||||
|
Ubuntu/Debian:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo apt-get install -y rpm fakeroot
|
||||||
|
```
|
||||||
|
|
||||||
|
Fedora:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ sudo dnf install -y dpkg dpkg-dev rpm-build fakeroot
|
||||||
|
```
|
||||||
|
|
||||||
|
Dann führe `grunt build` aus.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ grunt build
|
||||||
|
```
|
||||||
|
|
||||||
|
Du findest nun die `.deb` undd `.rpm` Pakete in dem `dist` Ordner.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Special thanks: Translated by [gino909](https://github.com/gino909)
|
||||||
25
docs/de/debug.md
Normal file
25
docs/de/debug.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# How to debug Boostnote (Electron app)
|
||||||
|
Diese Seite ist auch verfügbar in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md) and [German](https://github.com/BoostIO/Boostnote/blob/add-german-documents/docs/de/debug.md).
|
||||||
|
|
||||||
|
Boostnote is eine Electron app, somit basiert sie auf Chromium; Entwickler können die `Developer Tools` verwenden, wie Google Chrome.
|
||||||
|
|
||||||
|
Du kannst die `Developer Tools` so einschalten:
|
||||||
|

|
||||||
|
|
||||||
|
Die `Developer Tools` schauen dann ungefähr so aus:
|
||||||
|

|
||||||
|
|
||||||
|
Wenn Fehler vorkommen, werden die Fehlermeldungen in der `console` ausgegeben.
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
Zum Beispiel kannst du mit dem `debugger` Haltepunkte im Code setzen wie hier veranschaulicht:
|
||||||
|

|
||||||
|
|
||||||
|
Das ist ledigtlich ein Beispiel, du kannst die Art von Debugging verwenden die für dich am besten ist.
|
||||||
|
|
||||||
|
## Referenz
|
||||||
|
* [Official document of Google Chrome about debugging](https://developer.chrome.com/devtools)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Special thanks: Translated by [gino909](https://github.com/gino909)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
# How to debug Boostnote (Electron app)
|
# How to debug Boostnote (Electron app)
|
||||||
This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), and [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md).
|
This page is also available in [Japanese](https://github.com/BoostIO/Boostnote/blob/master/docs/jp/debug.md), [Korean](https://github.com/BoostIO/Boostnote/blob/master/docs/ko/debug.md), [Russain](https://github.com/BoostIO/Boostnote/blob/master/docs/ru/debug.md), [Simplified Chinese](https://github.com/BoostIO/Boostnote/blob/master/docs/zh_CN/debug.md), [French](https://github.com/BoostIO/Boostnote/blob/master/docs/fr/debug.md) and [German](https://github.com/BoostIO/Boostnote/blob/add-german-documents/docs/de/debug.md).
|
||||||
|
|
||||||
Boostnote is an Electron app so it's based on Chromium; developers can use `Developer Tools` just like Google Chrome.
|
Boostnote is an Electron app so it's based on Chromium; developers can use `Developer Tools` just like Google Chrome.
|
||||||
|
|
||||||
|
|||||||
@@ -28,12 +28,14 @@
|
|||||||
|
|
||||||
<script src="../node_modules/codemirror/lib/codemirror.js"></script>
|
<script src="../node_modules/codemirror/lib/codemirror.js"></script>
|
||||||
<script src="../node_modules/codemirror/mode/meta.js"></script>
|
<script src="../node_modules/codemirror/mode/meta.js"></script>
|
||||||
|
<script src="../node_modules/codemirror-mode-elixir/dist/elixir.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/mode/overlay.js"></script>
|
<script src="../node_modules/codemirror/addon/mode/overlay.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/mode/loadmode.js"></script>
|
<script src="../node_modules/codemirror/addon/mode/loadmode.js"></script>
|
||||||
<script src="../node_modules/codemirror/keymap/sublime.js"></script>
|
<script src="../node_modules/codemirror/keymap/sublime.js"></script>
|
||||||
<script src="../node_modules/codemirror/keymap/vim.js"></script>
|
<script src="../node_modules/codemirror/keymap/vim.js"></script>
|
||||||
<script src="../node_modules/codemirror/keymap/emacs.js"></script>
|
<script src="../node_modules/codemirror/keymap/emacs.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/runmode/runmode.js"></script>
|
<script src="../node_modules/codemirror/addon/runmode/runmode.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script>
|
||||||
|
|
||||||
<script src="../node_modules/raphael/raphael.min.js"></script>
|
<script src="../node_modules/raphael/raphael.min.js"></script>
|
||||||
<script src="../node_modules/flowchart.js/release/flowchart.min.js"></script>
|
<script src="../node_modules/flowchart.js/release/flowchart.min.js"></script>
|
||||||
|
|||||||
@@ -65,14 +65,6 @@ updater.autoUpdater.on('error', (err) => {
|
|||||||
console.log(err)
|
console.log(err)
|
||||||
})
|
})
|
||||||
|
|
||||||
ipc.on('update-check', function (event, msg) {
|
|
||||||
if (isUpdateReady) {
|
|
||||||
mainWindow.webContents.send('update-ready', 'Update available!')
|
|
||||||
} else {
|
|
||||||
checkUpdate()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ipc.on('update-app-confirm', function (event, msg) {
|
ipc.on('update-app-confirm', function (event, msg) {
|
||||||
if (isUpdateReady) {
|
if (isUpdateReady) {
|
||||||
mainWindow.removeAllListeners()
|
mainWindow.removeAllListeners()
|
||||||
@@ -102,12 +94,11 @@ app.on('ready', function () {
|
|||||||
Menu.setApplicationMenu(menu)
|
Menu.setApplicationMenu(menu)
|
||||||
break
|
break
|
||||||
case 'win32':
|
case 'win32':
|
||||||
/* eslint-disable */
|
require('./finder-window')
|
||||||
finderWindow = require('./finder-window')
|
|
||||||
/* eslint-disable */
|
|
||||||
mainWindow.setMenu(menu)
|
mainWindow.setMenu(menu)
|
||||||
break
|
break
|
||||||
case 'linux':
|
case 'linux':
|
||||||
|
require('./finder-window')
|
||||||
Menu.setApplicationMenu(menu)
|
Menu.setApplicationMenu(menu)
|
||||||
mainWindow.setMenu(menu)
|
mainWindow.setMenu(menu)
|
||||||
}
|
}
|
||||||
@@ -115,9 +106,20 @@ app.on('ready', function () {
|
|||||||
// Check update every hour
|
// Check update every hour
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
checkUpdate()
|
checkUpdate()
|
||||||
}, 1000 * 60 * 60)
|
}, 1000 * 60 * 60 * 24)
|
||||||
|
|
||||||
checkUpdate()
|
// Check update after 10 secs to prevent file locking of Windows
|
||||||
|
setTimeout(() => {
|
||||||
|
checkUpdate()
|
||||||
|
|
||||||
|
ipc.on('update-check', function (event, msg) {
|
||||||
|
if (isUpdateReady) {
|
||||||
|
mainWindow.webContents.send('update-ready', 'Update available!')
|
||||||
|
} else {
|
||||||
|
checkUpdate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, 10000)
|
||||||
ipcServer = require('./ipcServer')
|
ipcServer = require('./ipcServer')
|
||||||
ipcServer.server.start()
|
ipcServer.server.start()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ const boost = macOS
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Preferences',
|
label: 'Preferences',
|
||||||
|
accelerator: 'Command+,',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('side:preferences')
|
mainWindow.webContents.send('side:preferences')
|
||||||
}
|
}
|
||||||
@@ -56,6 +57,7 @@ const boost = macOS
|
|||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: 'Preferences',
|
label: 'Preferences',
|
||||||
|
accelerator: 'Control+,',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('side:preferences')
|
mainWindow.webContents.send('side:preferences')
|
||||||
}
|
}
|
||||||
@@ -106,6 +108,13 @@ const file = {
|
|||||||
mainWindow.webContents.send('list:isMarkdownNote')
|
mainWindow.webContents.send('list:isMarkdownNote')
|
||||||
mainWindow.webContents.send('export:save-md')
|
mainWindow.webContents.send('export:save-md')
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'HTML (.html)',
|
||||||
|
click () {
|
||||||
|
mainWindow.webContents.send('list:isMarkdownNote')
|
||||||
|
mainWindow.webContents.send('export:save-html')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -152,6 +161,7 @@ if (LINUX) {
|
|||||||
type: 'separator'
|
type: 'separator'
|
||||||
}, {
|
}, {
|
||||||
label: 'Preferences',
|
label: 'Preferences',
|
||||||
|
accelerator: 'Control+,',
|
||||||
click () {
|
click () {
|
||||||
mainWindow.webContents.send('side:preferences')
|
mainWindow.webContents.send('side:preferences')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@
|
|||||||
|
|
||||||
<script src="../node_modules/codemirror/lib/codemirror.js"></script>
|
<script src="../node_modules/codemirror/lib/codemirror.js"></script>
|
||||||
<script src="../node_modules/codemirror/mode/meta.js"></script>
|
<script src="../node_modules/codemirror/mode/meta.js"></script>
|
||||||
|
<script src="../node_modules/codemirror-mode-elixir/dist/elixir.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/mode/overlay.js"></script>
|
<script src="../node_modules/codemirror/addon/mode/overlay.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/mode/loadmode.js"></script>
|
<script src="../node_modules/codemirror/addon/mode/loadmode.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/mode/simple.js"></script>
|
<script src="../node_modules/codemirror/addon/mode/simple.js"></script>
|
||||||
@@ -79,9 +80,12 @@
|
|||||||
|
|
||||||
<script src="../node_modules/codemirror/addon/edit/continuelist.js"></script>
|
<script src="../node_modules/codemirror/addon/edit/continuelist.js"></script>
|
||||||
|
|
||||||
|
<script src="../node_modules/codemirror/addon/edit/closebrackets.js"></script>
|
||||||
|
|
||||||
<script src="../node_modules/codemirror/addon/search/search.js"></script>
|
<script src="../node_modules/codemirror/addon/search/search.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/search/searchcursor.js"></script>
|
<script src="../node_modules/codemirror/addon/search/searchcursor.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/scroll/annotatescrollbar.js"></script>
|
<script src="../node_modules/codemirror/addon/scroll/annotatescrollbar.js"></script>
|
||||||
|
<script src="../node_modules/codemirror/addon/scroll/scrollpastend.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/search/matchesonscrollbar.js"></script>
|
<script src="../node_modules/codemirror/addon/search/matchesonscrollbar.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/search/jump-to-line.js"></script>
|
<script src="../node_modules/codemirror/addon/search/jump-to-line.js"></script>
|
||||||
<script src="../node_modules/codemirror/addon/dialog/dialog.js"></script>
|
<script src="../node_modules/codemirror/addon/dialog/dialog.js"></script>
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "boost",
|
"name": "boost",
|
||||||
"productName": "Boostnote",
|
"productName": "Boostnote",
|
||||||
"version": "0.8.18",
|
"version": "0.8.20",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"description": "Boostnote",
|
"description": "Boostnote",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
"dev-start": "concurrently --kill-others \"npm run webpack\" \"npm run hot\""
|
"dev-start": "concurrently --kill-others \"npm run webpack\" \"npm run hot\""
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"electron-version": "1.6.15"
|
"electron-version": "1.7.10"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -53,6 +53,7 @@
|
|||||||
"aws-sdk": "^2.48.0",
|
"aws-sdk": "^2.48.0",
|
||||||
"aws-sdk-mobile-analytics": "^0.9.2",
|
"aws-sdk-mobile-analytics": "^0.9.2",
|
||||||
"codemirror": "^5.19.0",
|
"codemirror": "^5.19.0",
|
||||||
|
"codemirror-mode-elixir": "^1.1.1",
|
||||||
"electron-config": "^0.2.1",
|
"electron-config": "^0.2.1",
|
||||||
"electron-gh-releases": "^2.0.2",
|
"electron-gh-releases": "^2.0.2",
|
||||||
"flowchart.js": "^1.6.5",
|
"flowchart.js": "^1.6.5",
|
||||||
@@ -102,15 +103,16 @@
|
|||||||
"css-loader": "^0.19.0",
|
"css-loader": "^0.19.0",
|
||||||
"devtron": "^1.1.0",
|
"devtron": "^1.1.0",
|
||||||
"dom-storage": "^2.0.2",
|
"dom-storage": "^2.0.2",
|
||||||
|
"electron": "1.7.10",
|
||||||
"electron-packager": "^6.0.0",
|
"electron-packager": "^6.0.0",
|
||||||
"electron": "^1.6.15",
|
|
||||||
"eslint": "^3.13.1",
|
"eslint": "^3.13.1",
|
||||||
"eslint-config-standard": "^6.2.1",
|
"eslint-config-standard": "^6.2.1",
|
||||||
"eslint-config-standard-jsx": "^3.2.0",
|
"eslint-config-standard-jsx": "^3.2.0",
|
||||||
"eslint-plugin-react": "^7.2.0",
|
"eslint-plugin-react": "^7.2.0",
|
||||||
|
"eslint-plugin-standard": "^3.0.1",
|
||||||
"faker": "^3.1.0",
|
"faker": "^3.1.0",
|
||||||
"grunt": "^0.4.5",
|
"grunt": "^0.4.5",
|
||||||
"grunt-electron-installer": "^1.2.0",
|
"grunt-electron-installer": "2.1.0",
|
||||||
"history": "^1.17.0",
|
"history": "^1.17.0",
|
||||||
"jsdom": "^9.4.2",
|
"jsdom": "^9.4.2",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
|
|||||||
19
readme.md
19
readme.md
@@ -1,6 +1,4 @@
|
|||||||
New:zap:
|
:mega: Open sourcing our [Android and iOS apps](https://github.com/BoostIO/Boostnote-mobile)!
|
||||||
|
|
||||||
Open sourcing our [Android and iOS apps](https://github.com/BoostIO/Boostnote-mobile)!
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -12,7 +10,6 @@ Open sourcing our [Android and iOS apps](https://github.com/BoostIO/Boostnote-mo
|
|||||||
|
|
||||||
## Authors & Maintainers
|
## Authors & Maintainers
|
||||||
- [Rokt33r](https://github.com/rokt33r)
|
- [Rokt33r](https://github.com/rokt33r)
|
||||||
- [sota1235](https://github.com/sota1235)
|
|
||||||
- [Kohei TAKATA](https://github.com/kohei-takata)
|
- [Kohei TAKATA](https://github.com/kohei-takata)
|
||||||
- [Sosuke](https://github.com/sosukesuzuki)
|
- [Sosuke](https://github.com/sosukesuzuki)
|
||||||
- [Kazz](https://github.com/kazup01)
|
- [Kazz](https://github.com/kazup01)
|
||||||
@@ -26,16 +23,20 @@ Thank you to all the people who already contributed to Boostnote!
|
|||||||
Boostnote is an open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [backers](https://github.com/BoostIO/Boostnote/blob/master/Backers.md). If you'd like to join them, please consider:
|
Boostnote is an open source project. It's an independent project with its ongoing development made possible entirely thanks to the support by these awesome [backers](https://github.com/BoostIO/Boostnote/blob/master/Backers.md). If you'd like to join them, please consider:
|
||||||
- [Become a backer or sponsor on Open Collective.](https://opencollective.com/boostnoteio)
|
- [Become a backer or sponsor on Open Collective.](https://opencollective.com/boostnoteio)
|
||||||
|
|
||||||
## Slack Group
|
## Community
|
||||||
Let's talk about Boostnote! <br>
|
- [Facebook Group](https://www.facebook.com/groups/boostnote/)
|
||||||
[Join us](https://join.slack.com/t/boostnote-group/shared_invite/enQtMjc2MDM0MDEyODk2LThlZDlhYmYwMjdkMmJjMGM5MGFiMGJmNzk5ZTdhNzFhMmNmMDFlY2M2YTE1MTZkOThiOGZmNTI3YzJiOTBhMTQ)
|
- [Twitter](https://twitter.com/boostnoteapp)
|
||||||
|
- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMjkxMzMwODYxMDI1LTgwZmRiODg0NzA5MWRmOTJjNzBjZjAwMmMyZGQ4Y2RkOGE0MDg0YjcyMjA5OGUzMmZhNmFiNTMzOTlkYWNlMTM)
|
||||||
|
- [Blog](https://medium.com/boostnote)
|
||||||
|
- [Reddit](https://www.reddit.com/r/Boostnote/)
|
||||||
|
|
||||||
## More Information
|
|
||||||
|
#### More Information
|
||||||
* [Website](https://boostnote.io)
|
* [Website](https://boostnote.io)
|
||||||
* [Subscribe to the Newsletter](https://boostnote.io/#community): Get updates on Boostnote progress. No spam, ever :)
|
* [Subscribe to the Newsletter](https://boostnote.io/#community): Get updates on Boostnote progress. No spam, ever :)
|
||||||
* [Development](https://github.com/BoostIO/Boostnote/blob/master/docs/build.md): Development configurations for Boostnote.
|
* [Development](https://github.com/BoostIO/Boostnote/blob/master/docs/build.md): Development configurations for Boostnote.
|
||||||
* Copyright (C) 2017 Maisin&Co.
|
* Copyright (C) 2017 Maisin&Co.
|
||||||
|
|
||||||
## License
|
#### License
|
||||||
|
|
||||||
[GPL v3](./LICENSE).
|
[GPL v3](./LICENSE).
|
||||||
|
|||||||
17
resources/icon/icon-code-off.svg
Normal file
17
resources/icon/icon-code-off.svg
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="18px" height="20px" viewBox="0 0 18 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>icon-code-off</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<g id="Artboard-4" transform="translate(-1317.000000, -294.000000)" stroke="#8A8C8D" stroke-width="2">
|
||||||
|
<g id="icon-code-off" transform="translate(1318.000000, 295.000000)">
|
||||||
|
<path d="M0,6 L16,6" id="Shape"></path>
|
||||||
|
<path d="M0,12 L16,12" id="Shape"></path>
|
||||||
|
<path d="M6,0 L4,18" id="Shape"></path>
|
||||||
|
<path d="M12,0 L10,18" id="Shape"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 952 B |
28
resources/icon/icon-code-on.svg
Normal file
28
resources/icon/icon-code-on.svg
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="14px" height="15px" viewBox="0 0 14 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>icon-code-on</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<filter x="0.0%" y="0.0%" width="100.0%" height="100.0%" filterUnits="objectBoundingBox" id="filter-1">
|
||||||
|
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
|
||||||
|
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0" type="matrix" in="shadowOffsetOuter1" result="shadowMatrixOuter1"></feColorMatrix>
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="shadowMatrixOuter1"></feMergeNode>
|
||||||
|
<feMergeNode in="SourceGraphic"></feMergeNode>
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<g id="Artboard-4" transform="translate(-1480.000000, -373.000000)" stroke="#1EC38B" stroke-width="1.43999988">
|
||||||
|
<g id="Group" filter="url(#filter-1)" transform="translate(1336.000000, 363.000000)">
|
||||||
|
<g id="icon-code-on" transform="translate(145.000000, 11.657143)">
|
||||||
|
<path d="M0,4.51020408 L12,4.51020408" id="Shape"></path>
|
||||||
|
<path d="M0,8.11836735 L12,8.11836735" id="Shape"></path>
|
||||||
|
<path d="M4.61538462,0 L2.76923077,12.6285714" id="Shape"></path>
|
||||||
|
<path d="M9.23076923,0 L7.38461538,12.6285714" id="Shape"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
13
resources/icon/icon-edit-lock.svg
Normal file
13
resources/icon/icon-edit-lock.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="17px" height="19px" viewBox="0 0 17 19" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 48.1 (47250) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>icon-edit-lock</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-1443.000000, -336.000000)" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<g id="icon-edit-lock" transform="translate(1444.000000, 337.000000)" stroke="#1EC38B" stroke-width="1.66666667">
|
||||||
|
<polygon id="Shape" points="9.16666667 0 12.5 3.42857143 3.33333333 12.8571429 0 12.8571429 0 9.42857143"></polygon>
|
||||||
|
<path d="M0,17.1428571 L15,17.1428571" id="Shape"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 887 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user