mirror of
https://github.com/discourse/discourse.git
synced 2026-08-03 01:49:44 -05:00
DEV: Convert keyboard-shortcuts lib to service (#36098)
This lib file required an owner, and had a setup/teardown hooks, so it really makes more sense as a service. This also allows us to use `@service` injections, which are much better than eager `.lookup()` calls. This will resolve issues we're seeing with theme/plugin `modifyClass` calls racing with these service lookups.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import Controller from "@ember/controller";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import { translateModKey } from "discourse/lib/utilities";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
|
||||
export default class AdminSearchIndexController extends Controller {
|
||||
queryParams = ["filter"];
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { tracked } from "@glimmer/tracking";
|
||||
import { service } from "@ember/service";
|
||||
import AdminSearchModal from "discourse/admin/components/modal/admin-search";
|
||||
import KeyboardShortcuts, {
|
||||
PLATFORM_KEY_MODIFIER,
|
||||
} from "discourse/lib/keyboard-shortcuts";
|
||||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class AdminRoute extends DiscourseRoute {
|
||||
@service adminSidebarStateManager;
|
||||
@service modal;
|
||||
@service keyboardShortcuts;
|
||||
|
||||
@tracked initialSidebarState;
|
||||
|
||||
@@ -18,7 +17,7 @@ export default class AdminRoute extends DiscourseRoute {
|
||||
}
|
||||
|
||||
activate() {
|
||||
KeyboardShortcuts.addShortcut(
|
||||
this.keyboardShortcuts.addShortcut(
|
||||
`${PLATFORM_KEY_MODIFIER}+/`,
|
||||
(event) => this.showAdminSearchModal(event),
|
||||
{
|
||||
@@ -38,7 +37,7 @@ export default class AdminRoute extends DiscourseRoute {
|
||||
deactivate(transition) {
|
||||
this.controllerFor("application").set("showTop", true);
|
||||
|
||||
KeyboardShortcuts.unbind({
|
||||
this.keyboardShortcuts.unbind({
|
||||
[`${PLATFORM_KEY_MODIFIER}+/`]: this.showAdminSearchModal,
|
||||
});
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ import deprecated from "discourse/lib/deprecated";
|
||||
import { isTesting } from "discourse/lib/environment";
|
||||
import { getRegister } from "discourse/lib/get-owner";
|
||||
import { hashtagAutocompleteOptions } from "discourse/lib/hashtag-autocomplete";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import loadEmojiSearchAliases from "discourse/lib/load-emoji-search-aliases";
|
||||
import loadRichEditor from "discourse/lib/load-rich-editor";
|
||||
import { rovingButtonBar } from "discourse/lib/roving-button-bar";
|
||||
@@ -48,6 +47,7 @@ import {
|
||||
EMOJI_ALLOWED_PRECEDING_CHARS_REGEXP,
|
||||
SKIP,
|
||||
} from "discourse/modifiers/d-autocomplete";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import { not } from "discourse/truth-helpers";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ import RelativeTimePicker from "discourse/components/relative-time-picker";
|
||||
import TimeShortcutPicker from "discourse/components/time-shortcut-picker";
|
||||
import TopicTimerInfo from "discourse/components/topic-timer-info";
|
||||
import icon from "discourse/helpers/d-icon";
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import {
|
||||
TIME_SHORTCUT_TYPES,
|
||||
timeShortcuts,
|
||||
@@ -30,13 +29,14 @@ import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class EditTopicTimerForm extends Component {
|
||||
@service currentUser;
|
||||
@service keyboardShortcuts;
|
||||
|
||||
@tracked timerType;
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
KeyboardShortcuts.pause();
|
||||
this.keyboardShortcuts.pause();
|
||||
this._itsatrap = new ItsATrap();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export default class EditTopicTimerForm extends Component {
|
||||
super.willDestroy(...arguments);
|
||||
|
||||
this._itsatrap.destroy();
|
||||
KeyboardShortcuts.unpause();
|
||||
this.keyboardShortcuts.unpause();
|
||||
}
|
||||
|
||||
get showTimeOnly() {
|
||||
|
||||
@@ -19,7 +19,6 @@ import basePath from "discourse/helpers/base-path";
|
||||
import icon from "discourse/helpers/d-icon";
|
||||
import { extractError } from "discourse/lib/ajax-error";
|
||||
import { formattedReminderTime } from "discourse/lib/bookmark";
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import discourseLater from "discourse/lib/later";
|
||||
import { sanitize } from "discourse/lib/text";
|
||||
import {
|
||||
@@ -42,6 +41,7 @@ export default class BookmarkModal extends Component {
|
||||
@service capabilities;
|
||||
@service bookmarkApi;
|
||||
@service site;
|
||||
@service keyboardShortcuts;
|
||||
|
||||
@tracked postDetectedLocalDate = null;
|
||||
@tracked postDetectedLocalTime = null;
|
||||
@@ -70,7 +70,7 @@ export default class BookmarkModal extends Component {
|
||||
super.willDestroy(...arguments);
|
||||
this._itsatrap?.destroy();
|
||||
this._itsatrap = null;
|
||||
KeyboardShortcuts.unpause();
|
||||
this.keyboardShortcuts.unpause();
|
||||
}
|
||||
|
||||
get bookmark() {
|
||||
@@ -304,7 +304,7 @@ export default class BookmarkModal extends Component {
|
||||
}
|
||||
|
||||
#bindKeyboardShortcuts() {
|
||||
KeyboardShortcuts.pause();
|
||||
this.keyboardShortcuts.pause();
|
||||
|
||||
Object.keys(BOOKMARK_BINDINGS).forEach((shortcut) => {
|
||||
this._itsatrap.bind(shortcut, () => {
|
||||
|
||||
@@ -6,8 +6,8 @@ import { service } from "@ember/service";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import DModal from "discourse/components/d-modal";
|
||||
import FilterInput from "discourse/components/filter-input";
|
||||
import { extraKeyboardShortcutsHelp } from "discourse/lib/keyboard-shortcuts";
|
||||
import { translateModKey } from "discourse/lib/utilities";
|
||||
import { extraKeyboardShortcutsHelp } from "discourse/services/keyboard-shortcuts";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
const KEY = "keyboard_shortcuts_help";
|
||||
|
||||
@@ -11,7 +11,6 @@ import TextField from "discourse/components/text-field";
|
||||
import DTooltip from "discourse/float-kit/components/d-tooltip";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import {
|
||||
arrayToTable,
|
||||
findTableRegex,
|
||||
@@ -21,6 +20,7 @@ import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class SpreadsheetEditor extends Component {
|
||||
@service dialog;
|
||||
@service keyboardShortcuts;
|
||||
|
||||
@tracked showEditReason = false;
|
||||
@tracked loading = true;
|
||||
@@ -32,12 +32,12 @@ export default class SpreadsheetEditor extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.loadJspreadsheet();
|
||||
KeyboardShortcuts.pause();
|
||||
this.keyboardShortcuts.pause();
|
||||
}
|
||||
|
||||
willDestroy() {
|
||||
super.willDestroy(...arguments);
|
||||
KeyboardShortcuts.unpause();
|
||||
this.keyboardShortcuts.unpause();
|
||||
}
|
||||
|
||||
get modalAttributes() {
|
||||
|
||||
@@ -9,8 +9,8 @@ import DMenu from "discourse/float-kit/components/d-menu";
|
||||
import concatClass from "discourse/helpers/concat-class";
|
||||
import icon from "discourse/helpers/d-icon";
|
||||
import { iconHTML } from "discourse/lib/icon-library";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import { translateModKey } from "discourse/lib/utilities";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
export default class ToolbarPopupmenuOptions extends Component {
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import ItsATrap from "@discourse/itsatrap";
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
|
||||
export default {
|
||||
initialize(owner) {
|
||||
KeyboardShortcuts.init(ItsATrap, owner);
|
||||
KeyboardShortcuts.bindEvents();
|
||||
},
|
||||
|
||||
teardown() {
|
||||
KeyboardShortcuts.teardown();
|
||||
owner.lookup("service:keyboard-shortcuts");
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// @ts-check
|
||||
import { action } from "@ember/object";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import { translateModKey } from "discourse/lib/utilities";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import { i18n } from "discourse-i18n";
|
||||
|
||||
/**
|
||||
|
||||
@@ -72,9 +72,6 @@ import {
|
||||
registerIconRenderer,
|
||||
replaceIcon,
|
||||
} from "discourse/lib/icon-library";
|
||||
import KeyboardShortcuts, {
|
||||
disableDefaultKeyboardShortcuts,
|
||||
} from "discourse/lib/keyboard-shortcuts";
|
||||
import { registerModelTransformer } from "discourse/lib/model-transformers";
|
||||
import { registerNotificationTypeRenderer } from "discourse/lib/notification-types-manager";
|
||||
import { addGTMPageChangedCallback } from "discourse/lib/page-tracker";
|
||||
@@ -130,6 +127,7 @@ import { setNotificationsLimit } from "discourse/routes/user-notifications";
|
||||
import { CUSTOM_USER_SEARCH_OPTIONS } from "discourse/select-kit/components/user-chooser";
|
||||
import { modifySelectKit } from "discourse/select-kit/lib/plugin-api";
|
||||
import { addComposerSaveErrorCallback } from "discourse/services/composer";
|
||||
import { disableDefaultKeyboardShortcuts } from "discourse/services/keyboard-shortcuts";
|
||||
import { addPostClassesCallback } from "discourse/widgets/post";
|
||||
import { addDecorator } from "discourse/widgets/post-cooked";
|
||||
import {
|
||||
@@ -623,14 +621,18 @@ class _PluginApi {
|
||||
* See KeyboardShortcuts.addShortcut documentation.
|
||||
**/
|
||||
addKeyboardShortcut(shortcut, callback, opts = {}) {
|
||||
KeyboardShortcuts.addShortcut(shortcut, callback, opts);
|
||||
this.container
|
||||
.lookup("service:keyboard-shortcuts")
|
||||
.addShortcut(shortcut, callback, opts);
|
||||
}
|
||||
|
||||
/**
|
||||
* See KeyboardShortcuts.unbind documentation.
|
||||
**/
|
||||
removeKeyboardShortcut(shortcut, callback) {
|
||||
KeyboardShortcuts.unbind({ [shortcut]: callback });
|
||||
this.container
|
||||
.lookup("service:keyboard-shortcuts")
|
||||
.unbind({ [shortcut]: callback });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+90
-94
@@ -1,5 +1,7 @@
|
||||
import { getOwner, setOwner } from "@ember/owner";
|
||||
import { getOwner } from "@ember/owner";
|
||||
import { run, throttle } from "@ember/runloop";
|
||||
import Service, { service } from "@ember/service";
|
||||
import ItsATrap from "@discourse/itsatrap";
|
||||
import KeyboardShortcutsHelp from "discourse/components/modal/keyboard-shortcuts-help";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import domUtils from "discourse/lib/dom-utils";
|
||||
@@ -141,29 +143,20 @@ function preventKeyboardEvent(event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
export default {
|
||||
init(keyTrapper, owner) {
|
||||
setOwner(this, owner);
|
||||
export default class KeyboardShortcutLib extends Service {
|
||||
@service appEvents;
|
||||
@service composer;
|
||||
@service currentUser;
|
||||
@service router;
|
||||
@service siteSettings;
|
||||
@service modal;
|
||||
|
||||
// Sometimes the keyboard shortcut initializer is not torn down. This makes sure
|
||||
// we clear any previous test state.
|
||||
if (this.keyTrapper) {
|
||||
this.keyTrapper.destroy();
|
||||
this.keyTrapper = null;
|
||||
}
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
this.keyTrapper = new keyTrapper();
|
||||
this.keyTrapper = new ItsATrap();
|
||||
this._stopCallback();
|
||||
|
||||
this.appEvents = owner.lookup("service:app-events");
|
||||
this.composer = owner.lookup("service:composer");
|
||||
this.currentUser = owner.lookup("service:current-user");
|
||||
this.modal = owner.lookup("service:modal");
|
||||
this.router = owner.lookup("service:router");
|
||||
this.searchService = owner.lookup("service:search");
|
||||
this.siteSettings = owner.lookup("service:site-settings");
|
||||
this.site = owner.lookup("service:site");
|
||||
|
||||
// Disable the shortcut if private messages are disabled
|
||||
if (!this.currentUser?.can_send_private_messages) {
|
||||
delete DEFAULT_BINDINGS["g m"];
|
||||
@@ -172,26 +165,29 @@ export default {
|
||||
if (disabledBindings.length) {
|
||||
disabledBindings.forEach((binding) => delete DEFAULT_BINDINGS[binding]);
|
||||
}
|
||||
},
|
||||
|
||||
bindEvents() {
|
||||
Object.keys(DEFAULT_BINDINGS).forEach((key) => {
|
||||
this.bindKey(key);
|
||||
});
|
||||
},
|
||||
this.bindEvents();
|
||||
}
|
||||
|
||||
teardown() {
|
||||
willDestroy() {
|
||||
super.willDestroy(...arguments);
|
||||
const prototype = Object.getPrototypeOf(this.keyTrapper);
|
||||
prototype.stopCallback = this.oldStopCallback;
|
||||
this.oldStopCallback = null;
|
||||
|
||||
this.keyTrapper?.destroy();
|
||||
this.keyTrapper = null;
|
||||
},
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
Object.keys(DEFAULT_BINDINGS).forEach((key) => {
|
||||
this.bindKey(key);
|
||||
});
|
||||
}
|
||||
|
||||
isTornDown() {
|
||||
return this.keyTrapper == null;
|
||||
},
|
||||
}
|
||||
|
||||
bindKey(key, binding = null) {
|
||||
if (this.isTornDown()) {
|
||||
@@ -220,7 +216,7 @@ export default {
|
||||
} else if (binding.click) {
|
||||
this._bindToClick(binding.click, key);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// for cases when you want to disable global keyboard shortcuts
|
||||
// so that you can override them (e.g. inside a modal)
|
||||
@@ -234,7 +230,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
combinations.forEach((combo) => this.keyTrapper.unbind(combo));
|
||||
},
|
||||
}
|
||||
|
||||
// restore global shortcuts that you have paused
|
||||
unpause(combinations) {
|
||||
@@ -248,7 +244,7 @@ export default {
|
||||
}
|
||||
|
||||
combinations.forEach((combo) => this.bindKey(combo));
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* addShortcut(shortcut, callback, opts)
|
||||
@@ -281,7 +277,7 @@ export default {
|
||||
if (opts.help) {
|
||||
addExtraKeyboardShortcutHelp(opts.help);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* unbind(combinations)
|
||||
@@ -295,7 +291,7 @@ export default {
|
||||
*/
|
||||
unbind(combinations) {
|
||||
Object.keys(combinations).forEach((combo) => this.keyTrapper.unbind(combo));
|
||||
},
|
||||
}
|
||||
|
||||
toggleBookmark(event) {
|
||||
const selectedPost = this._getSelectedPost();
|
||||
@@ -313,7 +309,7 @@ export default {
|
||||
}
|
||||
|
||||
this._bookmarkCurrentTopic(event);
|
||||
},
|
||||
}
|
||||
|
||||
toggleBookmarkTopic(event) {
|
||||
const selectedTopicListItem = this._getSelectedTopicListItem();
|
||||
@@ -324,7 +320,7 @@ export default {
|
||||
}
|
||||
|
||||
this._bookmarkCurrentTopic(event);
|
||||
},
|
||||
}
|
||||
|
||||
_bookmarkCurrentTopic(event) {
|
||||
const topic = this.currentTopic();
|
||||
@@ -332,11 +328,11 @@ export default {
|
||||
preventKeyboardEvent(event);
|
||||
getOwner(this).lookup("controller:topic").send("toggleBookmark");
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
logout() {
|
||||
getOwner(this).lookup("route:application").send("logout");
|
||||
},
|
||||
}
|
||||
|
||||
quoteReply() {
|
||||
if (this.isPostTextSelected) {
|
||||
@@ -352,7 +348,7 @@ export default {
|
||||
);
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
editPost() {
|
||||
if (this.siteSettings.enable_fast_edit && this.isPostTextSelected) {
|
||||
@@ -363,7 +359,7 @@ export default {
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
goToNextTopic() {
|
||||
nextTopicUrl().then((url) => {
|
||||
@@ -371,7 +367,7 @@ export default {
|
||||
DiscourseURL.routeTo(url);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
goToPreviousTopic() {
|
||||
previousTopicUrl().then((url) => {
|
||||
@@ -379,7 +375,7 @@ export default {
|
||||
DiscourseURL.routeTo(url);
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
goToFirstSuggestedTopic() {
|
||||
const el = document.querySelector("#suggested-topics a.raw-topic-link");
|
||||
@@ -399,58 +395,58 @@ export default {
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
goToFirstPost() {
|
||||
this._jumpTo("jumpTop");
|
||||
},
|
||||
}
|
||||
|
||||
goToLastPost() {
|
||||
this._jumpTo("jumpBottom");
|
||||
},
|
||||
}
|
||||
|
||||
goToUnreadPost() {
|
||||
this._jumpTo("jumpUnread");
|
||||
},
|
||||
}
|
||||
|
||||
_jumpTo(direction) {
|
||||
if (document.querySelector(".container.posts")) {
|
||||
getOwner(this).lookup("controller:topic").send(direction);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
replyToTopic() {
|
||||
this._replyToPost();
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
selectDown() {
|
||||
this._moveSelection({ direction: 1, scrollWithinPosts: true });
|
||||
},
|
||||
}
|
||||
|
||||
selectUp() {
|
||||
this._moveSelection({ direction: -1, scrollWithinPosts: true });
|
||||
},
|
||||
}
|
||||
|
||||
bulkSelectItem() {
|
||||
const elem = document.querySelector(
|
||||
".selected input.bulk-select, .selected .select-post"
|
||||
);
|
||||
elem?.click();
|
||||
},
|
||||
}
|
||||
|
||||
goBack() {
|
||||
history.back();
|
||||
},
|
||||
}
|
||||
|
||||
nextSection() {
|
||||
this._changeSection(1);
|
||||
},
|
||||
}
|
||||
|
||||
prevSection() {
|
||||
this._changeSection(-1);
|
||||
},
|
||||
}
|
||||
|
||||
printTopic(event) {
|
||||
run(() => {
|
||||
@@ -459,7 +455,7 @@ export default {
|
||||
getOwner(this).lookup("controller:topic").print();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
createTopic(event) {
|
||||
if (!(this.currentUser && this.currentUser.can_create_topic)) {
|
||||
@@ -506,7 +502,7 @@ export default {
|
||||
action: Composer.CREATE_TOPIC,
|
||||
draftKey: Composer.NEW_TOPIC_KEY,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
focusComposer(event) {
|
||||
if (event) {
|
||||
@@ -514,22 +510,22 @@ export default {
|
||||
event.stopPropagation();
|
||||
}
|
||||
this.composer.focusComposer(event);
|
||||
},
|
||||
}
|
||||
|
||||
fullscreenComposer() {
|
||||
if (this.composer.get("model")) {
|
||||
this.composer.toggleFullscreen();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
pinUnpinTopic() {
|
||||
getOwner(this).lookup("controller:topic").togglePinnedState();
|
||||
},
|
||||
}
|
||||
|
||||
goToPost(event) {
|
||||
preventKeyboardEvent(event);
|
||||
this.appEvents.trigger("topic:keyboard-trigger", { type: "jump" });
|
||||
},
|
||||
}
|
||||
|
||||
toggleSearch(event) {
|
||||
this.appEvents.trigger("header:keyboard-trigger", {
|
||||
@@ -538,39 +534,39 @@ export default {
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
toggleHamburgerMenu(event) {
|
||||
this.appEvents.trigger("header:keyboard-trigger", {
|
||||
type: "hamburger",
|
||||
event,
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
showCurrentUser(event) {
|
||||
this.appEvents.trigger("header:keyboard-trigger", { type: "user", event });
|
||||
},
|
||||
}
|
||||
|
||||
showHelpModal(event) {
|
||||
event.preventDefault();
|
||||
this.modal.show(KeyboardShortcutsHelp);
|
||||
},
|
||||
}
|
||||
|
||||
setTrackingToMuted() {
|
||||
throttle(this, "_setTracking", 0, INPUT_DELAY, true);
|
||||
},
|
||||
}
|
||||
|
||||
setTrackingToRegular() {
|
||||
throttle(this, "_setTracking", 1, INPUT_DELAY, true);
|
||||
},
|
||||
}
|
||||
|
||||
setTrackingToTracking() {
|
||||
throttle(this, "_setTracking", 2, INPUT_DELAY, true);
|
||||
},
|
||||
}
|
||||
|
||||
setTrackingToWatching() {
|
||||
throttle(this, "_setTracking", 3, INPUT_DELAY, true);
|
||||
},
|
||||
}
|
||||
|
||||
_setTracking(levelId) {
|
||||
const topic = this.currentTopic();
|
||||
@@ -580,7 +576,7 @@ export default {
|
||||
}
|
||||
|
||||
topic.details.updateNotifications(levelId);
|
||||
},
|
||||
}
|
||||
|
||||
sendToTopicListItemView(action, elem) {
|
||||
elem = elem || document.querySelector("tr.selected.topic-list-item");
|
||||
@@ -591,7 +587,7 @@ export default {
|
||||
view.send(action);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
currentTopic() {
|
||||
const topicController = getOwner(this).lookup("controller:topic");
|
||||
@@ -601,12 +597,12 @@ export default {
|
||||
return topic;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
get isPostTextSelected() {
|
||||
const topicController = getOwner(this).lookup("controller:topic");
|
||||
return !!topicController.quoteState.postId;
|
||||
},
|
||||
}
|
||||
|
||||
sendToSelectedPost(action, elem) {
|
||||
// TODO: We should keep track of the post without a CSS class
|
||||
@@ -641,15 +637,15 @@ export default {
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
_bindToSelectedPost(action, binding) {
|
||||
this.keyTrapper.bind(binding, () => this.sendToSelectedPost(action));
|
||||
},
|
||||
}
|
||||
|
||||
_bindToPath(path, key) {
|
||||
this.keyTrapper.bind(key, () => DiscourseURL.routeTo(path));
|
||||
},
|
||||
}
|
||||
|
||||
_bindToClick(selector, binding) {
|
||||
binding = binding.split(",");
|
||||
@@ -670,21 +666,21 @@ export default {
|
||||
|
||||
selection?.click();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
_globalBindToFunction(func, binding) {
|
||||
let funcToBind = typeof func === "function" ? func : this[func];
|
||||
if (typeof funcToBind === "function") {
|
||||
this.keyTrapper.bindGlobal(binding, funcToBind.bind(this));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_bindToFunction(func, binding) {
|
||||
let funcToBind = typeof func === "function" ? func : this[func];
|
||||
if (typeof funcToBind === "function") {
|
||||
this.keyTrapper.bind(binding, funcToBind.bind(this));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_moveSelection({ direction, scrollWithinPosts }) {
|
||||
// Pressing a move key (J/K) very quick (i.e. keeping J or K pressed) will
|
||||
@@ -840,14 +836,14 @@ export default {
|
||||
|
||||
const scrollRatio = direction > 0 ? 0.2 : 0.7;
|
||||
this._scrollTo(articleTopPosition - window.innerHeight * scrollRatio);
|
||||
},
|
||||
}
|
||||
|
||||
_scrollTo(scrollTop) {
|
||||
window.scrollTo({
|
||||
top: scrollTop,
|
||||
behavior: "smooth",
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
categoriesTopicsList() {
|
||||
switch (this.siteSettings.desktop_category_page_style) {
|
||||
@@ -865,7 +861,7 @@ export default {
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_findArticles() {
|
||||
let categoriesTopicsList;
|
||||
@@ -880,7 +876,7 @@ export default {
|
||||
} else if ((categoriesTopicsList = this.categoriesTopicsList())) {
|
||||
return categoriesTopicsList;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_changeSection(direction) {
|
||||
if (document.querySelector(".post-stream")) {
|
||||
@@ -896,7 +892,7 @@ export default {
|
||||
sections[index].querySelector("a, button")?.click();
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
_stopCallback() {
|
||||
const prototype = Object.getPrototypeOf(this.keyTrapper);
|
||||
@@ -916,27 +912,27 @@ export default {
|
||||
|
||||
return oldCallback.call(this, e, element, combo, sequence);
|
||||
};
|
||||
},
|
||||
}
|
||||
|
||||
_replyToPost() {
|
||||
getOwner(this).lookup("controller:topic").send("replyToPost");
|
||||
},
|
||||
}
|
||||
|
||||
_getSelectedPost() {
|
||||
return document.querySelector(".topic-post.selected article[data-post-id]");
|
||||
},
|
||||
}
|
||||
|
||||
_getSelectedTopicListItem() {
|
||||
return document.querySelector("tr.selected.topic-list-item");
|
||||
},
|
||||
}
|
||||
|
||||
deferTopic() {
|
||||
getOwner(this).lookup("controller:topic").send("deferTopic");
|
||||
},
|
||||
}
|
||||
|
||||
toggleAdminActions() {
|
||||
document.querySelector(".toggle-admin-menu")?.click();
|
||||
},
|
||||
}
|
||||
|
||||
toggleBulkSelect() {
|
||||
const bulkSelect = document.querySelector("button.bulk-select");
|
||||
@@ -946,21 +942,21 @@ export default {
|
||||
} else {
|
||||
getOwner(this).lookup("controller:topic").send("toggleMultiSelect");
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
toggleArchivePM() {
|
||||
getOwner(this).lookup("controller:topic").send("toggleArchiveMessage");
|
||||
},
|
||||
}
|
||||
|
||||
webviewKeyboardBack() {
|
||||
if (capabilities.isAppWebview) {
|
||||
window.history.back();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
webviewKeyboardForward() {
|
||||
if (capabilities.isAppWebview) {
|
||||
window.history.forward();
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,13 @@ import {
|
||||
} from "@ember/test-helpers";
|
||||
import { module, test } from "qunit";
|
||||
import sinon from "sinon";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import LinkLookup from "discourse/lib/link-lookup";
|
||||
import { cloneJSON } from "discourse/lib/object";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { translateModKey } from "discourse/lib/utilities";
|
||||
import Composer, { CREATE_TOPIC } from "discourse/models/composer";
|
||||
import Draft from "discourse/models/draft";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import TopicFixtures from "discourse/tests/fixtures/topic";
|
||||
import pretender, { response } from "discourse/tests/helpers/create-pretender";
|
||||
import {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getOwner } from "@ember/owner";
|
||||
import { click, triggerKeyEvent, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import sinon from "sinon";
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
|
||||
@@ -27,7 +27,10 @@ acceptance("Plugin Keyboard Shortcuts - Logged In", function (needs) {
|
||||
|
||||
acceptance("Plugin Keyboard Shortcuts - Anonymous", function () {
|
||||
test("a plugin can add a keyboard shortcut with an option", async function (assert) {
|
||||
let spy = sinon.spy(KeyboardShortcuts, "_bindToPath");
|
||||
let spy = sinon.spy(
|
||||
getOwner(this).lookup("service:keyboard-shortcuts"),
|
||||
"_bindToPath"
|
||||
);
|
||||
withPluginApi((api) => {
|
||||
api.addKeyboardShortcut("]", () => {}, {
|
||||
anonymous: true,
|
||||
|
||||
@@ -45,11 +45,6 @@ import { clearDesktopNotificationHandlers } from "discourse/lib/desktop-notifica
|
||||
import { getOwnerWithFallback } from "discourse/lib/get-owner";
|
||||
import { restoreBaseUri } from "discourse/lib/get-url";
|
||||
import { cleanUpHashtagTypeClasses } from "discourse/lib/hashtag-type-registry";
|
||||
import {
|
||||
clearDisabledDefaultKeyboardBindings,
|
||||
clearExtraKeyboardShortcutHelp,
|
||||
PLATFORM_KEY_MODIFIER,
|
||||
} from "discourse/lib/keyboard-shortcuts";
|
||||
import { reset as resetLinkLookup } from "discourse/lib/link-lookup";
|
||||
import { resetMentions } from "discourse/lib/link-mentions";
|
||||
import { forceMobile, resetMobile } from "discourse/lib/mobile";
|
||||
@@ -95,6 +90,11 @@ import User from "discourse/models/user";
|
||||
import { clearResolverOptions } from "discourse/resolver";
|
||||
import { _clearSnapshots } from "discourse/select-kit/components/composer-actions";
|
||||
import { enableClearA11yAnnouncementsInTests } from "discourse/services/a11y";
|
||||
import {
|
||||
clearDisabledDefaultKeyboardBindings,
|
||||
clearExtraKeyboardShortcutHelp,
|
||||
PLATFORM_KEY_MODIFIER,
|
||||
} from "discourse/services/keyboard-shortcuts";
|
||||
import sessionFixtures from "discourse/tests/fixtures/session-fixtures";
|
||||
import siteFixtures from "discourse/tests/fixtures/site-fixtures";
|
||||
import {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { setupTest } from "ember-qunit";
|
||||
import { module, test } from "qunit";
|
||||
import sinon from "sinon";
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import DiscourseURL from "discourse/lib/url";
|
||||
|
||||
module("Unit | Utility | keyboard-shortcuts", function (hooks) {
|
||||
@@ -17,21 +16,24 @@ module("Unit | Utility | keyboard-shortcuts", function (hooks) {
|
||||
called = true;
|
||||
});
|
||||
|
||||
KeyboardShortcuts.goBack();
|
||||
const keyboardShortcuts = this.owner.lookup("service:keyboard-shortcuts");
|
||||
keyboardShortcuts.goBack();
|
||||
assert.true(called, "history.back is called");
|
||||
});
|
||||
|
||||
test("nextSection calls _changeSection with 1", function (assert) {
|
||||
let spy = sinon.spy(KeyboardShortcuts, "_changeSection");
|
||||
const keyboardShortcuts = this.owner.lookup("service:keyboard-shortcuts");
|
||||
let spy = sinon.spy(keyboardShortcuts, "_changeSection");
|
||||
|
||||
KeyboardShortcuts.nextSection();
|
||||
keyboardShortcuts.nextSection();
|
||||
assert.true(spy.calledWith(1), "_changeSection is called with 1");
|
||||
});
|
||||
|
||||
test("prevSection calls _changeSection with -1", function (assert) {
|
||||
let spy = sinon.spy(KeyboardShortcuts, "_changeSection");
|
||||
const keyboardShortcuts = this.owner.lookup("service:keyboard-shortcuts");
|
||||
let spy = sinon.spy(keyboardShortcuts, "_changeSection");
|
||||
|
||||
KeyboardShortcuts.prevSection();
|
||||
keyboardShortcuts.prevSection();
|
||||
assert.true(spy.calledWith(-1), "_changeSection is called with -1");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,8 +4,8 @@ import { service } from "@ember/service";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import discourseComputed from "discourse/lib/decorators";
|
||||
import { isTesting } from "discourse/lib/environment";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import { translateModKey } from "discourse/lib/utilities";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import { i18n } from "discourse-i18n";
|
||||
import { CHAT_SOUNDS } from "discourse/plugins/chat/discourse/services/chat-audio-manager";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import ChatModalNewMessage from "discourse/plugins/chat/discourse/components/chat/modal/new-message";
|
||||
|
||||
export default {
|
||||
|
||||
+1
-1
@@ -2,8 +2,8 @@ import Component from "@glimmer/component";
|
||||
import { fn } from "@ember/helper";
|
||||
import { service } from "@ember/service";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import { translateModKey } from "discourse/lib/utilities";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import { and, eq } from "discourse/truth-helpers";
|
||||
import AiHelperCustomPrompt from "../components/ai-helper-custom-prompt";
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import { withPluginApi } from "discourse/lib/plugin-api";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import extractVariablesFromChatChannel from "../../lib/variables-chat-channel";
|
||||
import extractVariablesFromChatThread from "../../lib/variables-chat-thread";
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
visit,
|
||||
} from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/lib/keyboard-shortcuts";
|
||||
import { cloneJSON } from "discourse/lib/object";
|
||||
import { PLATFORM_KEY_MODIFIER } from "discourse/services/keyboard-shortcuts";
|
||||
import topicFixtures from "discourse/tests/fixtures/topic";
|
||||
import { acceptance } from "discourse/tests/helpers/qunit-helpers";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
|
||||
Reference in New Issue
Block a user