Compare commits
97 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8315b75587 | ||
|
|
562b0592af | ||
|
|
1fd1bed01a | ||
|
|
4f116cba34 | ||
|
|
9d1d57f183 | ||
|
|
6feeee8933 | ||
|
|
5541c0dc38 | ||
|
|
4a8054faed | ||
|
|
bbced7be25 | ||
|
|
4055ce19cd | ||
|
|
bcf27233bc | ||
|
|
45111e1610 | ||
|
|
2af86dfa3e | ||
|
|
1b474e1c28 | ||
|
|
c4370694cc | ||
|
|
91f24d96b9 | ||
|
|
bb0b74e889 | ||
|
|
525ab900bd | ||
|
|
31c04de7b6 | ||
|
|
dea0c4287b | ||
|
|
cec4b3132c | ||
|
|
f3ed22dd51 | ||
|
|
6aa9104076 | ||
|
|
e7fd18967b | ||
|
|
8a5558db55 | ||
|
|
4767f15e9b | ||
|
|
b7ca4668e9 | ||
|
|
70e637fada | ||
|
|
459b0ff030 | ||
|
|
2903788fd4 | ||
|
|
af0fdb9277 | ||
|
|
41a58583dc | ||
|
|
c80a26fe0b | ||
|
|
806c3bbaf9 | ||
|
|
fe1c197138 | ||
|
|
b577ca2bc2 | ||
|
|
70a97a6a2a | ||
|
|
034f46792b | ||
|
|
3dc1b59753 | ||
|
|
98b761f1d1 | ||
|
|
712301436d | ||
|
|
4243afb033 | ||
|
|
0f43485606 | ||
|
|
b91b88f16e | ||
|
|
2f2c500e4a | ||
|
|
48514d1020 | ||
|
|
49a4ec5e16 | ||
|
|
c3e92b3b81 | ||
|
|
e78492983a | ||
|
|
a6bd239592 | ||
|
|
7845bbd881 | ||
|
|
68bc440749 | ||
|
|
6dbe3cec69 | ||
|
|
850c339bb3 | ||
|
|
57835d0e32 | ||
|
|
ac2c50c8bc | ||
|
|
7296cbe4ec | ||
|
|
16061a7eba | ||
|
|
566fe92589 | ||
|
|
83cef13f1c | ||
|
|
4bb9533049 | ||
|
|
8beb661af4 | ||
|
|
aa0ad3bb70 | ||
|
|
f7fb531902 | ||
|
|
b32b38bb0d | ||
|
|
6e5f6cc739 | ||
|
|
bbeeeccb31 | ||
|
|
e9525fae22 | ||
|
|
672d409bf2 | ||
|
|
6624178864 | ||
|
|
4a66c6717c | ||
|
|
dd76bc027b | ||
|
|
74ee6ae6ce | ||
|
|
1ae3f295f3 | ||
|
|
3cb2ce41fe | ||
|
|
5534319e93 | ||
|
|
c7373c15a5 | ||
|
|
dbf1d6403b | ||
|
|
95d74c6f5b | ||
|
|
f04b7db9fc | ||
|
|
900fa023fb | ||
|
|
ad9da44afb | ||
|
|
c827717202 | ||
|
|
7d3caa3c2e | ||
|
|
fde7fbccac | ||
|
|
56f06fa7d5 | ||
|
|
c0fba82e73 | ||
|
|
5438cd14a0 | ||
|
|
0d642b308d | ||
|
|
0b96472f72 | ||
|
|
675d0ed08c | ||
|
|
9c0f5c31c2 | ||
|
|
09ce59fd04 | ||
|
|
98cd83c4e0 | ||
|
|
1aec386656 | ||
|
|
b03cd9cd99 | ||
|
|
a641a7b3e4 |
@@ -55,6 +55,7 @@ export default class CodeEditor extends React.Component {
|
||||
indentWithTabs: this.props.indentType !== 'space',
|
||||
keyMap: this.props.keyMap,
|
||||
inputStyle: 'textarea',
|
||||
dragDrop: false,
|
||||
extraKeys: {
|
||||
Tab: function (cm) {
|
||||
if (cm.somethingSelected()) cm.indentSelection('add')
|
||||
@@ -166,9 +167,9 @@ export default class CodeEditor extends React.Component {
|
||||
|
||||
handleDropImage (e) {
|
||||
e.preventDefault()
|
||||
let imagePath = e.dataTransfer.files[0].path
|
||||
let filename = path.basename(imagePath)
|
||||
let imageMd = ``
|
||||
const imagePath = e.dataTransfer.files[0].path
|
||||
const filename = path.basename(imagePath)
|
||||
const imageMd = `})`
|
||||
this.insertImage(imageMd)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,22 +3,31 @@ import CSSModules from 'browser/lib/CSSModules'
|
||||
import styles from './MarkdownEditor.styl'
|
||||
import CodeEditor from 'browser/components/CodeEditor'
|
||||
import MarkdownPreview from 'browser/components/MarkdownPreview'
|
||||
import eventEmitter from 'browser/main/lib/eventEmitter'
|
||||
|
||||
class MarkdownEditor extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.hotkey = props.config.hotkey
|
||||
this.escapeFromEditor = ['Control', 'w']
|
||||
|
||||
this.supportMdBold = ['Control', 'b']
|
||||
|
||||
this.supportMdWordBold = ['Control', ':']
|
||||
|
||||
this.state = {
|
||||
status: 'PREVIEW',
|
||||
renderValue: props.value,
|
||||
keyPressed: {}
|
||||
keyPressed: {},
|
||||
isLocked: false
|
||||
}
|
||||
|
||||
this.lockEditorCode = () => this.handleLockEditor()
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.value = this.refs.code.value
|
||||
eventEmitter.on('editor:lock', this.lockEditorCode)
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
@@ -33,6 +42,7 @@ class MarkdownEditor extends React.Component {
|
||||
|
||||
componentWillUnmount () {
|
||||
this.cancelQueue()
|
||||
eventEmitter.off('editor:lock', this.lockEditorCode)
|
||||
}
|
||||
|
||||
queueRendering (value) {
|
||||
@@ -72,11 +82,14 @@ class MarkdownEditor extends React.Component {
|
||||
this.refs.code.blur()
|
||||
this.refs.preview.focus()
|
||||
}
|
||||
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleBlur (e) {
|
||||
if (this.state.isLocked) return
|
||||
this.setState({ keyPressed: [] })
|
||||
let { config } = this.props
|
||||
if (config.editor.switchPreview === 'BLUR') {
|
||||
let cursorPosition = this.refs.code.editor.getCursor()
|
||||
@@ -86,6 +99,7 @@ class MarkdownEditor extends React.Component {
|
||||
this.refs.preview.focus()
|
||||
this.refs.preview.scrollTo(cursorPosition.line)
|
||||
})
|
||||
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,6 +115,7 @@ class MarkdownEditor extends React.Component {
|
||||
}, () => {
|
||||
this.refs.code.focus()
|
||||
})
|
||||
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +152,7 @@ class MarkdownEditor extends React.Component {
|
||||
} else {
|
||||
this.refs.code.focus()
|
||||
}
|
||||
eventEmitter.emit('topbar:togglelockbutton', this.state.status)
|
||||
}
|
||||
|
||||
reload () {
|
||||
@@ -146,14 +162,36 @@ class MarkdownEditor extends React.Component {
|
||||
}
|
||||
|
||||
handleKeyDown(e) {
|
||||
if (this.state.status !== 'CODE') return false
|
||||
const keyPressed = Object.assign(this.state.keyPressed, {
|
||||
[e.key]: true
|
||||
})
|
||||
this.setState({ keyPressed })
|
||||
let isNoteHandlerKey = (el) => { return this.state.keyPressed[el] }
|
||||
if (this.state.status === 'CODE' && this.hotkey.noteHandlerKey.escapeFromEditor.every(isNoteHandlerKey)) {
|
||||
if (!this.state.isLocked && this.state.status === 'CODE' && this.escapeFromEditor.every(isNoteHandlerKey)) {
|
||||
document.activeElement.blur()
|
||||
}
|
||||
if (this.supportMdBold.every(isNoteHandlerKey)) {
|
||||
this.addMdAndMoveCaretToCenter('****')
|
||||
}
|
||||
if (this.supportMdWordBold.every(isNoteHandlerKey)) {
|
||||
this.addMdBetweenWord('**')
|
||||
}
|
||||
}
|
||||
|
||||
addMdAndMoveCaretToCenter (mdElement) {
|
||||
const currentCaret = this.refs.code.editor.getCursor()
|
||||
const cmDoc = this.refs.code.editor.getDoc()
|
||||
cmDoc.replaceRange(mdElement, currentCaret)
|
||||
this.refs.code.editor.setCursor({line: currentCaret.line, ch: currentCaret.ch + mdElement.length/2})
|
||||
}
|
||||
|
||||
addMdBetweenWord (mdElement) {
|
||||
const currentCaret = this.refs.code.editor.getCursor()
|
||||
const word = this.refs.code.editor.findWordAt(currentCaret)
|
||||
const cmDoc = this.refs.code.editor.getDoc()
|
||||
cmDoc.replaceRange(mdElement, word.anchor)
|
||||
cmDoc.replaceRange(mdElement, { line: word.head.line, ch: word.head.ch + mdElement.length })
|
||||
}
|
||||
|
||||
handleKeyUp (e) {
|
||||
@@ -163,6 +201,10 @@ class MarkdownEditor extends React.Component {
|
||||
this.setState({ keyPressed })
|
||||
}
|
||||
|
||||
handleLockEditor () {
|
||||
this.setState({ isLocked: !this.state.isLocked })
|
||||
}
|
||||
|
||||
render () {
|
||||
let { className, value, config } = this.props
|
||||
|
||||
|
||||
@@ -181,6 +181,8 @@ export default class MarkdownPreview extends React.Component {
|
||||
|
||||
this.refs.root.contentWindow.document.addEventListener('mousedown', this.mouseDownHandler)
|
||||
this.refs.root.contentWindow.document.addEventListener('mouseup', this.mouseUpHandler)
|
||||
this.refs.root.contentWindow.document.addEventListener('drop', this.preventImageDroppedHandler)
|
||||
this.refs.root.contentWindow.document.addEventListener('dragover', this.preventImageDroppedHandler)
|
||||
eventEmitter.on('export:save-text', this.saveAsTextHandler)
|
||||
eventEmitter.on('export:save-md', this.saveAsMdHandler)
|
||||
}
|
||||
@@ -189,6 +191,8 @@ export default class MarkdownPreview extends React.Component {
|
||||
this.refs.root.contentWindow.document.body.removeEventListener('contextmenu', this.contextMenuHandler)
|
||||
this.refs.root.contentWindow.document.removeEventListener('mousedown', this.mouseDownHandler)
|
||||
this.refs.root.contentWindow.document.removeEventListener('mouseup', this.mouseUpHandler)
|
||||
this.refs.root.contentWindow.document.removeEventListener('drop', this.preventImageDroppedHandler)
|
||||
this.refs.root.contentWindow.document.removeEventListener('dragover', this.preventImageDroppedHandler)
|
||||
eventEmitter.off('export:save-text', this.saveAsTextHandler)
|
||||
eventEmitter.off('export:save-md', this.saveAsMdHandler)
|
||||
}
|
||||
@@ -239,6 +243,10 @@ export default class MarkdownPreview extends React.Component {
|
||||
this.refs.root.contentWindow.document.body.setAttribute('data-theme', theme)
|
||||
this.refs.root.contentWindow.document.body.innerHTML = markdown.render(value)
|
||||
|
||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('.taskListItem'), (el) => {
|
||||
el.parentNode.parentNode.style.listStyleType = 'none'
|
||||
})
|
||||
|
||||
_.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => {
|
||||
el.addEventListener('click', this.anchorClickHandler)
|
||||
})
|
||||
@@ -255,7 +263,7 @@ export default class MarkdownPreview extends React.Component {
|
||||
let syntax = CodeMirror.findModeByName(el.className)
|
||||
if (syntax == null) syntax = CodeMirror.findModeByName('Plain Text')
|
||||
CodeMirror.requireMode(syntax.mode, () => {
|
||||
let content = el.innerHTML
|
||||
let content = decodeHTMLEntities(el.innerHTML)
|
||||
el.innerHTML = ''
|
||||
el.parentNode.className += ` cm-s-${codeBlockTheme} CodeMirror`
|
||||
CodeMirror.runMode(content, syntax.mime, el, {
|
||||
@@ -325,6 +333,11 @@ export default class MarkdownPreview extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
preventImageDroppedHandler(e) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
render () {
|
||||
let { className, style, tabIndex } = this.props
|
||||
return (
|
||||
|
||||
@@ -54,7 +54,6 @@ body
|
||||
font-family helvetica, arial, sans-serif
|
||||
line-height 1.6
|
||||
overflow-x hidden
|
||||
user-select all
|
||||
background-color $ui-noteDetail-backgroundColor
|
||||
.katex
|
||||
font 400 1.2em 'KaTeX_Main'
|
||||
@@ -78,7 +77,6 @@ body
|
||||
li
|
||||
label.taskListItem
|
||||
margin-left -2em
|
||||
background-color white
|
||||
div.math-rendered
|
||||
text-align center
|
||||
.math-failed
|
||||
|
||||
@@ -25,15 +25,23 @@ class MarkdownNoteDetail extends React.Component {
|
||||
note: Object.assign({
|
||||
title: '',
|
||||
content: ''
|
||||
}, props.note)
|
||||
}, props.note),
|
||||
isLockButtonShown: false,
|
||||
isLocked: false
|
||||
}
|
||||
this.dispatchTimer = null
|
||||
|
||||
this.toggleLockButton = this.handleToggleLockButton.bind(this)
|
||||
}
|
||||
|
||||
focus () {
|
||||
this.refs.content.focus()
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
ee.on('topbar:togglelockbutton', this.toggleLockButton)
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.note.key !== this.props.note.key && !this.isMovingNote) {
|
||||
if (this.saveQueue != null) this.saveNow()
|
||||
@@ -50,13 +58,20 @@ class MarkdownNoteDetail extends React.Component {
|
||||
if (this.saveQueue != null) this.saveNow()
|
||||
}
|
||||
|
||||
componentDidUnmount () {
|
||||
ee.off('topbar:togglelockbutton', this.toggleLockButton)
|
||||
}
|
||||
|
||||
findTitle (value) {
|
||||
let splitted = value.split('\n')
|
||||
let title = null
|
||||
let isMarkdownInCode = false
|
||||
|
||||
for (let i = 0; i < splitted.length; i++) {
|
||||
let trimmedLine = splitted[i].trim()
|
||||
if (trimmedLine.match(/^# .+/)) {
|
||||
if (trimmedLine.match('```')) {
|
||||
isMarkdownInCode = !isMarkdownInCode
|
||||
} else if (isMarkdownInCode === false && trimmedLine.match(/^# +/)) {
|
||||
title = trimmedLine.substring(1, trimmedLine.length).trim()
|
||||
break
|
||||
}
|
||||
@@ -200,10 +215,34 @@ class MarkdownNoteDetail extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleLockButtonMouseDown (e) {
|
||||
e.preventDefault()
|
||||
ee.emit('editor:lock')
|
||||
this.setState({ isLocked: !this.state.isLocked })
|
||||
if (this.state.isLocked) this.focus()
|
||||
}
|
||||
|
||||
getToggleLockButton () {
|
||||
return this.state.isLocked ? 'fa-lock' : 'fa-unlock-alt'
|
||||
}
|
||||
|
||||
handleDeleteKeyDown (e) {
|
||||
if (e.keyCode === 27) this.handleDeleteCancelButtonClick(e)
|
||||
}
|
||||
|
||||
handleToggleLockButton (event, noteStatus) {
|
||||
// first argument event is not used
|
||||
if (this.props.config.editor.switchPreview === 'BLUR' && noteStatus === 'CODE') {
|
||||
this.setState({isLockButtonShown: true})
|
||||
} else {
|
||||
this.setState({isLockButtonShown: false})
|
||||
}
|
||||
}
|
||||
|
||||
handleFocus (e) {
|
||||
this.focus()
|
||||
}
|
||||
|
||||
render () {
|
||||
let { data, config } = this.props
|
||||
let { note } = this.state
|
||||
@@ -235,10 +274,34 @@ class MarkdownNoteDetail extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
<div styleName='info-right'>
|
||||
<button styleName='info-right-button'
|
||||
{(() => {
|
||||
const faClassName=`fa ${this.getToggleLockButton()}`
|
||||
const lockButtonComponent =
|
||||
<button styleName='control-lockButton'
|
||||
onFocus={(e) => this.handleFocus(e)}
|
||||
onMouseDown={(e) => this.handleLockButtonMouseDown(e)}
|
||||
>
|
||||
<i className={faClassName} styleName='lock-button'/>
|
||||
<span styleName='control-lockButton-tooltip'>
|
||||
{this.state.isLocked ? 'Unlock' : 'Lock'}
|
||||
</span>
|
||||
</button>
|
||||
return (
|
||||
this.state.isLockButtonShown ? lockButtonComponent : ''
|
||||
)
|
||||
})()}
|
||||
<button styleName='control-trashButton'
|
||||
onClick={(e) => this.handleContextButtonClick(e)}
|
||||
>
|
||||
<i className='fa fa-ellipsis-v' />
|
||||
<svg height="17px" id="Capa_1" style={{"enableBackground":"new 0 0 753.23 753.23"}} width="17px" version="1.1" viewBox="0 0 753.23 753.23" x="0px" y="0px" xmlSpace="preserve">
|
||||
<g>
|
||||
<g id="_x34__19_">
|
||||
<g>
|
||||
<path d="M494.308,659.077c12.993,0,23.538-10.546,23.538-23.539V353.077c0-12.993-10.545-23.539-23.538-23.539
				s-23.538,10.545-23.538,23.539v282.461C470.77,648.531,481.314,659.077,494.308,659.077z M635.538,94.154h-141.23V47.077
				C494.308,21.067,473.24,0,447.23,0H306c-26.01,0-47.077,21.067-47.077,47.077v47.077h-141.23
				c-26.01,0-47.077,21.067-47.077,47.077v47.077c0,25.986,21.067,47.077,47.077,47.077v423.692
				c0,51.996,42.157,94.153,94.154,94.153h329.539c51.996,0,94.153-42.157,94.153-94.153V235.385
				c26.01,0,47.077-21.091,47.077-47.077V141.23C682.615,115.221,661.548,94.154,635.538,94.154z M306,70.615
				c0-12.993,10.545-23.539,23.538-23.539h94.154c12.993,0,23.538,10.545,23.538,23.539v23.539c-22.809,0-141.23,0-141.23,0V70.615z
				 M588.461,659.077c0,25.986-21.066,47.076-47.076,47.076H211.846c-26.01,0-47.077-21.09-47.077-47.076V235.385h423.692V659.077z
				 M612,188.308H141.23c-12.993,0-23.538-10.545-23.538-23.539s10.545-23.539,23.538-23.539H612
				c12.993,0,23.538,10.545,23.538,23.539S624.993,188.308,612,188.308z M258.923,659.077c12.993,0,23.539-10.546,23.539-23.539
				V353.077c0-12.993-10.545-23.539-23.539-23.539s-23.539,10.545-23.539,23.539v282.461
				C235.384,648.531,245.93,659.077,258.923,659.077z M376.615,659.077c12.993,0,23.538-10.546,23.538-23.539V353.077
				c0-12.993-10.545-23.539-23.538-23.539s-23.539,10.545-23.539,23.539v282.461C353.077,648.531,363.622,659.077,376.615,659.077z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,28 @@
|
||||
background-color $ui-noteDetail-backgroundColor
|
||||
box-shadow $note-detail-box-shadow
|
||||
|
||||
.lock-button
|
||||
padding-bottom 3px
|
||||
|
||||
.control-lockButton
|
||||
topBarButtonLight()
|
||||
|
||||
.control-lockButton-tooltip
|
||||
tooltip()
|
||||
position fixed
|
||||
pointer-events none
|
||||
top 50px
|
||||
z-index 200
|
||||
padding 5px
|
||||
line-height normal
|
||||
border-radius 2px
|
||||
opacity 0
|
||||
transition 0.1s
|
||||
|
||||
.control-trashButton
|
||||
float right
|
||||
topBarButtonLight()
|
||||
|
||||
.body
|
||||
absolute left right
|
||||
left $note-detail-left-margin
|
||||
@@ -24,3 +46,12 @@ body[data-theme="dark"]
|
||||
border-color $ui-dark-borderColor
|
||||
background-color $ui-dark-noteDetail-backgroundColor
|
||||
box-shadow none
|
||||
|
||||
.control-lockButton
|
||||
topBarButtonDark()
|
||||
|
||||
.control-lockButton-tooltip
|
||||
darkTooltip()
|
||||
|
||||
.control-trashButton
|
||||
topBarButtonDark()
|
||||
|
||||
@@ -38,7 +38,7 @@ $info-margin-under-border = 27px
|
||||
margin 13px 2px
|
||||
padding 0
|
||||
border-radius 17px
|
||||
&:hover .info-right-button-tooltip
|
||||
&:hover .info-left-button-tooltip
|
||||
opacity 1
|
||||
&:focus
|
||||
border-color $ui-favorite-star-button-color
|
||||
@@ -54,21 +54,6 @@ $info-margin-under-border = 27px
|
||||
bottom 1px
|
||||
padding-left 30px
|
||||
|
||||
.info-right-button
|
||||
width 34px
|
||||
height 34px
|
||||
border-radius 17px
|
||||
font-size 14px
|
||||
margin 13px 7px
|
||||
padding 0
|
||||
border none
|
||||
color $ui-button-color
|
||||
background-color transparent
|
||||
&:hover
|
||||
opacity 1
|
||||
background-color $ui-button--hover-backgroundColor
|
||||
|
||||
|
||||
body[data-theme="dark"]
|
||||
.info
|
||||
border-color $ui-dark-borderColor
|
||||
@@ -88,11 +73,3 @@ body[data-theme="dark"]
|
||||
|
||||
.info-right
|
||||
background-color $ui-dark-noteDetail-backgroundColor
|
||||
|
||||
.info-right-button
|
||||
navDarkButtonColor()
|
||||
border-color $ui-dark-borderColor
|
||||
&:active
|
||||
border-color $ui-dark-button--focus-borderColor
|
||||
&:focus
|
||||
border-color $ui-button--focus-borderColor
|
||||
|
||||
@@ -259,6 +259,8 @@ class SnippetNoteDetail extends React.Component {
|
||||
this.setState({
|
||||
note: this.state.note,
|
||||
snippetIndex
|
||||
}, () => {
|
||||
this.save()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -545,10 +547,18 @@ class SnippetNoteDetail extends React.Component {
|
||||
/>
|
||||
</div>
|
||||
<div styleName='info-right'>
|
||||
<button styleName='info-right-button'
|
||||
<button styleName='control-trashButton'
|
||||
onClick={(e) => this.handleContextButtonClick(e)}
|
||||
>
|
||||
<i className='fa fa-ellipsis-v' />
|
||||
<svg height="17px" id="Capa_1" style={{"enableBackground":"new 0 0 753.23 753.23"}} width="17px" version="1.1" viewBox="0 0 753.23 753.23" x="0px" y="0px" xmlSpace="preserve">
|
||||
<g>
|
||||
<g id="_x34__19_">
|
||||
<g>
|
||||
<path d="M494.308,659.077c12.993,0,23.538-10.546,23.538-23.539V353.077c0-12.993-10.545-23.539-23.538-23.539
				s-23.538,10.545-23.538,23.539v282.461C470.77,648.531,481.314,659.077,494.308,659.077z M635.538,94.154h-141.23V47.077
				C494.308,21.067,473.24,0,447.23,0H306c-26.01,0-47.077,21.067-47.077,47.077v47.077h-141.23
				c-26.01,0-47.077,21.067-47.077,47.077v47.077c0,25.986,21.067,47.077,47.077,47.077v423.692
				c0,51.996,42.157,94.153,94.154,94.153h329.539c51.996,0,94.153-42.157,94.153-94.153V235.385
				c26.01,0,47.077-21.091,47.077-47.077V141.23C682.615,115.221,661.548,94.154,635.538,94.154z M306,70.615
				c0-12.993,10.545-23.539,23.538-23.539h94.154c12.993,0,23.538,10.545,23.538,23.539v23.539c-22.809,0-141.23,0-141.23,0V70.615z
				 M588.461,659.077c0,25.986-21.066,47.076-47.076,47.076H211.846c-26.01,0-47.077-21.09-47.077-47.076V235.385h423.692V659.077z
				 M612,188.308H141.23c-12.993,0-23.538-10.545-23.538-23.539s10.545-23.539,23.538-23.539H612
				c12.993,0,23.538,10.545,23.538,23.539S624.993,188.308,612,188.308z M258.923,659.077c12.993,0,23.539-10.546,23.539-23.539
				V353.077c0-12.993-10.545-23.539-23.539-23.539s-23.539,10.545-23.539,23.539v282.461
				C235.384,648.531,245.93,659.077,258.923,659.077z M376.615,659.077c12.993,0,23.538-10.546,23.538-23.539V353.077
				c0-12.993-10.545-23.539-23.538-23.539s-23.539,10.545-23.539,23.539v282.461C353.077,648.531,363.622,659.077,376.615,659.077z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,6 +68,10 @@
|
||||
&:active .update-icon
|
||||
color white
|
||||
|
||||
.control-trashButton
|
||||
float right
|
||||
topBarButtonLight()
|
||||
|
||||
body[data-theme="dark"]
|
||||
.root
|
||||
border-color $ui-dark-borderColor
|
||||
@@ -93,3 +97,6 @@ body[data-theme="dark"]
|
||||
.override
|
||||
button
|
||||
border-color $ui-dark-borderColor
|
||||
|
||||
.control-trashButton
|
||||
topBarButtonDark()
|
||||
|
||||
@@ -38,10 +38,14 @@ class NoteList extends React.Component {
|
||||
this.focusHandler = () => {
|
||||
this.refs.list.focus()
|
||||
}
|
||||
this.alertIfSnippetHnalder = () => {
|
||||
this.alertIfSnippetHandler = () => {
|
||||
this.alertIfSnippet()
|
||||
}
|
||||
|
||||
this.jumpToTopHandler = () => {
|
||||
this.jumpToTop()
|
||||
}
|
||||
|
||||
this.state = {
|
||||
}
|
||||
}
|
||||
@@ -51,7 +55,9 @@ class NoteList extends React.Component {
|
||||
ee.on('list:next', this.selectNextNoteHandler)
|
||||
ee.on('list:prior', this.selectPriorNoteHandler)
|
||||
ee.on('list:focus', this.focusHandler)
|
||||
ee.on('list:isMarkdownNote', this.alertIfSnippetHnalder)
|
||||
ee.on('list:isMarkdownNote', this.alertIfSnippetHandler)
|
||||
ee.on('list:top', this.jumpToTopHandler)
|
||||
ee.on('list:jumpToTop', this.jumpToTopHandler)
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
@@ -70,7 +76,9 @@ class NoteList extends React.Component {
|
||||
ee.off('list:next', this.selectNextNoteHandler)
|
||||
ee.off('list:prior', this.selectPriorNoteHandler)
|
||||
ee.off('list:focus', this.focusHandler)
|
||||
ee.off('list:isMarkdownNote', this.alertIfSnippetHnalder)
|
||||
ee.off('list:isMarkdownNote', this.alertIfSnippetHandler)
|
||||
ee.off('list:top', this.jumpToTopHandler)
|
||||
ee.off('list:jumpToTop', this.jumpToTopHandler)
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
@@ -324,6 +332,23 @@ class NoteList extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
jumpToTop() {
|
||||
if (this.notes === null || this.notes.length === 0) {
|
||||
return
|
||||
}
|
||||
let { router } = this.context
|
||||
let { location } = this.props
|
||||
|
||||
const targetIndex = 0
|
||||
|
||||
router.push({
|
||||
pathname: location.pathname,
|
||||
query: {
|
||||
key: this.notes[targetIndex].storage + '-' + this.notes[targetIndex].key
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
render () {
|
||||
let { location, notes, config } = this.props
|
||||
let sortFunc = config.sortBy === 'CREATED_AT'
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
.top-menu
|
||||
navButtonColor()
|
||||
height $topBar-height - 1
|
||||
height $topBar-height
|
||||
padding 0 15px
|
||||
font-size 14px
|
||||
width 100%
|
||||
|
||||
@@ -17,9 +17,6 @@ export const DEFAULT_CONFIG = {
|
||||
hotkey: {
|
||||
toggleFinder: OSX ? 'Cmd + Alt + S' : 'Super + Alt + S',
|
||||
toggleMain: OSX ? 'Cmd + Alt + L' : 'Super + Alt + E',
|
||||
noteHandlerKey: {
|
||||
escapeFromEditor: ['Control', 'e']
|
||||
}
|
||||
},
|
||||
ui: {
|
||||
theme: 'default',
|
||||
|
||||
@@ -75,3 +75,4 @@ body[data-theme="dark"]
|
||||
|
||||
.control-input
|
||||
border-color $ui-dark-borderColor
|
||||
color $ui-dark-text-color
|
||||
|
||||
@@ -139,6 +139,24 @@ modal()
|
||||
border-radius $modal-border-radius
|
||||
box-shadow 2px 2px 10px gray
|
||||
|
||||
topBarButtonLight()
|
||||
width 34px
|
||||
height 34px
|
||||
border-radius 17px
|
||||
font-size 14px
|
||||
margin 13px 7px
|
||||
padding-top 7px
|
||||
border none
|
||||
color $ui-button-color
|
||||
fill $ui-button-color
|
||||
background-color transparent
|
||||
&:active
|
||||
border-color $ui-button--active-backgroundColor
|
||||
&:hover
|
||||
background-color $ui-button--hover-backgroundColor
|
||||
.control-lockButton-tooltip
|
||||
opacity 1
|
||||
|
||||
// Dark theme
|
||||
$ui-dark-borderColor = lighten(#21252B, 20%)
|
||||
$ui-dark-backgroundColor = #1D1D1D
|
||||
@@ -151,6 +169,7 @@ $ui-dark-button--active-color = white
|
||||
$ui-dark-button--active-backgroundColor = #6AA5E9
|
||||
$ui-dark-button--hover-backgroundColor = lighten($ui-dark-backgroundColor, 10%)
|
||||
$ui-dark-button--focus-borderColor = lighten(#369DCD, 25%)
|
||||
$ui-dark-topbar-button-color = #939395
|
||||
|
||||
$dark-default-button-background = $ui-dark-backgroundColor
|
||||
$dark-default-button-background--hover = $ui-dark-button--hover-backgroundColor
|
||||
@@ -190,6 +209,18 @@ navDarkButtonColor()
|
||||
background-color $ui-dark-button--active-backgroundColor
|
||||
color $ui-dark-button--active-color
|
||||
|
||||
topBarButtonDark()
|
||||
border-color $ui-dark-borderColor
|
||||
color $ui-dark-topbar-button-color
|
||||
&:hover
|
||||
background-color $dark-default-button-background--hover
|
||||
&:active
|
||||
border-color $ui-dark-button--focus-borderColor
|
||||
&:active:hover
|
||||
background-color $ui-dark-button--active-backgroundColor
|
||||
&:focus
|
||||
border-color $ui-button--focus-borderColor
|
||||
|
||||
$ui-dark-tooltip-text-color = white
|
||||
$ui-dark-tooltip-backgroundColor = alpha(#444, 70%)
|
||||
$ui-dark-tooltip-button-backgroundColor = #D1D1D1
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
# Contributing to Boostnote
|
||||
|
||||
> English below.
|
||||
|
||||
## Pull requestの著作権について
|
||||
|
||||
Pull requestをすることはその変化分のコードの著作権をMAISIN&CO.に譲渡することに同意することになります。
|
||||
|
||||
アプリケーションのLicenseのをいつでも変える選択肢を残したいからです。
|
||||
しかし、これはいずれかBoostnoteが有料の商用アプリになる可能性がある話ではありません。
|
||||
もし、このアプリケーションで金を稼ごうとするならBoostnote専用のCloud storageの提供やMobile appとの連動、何か特殊なプレミアム機能の提供など形になると思います。
|
||||
現在考えられているのは、GPL v3の場合、他のライセンスとの互換が不可能であるため、もしより自由なLicense(BSD, MIT)に変える時に改めて著作権者としてライセンスし直す選択肢を残したいぐらいのイメージです。
|
||||
|
||||
---
|
||||
|
||||
# Contributing to Boostnote(ENG)
|
||||
|
||||
## About copyright of Pull Request
|
||||
|
||||
If you make a pull request, It means you agree to transfer the copyright of the code changes to MAISIN&CO.
|
||||
|
||||
It doesn't mean Boostnote will become a paid app. If we want to earn some money, We will try other way, which is some kind of cloud storage, Mobile app integration or some SPECIAL features.
|
||||
Because GPL v3 is too strict to be compatible with any other License, We thought this is needed to replace the license with much freer one(like BSD, MIT) somewhen.
|
||||
|
||||
---
|
||||
|
||||
# Contributing to Boostnote(Japanese)
|
||||
|
||||
## Pull requestの著作権について
|
||||
|
||||
Pull requestをすることはその変化分のコードの著作権をMAISIN&CO.に譲渡することに同意することになります。
|
||||
|
||||
アプリケーションのLicenseをいつでも変える選択肢を残したいと思うからです。
|
||||
これはいずれかBoostnoteが有料の商用アプリになる可能性がある話ではありません。
|
||||
もし、このアプリケーションに料金が発生する時は、Boostnote専用のCloud storageの提供やMobile appとの連動、何か特殊なプレミアム機能の提供など形になります。
|
||||
現在考えられているのは、GPL v3の場合、他のライセンスとの互換が不可能であるため、もしより自由なLicense(BSD, MIT)に変える時に改めて著作権者としてライセンスし直す選択肢を残すイメージです。
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const electron = require('electron')
|
||||
const { app } = electron
|
||||
const { systemPreferences } = electron
|
||||
const BrowserWindow = electron.BrowserWindow
|
||||
const Menu = electron.Menu
|
||||
const MenuItem = electron.MenuItem
|
||||
@@ -45,12 +44,8 @@ finderWindow.on('close', function (e) {
|
||||
finderWindow.hide()
|
||||
})
|
||||
|
||||
var trayIcon = process.platform === 'darwin'
|
||||
? !systemPreferences.isDarkMode()
|
||||
var trayIcon = process.platform === 'darwin' || process.platform === 'win32'
|
||||
? path.join(__dirname, '../resources/tray-icon-default.png')
|
||||
: path.join(__dirname, '../resources/tray-icon-dark.png')
|
||||
: process.platform === 'win32'
|
||||
? path.join(__dirname, '../resources/tray-icon-dark.png')
|
||||
: path.join(__dirname, '../resources/tray-icon.png')
|
||||
var appIcon = new Tray(trayIcon)
|
||||
appIcon.setToolTip('Boostnote')
|
||||
|
||||
@@ -102,6 +102,9 @@ app.on('ready', function () {
|
||||
Menu.setApplicationMenu(menu)
|
||||
break
|
||||
case 'win32':
|
||||
/* eslint-disable */
|
||||
finderWindow = require('./finder-window')
|
||||
/* eslint-disable */
|
||||
mainWindow.setMenu(menu)
|
||||
break
|
||||
case 'linux':
|
||||
|
||||
@@ -183,6 +183,13 @@ var view = {
|
||||
mainWindow.webContents.send('list:prior')
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Jump to Top',
|
||||
accelerator: 'Control + G',
|
||||
click () {
|
||||
mainWindow.webContents.send('list:jumpToTop')
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "boost",
|
||||
"version": "0.8.3",
|
||||
"version": "0.8.7",
|
||||
"description": "Boostnote",
|
||||
"main": "index.js",
|
||||
"license": "GPL-3.0",
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
- [Rokt33r](https://github.com/rokt33r)
|
||||
- [sota1235](https://github.com/sota1235)
|
||||
- [Kohei TAKATA](https://github.com/kohei-takata)
|
||||
- [asmsuechan](https://github.com/asmsuechan)
|
||||
- [Kazu Yokomizo](https://github.com/kazup01)
|
||||
|
||||
## Contributors
|
||||
|
||||
85
readme-ko.md
@@ -1,85 +0,0 @@
|
||||
# Boostnote
|
||||
|
||||
> [Boostnote store](https://boostnote.paintory.com/)가 생겼습니다!! :tada: 그리고,[Pateron](https://www.patreon.com/boostnote)에서도 저희를 지원 하실 수 있습니다.!
|
||||
|
||||

|
||||
|
||||
오픈소스 노트 앱
|
||||
|
||||
다음과 같은 용무가 있는 경우 이슈트래커를 이용해 주세요.
|
||||
- Boostnote에 대해 질문을 하고 싶을 때
|
||||
- Boostnote나 계획사항에 대해 피드백을 주고 싶을 때
|
||||
- Boostnote에 버그를 보고하고 싶을 때
|
||||
- Boostnote에 기여하고 싶을 때
|
||||
|
||||
저흰 Slack을 운영하고 있습니다. 혹시 좀 더 저희들과 깊게 관여하고 싶으시다면 @rokt33r에 초대를 부탁하세요.
|
||||
|
||||
## Goal
|
||||
|
||||
그냥 글쓰는게 즐거워지셨으면 좋겠어요. :grinning:
|
||||
|
||||
- 타겟 OS : OSX, Windows, Linux(나중엔 모바일까지도!)
|
||||
- Cloud : Google drive, Dropbox, One drive, iCloud...
|
||||
- 오픈소스로 남을 것!
|
||||
|
||||
## 영감받은 앱/서비스
|
||||
|
||||
- Atom
|
||||
- Quiver
|
||||
- Evernote
|
||||
- GitKraken
|
||||
- GitBook
|
||||
- Gist
|
||||
- Gistbox
|
||||
- Snippets Lab
|
||||
|
||||
## Using stack
|
||||
|
||||
- Electron
|
||||
- React
|
||||
- Webpack
|
||||
- Redux
|
||||
- CSSModules
|
||||
|
||||
## Codestyle
|
||||
|
||||
[](https://github.com/feross/standard)
|
||||
|
||||
## Development
|
||||
|
||||
- [Build](docs/build.md)
|
||||
|
||||
## Goods
|
||||
|
||||
<img src="https://boostnote.io/images/t3.png" width="250"/>
|
||||
<img src="https://boostnote.io/images/t1.png" width="250"/>
|
||||
|
||||
[Boostnote store](https://boostnote.paintory.com/)에서 몇가지 상품들을 팔고있습니다.
|
||||
|
||||
전세계 어디든 배송 가능합니다. 이 스토어는 [Paintory](https://paintory.com/)에서 제공됩니다.
|
||||
|
||||
## Donation
|
||||
|
||||
[Pateron page](https://www.patreon.com/boostnote)에서 기부 하실 수 있습니다.
|
||||
|
||||
## Author & Maintainer
|
||||
|
||||
[Rokt33r(Dick Choi of MAISIN&CO.)](https://github.com/rokt33r)
|
||||
|
||||
## Contributors
|
||||
|
||||
- [Kazu Yokomizo](https://github.com/kazup01)
|
||||
- [dojineko](https://github.com/dojineko)
|
||||
- [Romain Bazile](https://github.com/gromain)
|
||||
- [Bruno Paz](https://github.com/brpaz)
|
||||
- [Fabian Mueller](https://github.com/dotcs)
|
||||
- [Yoshihisa Mochihara](https://github.com/yosmoc)
|
||||
- [Mike Resoli](https://github.com/mikeres0)
|
||||
- [tjado](https://github.com/tejado)
|
||||
- [sota1235](https://github.com/sota1235)
|
||||
|
||||
## Copyright & License
|
||||
|
||||
Copyright (C) 2016 MAISIN&CO.
|
||||
|
||||
[GPL v3](./LICENSE).
|
||||
@@ -17,6 +17,7 @@
|
||||
- [Rokt33r](https://github.com/rokt33r)
|
||||
- [sota1235](https://github.com/sota1235)
|
||||
- [Kohei TAKATA](https://github.com/kohei-takata)
|
||||
- [asmsuechan](https://github.com/asmsuechan)
|
||||
- [Kazu Yokomizo](https://github.com/kazup01)
|
||||
|
||||
## Contributors
|
||||
|
||||
BIN
resources/tray-icon-dark.png
Executable file → Normal file
|
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 498 B |
BIN
resources/tray-icon-dark@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 937 B |
BIN
resources/tray-icon-default.png
Executable file → Normal file
|
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 624 B |
BIN
resources/tray-icon-default@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
resources/tray-icon.png
Executable file → Normal file
|
Before Width: | Height: | Size: 802 B After Width: | Height: | Size: 624 B |
BIN
resources/tray-icon@2x.png
Executable file → Normal file
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.1 KiB |