feat(keybindings): Show all keybindings in prefs

This commit is contained in:
Ben Gotow 2015-12-01 18:31:12 -08:00
parent 465d60489f
commit 092956b379
5 changed files with 149 additions and 45 deletions

View file

@ -5,14 +5,63 @@ fs = require 'fs'
{RetinaImg, Flexbox} = require 'nylas-component-kit'
DisplayedKeybindings = [
['application:new-message', 'New Message'],
['application:reply', 'Reply'],
['application:reply-all', 'Reply All'],
['application:forward', 'Forward'],
['application:focus-search', 'Search'],
['application:change-category', 'Change Folder / Labels'],
['core:select-item', 'Select Focused Item'],
['application:star-item', 'Star Focused Item'],
{
title: 'Application',
items: [
['application:new-message', 'New Message'],
['application:focus-search', 'Search'],
]
},
{
title: 'Actions',
items: [
['application:reply', 'Reply'],
['application:reply-all', 'Reply All'],
['application:forward', 'Forward'],
['application:archive-item', 'Archive'],
['application:delete-item', 'Trash'],
['core:remove-from-view', 'Remove from view'],
['application:star-item', 'Star'],
['application:change-category', 'Change Folder / Labels'],
['application:mark-as-read', 'Mark as read'],
['application:mark-as-unread', 'Mark as unread'],
['application:mark-important', 'Mark as important (Gmail)'],
['application:mark-unimportant', 'Mark as unimportant (Gmail)'],
['application:remove-and-previous', 'Remove from view and previous'],
['application:remove-and-next', 'Remove from view and next'],
]
},
{
title: 'Navigation',
items: [
['application:pop-sheet', 'Return to conversation list'],
['core:focus-item', 'Open selected conversation'],
['core:previous-item', 'Move to newer conversation'],
['core:next-item', 'Move to older conversation'],
]
},
{
title: 'Selection',
items: [
['core:select-item', 'Select conversation'],
['multiselect-list:select-all', 'Select all conversations'],
['multiselect-list:deselect-all', 'Deselect all conversations'],
['thread-list:select-read', 'Select all read conversations'],
['thread-list:select-unread', 'Select all unread conversations'],
['thread-list:select-starred', 'Select all starred conversations'],
['thread-list:select-unstarred', 'Select all unstarred conversations'],
]
},
{
title: 'Jumping',
items: [
['navigation:go-to-inbox', 'Go to "Inbox"'],
['navigation:go-to-starred', 'Go to "Starred"'],
['navigation:go-to-sent', 'Go to "Sent Mail"'],
['navigation:go-to-drafts', 'Go to "Drafts"'],
['navigation:go-to-all', 'Go to "All Mail"'],
]
}
]
class PreferencesKeymaps extends React.Component
@ -43,17 +92,18 @@ class PreferencesKeymaps extends React.Component
_getStateFromKeymaps: =>
bindings = {}
for [command, label] in DisplayedKeybindings
bindings[command] = NylasEnv.keymaps.findKeyBindings(command: command, target: document.body) || []
for section in DisplayedKeybindings
for [command, label] in section.items
bindings[command] = NylasEnv.keymaps.findKeyBindings(command: command, target: document.body) || []
bindings
render: =>
<div className="container-keymaps">
<section>
<h2>Shortcuts</h2>
<Flexbox className="shortcut shortcut-select">
<div className="shortcut-name">Keyboard shortcut set:</div>
<div className="shortcut-value">
<Flexbox className="shortcut-presets">
<div className="col-left">Keyboard shortcut set:</div>
<div className="col-right">
<select
style={margin:0}
value={@props.config.get('core.keymapTemplate')}
@ -64,7 +114,9 @@ class PreferencesKeymaps extends React.Component
</select>
</div>
</Flexbox>
{@_renderBindings()}
{
DisplayedKeybindings.map(@_renderBindingsSection)
}
</section>
<section>
<h2>Customization</h2>
@ -73,32 +125,60 @@ class PreferencesKeymaps extends React.Component
</section>
</div>
_renderBindingsSection: (section) =>
<section>
<div className="shortcut-section-title">{section.title}</div>
{
section.items.map(@_renderBindingFor)
}
</section>
_renderBindingFor: ([command, label]) =>
descriptions = []
if @state.bindings[command]
for binding in @state.bindings[command]
descriptions.push(@_formatKeystrokes(binding.keystrokes))
descriptions.push(binding.keystrokes)
if descriptions.length is 0
value = 'None'
else
value = _.uniq(descriptions).join(', ')
value = _.uniq(descriptions).map(@_renderKeystrokes)
<Flexbox className="shortcut" key={command}>
<div className="shortcut-name">{label}</div>
<div className="shortcut-value">{value}</div>
<div className="col-left shortcut-name">{label}</div>
<div className="col-right">{value}</div>
</Flexbox>
_renderBindings: =>
DisplayedKeybindings.map(@_renderBindingFor)
_renderKeystrokes: (keystrokes) =>
elements = []
keystrokes = keystrokes.split(' ')
_formatKeystrokes: (keystrokes) ->
for keystroke, idx in keystrokes
elements.push <span>{@_formatKeystrokes(keystroke)}</span>
elements.push <span className="then"> then </span> unless idx is keystrokes.length - 1
<span className="shortcut-value">{elements}</span>
_formatKeystrokes: (original) =>
if process.platform is 'win32'
# On Windows, display cmd-shift-c
return keystrokes
return original
else
# On Mac and Linux, display ⌘⇧C
return keystrokes.replace(/-/gi,'').replace(/cmd/gi, '⌘').replace(/alt/gi, '⌥').replace(/shift/gi, '⇧').replace(/ctrl/gi, '^').toUpperCase()
# Replace "cmd" => ⌘, etc.
modifiers = [[/-(?!$)/gi,''], [/cmd/gi, '⌘'], [/alt/gi, '⌥'], [/shift/gi, '⇧'], [/ctrl/gi, '^']]
clean = original
for [regexp, char] in modifiers
clean = clean.replace(regexp, char)
# ⌘⇧c => ⌘⇧C
if clean isnt original
clean = clean.toUpperCase()
# backspace => Backspace
if original.length > 1 and clean is original
clean = clean[0].toUpperCase() + clean[1..-1]
return clean
_onShowUserKeymaps: =>
keymapsFile = NylasEnv.keymaps.getUserKeymapPath()

View file

@ -140,24 +140,49 @@
.container-keymaps {
max-width: 450px;
.col-left {
text-align: right;
flex: 1;
margin-right: 20px;
}
.col-right {
text-align: left;
flex: 1;
select {
width: 75%;
}
}
.shortcut-presets {
padding: 5px 0 20px 0;
}
.shortcut-section-title {
border-bottom:1px solid @border-color-divider;
margin: @padding-large-vertical * 1.5 0;
}
.shortcut {
padding: 3px 0;
&.shortcut-select {
padding: 5px 0 20px 0;
select {
width: 75%;
}
}
.shortcut-name {
text-align: right;
flex: 1;
margin-right: 20px;
}
color: @text-color-very-subtle;
.shortcut-value {
text-align: left;
flex: 1;
font-family: monospace;
font-weight: 600;
color: @text-color;
.then {
font-family: @font-family-base;
color: @text-color-very-subtle;
font-weight: 400;
font-size: 0.9em;
padding-left:3px;
padding-right:3px;
}
&:after {
content: ", "
}
&:last-child:after {
content: "";
}
}
}
}

View file

@ -27,8 +27,6 @@
'o': 'core:focus-item'
'p': 'message-list:previous-message'
'n': 'message-list:next-message'
'`': 'thread-list:next-inbox'
'~': 'thread-list:previous-inbox'
### Application ###
'c': 'application:new-message'
@ -56,8 +54,6 @@
'f': 'application:forward'
'F': 'application:forward-new-window'
'N': 'application:update-conversation'
']': 'application:remove-and-previous'
'}': 'application:remove-and-previous'
'[': 'application:remove-and-next'

View file

@ -28,7 +28,10 @@ h2 {
font-size: @font-size-h2;
font-weight: @font-weight-blond;
}
h3 { font-size: @font-size-h3; }
h3 {
font-size: @font-size-h3;
font-weight: @font-weight-blond;
}
h4 { font-size: @font-size-h4; }
h5 { font-size: @font-size-h5; }
h6 { font-size: @font-size-h6; }

View file

@ -115,7 +115,7 @@
@font-size-h1: @font-size-base * 1.6; // 24px
@font-size-h2: @font-size-base * 1.6; // 24px
@font-size-h3: @font-size-base * 1.7; // 24px
@font-size-h3: @font-size-base * 1.4; // 24px
@font-size-h4: @font-size-base * 1.25; // 18px
@font-size-h5: @font-size-base;
@font-size-h6: @font-size-base * 0.85; // 12px