diff --git a/app/assets/javascripts/discourse/app/components/bookmark.js b/app/assets/javascripts/discourse/app/components/bookmark.js index 7d05dd780dc..ccd790e526b 100644 --- a/app/assets/javascripts/discourse/app/components/bookmark.js +++ b/app/assets/javascripts/discourse/app/components/bookmark.js @@ -7,14 +7,13 @@ import { startOfDay, tomorrow, } from "discourse/lib/time-utils"; - import { AUTO_DELETE_PREFERENCES } from "discourse/models/bookmark"; import Component from "@ember/component"; import I18n from "I18n"; import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts"; +import Mousetrap from "mousetrap"; import { Promise } from "rsvp"; import { TIME_SHORTCUT_TYPES } from "discourse/lib/time-shortcut"; - import { action } from "@ember/object"; import { ajax } from "discourse/lib/ajax"; import bootbox from "bootbox"; @@ -24,11 +23,6 @@ import { and, notEmpty } from "@ember/object/computed"; import { popupAjaxError } from "discourse/lib/ajax-error"; import { later } from "@ember/runloop"; -// global shortcuts that interfere with these modal shortcuts, they are rebound when the -// modal is closed -// -// d deletePost -const GLOBAL_SHORTCUTS_TO_PAUSE = ["d"]; const BOOKMARK_BINDINGS = { enter: { handler: "saveAndClose" }, "d d": { handler: "delete" }, @@ -127,26 +121,18 @@ export default Component.extend({ }, _bindKeyboardShortcuts() { - KeyboardShortcuts.pause(GLOBAL_SHORTCUTS_TO_PAUSE); + KeyboardShortcuts.pause(); + + this._mousetrap = new Mousetrap(); Object.keys(BOOKMARK_BINDINGS).forEach((shortcut) => { - KeyboardShortcuts.addShortcut(shortcut, () => { + this._mousetrap.bind(shortcut, () => { let binding = BOOKMARK_BINDINGS[shortcut]; - if (binding.args) { - return this.send(binding.handler, ...binding.args); - } this.send(binding.handler); + return false; }); }); }, - _unbindKeyboardShortcuts() { - KeyboardShortcuts.unbind(BOOKMARK_BINDINGS); - }, - - _restoreGlobalShortcuts() { - KeyboardShortcuts.unpause(GLOBAL_SHORTCUTS_TO_PAUSE); - }, - _loadPostLocalDates() { let postEl = document.querySelector( `[data-post-id="${this.model.postId}"]` @@ -270,9 +256,6 @@ export default Component.extend({ this._closeWithoutSaving = this._closeWithoutSaving || initiatedByCloseButton; - this._unbindKeyboardShortcuts(); - this._restoreGlobalShortcuts(); - if (!this._closeWithoutSaving && !this._savingBookmarkManually) { this._saveBookmark().catch((e) => this._handleSaveError(e)); } @@ -281,6 +264,12 @@ export default Component.extend({ } }, + willDestroyElement() { + this._super(...arguments); + this._mousetrap.reset(); + KeyboardShortcuts.unpause(); + }, + showExistingReminderAt: notEmpty("model.reminderAt"), showDelete: notEmpty("model.id"), userHasTimezoneSet: notEmpty("userTimezone"), diff --git a/app/assets/javascripts/discourse/app/components/d-editor.js b/app/assets/javascripts/discourse/app/components/d-editor.js index 83d9e24f9c0..a0c9d2dda0c 100644 --- a/app/assets/javascripts/discourse/app/components/d-editor.js +++ b/app/assets/javascripts/discourse/app/components/d-editor.js @@ -274,12 +274,14 @@ export default Component.extend({ scheduleOnce("afterRender", this, this._readyNow); - const mouseTrap = Mousetrap(this.element.querySelector(".d-editor-input")); + this._mouseTrap = new Mousetrap( + this.element.querySelector(".d-editor-input") + ); const shortcuts = this.get("toolbar.shortcuts"); Object.keys(shortcuts).forEach((sc) => { const button = shortcuts[sc]; - mouseTrap.bind(sc, () => { + this._mouseTrap.bind(sc, () => { button.action(button); return false; }); @@ -317,7 +319,6 @@ export default Component.extend({ this.appEvents.on("composer:insert-text", this, "_insertText"); this.appEvents.on("composer:replace-text", this, "_replaceText"); } - this._mouseTrap = mouseTrap; if (isTesting()) { this.element.addEventListener("paste", this.paste.bind(this)); @@ -340,10 +341,7 @@ export default Component.extend({ this.appEvents.off("composer:replace-text", this, "_replaceText"); } - const mouseTrap = this._mouseTrap; - Object.keys(this.get("toolbar.shortcuts")).forEach((sc) => - mouseTrap.unbind(sc) - ); + this._mouseTrap.reset(); $(this.element.querySelector(".d-editor-preview")).off("click.preview"); if (isTesting()) { diff --git a/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js b/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js index d766575675c..cb3ad395236 100644 --- a/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js +++ b/app/assets/javascripts/discourse/app/components/edit-topic-timer-form.js @@ -8,13 +8,15 @@ import { PUBLISH_TO_CATEGORY_STATUS_TYPE, } from "discourse/controllers/edit-topic-timer"; import { FORMAT } from "select-kit/components/future-date-input-selector"; -import discourseComputed, { on } from "discourse-common/utils/decorators"; +import discourseComputed from "discourse-common/utils/decorators"; import { equal, or, readOnly } from "@ember/object/computed"; import I18n from "I18n"; import { action } from "@ember/object"; import Component from "@ember/component"; import { isEmpty } from "@ember/utils"; import { now, startOfDay, thisWeekend } from "discourse/lib/time-utils"; +import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts"; +import Mousetrap from "mousetrap"; export default Component.extend({ statusType: readOnly("topicTimer.status_type"), @@ -37,18 +39,31 @@ export default Component.extend({ ), duration: null, - @on("init") - preloadDuration() { + init() { + this._super(...arguments); + + KeyboardShortcuts.pause(); + this._mousetrap = new Mousetrap(); + + this.set("duration", this.initialDuration); + }, + + get initialDuration() { if (!this.useDuration || !this.topicTimer.duration_minutes) { - return; - } - if (this.durationType === "days") { - this.set("duration", this.topicTimer.duration_minutes / 60 / 24); + return null; + } else if (this.durationType === "days") { + return this.topicTimer.duration_minutes / 60 / 24; } else { - this.set("duration", this.topicTimer.duration_minutes / 60); + return this.topicTimer.duration_minutes / 60; } }, + willDestroyElement() { + this._super(...arguments); + this._mousetrap.reset(); + KeyboardShortcuts.unpause(); + }, + @discourseComputed("autoDeleteReplies") durationType(autoDeleteReplies) { return autoDeleteReplies ? "days" : "hours"; diff --git a/app/assets/javascripts/discourse/app/components/site-header.js b/app/assets/javascripts/discourse/app/components/site-header.js index 487fa1c620a..eac53665d6f 100644 --- a/app/assets/javascripts/discourse/app/components/site-header.js +++ b/app/assets/javascripts/discourse/app/components/site-header.js @@ -251,8 +251,8 @@ const SiteHeaderComponent = MountWidget.extend( } const header = document.querySelector("header.d-header"); - const mousetrap = new Mousetrap(header); - mousetrap.bind(["right", "left"], (e) => { + this._mousetrap = new Mousetrap(header); + this._mousetrap.bind(["right", "left"], (e) => { const activeTab = document.querySelector(".glyphs .menu-link.active"); if (activeTab) { @@ -267,8 +267,6 @@ const SiteHeaderComponent = MountWidget.extend( }); } }); - - this.set("_mousetrap", mousetrap); }, _cleanDom() { @@ -290,7 +288,7 @@ const SiteHeaderComponent = MountWidget.extend( cancel(this._scheduledRemoveAnimate); window.cancelAnimationFrame(this._scheduledMovingAnimation); - this._mousetrap.unbind(["right", "left"]); + this._mousetrap.reset(); document.removeEventListener("click", this._dismissFirstNotification); }, diff --git a/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js b/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js index cc127e490d8..e35e3a33a37 100644 --- a/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js +++ b/app/assets/javascripts/discourse/app/components/time-shortcut-picker.js @@ -16,18 +16,9 @@ import discourseComputed, { import Component from "@ember/component"; import I18n from "I18n"; -import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts"; import { action } from "@ember/object"; import { and, equal } from "@ember/object/computed"; -// global shortcuts that interfere with these modal shortcuts, they are rebound when the -// component is destroyed -// -// c createTopic -// r replyToPost -// l toggle like -// t replyAsNewTopic -const GLOBAL_SHORTCUTS_TO_PAUSE = ["c", "r", "l", "t"]; const BINDINGS = { "l t": { handler: "selectShortcut", @@ -113,10 +104,9 @@ export default Component.extend({ } }, - @on("willDestroyElement") - _resetKeyboardShortcuts() { - KeyboardShortcuts.unbind(BINDINGS); - KeyboardShortcuts.unpause(GLOBAL_SHORTCUTS_TO_PAUSE); + willDestroyElement() { + this._super(...arguments); + this.mousetrap.unbind(Object.keys(BINDINGS)); }, parsePrefilledDatetime() { @@ -157,14 +147,11 @@ export default Component.extend({ }, _bindKeyboardShortcuts() { - KeyboardShortcuts.pause(GLOBAL_SHORTCUTS_TO_PAUSE); Object.keys(BINDINGS).forEach((shortcut) => { - KeyboardShortcuts.addShortcut(shortcut, () => { + this.mousetrap.bind(shortcut, () => { let binding = BINDINGS[shortcut]; - if (binding.args) { - return this.send(binding.handler, ...binding.args); - } - this.send(binding.handler); + this.send(binding.handler, ...binding.args); + return false; }); }); }, diff --git a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js index 5b2b230fbf2..dbe5dbb6853 100644 --- a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js +++ b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js @@ -100,7 +100,7 @@ function preventKeyboardEvent(event) { export default { init(keyTrapper, container) { - this.keyTrapper = keyTrapper; + this.keyTrapper = new keyTrapper(); this.container = container; this._stopCallback(); @@ -168,6 +168,12 @@ export default { if (this.isTornDown()) { return; } + + if (!combinations) { + this.keyTrapper.paused = true; + return; + } + combinations.forEach((combo) => this.keyTrapper.unbind(combo)); }, @@ -176,10 +182,12 @@ export default { if (this.isTornDown()) { return; } - // if the keytrapper has already been torn down this will error - if (this.keyTrapper == null) { + + if (!combinations) { + this.keyTrapper.paused = false; return; } + combinations.forEach((combo) => this.bindKey(combo)); }, @@ -210,7 +218,7 @@ export default { // 'c': createTopic // } unbind(combinations) { - this.pause(Object.keys(combinations)); + Object.keys(combinations).forEach((combo) => this.keyTrapper.unbind(combo)); }, toggleBookmark(event) { @@ -758,20 +766,21 @@ export default { }, _stopCallback() { - const oldStopCallback = this.keyTrapper.prototype.stopCallback; + const prototype = Object.getPrototypeOf(this.keyTrapper); + const oldStopCallback = prototype.stopCallback; + + prototype.stopCallback = function (e, element, combo, sequence) { + if (this.paused) { + return true; + } - this.keyTrapper.prototype.stopCallback = function ( - e, - element, - combo, - sequence - ) { if ( (combo === "ctrl+f" || combo === "command+f") && element.id === "search-term" ) { return false; } + return oldStopCallback.call(this, e, element, combo, sequence); }; }, diff --git a/app/assets/javascripts/discourse/app/templates/components/bookmark.hbs b/app/assets/javascripts/discourse/app/templates/components/bookmark.hbs index f2dace34511..f9748900680 100644 --- a/app/assets/javascripts/discourse/app/templates/components/bookmark.hbs +++ b/app/assets/javascripts/discourse/app/templates/components/bookmark.hbs @@ -30,12 +30,18 @@ {{/if}}