mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-14 18:26:26 +00:00
Merge branch 'dev'
* dev: 0.4.0-beta.2 tutorial 追加 ModeSelect 行動データ, contact form, default articleに英語文追加, Intro fix Hotkey settingの時Alertで結果を出す Folder nameが長すぎ雨時のlayout崩れ解決 ArticleNavigatorの余計なスペースをなくす Default articleの誤字直し Cmd+Sで保存 debug craetedAt fix Title overflow behaviour 0.4.0-beta.1 Conflicts: package.json
This commit is contained in:
@@ -8,6 +8,7 @@ import FinderList from './FinderList'
|
||||
import FinderDetail from './FinderDetail'
|
||||
import { selectArticle, searchArticle, refreshData } from './actions'
|
||||
import _ from 'lodash'
|
||||
import activityRecord from 'boost/activityRecord'
|
||||
|
||||
import remote from 'remote'
|
||||
var hideFinder = remote.getGlobal('hideFinder')
|
||||
@@ -46,6 +47,7 @@ class FinderMain extends React.Component {
|
||||
if (e.keyCode === 13) {
|
||||
let { activeArticle } = this.props
|
||||
clipboard.writeText(activeArticle.content)
|
||||
activityRecord.emit('FINDER_COPY')
|
||||
hideFinder()
|
||||
e.preventDefault()
|
||||
}
|
||||
@@ -174,6 +176,7 @@ var store = createStore(reducer)
|
||||
|
||||
window.onfocus = e => {
|
||||
store.dispatch(refreshData())
|
||||
activityRecord.emit('FINDER_OPEN')
|
||||
}
|
||||
|
||||
ReactDOM.render((
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { PropTypes} from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { CREATE_MODE, EDIT_MODE, IDLE_MODE, NEW } from 'boost/actions'
|
||||
import { CREATE_MODE, EDIT_MODE, IDLE_MODE, NEW, toggleTutorial } from 'boost/actions'
|
||||
// import UserNavigator from './HomePage/UserNavigator'
|
||||
import ArticleNavigator from './HomePage/ArticleNavigator'
|
||||
import ArticleTopBar from './HomePage/ArticleTopBar'
|
||||
@@ -32,9 +32,15 @@ class HomePage extends React.Component {
|
||||
return
|
||||
}
|
||||
|
||||
let { status } = this.props
|
||||
let { status, dispatch } = this.props
|
||||
let { nav, top, list, detail } = this.refs
|
||||
|
||||
if (status.isTutorialOpen) {
|
||||
dispatch(toggleTutorial())
|
||||
e.preventDefault()
|
||||
return
|
||||
}
|
||||
|
||||
// Search inputがfocusされていたら大体のキー入力は無視される。
|
||||
if (top.isInputFocused() && !e.metaKey) {
|
||||
if (e.keyCode === 13 || e.keyCode === 27) top.escape()
|
||||
@@ -47,7 +53,7 @@ class HomePage extends React.Component {
|
||||
if (e.keyCode === 27) {
|
||||
detail.handleCancelButtonClick()
|
||||
}
|
||||
if (e.keyCode === 13 && e.metaKey) {
|
||||
if ((e.keyCode === 13 && e.metaKey) || (e.keyCode === 83 && e.metaKey)) {
|
||||
detail.handleSaveButtonClick()
|
||||
}
|
||||
break
|
||||
|
||||
@@ -6,19 +6,71 @@ import ModeIcon from 'boost/components/ModeIcon'
|
||||
import MarkdownPreview from 'boost/components/MarkdownPreview'
|
||||
import CodeEditor from 'boost/components/CodeEditor'
|
||||
import { IDLE_MODE, CREATE_MODE, EDIT_MODE, switchMode, switchArticle, switchFolder, clearSearch, updateArticle, destroyArticle, NEW } from 'boost/actions'
|
||||
import aceModes from 'boost/ace-modes'
|
||||
import Select from 'react-select'
|
||||
import linkState from 'boost/linkState'
|
||||
import FolderMark from 'boost/components/FolderMark'
|
||||
import TagLink from 'boost/components/TagLink'
|
||||
import TagSelect from 'boost/components/TagSelect'
|
||||
import ModeSelect from 'boost/components/ModeSelect'
|
||||
import activityRecord from 'boost/activityRecord'
|
||||
|
||||
var modeOptions = aceModes.map(function (mode) {
|
||||
return {
|
||||
label: mode,
|
||||
value: mode
|
||||
}
|
||||
})
|
||||
const BRAND_COLOR = '#18AF90'
|
||||
|
||||
const editDeleteTutorialElement = (
|
||||
<svg width='300' height='500' className='tutorial'>
|
||||
<text x='50' y='220' fill={BRAND_COLOR} fontSize='24'>Edit / Delete a post</text>
|
||||
<text x='90' y='245' fill={BRAND_COLOR} fontSize='18'>press `e`/`d`</text>
|
||||
|
||||
<svg x='150' y='35'>
|
||||
<path fill='white' d='M87.5,93.6c-16.3-5.7-30.6-16.7-39.9-31.4c-5.5-8.7-9-19.1-3.4-28.7c4.8-8.2,13.6-12.8,22.4-15.3
|
||||
c15.7-4.5,34.4-6.2,49.7,0.4c17.3,7.4,25.6,26.3,25.7,44.4c0.1,10.4-3.4,20.9-13.1,26c-8.6,4.5-19,4.1-28.4,3.7
|
||||
c-1.9-0.1-1.9,2.9,0,3c9.3,0.4,19.2,0.6,27.9-3.2c8.5-3.7,13.8-11.2,15.7-20.2c3.6-17.9-2.9-40.2-17.7-51.4
|
||||
C110.8,9.1,89,9.9,70.8,14c-17.9,4-37.4,16.8-31.3,37.9C45.6,73,66.7,89.5,86.7,96.5C88.6,97.1,89.4,94.2,87.5,93.6L87.5,93.6z'/>
|
||||
<path fill='white' d='M11.9,89.7c14.8-3.4,29.7-6,44.8-7.9c-0.5-0.6-1-1.3-1.4-1.9c-2.6,6.3-2.8,12.7-0.7,19.2
|
||||
c0.6,1.8,3.5,1,2.9-0.8c-1.9-6-1.7-11.8,0.7-17.6c0.3-0.8-0.5-2-1.4-1.9c-15.3,1.9-30.6,4.5-45.6,8C9.3,87.3,10.1,90.2,11.9,89.7
|
||||
L11.9,89.7z'/>
|
||||
<path fill='white' d='M48.6,81.5c-9.4,10.4-17,22.3-22.2,35.3c-5.5,13.6-9.3,28.9-6,43.4c0.4,1.9,3.3,1.1,2.9-0.8
|
||||
c-3.2-14,0.7-28.8,6-41.8c5.1-12.5,12.4-24,21.5-34C52,82.2,49.9,80,48.6,81.5L48.6,81.5z'/>
|
||||
</svg>
|
||||
</svg>
|
||||
)
|
||||
|
||||
const tagSelectTutorialElement = (
|
||||
<svg width='500' height='500' className='tutorial'>
|
||||
<text x='155' y='50' fill={BRAND_COLOR} fontSize='24'>Attach some tags here!</text>
|
||||
|
||||
<svg x='0' y='-15'>
|
||||
<path fill='white' d='M15.5,22.2c77.8-0.7,155.6-1.3,233.5-2c22.2-0.2,44.4-0.4,66.6-0.6c1.9,0,1.9-3,0-3
|
||||
c-77.8,0.7-155.6,1.3-233.5,2c-22.2,0.2-44.4,0.4-66.6,0.6C13.6,19.2,13.6,22.2,15.5,22.2L15.5,22.2z'/>
|
||||
<path fill='white' d='M130.8,25c-5.4,6.8-10.3,14-14.6,21.5c-0.8,1.4,1.2,3.2,2.4,1.8c1-1.2,2-2.4,3.1-3.7c1.2-1.5-0.9-3.6-2.1-2.1
|
||||
c-1,1.2-2,2.4-3.1,3.7c0.8,0.6,1.6,1.2,2.4,1.8c4.2-7.3,8.9-14.3,14.2-20.9C134.1,25.6,132,23.4,130.8,25L130.8,25z'/>
|
||||
<path fill='white' d='M132.6,22.1c8.4,5.9,16.8,11.9,25.2,17.8c1.6,1.1,3.1-1.5,1.5-2.6c-8.4-5.9-16.8-11.9-25.2-17.8
|
||||
C132.5,18.4,131,21,132.6,22.1L132.6,22.1z'/>
|
||||
<path fill='white' d='M132.9,18.6c0.4,6.7-0.7,13.3-3.5,19.3c-1.5,3.1-3.9,6.4-3.1,10c0.7,3.1,3.4,4.4,6.2,5.5
|
||||
c5.1,2.1,10.5,3.1,16.1,3.2c1.9,0,1.9-3,0-3c-4.7-0.1-9.2-0.8-13.6-2.4c-3-1.1-6.2-1.9-5.4-6.6c0.4-2,2-4.1,2.8-5.9
|
||||
c2.9-6.3,4-13.1,3.6-20.1C135.8,16.7,132.8,16.7,132.9,18.6L132.9,18.6z'/>
|
||||
</svg>
|
||||
</svg>
|
||||
)
|
||||
|
||||
const modeSelectTutorialElement = (
|
||||
<svg width='500' height='500' className='tutorial'>
|
||||
<text x='195' y='130' fill={BRAND_COLOR} fontSize='24'>Select code syntax!!</text>
|
||||
|
||||
<svg x='300' y='0'>
|
||||
<path fill='white' d='M99.9,58.8c-14.5-0.5-29-2.2-43.1-5.6c-12.3-2.9-27.9-6.4-37.1-15.5C7.9,26,28.2,18.9,37,16.7
|
||||
c13.8-3.5,28.3-4.7,42.4-5.8c29.6-2.2,59.3-1.7,89-1c3,0.1,7.5-0.6,10.2,0.6c3.1,1.4,3.1,5.3,3.3,8.1c0.3,5.2-0.2,10.7-2.4,15.4
|
||||
c-4.4,9.6-18.4,14.7-27.5,18.1c-27.1,10.1-56.7,12.8-85.3,15.6c-1.9,0.2-1.9,3.2,0,3c29.3-2.9,59.8-5.6,87.5-16.2
|
||||
c9.6-3.7,22.8-8.7,27.7-18.4c2.3-4.6,3.2-9.9,3.2-15c0-3.6,0-9.4-2.9-12c-1.9-1.7-4.7-1.8-7.1-2c-4.8-0.2-9.6-0.2-14.4-0.3
|
||||
c-8.7-0.2-17.5-0.3-26.2-0.4C116.7,6.3,99,6.5,81.3,7.8c-15.8,1.1-32.1,2.3-47.4,6.6c-7.7,2.2-22.1,6.9-20.9,17.4
|
||||
c0.6,5.4,5.6,9.4,9.9,12.1c6.7,4.3,14.4,6.9,22,9.2c17.8,5.4,36.4,8,54.9,8.6C101.8,61.8,101.8,58.8,99.9,58.8L99.9,58.8z'/>
|
||||
<path fill='white' d='M11.1,67.8c9.2-6.1,18.6-11.9,28.2-17.2c-0.7-0.3-1.5-0.6-2.2-0.9c0.9,5.3,0.7,10.3-0.5,15.5
|
||||
c-0.4,1.9,2.4,2.7,2.9,0.8c1.4-5.7,1.5-11.3,0.5-17.1c-0.2-1-1.4-1.3-2.2-0.9c-9.7,5.3-19.1,11.1-28.2,17.2
|
||||
C8,66.3,9.5,68.9,11.1,67.8L11.1,67.8z'/>
|
||||
<path fill='white' d='M31.5,52.8C23.4,68.9,0.2,83.2,7.9,104c0.7,1.8,3.6,1,2.9-0.8C3.6,83.7,26.4,69.7,34.1,54.3
|
||||
C35,52.6,32.4,51.1,31.5,52.8L31.5,52.8z'/>
|
||||
</svg>
|
||||
</svg>
|
||||
)
|
||||
|
||||
function makeInstantArticle (article) {
|
||||
return Object.assign({}, article)
|
||||
@@ -93,6 +145,7 @@ export default class ArticleDetail extends React.Component {
|
||||
let { dispatch, activeArticle } = this.props
|
||||
|
||||
dispatch(destroyArticle(activeArticle.key))
|
||||
activityRecord.emit('ARTICLE_DESTROY')
|
||||
this.setState({openDeleteConfirmMenu: false})
|
||||
}
|
||||
|
||||
@@ -101,7 +154,7 @@ export default class ArticleDetail extends React.Component {
|
||||
}
|
||||
|
||||
renderIdle () {
|
||||
let { activeArticle, folders } = this.props
|
||||
let { status, activeArticle, folders } = this.props
|
||||
|
||||
let tags = activeArticle.tags != null ? activeArticle.tags.length > 0
|
||||
? activeArticle.tags.map(tag => {
|
||||
@@ -132,7 +185,7 @@ export default class ArticleDetail extends React.Component {
|
||||
<div className='detailInfo'>
|
||||
<div className='left'>
|
||||
<div className='info'>
|
||||
<FolderMark color={folder.color}/> {folder.name}
|
||||
<FolderMark color={folder.color}/> <span className='folderName'>{folder.name}</span>
|
||||
Created : {moment(activeArticle.createdAt).format('YYYY/MM/DD')}
|
||||
Updated : {moment(activeArticle.updatedAt).format('YYYY/MM/DD')}
|
||||
</div>
|
||||
@@ -146,6 +199,9 @@ export default class ArticleDetail extends React.Component {
|
||||
<i className='fa fa-fw fa-trash'/><span className='tooltip'>Delete (d)</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{status.isTutorialOpen ? editDeleteTutorialElement : null}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -182,6 +238,12 @@ export default class ArticleDetail extends React.Component {
|
||||
|
||||
delete newArticle.status
|
||||
newArticle.updatedAt = new Date()
|
||||
if (newArticle.createdAt == null) {
|
||||
newArticle.createdAt = new Date()
|
||||
activityRecord.emit('ARTICLE_CREATE')
|
||||
} else {
|
||||
activityRecord.emit('ARTICLE_UPDATE')
|
||||
}
|
||||
|
||||
dispatch(updateArticle(newArticle))
|
||||
dispatch(switchMode(IDLE_MODE))
|
||||
@@ -211,7 +273,16 @@ export default class ArticleDetail extends React.Component {
|
||||
handleModeChange (value) {
|
||||
let article = this.state.article
|
||||
article.mode = value
|
||||
this.setState({article: article})
|
||||
this.setState({
|
||||
article: article,
|
||||
previewMode: false
|
||||
})
|
||||
}
|
||||
|
||||
handleModeSelectBlur () {
|
||||
if (this.refs.code != null) {
|
||||
this.refs.code.editor.focus()
|
||||
}
|
||||
}
|
||||
|
||||
handleContentChange (e, value) {
|
||||
@@ -224,8 +295,15 @@ export default class ArticleDetail extends React.Component {
|
||||
this.setState({previewMode: !this.state.previewMode})
|
||||
}
|
||||
|
||||
handleTitleKeyDown (e) {
|
||||
if (e.keyCode === 9 && !e.shiftKey) {
|
||||
e.preventDefault()
|
||||
this.refs.mode.handleIdleSelectClick()
|
||||
}
|
||||
}
|
||||
|
||||
renderEdit () {
|
||||
let { folders } = this.props
|
||||
let { folders, status } = this.props
|
||||
|
||||
let folderOptions = folders.map(folder => {
|
||||
return (
|
||||
@@ -249,7 +327,11 @@ export default class ArticleDetail extends React.Component {
|
||||
tags={this.state.article.tags}
|
||||
onChange={(tags, tag) => this.handleTagsChange(tags, tag)}
|
||||
/>
|
||||
|
||||
{status.isTutorialOpen ? tagSelectTutorialElement : null}
|
||||
|
||||
</div>
|
||||
|
||||
<div className='right'>
|
||||
{
|
||||
this.state.article.mode === 'markdown'
|
||||
@@ -264,22 +346,23 @@ export default class ArticleDetail extends React.Component {
|
||||
<div className='detailPanel'>
|
||||
<div className='header'>
|
||||
<div className='title'>
|
||||
<input placeholder='Title' ref='title' valueLink={this.linkState('article.title')}/>
|
||||
<input onKeyDown={e => this.handleTitleKeyDown(e)} placeholder='Title' ref='title' valueLink={this.linkState('article.title')}/>
|
||||
</div>
|
||||
<Select
|
||||
<ModeSelect
|
||||
ref='mode'
|
||||
onChange={value => this.handleModeChange(value)}
|
||||
clearable={false}
|
||||
options={modeOptions}
|
||||
placeholder='select mode...'
|
||||
onChange={e => this.handleModeChange(e)}
|
||||
value={this.state.article.mode}
|
||||
className='mode'
|
||||
onBlur={() => this.handleModeSelectBlur()}
|
||||
/>
|
||||
|
||||
{status.isTutorialOpen ? modeSelectTutorialElement : null}
|
||||
</div>
|
||||
|
||||
{this.state.previewMode
|
||||
? <MarkdownPreview content={this.state.article.content}/>
|
||||
: (<CodeEditor
|
||||
ref='code'
|
||||
onChange={(e, value) => this.handleContentChange(e, value)}
|
||||
readOnly={false}
|
||||
mode={this.state.article.mode}
|
||||
|
||||
@@ -85,7 +85,7 @@ export default class ArticleList extends React.Component {
|
||||
<div onClick={e => this.handleArticleClick(article)(e)} className={'articleItem' + (activeArticle.key === article.key ? ' active' : '')}>
|
||||
<div className='top'>
|
||||
{folder != null
|
||||
? <span><FolderMark color={folder.color}/>{folder.name}</span>
|
||||
? <span className='folderName'><FolderMark color={folder.color}/>{folder.name}</span>
|
||||
: <span><FolderMark color={-1}/>Unknown</span>
|
||||
}
|
||||
<span className='updatedAt'>{article.status != null ? article.status : moment(article.updatedAt).fromNow()}</span>
|
||||
|
||||
@@ -9,6 +9,56 @@ import CreateNewFolder from 'boost/components/modal/CreateNewFolder'
|
||||
import remote from 'remote'
|
||||
let userName = remote.getGlobal('process').env.USER
|
||||
|
||||
const BRAND_COLOR = '#18AF90'
|
||||
|
||||
const preferenceTutorialElement = (
|
||||
<svg width='300' height='300' className='tutorial'>
|
||||
<text x='15' y='30' fill={BRAND_COLOR} fontSize='24'>Preference</text>
|
||||
<svg x='-30' y='-270' width='400' height='400'>
|
||||
<path fill='white' d='M165.9,297c5.3,0,10.6,0.1,15.8,0.1c3.3,0,7.7,0.8,10.7-1c2.3-1.4,3.1-4,4.5-6.2c3.5-5.5,9.6-5.2,14.6-1.9
|
||||
c4.6,3.1,8.7,8,8.4,13.8c-0.3,5.2-3.3,10.1-6.1,14.3c-3.1,4.7-6.6,7-12.2,7.9c-5.2,0.8-11.7,1.6-15.4-3
|
||||
c-6.6-8.2,2.1-20.5,7.4-27.1c6.5-8.1,20.1-14,26.4-2.1c5.4,10.3-3.1,21.7-13,24.8c-5.7,1.8-11,0.9-16.2-1.9c-2-1.1-5-2.6-6.6-4.4
|
||||
c-3.9-4.3-0.3-8.2,2.5-11.2c1.3-1.4-0.8-3.6-2.1-2.1c-2.7,2.9-5.8,6.6-5.1,10.9c0.7,4.4,5.6,6.9,9,8.9c8.6,5.1,18.7,4.8,26.8-1.2
|
||||
c7.3-5.4,11.6-15,8-23.7c-3.3-8.1-11.7-11.8-20-9c-12.5,4.1-33.7,33.5-15.9,43.1c6.8,3.7,19.8,1.8,25.3-3.6
|
||||
c6.1-5.8,12.1-17.2,9.5-25.7c-2.6-8.4-13.7-17-22.6-13.3c-1.6,0.7-3,1.7-4.1,3c-1.6,1.9-2.2,5.1-4.1,6.6c-3.1,2.4-10.1,1-13.7,1
|
||||
c-4,0-7.9,0-11.9-0.1C164,294,164,297,165.9,297L165.9,297z'/>
|
||||
</svg>
|
||||
</svg>
|
||||
)
|
||||
|
||||
const newPostTutorialElement = (
|
||||
<svg width='900' height='900' className='tutorial'>
|
||||
<text x='290' y='155' fill={BRAND_COLOR} fontSize='24'>Create a new post!!</text>
|
||||
<text x='300' y='180' fill={BRAND_COLOR} fontSize='16'>press `⌘ + Enter` or `a`</text>
|
||||
<svg x='130' y='-20' width='400' height='400'>
|
||||
<path fill='white' d='M56.2,132.5c11.7-2.9,23.9-6,36.1-4.1c8.7,1.4,16.6,5.5,23.7,10.5c13.3,9.4,24.5,21.5,40.2,27
|
||||
c1.8,0.6,2.6-2.3,0.8-2.9c-17.1-6-28.9-20.3-44-29.7c-7-4.4-14.8-7.4-23-8.2c-11.7-1.1-23.3,1.7-34.5,4.5
|
||||
C53.6,130.1,54.4,133,56.2,132.5L56.2,132.5 z'/>
|
||||
</svg>
|
||||
<svg x='130' y='-120' width='400' height='400'>
|
||||
<path fill='white' d='M82.6,218c-7.7,4.5-15.3,9.3-22.7,14.3c-1,0.7-0.9,2.4,0.4,2.7c6.2,1.8,11.5,4.8,16.2,9.2
|
||||
c1.4,1.3,3.5-0.8,2.1-2.1c-5.1-4.8-10.9-8.1-17.6-10c0.1,0.9,0.2,1.8,0.4,2.7c7.4-5,15-9.8,22.7-14.3
|
||||
C85.7,219.7,84.2,217.1,82.6,218L82.6,218z'/>
|
||||
</svg>
|
||||
</svg>
|
||||
)
|
||||
|
||||
const newFolderTutorialElement = (
|
||||
<svg width='800' height='500' className='tutorial'>
|
||||
<text x='145' y='110' fill={BRAND_COLOR} fontSize='24'>Create a new folder!!</text>
|
||||
<svg x='115' y='-10' width='300' height='400'>
|
||||
<path fill='white' d='M36.6,3.7C28.8,8.2,21.3,13,13.9,18c-1,0.7-0.9,2.4,0.4,2.7c6.2,1.8,11.5,4.8,16.2,9.2
|
||||
c1.4,1.3,3.5-0.8,2.1-2.1c-5.1-4.8-10.9-8.1-17.6-10c0.1,0.9,0.2,1.8,0.4,2.7c7.4-5,15-9.8,22.7-14.3C39.7,5.3,38.2,2.7,36.6,3.7
|
||||
L36.6,3.7z'/>
|
||||
<path fill='white' d='M16.8,21.5c13.3-6.9,29.5-7,42.6,0.6c5.6,3.2,10.4,7.7,14.1,13c3.8,5.4,10.3,16.2,2.2,20.6
|
||||
c-1.2,0.7-2.5,1.2-3.9,1.6c-1.1,0.4-2.3,0.5-3.4,0.5c-1.3-1.4-2.6-2.8-3.9-4.2c-0.2-4.6,7.5-6,10.5-5.8
|
||||
c7.4,0.7,13.7,6.2,18.4,11.6c9.4,10.7,14.7,24.3,15.6,38.5c0.1,1.9,3.1,1.9,3,0c-0.9-15.5-6.9-30.4-17.5-41.8
|
||||
c-6.8-7.3-25.8-19.1-32.3-4.8c-1.9,4.1,0.3,8.5,4.8,9.4c4.6,0.8,11.6-1.8,14.3-5.7c3.6-5.3-0.1-12.8-2.8-17.6
|
||||
c-3.4-6.1-8.2-11.3-13.8-15.4C50.2,11.6,31,10.9,15.3,19C13.6,19.8,15.1,22.4,16.8,21.5L16.8,21.5z'/>
|
||||
</svg>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default class ArticleNavigator extends React.Component {
|
||||
handlePreferencesButtonClick (e) {
|
||||
openModal(Preferences)
|
||||
@@ -56,11 +106,14 @@ export default class ArticleNavigator extends React.Component {
|
||||
<div className='ArticleNavigator'>
|
||||
<div className='userInfo'>
|
||||
<div className='userProfileName'>{userName}</div>
|
||||
<div className='userName'>local</div>
|
||||
<div className='userName'>localStorage</div>
|
||||
<button onClick={e => this.handlePreferencesButtonClick(e)} className='settingBtn'>
|
||||
<i className='fa fa-fw fa-chevron-down'/>
|
||||
<span className='tooltip'>Preferences</span>
|
||||
</button>
|
||||
|
||||
{status.isTutorialOpen ? preferenceTutorialElement : null}
|
||||
|
||||
</div>
|
||||
|
||||
<div className='controlSection'>
|
||||
@@ -68,6 +121,9 @@ export default class ArticleNavigator extends React.Component {
|
||||
New Post
|
||||
<span className='tooltip'>Create a new Post (⌘ + Enter or a)</span>
|
||||
</button>
|
||||
|
||||
{status.isTutorialOpen ? newPostTutorialElement : null}
|
||||
|
||||
</div>
|
||||
|
||||
<div className='folders'>
|
||||
@@ -77,6 +133,9 @@ export default class ArticleNavigator extends React.Component {
|
||||
<i className='fa fa-fw fa-plus'/>
|
||||
<span className='tooltip'>Create a new folder</span>
|
||||
</button>
|
||||
|
||||
{status.isTutorialOpen ? newFolderTutorialElement : null}
|
||||
|
||||
</div>
|
||||
<div className='folderList'>
|
||||
<button onClick={e => this.handleAllFoldersButtonClick(e)} className={targetFolders.length === 0 ? 'active' : ''}>All folders</button>
|
||||
|
||||
@@ -1,9 +1,32 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import ExternalLink from 'boost/components/ExternalLink'
|
||||
import { setSearchFilter, clearSearch } from 'boost/actions'
|
||||
import { openModal } from 'boost/modal'
|
||||
import Tutorial from 'boost/components/modal/Tutorial'
|
||||
import { setSearchFilter, clearSearch, toggleTutorial } from 'boost/actions'
|
||||
|
||||
const BRAND_COLOR = '#18AF90'
|
||||
|
||||
const searchTutorialElement = (
|
||||
<svg width='750' height='120' className='tutorial'>
|
||||
<text x='450' y='33' fill={BRAND_COLOR} fontSize='24'>Search some posts!!</text>
|
||||
<text x='450' y='60' fill={BRAND_COLOR} fontSize='18'>{'- Search by tag : #{string}'}</text>
|
||||
<text x='450' y='85' fill={BRAND_COLOR} fontSize='18'>
|
||||
{'- Search by folder : in:{folder_name}\n'}</text>
|
||||
|
||||
<svg width='500' height='300'>
|
||||
<path fill='white' d='M54.5,51.5c-12.4,3.3-27.3-1.4-38.4-7C11.2,42,5,38.1,5.6,31.8c0.7-6.9,8.1-11.2,13.8-13.7
|
||||
c12.3-5.4,26.4-6.8,39.7-7.7C72.4,9.6,85.7,9.7,99,9.8c55.2,0.3,110.4,2.2,165.5-1.5C291,6.5,317.7,3.8,344.1,7
|
||||
c12.8,1.6,25.8,4.4,37.5,10c1.2,0.6,2.4,1.1,3.5,1.8c2.4,1.4,3.2,1.5,3.3,4.5c0.1,3.6-2.3,5.9-4.8,8.3c-3.9,3.8-8.6,6.8-13.5,9.2
|
||||
c-12.6,6-26.5,7.2-40.3,7.7c-13.7,0.5-27.5,0.6-41.2,1.1c-27.7,0.9-55.3,2.2-82.9,4c-30.8,2-61.6,4.5-92.3,7.6
|
||||
c-15.4,1.5-30.8,3.7-46.3,4.9c-13.6,1.1-30.7,1.5-41.8-7.8c-1.5-1.2-3.6,0.9-2.1,2.1c8.9,7.5,21.4,9.2,32.7,9.2
|
||||
c15.3,0,30.6-2.6,45.8-4.2c31.3-3.3,62.7-6,94.2-8.1c30.9-2.1,61.8-3.7,92.8-4.7c15.7-0.5,31.4-0.5,47-1.3
|
||||
c13.1-0.7,26.3-2.7,38.1-8.9c4.4-2.3,8.5-5.1,12-8.6c2.8-2.8,7.3-7.3,6.4-11.7c-0.8-4.3-6.4-6.3-9.8-7.9
|
||||
c-5.6-2.6-11.4-4.6-17.3-6.2c-28.3-7.5-58.1-5.6-87-3.6c-62.3,4.4-124.5,2.6-187,2.4c-16.4,0-32.8,0-49,2.4
|
||||
C29.9,11,13.4,13.8,5.5,24.6c-7.3,10,0.7,18.4,9.8,22.9c11.9,5.8,26.9,10.4,40,7C57.2,53.9,56.4,51,54.5,51.5L54.5,51.5z'/>
|
||||
<path fill='white' d='M446.5,21.4c-9.1-1.6-18.1-3.5-27.4-3.5c-10.2,0-20.4,1.4-30.5,2.8c-1.9,0.3-1.9,3.3,0,3
|
||||
c9.5-1.3,19.1-2.6,28.8-2.7c9.6-0.2,18.9,1.7,28.3,3.4C447.6,24.7,448.4,21.8,446.5,21.4L446.5,21.4z'/>
|
||||
</svg>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default class ArticleTopBar extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -66,10 +89,13 @@ export default class ArticleTopBar extends React.Component {
|
||||
}
|
||||
|
||||
handleTutorialButtonClick (e) {
|
||||
openModal(Tutorial)
|
||||
let { dispatch } = this.props
|
||||
|
||||
dispatch(toggleTutorial())
|
||||
}
|
||||
|
||||
render () {
|
||||
let { status } = this.props
|
||||
return (
|
||||
<div className='ArticleTopBar'>
|
||||
<div className='left'>
|
||||
@@ -94,14 +120,34 @@ export default class ArticleTopBar extends React.Component {
|
||||
- Search by folder : in:{'{folder_name}'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{status.isTutorialOpen ? searchTutorialElement : null}
|
||||
|
||||
</div>
|
||||
<div className='right'>
|
||||
<button onClick={e => this.handleTutorialButtonClick(e)}>?<span className='tooltip'>How to use</span></button>
|
||||
<button onClick={e => this.handleTutorialButtonClick(e)}>?<span className='tooltip'>How to use</span>
|
||||
</button>
|
||||
<ExternalLink className='logo' href='http://b00st.io'>
|
||||
<img src='../../resources/favicon-230x230.png' width='44' height='44'/>
|
||||
<span className='tooltip'>Boost official page</span>
|
||||
</ExternalLink>
|
||||
</div>
|
||||
|
||||
{status.isTutorialOpen ? (
|
||||
<div className='tutorial'>
|
||||
<div onClick={e => this.handleTutorialButtonClick(e)} className='clickJammer'/>
|
||||
<svg width='500' height='250' className='finder'>
|
||||
<text x='100' y='25' fontSize='32' fill={BRAND_COLOR}>Also, you can open Finder!!</text>
|
||||
<text x='120' y='55' fontSize='18' fill={BRAND_COLOR}>with pressing `Control` + `shift` + `tab`</text>
|
||||
</svg>
|
||||
<svg width='450' className='global'>
|
||||
<text x='100' y='45' fontSize='24' fill={BRAND_COLOR}>Hope you to enjoy our app :D</text>
|
||||
<text x='50' y='75' fontSize='18' fill={BRAND_COLOR}>Press any key or click to escape tutorial mode</text>
|
||||
</svg>
|
||||
<div className='back'></div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ import ReactDOM from 'react-dom'
|
||||
require('../styles/main/index.styl')
|
||||
import { openModal } from 'boost/modal'
|
||||
import Tutorial from 'boost/components/modal/Tutorial'
|
||||
import activityRecord from 'boost/activityRecord'
|
||||
|
||||
activityRecord.init()
|
||||
|
||||
let routes = (
|
||||
<Route path='/' component={MainPage}>
|
||||
|
||||
@@ -44,6 +44,11 @@ iptFocusBorderColor = #369DCD
|
||||
.left
|
||||
absolute top left bottom
|
||||
right 120px
|
||||
.folderName
|
||||
display inline-block
|
||||
max-width 100px
|
||||
overflow ellipsis
|
||||
height 10px
|
||||
.right
|
||||
absolute top right
|
||||
.detailBody
|
||||
@@ -80,6 +85,10 @@ iptFocusBorderColor = #369DCD
|
||||
&.edit
|
||||
.detailInfo
|
||||
.left
|
||||
&>.tutorial
|
||||
position fixed
|
||||
z-index 35
|
||||
font-style italic
|
||||
.folder
|
||||
border none
|
||||
width 150px
|
||||
@@ -94,6 +103,8 @@ iptFocusBorderColor = #369DCD
|
||||
position relative
|
||||
margin-top 5px
|
||||
noSelect()
|
||||
z-index 30
|
||||
background-color #E6E6E6
|
||||
.tagItem
|
||||
background-color brandColor
|
||||
border-radius 2px
|
||||
@@ -150,16 +161,73 @@ iptFocusBorderColor = #369DCD
|
||||
.detailBody
|
||||
.detailPanel
|
||||
&>.header
|
||||
&>.tutorial
|
||||
fixed right
|
||||
z-index 35
|
||||
font-style italic
|
||||
.mode
|
||||
position relative
|
||||
z-index 30
|
||||
absolute top bottom right
|
||||
display block
|
||||
height 33px
|
||||
margin-top 12px
|
||||
width 120px
|
||||
width 150px
|
||||
margin-right 15px
|
||||
border-radius 5px
|
||||
border solid 1px borderColor
|
||||
transition 0.1s
|
||||
&.idle
|
||||
background-color darken(white, 5%)
|
||||
cursor pointer
|
||||
&:hover
|
||||
background-color white
|
||||
.ModeIcon
|
||||
float left
|
||||
width 25px
|
||||
line-height 33px
|
||||
text-align center
|
||||
.modeLabel
|
||||
line-height 30px
|
||||
&.edit
|
||||
background-color white
|
||||
input
|
||||
width 150px
|
||||
line-height 30px
|
||||
padding 0 10px
|
||||
border none
|
||||
outline none
|
||||
background-color transparent
|
||||
font-size 14px
|
||||
.modeOptions
|
||||
position fixed
|
||||
width 150px
|
||||
z-index 10
|
||||
margin-top 5px
|
||||
border 1px solid borderColor
|
||||
border-radius 5px
|
||||
background-color white
|
||||
max-height 250px
|
||||
overflow-y auto
|
||||
.option
|
||||
height 33px
|
||||
line-height 33px
|
||||
cursor pointer
|
||||
&.active, &:hover.active
|
||||
background-color brandColor
|
||||
color white
|
||||
.ModeIcon
|
||||
width 30px
|
||||
text-align center
|
||||
display inline-block
|
||||
&:hover
|
||||
background-color darken(white, 10%)
|
||||
|
||||
|
||||
|
||||
.title
|
||||
absolute left top bottom
|
||||
right 120px
|
||||
right 150px
|
||||
padding 0 15px
|
||||
input
|
||||
width 100%
|
||||
@@ -170,6 +238,10 @@ iptFocusBorderColor = #369DCD
|
||||
outline none
|
||||
&.idle
|
||||
.detailInfo
|
||||
&>.tutorial
|
||||
fixed top right
|
||||
z-index 35
|
||||
font-style italic
|
||||
.left
|
||||
right 99px
|
||||
.info
|
||||
@@ -192,14 +264,17 @@ iptFocusBorderColor = #369DCD
|
||||
span.noTags
|
||||
color noTagsColor
|
||||
.right
|
||||
z-index 30
|
||||
button
|
||||
border-radius 16.5px
|
||||
cursor pointer
|
||||
height 33px
|
||||
width 33px
|
||||
border none
|
||||
margin-right 5px
|
||||
font-size 18px
|
||||
color inactiveTextColor
|
||||
background-color transparent
|
||||
background-color darken(white, 5%)
|
||||
padding 0
|
||||
.tooltip
|
||||
tooltip()
|
||||
@@ -210,7 +285,7 @@ iptFocusBorderColor = #369DCD
|
||||
margin-top 25px
|
||||
margin-left -73px
|
||||
&:hover
|
||||
color inherit
|
||||
color textColor
|
||||
.tooltip
|
||||
opacity 1
|
||||
.detailBody
|
||||
|
||||
@@ -26,23 +26,28 @@ articleItemColor = #777
|
||||
line-height 20px
|
||||
padding 5px 0
|
||||
color articleItemColor
|
||||
.profileImage
|
||||
vertical-align middle
|
||||
.folderName
|
||||
overflow ellipsis
|
||||
display inline-block
|
||||
width 120px
|
||||
.updatedAt
|
||||
float right
|
||||
line-height 20px
|
||||
.middle
|
||||
clearfix()
|
||||
padding 3px 0 7px
|
||||
font-size 16px
|
||||
position relative
|
||||
height 26px
|
||||
.mode
|
||||
float left
|
||||
position absolute
|
||||
left 0
|
||||
font-size 12px
|
||||
line-height 16px
|
||||
.title
|
||||
float left
|
||||
position absolute
|
||||
left 19px
|
||||
right 0
|
||||
overflow ellipsis
|
||||
padding 0 5px
|
||||
.bottom
|
||||
padding 5px 0
|
||||
overflow-x auto
|
||||
|
||||
@@ -21,6 +21,16 @@ articleNavBgColor = #353535
|
||||
color white
|
||||
padding-left 20px
|
||||
margin-top 3px
|
||||
.tutorial
|
||||
position fixed
|
||||
z-index 35
|
||||
top 0
|
||||
left 0
|
||||
pointer-event none
|
||||
font-style italic
|
||||
transition 0.1s
|
||||
&.hide
|
||||
opacity 0
|
||||
.settingBtn
|
||||
width 22px
|
||||
height 22px
|
||||
@@ -33,6 +43,7 @@ articleNavBgColor = #353535
|
||||
padding 0
|
||||
background-color transparent
|
||||
border 1px solid white
|
||||
z-index 31
|
||||
.tooltip
|
||||
tooltip()
|
||||
margin-top -5px
|
||||
@@ -47,7 +58,16 @@ articleNavBgColor = #353535
|
||||
height 88px
|
||||
padding 22px 15px
|
||||
margin-bottom 44px
|
||||
.tutorial
|
||||
fixed top left
|
||||
z-index 35
|
||||
pointer-event none
|
||||
font-style italic
|
||||
transition 0.1s
|
||||
&.hide
|
||||
opacity 0
|
||||
.newPostBtn
|
||||
position relative
|
||||
border none
|
||||
background-color brandColor
|
||||
color white
|
||||
@@ -56,6 +76,7 @@ articleNavBgColor = #353535
|
||||
border-radius 5px
|
||||
font-size 20px
|
||||
transition 0.1s
|
||||
z-index 30
|
||||
.tooltip
|
||||
tooltip()
|
||||
margin-left 48px
|
||||
@@ -70,6 +91,8 @@ articleNavBgColor = #353535
|
||||
padding-bottom 5px
|
||||
margin-bottom 10px
|
||||
clearfix()
|
||||
position relative
|
||||
z-index 30
|
||||
.title
|
||||
float left
|
||||
padding-left 10px
|
||||
@@ -100,9 +123,18 @@ articleNavBgColor = #353535
|
||||
background-color brandColor
|
||||
border-color brandColor
|
||||
.folders
|
||||
margin-bottom 15px
|
||||
absolute bottom
|
||||
top 200px
|
||||
width 100%
|
||||
.header
|
||||
.tutorial
|
||||
position fixed
|
||||
z-index 35px
|
||||
top 200px
|
||||
font-style italic
|
||||
.folderList
|
||||
height 340px
|
||||
absolute bottom
|
||||
top 38px
|
||||
overflow-y auto
|
||||
.folderList button
|
||||
height 33px
|
||||
|
||||
@@ -15,8 +15,34 @@ infoBtnActiveBgColor = #3A3A3A
|
||||
left 200px
|
||||
height 60px
|
||||
background-color bgColor
|
||||
&>.tutorial
|
||||
.clickJammer
|
||||
fixed top left bottom right
|
||||
z-index 40
|
||||
background transparent
|
||||
.global
|
||||
fixed bottom right
|
||||
height 100px
|
||||
z-index 35
|
||||
font-style italic
|
||||
.finder
|
||||
fixed bottom right
|
||||
height 250px
|
||||
left 50%
|
||||
margin-left -250px
|
||||
z-index 35
|
||||
font-style italic
|
||||
.back
|
||||
fixed top left bottom right
|
||||
z-index 20
|
||||
background-color transparentify(black, 80%)
|
||||
&>.left
|
||||
float left
|
||||
&>.tutorial
|
||||
fixed top
|
||||
left 200px
|
||||
z-index 36
|
||||
font-style italic
|
||||
&>.search
|
||||
position relative
|
||||
float left
|
||||
@@ -28,6 +54,7 @@ infoBtnActiveBgColor = #3A3A3A
|
||||
transition 0.1s
|
||||
font-size 16px
|
||||
border 1px solid transparent
|
||||
z-index 30
|
||||
.tooltip
|
||||
tooltip()
|
||||
margin-left -24px
|
||||
|
||||
@@ -103,6 +103,11 @@ iptFocusBorderColor = #369DCD
|
||||
font-size 14px
|
||||
&:hover
|
||||
background-color lighten(brandColor, 10%)
|
||||
.alert
|
||||
float right
|
||||
width 250px
|
||||
padding 10px 15px
|
||||
margin 0 10px 0
|
||||
.alert
|
||||
color infoTextColor
|
||||
background-color infoBackgroundColor
|
||||
@@ -114,6 +119,70 @@ iptFocusBorderColor = #369DCD
|
||||
&.error
|
||||
color errorTextColor
|
||||
background-color errorBackgroundColor
|
||||
&.ContactTab
|
||||
&.done
|
||||
.message
|
||||
margin-top 75px
|
||||
margin-bottom 15px
|
||||
text-align center
|
||||
font-size 22px
|
||||
.checkIcon
|
||||
margin-bottom 15px
|
||||
font-size 144px
|
||||
color brandColor
|
||||
text-align center
|
||||
.control
|
||||
text-align center
|
||||
button
|
||||
border solid 1px borderColor
|
||||
border-radius 5px
|
||||
background-color white
|
||||
padding 15px 15px
|
||||
font-size 14px
|
||||
&:hover
|
||||
background-color darken(white, 10%)
|
||||
&.form
|
||||
padding 10px
|
||||
.title
|
||||
font-size 18px
|
||||
color brandColor
|
||||
margin-top 10px
|
||||
margin-bottom 10px
|
||||
.description
|
||||
margin-bottom 15px
|
||||
.iptGroup
|
||||
margin-bottom 10px
|
||||
input, textarea
|
||||
border-radius 5px
|
||||
border 1px solid borderColor
|
||||
font-size 14px
|
||||
outline none
|
||||
padding 10px 15px
|
||||
width 100%
|
||||
&:focus
|
||||
border-color iptFocusBorderColor
|
||||
textarea
|
||||
resize vertical
|
||||
min-height 150px
|
||||
.formControl
|
||||
clearfix()
|
||||
.alert
|
||||
float right
|
||||
padding 10px 15px
|
||||
margin 0 5px 0
|
||||
font-size 14px
|
||||
line-height normal
|
||||
button
|
||||
padding 10px 15px
|
||||
background-color brandColor
|
||||
color white
|
||||
font-size 14px
|
||||
border-radius 5px
|
||||
border none
|
||||
float right
|
||||
&:hover
|
||||
background-color lighten(brandColor, 10%)
|
||||
|
||||
&.AppSettingTab
|
||||
.description
|
||||
marked()
|
||||
@@ -374,6 +443,7 @@ iptFocusBorderColor = #369DCD
|
||||
.folderName
|
||||
float left
|
||||
width 175px
|
||||
overflow ellipsis
|
||||
padding-left 15px
|
||||
.folderPublic
|
||||
float left
|
||||
@@ -480,6 +550,7 @@ iptFocusBorderColor = #369DCD
|
||||
height 33px
|
||||
width 250px
|
||||
padding-left 15px
|
||||
overflow ellipsis
|
||||
strong
|
||||
font-size 16px
|
||||
color brandColor
|
||||
|
||||
@@ -109,8 +109,9 @@ slideBgColor4 = #00B493
|
||||
.slide3
|
||||
background-color slideBgColor3
|
||||
.content
|
||||
font-size 18px
|
||||
&>img
|
||||
margin-top 45px
|
||||
margin-top 25px
|
||||
.slide4
|
||||
background-color slideBgColor4
|
||||
.content
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
|
||||
var rootUrl = process.cwd()
|
||||
if (rootUrl === '/') rootUrl = require('remote').require('app').getAppPath()
|
||||
var url = path.resolve(rootUrl, './submodules/ace/src-min')
|
||||
console.log(url)
|
||||
|
||||
module.exports = fs.readdirSync(url)
|
||||
.filter(function (file) {
|
||||
return file.match(/^mode-/)
|
||||
})
|
||||
.map(function (file) {
|
||||
var match = file.match(/^mode-([a-z0-9\_]+).js$/)
|
||||
return match[1]
|
||||
})
|
||||
@@ -11,6 +11,7 @@ export const SWITCH_ARTICLE = 'SWITCH_ARTICLE'
|
||||
export const SET_SEARCH_FILTER = 'SET_SEARCH_FILTER'
|
||||
export const SET_TAG_FILTER = 'SET_TAG_FILTER'
|
||||
export const CLEAR_SEARCH = 'CLEAR_SEARCH'
|
||||
export const TOGGLE_TUTORIAL = 'TOGGLE_TUTORIAL'
|
||||
|
||||
// Status - mode
|
||||
export const IDLE_MODE = 'IDLE_MODE'
|
||||
@@ -96,3 +97,9 @@ export function clearSearch () {
|
||||
type: CLEAR_SEARCH
|
||||
}
|
||||
}
|
||||
|
||||
export function toggleTutorial() {
|
||||
return {
|
||||
type: TOGGLE_TUTORIAL
|
||||
}
|
||||
}
|
||||
|
||||
122
lib/activityRecord.js
Normal file
122
lib/activityRecord.js
Normal file
@@ -0,0 +1,122 @@
|
||||
import _ from 'lodash'
|
||||
import moment from 'moment'
|
||||
import keygen from 'boost/keygen'
|
||||
import dataStore from 'boost/dataStore'
|
||||
import { request, WEB_URL } from 'boost/api'
|
||||
|
||||
function isSameDate (a, b) {
|
||||
a = moment(a).utcOffset(+540).format('YYYYMMDD')
|
||||
b = moment(b).utcOffset(+540).format('YYYYMMDD')
|
||||
|
||||
return a === b
|
||||
}
|
||||
|
||||
export function init () {
|
||||
let records = getAllRecords()
|
||||
if (records == null) {
|
||||
saveAllRecords([])
|
||||
}
|
||||
|
||||
postRecords()
|
||||
if (window != null) {
|
||||
window.addEventListener('online', postRecords)
|
||||
window.setInterval(postRecords, 1000 * 60 * 60 * 24)
|
||||
}
|
||||
}
|
||||
|
||||
export function getClientKey () {
|
||||
let clientKey = localStorage.getItem('clientKey')
|
||||
if (!_.isString(clientKey) || clientKey.length !== 40) {
|
||||
clientKey = keygen()
|
||||
localStorage.setItem('clientKey', clientKey)
|
||||
}
|
||||
|
||||
return clientKey
|
||||
}
|
||||
|
||||
export function getAllRecords () {
|
||||
return JSON.parse(localStorage.getItem('activityRecords'))
|
||||
}
|
||||
|
||||
export function saveAllRecords (records) {
|
||||
localStorage.setItem('activityRecords', JSON.stringify(records))
|
||||
}
|
||||
|
||||
/*
|
||||
Post all records(except today)
|
||||
and remove all posted records
|
||||
*/
|
||||
export function postRecords (data) {
|
||||
let records = getAllRecords()
|
||||
records = records.filter(record => {
|
||||
return !isSameDate(new Date(), record.date)
|
||||
})
|
||||
|
||||
if (records.length === 0) {
|
||||
console.log('No records to post')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('posting...', records)
|
||||
let input = {
|
||||
clientKey: getClientKey(),
|
||||
records
|
||||
}
|
||||
return request.post(WEB_URL + 'apis/activity')
|
||||
.send(input)
|
||||
.then(res => {
|
||||
let records = getAllRecords()
|
||||
let todayRecord = _.find(records, record => {
|
||||
return isSameDate(new Date(), record.date)
|
||||
})
|
||||
if (todayRecord != null) saveAllRecords([todayRecord])
|
||||
else saveAllRecords([])
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
|
||||
export function emit (type, data) {
|
||||
let records = getAllRecords()
|
||||
|
||||
let index = _.findIndex(records, record => {
|
||||
return isSameDate(new Date(), record.date)
|
||||
})
|
||||
|
||||
let todayRecord
|
||||
if (index < 0) {
|
||||
todayRecord = {date: new Date()}
|
||||
records.push(todayRecord)
|
||||
}
|
||||
else todayRecord = records[index]
|
||||
console.log(type)
|
||||
switch (type) {
|
||||
case 'ARTICLE_CREATE':
|
||||
case 'ARTICLE_UPDATE':
|
||||
case 'ARTICLE_DESTROY':
|
||||
case 'FOLDER_CREATE':
|
||||
case 'FOLDER_UPDATE':
|
||||
case 'FOLDER_DESTROY':
|
||||
case 'FINDER_OPEN':
|
||||
case 'FINDER_COPY':
|
||||
todayRecord[type] = todayRecord[type] == null
|
||||
? 1
|
||||
: todayRecord[type] + 1
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
let storeData = dataStore.getData()
|
||||
todayRecord.FOLDER_COUNT = _.isArray(storeData.folders) ? storeData.folders.length : 0
|
||||
todayRecord.ARTICLE_COUNT = _.isArray(storeData.articles) ? storeData.articles.length : 0
|
||||
|
||||
saveAllRecords(records)
|
||||
}
|
||||
|
||||
export default {
|
||||
init,
|
||||
emit,
|
||||
getClientKey,
|
||||
postRecords
|
||||
}
|
||||
10
lib/api.js
10
lib/api.js
@@ -1,9 +1,12 @@
|
||||
import superagent from 'superagent'
|
||||
import superagentPromise from 'superagent-promise'
|
||||
import { API_URL } from '../config'
|
||||
import auth from 'boost/auth'
|
||||
|
||||
const request = superagentPromise(superagent, Promise)
|
||||
export const API_URL = 'http://boost-api4.elasticbeanstalk.com/'
|
||||
export const WEB_URL = 'https://b00st.io/'
|
||||
// export const WEB_URL = 'http://localhost:3333/'
|
||||
|
||||
export const request = superagentPromise(superagent, Promise)
|
||||
|
||||
export function login (input) {
|
||||
return request
|
||||
@@ -163,6 +166,9 @@ export function sendEmail (input) {
|
||||
}
|
||||
|
||||
export default {
|
||||
API_URL,
|
||||
WEB_URL,
|
||||
request,
|
||||
login,
|
||||
signup,
|
||||
updateUserInfo,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import modes from 'boost/vars/modes'
|
||||
import _ from 'lodash'
|
||||
var ace = window.ace
|
||||
|
||||
module.exports = React.createClass({
|
||||
@@ -32,11 +34,12 @@ module.exports = React.createClass({
|
||||
editor.setReadOnly(!!this.props.readOnly)
|
||||
|
||||
var session = editor.getSession()
|
||||
if (this.props.mode != null && this.props.mode.length > 0) {
|
||||
session.setMode('ace/mode/' + this.props.mode)
|
||||
} else {
|
||||
session.setMode('ace/mode/text')
|
||||
}
|
||||
let mode = _.findWhere(modes, {name: this.props.mode})
|
||||
let syntaxMode = mode != null
|
||||
? mode.mode
|
||||
: 'text'
|
||||
session.setMode('ace/mode/' + syntaxMode)
|
||||
|
||||
session.setUseSoftTabs(true)
|
||||
session.setOption('useWorker', false)
|
||||
session.setUseWrapMode(true)
|
||||
@@ -57,11 +60,11 @@ module.exports = React.createClass({
|
||||
}
|
||||
if (prevProps.mode !== this.props.mode) {
|
||||
var session = this.state.editor.getSession()
|
||||
if (this.props.mode != null && this.props.mode.length > 0) {
|
||||
session.setMode('ace/mode/' + this.props.mode)
|
||||
} else {
|
||||
session.setMode('ace/mode/text')
|
||||
}
|
||||
let mode = _.findWhere(modes, {name: this.props.mode})
|
||||
let syntaxMode = mode != null
|
||||
? mode.mode
|
||||
: 'text'
|
||||
session.setMode('ace/mode/' + syntaxMode)
|
||||
}
|
||||
},
|
||||
render: function () {
|
||||
|
||||
@@ -32,8 +32,10 @@ export default class ModeIcon extends React.Component {
|
||||
return 'devicon-sass-original'
|
||||
|
||||
// Compile
|
||||
case 'c_cpp':
|
||||
case 'c':
|
||||
return 'devicon-c-plain'
|
||||
case 'cpp':
|
||||
return 'devicon-cplusplus-plain'
|
||||
case 'csharp':
|
||||
return 'devicon-csharp-plain'
|
||||
case 'objc':
|
||||
@@ -60,7 +62,6 @@ export default class ModeIcon extends React.Component {
|
||||
return 'fa fa-fw fa-terminal'
|
||||
|
||||
case 'text':
|
||||
case 'plain_text':
|
||||
case 'markdown':
|
||||
return 'fa fa-fw fa-file-text-o'
|
||||
}
|
||||
@@ -68,9 +69,9 @@ export default class ModeIcon extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
var className = this.getClassName()
|
||||
let className = `ModeIcon ${this.getClassName()} ${this.props.className}`
|
||||
return (
|
||||
<i className={this.props.className + ' ' + className}/>
|
||||
<i className={className}/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
190
lib/components/ModeSelect.js
Normal file
190
lib/components/ModeSelect.js
Normal file
@@ -0,0 +1,190 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import ModeIcon from 'boost/components/ModeIcon'
|
||||
import modes from 'boost/vars/modes'
|
||||
import _ from 'lodash'
|
||||
|
||||
const IDLE_MODE = 'IDLE_MODE'
|
||||
const EDIT_MODE = 'EDIT_MODE'
|
||||
|
||||
export default class ModeSelect extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
mode: IDLE_MODE,
|
||||
search: '',
|
||||
focusIndex: 0
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount (e) {
|
||||
this.blurHandler = e => {
|
||||
let searchElement = ReactDOM.findDOMNode(this.refs.search)
|
||||
if (this.state.mode === EDIT_MODE && document.activeElement !== searchElement) {
|
||||
this.handleBlur()
|
||||
}
|
||||
}
|
||||
window.addEventListener('click', this.blurHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount (e) {
|
||||
window.removeEventListener('click', this.blurHandler)
|
||||
let searchElement = ReactDOM.findDOMNode(this.refs.search)
|
||||
if (searchElement != null && this.searchKeyDownListener != null) {
|
||||
searchElement.removeEventListener('keydown', this.searchKeyDownListener)
|
||||
}
|
||||
}
|
||||
|
||||
handleIdleSelectClick (e) {
|
||||
this.setState({mode: EDIT_MODE})
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps, prevState) {
|
||||
if (prevState.mode !== this.state.mode && this.state.mode === EDIT_MODE) {
|
||||
let searchElement = ReactDOM.findDOMNode(this.refs.search)
|
||||
searchElement.focus()
|
||||
if (this.searchKeyDownListener == null) {
|
||||
this.searchKeyDownListener = e => this.handleSearchKeyDown
|
||||
}
|
||||
searchElement.addEventListener('keydown', this.searchKeyDownListener)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUpdate (nextProps, nextState) {
|
||||
if (nextProps.mode !== this.state.mode && nextState.mode === IDLE_MODE) {
|
||||
let searchElement = ReactDOM.findDOMNode(this.refs.search)
|
||||
if (searchElement != null && this.searchKeyDownListener != null) {
|
||||
searchElement.removeEventListener('keydown', this.searchKeyDownListener)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleModeOptionClick (modeName) {
|
||||
return e => {
|
||||
this.props.onChange(modeName)
|
||||
this.setState({
|
||||
mode: IDLE_MODE,
|
||||
search: '',
|
||||
focusIndex: 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleSearchKeyDown (e) {
|
||||
switch (e.keyCode) {
|
||||
// up
|
||||
case 38:
|
||||
e.preventDefault()
|
||||
if (this.state.focusIndex > 0) this.setState({focusIndex: this.state.focusIndex - 1})
|
||||
break
|
||||
// down
|
||||
case 40:
|
||||
e.preventDefault()
|
||||
{
|
||||
let filteredModes = modes
|
||||
.filter(mode => {
|
||||
let search = this.state.search
|
||||
let nameMatched = mode.name.match(search)
|
||||
let aliasMatched = _.some(mode.alias, alias => alias.match(search))
|
||||
return nameMatched || aliasMatched
|
||||
})
|
||||
if (filteredModes.length === this.state.focusIndex + 1) this.setState({focusIndex: filteredModes.length - 1})
|
||||
else this.setState({focusIndex: this.state.focusIndex + 1})
|
||||
}
|
||||
break
|
||||
// enter
|
||||
case 13:
|
||||
e.preventDefault()
|
||||
{
|
||||
let filteredModes = modes
|
||||
.filter(mode => {
|
||||
let search = this.state.search
|
||||
let nameMatched = mode.name.match(search)
|
||||
let aliasMatched = _.some(mode.alias, alias => alias.match(search))
|
||||
return nameMatched || aliasMatched
|
||||
})
|
||||
let targetMode = filteredModes[this.state.focusIndex]
|
||||
if (targetMode != null) {
|
||||
this.props.onChange(targetMode.name)
|
||||
this.handleBlur()
|
||||
}
|
||||
}
|
||||
break
|
||||
// esc
|
||||
case 27:
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
this.handleBlur()
|
||||
break
|
||||
case 9:
|
||||
this.handleBlur()
|
||||
}
|
||||
}
|
||||
|
||||
handleSearchChange (e) {
|
||||
this.setState({
|
||||
search: e.target.value,
|
||||
focusIndex: 0
|
||||
})
|
||||
}
|
||||
|
||||
handleBlur () {
|
||||
if (this.state.mode === EDIT_MODE) {
|
||||
this.setState({
|
||||
mode: IDLE_MODE,
|
||||
search: '',
|
||||
focusIndex: 0
|
||||
})
|
||||
}
|
||||
if (this.props.onBlur != null) this.props.onBlur()
|
||||
}
|
||||
|
||||
render () {
|
||||
let className = this.props.className != null
|
||||
? `ModeSelect ${this.props.className}`
|
||||
: this.props.className
|
||||
|
||||
if (this.state.mode === IDLE_MODE) {
|
||||
let mode = _.findWhere(modes, {name: this.props.value})
|
||||
let modeName = mode != null ? mode.name : 'text'
|
||||
let modeLabel = mode != null ? mode.label : 'Plain text'
|
||||
|
||||
return (
|
||||
<div className={className + ' idle'} onClick={e => this.handleIdleSelectClick(e)}>
|
||||
<ModeIcon mode={modeName}/>
|
||||
<span className='modeLabel'>{modeLabel}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
let filteredOptions = modes
|
||||
.filter(mode => {
|
||||
let search = this.state.search
|
||||
let nameMatched = mode.name.match(search)
|
||||
let aliasMatched = _.some(mode.alias, alias => alias.match(search))
|
||||
return nameMatched || aliasMatched
|
||||
})
|
||||
.map((mode, index) => {
|
||||
return (
|
||||
<div key={mode.name} className={index === this.state.focusIndex ? 'option active' : 'option'} onClick={e => this.handleModeOptionClick(mode.name)(e)}><ModeIcon mode={mode.name}/>{mode.label}</div>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={className + ' edit'}>
|
||||
<input onKeyDown={e => this.handleSearchKeyDown(e)} ref='search' onChange={e => this.handleSearchChange(e)} value={this.state.search} type='text'/>
|
||||
<div ref='options' className='modeOptions hide'>
|
||||
{filteredOptions}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ModeSelect.propTypes = {
|
||||
className: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onBlur: PropTypes.func
|
||||
}
|
||||
@@ -9,10 +9,33 @@ export default class AppSettingTab extends React.Component {
|
||||
let keymap = remote.getGlobal('keymap')
|
||||
|
||||
this.state = {
|
||||
toggleFinder: keymap.toggleFinder
|
||||
toggleFinder: keymap.toggleFinder,
|
||||
alert: null
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.handleSettingDone = () => {
|
||||
this.setState({alert: {
|
||||
type: 'success',
|
||||
message: 'Successfully done!'
|
||||
}})
|
||||
}
|
||||
this.handleSettingError = err => {
|
||||
this.setState({alert: {
|
||||
type: 'error',
|
||||
message: err.message
|
||||
}})
|
||||
}
|
||||
ipc.addListener('APP_SETTING_DONE', this.handleSettingDone)
|
||||
ipc.addListener('APP_SETTING_ERROR', this.handleSettingError)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
ipc.removeListener('APP_SETTING_DONE', this.handleSettingDone)
|
||||
ipc.removeListener('APP_SETTING_ERROR', this.handleSettingError)
|
||||
}
|
||||
|
||||
handleSaveButtonClick (e) {
|
||||
ipc.send('hotkeyUpdated', {
|
||||
toggleFinder: this.state.toggleFinder
|
||||
@@ -20,6 +43,13 @@ export default class AppSettingTab extends React.Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
let alert = this.state.alert
|
||||
let alertElement = alert != null ? (
|
||||
<p className={`alert ${alert.type}`}>
|
||||
{alert.message}
|
||||
</p>
|
||||
) : null
|
||||
|
||||
return (
|
||||
<div className='AppSettingTab content'>
|
||||
<div className='section'>
|
||||
@@ -30,6 +60,7 @@ export default class AppSettingTab extends React.Component {
|
||||
</div>
|
||||
<div className='sectionConfirm'>
|
||||
<button onClick={e => this.handleSaveButtonClick(e)}>Save</button>
|
||||
{alertElement}
|
||||
</div>
|
||||
<div className='description'>
|
||||
<ul>
|
||||
|
||||
123
lib/components/modal/Preference/ContactTab.js
Normal file
123
lib/components/modal/Preference/ContactTab.js
Normal file
@@ -0,0 +1,123 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { getClientKey } from 'boost/activityRecord'
|
||||
import linkState from 'boost/linkState'
|
||||
import _ from 'lodash'
|
||||
import { request, WEB_URL } from 'boost/api'
|
||||
|
||||
const FORM_MODE = 'FORM_MODE'
|
||||
const DONE_MODE = 'DONE_MODE'
|
||||
|
||||
export default class ContactTab extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
title: '',
|
||||
content: '',
|
||||
email: '',
|
||||
mode: FORM_MODE,
|
||||
alert: null
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
let titleInput = ReactDOM.findDOMNode(this.refs.title)
|
||||
if (titleInput != null) titleInput.focus()
|
||||
}
|
||||
|
||||
handleBackButtonClick (e) {
|
||||
this.setState({
|
||||
mode: FORM_MODE
|
||||
})
|
||||
}
|
||||
|
||||
handleSendButtonClick (e) {
|
||||
let input = _.pick(this.state, ['title', 'content', 'email'])
|
||||
input.clientKey = getClientKey()
|
||||
|
||||
this.setState({
|
||||
alert: {
|
||||
type: 'info',
|
||||
message: 'Sending...'
|
||||
}
|
||||
}, () => {
|
||||
request.post(WEB_URL + 'apis/inquiry')
|
||||
.send(input)
|
||||
.then(res => {
|
||||
console.log('sent')
|
||||
this.setState({
|
||||
title: '',
|
||||
content: '',
|
||||
mode: DONE_MODE,
|
||||
alert: null
|
||||
})
|
||||
})
|
||||
.catch(err => {
|
||||
if (err.code === 'ECONNREFUSED') {
|
||||
this.setState({
|
||||
alert: {
|
||||
type: 'error',
|
||||
message: 'Can\'t connect to API server.'
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.error(err)
|
||||
this.setState({
|
||||
alert: {
|
||||
type: 'error',
|
||||
message: err.message
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
render () {
|
||||
switch (this.state.mode) {
|
||||
case DONE_MODE:
|
||||
return (
|
||||
<div className='ContactTab content done'>
|
||||
<div className='message'>
|
||||
<i className='checkIcon fa fa-check-circle'/><br/>
|
||||
Your message has been sent successfully!!
|
||||
</div>
|
||||
<div className='control'>
|
||||
<button onClick={e => this.handleBackButtonClick(e)}>Back to Contact form</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
case FORM_MODE:
|
||||
default:
|
||||
let alertElement = this.state.alert != null
|
||||
? (
|
||||
<div className={'alert ' + this.state.alert.type}>{this.state.alert.message}</div>
|
||||
)
|
||||
: null
|
||||
return (
|
||||
<div className='ContactTab content form'>
|
||||
<div className='title'>Contact form</div>
|
||||
<div className='description'>
|
||||
Your feedback is highly appreciated and will help us to improve our app. :D
|
||||
</div>
|
||||
<div className='iptGroup'>
|
||||
<input ref='title' valueLink={this.linkState('title')} placeholder='Title' type='text'/>
|
||||
</div>
|
||||
<div className='iptGroup'>
|
||||
<textarea valueLink={this.linkState('content')} placeholder='Content'/>
|
||||
</div>
|
||||
<div className='iptGroup'>
|
||||
<input valueLink={this.linkState('email')} placeholder='E-mail (Optional)' type='email'/>
|
||||
</div>
|
||||
<div className='formControl'>
|
||||
<button onClick={e => this.handleSendButtonClick(e)} className='primary'>Send</button>
|
||||
{alertElement}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContactTab.prototype.linkState = linkState
|
||||
@@ -5,11 +5,13 @@ import store from 'boost/store'
|
||||
import AppSettingTab from './Preference/AppSettingTab'
|
||||
import HelpTab from './Preference/HelpTab'
|
||||
import FolderSettingTab from './Preference/FolderSettingTab'
|
||||
import ContactTab from './Preference/ContactTab'
|
||||
import { closeModal } from 'boost/modal'
|
||||
|
||||
const APP = 'APP'
|
||||
const HELP = 'HELP'
|
||||
const FOLDER = 'FOLDER'
|
||||
const CONTACT = 'CONTACT'
|
||||
|
||||
class Preferences extends React.Component {
|
||||
constructor (props) {
|
||||
@@ -35,7 +37,8 @@ class Preferences extends React.Component {
|
||||
|
||||
let tabs = [
|
||||
{target: APP, label: 'Preferences'},
|
||||
{target: FOLDER, label: 'Manage folder'}
|
||||
{target: FOLDER, label: 'Manage folder'},
|
||||
{target: CONTACT, label: 'Contact form'}
|
||||
]
|
||||
|
||||
let navButtons = tabs.map(tab => (
|
||||
@@ -71,6 +74,10 @@ class Preferences extends React.Component {
|
||||
folders={folders}
|
||||
/>
|
||||
)
|
||||
case CONTACT:
|
||||
return (
|
||||
<ContactTab/>
|
||||
)
|
||||
case APP:
|
||||
default:
|
||||
return (<AppSettingTab/>)
|
||||
@@ -239,7 +246,6 @@ Preferences.prototype.linkState = linkState
|
||||
|
||||
function remap (state) {
|
||||
let { folders, status } = state
|
||||
console.log(state)
|
||||
|
||||
return {
|
||||
folders,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React, { PropTypes } from 'react'
|
||||
import MarkdownPreview from 'boost/components/MarkdownPreview'
|
||||
import CodeEditor from 'boost/components/CodeEditor'
|
||||
|
||||
@@ -88,8 +88,11 @@ export default class Tutorial extends React.Component {
|
||||
return (<div className='slide slide3'>
|
||||
<div className='title'>Easy to access with Finder</div>
|
||||
<div className='content'>
|
||||
Finder is a small popup window.<br/>
|
||||
With finder, You can search your articles faster.<br/>
|
||||
With Finder, You can search your articles faster.<br/>
|
||||
You can open Finder by pressing Control + shift + tab<br/>
|
||||
To put the content of an article in the clipboard, press Enter.<br/>
|
||||
So you can paste it with Cmd(⌘) + V
|
||||
|
||||
<img width='480' src='../../resources/finder.png'/>
|
||||
</div>
|
||||
</div>)
|
||||
@@ -105,3 +108,7 @@ export default class Tutorial extends React.Component {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tutorial.propTypes = {
|
||||
close: PropTypes.func
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import keygen from 'boost/keygen'
|
||||
|
||||
let defaultContent = '**Boost**は全く新しいエンジニアライクのノートアプリです。\n\n# ◎特徴\nBoostはエンジニアの仕事を圧倒的に効率化するいくつかの機能を備えています。\nその一部をご紹介します。\n1. Folderで情報を分類\n2. 豊富なsyantaxに対応\n3. Finder機能\n4. チーム機能(リアルタイム搭載)\n\n* * * *\n\n# 1. Folderで情報を分類、欲しい情報にすぐアクセス。\n左側のバーに存在する「Folders」。\n今すぐプラスボタンを押しましょう。\n分類の仕方も自由自在です。\n- 言語やフレームワークごとにFolderを作成\n- 自分用のカジュアルなメモをまとめる場としてFolderを作成\n\n\n# 2. 豊富なsyantaxに対応、自分の脳の代わりに。\nプログラミングに関する情報を全て、手軽に保存しましょう。\n- mdで、apiの仕様をまとめる\n- よく使うモジュールやスニペット\n\nBoostに保存しておくことで、何度も同じコードを書いたり調べたりする必要がなくなります。\n\n# 3. Finder機能を搭載、もうコマンドを手打ちする必要はありません。\n**「shift+cmd+tab」** を同時に押してみてください。\nここでは、一瞬でBoostの中身を検索するウィンドウを表示させることができます。\n\n矢印キーで選択、Enterを押し、cmd+vでペーストすると…続きはご自身の目でお確かめください。\n- sqlやlinux等の、よく使うが手打ちが面倒なコマンド\n- (メールやカスタマーサポート等でよく使うフレーズ)\n\n私たちは、圧倒的な効率性を支援します。\n\* * * *\n\n\n## ◎詳しくは\nこちらのブログ( http://blog-jp.b00st.io )にて随時更新しています。\n\nそれでは素晴らしいエンジニアライフを!\n\n## Hack your memory**'
|
||||
let defaultContent = 'Boost is a brand new note App for programmers.\n\n> 下に日本語版があります。\n\n# \u25CEfeature\n\nBoost has some preponderant functions for efficient engineer\'s task.See some part of it.\n\n1. classify information by\u300CFolders\u300D\n2. deal with great variety of syntax\n3. Finder function\n\n\uFF0A\u3000\uFF0A\u3000\uFF0A\u3000\uFF0A\n\n# 1. classify information by \u300CFolders\u300D- access the information you needed easily.\n\n\u300CFolders\u300D which on the left side bar. Press plus button now. flexible way of classification.\n- Create Folder every language or flamework\n- Make Folder for your own casual memos\n\n# 2. Deal with a great variety of syntax \u2013 instead of your brain\nSave handy all information related with programming\n- Use markdown and gather api specification\n- Well using module and snippet\n\nSave them on Boost, you don\'t need to rewrite or re-search same code again.\n\n# 3. Load Finder function \u2013 now you don\'t need to spell command by hand typing.\n\n**Shift +cmd+tab** press buttons at same time.\nThen, the window will show up for search Boost contents that instant.\n\nUsing cursor key to chose, press enter, cmd+v to paste and\u2026 please check it out by your own eye.\n\n- Such command spl or linux which programmers often use but troublesome to hand type\n\n- (Phrases commonly used for e-mail or customer support)\n\nWe support preponderant efficiency\n\n\uFF0A\u3000\uFF0A\u3000\uFF0A\u3000\uFF0A\n\n## \u25CEfor more information\nFrequently updated with this blog ( http:\/\/blog-jp.b00st.io )\n\nHave wonderful programmer life!\n\n## Hack your memory**\n\n\n\n# 日本語版\n\n**Boost**は全く新しいエンジニアライクのノートアプリです。\n\n# ◎特徴\nBoostはエンジニアの仕事を圧倒的に効率化するいくつかの機能を備えています。\nその一部をご紹介します。\n1. Folderで情報を分類\n2. 豊富なsyantaxに対応\n3. Finder機能\n4. チーム機能(リアルタイム搭載)\n\n* * * *\n\n# 1. Folderで情報を分類、欲しい情報にすぐアクセス。\n左側のバーに存在する「Folders」。\n今すぐプラスボタンを押しましょう。\n分類の仕方も自由自在です。\n- 言語やフレームワークごとにFolderを作成\n- 自分用のカジュアルなメモをまとめる場としてFolderを作成\n\n\n# 2. 豊富なsyntaxに対応、自分の脳の代わりに。\nプログラミングに関する情報を全て、手軽に保存しましょう。\n- mdで、apiの仕様をまとめる\n- よく使うモジュールやスニペット\n\nBoostに保存しておくことで、何度も同じコードを書いたり調べたりする必要がなくなります。\n\n# 3. Finder機能を搭載、もうコマンドを手打ちする必要はありません。\n**「shift+cmd+tab」** を同時に押してみてください。\nここでは、一瞬でBoostの中身を検索するウィンドウを表示させることができます。\n\n矢印キーで選択、Enterを押し、cmd+vでペーストすると…続きはご自身の目でお確かめください。\n- sqlやlinux等の、よく使うが手打ちが面倒なコマンド\n- (メールやカスタマーサポート等でよく使うフレーズ)\n\n私たちは、圧倒的な効率性を支援します。\n\* * * *\n\n\n## ◎詳しくは\nこちらのブログ( http://blog-jp.b00st.io )にて随時更新しています。\n\nそれでは素晴らしいエンジニアライフを!\n\n## Hack your memory**'
|
||||
|
||||
export function init () {
|
||||
console.log('initialize data store')
|
||||
@@ -11,7 +11,7 @@ export function init () {
|
||||
key: keygen()
|
||||
}
|
||||
let defaultArticle = {
|
||||
title: 'Boostとは',
|
||||
title: 'About Boost',
|
||||
tags: ['boost', 'intro'],
|
||||
content: defaultContent,
|
||||
mode: 'markdown',
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { combineReducers } from 'redux'
|
||||
import _ from 'lodash'
|
||||
import { SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, SET_SEARCH_FILTER, SET_TAG_FILTER, CLEAR_SEARCH, ARTICLE_UPDATE, ARTICLE_DESTROY, FOLDER_CREATE, FOLDER_UPDATE, FOLDER_DESTROY, IDLE_MODE, CREATE_MODE } from './actions'
|
||||
import { SWITCH_FOLDER, SWITCH_MODE, SWITCH_ARTICLE, SET_SEARCH_FILTER, SET_TAG_FILTER, CLEAR_SEARCH, TOGGLE_TUTORIAL, ARTICLE_UPDATE, ARTICLE_DESTROY, FOLDER_CREATE, FOLDER_UPDATE, FOLDER_DESTROY, IDLE_MODE, CREATE_MODE } from './actions'
|
||||
import dataStore from 'boost/dataStore'
|
||||
import keygen from 'boost/keygen'
|
||||
import activityRecord from 'boost/activityRecord'
|
||||
|
||||
const initialStatus = {
|
||||
mode: IDLE_MODE,
|
||||
search: ''
|
||||
search: '',
|
||||
isTutorialOpen: false
|
||||
}
|
||||
|
||||
let data = dataStore.getData()
|
||||
@@ -23,7 +25,7 @@ function folders (state = initialFolders, action) {
|
||||
newFolder.name = newFolder.name.trim().replace(/\s/, '_')
|
||||
Object.assign(newFolder, {
|
||||
key: keygen(),
|
||||
createAt: new Date(),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
// random number (0-7)
|
||||
color: Math.round(Math.random() * 7)
|
||||
@@ -36,6 +38,7 @@ function folders (state = initialFolders, action) {
|
||||
state.push(newFolder)
|
||||
|
||||
dataStore.setFolders(null, state)
|
||||
activityRecord.emit('FOLDER_CREATE')
|
||||
return state
|
||||
}
|
||||
case FOLDER_UPDATE:
|
||||
@@ -54,7 +57,6 @@ function folders (state = initialFolders, action) {
|
||||
let conflictFolder = _.find(state, _folder => {
|
||||
return folder.name === _folder.name && folder.key !== _folder.key
|
||||
})
|
||||
console.log(conflictFolder)
|
||||
if (conflictFolder != null) throw new Error('Name conflicted')
|
||||
}
|
||||
Object.assign(targetFolder, folder, {
|
||||
@@ -62,6 +64,7 @@ function folders (state = initialFolders, action) {
|
||||
})
|
||||
|
||||
dataStore.setFolders(null, state)
|
||||
activityRecord.emit('FOLDER_UPDATE')
|
||||
return state
|
||||
}
|
||||
case FOLDER_DESTROY:
|
||||
@@ -74,6 +77,7 @@ function folders (state = initialFolders, action) {
|
||||
state.splice(targetIndex, 1)
|
||||
}
|
||||
dataStore.setFolders(null, state)
|
||||
activityRecord.emit('FOLDER_DESTROY')
|
||||
return state
|
||||
}
|
||||
default:
|
||||
@@ -122,6 +126,9 @@ function articles (state = initialArticles, action) {
|
||||
function status (state = initialStatus, action) {
|
||||
state = Object.assign({}, state)
|
||||
switch (action.type) {
|
||||
case TOGGLE_TUTORIAL:
|
||||
state.isTutorialOpen = !state.isTutorialOpen
|
||||
return state
|
||||
case SWITCH_FOLDER:
|
||||
state.mode = IDLE_MODE
|
||||
state.search = `in:${action.data} `
|
||||
|
||||
756
lib/vars/modes.js
Normal file
756
lib/vars/modes.js
Normal file
@@ -0,0 +1,756 @@
|
||||
const modes = [
|
||||
// Major
|
||||
{
|
||||
name: 'text',
|
||||
label: 'Plain text',
|
||||
mode: 'text'
|
||||
},
|
||||
{
|
||||
name: 'markdown',
|
||||
label: 'Markdown',
|
||||
alias: ['md'],
|
||||
mode: 'markdown'
|
||||
},
|
||||
{
|
||||
name: 'javascript',
|
||||
label: 'JavaScript',
|
||||
alias: ['js', 'jscript', 'babel', 'es'],
|
||||
mode: 'javascript'
|
||||
},
|
||||
{
|
||||
name: 'html',
|
||||
label: 'HTML',
|
||||
alias: [],
|
||||
mode: 'html'
|
||||
},
|
||||
{
|
||||
name: 'css',
|
||||
label: 'CSS',
|
||||
alias: ['cascade', 'stylesheet'],
|
||||
mode: 'css'
|
||||
},
|
||||
{
|
||||
name: 'php',
|
||||
label: 'PHP',
|
||||
alias: [],
|
||||
mode: 'php'
|
||||
},
|
||||
{
|
||||
name: 'python',
|
||||
label: 'Python',
|
||||
alias: ['py'],
|
||||
mode: 'python'
|
||||
},
|
||||
{
|
||||
name: 'ruby',
|
||||
label: 'Ruby',
|
||||
alias: ['rb'],
|
||||
mode: 'ruby'
|
||||
},
|
||||
{
|
||||
name: 'java',
|
||||
label: 'Java',
|
||||
alias: [],
|
||||
mode: 'java'
|
||||
},
|
||||
{
|
||||
name: 'c',
|
||||
label: 'C',
|
||||
alias: ['c', 'h', 'clang', 'clang'],
|
||||
mode: 'c_cpp'
|
||||
},
|
||||
{
|
||||
name: 'cpp',
|
||||
label: 'C++',
|
||||
alias: ['cc', 'cpp', 'cxx', 'hh', 'c++', 'cplusplus'],
|
||||
mode: 'c_cpp'
|
||||
},
|
||||
{
|
||||
name: 'csharp',
|
||||
label: 'C#',
|
||||
alias: ['cs'],
|
||||
mode: 'csharp'
|
||||
},
|
||||
{
|
||||
name: 'swift',
|
||||
label: 'Swift',
|
||||
alias: [],
|
||||
mode: 'swift'
|
||||
},
|
||||
{
|
||||
name: 'golang',
|
||||
label: 'Go',
|
||||
alias: ['go'],
|
||||
mode: 'golang'
|
||||
},
|
||||
|
||||
// Minor
|
||||
{
|
||||
name: 'abap',
|
||||
label: 'ABAP',
|
||||
alias: [],
|
||||
mode: 'abap'
|
||||
},
|
||||
{
|
||||
name: 'abc',
|
||||
label: 'ABC',
|
||||
alias: [],
|
||||
mode: 'abc'
|
||||
},
|
||||
{
|
||||
name: 'actionscript',
|
||||
label: 'ActionScript',
|
||||
alias: ['as'],
|
||||
mode: 'actionscript'
|
||||
},
|
||||
{
|
||||
name: 'ada',
|
||||
label: 'Ada',
|
||||
alias: [],
|
||||
mode: 'ada'
|
||||
},
|
||||
{
|
||||
name: 'apache_conf',
|
||||
label: 'Apache config',
|
||||
alias: ['apache', 'conf'],
|
||||
mode: 'apache_conf'
|
||||
},
|
||||
{
|
||||
name: 'applescript',
|
||||
label: 'AppleScript',
|
||||
alias: ['scpt'],
|
||||
mode: 'applescript'
|
||||
},
|
||||
{
|
||||
name: 'asciidoc',
|
||||
label: 'AsciiDoc',
|
||||
alias: ['ascii', 'doc', 'txt'],
|
||||
mode: 'asciidoc'
|
||||
},
|
||||
{
|
||||
name: 'assembly_x86',
|
||||
label: 'Assembly x86',
|
||||
alias: ['assembly', 'x86', 'asm'],
|
||||
mode: 'assembly_x86'
|
||||
},
|
||||
{
|
||||
name: 'autohotkey',
|
||||
label: 'AutoHotkey',
|
||||
alias: ['ahk'],
|
||||
mode: 'autohotkey'
|
||||
},
|
||||
{
|
||||
name: 'batchfile',
|
||||
label: 'Batch file',
|
||||
alias: ['dos', 'windows', 'bat', 'cmd', 'btm'],
|
||||
mode: 'batchfile'
|
||||
},
|
||||
{
|
||||
name: 'cirru',
|
||||
label: 'Cirru',
|
||||
alias: [],
|
||||
mode: 'cirru'
|
||||
},
|
||||
{
|
||||
name: 'clojure',
|
||||
label: 'Clojure',
|
||||
alias: ['clj', 'cljs', 'cljc', 'edn'],
|
||||
mode: 'clojure'
|
||||
},
|
||||
{
|
||||
name: 'cobol',
|
||||
label: 'COBOL',
|
||||
alias: ['cbl', 'cob', 'cpy'],
|
||||
mode: 'cobol'
|
||||
},
|
||||
{
|
||||
name: 'coffee',
|
||||
label: 'CoffeeScript',
|
||||
alias: ['coffee'],
|
||||
mode: 'coffee'
|
||||
},
|
||||
{
|
||||
name: 'coldfusion',
|
||||
label: 'ColdFusion',
|
||||
alias: ['cfm', 'cfc'],
|
||||
mode: 'coldfusion'
|
||||
},
|
||||
{
|
||||
name: 'curly',
|
||||
label: 'Curly',
|
||||
alias: [],
|
||||
mode: 'curly'
|
||||
},
|
||||
{
|
||||
name: 'd',
|
||||
label: 'D',
|
||||
alias: ['dlang'],
|
||||
mode: 'd'
|
||||
},
|
||||
{
|
||||
name: 'dockerfile',
|
||||
label: 'DockerFile',
|
||||
alias: ['docker'],
|
||||
mode: 'docker'
|
||||
},
|
||||
{
|
||||
name: 'dart',
|
||||
label: 'Dart',
|
||||
alias: [],
|
||||
mode: 'dart'
|
||||
},
|
||||
{
|
||||
name: 'diff',
|
||||
label: 'Diff',
|
||||
alias: [],
|
||||
mode: 'diff'
|
||||
},
|
||||
{
|
||||
name: 'django',
|
||||
label: 'Django',
|
||||
alias: [],
|
||||
mode: 'djt'
|
||||
},
|
||||
{
|
||||
name: 'dot',
|
||||
label: 'DOT',
|
||||
alias: ['gv'],
|
||||
mode: 'dot'
|
||||
},
|
||||
{
|
||||
name: 'eiffel',
|
||||
label: 'Eiffel',
|
||||
alias: [],
|
||||
mode: 'eiffel'
|
||||
},
|
||||
{
|
||||
name: 'ejs',
|
||||
label: 'EJS',
|
||||
alias: [],
|
||||
mode: 'ejs'
|
||||
},
|
||||
{
|
||||
name: 'elixir',
|
||||
label: 'Elixir',
|
||||
alias: ['ex', 'exs'],
|
||||
mode: 'elixir'
|
||||
},
|
||||
{
|
||||
name: 'elm',
|
||||
label: 'Elm',
|
||||
alias: [],
|
||||
mode: 'elm'
|
||||
},
|
||||
{
|
||||
name: 'erlang',
|
||||
label: 'Erlang',
|
||||
alias: ['erl', 'hrl'],
|
||||
mode: 'erlang'
|
||||
},
|
||||
{
|
||||
name: 'forth',
|
||||
label: 'Forth',
|
||||
alias: ['fs', 'fth'],
|
||||
mode: 'forth'
|
||||
},
|
||||
{
|
||||
name: 'freemaker',
|
||||
label: 'Freemaker',
|
||||
alias: ['ftl'],
|
||||
mode: 'ftl'
|
||||
},
|
||||
{
|
||||
name: 'gcode',
|
||||
label: 'G-code',
|
||||
alias: ['mpt', 'mpf', 'nc'],
|
||||
mode: 'gcode'
|
||||
},
|
||||
{
|
||||
name: 'gherkin',
|
||||
label: 'Gherkin',
|
||||
alias: ['cucumber'],
|
||||
mode: 'gherkin'
|
||||
},
|
||||
{
|
||||
name: 'gitignore',
|
||||
label: 'Gitignore',
|
||||
alias: ['git'],
|
||||
mode: 'gitignore'
|
||||
},
|
||||
{
|
||||
name: 'glsl',
|
||||
label: 'GLSL',
|
||||
alias: ['opengl', 'shading'],
|
||||
mode: 'glsl'
|
||||
},
|
||||
{
|
||||
name: 'groovy',
|
||||
label: 'Groovy',
|
||||
alias: [],
|
||||
mode: 'grooby'
|
||||
},
|
||||
{
|
||||
name: 'haml',
|
||||
label: 'Haml',
|
||||
alias: [],
|
||||
mode: 'haml'
|
||||
},
|
||||
{
|
||||
name: 'handlebars',
|
||||
label: 'Handlebars',
|
||||
alias: ['hbs'],
|
||||
mode: 'handlebars'
|
||||
},
|
||||
{
|
||||
name: 'haskell',
|
||||
label: 'Haskell',
|
||||
alias: ['hs', 'lhs'],
|
||||
mode: 'haskell'
|
||||
},
|
||||
{
|
||||
name: 'haxe',
|
||||
label: 'Haxe',
|
||||
alias: ['hx', 'hxml'],
|
||||
mode: 'haxe'
|
||||
},
|
||||
{
|
||||
name: 'html_ruby',
|
||||
label: 'HTML (Ruby)',
|
||||
alias: ['erb', 'rhtml'],
|
||||
mode: 'html_ruby'
|
||||
},
|
||||
{
|
||||
name: 'jsx',
|
||||
label: 'JSX',
|
||||
alias: ['es', 'babel', 'js', 'jsx', 'react'],
|
||||
mode: 'jsx'
|
||||
},
|
||||
{
|
||||
name: 'typescript',
|
||||
label: 'TypeScript',
|
||||
alias: ['ts'],
|
||||
mode: 'typescript'
|
||||
},
|
||||
{
|
||||
name: 'ini',
|
||||
label: 'INI file',
|
||||
alias: [],
|
||||
mode: 'ini'
|
||||
},
|
||||
{
|
||||
name: 'io',
|
||||
label: 'Io',
|
||||
alias: [],
|
||||
mode: 'io'
|
||||
},
|
||||
{
|
||||
name: 'jack',
|
||||
label: 'Jack',
|
||||
alias: [],
|
||||
mode: 'jack'
|
||||
},
|
||||
{
|
||||
name: 'jade',
|
||||
label: 'Jade',
|
||||
alias: [],
|
||||
mode: 'jade'
|
||||
},
|
||||
{
|
||||
name: 'json',
|
||||
label: 'JSON',
|
||||
alias: [],
|
||||
mode: 'json'
|
||||
},
|
||||
{
|
||||
name: 'jsoniq',
|
||||
label: 'JSONiq',
|
||||
alias: ['query'],
|
||||
mode: 'jsoniq'
|
||||
},
|
||||
{
|
||||
name: 'jsp',
|
||||
label: 'JSP',
|
||||
alias: [],
|
||||
mode: 'jsp'
|
||||
},
|
||||
{
|
||||
name: 'julia',
|
||||
label: 'Julia',
|
||||
alias: [],
|
||||
mode: 'julia'
|
||||
},
|
||||
{
|
||||
name: 'latex',
|
||||
label: 'Latex',
|
||||
alias: ['tex'],
|
||||
mode: 'latex'
|
||||
},
|
||||
{
|
||||
name: 'lean',
|
||||
label: 'Lean',
|
||||
alias: [],
|
||||
mode: 'lean'
|
||||
},
|
||||
{
|
||||
name: 'less',
|
||||
label: 'Less',
|
||||
alias: [],
|
||||
mode: 'less'
|
||||
},
|
||||
{
|
||||
name: 'liquid',
|
||||
label: 'Liquid',
|
||||
alias: [],
|
||||
mode: 'liquid'
|
||||
},
|
||||
{
|
||||
name: 'lisp',
|
||||
label: 'Lisp',
|
||||
alias: ['lsp'],
|
||||
mode: 'lisp'
|
||||
},
|
||||
{
|
||||
name: 'livescript',
|
||||
label: 'LiveScript',
|
||||
alias: ['ls'],
|
||||
mode: 'livescript'
|
||||
},
|
||||
{
|
||||
name: 'logiql',
|
||||
label: 'LogiQL',
|
||||
alias: [],
|
||||
mode: 'logiql'
|
||||
},
|
||||
{
|
||||
name: 'lsl',
|
||||
label: 'LSL',
|
||||
alias: [],
|
||||
mode: 'lsl'
|
||||
},
|
||||
{
|
||||
name: 'lua',
|
||||
label: 'Lua',
|
||||
alias: [],
|
||||
mode: 'lua'
|
||||
},
|
||||
{
|
||||
name: 'luapage',
|
||||
label: 'Luapage',
|
||||
alias: [],
|
||||
mode: 'luapage'
|
||||
},
|
||||
{
|
||||
name: 'lucene',
|
||||
label: 'Lucene',
|
||||
alias: [],
|
||||
mode: 'lucene'
|
||||
},
|
||||
{
|
||||
name: 'makefile',
|
||||
label: 'Makefile',
|
||||
alias: [],
|
||||
mode: 'makefile'
|
||||
},
|
||||
{
|
||||
name: 'mask',
|
||||
label: 'Mask',
|
||||
alias: [],
|
||||
mode: 'mask'
|
||||
},
|
||||
{
|
||||
name: 'matlab',
|
||||
label: 'MATLAB',
|
||||
alias: [],
|
||||
mode: 'matlab'
|
||||
},
|
||||
{
|
||||
name: 'maze',
|
||||
label: 'Maze',
|
||||
alias: [],
|
||||
mode: 'maze'
|
||||
},
|
||||
{
|
||||
name: 'mel',
|
||||
label: 'MEL',
|
||||
alias: [],
|
||||
mode: 'mel'
|
||||
},
|
||||
{
|
||||
name: 'mipsassembler',
|
||||
label: 'MIPS assembly',
|
||||
alias: [],
|
||||
mode: 'mipsassembler'
|
||||
},
|
||||
{
|
||||
name: 'mushcode',
|
||||
label: 'MUSHCode',
|
||||
alias: [],
|
||||
mode: 'mushcode'
|
||||
},
|
||||
{
|
||||
name: 'mysql',
|
||||
label: 'MySQL',
|
||||
alias: [],
|
||||
mode: 'mysql'
|
||||
},
|
||||
{
|
||||
name: 'nix',
|
||||
label: 'Nix',
|
||||
alias: [],
|
||||
mode: 'nix'
|
||||
},
|
||||
{
|
||||
name: 'objectivec',
|
||||
label: 'Objective C',
|
||||
alias: ['objc'],
|
||||
mode: 'objectivec'
|
||||
},
|
||||
{
|
||||
name: 'ocaml',
|
||||
label: 'OCaml',
|
||||
alias: [],
|
||||
mode: 'ocaml'
|
||||
},
|
||||
{
|
||||
name: 'pascal',
|
||||
label: 'Pascal',
|
||||
alias: [],
|
||||
mode: 'pascal'
|
||||
},
|
||||
{
|
||||
name: 'perl',
|
||||
label: 'Perl',
|
||||
alias: [],
|
||||
mode: 'perl'
|
||||
},
|
||||
{
|
||||
name: 'pgsql',
|
||||
label: 'Postgres SQL',
|
||||
alias: ['postgres'],
|
||||
mode: 'pgsql'
|
||||
},
|
||||
{
|
||||
name: 'powershell',
|
||||
label: 'PowerShell',
|
||||
alias: ['ps1'],
|
||||
mode: 'powershell'
|
||||
},
|
||||
{
|
||||
name: 'praat',
|
||||
label: 'Praat',
|
||||
alias: [],
|
||||
mode: 'praat'
|
||||
},
|
||||
{
|
||||
name: 'prolog',
|
||||
label: 'Prolog',
|
||||
alias: ['pl', 'pro'],
|
||||
mode: 'prolog'
|
||||
},
|
||||
{
|
||||
name: 'properties',
|
||||
label: 'Properties',
|
||||
alias: [],
|
||||
mode: 'properties'
|
||||
},
|
||||
{
|
||||
name: 'protobuf',
|
||||
label: 'Protocol Buffers',
|
||||
alias: ['protocol', 'buffers'],
|
||||
mode: 'protobuf'
|
||||
},
|
||||
{
|
||||
name: 'r',
|
||||
label: 'R',
|
||||
alias: ['rlang'],
|
||||
mode: 'r'
|
||||
},
|
||||
{
|
||||
name: 'rdoc',
|
||||
label: 'RDoc',
|
||||
alias: [],
|
||||
mode: 'rdoc'
|
||||
},
|
||||
{
|
||||
name: 'rust',
|
||||
label: 'Rust',
|
||||
alias: [],
|
||||
mode: 'rust'
|
||||
},
|
||||
{
|
||||
name: 'sass',
|
||||
label: 'Sass',
|
||||
alias: [],
|
||||
mode: 'sass'
|
||||
},
|
||||
{
|
||||
name: 'scad',
|
||||
label: 'SCAD',
|
||||
alias: [],
|
||||
mode: 'scad'
|
||||
},
|
||||
{
|
||||
name: 'scala',
|
||||
label: 'Scala',
|
||||
alias: [],
|
||||
mode: 'scala'
|
||||
},
|
||||
{
|
||||
name: 'scheme',
|
||||
label: 'Scheme',
|
||||
alias: ['scm', 'ss'],
|
||||
mode: 'scheme'
|
||||
},
|
||||
{
|
||||
name: 'scss',
|
||||
label: 'Scss',
|
||||
alias: [],
|
||||
mode: 'scss'
|
||||
},
|
||||
{
|
||||
name: 'sh',
|
||||
label: 'Shell',
|
||||
alias: ['shell'],
|
||||
mode: 'sh'
|
||||
},
|
||||
{
|
||||
name: 'sjs',
|
||||
label: 'StratifiedJS',
|
||||
alias: ['stratified'],
|
||||
mode: 'sjs'
|
||||
},
|
||||
{
|
||||
name: 'smarty',
|
||||
label: 'Smarty',
|
||||
alias: [],
|
||||
mode: 'smarty'
|
||||
},
|
||||
{
|
||||
name: 'snippets',
|
||||
label: 'Snippets',
|
||||
alias: [],
|
||||
mode: 'snippets'
|
||||
},
|
||||
{
|
||||
name: 'soy_template',
|
||||
label: 'Soy Template',
|
||||
alias: ['soy'],
|
||||
mode: 'soy_template'
|
||||
},
|
||||
{
|
||||
name: 'space',
|
||||
label: 'Space',
|
||||
alias: [],
|
||||
mode: 'space'
|
||||
},
|
||||
{
|
||||
name: 'sql',
|
||||
label: 'SQL',
|
||||
alias: [],
|
||||
mode: 'sql'
|
||||
},
|
||||
{
|
||||
name: 'sqlserver',
|
||||
label: 'SQL Server',
|
||||
alias: [],
|
||||
mode: 'sqlserver'
|
||||
},
|
||||
{
|
||||
name: 'stylus',
|
||||
label: 'Stylus',
|
||||
alias: [],
|
||||
mode: 'stylus'
|
||||
},
|
||||
{
|
||||
name: 'svg',
|
||||
label: 'SVG',
|
||||
alias: [],
|
||||
mode: 'svg'
|
||||
},
|
||||
{
|
||||
name: 'swig',
|
||||
label: 'SWIG',
|
||||
alias: [],
|
||||
mode: 'swig'
|
||||
},
|
||||
{
|
||||
name: 'tcl',
|
||||
label: 'Tcl',
|
||||
alias: [],
|
||||
mode: 'tcl'
|
||||
},
|
||||
{
|
||||
name: 'tex',
|
||||
label: 'TeX',
|
||||
alias: [],
|
||||
mode: 'tex'
|
||||
},
|
||||
{
|
||||
name: 'textile',
|
||||
label: 'Textile',
|
||||
alias: [],
|
||||
mode: 'textile'
|
||||
},
|
||||
{
|
||||
name: 'toml',
|
||||
label: 'TOML',
|
||||
alias: [],
|
||||
mode: 'toml'
|
||||
},
|
||||
{
|
||||
name: 'twig',
|
||||
label: 'Twig',
|
||||
alias: [],
|
||||
mode: 'twig'
|
||||
},
|
||||
{
|
||||
name: 'vala',
|
||||
label: 'Vala',
|
||||
alias: [],
|
||||
mode: 'vala'
|
||||
},
|
||||
{
|
||||
name: 'vbscript',
|
||||
label: 'VBScript',
|
||||
alias: ['vbs', 'vbe'],
|
||||
mode: 'vbscript'
|
||||
},
|
||||
{
|
||||
name: 'velocity',
|
||||
label: 'Velocity',
|
||||
alias: [],
|
||||
mode: 'velocity'
|
||||
},
|
||||
{
|
||||
name: 'verilog',
|
||||
label: 'Verilog',
|
||||
alias: [],
|
||||
mode: 'verilog'
|
||||
},
|
||||
{
|
||||
name: 'vhdl',
|
||||
label: 'VHDL',
|
||||
alias: [],
|
||||
mode: 'vhdl'
|
||||
},
|
||||
{
|
||||
name: 'xml',
|
||||
label: 'XML',
|
||||
alias: [],
|
||||
mode: 'xml'
|
||||
},
|
||||
{
|
||||
name: 'xquery',
|
||||
label: 'XQuery',
|
||||
alias: [],
|
||||
mode: 'xquery'
|
||||
},
|
||||
{
|
||||
name: 'yaml',
|
||||
label: 'YAML',
|
||||
alias: [],
|
||||
mode: 'yaml'
|
||||
}
|
||||
]
|
||||
|
||||
export default modes
|
||||
6
main.js
6
main.js
@@ -138,8 +138,12 @@ app.on('ready', function () {
|
||||
}
|
||||
finderWindow.show()
|
||||
})
|
||||
mainWindow.webContents.send('APP_SETTING_DONE', {})
|
||||
} catch (err) {
|
||||
console.log(err.name)
|
||||
console.error(err)
|
||||
mainWindow.webContents.send('APP_SETTING_ERROR', {
|
||||
message: 'Failed to apply hotkey: Invalid format'
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "boost",
|
||||
"version": "0.4.0-beta.1",
|
||||
"version": "0.4.0-beta.2",
|
||||
"description": "Boost App",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user