mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
[PLT-3377] Open up a shortcuts dialog instead of printing help text (#7064)
* open up a shortcuts dialog instead of printing help text * Updating UI for keyboard shortcuts modal * update PR per PLT-7284 * fix typo error * fix mixed up shortcut keys * move to client side * fix shortcuts list, remove unused function and revert server side code for autocompletion * remove quick team switcher
This commit is contained in:
@@ -4,23 +4,10 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/mattermost/platform/model"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestShortcutsCommand(t *testing.T) {
|
||||
th := Setup().InitBasic()
|
||||
Client := th.BasicClient
|
||||
channel := th.BasicChannel
|
||||
|
||||
rs := Client.Must(Client.Command(channel.Id, "/shortcuts ")).Data.(*model.CommandResponse)
|
||||
if !strings.Contains(rs.Text, "CTRL") {
|
||||
t.Fatal("failed to display shortcuts")
|
||||
}
|
||||
|
||||
rs = Client.Must(Client.Command(channel.Id, "/shortcuts mac")).Data.(*model.CommandResponse)
|
||||
if !strings.Contains(rs.Text, "CMD") {
|
||||
t.Fatal("failed to display Mac shortcuts")
|
||||
}
|
||||
th.BasicClient.Must(th.BasicClient.Command(th.BasicChannel.Id, "/shortcuts"))
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/platform/model"
|
||||
goi18n "github.com/nicksnyder/go-i18n/i18n"
|
||||
)
|
||||
@@ -37,61 +34,9 @@ func (me *ShortcutsProvider) GetCommand(T goi18n.TranslateFunc) *model.Command {
|
||||
}
|
||||
|
||||
func (me *ShortcutsProvider) DoCommand(args *model.CommandArgs, message string) *model.CommandResponse {
|
||||
shortcutIds := [...]string{
|
||||
"api.command_shortcuts.header",
|
||||
// Nav shortcuts
|
||||
"api.command_shortcuts.nav.header",
|
||||
"api.command_shortcuts.nav.prev",
|
||||
"api.command_shortcuts.nav.next",
|
||||
"api.command_shortcuts.nav.unread_prev",
|
||||
"api.command_shortcuts.nav.unread_next",
|
||||
"api.command_shortcuts.nav.switcher",
|
||||
"api.command_shortcuts.nav.direct_messages_menu",
|
||||
"api.command_shortcuts.nav.settings",
|
||||
"api.command_shortcuts.nav.recent_mentions",
|
||||
// Files shortcuts
|
||||
"api.command_shortcuts.files.header",
|
||||
"api.command_shortcuts.files.upload",
|
||||
// Msg shortcuts
|
||||
"api.command_shortcuts.msgs.header",
|
||||
"api.command_shortcuts.msgs.mark_as_read",
|
||||
"api.command_shortcuts.msgs.reprint_prev",
|
||||
"api.command_shortcuts.msgs.reprint_next",
|
||||
"api.command_shortcuts.msgs.edit",
|
||||
"api.command_shortcuts.msgs.reply",
|
||||
"api.command_shortcuts.msgs.comp_username",
|
||||
"api.command_shortcuts.msgs.comp_channel",
|
||||
"api.command_shortcuts.msgs.comp_emoji",
|
||||
// Browser shortcuts
|
||||
"api.command_shortcuts.browser.header",
|
||||
"api.command_shortcuts.browser.channel_prev",
|
||||
"api.command_shortcuts.browser.channel_next",
|
||||
"api.command_shortcuts.browser.font_increase",
|
||||
"api.command_shortcuts.browser.font_decrease",
|
||||
"api.command_shortcuts.browser.highlight_prev",
|
||||
"api.command_shortcuts.browser.highlight_next",
|
||||
"api.command_shortcuts.browser.newline",
|
||||
// This command is handled client-side and shouldn't hit the server.
|
||||
return &model.CommandResponse{
|
||||
Text: args.T("api.command_shortcuts.unsupported.app_error"),
|
||||
ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL,
|
||||
}
|
||||
|
||||
var osDependentWords map[string]interface{}
|
||||
if strings.Contains(message, "mac") {
|
||||
osDependentWords = map[string]interface{}{
|
||||
"CmdOrCtrl": args.T("api.command_shortcuts.cmd"),
|
||||
"ChannelPrevCmd": args.T("api.command_shortcuts.browser.channel_prev.cmd_mac"),
|
||||
"ChannelNextCmd": args.T("api.command_shortcuts.browser.channel_next.cmd_mac"),
|
||||
}
|
||||
} else {
|
||||
osDependentWords = map[string]interface{}{
|
||||
"CmdOrCtrl": args.T("api.command_shortcuts.ctrl"),
|
||||
"ChannelPrevCmd": args.T("api.command_shortcuts.browser.channel_prev.cmd"),
|
||||
"ChannelNextCmd": args.T("api.command_shortcuts.browser.channel_next.cmd"),
|
||||
}
|
||||
}
|
||||
|
||||
var buffer bytes.Buffer
|
||||
for _, element := range shortcutIds {
|
||||
buffer.WriteString(args.T(element, osDependentWords))
|
||||
}
|
||||
|
||||
return &model.CommandResponse{ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, Text: buffer.String()}
|
||||
}
|
||||
|
||||
144
i18n/en.json
144
i18n/en.json
@@ -843,157 +843,17 @@
|
||||
"id": "api.command_settings.unsupported.app_error",
|
||||
"translation": "The settings command is not supported on your device"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.channel_next",
|
||||
"translation": "{{.ChannelNextCmd}}: Next channel in your history\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.channel_next.cmd",
|
||||
"translation": "ALT+RIGHT"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.channel_next.cmd_mac",
|
||||
"translation": "CMD+]"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.channel_prev",
|
||||
"translation": "{{.ChannelPrevCmd}}: Previous channel in your history\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.channel_prev.cmd",
|
||||
"translation": "ALT+LEFT"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.channel_prev.cmd_mac",
|
||||
"translation": "CMD+["
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.font_decrease",
|
||||
"translation": "{{.CmdOrCtrl}}+MINUS: Decrease font size (zoom out)\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.font_increase",
|
||||
"translation": "{{.CmdOrCtrl}}+PLUS: Increase font size (zoom in)\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.header",
|
||||
"translation": "#### Built-in Browser Commands\n\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.highlight_next",
|
||||
"translation": "SHIFT+DOWN (in input field): Highlight text to the next line\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.highlight_prev",
|
||||
"translation": "SHIFT+UP (in input field): Highlight text to the previous line\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.browser.newline",
|
||||
"translation": "SHIFT+ENTER (in input field): Create a new line\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.cmd",
|
||||
"translation": "CMD"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.ctrl",
|
||||
"translation": "CTRL"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.desc",
|
||||
"translation": "Displays a list of keyboard shortcuts"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.files.header",
|
||||
"translation": "#### Files\n\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.files.upload",
|
||||
"translation": "{{.CmdOrCtrl}}+U: Upload file(s)\n\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.header",
|
||||
"translation": "### Keyboard Shortcuts\n\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.comp_channel",
|
||||
"translation": "~[character]+TAB: Autocomplete channel beginning with [character]\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.comp_emoji",
|
||||
"translation": ":[character]+TAB: Autocomplete emoji beginning with [character]\n\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.comp_username",
|
||||
"translation": "@[character]+TAB: Autocomplete @username beginning with [character]\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.edit",
|
||||
"translation": "UP (in empty input field): Edit your last message in the current channel\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.header",
|
||||
"translation": "#### Messages\n\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.mark_as_read",
|
||||
"translation": "ESC: Mark all messages in the current channel as read\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.reply",
|
||||
"translation": "SHIFT+UP (in empty input field): Reply to the most recent message in the current channel\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.reprint_next",
|
||||
"translation": "{{.CmdOrCtrl}}+DOWN (in empty input field): Reprint the next message or slash command you entered\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.msgs.reprint_prev",
|
||||
"translation": "{{.CmdOrCtrl}}+UP (in empty input field): Reprint the previous message or slash command you entered\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.name",
|
||||
"translation": "shortcuts"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.direct_messages_menu",
|
||||
"translation": "{{.CmdOrCtrl}}+SHIFT+K: Open direct messages menu\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.header",
|
||||
"translation": "#### Navigation\n\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.next",
|
||||
"translation": "ALT+DOWN: Next channel or direct message in left hand sidebar\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.prev",
|
||||
"translation": "ALT+UP: Previous channel or direct message in left hand sidebar\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.recent_mentions",
|
||||
"translation": "{{.CmdOrCtrl}}+SHIFT+M: Open recent mentions\n\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.settings",
|
||||
"translation": "{{.CmdOrCtrl}}+SHIFT+A: Open account settings\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.switcher",
|
||||
"translation": "{{.CmdOrCtrl}}+K: Open a quick channel switcher dialog\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.switcher_team",
|
||||
"translation": "{{.CmdOrCtrl}}+ALT+K: Open a quick team switcher dialog\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.unread_next",
|
||||
"translation": "ALT+SHIFT+DOWN: Next channel or direct message in left hand sidebar with unread messages\n"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shortcuts.nav.unread_prev",
|
||||
"translation": "ALT+SHIFT+UP: Previous channel or direct message in left hand sidebar with unread messages\n"
|
||||
"id": "api.command_shortcuts.unsupported.app_error",
|
||||
"translation": "The shortcuts command is not supported on your device"
|
||||
},
|
||||
{
|
||||
"id": "api.command_shrug.desc",
|
||||
|
||||
@@ -66,12 +66,10 @@ export function executeCommand(message, args, success, error) {
|
||||
const err = {message: Utils.localizeMessage('create_post.shortcutsNotSupported', 'Keyboard shortcuts are not supported on your device')};
|
||||
error(err);
|
||||
return;
|
||||
} else if (Utils.isMac()) {
|
||||
msg += ' mac';
|
||||
} else if (message.indexOf('mac') !== -1) {
|
||||
msg = '/shortcuts';
|
||||
}
|
||||
break;
|
||||
|
||||
GlobalActions.showShortcutsModal();
|
||||
return;
|
||||
case '/leave': {
|
||||
// /leave command not supported in reply threads.
|
||||
if (args.channel_id && (args.root_id || args.parent_id)) {
|
||||
|
||||
@@ -211,6 +211,13 @@ export function showAccountSettingsModal() {
|
||||
});
|
||||
}
|
||||
|
||||
export function showShortcutsModal() {
|
||||
AppDispatcher.handleViewAction({
|
||||
type: ActionTypes.TOGGLE_SHORTCUTS_MODAL,
|
||||
value: true
|
||||
});
|
||||
}
|
||||
|
||||
export function showDeletePostModal(post, commentCount = 0) {
|
||||
AppDispatcher.handleViewAction({
|
||||
type: ActionTypes.TOGGLE_DELETE_POST_MODAL,
|
||||
|
||||
@@ -466,20 +466,8 @@ export default class CreatePost extends React.Component {
|
||||
showShortcuts(e) {
|
||||
if ((e.ctrlKey || e.metaKey) && e.keyCode === Constants.KeyCodes.FORWARD_SLASH) {
|
||||
e.preventDefault();
|
||||
const args = {};
|
||||
args.channel_id = this.state.channelId;
|
||||
args.team_id = TeamStore.getCurrentId();
|
||||
ChannelActions.executeCommand(
|
||||
'/shortcuts',
|
||||
args,
|
||||
null,
|
||||
(err) => {
|
||||
this.setState({
|
||||
serverError: err.message,
|
||||
submitting: false
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
GlobalActions.showShortcutsModal();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ import InviteMemberModal from 'components/invite_member_modal.jsx';
|
||||
import LeaveTeamModal from 'components/leave_team_modal.jsx';
|
||||
import ResetStatusModal from 'components/reset_status_modal';
|
||||
import LeavePrivateChannelModal from 'components/modals/leave_private_channel_modal.jsx';
|
||||
import ShortcutsModal from 'components/shortcuts_modal.jsx';
|
||||
|
||||
import iNoBounce from 'inobounce';
|
||||
import * as UserAgent from 'utils/user_agent.jsx';
|
||||
@@ -233,6 +234,7 @@ export default class NeedsTeam extends React.Component {
|
||||
<RemovedFromChannelModal/>
|
||||
<ResetStatusModal/>
|
||||
<LeavePrivateChannelModal/>
|
||||
<ShortcutsModal/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
394
webapp/components/shortcuts_modal.jsx
Normal file
394
webapp/components/shortcuts_modal.jsx
Normal file
@@ -0,0 +1,394 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import Constants from 'utils/constants.jsx';
|
||||
import * as Utils from 'utils/utils.jsx';
|
||||
|
||||
import ModalStore from 'stores/modal_store.jsx';
|
||||
|
||||
import {intlShape, injectIntl, defineMessages} from 'react-intl';
|
||||
import {Modal} from 'react-bootstrap';
|
||||
import React from 'react';
|
||||
|
||||
const allShortcuts = defineMessages({
|
||||
mainHeader: {
|
||||
id: 'shortcuts.header',
|
||||
defaultMessage: 'Keyboard Shortcuts'
|
||||
},
|
||||
navHeader: {
|
||||
id: 'shortcuts.nav.header',
|
||||
defaultMessage: 'Navigation'
|
||||
},
|
||||
navPrev: {
|
||||
default: {
|
||||
id: 'shortcuts.nav.prev',
|
||||
defaultMessage: 'Previous channel:\tAlt|Up'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.nav.prev.mac',
|
||||
defaultMessage: 'Previous channel:\t⌥|Up'
|
||||
}
|
||||
},
|
||||
navNext: {
|
||||
default: {
|
||||
id: 'shortcuts.nav.next',
|
||||
defaultMessage: 'Next channel:\tAlt|Down'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.nav.next.mac',
|
||||
defaultMessage: 'Next channel:\t⌥|Down'
|
||||
}
|
||||
},
|
||||
navUnreadPrev: {
|
||||
default: {
|
||||
id: 'shortcuts.nav.unread_prev',
|
||||
defaultMessage: 'Previous unread channel:\tAlt|Shift|Up'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.nav.unread_prev.mac',
|
||||
defaultMessage: 'Previous unread channel:\t⌥|Shift|Up'
|
||||
}
|
||||
},
|
||||
navUnreadNext: {
|
||||
default: {
|
||||
id: 'shortcuts.nav.unread_next',
|
||||
defaultMessage: 'Next unread channel:\tAlt|Shift|Down'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.nav.unread_next.mac',
|
||||
defaultMessage: 'Next unread channel:\t⌥|Shift|Down'
|
||||
}
|
||||
},
|
||||
navSwitcher: {
|
||||
default: {
|
||||
id: 'shortcuts.nav.switcher',
|
||||
defaultMessage: 'Quick channel switcher:\tCtrl|K'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.nav.switcher.mac',
|
||||
defaultMessage: 'Quick channel switcher:\t⌘|K'
|
||||
}
|
||||
},
|
||||
navDMMenu: {
|
||||
default: {
|
||||
id: 'shortcuts.nav.direct_messages_menu',
|
||||
defaultMessage: 'Direct messages menu:\tCtrl|Shift|K'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.nav.direct_messages_menu.mac',
|
||||
defaultMessage: 'Direct messages menu:\t⌘|Shift|K'
|
||||
}
|
||||
},
|
||||
navSettings: {
|
||||
default: {
|
||||
id: 'shortcuts.nav.settings',
|
||||
defaultMessage: 'Account settings:\tCtrl|Shift|A'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.nav.settings.mac',
|
||||
defaultMessage: 'Account settings:\t⌘|Shift|A'
|
||||
}
|
||||
},
|
||||
navMentions: {
|
||||
default: {
|
||||
id: 'shortcuts.nav.mentions',
|
||||
defaultMessage: 'Recent mentions:\tCtrl|Shift|M'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.nav.mentions.mac',
|
||||
defaultMessage: 'Recent mentions:\t⌘|Shift|M'
|
||||
}
|
||||
},
|
||||
msgHeader: {
|
||||
id: 'shortcuts.msgs.header',
|
||||
defaultMessage: 'Messages'
|
||||
},
|
||||
msgMarkAsRead: {
|
||||
id: 'shortcuts.msgs.mark_as_read',
|
||||
defaultMessage: 'Mark current channel as read:\tEsc'
|
||||
},
|
||||
msgInputHeader: {
|
||||
id: 'shortcuts.msgs.input.header',
|
||||
defaultMessage: 'Works inside an empty input field'
|
||||
},
|
||||
msgEdit: {
|
||||
id: 'shortcuts.msgs.edit',
|
||||
defaultMessage: 'Edit last message in channel:\tUp'
|
||||
},
|
||||
msgReply: {
|
||||
id: 'shortcuts.msgs.reply',
|
||||
defaultMessage: 'Reply to last message in channel:\tShift|Up'
|
||||
},
|
||||
msgReprintPrev: {
|
||||
default: {
|
||||
id: 'shortcuts.msgs.reprint_prev',
|
||||
defaultMessage: 'Reprint previous message:\tCtrl|Up'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.msgs.reprint_prev.mac',
|
||||
defaultMessage: 'Reprint previous message:\t⌘|Up'
|
||||
}
|
||||
},
|
||||
msgReprintNext: {
|
||||
default: {
|
||||
id: 'shortcuts.msgs.reprint_next',
|
||||
defaultMessage: 'Reprint next message:\tCtrl|Down'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.msgs.reprint_next.mac',
|
||||
defaultMessage: 'Reprint next message:\t⌘|Down'
|
||||
}
|
||||
},
|
||||
msgCompHeader: {
|
||||
id: 'shortcuts.msgs.comp.header',
|
||||
defaultMessage: 'Autocomplete'
|
||||
},
|
||||
msgCompUsername: {
|
||||
id: 'shortcuts.msgs.comp.username',
|
||||
defaultMessage: 'Username:\t@|[a-z]|Tab'
|
||||
},
|
||||
msgCompChannel: {
|
||||
id: 'shortcuts.msgs.comp.channel',
|
||||
defaultMessage: 'Channel:\t~|[a-z]|Tab'
|
||||
},
|
||||
msgCompEmoji: {
|
||||
id: 'shortcuts.msgs.comp.emoji',
|
||||
defaultMessage: 'Emoji:\t:|[a-z]|Tab'
|
||||
},
|
||||
filesHeader: {
|
||||
id: 'shortcuts.files.header',
|
||||
defaultMessage: 'Files'
|
||||
},
|
||||
filesUpload: {
|
||||
default: {
|
||||
id: 'shortcuts.files.upload',
|
||||
defaultMessage: 'Upload files:\tCtrl|U'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.files.upload.mac',
|
||||
defaultMessage: 'Upload files:\t⌘|U'
|
||||
}
|
||||
},
|
||||
browserHeader: {
|
||||
id: 'shortcuts.browser.header',
|
||||
defaultMessage: 'Built-in Browser Commands'
|
||||
},
|
||||
browserChannelPrev: {
|
||||
default: {
|
||||
id: 'shortcuts.browser.channel_prev',
|
||||
defaultMessage: 'Back in history:\tAlt|Left'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.browser.channel_prev.mac',
|
||||
defaultMessage: 'Back in history:\t⌘|['
|
||||
}
|
||||
},
|
||||
browserChannelNext: {
|
||||
default: {
|
||||
id: 'shortcuts.browser.channel_next',
|
||||
defaultMessage: 'Forward in history:\tAlt|Right'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.browser.channel_next.mac',
|
||||
defaultMessage: 'Forward in history:\t⌘|]'
|
||||
}
|
||||
},
|
||||
browserFontIncrease: {
|
||||
default: {
|
||||
id: 'shortcuts.browser.font_increase',
|
||||
defaultMessage: 'Zoom in:\tCtrl|+'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.browser.font_increase.mac',
|
||||
defaultMessage: 'Zoom in:\t⌘|+'
|
||||
}
|
||||
},
|
||||
browserFontDecrease: {
|
||||
default: {
|
||||
id: 'shortcuts.browser.font_decrease',
|
||||
defaultMessage: 'Zoom out:\tCtrl|-'
|
||||
},
|
||||
mac: {
|
||||
id: 'shortcuts.browser.font_decrease.mac',
|
||||
defaultMessage: 'Zoom out:\t⌘|-'
|
||||
}
|
||||
},
|
||||
browserInputHeader: {
|
||||
id: 'shortcuts.browser.input.header',
|
||||
defaultMessage: 'Works inside an input field'
|
||||
},
|
||||
browserHighlightPrev: {
|
||||
id: 'shortcuts.browser.highlight_prev',
|
||||
defaultMessage: 'Highlight text to the previous line:\tShift|Up'
|
||||
},
|
||||
browserHighlightNext: {
|
||||
id: 'shortcuts.browser.highlight_next',
|
||||
defaultMessage: 'Highlight text to the next line:\tShift|Down'
|
||||
},
|
||||
browserNewline: {
|
||||
id: 'shortcuts.browser.newline',
|
||||
defaultMessage: 'Create a new line:\tShift|Enter'
|
||||
},
|
||||
info: {
|
||||
id: 'shortcuts.info',
|
||||
defaultMessage: 'Begin a message with / for a list of all the commands at your disposal.'
|
||||
}
|
||||
});
|
||||
|
||||
class ShortcutsModal extends React.PureComponent {
|
||||
static propTypes = {
|
||||
intl: intlShape.isRequired
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
show: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
ModalStore.addModalListener(Constants.ActionTypes.TOGGLE_SHORTCUTS_MODAL, this.handleToggle);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
ModalStore.removeModalListener(Constants.ActionTypes.TOGGLE_SHORTCUTS_MODAL, this.handleToggle);
|
||||
}
|
||||
|
||||
handleToggle = (value) => {
|
||||
this.setState({
|
||||
show: value
|
||||
});
|
||||
}
|
||||
|
||||
handleHide = () => {
|
||||
this.setState({show: false});
|
||||
}
|
||||
|
||||
getShortcuts(isMac) {
|
||||
const shortcuts = {};
|
||||
Object.keys(allShortcuts).forEach((s) => {
|
||||
if (isMac && allShortcuts[s].mac) {
|
||||
shortcuts[s] = allShortcuts[s].mac;
|
||||
} else if (!isMac && allShortcuts[s].default) {
|
||||
shortcuts[s] = allShortcuts[s].default;
|
||||
} else {
|
||||
shortcuts[s] = allShortcuts[s];
|
||||
}
|
||||
});
|
||||
|
||||
return shortcuts;
|
||||
}
|
||||
|
||||
render() {
|
||||
const shortcuts = this.getShortcuts(Utils.isMac());
|
||||
|
||||
const {formatMessage} = this.props.intl;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
dialogClassName='shortcuts-modal'
|
||||
show={this.state.show}
|
||||
onHide={this.handleHide}
|
||||
onExited={this.handleHide}
|
||||
>
|
||||
<div className='shortcuts-content'>
|
||||
<Modal.Header closeButton={true}>
|
||||
<Modal.Title>
|
||||
<strong>{formatMessage(shortcuts.mainHeader)}</strong>
|
||||
</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body ref='modalBody'>
|
||||
<div className='row'>
|
||||
<div className='col-sm-4'>
|
||||
<div className='section'>
|
||||
<div>
|
||||
<h4 className='section-title'><strong>{formatMessage(shortcuts.navHeader)}</strong></h4>
|
||||
{renderShortcut(formatMessage(shortcuts.navPrev))}
|
||||
{renderShortcut(formatMessage(shortcuts.navNext))}
|
||||
{renderShortcut(formatMessage(shortcuts.navUnreadPrev))}
|
||||
{renderShortcut(formatMessage(shortcuts.navUnreadNext))}
|
||||
{renderShortcut(formatMessage(shortcuts.navSwitcher))}
|
||||
{renderShortcut(formatMessage(shortcuts.navDMMenu))}
|
||||
{renderShortcut(formatMessage(shortcuts.navSettings))}
|
||||
{renderShortcut(formatMessage(shortcuts.navMentions))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='col-sm-4'>
|
||||
<div className='section'>
|
||||
<div>
|
||||
<h4 className='section-title'><strong>{formatMessage(shortcuts.msgHeader)}</strong></h4>
|
||||
{renderShortcut(formatMessage(shortcuts.msgMarkAsRead))}
|
||||
<span><strong>{formatMessage(shortcuts.msgInputHeader)}</strong></span>
|
||||
<div className='subsection'>
|
||||
{renderShortcut(formatMessage(shortcuts.msgEdit))}
|
||||
{renderShortcut(formatMessage(shortcuts.msgReply))}
|
||||
{renderShortcut(formatMessage(shortcuts.msgReprintPrev))}
|
||||
{renderShortcut(formatMessage(shortcuts.msgReprintNext))}
|
||||
</div>
|
||||
<span><strong>{formatMessage(shortcuts.msgCompHeader)}</strong></span>
|
||||
<div className='subsection'>
|
||||
{renderShortcut(formatMessage(shortcuts.msgCompUsername))}
|
||||
{renderShortcut(formatMessage(shortcuts.msgCompChannel))}
|
||||
{renderShortcut(formatMessage(shortcuts.msgCompEmoji))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='col-sm-4'>
|
||||
<div className='section'>
|
||||
<div>
|
||||
<h4 className='section-title'><strong>{formatMessage(shortcuts.filesHeader)}</strong></h4>
|
||||
{renderShortcut(formatMessage(shortcuts.filesUpload))}
|
||||
</div>
|
||||
<div className='section--lower'>
|
||||
<h4 className='section-title'><strong>{formatMessage(shortcuts.browserHeader)}</strong></h4>
|
||||
{renderShortcut(formatMessage(shortcuts.browserChannelPrev))}
|
||||
{renderShortcut(formatMessage(shortcuts.browserChannelNext))}
|
||||
{renderShortcut(formatMessage(shortcuts.browserFontIncrease))}
|
||||
{renderShortcut(formatMessage(shortcuts.browserFontDecrease))}
|
||||
<span><strong>{formatMessage(shortcuts.browserInputHeader)}</strong></span>
|
||||
<div className='subsection'>
|
||||
{renderShortcut(formatMessage(shortcuts.browserHighlightPrev))}
|
||||
{renderShortcut(formatMessage(shortcuts.browserHighlightNext))}
|
||||
{renderShortcut(formatMessage(shortcuts.browserNewline))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='info__label'>{formatMessage(shortcuts.info)}</div>
|
||||
</Modal.Body>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function renderShortcut(text) {
|
||||
if (!text) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const shortcut = text.split('\t');
|
||||
const description = <span>{shortcut[0]}</span>;
|
||||
const keys = shortcut[1].split('|').map((key) =>
|
||||
<span
|
||||
className='shortcut-key'
|
||||
key={key}
|
||||
>
|
||||
{key}
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className='shortcut-line'>
|
||||
{description}
|
||||
{keys}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default injectIntl(ShortcutsModal);
|
||||
@@ -51,6 +51,7 @@ export default class SidebarHeaderDropdown extends React.Component {
|
||||
this.showGetTeamInviteLinkModal = this.showGetTeamInviteLinkModal.bind(this);
|
||||
this.showTeamMembersModal = this.showTeamMembersModal.bind(this);
|
||||
this.hideTeamMembersModal = this.hideTeamMembersModal.bind(this);
|
||||
this.showShortcutsModal = this.showShortcutsModal.bind(this);
|
||||
|
||||
this.onTeamChange = this.onTeamChange.bind(this);
|
||||
|
||||
@@ -109,6 +110,13 @@ export default class SidebarHeaderDropdown extends React.Component {
|
||||
GlobalActions.showAccountSettingsModal();
|
||||
}
|
||||
|
||||
showShortcutsModal(e) {
|
||||
e.preventDefault();
|
||||
this.setState({showDropdown: false});
|
||||
|
||||
GlobalActions.showShortcutsModal();
|
||||
}
|
||||
|
||||
showAddUsersToTeamModal(e) {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -495,18 +503,18 @@ export default class SidebarHeaderDropdown extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
const keyboardShortcutsLink = (
|
||||
const keyboardShortcuts = (
|
||||
<li>
|
||||
<Link
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
to='https://about.mattermost.com/default-keyboard_shortcut_link/'
|
||||
<a
|
||||
id='keyboardShortcuts'
|
||||
href='#'
|
||||
onClick={this.showShortcutsModal}
|
||||
>
|
||||
<FormattedMessage
|
||||
id='navbar_dropdown.keyboardShortcuts'
|
||||
defaultMessage='Keyboard Shortcuts'
|
||||
/>
|
||||
</Link>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -616,7 +624,7 @@ export default class SidebarHeaderDropdown extends React.Component {
|
||||
{sysAdminLink}
|
||||
{helpDivider}
|
||||
{helpLink}
|
||||
{keyboardShortcutsLink}
|
||||
{keyboardShortcuts}
|
||||
{reportLink}
|
||||
{nativeAppLink}
|
||||
{about}
|
||||
|
||||
@@ -2105,6 +2105,54 @@
|
||||
"setting_upload.import": "Import",
|
||||
"setting_upload.noFile": "No file selected.",
|
||||
"setting_upload.select": "Select file",
|
||||
"shortcuts.info": "Begin a message with / for a list of all the commands at your disposal.",
|
||||
"shortcuts.header": "Keyboard Shortcuts",
|
||||
"shortcuts.nav.header": "Navigation",
|
||||
"shortcuts.nav.prev": "Previous channel:\tAlt|Up",
|
||||
"shortcuts.nav.prev.mac": "Previous channel:\t⌥|Up",
|
||||
"shortcuts.nav.next": "Next channel:\tAlt|Down",
|
||||
"shortcuts.nav.next.mac": "Next channel:\t⌥|Down",
|
||||
"shortcuts.nav.unread_prev": "Previous unread channel:\tAlt|Shift|Up",
|
||||
"shortcuts.nav.unread_prev.mac": "Previous unread channel:\t⌥|Shift|Up",
|
||||
"shortcuts.nav.unread_next": "Next unread channel:\tAlt|Shift|Down",
|
||||
"shortcuts.nav.unread_next.mac": "Next unread channel:\t⌥|Shift|Down",
|
||||
"shortcuts.nav.switcher": "Quick channel switcher:\tCtrl|K",
|
||||
"shortcuts.nav.switcher.mac": "Quick channel switcher:\t⌘|K",
|
||||
"shortcuts.nav.direct_messages_menu": "Direct messages menu:\tCtrl|Shift|K",
|
||||
"shortcuts.nav.direct_messages_menu.mac": "Direct messages menu:\t⌘|Shift|K",
|
||||
"shortcuts.nav.settings": "Account settings:\tCtrl|Shift|A",
|
||||
"shortcuts.nav.settings.mac": "Account settings:\t⌘|Shift|A",
|
||||
"shortcuts.nav.recent_mentions": "Recent mentions:\tCtrl|Shift|M",
|
||||
"shortcuts.nav.recent_mentions.mac": "Recent mentions:\t⌘|Shift|M",
|
||||
"shortcuts.msgs.header": "Messages",
|
||||
"shortcuts.msgs.mark_as_read": "Mark current channel as read:\tEsc",
|
||||
"shortcuts.msgs.input.header": "Works inside an empty input field",
|
||||
"shortcuts.msgs.edit": "Edit last message in channel:\tUp",
|
||||
"shortcuts.msgs.reply": "Reply to last message in channel:\tShift|Up",
|
||||
"shortcuts.msgs.reprint_prev": "Reprint previous message:\tCtrl|Up",
|
||||
"shortcuts.msgs.reprint_prev.mac": "Reprint previous message:\t⌘|Up",
|
||||
"shortcuts.msgs.reprint_next": "Reprint next message:\tCtrl|Down",
|
||||
"shortcuts.msgs.reprint_next.mac": "Reprint next message:\t⌘|Down",
|
||||
"shortcuts.msgs.comp.header": "Autocomplete",
|
||||
"shortcuts.msgs.comp.username": "Username:\t@|[a-z]|Tab",
|
||||
"shortcuts.msgs.comp.channel": "Channel:\t~|[a-z]|Tab",
|
||||
"shortcuts.msgs.comp.emoji": "Emoji:\t:|[a-z]|Tab",
|
||||
"shortcuts.files.header": "Files",
|
||||
"shortcuts.files.upload": "Upload files:\tCtrl|U",
|
||||
"shortcuts.files.upload.mac": "Upload files:\t⌘|U",
|
||||
"shortcuts.browser.header": "Built-in Browser Commands",
|
||||
"shortcuts.browser.channel_prev": "Back in history:\tAlt|Left",
|
||||
"shortcuts.browser.channel_prev.mac": "Back in history:\t⌘|[",
|
||||
"shortcuts.browser.channel_next": "Forward in history:\tAlt|Right",
|
||||
"shortcuts.browser.channel_next.mac": "Forward in history:\t⌘|]",
|
||||
"shortcuts.browser.font_increase": "Zoom in:\tCtrl|+",
|
||||
"shortcuts.browser.font_increase.mac": "Zoom in:\t⌘|+",
|
||||
"shortcuts.browser.font_decrease": "Zoom out:\tCtrl|-",
|
||||
"shortcuts.browser.font_decrease.mac": "Zoom out:\t⌘|-",
|
||||
"shortcuts.browser.input.header": "Works inside an input field",
|
||||
"shortcuts.browser.highlight_prev": "Highlight text to the previous line:\tShift|Up",
|
||||
"shortcuts.browser.highlight_next": "Highlight text to the next line:\tShift|Down",
|
||||
"shortcuts.browser.newline": "Create a new line:\tShift|Enter",
|
||||
"sidebar.channels": "PUBLIC CHANNELS",
|
||||
"sidebar.createChannel": "Create new public channel",
|
||||
"sidebar.createGroup": "Create new private channel",
|
||||
|
||||
@@ -11,5 +11,6 @@
|
||||
@import 'loading';
|
||||
@import 'print';
|
||||
@import 'settings';
|
||||
@import 'shortcuts-modal';
|
||||
@import 'signup';
|
||||
@import 'statistics';
|
||||
|
||||
77
webapp/sass/routes/_shortcuts-modal.scss
Normal file
77
webapp/sass/routes/_shortcuts-modal.scss
Normal file
@@ -0,0 +1,77 @@
|
||||
@charset 'UTF-8';
|
||||
|
||||
.app__body {
|
||||
.modal {
|
||||
.shortcuts-modal {
|
||||
margin-top: 50px;
|
||||
width: 1100px;
|
||||
|
||||
.shortcuts-content {
|
||||
.modal-header {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: inherit;
|
||||
padding: 40px 40px 20px;
|
||||
|
||||
.close {
|
||||
color: inherit;
|
||||
font-size: 28px;
|
||||
font-weight: normal;
|
||||
right: 35px;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
color: inherit;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
max-height: calc(100vh - 67px);
|
||||
padding: 0 40px 20px;
|
||||
}
|
||||
|
||||
.section {
|
||||
> div {
|
||||
&:first-child {
|
||||
margin-bottom: 2.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.shortcut-line {
|
||||
margin: 17px 0;
|
||||
|
||||
span {
|
||||
&:first-child {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.shortcut-key {
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
margin: 5px 0 5px 5px;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 18px;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
|
||||
.subsection {
|
||||
border-left: 2px solid;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.info__label {
|
||||
margin: 35px 0 10px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ class ModalStoreClass extends EventEmitter {
|
||||
|
||||
switch (type) {
|
||||
case ActionTypes.TOGGLE_ACCOUNT_SETTINGS_MODAL:
|
||||
case ActionTypes.TOGGLE_SHORTCUTS_MODAL:
|
||||
case ActionTypes.TOGGLE_IMPORT_THEME_MODAL:
|
||||
case ActionTypes.TOGGLE_INVITE_MEMBER_MODAL:
|
||||
case ActionTypes.TOGGLE_LEAVE_TEAM_MODAL:
|
||||
|
||||
@@ -168,6 +168,7 @@ export const ActionTypes = keyMirror({
|
||||
USER_TYPING: null,
|
||||
|
||||
TOGGLE_ACCOUNT_SETTINGS_MODAL: null,
|
||||
TOGGLE_SHORTCUTS_MODAL: null,
|
||||
TOGGLE_IMPORT_THEME_MODAL: null,
|
||||
TOGGLE_INVITE_MEMBER_MODAL: null,
|
||||
TOGGLE_LEAVE_TEAM_MODAL: null,
|
||||
|
||||
@@ -603,7 +603,7 @@ export function applyTheme(theme) {
|
||||
changeCss('.app__body .attachment__content', 'background:' + theme.centerChannelBg);
|
||||
changeCss('body.app__body', 'scrollbar-face-color:' + theme.centerChannelBg);
|
||||
changeCss('body.app__body', 'scrollbar-track-color:' + theme.centerChannelBg);
|
||||
changeCss('.app__body .post-list__new-messages-below', 'color:' + theme.centerChannelBg);
|
||||
changeCss('.app__body .shortcut-key, .app__body .post-list__new-messages-below', 'color:' + theme.centerChannelBg);
|
||||
changeCss('.app__body .emoji-picker, .app__body .emoji-picker__search', 'background:' + theme.centerChannelBg);
|
||||
changeCss('.app__body .nav-tabs, .app__body .nav-tabs > li.active > a', 'background:' + theme.centerChannelBg);
|
||||
}
|
||||
@@ -616,7 +616,7 @@ export function applyTheme(theme) {
|
||||
changeCss('.app__body .channel-header__icon svg', 'fill:' + changeOpacity(theme.centerChannelColor, 0.4));
|
||||
changeCss('.app__body .modal .status .offline--icon, .app__body .channel-header__links .icon, .app__body .sidebar--right .sidebar--right__subheader .usage__icon, .app__body .more-modal__header svg, .app__body .icon--body', 'fill:' + theme.centerChannelColor);
|
||||
changeCss('@media(min-width: 768px){.app__body .post:hover .post__header .col__reply, .app__body .post.post--hovered .post__header .col__reply', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
|
||||
changeCss('.app__body .sidebar--right .sidebar--right__header, .app__body .channel-header, .app__body .nav-tabs > li > a:hover, .app__body .nav-tabs, .app__body .nav-tabs > li.active > a, .app__body .nav-tabs, .app__body .nav-tabs > li.active > a:focus, .app__body .nav-tabs, .app__body .nav-tabs > li.active > a:hover, .app__body .post .dropdown-menu a, .sidebar--left, .app__body .suggestion-list__content .command', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
|
||||
changeCss('.app__body .modal .shortcuts-modal .subsection, .app__body .sidebar--right .sidebar--right__header, .app__body .channel-header, .app__body .nav-tabs > li > a:hover, .app__body .nav-tabs, .app__body .nav-tabs > li.active > a, .app__body .nav-tabs, .app__body .nav-tabs > li.active > a:focus, .app__body .nav-tabs, .app__body .nav-tabs > li.active > a:hover, .app__body .post .dropdown-menu a, .sidebar--left, .app__body .suggestion-list__content .command', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
|
||||
changeCss('.app__body .post.post--system .post__body, .app__body .modal .channel-switch-modal .modal-header .close', 'color:' + changeOpacity(theme.centerChannelColor, 0.6));
|
||||
changeCss('.app__body .nav-tabs, .app__body .nav-tabs > li.active > a, pp__body .input-group-addon, .app__body .app__content, .app__body .post-create__container .post-create-body .btn-file, .app__body .post-create__container .post-create-footer .msg-typing, .app__body .suggestion-list__content .command, .app__body .modal .modal-content, .app__body .dropdown-menu, .app__body .popover, .app__body .mentions__name, .app__body .tip-overlay, .app__body .form-control[disabled], .app__body .form-control[readonly], .app__body fieldset[disabled] .form-control', 'color:' + theme.centerChannelColor);
|
||||
changeCss('.app__body .post .post__link', 'color:' + changeOpacity(theme.centerChannelColor, 0.65));
|
||||
@@ -628,7 +628,7 @@ export function applyTheme(theme) {
|
||||
changeCss('.app__body .dropdown-menu, .app__body .popover ', 'box-shadow: 0 17px 50px 0 ' + changeOpacity(theme.centerChannelColor, 0.1) + ', 0 12px 15px 0 ' + changeOpacity(theme.centerChannelColor, 0.1));
|
||||
changeCss('.app__body .dropdown-menu, .app__body .popover ', '-moz-box-shadow: 0 17px 50px 0 ' + changeOpacity(theme.centerChannelColor, 0.1) + ', 0 12px 15px 0 ' + changeOpacity(theme.centerChannelColor, 0.1));
|
||||
changeCss('.app__body .dropdown-menu, .app__body .popover ', '-webkit-box-shadow: 0 17px 50px 0 ' + changeOpacity(theme.centerChannelColor, 0.1) + ', 0 12px 15px 0 ' + changeOpacity(theme.centerChannelColor, 0.1));
|
||||
changeCss('.app__body .post__body hr, .app__body .loading-screen .loading__content .round, .app__body .tutorial__circles .circle', 'background:' + theme.centerChannelColor);
|
||||
changeCss('.app__body .shortcut-key, .app__body .post__body hr, .app__body .loading-screen .loading__content .round, .app__body .tutorial__circles .circle', 'background:' + theme.centerChannelColor);
|
||||
changeCss('.app__body .channel-header .heading', 'color:' + theme.centerChannelColor);
|
||||
changeCss('.app__body .markdown__table tbody tr:nth-child(2n)', 'background:' + changeOpacity(theme.centerChannelColor, 0.07));
|
||||
changeCss('.app__body .channel-header__info>div.dropdown .header-dropdown__icon', 'color:' + changeOpacity(theme.centerChannelColor, 0.8));
|
||||
|
||||
Reference in New Issue
Block a user