Skip to content
This repository has been archived by the owner on Jul 9, 2019. It is now read-only.

Commit

Permalink
add a help modal that explains all the shortcuts
Browse files Browse the repository at this point in the history
  • Loading branch information
grantcodes committed Dec 8, 2018
1 parent 3955f1b commit c23fb6a
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 33 deletions.
4 changes: 4 additions & 0 deletions src/actions/app.js
Expand Up @@ -23,3 +23,7 @@ export const focusComponent = component => ({
type: 'SET_FOCUSED_COMPONENT',
component,
})

export const toggleShortcutHelp = () => ({
type: 'TOGGLE_SHORTCUT_HELP',
})
13 changes: 10 additions & 3 deletions src/components/GlobalShotcuts/index.js
Expand Up @@ -7,6 +7,7 @@ import {
selectChannel,
toggleChannelsMenu,
focusComponent,
toggleShortcutHelp,
} from '../../actions'

class GlobalShortcutHandler extends Component {
Expand All @@ -16,7 +17,13 @@ class GlobalShortcutHandler extends Component {
}

handleShortcuts(action) {
const { channels, selectChannel, history, focusComponent } = this.props
const {
channels,
selectChannel,
history,
focusComponent,
toggleShortcutHelp,
} = this.props

if (action.indexOf('CHANNEL_') === 0) {
// Switch channel
Expand All @@ -40,7 +47,7 @@ class GlobalShortcutHandler extends Component {
focusComponent('channels')
break
case 'HELP':
alert("Sorry, I can't help you yet")
toggleShortcutHelp()
break
case 'KONAMI':
alert('Look at you. You are very clever')
Expand Down Expand Up @@ -69,7 +76,7 @@ const mapStateToProps = state => ({

const mapDispatchToProps = dispatch =>
bindActionCreators(
{ selectChannel, toggleChannelsMenu, focusComponent },
{ selectChannel, toggleChannelsMenu, focusComponent, toggleShortcutHelp },
dispatch
)

Expand Down
33 changes: 18 additions & 15 deletions src/components/SettingsModal/index.js
Expand Up @@ -35,49 +35,52 @@ class SettingsModal extends Component {
}

render() {
const { open } = this.state
const { classes, children, singleColumn, ...dialogProps } = this.props
return (
<Dialog
// fullScreen
open={this.state.open}
open={open}
onClose={this.handleClose}
transition={Transition}
TransitionComponent={Transition}
classes={{
root: this.props.classes.dialogRoot,
paper: this.props.classes.dialogPaper,
root: classes.dialogRoot,
paper: classes.dialogPaper,
}}
{...dialogProps}
>
<AppBar color="secondary" position="sticky">
<Toolbar>
<Typography
variant="h6"
color="inherit"
className={this.props.classes.title}
>
<Typography variant="h6" color="inherit" className={classes.title}>
{this.props.title}
</Typography>
<IconButton
className={this.props.classes.popupClose}
className={classes.popupClose}
onClick={this.handleClose}
>
<CloseIcon />
</IconButton>
</Toolbar>
</AppBar>
<div className={this.props.classes.wrapper}>
<DialogContent className={this.props.classes.content}>
{this.props.children}
<div className={classes.wrapper}>
<DialogContent
className={singleColumn ? classes.singleColumn : classes.twoColumns}
>
{children}
</DialogContent>
</div>
</Dialog>
)
}
}

SettingsModal.defaultProps = {}
SettingsModal.defaultProps = {
singleColumn: false,
}

SettingsModal.propTypes = {
title: PropTypes.string.isRequired,
onClose: PropTypes.func,
singleColumn: PropTypes.bool.isRequired,
}

export default withRouter(withStyles(styles)(SettingsModal))
5 changes: 4 additions & 1 deletion src/components/SettingsModal/style.js
Expand Up @@ -12,7 +12,10 @@ export default theme => ({
flex: 1,
fontWeight: 'normal',
},
content: {
singleColumn: {
display: 'block',
},
twoColumns: {
[theme.breakpoints.up('sm')]: {
display: 'flex',
flexWrap: 'wrap',
Expand Down
38 changes: 38 additions & 0 deletions src/components/ShortcutHelp/ShortcutTable.js
@@ -0,0 +1,38 @@
import React from 'react'
import Table from '@material-ui/core/Table'
import TableBody from '@material-ui/core/TableBody'
import TableCell from '@material-ui/core/TableCell'
import TableRow from '@material-ui/core/TableRow'
import Typography from '@material-ui/core/Typography'
import Chip from '@material-ui/core/Chip'

const ShortcutTable = ({ title, keys }) => (
<div>
<Typography
variant="subtitle1"
style={{ borderBottom: '1px solid', paddingLeft: 24 }}
>
{title}
</Typography>
<Table style={{ marginBottom: 40 }}>
<TableBody>
{keys.map(key => (
<TableRow key={`key-row-${title}-${key.name}`}>
<TableCell style={{ width: '15em' }}>{key.name}</TableCell>
<TableCell>
{key.shortcuts.map(key => (
<Chip
key={`key-row-${title}-${key.name}-key-${key}`}
label={key}
style={{ marginRight: 10 }}
/>
))}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
)

export default ShortcutTable
121 changes: 121 additions & 0 deletions src/components/ShortcutHelp/index.js
@@ -0,0 +1,121 @@
import React from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import SettingsModal from '../SettingsModal'
import { toggleShortcutHelp } from '../../actions'
import keymap from '../../modules/keymap'
import ShortcutTable from './ShortcutTable'

const globalKeys = [
{
name: 'Focus Channels List',
shortcuts: keymap.GLOBAL.FOCUS_CHANNEL_LIST,
},
{
name: 'Show Keyboard Shorcuts',
shortcuts: keymap.GLOBAL.HELP,
},
{
name: 'Open New Post Editor',
shortcuts: keymap.GLOBAL.NEW_POST,
},
{
name: 'Load Channel',
shortcuts: ['ctrl+1-9', 'meta+1-9', 'alt+1-9'],
},
]

const channelListKeys = [
{
name: 'Next Channel',
shortcuts: keymap.CHANNEL_LIST.NEXT,
},
{
name: 'Previous Channel',
shortcuts: keymap.CHANNEL_LIST.PREVIOUS,
},
{
name: 'Load Channel',
shortcuts: keymap.CHANNEL_LIST.SELECT_CHANNEL,
},
]

const channelKeys = [
{
name: 'Next Post',
shortcuts: keymap.TIMELINE.NEXT,
},
{
name: 'Previous Post',
shortcuts: keymap.TIMELINE.PREVIOUS,
},
{
name: 'Select Post',
shortcuts: keymap.TIMELINE.SELECT_POST,
},
{
name: 'Focus Channel List',
shortcuts: keymap.TIMELINE.FOCUS_CHANNEL_LIST,
},
{
name: 'Toggle Selected Post Read',
shortcuts: keymap.TIMELINE.MARK_READ,
},
]

const singlePostKeys = [
{
name: 'Next Post',
shortcuts: keymap.POST.NEXT,
},
{
name: 'Open Post Url',
shortcuts: keymap.POST.OPEN,
},
{
name: 'Toggle Post Read',
shortcuts: keymap.POST.TOGGLE_READ,
},
{
name: 'Back to Post List',
shortcuts: keymap.POST.TO_TIMELINE,
},
{
name: 'Scroll Up',
shortcuts: keymap.POST.SCROLL_UP,
},
{
name: 'Scroll Down',
shortcuts: keymap.POST.SCROLL_DOWN,
},
]

const ShortcutHelp = ({ open, toggleShortcutHelp }) => {
return (
<SettingsModal
title="Keyboard Controls"
maxWidth="lg"
open={open}
onClose={() => (open ? toggleShortcutHelp() : null)}
singleColumn
disableAutoFocus
>
<ShortcutTable title="Global Controls" keys={globalKeys} />
<ShortcutTable title="Channel List Controls" keys={channelListKeys} />
<ShortcutTable title="Channel Controls" keys={channelKeys} />
<ShortcutTable title="Post Controls" keys={singlePostKeys} />
</SettingsModal>
)
}

const mapStateToProps = state => ({
open: state.app.get('shortcutHelpOpen'),
})

const mapDispatchToProps = dispatch =>
bindActionCreators({ toggleShortcutHelp }, dispatch)

export default connect(
mapStateToProps,
mapDispatchToProps
)(ShortcutHelp)
2 changes: 2 additions & 0 deletions src/containers/App.js
Expand Up @@ -15,6 +15,7 @@ import Notification from '../components/Notification'
import MicropubEditor from '../components/MicropubEditorFull'
import ErrorBoundary from '../components/ErrorBoundary'
import GlobalShortcuts from '../components/GlobalShotcuts'
import ShortcutHelp from '../components/ShortcutHelp'
import keymap from '../modules/keymap'
import style from './style'

Expand Down Expand Up @@ -61,6 +62,7 @@ class App extends Component {
/>
<Route path="/editor" component={MicropubEditor} />
<Route path="/settings" component={AppSettings} />
<ShortcutHelp />
</Grid>
<Login />
<Notification />
Expand Down
23 changes: 9 additions & 14 deletions src/modules/keymap.js
Expand Up @@ -9,18 +9,18 @@ export default {
PREVIOUS: ['k', 'up'],
SELECT_POST: ['l', 'enter', 'right', 'v'],
FOCUS_CHANNEL_LIST: ['h', 'left'],
MARK_READ: 'm',
MARK_READ: ['m'],
},
POST: {
SCROLL_DOWN: 'j',
SCROLL_UP: 'k',
TO_TIMELINE: 'h',
NEXT: 'space',
OPEN: 'v',
TOGGLE_READ: 'm',
SCROLL_DOWN: ['j'],
SCROLL_UP: ['k'],
TO_TIMELINE: ['h'],
NEXT: ['space'],
OPEN: ['v'],
TOGGLE_READ: ['m'],
},
GLOBAL: {
KONAMI: 'up up down down left right left right b a',
KONAMI: ['up up down down left right left right b a'],
CHANNEL_1: ['ctrl+1', 'meta+1', 'alt+1'],
CHANNEL_2: ['ctrl+2', 'meta+2', 'alt+2'],
CHANNEL_3: ['ctrl+3', 'meta+3', 'alt+3'],
Expand All @@ -32,20 +32,15 @@ export default {
CHANNEL_9: ['ctrl+9', 'meta+9', 'alt+9'],
NEW_POST: ['ctrl+n', 'meta+n', 'alt+n'],
FOCUS_CHANNEL_LIST: ['c'],
HELP: '?',
HELP: ['?'],
},
}

/**
* TODO: Focus channel list or timeline on load
* TODO: Classic view needs to mark stuff as read
* TODO: Global keymapping for:
* Open notifications
* Mark channel read
* Jump to channel list
* Jump to timeline
* TODO: Gallery view controls
* TODO: Timeline view contols
* TODO: Map view controls
* TODO: Shortcuts help view to show what all the shortcuts do
*/
4 changes: 4 additions & 0 deletions src/reducers/app.js
Expand Up @@ -8,6 +8,7 @@ const defaultState = new Map({
timelineAfter: '',
notifications: [],
focusedComponent: null,
shortcutHelpOpen: false,
theme: localStorage.getItem('together-theme') || getTheme() || 'light',
})

Expand Down Expand Up @@ -53,6 +54,9 @@ export default (state = defaultState, payload) => {
case 'SET_FOCUSED_COMPONENT': {
return state.set('focusedComponent', payload.component)
}
case 'TOGGLE_SHORTCUT_HELP': {
return state.set('shortcutHelpOpen', !state.get('shortcutHelpOpen'))
}
default: {
return state
}
Expand Down

0 comments on commit c23fb6a

Please sign in to comment.