mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 18:30:26 -06:00
DEV: uses forked Mousetrap to avoid leaking listeners (#14198)
This commit is contained in:
parent
e1581f6dfd
commit
95b15acb1e
@ -2,11 +2,6 @@ define("message-bus-client", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.MessageBus;
|
||||
});
|
||||
|
||||
define("mousetrap-global-bind", ["exports"], function (__exports__) {
|
||||
// In the Rails app it's applied from the vendored file
|
||||
__exports__.default = {};
|
||||
});
|
||||
|
||||
define("ember-buffered-proxy/proxy", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.BufferedProxy;
|
||||
});
|
||||
@ -19,8 +14,8 @@ define("xss", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.filterXSS;
|
||||
});
|
||||
|
||||
define("mousetrap", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.Mousetrap;
|
||||
define("@discourse/itsatrap", ["exports"], function (__exports__) {
|
||||
__exports__.default = window.ItsATrap;
|
||||
});
|
||||
|
||||
define("@popperjs/core", ["exports"], function (__exports__) {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import Application from "@ember/application";
|
||||
import Mousetrap from "mousetrap";
|
||||
import { buildResolver } from "discourse-common/resolver";
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
|
||||
@ -13,11 +12,6 @@ const Discourse = Application.extend({
|
||||
paste: "paste",
|
||||
},
|
||||
|
||||
reset() {
|
||||
this._super(...arguments);
|
||||
Mousetrap.reset();
|
||||
},
|
||||
|
||||
Resolver: buildResolver("discourse"),
|
||||
|
||||
_prepareInitializer(moduleName) {
|
||||
|
@ -11,7 +11,7 @@ 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 ItsATrap from "@discourse/itsatrap";
|
||||
import { Promise } from "rsvp";
|
||||
import { TIME_SHORTCUT_TYPES } from "discourse/lib/time-shortcut";
|
||||
import { action } from "@ember/object";
|
||||
@ -37,6 +37,7 @@ export default Component.extend({
|
||||
_savingBookmarkManually: null,
|
||||
_saving: null,
|
||||
_deleting: null,
|
||||
_itsatrap: null,
|
||||
postDetectedLocalDate: null,
|
||||
postDetectedLocalTime: null,
|
||||
postDetectedLocalTimezone: null,
|
||||
@ -44,7 +45,6 @@ export default Component.extend({
|
||||
userTimezone: null,
|
||||
showOptions: null,
|
||||
model: null,
|
||||
|
||||
afterSave: null,
|
||||
|
||||
@on("init")
|
||||
@ -62,6 +62,7 @@ export default Component.extend({
|
||||
prefilledDatetime: null,
|
||||
userTimezone: this.currentUser.resolvedTimezone(this.currentUser),
|
||||
showOptions: false,
|
||||
_itsatrap: new ItsATrap(),
|
||||
});
|
||||
|
||||
this.registerOnCloseHandler(this._onModalClose.bind(this));
|
||||
@ -123,9 +124,8 @@ export default Component.extend({
|
||||
_bindKeyboardShortcuts() {
|
||||
KeyboardShortcuts.pause();
|
||||
|
||||
this._mousetrap = new Mousetrap();
|
||||
Object.keys(BOOKMARK_BINDINGS).forEach((shortcut) => {
|
||||
this._mousetrap.bind(shortcut, () => {
|
||||
this._itsatrap.bind(shortcut, () => {
|
||||
let binding = BOOKMARK_BINDINGS[shortcut];
|
||||
this.send(binding.handler);
|
||||
return false;
|
||||
@ -266,7 +266,9 @@ export default Component.extend({
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
this._mousetrap.reset();
|
||||
|
||||
this._itsatrap?.destroy();
|
||||
this.set("_itsatrap", null);
|
||||
KeyboardShortcuts.unpause();
|
||||
},
|
||||
|
||||
|
@ -9,7 +9,7 @@ import { emojiUrlFor, generateCookFunction } from "discourse/lib/text";
|
||||
import { later, schedule, scheduleOnce } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import I18n from "I18n";
|
||||
import Mousetrap from "mousetrap";
|
||||
import ItsATrap from "@discourse/itsatrap";
|
||||
import { Promise } from "rsvp";
|
||||
import { SKIP } from "discourse/lib/autocomplete";
|
||||
import { categoryHashtagTriggerRule } from "discourse/lib/category-hashtags";
|
||||
@ -238,7 +238,7 @@ export default Component.extend(TextareaTextManipulation, {
|
||||
classNames: ["d-editor"],
|
||||
ready: false,
|
||||
lastSel: null,
|
||||
_mouseTrap: null,
|
||||
_itsatrap: null,
|
||||
showLink: true,
|
||||
emojiPickerIsActive: false,
|
||||
emojiStore: service("emoji-store"),
|
||||
@ -278,12 +278,12 @@ export default Component.extend(TextareaTextManipulation, {
|
||||
|
||||
scheduleOnce("afterRender", this, this._readyNow);
|
||||
|
||||
this._mouseTrap = new Mousetrap(this._textarea);
|
||||
this._itsatrap = new ItsATrap(this._textarea);
|
||||
const shortcuts = this.get("toolbar.shortcuts");
|
||||
|
||||
Object.keys(shortcuts).forEach((sc) => {
|
||||
const button = shortcuts[sc];
|
||||
this._mouseTrap.bind(sc, () => {
|
||||
this._itsatrap.bind(sc, () => {
|
||||
button.action(button);
|
||||
return false;
|
||||
});
|
||||
@ -335,7 +335,9 @@ export default Component.extend(TextareaTextManipulation, {
|
||||
this.appEvents.off("composer:replace-text", this, "_replaceText");
|
||||
}
|
||||
|
||||
this._mouseTrap.reset();
|
||||
this._itsatrap?.destroy();
|
||||
this._itsatrap = null;
|
||||
|
||||
$(this.element.querySelector(".d-editor-preview")).off("click.preview");
|
||||
|
||||
if (isTesting()) {
|
||||
|
@ -21,7 +21,7 @@ import {
|
||||
thisWeekend,
|
||||
} from "discourse/lib/time-utils";
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import Mousetrap from "mousetrap";
|
||||
import ItsATrap from "@discourse/itsatrap";
|
||||
|
||||
export default Component.extend({
|
||||
statusType: readOnly("topicTimer.status_type"),
|
||||
@ -43,12 +43,13 @@ export default Component.extend({
|
||||
"autoCloseAfterLastPost"
|
||||
),
|
||||
duration: null,
|
||||
_itsatrap: null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
KeyboardShortcuts.pause();
|
||||
this._mousetrap = new Mousetrap();
|
||||
this.set("_itsatrap", new ItsATrap());
|
||||
|
||||
this.set("duration", this.initialDuration);
|
||||
},
|
||||
@ -65,7 +66,9 @@ export default Component.extend({
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
this._mousetrap.reset();
|
||||
|
||||
this._itsatrap.destroy();
|
||||
this.set("_itsatrap", null);
|
||||
KeyboardShortcuts.unpause();
|
||||
},
|
||||
|
||||
|
@ -5,7 +5,7 @@ import PanEvents, {
|
||||
import { cancel, later, schedule } from "@ember/runloop";
|
||||
import Docking from "discourse/mixins/docking";
|
||||
import MountWidget from "discourse/components/mount-widget";
|
||||
import Mousetrap from "mousetrap";
|
||||
import ItsATrap from "@discourse/itsatrap";
|
||||
import RerenderOnDoNotDisturbChange from "discourse/mixins/rerender-on-do-not-disturb-change";
|
||||
import { observes } from "discourse-common/utils/decorators";
|
||||
import { topicTitleDecorators } from "discourse/components/topic-title";
|
||||
@ -24,7 +24,7 @@ const SiteHeaderComponent = MountWidget.extend(
|
||||
_panMenuOffset: 0,
|
||||
_scheduledRemoveAnimate: null,
|
||||
_topic: null,
|
||||
_mousetrap: null,
|
||||
_itsatrap: null,
|
||||
|
||||
@observes(
|
||||
"currentUser.unread_notifications",
|
||||
@ -258,8 +258,8 @@ const SiteHeaderComponent = MountWidget.extend(
|
||||
}
|
||||
|
||||
const header = document.querySelector("header.d-header");
|
||||
this._mousetrap = new Mousetrap(header);
|
||||
this._mousetrap.bind(["right", "left"], (e) => {
|
||||
this._itsatrap = new ItsATrap(header);
|
||||
this._itsatrap.bind(["right", "left"], (e) => {
|
||||
const activeTab = document.querySelector(".glyphs .menu-link.active");
|
||||
|
||||
if (activeTab) {
|
||||
@ -294,7 +294,8 @@ const SiteHeaderComponent = MountWidget.extend(
|
||||
|
||||
cancel(this._scheduledRemoveAnimate);
|
||||
|
||||
this._mousetrap.reset();
|
||||
this._itsatrap?.destroy();
|
||||
this._itsatrap = null;
|
||||
|
||||
document.removeEventListener("click", this._dismissFirstNotification);
|
||||
},
|
||||
|
@ -67,6 +67,8 @@ export default Component.extend({
|
||||
customDate: null,
|
||||
customTime: null,
|
||||
|
||||
_itsatrap: null,
|
||||
|
||||
defaultCustomReminderTime: `0${START_OF_DAY_HOUR}:00`,
|
||||
|
||||
@on("init")
|
||||
@ -101,7 +103,8 @@ export default Component.extend({
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
this.mousetrap.unbind(Object.keys(BINDINGS));
|
||||
|
||||
this._itsatrap.unbind(Object.keys(BINDINGS));
|
||||
},
|
||||
|
||||
parsePrefilledDatetime() {
|
||||
@ -143,7 +146,7 @@ export default Component.extend({
|
||||
|
||||
_bindKeyboardShortcuts() {
|
||||
Object.keys(BINDINGS).forEach((shortcut) => {
|
||||
this.mousetrap.bind(shortcut, () => {
|
||||
this._itsatrap.bind(shortcut, () => {
|
||||
let binding = BINDINGS[shortcut];
|
||||
this.send(binding.handler, ...binding.args);
|
||||
return false;
|
||||
|
@ -1,15 +1,11 @@
|
||||
import KeyboardShortcuts from "discourse/lib/keyboard-shortcuts";
|
||||
import Mousetrap from "mousetrap";
|
||||
import bindGlobal from "mousetrap-global-bind";
|
||||
import ItsATrap from "@discourse/itsatrap";
|
||||
|
||||
export default {
|
||||
name: "keyboard-shortcuts",
|
||||
|
||||
initialize(container) {
|
||||
// Ensure mousetrap-global-bind is executed
|
||||
void bindGlobal;
|
||||
|
||||
KeyboardShortcuts.init(Mousetrap, container);
|
||||
KeyboardShortcuts.init(ItsATrap, container);
|
||||
KeyboardShortcuts.bindEvents();
|
||||
},
|
||||
|
||||
|
@ -122,10 +122,8 @@ export default {
|
||||
},
|
||||
|
||||
teardown() {
|
||||
if (this.keyTrapper) {
|
||||
this.keyTrapper.reset();
|
||||
this.keyTrapper = null;
|
||||
}
|
||||
this.keyTrapper?.destroy();
|
||||
this.keyTrapper = null;
|
||||
this.container = null;
|
||||
},
|
||||
|
||||
@ -207,7 +205,7 @@ export default {
|
||||
**/
|
||||
addShortcut(shortcut, callback, opts = {}) {
|
||||
// we trim but leave whitespace between characters, as shortcuts
|
||||
// like `z z` are valid for Mousetrap
|
||||
// like `z z` are valid for ItsATrap
|
||||
shortcut = shortcut.trim();
|
||||
let newBinding = Object.assign({ handler: callback }, opts);
|
||||
this.bindKey(shortcut, newBinding);
|
||||
|
@ -40,7 +40,7 @@
|
||||
onTimeSelected=(action "onTimeSelected")
|
||||
customOptions=customTimeShortcutOptions
|
||||
additionalOptionsToShow=additionalTimeShortcutOptions
|
||||
mousetrap=_mousetrap
|
||||
_itsatrap=_itsatrap
|
||||
}}
|
||||
{{else}}
|
||||
<div class="alert alert-info">{{html-safe (i18n "bookmarks.no_timezone" basePath=(base-path))}}</div>
|
||||
|
@ -24,7 +24,7 @@
|
||||
onTimeSelected=onTimeSelected
|
||||
customOptions=customTimeShortcutOptions
|
||||
hiddenOptions=hiddenTimeShortcutOptions
|
||||
mousetrap=_mousetrap
|
||||
_itsatrap=_itsatrap
|
||||
}}
|
||||
{{/if}}
|
||||
{{#if useDuration}}
|
||||
|
@ -53,8 +53,6 @@
|
||||
"loader.js": "^4.7.0",
|
||||
"message-bus-client": "^3.3.0",
|
||||
"messageformat": "0.1.5",
|
||||
"mousetrap": "^1.6.5",
|
||||
"mousetrap-global-bind": "^1.1.0",
|
||||
"pretender": "^3.4.7",
|
||||
"pretty-text": "^1.0.0",
|
||||
"qunit": "^2.14.0",
|
||||
@ -62,7 +60,8 @@
|
||||
"sass": "^1.32.8",
|
||||
"select-kit": "^1.0.0",
|
||||
"sinon": "^9.2.0",
|
||||
"virtual-dom": "^2.1.1"
|
||||
"virtual-dom": "^2.1.1",
|
||||
"@discourse/itsatrap": "^2.0.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.*",
|
||||
|
@ -25,8 +25,7 @@
|
||||
//= require jquery.tagsinput.js
|
||||
//= require jquery.sortable.js
|
||||
//= require lodash.js
|
||||
//= require mousetrap.js
|
||||
//= require mousetrap-global-bind.js
|
||||
//= require itsatrap.js
|
||||
//= require rsvp.js
|
||||
//= require show-html.js
|
||||
//= require uppy.js
|
||||
|
@ -18,8 +18,7 @@
|
||||
//= require jquery.tagsinput.js
|
||||
//= require jquery.sortable.js
|
||||
//= require lodash.js
|
||||
//= require mousetrap.js
|
||||
//= require mousetrap-global-bind.js
|
||||
//= require itsatrap.js
|
||||
//= require rsvp.js
|
||||
//= require show-html.js
|
||||
//= require uppy.js
|
||||
|
@ -928,6 +928,11 @@
|
||||
exec-sh "^0.3.2"
|
||||
minimist "^1.2.0"
|
||||
|
||||
"@discourse/itsatrap@^2.0.10":
|
||||
version "2.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@discourse/itsatrap/-/itsatrap-2.0.10.tgz#c7e750eeb32b54e769e952c4ecc472213eb1385a"
|
||||
integrity sha512-Jn1gdiyHMGUsmUfLFf4Q7VnTAv0l7NePbegU6pKhKHEmbzV3FosGxq30fTOYgVyTS1bxqGjlA6LvQttJpv3ROw==
|
||||
|
||||
"@ember-data/rfc395-data@^0.0.4":
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz#ecb86efdf5d7733a76ff14ea651a1b0ed1f8a843"
|
||||
@ -8586,16 +8591,6 @@ morgan@^1.10.0:
|
||||
on-finished "~2.3.0"
|
||||
on-headers "~1.0.2"
|
||||
|
||||
mousetrap-global-bind@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/mousetrap-global-bind/-/mousetrap-global-bind-1.1.0.tgz#cd7de9222bd0646fa2e010d54c84a74c26a88edd"
|
||||
integrity sha1-zX3pIivQZG+i4BDVTISnTCaojt0=
|
||||
|
||||
mousetrap@^1.6.5:
|
||||
version "1.6.5"
|
||||
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9"
|
||||
integrity sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==
|
||||
|
||||
mout@^1.0.0:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/mout/-/mout-1.2.2.tgz#c9b718a499806a0632cede178e80f436259e777d"
|
||||
|
@ -123,7 +123,7 @@ def dependencies
|
||||
}, {
|
||||
source: 'markdown-it/dist/markdown-it.js'
|
||||
}, {
|
||||
source: 'mousetrap/mousetrap.js'
|
||||
source: '@discourse/itsatrap/itsatrap.js'
|
||||
}, {
|
||||
source: 'moment/moment.js'
|
||||
}, {
|
||||
@ -138,8 +138,6 @@ def dependencies
|
||||
}, {
|
||||
source: 'moment-timezone-names-translations/locales/.',
|
||||
destination: 'moment-timezone-names-locale'
|
||||
}, {
|
||||
source: 'mousetrap/plugins/global-bind/mousetrap-global-bind.js'
|
||||
}, {
|
||||
source: 'resumablejs/resumable.js'
|
||||
}, {
|
||||
|
@ -10,9 +10,9 @@
|
||||
"@highlightjs/cdn-assets": "^10.6.0",
|
||||
"@json-editor/json-editor": "^2.5.2",
|
||||
"@popperjs/core": "v2.9.3",
|
||||
"@uppy/core": "^2.0.1",
|
||||
"@uppy/aws-s3": "^2.0.1",
|
||||
"@uppy/aws-s3-multipart": "^2.0.2",
|
||||
"@uppy/core": "^2.0.1",
|
||||
"@uppy/drop-target": "^1.0.1",
|
||||
"@uppy/xhr-upload": "^2.0.1",
|
||||
"ace-builds": "1.4.12",
|
||||
@ -33,7 +33,6 @@
|
||||
"moment": "2.29.1",
|
||||
"moment-timezone": "0.5.31",
|
||||
"moment-timezone-names-translations": "https://github.com/discourse/moment-timezone-names-translations",
|
||||
"mousetrap": "https://github.com/discourse/mousetrap#firefox-alt-key",
|
||||
"pikaday": "1.8.0",
|
||||
"resumablejs": "1.1.0",
|
||||
"spectrum-colorpicker": "1.8.0",
|
||||
@ -42,7 +41,8 @@
|
||||
"workbox-expiration": "^4.3.1",
|
||||
"workbox-routing": "^4.3.1",
|
||||
"workbox-strategies": "^4.3.1",
|
||||
"workbox-sw": "^4.3.1"
|
||||
"workbox-sw": "^4.3.1",
|
||||
"@discourse/itsatrap": "^2.0.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arkweid/lefthook": "^0.7.2",
|
||||
|
1159
vendor/assets/javascripts/itsatrap.js
vendored
Normal file
1159
vendor/assets/javascripts/itsatrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
||||
/**
|
||||
* adds a bindGlobal method to Mousetrap that allows you to
|
||||
* bind specific keyboard shortcuts that will still work
|
||||
* inside a text input field
|
||||
*
|
||||
* usage:
|
||||
* Mousetrap.bindGlobal('ctrl+s', _saveChanges);
|
||||
*/
|
||||
/* global Mousetrap:true */
|
||||
(function(Mousetrap) {
|
||||
if (! Mousetrap) {
|
||||
return;
|
||||
}
|
||||
var _globalCallbacks = {};
|
||||
var _originalStopCallback = Mousetrap.prototype.stopCallback;
|
||||
|
||||
Mousetrap.prototype.stopCallback = function(e, element, combo, sequence) {
|
||||
var self = this;
|
||||
|
||||
if (self.paused) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_globalCallbacks[combo] || _globalCallbacks[sequence]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _originalStopCallback.call(self, e, element, combo);
|
||||
};
|
||||
|
||||
Mousetrap.prototype.bindGlobal = function(keys, callback, action) {
|
||||
var self = this;
|
||||
self.bind(keys, callback, action);
|
||||
|
||||
if (keys instanceof Array) {
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
_globalCallbacks[keys[i]] = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_globalCallbacks[keys] = true;
|
||||
};
|
||||
|
||||
Mousetrap.init();
|
||||
}) (typeof Mousetrap !== "undefined" ? Mousetrap : undefined);
|
1058
vendor/assets/javascripts/mousetrap.js
vendored
1058
vendor/assets/javascripts/mousetrap.js
vendored
File diff suppressed because it is too large
Load Diff
@ -245,6 +245,11 @@
|
||||
exec-sh "^0.3.2"
|
||||
minimist "^1.2.0"
|
||||
|
||||
"@discourse/itsatrap@^2.0.10":
|
||||
version "2.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@discourse/itsatrap/-/itsatrap-2.0.10.tgz#c7e750eeb32b54e769e952c4ecc472213eb1385a"
|
||||
integrity sha512-Jn1gdiyHMGUsmUfLFf4Q7VnTAv0l7NePbegU6pKhKHEmbzV3FosGxq30fTOYgVyTS1bxqGjlA6LvQttJpv3ROw==
|
||||
|
||||
"@ember-data/rfc395-data@^0.0.4":
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@ember-data/rfc395-data/-/rfc395-data-0.0.4.tgz#ecb86efdf5d7733a76ff14ea651a1b0ed1f8a843"
|
||||
@ -3116,10 +3121,6 @@ moment@2.29.1:
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.0.tgz#fcbef955844d91deb55438613ddcec56e86a3425"
|
||||
integrity sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA==
|
||||
|
||||
"mousetrap@https://github.com/discourse/mousetrap#firefox-alt-key":
|
||||
version "1.6.5"
|
||||
resolved "https://github.com/discourse/mousetrap#cc8e2c0b9229e1a01ce68de4f339b6fd35503041"
|
||||
|
||||
ms@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||
|
Loading…
Reference in New Issue
Block a user