mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-13 17:56:25 +00:00
編集状態でのMarkdown preview追加
This commit is contained in:
@@ -16,6 +16,8 @@ const TAG_FILTER = 'TAG_FILTER'
|
|||||||
|
|
||||||
class HomePage extends React.Component {
|
class HomePage extends React.Component {
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
|
// React自体のKey入力はfocusされていないElementからは動かないため、
|
||||||
|
// `window`に直接かける
|
||||||
this.listener = (e) => this.handleKeyDown(e)
|
this.listener = (e) => this.handleKeyDown(e)
|
||||||
window.addEventListener('keydown', this.listener)
|
window.addEventListener('keydown', this.listener)
|
||||||
}
|
}
|
||||||
@@ -33,6 +35,7 @@ class HomePage extends React.Component {
|
|||||||
let { status } = this.props
|
let { status } = this.props
|
||||||
let { nav, top, list, detail } = this.refs
|
let { nav, top, list, detail } = this.refs
|
||||||
|
|
||||||
|
// Search inputがfocusされていたら大体のキー入力は無視される。
|
||||||
if (top.isInputFocused() && !e.metaKey) {
|
if (top.isInputFocused() && !e.metaKey) {
|
||||||
if (e.keyCode === 13 || e.keyCode === 27) top.escape()
|
if (e.keyCode === 13 || e.keyCode === 27) top.escape()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import _ from 'lodash'
|
|||||||
import ModeIcon from 'boost/components/ModeIcon'
|
import ModeIcon from 'boost/components/ModeIcon'
|
||||||
import MarkdownPreview from 'boost/components/MarkdownPreview'
|
import MarkdownPreview from 'boost/components/MarkdownPreview'
|
||||||
import CodeEditor from 'boost/components/CodeEditor'
|
import CodeEditor from 'boost/components/CodeEditor'
|
||||||
import { IDLE_MODE, CREATE_MODE, EDIT_MODE, switchMode, switchArticle, switchFolder, updateArticle, destroyArticle } from 'boost/actions'
|
import { IDLE_MODE, CREATE_MODE, EDIT_MODE, switchMode, switchArticle, switchFolder, clearSearch, updateArticle, destroyArticle } from 'boost/actions'
|
||||||
import aceModes from 'boost/ace-modes'
|
import aceModes from 'boost/ace-modes'
|
||||||
import Select from 'react-select'
|
import Select from 'react-select'
|
||||||
import linkState from 'boost/linkState'
|
import linkState from 'boost/linkState'
|
||||||
@@ -33,16 +33,23 @@ export default class ArticleDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps (nextProps) {
|
componentWillReceiveProps (nextProps) {
|
||||||
if (nextProps.activeArticle != null && (nextProps.activeArticle.key !== this.state.article.key) || (nextProps.status.mode !== this.props.status.mode)) {
|
let nextState = {}
|
||||||
this.setState({article: makeInstantArticle(nextProps.activeArticle)}, function () {
|
|
||||||
console.log('receive props')
|
let isArticleChanged = nextProps.activeArticle != null && (nextProps.activeArticle.key !== this.state.article.key)
|
||||||
|
let isModeChanged = nextProps.status.mode !== this.props.status.mode
|
||||||
|
if (isArticleChanged || (isModeChanged && nextProps.status.mode !== IDLE_MODE)) {
|
||||||
|
Object.assign(nextState, {
|
||||||
|
article: makeInstantArticle(nextProps.activeArticle)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let isEdit = nextProps.status.mode === EDIT_MODE || nextProps.status.mode === CREATE_MODE
|
if (isModeChanged) {
|
||||||
if (isEdit && this.state.openDeleteConfirmMenu) {
|
Object.assign(nextState, {
|
||||||
this.setState({openDeleteConfirmMenu: false})
|
openDeleteConfirmMenu: false,
|
||||||
|
previewMode: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
this.setState(nextState)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEmpty () {
|
renderEmpty () {
|
||||||
@@ -152,7 +159,12 @@ export default class ArticleDetail extends React.Component {
|
|||||||
|
|
||||||
dispatch(updateArticle(newArticle))
|
dispatch(updateArticle(newArticle))
|
||||||
dispatch(switchMode(IDLE_MODE))
|
dispatch(switchMode(IDLE_MODE))
|
||||||
|
// Folder filterがかかっている時に、
|
||||||
|
// Searchを初期化し、更新先のFolder filterをかける
|
||||||
|
// かかれていない時に
|
||||||
|
// Searchを初期化する
|
||||||
if (filters.folder.length !== 0) dispatch(switchFolder(folder.name))
|
if (filters.folder.length !== 0) dispatch(switchFolder(folder.name))
|
||||||
|
else dispatch(clearSearch())
|
||||||
dispatch(switchArticle(newArticle.key))
|
dispatch(switchArticle(newArticle.key))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +194,10 @@ export default class ArticleDetail extends React.Component {
|
|||||||
this.setState({article: article})
|
this.setState({article: article})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleTogglePreviewButtonClick (e) {
|
||||||
|
this.setState({previewMode: !this.state.previewMode})
|
||||||
|
}
|
||||||
|
|
||||||
renderEdit () {
|
renderEdit () {
|
||||||
let { folders } = this.props
|
let { folders } = this.props
|
||||||
|
|
||||||
@@ -209,6 +225,11 @@ export default class ArticleDetail extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='right'>
|
<div className='right'>
|
||||||
|
{
|
||||||
|
this.state.article.mode === 'markdown'
|
||||||
|
? (<button className='preview' onClick={e => this.handleTogglePreviewButtonClick(e)}>Toggle Preview</button>)
|
||||||
|
: null
|
||||||
|
}
|
||||||
<button onClick={e => this.handleCancelButtonClick(e)}>Cancel</button>
|
<button onClick={e => this.handleCancelButtonClick(e)}>Cancel</button>
|
||||||
<button onClick={e => this.handleSaveButtonClick(e)} className='primary'>Save</button>
|
<button onClick={e => this.handleSaveButtonClick(e)} className='primary'>Save</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -229,12 +250,16 @@ export default class ArticleDetail extends React.Component {
|
|||||||
className='mode'
|
className='mode'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<CodeEditor
|
|
||||||
onChange={(e, value) => this.handleContentChange(e, value)}
|
{this.state.previewMode
|
||||||
readOnly={false}
|
? <MarkdownPreview content={this.state.article.content}/>
|
||||||
mode={this.state.article.mode}
|
: (<CodeEditor
|
||||||
code={this.state.article.content}
|
onChange={(e, value) => this.handleContentChange(e, value)}
|
||||||
/>
|
readOnly={false}
|
||||||
|
mode={this.state.article.mode}
|
||||||
|
code={this.state.article.content}
|
||||||
|
/>)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -29,10 +29,10 @@ export default class MainContainer extends React.Component {
|
|||||||
{this.state.updateAvailable ? (
|
{this.state.updateAvailable ? (
|
||||||
<button onClick={this.updateApp} className='appUpdateButton'><i className='fa fa-cloud-download'/> Update available!</button>
|
<button onClick={this.updateApp} className='appUpdateButton'><i className='fa fa-cloud-download'/> Update available!</button>
|
||||||
) : null}
|
) : null}
|
||||||
<button onClick={this.openContactModal} className='contactButton'>
|
{/* <button onClick={this.openContactModal} className='contactButton'>
|
||||||
<i className='fa fa-paper-plane-o'/>
|
<i className='fa fa-paper-plane-o'/>
|
||||||
<div className='tooltip'>Contact us</div>
|
<div className='tooltip'>Contact us</div>
|
||||||
</button>
|
</button> */}
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ iptFocusBorderColor = #369DCD
|
|||||||
background-color darken(white, 5%)
|
background-color darken(white, 5%)
|
||||||
border solid 1px borderColor
|
border solid 1px borderColor
|
||||||
border-radius 5px
|
border-radius 5px
|
||||||
|
&.preview
|
||||||
|
width inherit
|
||||||
&:hover
|
&:hover
|
||||||
background-color white
|
background-color white
|
||||||
&.primary
|
&.primary
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ function articles (state = initialArticles, action) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function status (state = initialStatus, action) {
|
function status (state = initialStatus, action) {
|
||||||
|
state = Object.assign({}, state)
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case SWITCH_FOLDER:
|
case SWITCH_FOLDER:
|
||||||
state.mode = IDLE_MODE
|
state.mode = IDLE_MODE
|
||||||
|
|||||||
Reference in New Issue
Block a user