mirror of
https://github.com/discourse/discourse.git
synced 2025-06-07 09:04:41 +08:00
DEV: Normalize key modifier checks for keyboard shortcuts (#22451)
This introduces a PLATFORM_KEY_MODIFIER const that can be used both client and server side, to determine whether we should be using the Meta or Ctrl key based on whether the user is on Windows/Linux or Mac.
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||||
import {
|
import {
|
||||||
caretPosition,
|
caretPosition,
|
||||||
inCodeBlock,
|
inCodeBlock,
|
||||||
@ -180,15 +181,14 @@ class Toolbar {
|
|||||||
|
|
||||||
const title = I18n.t(button.title || `composer.${button.id}_title`);
|
const title = I18n.t(button.title || `composer.${button.id}_title`);
|
||||||
if (button.shortcut) {
|
if (button.shortcut) {
|
||||||
const mac = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
const shortcutTitle = `${translateModKey(
|
||||||
const mod = mac ? "Meta" : "Ctrl";
|
PLATFORM_KEY_MODIFIER + "+"
|
||||||
|
)}${translateModKey(button.shortcut)}`;
|
||||||
const shortcutTitle = `${translateModKey(mod + "+")}${translateModKey(
|
|
||||||
button.shortcut
|
|
||||||
)}`;
|
|
||||||
|
|
||||||
createdButton.title = `${title} (${shortcutTitle})`;
|
createdButton.title = `${title} (${shortcutTitle})`;
|
||||||
this.shortcuts[`${mod}+${button.shortcut}`.toLowerCase()] = createdButton;
|
this.shortcuts[
|
||||||
|
`${PLATFORM_KEY_MODIFIER}+${button.shortcut}`.toLowerCase()
|
||||||
|
] = createdButton;
|
||||||
} else {
|
} else {
|
||||||
createdButton.title = title;
|
createdButton.title = title;
|
||||||
}
|
}
|
||||||
@ -304,11 +304,9 @@ export default Component.extend(TextareaTextManipulation, {
|
|||||||
|
|
||||||
this._itsatrap.bind("tab", () => this.indentSelection("right"));
|
this._itsatrap.bind("tab", () => this.indentSelection("right"));
|
||||||
this._itsatrap.bind("shift+tab", () => this.indentSelection("left"));
|
this._itsatrap.bind("shift+tab", () => this.indentSelection("left"));
|
||||||
|
this._itsatrap.bind(`${PLATFORM_KEY_MODIFIER}+shift+.`, () =>
|
||||||
const mac = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
this.send("insertCurrentTime")
|
||||||
const mod = mac ? "meta" : "ctrl";
|
);
|
||||||
|
|
||||||
this._itsatrap.bind(`${mod}+shift+.`, () => this.send("insertCurrentTime"));
|
|
||||||
|
|
||||||
// disable clicking on links in the preview
|
// disable clicking on links in the preview
|
||||||
this.element
|
this.element
|
||||||
|
@ -33,6 +33,12 @@ export function clearExtraKeyboardShortcutHelp() {
|
|||||||
|
|
||||||
export { extraKeyboardShortcutsHelp as extraKeyboardShortcutsHelp };
|
export { extraKeyboardShortcutsHelp as extraKeyboardShortcutsHelp };
|
||||||
|
|
||||||
|
export const PLATFORM_KEY_MODIFIER = /Mac|iPod|iPhone|iPad/.test(
|
||||||
|
navigator.platform
|
||||||
|
)
|
||||||
|
? "meta"
|
||||||
|
: "ctrl";
|
||||||
|
|
||||||
const DEFAULT_BINDINGS = {
|
const DEFAULT_BINDINGS = {
|
||||||
"!": { postAction: "showFlags" },
|
"!": { postAction: "showFlags" },
|
||||||
"#": { handler: "goToPost", anonymous: true },
|
"#": { handler: "goToPost", anonymous: true },
|
||||||
|
@ -520,16 +520,18 @@ export function translateModKey(string) {
|
|||||||
// Apple device users are used to glyphs for shortcut keys
|
// Apple device users are used to glyphs for shortcut keys
|
||||||
if (isApple) {
|
if (isApple) {
|
||||||
string = string
|
string = string
|
||||||
.replace("Shift", "\u21E7")
|
.toLowerCase()
|
||||||
.replace("Meta", "\u2318")
|
.replace("shift", "\u21E7")
|
||||||
.replace("Alt", "\u2325")
|
.replace("meta", "\u2318")
|
||||||
|
.replace("alt", "\u2325")
|
||||||
.replace(/\+/g, "");
|
.replace(/\+/g, "");
|
||||||
} else {
|
} else {
|
||||||
string = string
|
string = string
|
||||||
.replace("Shift", I18n.t("shortcut_modifier_key.shift"))
|
.toLowerCase()
|
||||||
.replace("Ctrl", I18n.t("shortcut_modifier_key.ctrl"))
|
.replace("shift", I18n.t("shortcut_modifier_key.shift"))
|
||||||
.replace("Meta", I18n.t("shortcut_modifier_key.ctrl"))
|
.replace("ctrl", I18n.t("shortcut_modifier_key.ctrl"))
|
||||||
.replace("Alt", I18n.t("shortcut_modifier_key.alt"));
|
.replace("meta", I18n.t("shortcut_modifier_key.ctrl"))
|
||||||
|
.replace("alt", I18n.t("shortcut_modifier_key.alt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
triggerKeyEvent,
|
triggerKeyEvent,
|
||||||
visit,
|
visit,
|
||||||
} from "@ember/test-helpers";
|
} from "@ember/test-helpers";
|
||||||
|
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||||
import { toggleCheckDraftPopup } from "discourse/services/composer";
|
import { toggleCheckDraftPopup } from "discourse/services/composer";
|
||||||
import { cloneJSON } from "discourse-common/lib/object";
|
import { cloneJSON } from "discourse-common/lib/object";
|
||||||
import TopicFixtures from "discourse/tests/fixtures/topic";
|
import TopicFixtures from "discourse/tests/fixtures/topic";
|
||||||
@ -217,10 +218,9 @@ acceptance("Composer", function (needs) {
|
|||||||
textarea.selectionEnd = textarea.value.length;
|
textarea.selectionEnd = textarea.value.length;
|
||||||
|
|
||||||
// Testing keyboard events is tough!
|
// Testing keyboard events is tough!
|
||||||
const mac = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
|
||||||
const event = document.createEvent("Event");
|
const event = document.createEvent("Event");
|
||||||
event.initEvent("keydown", true, true);
|
event.initEvent("keydown", true, true);
|
||||||
event[mac ? "metaKey" : "ctrlKey"] = true;
|
event[`${PLATFORM_KEY_MODIFIER}Key`] = true;
|
||||||
event.key = "B";
|
event.key = "B";
|
||||||
event.keyCode = 66;
|
event.keyCode = 66;
|
||||||
|
|
||||||
@ -1371,14 +1371,14 @@ acceptance("Composer - current time", function (needs) {
|
|||||||
assert.ok(exists(".d-editor-input"), "the composer input is visible");
|
assert.ok(exists(".d-editor-input"), "the composer input is visible");
|
||||||
await fillIn(".d-editor-input", "and the time now is: ");
|
await fillIn(".d-editor-input", "and the time now is: ");
|
||||||
|
|
||||||
const mac = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
|
||||||
const date = moment().format("YYYY-MM-DD");
|
const date = moment().format("YYYY-MM-DD");
|
||||||
|
|
||||||
await triggerKeyEvent(".d-editor-input", "keydown", ".", {
|
const eventOptions = {
|
||||||
shiftKey: true,
|
shiftKey: true,
|
||||||
ctrlKey: !mac,
|
};
|
||||||
metaKey: mac,
|
eventOptions[`${PLATFORM_KEY_MODIFIER}Key`] = true;
|
||||||
});
|
|
||||||
|
await triggerKeyEvent(".d-editor-input", "keydown", ".", eventOptions);
|
||||||
|
|
||||||
const inputValue = query("#reply-control .d-editor-input").value.trim();
|
const inputValue = query("#reply-control .d-editor-input").value.trim();
|
||||||
|
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||||
|
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||||
import ChatNewMessageModal from "discourse/plugins/chat/discourse/components/modal/chat-new-message";
|
import ChatNewMessageModal from "discourse/plugins/chat/discourse/components/modal/chat-new-message";
|
||||||
|
|
||||||
const APPLE =
|
|
||||||
navigator.platform.startsWith("Mac") || navigator.platform === "iPhone";
|
|
||||||
export const KEY_MODIFIER = APPLE ? "meta" : "ctrl";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "chat-keyboard-shortcuts",
|
name: "chat-keyboard-shortcuts",
|
||||||
|
|
||||||
@ -127,17 +124,21 @@ export default {
|
|||||||
};
|
};
|
||||||
|
|
||||||
withPluginApi("0.12.1", (api) => {
|
withPluginApi("0.12.1", (api) => {
|
||||||
api.addKeyboardShortcut(`${KEY_MODIFIER}+k`, openChannelSelector, {
|
api.addKeyboardShortcut(
|
||||||
global: true,
|
`${PLATFORM_KEY_MODIFIER}+k`,
|
||||||
help: {
|
openChannelSelector,
|
||||||
category: "chat",
|
{
|
||||||
name: "chat.keyboard_shortcuts.open_quick_channel_selector",
|
global: true,
|
||||||
definition: {
|
help: {
|
||||||
keys1: ["meta", "k"],
|
category: "chat",
|
||||||
keysDelimiter: "plus",
|
name: "chat.keyboard_shortcuts.open_quick_channel_selector",
|
||||||
|
definition: {
|
||||||
|
keys1: ["meta", "k"],
|
||||||
|
keysDelimiter: "plus",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
});
|
);
|
||||||
api.addKeyboardShortcut("alt+up", handleMoveUpShortcut, {
|
api.addKeyboardShortcut("alt+up", handleMoveUpShortcut, {
|
||||||
global: true,
|
global: true,
|
||||||
help: {
|
help: {
|
||||||
@ -156,7 +157,7 @@ export default {
|
|||||||
global: true,
|
global: true,
|
||||||
});
|
});
|
||||||
api.addKeyboardShortcut(
|
api.addKeyboardShortcut(
|
||||||
`${KEY_MODIFIER}+b`,
|
`${PLATFORM_KEY_MODIFIER}+b`,
|
||||||
(event) => modifyComposerSelection(event, "bold"),
|
(event) => modifyComposerSelection(event, "bold"),
|
||||||
{
|
{
|
||||||
global: true,
|
global: true,
|
||||||
@ -171,7 +172,7 @@ export default {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
api.addKeyboardShortcut(
|
api.addKeyboardShortcut(
|
||||||
`${KEY_MODIFIER}+i`,
|
`${PLATFORM_KEY_MODIFIER}+i`,
|
||||||
(event) => modifyComposerSelection(event, "italic"),
|
(event) => modifyComposerSelection(event, "italic"),
|
||||||
{
|
{
|
||||||
global: true,
|
global: true,
|
||||||
@ -186,7 +187,7 @@ export default {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
api.addKeyboardShortcut(
|
api.addKeyboardShortcut(
|
||||||
`${KEY_MODIFIER}+e`,
|
`${PLATFORM_KEY_MODIFIER}+e`,
|
||||||
(event) => modifyComposerSelection(event, "code"),
|
(event) => modifyComposerSelection(event, "code"),
|
||||||
{
|
{
|
||||||
global: true,
|
global: true,
|
||||||
@ -201,7 +202,7 @@ export default {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
api.addKeyboardShortcut(
|
api.addKeyboardShortcut(
|
||||||
`${KEY_MODIFIER}+l`,
|
`${PLATFORM_KEY_MODIFIER}+l`,
|
||||||
(event) => openInsertLinkModal(event),
|
(event) => openInsertLinkModal(event),
|
||||||
{
|
{
|
||||||
global: true,
|
global: true,
|
||||||
|
@ -7,7 +7,6 @@ RSpec.describe "Chat | composer | shortcuts | channel", type: :system do
|
|||||||
let(:chat) { PageObjects::Pages::Chat.new }
|
let(:chat) { PageObjects::Pages::Chat.new }
|
||||||
let(:channel_page) { PageObjects::Pages::ChatChannel.new }
|
let(:channel_page) { PageObjects::Pages::ChatChannel.new }
|
||||||
let(:thread_page) { PageObjects::Pages::ChatThread.new }
|
let(:thread_page) { PageObjects::Pages::ChatThread.new }
|
||||||
let(:key_modifier) { RUBY_PLATFORM =~ /darwin/i ? :meta : :control }
|
|
||||||
|
|
||||||
before do
|
before do
|
||||||
chat_system_bootstrap
|
chat_system_bootstrap
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
module PageObjects
|
module PageObjects
|
||||||
module Pages
|
module Pages
|
||||||
class Chat < PageObjects::Pages::Base
|
class Chat < PageObjects::Pages::Base
|
||||||
MODIFIER = RUBY_PLATFORM =~ /darwin/i ? :meta : :control
|
|
||||||
|
|
||||||
def message_creator
|
def message_creator
|
||||||
@message_creator ||= PageObjects::Components::Chat::MessageCreator.new
|
@message_creator ||= PageObjects::Components::Chat::MessageCreator.new
|
||||||
end
|
end
|
||||||
@ -24,7 +22,7 @@ module PageObjects
|
|||||||
end
|
end
|
||||||
|
|
||||||
def open_new_message
|
def open_new_message
|
||||||
send_keys([MODIFIER, "k"])
|
send_keys([PLATFORM_KEY_MODIFIER, "k"])
|
||||||
find(".chat-new-message-modal")
|
find(".chat-new-message-modal")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -8,8 +8,6 @@ module PageObjects
|
|||||||
|
|
||||||
SELECTOR = ".chat-composer__wrapper"
|
SELECTOR = ".chat-composer__wrapper"
|
||||||
|
|
||||||
MODIFIER = RUBY_PLATFORM =~ /darwin/i ? :meta : :control
|
|
||||||
|
|
||||||
def initialize(context)
|
def initialize(context)
|
||||||
@context = context
|
@context = context
|
||||||
end
|
end
|
||||||
@ -59,7 +57,7 @@ module PageObjects
|
|||||||
end
|
end
|
||||||
|
|
||||||
def emphasized_text_shortcut
|
def emphasized_text_shortcut
|
||||||
input.send_keys([MODIFIER, "i"])
|
input.send_keys([PLATFORM_KEY_MODIFIER, "i"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def cancel_shortcut
|
def cancel_shortcut
|
||||||
@ -67,11 +65,11 @@ module PageObjects
|
|||||||
end
|
end
|
||||||
|
|
||||||
def indented_text_shortcut
|
def indented_text_shortcut
|
||||||
input.send_keys([MODIFIER, "e"])
|
input.send_keys([PLATFORM_KEY_MODIFIER, "e"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def bold_text_shortcut
|
def bold_text_shortcut
|
||||||
input.send_keys([MODIFIER, "b"])
|
input.send_keys([PLATFORM_KEY_MODIFIER, "b"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def open_emoji_picker
|
def open_emoji_picker
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
require "highline/import"
|
require "highline/import"
|
||||||
|
|
||||||
module SystemHelpers
|
module SystemHelpers
|
||||||
|
PLATFORM_KEY_MODIFIER = RUBY_PLATFORM =~ /darwin/i ? :meta : :control
|
||||||
|
|
||||||
def pause_test
|
def pause_test
|
||||||
result =
|
result =
|
||||||
ask(
|
ask(
|
||||||
|
Reference in New Issue
Block a user