mirror of
https://github.com/BoostIo/Boostnote
synced 2025-12-15 18:56:22 +00:00
Key入力追加
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import React, { PropTypes} from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { CREATE_MODE, IDLE_MODE, NEW } from 'boost/actions'
|
||||
import { CREATE_MODE, EDIT_MODE, IDLE_MODE, NEW } from 'boost/actions'
|
||||
// import UserNavigator from './HomePage/UserNavigator'
|
||||
import ArticleNavigator from './HomePage/ArticleNavigator'
|
||||
import ArticleTopBar from './HomePage/ArticleTopBar'
|
||||
@@ -8,24 +8,102 @@ import ArticleList from './HomePage/ArticleList'
|
||||
import ArticleDetail from './HomePage/ArticleDetail'
|
||||
import _ from 'lodash'
|
||||
import keygen from 'boost/keygen'
|
||||
import { isModalOpen, closeModal } from 'boost/modal'
|
||||
|
||||
const TEXT_FILTER = 'TEXT_FILTER'
|
||||
const FOLDER_FILTER = 'FOLDER_FILTER'
|
||||
const TAG_FILTER = 'TAG_FILTER'
|
||||
|
||||
class HomePage extends React.Component {
|
||||
componentDidMount () {
|
||||
this.listener = (e) => this.handleKeyDown(e)
|
||||
window.addEventListener('keydown', this.listener)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
window.removeEventListener('keydown', this.listener)
|
||||
}
|
||||
|
||||
handleKeyDown (e) {
|
||||
if (isModalOpen() && e.keyCode === 27) {
|
||||
closeModal()
|
||||
return
|
||||
}
|
||||
|
||||
let { status } = this.props
|
||||
let { nav, top, list, detail } = this.refs
|
||||
|
||||
if (top.isInputFocused() && !e.metaKey) {
|
||||
if (e.keyCode === 13 || e.keyCode === 27) top.blurInput()
|
||||
return
|
||||
}
|
||||
|
||||
switch (status.mode) {
|
||||
case CREATE_MODE:
|
||||
case EDIT_MODE:
|
||||
if (e.keyCode === 27) {
|
||||
detail.handleCancelButtonClick()
|
||||
}
|
||||
if (e.keyCode === 13 && e.metaKey) {
|
||||
detail.handleSaveButtonClick()
|
||||
}
|
||||
break
|
||||
case IDLE_MODE:
|
||||
if (e.keyCode === 69) {
|
||||
detail.handleEditButtonClick()
|
||||
}
|
||||
if (e.keyCode === 68) {
|
||||
detail.handleDeleteButtonClick()
|
||||
}
|
||||
|
||||
// `detail`の`openDeleteConfirmMenu`の時。
|
||||
if (detail.state.openDeleteConfirmMenu) {
|
||||
if (e.keyCode === 27) {
|
||||
detail.handleDeleteCancleButtonClick()
|
||||
}
|
||||
if (e.keyCode === 13 && e.metaKey) {
|
||||
detail.handleDeleteConfirmButtonClick()
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// `detail`の`openDeleteConfirmMenu`が`true`なら呼ばれない。
|
||||
if (e.keyCode === 27) {
|
||||
top.focusInput()
|
||||
}
|
||||
|
||||
if (e.keyCode === 38) {
|
||||
list.selectPriorArticle()
|
||||
}
|
||||
|
||||
if (e.keyCode === 40) {
|
||||
list.selectNextArticle()
|
||||
}
|
||||
|
||||
if (e.keyCode === 13 && e.metaKey) {
|
||||
nav.handleNewPostButtonClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
let { dispatch, status, articles, activeArticle, folders } = this.props
|
||||
let { dispatch, status, articles, activeArticle, folders, filters } = this.props
|
||||
|
||||
return (
|
||||
<div className='HomePage'>
|
||||
<ArticleNavigator
|
||||
ref='nav'
|
||||
dispatch={dispatch}
|
||||
folders={folders}
|
||||
status={status}
|
||||
/>
|
||||
<ArticleTopBar dispatch={dispatch} status={status}/>
|
||||
<ArticleTopBar
|
||||
ref='top'
|
||||
dispatch={dispatch}
|
||||
status={status}
|
||||
/>
|
||||
<ArticleList
|
||||
ref='list'
|
||||
dispatch={dispatch}
|
||||
folders={folders}
|
||||
articles={articles}
|
||||
@@ -33,10 +111,12 @@ class HomePage extends React.Component {
|
||||
activeArticle={activeArticle}
|
||||
/>
|
||||
<ArticleDetail
|
||||
ref='detail'
|
||||
dispatch={dispatch}
|
||||
activeArticle={activeArticle}
|
||||
folders={folders}
|
||||
status={status}
|
||||
filters={filters}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
@@ -139,7 +219,12 @@ function remap (state) {
|
||||
folders,
|
||||
status,
|
||||
articles,
|
||||
activeArticle
|
||||
activeArticle,
|
||||
filters: {
|
||||
folder: folderFilters,
|
||||
tag: tagFilters,
|
||||
text: textFilters
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +238,12 @@ HomePage.propTypes = {
|
||||
articles: PropTypes.array,
|
||||
activeArticle: PropTypes.shape(),
|
||||
dispatch: PropTypes.func,
|
||||
folders: PropTypes.array
|
||||
folders: PropTypes.array,
|
||||
filters: PropTypes.shape({
|
||||
folder: PropTypes.array,
|
||||
tag: PropTypes.array,
|
||||
text: PropTypes.array
|
||||
})
|
||||
}
|
||||
|
||||
export default connect(remap)(HomePage)
|
||||
|
||||
@@ -4,7 +4,7 @@ import _ from 'lodash'
|
||||
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, updateArticle, destroyArticle } from 'boost/actions'
|
||||
import { IDLE_MODE, CREATE_MODE, EDIT_MODE, switchMode, switchArticle, switchFolder, updateArticle, destroyArticle } from 'boost/actions'
|
||||
import aceModes from 'boost/ace-modes'
|
||||
import Select from 'react-select'
|
||||
import linkState from 'boost/linkState'
|
||||
@@ -38,6 +38,11 @@ export default class ArticleDetail extends React.Component {
|
||||
console.log('receive props')
|
||||
})
|
||||
}
|
||||
|
||||
let isEdit = nextProps.status.mode === EDIT_MODE || nextProps.status.mode === CREATE_MODE
|
||||
if (isEdit && this.state.openDeleteConfirmMenu) {
|
||||
this.setState({openDeleteConfirmMenu: false})
|
||||
}
|
||||
}
|
||||
|
||||
renderEmpty () {
|
||||
@@ -135,7 +140,7 @@ export default class ArticleDetail extends React.Component {
|
||||
}
|
||||
|
||||
handleSaveButtonClick (e) {
|
||||
let { dispatch, folders } = this.props
|
||||
let { dispatch, folders, filters } = this.props
|
||||
let article = this.state.article
|
||||
let newArticle = Object.assign({}, article)
|
||||
|
||||
@@ -147,6 +152,8 @@ export default class ArticleDetail extends React.Component {
|
||||
|
||||
dispatch(updateArticle(newArticle))
|
||||
dispatch(switchMode(IDLE_MODE))
|
||||
if (filters.folder.length !== 0) dispatch(switchFolder(folder.name))
|
||||
dispatch(switchArticle(newArticle.key))
|
||||
}
|
||||
|
||||
handleFolderKeyChange (e) {
|
||||
|
||||
@@ -15,6 +15,26 @@ export default class ArticleList extends React.Component {
|
||||
clearInterval(this.refreshTimer)
|
||||
}
|
||||
|
||||
selectPriorArticle () {
|
||||
let { articles, activeArticle, dispatch } = this.props
|
||||
let targetIndex = articles.indexOf(activeArticle) - 1
|
||||
let targetArticle = articles[targetIndex]
|
||||
|
||||
if (targetArticle != null) {
|
||||
dispatch(switchArticle(targetArticle.key))
|
||||
}
|
||||
}
|
||||
|
||||
selectNextArticle () {
|
||||
let { articles, activeArticle, dispatch } = this.props
|
||||
let targetIndex = articles.indexOf(activeArticle) + 1
|
||||
let targetArticle = articles[targetIndex]
|
||||
|
||||
if (targetArticle != null) {
|
||||
dispatch(switchArticle(targetArticle.key))
|
||||
}
|
||||
}
|
||||
|
||||
handleArticleClick (article) {
|
||||
let { dispatch } = this.props
|
||||
return function (e) {
|
||||
|
||||
@@ -7,6 +7,7 @@ import Preferences from 'boost/components/modal/Preferences'
|
||||
import CreateNewFolder from 'boost/components/modal/CreateNewFolder'
|
||||
|
||||
import remote from 'remote'
|
||||
let userName = remote.getGlobal('process').env.USER
|
||||
|
||||
export default class ArticleNavigator extends React.Component {
|
||||
handlePreferencesButtonClick (e) {
|
||||
@@ -51,8 +52,6 @@ export default class ArticleNavigator extends React.Component {
|
||||
)
|
||||
})
|
||||
|
||||
let userName = remote.getGlobal('process').env.USER
|
||||
|
||||
return (
|
||||
<div className='ArticleNavigator'>
|
||||
<div className='userInfo'>
|
||||
|
||||
@@ -4,16 +4,29 @@ import ExternalLink from 'boost/components/ExternalLink'
|
||||
import { setSearchFilter } from 'boost/actions'
|
||||
|
||||
export default class ArticleTopBar extends React.Component {
|
||||
isInputFocused () {
|
||||
return document.activeElement === ReactDOM.findDOMNode(this.refs.searchInput)
|
||||
}
|
||||
|
||||
focusInput () {
|
||||
ReactDOM.findDOMNode(this.refs.searchInput).focus()
|
||||
}
|
||||
|
||||
blurInput () {
|
||||
ReactDOM.findDOMNode(this.refs.searchInput).blur()
|
||||
}
|
||||
|
||||
handleSearchChange (e) {
|
||||
let { dispatch } = this.props
|
||||
|
||||
dispatch(setSearchFilter(e.target.value))
|
||||
}
|
||||
|
||||
handleSearchClearButton (e) {
|
||||
let { dispatch } = this.props
|
||||
|
||||
dispatch(setSearchFilter(''))
|
||||
ReactDOM.findDOMNode(this.refs.searchInput).focus()
|
||||
this.focusInput()
|
||||
}
|
||||
|
||||
render () {
|
||||
|
||||
@@ -7,6 +7,8 @@ import HomePage from './HomePage'
|
||||
// import auth from 'boost/auth'
|
||||
import store from 'boost/store'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { isModalOpen, closeModal } from 'boost/modal'
|
||||
import { IDLE_MODE, CREATE_MODE, EDIT_MODE } from 'boost/actions'
|
||||
require('../styles/main/index.styl')
|
||||
|
||||
let routes = (
|
||||
@@ -25,21 +27,4 @@ ReactDOM.render((
|
||||
), el, function () {
|
||||
let loadingCover = document.getElementById('loadingCover')
|
||||
loadingCover.parentNode.removeChild(loadingCover)
|
||||
|
||||
// Refresh user information
|
||||
// if (auth.user() != null) {
|
||||
// fetchCurrentUser()
|
||||
// .then(function (res) {
|
||||
// let user = res.body
|
||||
// store.dispatch(updateUser(user))
|
||||
// })
|
||||
// .catch(function (err) {
|
||||
// if (err.status === 401) {
|
||||
// auth.clear()
|
||||
// if (window != null) window.location.reload()
|
||||
// }
|
||||
// console.error(err.message)
|
||||
// console.log('Fetch failed')
|
||||
// })
|
||||
// }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user