mirror of
https://github.com/BoostIo/Boostnote
synced 2026-02-11 15:01:41 +00:00
renewal key binding
This commit is contained in:
@@ -14,11 +14,12 @@ import TagSelect from 'browser/components/TagSelect'
|
||||
import ModeSelect from 'browser/components/ModeSelect'
|
||||
import activityRecord from 'browser/lib/activityRecord'
|
||||
import ShareButton from './ShareButton'
|
||||
import { openModal } from 'browser/lib/modal'
|
||||
import { openModal, isModalOpen } from 'browser/lib/modal'
|
||||
import DeleteArticleModal from '../../modal/DeleteArticleModal'
|
||||
|
||||
const electron = require('electron')
|
||||
const clipboard = electron.clipboard
|
||||
const ipc = electron.ipcRenderer
|
||||
|
||||
const OSX = process.platform === 'darwin'
|
||||
const BRAND_COLOR = '#18AF90'
|
||||
@@ -88,6 +89,23 @@ export default class ArticleDetail extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.saveHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleSaveButtonClick()
|
||||
}
|
||||
this.deleteHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleDeleteButtonClick()
|
||||
}
|
||||
this.togglePreviewHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleTogglePreviewButtonClick()
|
||||
}
|
||||
this.editHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.editArticle()
|
||||
}
|
||||
|
||||
this.state = {
|
||||
article: Object.assign({content: ''}, props.activeArticle),
|
||||
previewMode: false,
|
||||
@@ -102,10 +120,20 @@ export default class ArticleDetail extends React.Component {
|
||||
this.shareDropdownInterceptor = e => {
|
||||
e.stopPropagation()
|
||||
}
|
||||
|
||||
ipc.on('detail-save', this.saveHandler)
|
||||
ipc.on('detail-delete', this.deleteHandler)
|
||||
ipc.on('detail-toggle-preview', this.togglePreviewHandler)
|
||||
ipc.on('detail-edit', this.editHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
clearInterval(this.refreshTimer)
|
||||
|
||||
ipc.removeListener('detail-save', this.saveHandler)
|
||||
ipc.removeListener('detail-delete', this.deleteHandler)
|
||||
ipc.removeListener('detail-toggle-preview', this.togglePreviewHandler)
|
||||
ipc.removeListener('detail-on', this.editHandler)
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
@@ -127,6 +155,12 @@ export default class ArticleDetail extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
editArticle () {
|
||||
ReactDOM.findDOMNode(this.refs.title).focus()
|
||||
ReactDOM.findDOMNode(this.refs.title).select()
|
||||
this.setState({previewMode: false})
|
||||
}
|
||||
|
||||
cacheArticle () {
|
||||
let { dispatch } = this.props
|
||||
|
||||
|
||||
@@ -7,13 +7,25 @@ import FolderMark from 'browser/components/FolderMark'
|
||||
import TagLink from './TagLink'
|
||||
import _ from 'lodash'
|
||||
|
||||
const electron = require('electron')
|
||||
const remote = electron.remote
|
||||
const ipc = electron.ipcRenderer
|
||||
|
||||
export default class ArticleList extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.focusHandler = e => this.focus()
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.refreshTimer = setInterval(() => this.forceUpdate(), 60 * 1000)
|
||||
ipc.on('list-focus', this.focusHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
clearInterval(this.refreshTimer)
|
||||
ipc.removeListener('list-focus', this.focusHandler)
|
||||
}
|
||||
|
||||
componentDidUpdate () {
|
||||
@@ -36,6 +48,10 @@ export default class ArticleList extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
focus () {
|
||||
ReactDOM.findDOMNode(this).focus()
|
||||
}
|
||||
|
||||
// 移動ができなかったらfalseを返す:
|
||||
selectPriorArticle () {
|
||||
let { articles, activeArticle, dispatch } = this.props
|
||||
@@ -68,6 +84,41 @@ export default class ArticleList extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleArticleListKeyDown (e) {
|
||||
console.log(e.keyCode)
|
||||
if (e.metaKey || e.ctrlKey) return true
|
||||
|
||||
if (e.keyCode === 65) {
|
||||
e.preventDefault()
|
||||
remote.getCurrentWebContents().send('nav-new-post')
|
||||
}
|
||||
|
||||
if (e.keyCode === 68) {
|
||||
e.preventDefault()
|
||||
remote.getCurrentWebContents().send('detail-delete')
|
||||
}
|
||||
|
||||
if (e.keyCode === 69) {
|
||||
e.preventDefault()
|
||||
remote.getCurrentWebContents().send('detail-edit')
|
||||
}
|
||||
|
||||
if (e.keyCode === 83) {
|
||||
e.preventDefault()
|
||||
remote.getCurrentWebContents().send('detail-save')
|
||||
}
|
||||
|
||||
if (e.keyCode === 38) {
|
||||
e.preventDefault()
|
||||
this.selectPriorArticle()
|
||||
}
|
||||
|
||||
if (e.keyCode === 40) {
|
||||
e.preventDefault()
|
||||
this.selectNextArticle()
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
let { articles, modified, activeArticle, folders } = this.props
|
||||
|
||||
@@ -130,7 +181,7 @@ export default class ArticleList extends React.Component {
|
||||
})
|
||||
|
||||
return (
|
||||
<div className='ArticleList'>
|
||||
<div tabIndex='1' onKeyDown={e => this.handleArticleListKeyDown(e)} className='ArticleList'>
|
||||
{articleElements}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { findWhere } from 'lodash'
|
||||
import { setSearchFilter, switchFolder, saveArticle } from '../actions'
|
||||
import { openModal } from 'browser/lib/modal'
|
||||
import { openModal, isModalOpen } from 'browser/lib/modal'
|
||||
import FolderMark from 'browser/components/FolderMark'
|
||||
import Preferences from '../modal/Preferences'
|
||||
import CreateNewFolder from '../modal/CreateNewFolder'
|
||||
import keygen from 'browser/lib/keygen'
|
||||
|
||||
const ipc = require('electron').ipcRenderer
|
||||
|
||||
const BRAND_COLOR = '#18AF90'
|
||||
|
||||
const preferenceTutorialElement = (
|
||||
@@ -58,6 +60,28 @@ 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,
|
||||
)
|
||||
|
||||
export default class ArticleNavigator extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.newPostHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleNewPostButtonClick(e)
|
||||
}
|
||||
this.newFolderHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleNewFolderButton(e)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
ipc.on('nav-new-post', this.newPostHandler)
|
||||
ipc.on('nav-new-folder', this.newFolderHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
ipc.removeListener('nav-new-post', this.newPostHandler)
|
||||
ipc.removeListener('nav-new-folder', this.newFolderHandler)
|
||||
}
|
||||
|
||||
handlePreferencesButtonClick (e) {
|
||||
openModal(Preferences)
|
||||
}
|
||||
@@ -136,7 +160,7 @@ export default class ArticleNavigator extends React.Component {
|
||||
<div className='controlSection'>
|
||||
<button onClick={e => this.handleNewPostButtonClick(e)} className='newPostBtn'>
|
||||
New Post
|
||||
<span className='tooltip'>Create a new Post ({process.platform === 'darwin' ? '⌘' : '^'} + Enter or a)</span>
|
||||
<span className='tooltip'>Create a new Post ({process.platform === 'darwin' ? '⌘' : '^'} + n)</span>
|
||||
</button>
|
||||
|
||||
{status.isTutorialOpen ? newPostTutorialElement : null}
|
||||
@@ -148,7 +172,7 @@ export default class ArticleNavigator extends React.Component {
|
||||
<div className='title'>Folders</div>
|
||||
<button onClick={e => this.handleNewFolderButton(e)} className='addBtn'>
|
||||
<i className='fa fa-fw fa-plus'/>
|
||||
<span className='tooltip'>Create a new folder</span>
|
||||
<span className='tooltip'>Create a new folder ({process.platform === 'darwin' ? '⌘' : '^'} + Shift + n)</span>
|
||||
</button>
|
||||
|
||||
{status.isTutorialOpen ? newFolderTutorialElement : null}
|
||||
|
||||
@@ -3,11 +3,13 @@ import ReactDOM from 'react-dom'
|
||||
import ExternalLink from 'browser/components/ExternalLink'
|
||||
import { setSearchFilter, clearSearch, toggleOnlyUnsavedFilter, toggleTutorial, saveAllArticles, switchArticle } from '../actions'
|
||||
import store from '../store'
|
||||
import { isModalOpen } from 'browser/lib/modal'
|
||||
|
||||
const electron = require('electron')
|
||||
const remote = electron.remote
|
||||
const Menu = remote.Menu
|
||||
const MenuItem = remote.MenuItem
|
||||
const ipc = electron.ipcRenderer
|
||||
|
||||
const OSX = process.platform === 'darwin'
|
||||
|
||||
@@ -64,6 +66,15 @@ export default class ArticleTopBar extends React.Component {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
|
||||
this.saveAllHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.handleSaveAllButtonClick(e)
|
||||
}
|
||||
this.focusSearchHandler = e => {
|
||||
if (isModalOpen()) return true
|
||||
this.focusInput(e)
|
||||
}
|
||||
|
||||
this.state = {
|
||||
isTooltipHidden: true,
|
||||
isLinksDropdownOpen: false
|
||||
@@ -87,11 +98,17 @@ export default class ArticleTopBar extends React.Component {
|
||||
}
|
||||
}
|
||||
document.addEventListener('click', this.hideLinksDropdown)
|
||||
|
||||
ipc.on('top-save-all', this.saveAllHandler)
|
||||
ipc.on('top-focus-search', this.focusSearchHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
document.removeEventListener('click', this.hideLinksDropdown)
|
||||
this.linksButton.removeEventListener('click', this.showLinksDropdown())
|
||||
|
||||
ipc.removeListener('top-save-all', this.saveAllHandler)
|
||||
ipc.removeListener('top-focus-search', this.focusSearchHandler)
|
||||
}
|
||||
|
||||
handleTooltipRequest (e) {
|
||||
@@ -112,10 +129,10 @@ export default class ArticleTopBar extends React.Component {
|
||||
dispatch(clearSearch())
|
||||
return
|
||||
}
|
||||
this.blurInput()
|
||||
}
|
||||
|
||||
focusInput () {
|
||||
console.log('focinp')
|
||||
this.searchInput.focus()
|
||||
}
|
||||
|
||||
@@ -145,6 +162,7 @@ export default class ArticleTopBar extends React.Component {
|
||||
let { dispatch } = this.props
|
||||
|
||||
dispatch(saveAllArticles())
|
||||
remote.getCurrentWebContents().send('list-focus')
|
||||
}
|
||||
|
||||
handleSaveMenuButtonClick (e) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { PropTypes} from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { toggleTutorial } from '../actions'
|
||||
import ArticleNavigator from './ArticleNavigator'
|
||||
import ArticleTopBar from './ArticleTopBar'
|
||||
@@ -26,15 +27,14 @@ class HomePage extends React.Component {
|
||||
}
|
||||
|
||||
handleKeyDown (e) {
|
||||
let cmdOrCtrl = process.platform === 'darwin' ? e.metaKey : e.ctrlKey
|
||||
|
||||
if (isModalOpen()) {
|
||||
if (e.keyCode === 27) closeModal()
|
||||
return
|
||||
}
|
||||
|
||||
let { status, dispatch } = this.props
|
||||
let { nav, top, list, detail } = this.refs
|
||||
let { top, list } = this.refs
|
||||
let listElement = ReactDOM.findDOMNode(list)
|
||||
|
||||
if (status.isTutorialOpen) {
|
||||
dispatch(toggleTutorial())
|
||||
@@ -42,28 +42,24 @@ class HomePage extends React.Component {
|
||||
return
|
||||
}
|
||||
|
||||
// Search inputがfocusされていたら大体のキー入力は無視される。
|
||||
if (top.isInputFocused() && !(e.metaKey || e.ctrlKey)) {
|
||||
if (e.keyCode === 13 || e.keyCode === 27) top.escape()
|
||||
if (e.keyCode === 13 && top.isInputFocused()) {
|
||||
listElement.focus()
|
||||
return
|
||||
}
|
||||
if (e.keyCode === 27 && top.isInputFocused()) {
|
||||
if (status.search.length > 0) top.escape()
|
||||
else listElement.focus()
|
||||
return
|
||||
}
|
||||
|
||||
// `detail`の`openDeleteConfirmMenu`が`true`なら呼ばれない。
|
||||
if (e.keyCode === 27 || (e.keyCode === 70 && cmdOrCtrl)) {
|
||||
top.focusInput()
|
||||
}
|
||||
|
||||
if (e.keyCode === 38) {
|
||||
list.selectPriorArticle()
|
||||
}
|
||||
|
||||
if (e.keyCode === 40) {
|
||||
list.selectNextArticle()
|
||||
}
|
||||
|
||||
if (e.keyCode === 78 && cmdOrCtrl) {
|
||||
nav.handleNewPostButtonClick()
|
||||
e.preventDefault()
|
||||
// Search inputがfocusされていたら大体のキー入力は無視される。
|
||||
if (e.keyCode === 27) {
|
||||
if (document.activeElement !== listElement) {
|
||||
listElement.focus()
|
||||
} else {
|
||||
top.focusInput()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user