DEV: Wrap `Ember.run.debounce`. (#11352)

We want to wrap the `Ember.run.debounce` function and internally call `Ember.run` instead when running tests.

This commit changes discourseDebounce to work the same way as `Ember.run.debounce`.

Now that `discourseDebounce` works exactly like `Ember.run.debounce`, let's replace it and only use `DiscourseDebounce` from now on.

Move debounce to discourse-common to be able to reuse it in different bundles

Keep old debounce file for backwards-compatibility
This commit is contained in:
Roman Rizzi 2020-12-10 11:01:42 -03:00 committed by GitHub
parent fb2e24a77a
commit 8b426431a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 519 additions and 353 deletions

View File

@ -1,7 +1,7 @@
import { observes, on } from "discourse-common/utils/decorators";
import Component from "@ember/component";
import I18n from "I18n";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { scheduleOnce } from "@ember/runloop";
export default Component.extend({
@ -33,9 +33,7 @@ export default Component.extend({
}
},
@on("init")
@observes("logs.[]")
_updateFormattedLogs: discourseDebounce(function () {
_updateFormattedLogsFunc: function () {
const logs = this.logs;
if (logs.length === 0) {
return;
@ -57,7 +55,13 @@ export default Component.extend({
this.renderLogs();
scheduleOnce("afterRender", this, this._scrollDown);
}, 150),
},
@on("init")
@observes("logs.[]")
_updateFormattedLogs() {
discourseDebounce(this, this._updateFormattedLogsFunc, 150);
},
renderLogs() {
const formattedLogs = this.formattedLogs;

View File

@ -1,8 +1,9 @@
import { debounce, schedule } from "@ember/runloop";
import Component from "@ember/component";
import discourseDebounce from "discourse-common/lib/debounce";
import loadScript from "discourse/lib/load-script";
import { makeArray } from "discourse-common/lib/helpers";
import { number } from "discourse/lib/formatter";
import { schedule } from "@ember/runloop";
export default Component.extend({
classNames: ["admin-report-chart"],
@ -14,7 +15,7 @@ export default Component.extend({
this._super(...arguments);
this.resizeHandler = () =>
debounce(this, this._scheduleChartRendering, 500);
discourseDebounce(this, this._scheduleChartRendering, 500);
},
didInsertElement() {
@ -34,7 +35,7 @@ export default Component.extend({
didReceiveAttrs() {
this._super(...arguments);
debounce(this, this._scheduleChartRendering, 100);
discourseDebounce(this, this._scheduleChartRendering, 100);
},
_scheduleChartRendering() {

View File

@ -1,8 +1,9 @@
import { debounce, schedule } from "@ember/runloop";
import Component from "@ember/component";
import discourseDebounce from "discourse-common/lib/debounce";
import loadScript from "discourse/lib/load-script";
import { makeArray } from "discourse-common/lib/helpers";
import { number } from "discourse/lib/formatter";
import { schedule } from "@ember/runloop";
export default Component.extend({
classNames: ["admin-report-chart", "admin-report-stacked-chart"],
@ -11,7 +12,7 @@ export default Component.extend({
this._super(...arguments);
this.resizeHandler = () =>
debounce(this, this._scheduleChartRendering, 500);
discourseDebounce(this, this._scheduleChartRendering, 500);
},
didInsertElement() {
@ -31,7 +32,7 @@ export default Component.extend({
didReceiveAttrs() {
this._super(...arguments);
debounce(this, this._scheduleChartRendering, 100);
discourseDebounce(this, this._scheduleChartRendering, 100);
},
_scheduleChartRendering() {

View File

@ -1,7 +1,7 @@
import Controller from "@ember/controller";
import { INPUT_DELAY } from "discourse-common/config/environment";
import { debounce } from "@ember/runloop";
import discourseComputed from "discourse-common/utils/decorators";
import discourseDebounce from "discourse-common/lib/debounce";
const { get } = Ember;
@ -34,7 +34,7 @@ export default Controller.extend({
actions: {
filterReports(filter) {
debounce(this, this._performFiltering, filter, INPUT_DELAY);
discourseDebounce(this, this._performFiltering, filter, INPUT_DELAY);
},
},

View File

@ -1,11 +1,11 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
import { INPUT_DELAY } from "discourse-common/config/environment";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,user,address,type}")
filterEmailLogs: discourseDebounce(function () {
this.loadLogs();
}, INPUT_DELAY),
filterEmailLogs() {
discourseDebounce(this, this.loadLogs, INPUT_DELAY);
},
});

View File

@ -1,14 +1,14 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
import { INPUT_DELAY } from "discourse-common/config/environment";
import IncomingEmail from "admin/models/incoming-email";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,from,to,subject}")
filterIncomingEmails: discourseDebounce(function () {
this.loadLogs(IncomingEmail);
}, INPUT_DELAY),
filterIncomingEmails() {
discourseDebounce(this, this.loadLogs, IncomingEmail, INPUT_DELAY);
},
actions: {
loadMore() {

View File

@ -1,14 +1,14 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
import { INPUT_DELAY } from "discourse-common/config/environment";
import IncomingEmail from "admin/models/incoming-email";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,from,to,subject,error}")
filterIncomingEmails: discourseDebounce(function () {
this.loadLogs(IncomingEmail);
}, INPUT_DELAY),
filterIncomingEmails() {
discourseDebounce(this, this.loadLogs, IncomingEmail, INPUT_DELAY);
},
actions: {
loadMore() {

View File

@ -1,11 +1,11 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
import { INPUT_DELAY } from "discourse-common/config/environment";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,user,address,type,reply_key}")
filterEmailLogs: discourseDebounce(function () {
this.loadLogs();
}, INPUT_DELAY),
filterEmailLogs() {
discourseDebounce(this, this.loadLogs, INPUT_DELAY);
},
});

View File

@ -1,11 +1,11 @@
import AdminEmailLogsController from "admin/controllers/admin-email-logs";
import { INPUT_DELAY } from "discourse-common/config/environment";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { observes } from "discourse-common/utils/decorators";
export default AdminEmailLogsController.extend({
@observes("filter.{status,user,address,type}")
filterEmailLogs: discourseDebounce(function () {
this.loadLogs();
}, INPUT_DELAY),
filterEmailLogs() {
discourseDebounce(this, this.loadLogs, INPUT_DELAY);
},
});

View File

@ -3,7 +3,7 @@ import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
import ScreenedIpAddress from "admin/models/screened-ip-address";
import bootbox from "bootbox";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { exportEntity } from "discourse/lib/export-csv";
import { observes } from "discourse-common/utils/decorators";
import { outputExportResult } from "discourse/lib/export-result";
@ -13,13 +13,17 @@ export default Controller.extend({
filter: null,
savedIpAddress: null,
@observes("filter")
show: discourseDebounce(function () {
_debouncedShow() {
this.set("loading", true);
ScreenedIpAddress.findAll(this.filter).then((result) => {
this.setProperties({ model: result, loading: false });
});
}, INPUT_DELAY),
},
@observes("filter")
show() {
discourseDebounce(this, this._debouncedShow, INPUT_DELAY);
},
actions: {
allow(record) {

View File

@ -3,20 +3,24 @@ import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
import Permalink from "admin/models/permalink";
import bootbox from "bootbox";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { observes } from "discourse-common/utils/decorators";
export default Controller.extend({
loading: false,
filter: null,
@observes("filter")
show: discourseDebounce(function () {
_debouncedShow() {
Permalink.findAll(this.filter).then((result) => {
this.set("model", result);
this.set("loading", false);
});
}, INPUT_DELAY),
},
@observes("filter")
show() {
discourseDebounce(this, this._debouncedShow, INPUT_DELAY);
},
actions: {
recordAdded(arg) {

View File

@ -2,7 +2,7 @@ import Controller from "@ember/controller";
import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
import { alias } from "@ember/object/computed";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { isEmpty } from "@ember/utils";
import { observes } from "discourse-common/utils/decorators";
@ -112,13 +112,19 @@ export default Controller.extend({
},
@observes("filter", "onlyOverridden", "model")
filterContent: discourseDebounce(function () {
if (this._skipBounce) {
this.set("_skipBounce", false);
} else {
this.filterContentNow(this.categoryNameKey);
}
}, INPUT_DELAY),
filterContent() {
discourseDebounce(
this,
() => {
if (this._skipBounce) {
this.set("_skipBounce", false);
} else {
this.filterContentNow(this.categoryNameKey);
}
},
INPUT_DELAY
);
},
actions: {
clearFilter() {

View File

@ -1,5 +1,5 @@
import Controller from "@ember/controller";
import { debounce } from "@ember/runloop";
import discourseDebounce from "discourse-common/lib/debounce";
let lastSearch;
export default Controller.extend({
@ -28,14 +28,14 @@ export default Controller.extend({
toggleOverridden() {
this.toggleProperty("overridden");
this.set("searching", true);
debounce(this, this._performSearch, 400);
discourseDebounce(this, this._performSearch, 400);
},
search() {
const q = this.q;
if (q !== lastSearch) {
this.set("searching", true);
debounce(this, this._performSearch, 400);
discourseDebounce(this, this._performSearch, 400);
lastSearch = q;
}
},

View File

@ -4,7 +4,7 @@ import CanCheckEmails from "discourse/mixins/can-check-emails";
import Controller from "@ember/controller";
import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { i18n } from "discourse/lib/computed";
export default Controller.extend(CanCheckEmails, {
@ -32,9 +32,9 @@ export default Controller.extend(CanCheckEmails, {
},
@observes("listFilter")
_filterUsers: discourseDebounce(function () {
this.resetFilters();
}, INPUT_DELAY),
_filterUsers() {
discourseDebounce(this, this.resetFilters, INPUT_DELAY);
},
resetFilters() {
this._page = 1;

View File

@ -2,7 +2,7 @@ import Controller from "@ember/controller";
import EmberObject from "@ember/object";
import { INPUT_DELAY } from "discourse-common/config/environment";
import { alias } from "@ember/object/computed";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { isEmpty } from "@ember/utils";
import { observes } from "discourse-common/utils/decorators";
@ -48,10 +48,16 @@ export default Controller.extend({
},
@observes("filter")
filterContent: discourseDebounce(function () {
this.filterContentNow();
this.set("filtered", !isEmpty(this.filter));
}, INPUT_DELAY),
filterContent() {
discourseDebounce(
this,
function () {
this.filterContentNow();
this.set("filtered", !isEmpty(this.filter));
},
INPUT_DELAY
);
},
actions: {
clearFilter() {

View File

@ -0,0 +1,15 @@
import { debounce, run } from "@ember/runloop";
import { isTesting } from "discourse-common/config/environment";
/**
Debounce a Javascript function. This means if it's called many times in a time limit it
should only be executed once (at the end of the limit counted from the last call made).
Original function will be called with the context and arguments from the last call made.
**/
export default function () {
if (isTesting()) {
return run(...arguments);
} else {
return debounce(...arguments);
}
}

View File

@ -1,5 +1,5 @@
import Component from "@ember/component";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { get } from "@ember/object";
import { isEmpty } from "@ember/utils";
import { next } from "@ember/runloop";
@ -30,31 +30,38 @@ export default Component.extend({
this.set("loading", false);
},
search: discourseDebounce(function (title) {
const currentTopicId = this.currentTopicId;
search(title) {
discourseDebounce(
this,
function () {
const currentTopicId = this.currentTopicId;
if (isEmpty(title)) {
this.setProperties({ messages: null, loading: false });
return;
}
if (isEmpty(title)) {
this.setProperties({ messages: null, loading: false });
return;
}
searchForTerm(title, {
typeFilter: "private_messages",
searchForId: true,
restrictToArchetype: "private_message",
}).then((results) => {
if (results && results.posts && results.posts.length > 0) {
this.set(
"messages",
results.posts
.mapBy("topic")
.filter((t) => t.get("id") !== currentTopicId)
);
} else {
this.setProperties({ messages: null, loading: false });
}
});
}, 300),
searchForTerm(title, {
typeFilter: "private_messages",
searchForId: true,
restrictToArchetype: "private_message",
}).then((results) => {
if (results && results.posts && results.posts.length > 0) {
this.set(
"messages",
results.posts
.mapBy("topic")
.filter((t) => t.get("id") !== currentTopicId)
);
} else {
this.setProperties({ messages: null, loading: false });
}
});
},
title,
300
);
},
actions: {
chooseMessage(message) {

View File

@ -1,6 +1,6 @@
import discourseComputed, { observes } from "discourse-common/utils/decorators";
import Component from "@ember/component";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { isEmpty } from "@ember/utils";
import { next } from "@ember/runloop";
import { searchForTerm } from "discourse/lib/search";
@ -64,37 +64,46 @@ export default Component.extend({
this.set("loading", false);
},
search: discourseDebounce(function (title) {
if (!this.element || this.isDestroying || this.isDestroyed) {
return;
}
search(title) {
discourseDebounce(
this,
function () {
if (!this.element || this.isDestroying || this.isDestroyed) {
return;
}
if (isEmpty(title) && isEmpty(this.additionalFilters)) {
this.setProperties({ topics: null, loading: false });
return;
}
if (isEmpty(title) && isEmpty(this.additionalFilters)) {
this.setProperties({ topics: null, loading: false });
return;
}
const currentTopicId = this.currentTopicId;
const titleWithFilters = `${title} ${this.additionalFilters}`;
let searchParams = {};
const currentTopicId = this.currentTopicId;
const titleWithFilters = `${title} ${this.additionalFilters}`;
let searchParams = {};
if (!isEmpty(title)) {
searchParams.typeFilter = "topic";
searchParams.restrictToArchetype = "regular";
searchParams.searchForId = true;
}
if (!isEmpty(title)) {
searchParams.typeFilter = "topic";
searchParams.restrictToArchetype = "regular";
searchParams.searchForId = true;
}
searchForTerm(titleWithFilters, searchParams).then((results) => {
if (results && results.posts && results.posts.length > 0) {
this.set(
"topics",
results.posts.mapBy("topic").filter((t) => t.id !== currentTopicId)
);
} else {
this.setProperties({ topics: null, loading: false });
}
});
}, 300),
searchForTerm(titleWithFilters, searchParams).then((results) => {
if (results && results.posts && results.posts.length > 0) {
this.set(
"topics",
results.posts
.mapBy("topic")
.filter((t) => t.id !== currentTopicId)
);
} else {
this.setProperties({ topics: null, loading: false });
}
});
},
title,
300
);
},
actions: {
chooseTopic(topic) {

View File

@ -1,16 +1,10 @@
import {
cancel,
debounce,
later,
run,
schedule,
throttle,
} from "@ember/runloop";
import { cancel, later, run, schedule, throttle } from "@ember/runloop";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
import Component from "@ember/component";
import Composer from "discourse/models/composer";
import KeyEnterEscape from "discourse/mixins/key-enter-escape";
import afterTransition from "discourse/lib/after-transition";
import discourseDebounce from "discourse-common/lib/debounce";
import { headerHeight } from "discourse/components/site-header";
import { iOSWithVisualViewport } from "discourse/lib/utilities";
import positioningWorkaround from "discourse/lib/safari-hacks";
@ -76,7 +70,7 @@ export default Component.extend(KeyEnterEscape, {
return;
}
debounce(this, this.debounceMove, 300);
discourseDebounce(this, this.debounceMove, 300);
});
},

View File

@ -15,7 +15,6 @@ import {
inCodeBlock,
tinyAvatar,
} from "discourse/lib/utilities";
import { debounce, later, next, run, schedule, throttle } from "@ember/runloop";
import discourseComputed, {
observes,
on,
@ -28,12 +27,14 @@ import {
fetchUnseenMentions,
linkSeenMentions,
} from "discourse/lib/link-mentions";
import { later, next, run, schedule, throttle } from "@ember/runloop";
import Component from "@ember/component";
import Composer from "discourse/models/composer";
import EmberObject from "@ember/object";
import I18n from "I18n";
import { ajax } from "discourse/lib/ajax";
import bootbox from "bootbox";
import discourseDebounce from "discourse-common/lib/debounce";
import { findRawTemplate } from "discourse-common/lib/raw-templates";
import getURL from "discourse-common/lib/get-url";
import { iconHTML } from "discourse-common/lib/icon-library";
@ -905,7 +906,7 @@ export default Component.extend({
// Paint mentions
const unseenMentions = linkSeenMentions($preview, this.siteSettings);
if (unseenMentions.length) {
debounce(
discourseDebounce(
this,
this._renderUnseenMentions,
$preview,
@ -920,7 +921,7 @@ export default Component.extend({
// Paint category and tag hashtags
const unseenHashtags = linkSeenHashtags($preview);
if (unseenHashtags.length > 0) {
debounce(this, this._renderUnseenHashtags, $preview, 450);
discourseDebounce(this, this._renderUnseenHashtags, $preview, 450);
}
// Paint oneboxes
@ -947,7 +948,7 @@ export default Component.extend({
}
};
debounce(this, paintFunc, 450);
discourseDebounce(this, paintFunc, 450);
// Short upload urls need resolution
resolveAllShortUrls(ajax, this.siteSettings, $preview[0]);

View File

@ -1,10 +1,11 @@
import { alias, or } from "@ember/object/computed";
import { debounce, next, schedule } from "@ember/runloop";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { next, schedule } from "@ember/runloop";
import Component from "@ember/component";
import EmberObject from "@ember/object";
import I18n from "I18n";
import { ajax } from "discourse/lib/ajax";
import discourseDebounce from "discourse-common/lib/debounce";
import { isTesting } from "discourse-common/config/environment";
import { load } from "pretty-text/oneboxer";
import { lookupCache } from "pretty-text/oneboxer-cache";
@ -22,7 +23,7 @@ export default Component.extend({
}
if (this.get("composer.titleLength") > 0) {
debounce(this, this._titleChanged, 10);
discourseDebounce(this, this._titleChanged, 10);
}
},
@ -83,7 +84,7 @@ export default Component.extend({
this._checkForUrl()
);
} else {
debounce(this, this._checkForUrl, 500);
discourseDebounce(this, this._checkForUrl, 500);
}
},

View File

@ -5,13 +5,13 @@ import {
inCodeBlock,
safariHacksDisabled,
} from "discourse/lib/utilities";
import { debounce, later, next, schedule, scheduleOnce } from "@ember/runloop";
import discourseComputed, {
observes,
on,
} from "discourse-common/utils/decorators";
import { emojiSearch, isSkinTonableEmoji } from "pretty-text/emoji";
import { emojiUrlFor, generateCookFunction } from "discourse/lib/text";
import { later, next, schedule, scheduleOnce } from "@ember/runloop";
import Component from "@ember/component";
import I18n from "I18n";
import Mousetrap from "mousetrap";
@ -19,6 +19,7 @@ import { Promise } from "rsvp";
import { SKIP } from "discourse/lib/autocomplete";
import { categoryHashtagTriggerRule } from "discourse/lib/category-hashtags";
import deprecated from "discourse-common/lib/deprecated";
import discourseDebounce from "discourse-common/lib/debounce";
import { findRawTemplate } from "discourse-common/lib/raw-templates";
import { getRegister } from "discourse-common/lib/get-owner";
import { isEmpty } from "@ember/utils";
@ -414,7 +415,7 @@ export default Component.extend({
if (isTesting()) {
this._updatePreview();
} else {
debounce(this, this._updatePreview, 30);
discourseDebounce(this, this._updatePreview, 30);
}
},

View File

@ -7,7 +7,7 @@ import I18n from "I18n";
import { action } from "@ember/object";
import { ajax } from "discourse/lib/ajax";
import { convertIconClass } from "discourse-common/lib/icon-library";
import { debounce } from "@ember/runloop";
import discourseDebounce from "discourse-common/lib/debounce";
import { escapeExpression } from "discourse/lib/utilities";
import getURL from "discourse-common/lib/get-url";
import { htmlSafe } from "@ember/template";
@ -34,7 +34,7 @@ export default Component.extend({
@observes("model.flair_icon")
_loadSVGIcon(flairIcon) {
if (flairIcon) {
debounce(this, this._loadIcon, 1000);
discourseDebounce(this, this._loadIcon, 1000);
}
},

View File

@ -3,7 +3,7 @@ import Component from "@ember/component";
import EmberObject from "@ember/object";
import Group from "discourse/models/group";
import I18n from "I18n";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { isEmpty } from "@ember/utils";
import { not } from "@ember/object/computed";
import { popupAjaxError } from "discourse/lib/ajax-error";
@ -64,40 +64,46 @@ export default Component.extend({
);
},
checkGroupName: discourseDebounce(function () {
if (isEmpty(this.nameInput)) {
return;
}
Group.checkName(this.nameInput)
.then((response) => {
const validationName = "uniqueNameValidation";
if (response.available) {
this.set(
validationName,
EmberObject.create({
ok: true,
reason: I18n.t("admin.groups.new.name.available"),
})
);
this.set("disableSave", false);
this.set("model.name", this.nameInput);
} else {
let reason;
if (response.errors) {
reason = response.errors.join(" ");
} else {
reason = I18n.t("admin.groups.new.name.not_available");
}
this.set(validationName, this._failedInputValidation(reason));
checkGroupName() {
discourseDebounce(
this,
function () {
if (isEmpty(this.nameInput)) {
return;
}
})
.catch(popupAjaxError);
}, 500),
Group.checkName(this.nameInput)
.then((response) => {
const validationName = "uniqueNameValidation";
if (response.available) {
this.set(
validationName,
EmberObject.create({
ok: true,
reason: I18n.t("admin.groups.new.name.available"),
})
);
this.set("disableSave", false);
this.set("model.name", this.nameInput);
} else {
let reason;
if (response.errors) {
reason = response.errors.join(" ");
} else {
reason = I18n.t("admin.groups.new.name.not_available");
}
this.set(validationName, this._failedInputValidation(reason));
}
})
.catch(popupAjaxError);
},
500
);
},
_failedInputValidation(reason) {
this.set("disableSave", true);

View File

@ -9,7 +9,7 @@ import Sharing from "discourse/lib/sharing";
import { action } from "@ember/object";
import { alias } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { getAbsoluteURL } from "discourse-common/lib/get-url";
import { schedule } from "@ember/runloop";
import toMarkdown from "discourse/lib/to-markdown";
@ -183,10 +183,9 @@ export default Component.extend({
const { isWinphone, isAndroid } = this.capabilities;
const wait = isWinphone || isAndroid ? INPUT_DELAY : 25;
const onSelectionChanged = discourseDebounce(
() => this._selectionChanged(),
wait
);
const onSelectionChanged = () => {
discourseDebounce(this, this._selectionChanged, wait);
};
$(document)
.on("mousedown.quote-button", (e) => {

View File

@ -1,7 +1,8 @@
import { cloak, uncloak } from "discourse/widgets/post-stream";
import { debounce, next, scheduleOnce } from "@ember/runloop";
import { next, scheduleOnce } from "@ember/runloop";
import DiscourseURL from "discourse/lib/url";
import MountWidget from "discourse/components/mount-widget";
import discourseDebounce from "discourse-common/lib/debounce";
import { isWorkaroundActive } from "discourse/lib/safari-hacks";
import offsetCalculator from "discourse/lib/offset-calculator";
import { inject as service } from "@ember/service";
@ -309,12 +310,13 @@ export default MountWidget.extend({
},
_debouncedScroll() {
debounce(this, this._scrollTriggered, 10);
discourseDebounce(this, this._scrollTriggered, 10);
},
didInsertElement() {
this._super(...arguments);
const debouncedScroll = () => debounce(this, this._scrollTriggered, 10);
const debouncedScroll = () =>
discourseDebounce(this, this._scrollTriggered, 10);
this._previouslyNearby = {};

View File

@ -1,8 +1,9 @@
import { cancel, debounce, next } from "@ember/runloop";
import { cancel, next } from "@ember/runloop";
import { isLTR, isRTL, siteDir } from "discourse/lib/text-direction";
import I18n from "I18n";
import TextField from "@ember/component/text-field";
import discourseComputed from "discourse-common/utils/decorators";
import discourseDebounce from "discourse-common/lib/debounce";
const DEBOUNCE_MS = 500;
@ -38,7 +39,11 @@ export default TextField.extend({
}
if (this.onChange) {
cancel(this._timer);
this._timer = debounce(this, this._debouncedChange, DEBOUNCE_MS);
this._timer = discourseDebounce(
this,
this._debouncedChange,
DEBOUNCE_MS
);
}
}
},

View File

@ -3,9 +3,10 @@ import PanEvents, {
SWIPE_VELOCITY,
SWIPE_VELOCITY_THRESHOLD,
} from "discourse/mixins/pan-events";
import { debounce, later } from "@ember/runloop";
import Component from "@ember/component";
import EmberObject from "@ember/object";
import discourseDebounce from "discourse-common/lib/debounce";
import { later } from "@ember/runloop";
import { observes } from "discourse-common/utils/decorators";
import showModal from "discourse/lib/show-modal";
@ -53,7 +54,7 @@ export default Component.extend(PanEvents, {
},
_checkSize() {
debounce(this, this._performCheckSize, 300, true);
discourseDebounce(this, this._performCheckSize, 300, true);
},
// we need to store this so topic progress has something to init with

View File

@ -6,7 +6,7 @@ import {
authorizesOneOrMoreExtensions,
uploadIcon,
} from "discourse/lib/uploads";
import { cancel, debounce, run } from "@ember/runloop";
import { cancel, run } from "@ember/runloop";
import {
cannotPostAgain,
durationTextFromSeconds,
@ -22,6 +22,7 @@ import { Promise } from "rsvp";
import bootbox from "bootbox";
import { buildQuote } from "discourse/lib/quote";
import deprecated from "discourse-common/lib/deprecated";
import discourseDebounce from "discourse-common/lib/debounce";
import { emojiUnescape } from "discourse/lib/text";
import { escapeExpression } from "discourse/lib/utilities";
import { getOwner } from "discourse-common/lib/get-owner";
@ -1162,7 +1163,11 @@ export default Controller.extend({
// in test debounce is Ember.run, this will cause
// an infinite loop
if (!isTesting()) {
this._saveDraftDebounce = debounce(this, this._saveDraft, 2000);
this._saveDraftDebounce = discourseDebounce(
this,
this._saveDraft,
2000
);
}
} else {
this._saveDraftPromise = model.saveDraft().finally(() => {
@ -1188,7 +1193,7 @@ export default Controller.extend({
if (Date.now() - this._lastDraftSaved > 15000) {
this._saveDraft();
} else {
let method = isTesting() ? run : debounce;
let method = isTesting() ? run : discourseDebounce;
this._saveDraftDebounce = method(this, this._saveDraft, 2000);
}
}

View File

@ -1,7 +1,7 @@
import Controller, { inject as controller } from "@ember/controller";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { action } from "@ember/object";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { gt } from "@ember/object/computed";
import { popupAjaxError } from "discourse/lib/ajax-error";
@ -19,9 +19,15 @@ export default Controller.extend({
showActions: false,
@observes("filterInput")
_setFilter: discourseDebounce(function () {
this.set("filter", this.filterInput);
}, 500),
_setFilter() {
discourseDebounce(
this,
function () {
this.set("filter", this.filterInput);
},
500
);
},
@observes("order", "asc", "filter")
_filtersChanged() {

View File

@ -1,7 +1,7 @@
import Controller, { inject as controller } from "@ember/controller";
import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { ajax } from "discourse/lib/ajax";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
@ -17,9 +17,15 @@ export default Controller.extend({
loading: false,
@observes("filterInput")
_setFilter: discourseDebounce(function () {
this.set("filter", this.filterInput);
}, 500),
_setFilter() {
discourseDebounce(
this,
function () {
this.set("filter", this.filterInput);
},
500
);
},
@observes("order", "desc", "filter")
_filtersChanged() {

View File

@ -2,8 +2,8 @@ import Controller, { inject as controller } from "@ember/controller";
import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
import { action } from "@ember/object";
import { debounce } from "@ember/runloop";
import discourseComputed from "discourse-common/utils/decorators";
import discourseDebounce from "discourse-common/lib/debounce";
export default Controller.extend({
application: controller(),
@ -45,7 +45,7 @@ export default Controller.extend({
@action
onFilterChanged(filter) {
debounce(this, this._debouncedFilter, filter, INPUT_DELAY);
discourseDebounce(this, this._debouncedFilter, filter, INPUT_DELAY);
},
@action

View File

@ -1,7 +1,8 @@
import { cancel, debounce, schedule } from "@ember/runloop";
import { cancel, schedule } from "@ember/runloop";
import Controller from "@ember/controller";
import ModalFunctionality from "discourse/mixins/modal-functionality";
import { bind } from "discourse-common/utils/decorators";
import discourseDebounce from "discourse-common/lib/debounce";
import { isEmpty } from "@ember/utils";
import { prefixProtocol } from "discourse/lib/url";
import { searchForTerm } from "discourse/lib/search";
@ -177,7 +178,7 @@ export default Controller.extend(ModalFunctionality, {
}
},
search() {
this._debounced = debounce(this, this.triggerSearch, 400);
this._debounced = discourseDebounce(this, this.triggerSearch, 400);
},
},
});

View File

@ -18,7 +18,7 @@ import bootbox from "bootbox";
import { bufferedProperty } from "discourse/mixins/buffered-content";
import { buildQuote } from "discourse/lib/quote";
import { deepMerge } from "discourse-common/lib/object";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { escapeExpression } from "discourse/lib/utilities";
import { extractLinkMeta } from "discourse/lib/render-topic-featured-link";
import isElementInViewport from "discourse/lib/is-element-in-viewport";
@ -1500,15 +1500,22 @@ export default Controller.extend(bufferedProperty("model"), {
);
},
_scrollToPost: discourseDebounce(function (postNumber) {
const $post = $(`.topic-post article#post_${postNumber}`);
_scrollToPost(postNumber) {
discourseDebounce(
this,
function () {
const $post = $(`.topic-post article#post_${postNumber}`);
if ($post.length === 0 || isElementInViewport($post)) {
return;
}
if ($post.length === 0 || isElementInViewport($post)) {
return;
}
$("html, body").animate({ scrollTop: $post.offset().top }, 1000);
}, 500),
$("html, body").animate({ scrollTop: $post.offset().top }, 1000);
},
postNumber,
500
);
},
unsubscribe() {
// never unsubscribe when navigating from topic to topic

View File

@ -5,7 +5,7 @@ import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
import Invite from "discourse/models/invite";
import bootbox from "bootbox";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { popupAjaxError } from "discourse/lib/ajax-error";
export default Controller.extend({
@ -26,13 +26,19 @@ export default Controller.extend({
},
@observes("searchTerm")
_searchTermChanged: discourseDebounce(function () {
Invite.findInvitedBy(
this.user,
this.filter,
this.searchTerm
).then((invites) => this.set("model", invites));
}, INPUT_DELAY),
_searchTermChanged() {
discourseDebounce(
this,
function () {
Invite.findInvitedBy(
this.user,
this.filter,
this.searchTerm
).then((invites) => this.set("model", invites));
},
INPUT_DELAY
);
},
inviteRedeemed: equal("filter", "redeemed"),
invitePending: equal("filter", "pending"),

View File

@ -1,5 +1,5 @@
import Controller, { inject as controller } from "@ember/controller";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { equal } from "@ember/object/computed";
import { longDate } from "discourse/lib/formatter";
import { observes } from "discourse-common/utils/decorators";
@ -37,9 +37,15 @@ export default Controller.extend({
},
@observes("nameInput")
_setName: discourseDebounce(function () {
this.set("name", this.nameInput);
}, 500),
_setName() {
discourseDebounce(
this,
function () {
this.set("name", this.nameInput);
},
500
);
},
@observes("model.canLoadMore")
_showFooter: function () {

View File

@ -1,7 +1,8 @@
import { cancel, debounce, later } from "@ember/runloop";
import { cancel, later } from "@ember/runloop";
import { caretPosition, setCaretPosition } from "discourse/lib/utilities";
import { INPUT_DELAY } from "discourse-common/config/environment";
import Site from "discourse/models/site";
import discourseDebounce from "discourse-common/lib/debounce";
import { iconHTML } from "discourse-common/lib/icon-library";
/**
@ -422,7 +423,7 @@ export default function (options) {
$(this).on("keyup.autocomplete", function (e) {
if (options.debounced) {
debounce(this, performAutocomplete, e, INPUT_DELAY);
discourseDebounce(this, performAutocomplete, e, INPUT_DELAY);
} else {
performAutocomplete(e);
}

View File

@ -4,7 +4,7 @@ import Category from "discourse/models/category";
import { Promise } from "rsvp";
import { SEPARATOR } from "discourse/lib/category-hashtags";
import { TAG_HASHTAG_POSTFIX } from "discourse/lib/tag-hashtags";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import getURL from "discourse-common/lib/get-url";
import { isTesting } from "discourse-common/config/environment";
@ -27,38 +27,47 @@ function searchTags(term, categories, limit) {
isTesting() ? 50 : 5000
);
const debouncedSearch = discourseDebounce((q, cats, resultFunc) => {
oldSearch = $.ajax(getURL("/tags/filter/search"), {
type: "GET",
cache: true,
data: { limit: limit, q },
});
var returnVal = CANCELLED_STATUS;
oldSearch
.then((r) => {
const categoryNames = cats.map((c) => c.model.get("name"));
const tags = r.results.map((tag) => {
const tagName = tag.text;
return {
name: tagName,
text: categoryNames.includes(tagName)
? `${tagName}${TAG_HASHTAG_POSTFIX}`
: tagName,
count: tag.count,
};
const debouncedSearch = (q, cats, resultFunc) => {
discourseDebounce(
this,
function () {
oldSearch = $.ajax(getURL("/tags/filter/search"), {
type: "GET",
cache: true,
data: { limit: limit, q },
});
returnVal = cats.concat(tags);
})
.always(() => {
oldSearch = null;
resultFunc(returnVal);
});
}, 300);
var returnVal = CANCELLED_STATUS;
oldSearch
.then((r) => {
const categoryNames = cats.map((c) => c.model.get("name"));
const tags = r.results.map((tag) => {
const tagName = tag.text;
return {
name: tagName,
text: categoryNames.includes(tagName)
? `${tagName}${TAG_HASHTAG_POSTFIX}`
: tagName,
count: tag.count,
};
});
returnVal = cats.concat(tags);
})
.always(() => {
oldSearch = null;
resultFunc(returnVal);
});
},
q,
cats,
resultFunc,
300
);
};
debouncedSearch(term, categories, (result) => {
cancel(clearPromise);

View File

@ -1,6 +1,5 @@
import { ajax } from "discourse/lib/ajax";
import { run } from "@ember/runloop";
const { debounce } = run;
import discourseDebounce from "discourse-common/lib/debounce";
let _queue = [];
let _processing = 0;
@ -33,7 +32,7 @@ export default {
_queue.push({ runnable: () => callback, type, params });
debounce(this, this._processQueue, DEBOUNCING_DELAY);
discourseDebounce(this, this._processQueue, DEBOUNCING_DELAY);
},
_processQueue() {
@ -50,7 +49,7 @@ export default {
// if queue has still jobs after splice, we request a future processing
if (_queue.length > 0) {
debounce(this, this._processQueue, DEBOUNCING_DELAY);
discourseDebounce(this, this._processQueue, DEBOUNCING_DELAY);
}
let reports = {};
@ -79,7 +78,7 @@ export default {
.finally(() => {
_processing--;
debounce(this, this._processQueue, DEBOUNCING_DELAY);
discourseDebounce(this, this._processQueue, DEBOUNCING_DELAY);
});
},

View File

@ -3,7 +3,7 @@ import {
safariHacksDisabled,
} from "discourse/lib/utilities";
import { INPUT_DELAY } from "discourse-common/config/environment";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { helperContext } from "discourse-common/lib/helpers";
import { later } from "@ember/runloop";
@ -145,7 +145,9 @@ function positioningWorkaround($fixedElement) {
positioningWorkaround.blur(evt);
};
var blurred = discourseDebounce(blurredNow, INPUT_DELAY);
var blurred = function (evt) {
discourseDebounce(this, blurredNow, evt, INPUT_DELAY);
};
var positioningHack = function (evt) {
let _this = this;
@ -214,13 +216,19 @@ function positioningWorkaround($fixedElement) {
}
}
const checkForInputs = discourseDebounce(function () {
attachTouchStart(fixedElement, lastTouched);
const checkForInputs = function () {
discourseDebounce(
this,
function () {
attachTouchStart(fixedElement, lastTouched);
$fixedElement.find("input[type=text],textarea").each(function () {
attachTouchStart(this, positioningHack);
});
}, 100);
$fixedElement.find("input[type=text],textarea").each(function () {
attachTouchStart(this, positioningHack);
});
},
100
);
};
positioningWorkaround.touchstartEvent = function (element) {
var triggerHack = positioningHack.bind(element);

View File

@ -1,7 +1,7 @@
import { cancel, later } from "@ember/runloop";
import { CANCELLED_STATUS } from "discourse/lib/autocomplete";
import { Promise } from "rsvp";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { emailValid } from "discourse/lib/utilities";
import { isTesting } from "discourse-common/config/environment";
import { userPath } from "discourse/lib/url";
@ -81,7 +81,32 @@ function performSearch(
});
}
var debouncedSearch = discourseDebounce(performSearch, 300);
var debouncedSearch = function (
term,
topicId,
categoryId,
includeGroups,
includeMentionableGroups,
includeMessageableGroups,
allowedUsers,
groupMembersOf,
resultsFn
) {
discourseDebounce(
this,
performSearch,
term,
topicId,
categoryId,
includeGroups,
includeMentionableGroups,
includeMessageableGroups,
allowedUsers,
groupMembersOf,
resultsFn,
300
);
};
function organizeResults(r, options) {
if (r === CANCELLED_STATUS) {

View File

@ -1,5 +1,6 @@
import { debounce, later } from "@ember/runloop";
import Mixin from "@ember/object/mixin";
import discourseDebounce from "discourse-common/lib/debounce";
import { later } from "@ember/runloop";
const helper = {
offset() {
@ -15,7 +16,7 @@ export default Mixin.create({
init() {
this._super(...arguments);
this.queueDockCheck = () => {
debounce(this, this.safeDockCheck, 5);
discourseDebounce(this, this.safeDockCheck, 5);
};
},

View File

@ -1,5 +1,5 @@
import Mixin from "@ember/object/mixin";
import { debounce } from "@ember/runloop";
import discourseDebounce from "discourse-common/lib/debounce";
// Small buffer so that very tiny scrolls don't trigger mobile header switch
const MOBILE_SCROLL_TOLERANCE = 5;
@ -47,9 +47,13 @@ export default Mixin.create({
// If the user reaches the very bottom of the topic, we only want to reset
// this scroll direction after a second scrolldown. This is a nicer event
// similar to what Safari and Chrome do.
debounce(() => {
this._bottomHit = 1;
}, 1000);
discourseDebounce(
this,
function () {
this._bottomHit = 1;
},
1000
);
if (this._bottomHit === 1) {
this.set("mobileScrollDirection", null);

View File

@ -1,5 +1,5 @@
import Mixin from "@ember/object/mixin";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { scheduleOnce } from "@ember/runloop";
import { inject as service } from "@ember/service";
@ -45,7 +45,9 @@ const Scrolling = Mixin.create({
};
if (opts.debounce) {
onScrollMethod = discourseDebounce(onScrollMethod, opts.debounce);
onScrollMethod = () => {
discourseDebounce(this, onScrollMethod, opts.debounce);
};
}
ScrollingDOMMethods.bindOnScroll(onScrollMethod, opts.name);

View File

@ -3,7 +3,7 @@ import I18n from "I18n";
import Mixin from "@ember/object/mixin";
import User from "discourse/models/user";
import discourseComputed from "discourse-common/utils/decorators";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { isEmpty } from "@ember/utils";
import { setting } from "discourse/lib/computed";
@ -14,20 +14,26 @@ export default Mixin.create({
minUsernameLength: setting("min_username_length"),
fetchExistingUsername: discourseDebounce(function () {
User.checkUsername(null, this.accountEmail).then((result) => {
if (
result.suggestion &&
(isEmpty(this.accountUsername) ||
this.accountUsername === this.get("authOptions.username"))
) {
this.setProperties({
accountUsername: result.suggestion,
prefilledUsername: result.suggestion,
fetchExistingUsername() {
discourseDebounce(
this,
function () {
User.checkUsername(null, this.accountEmail).then((result) => {
if (
result.suggestion &&
(isEmpty(this.accountUsername) ||
this.accountUsername === this.get("authOptions.username"))
) {
this.setProperties({
accountUsername: result.suggestion,
prefilledUsername: result.suggestion,
});
}
});
}
});
}, 500),
},
500
);
},
@discourseComputed("accountUsername")
basicUsernameValidation(accountUsername) {
@ -87,54 +93,61 @@ export default Mixin.create({
);
},
checkUsernameAvailability: discourseDebounce(function () {
if (this.shouldCheckUsernameAvailability()) {
return User.checkUsername(this.accountUsername, this.accountEmail).then(
(result) => {
this.set("isDeveloper", false);
if (result.available) {
if (result.is_developer) {
this.set("isDeveloper", true);
}
return this.set(
"uniqueUsernameValidation",
EmberObject.create({
ok: true,
reason: I18n.t("user.username.available"),
})
);
} else {
const failedAttrs = {
failed: true,
element: document.querySelector("#new-account-username"),
};
if (result.suggestion) {
checkUsernameAvailability() {
discourseDebounce(
this,
function () {
if (this.shouldCheckUsernameAvailability()) {
return User.checkUsername(
this.accountUsername,
this.accountEmail
).then((result) => {
this.set("isDeveloper", false);
if (result.available) {
if (result.is_developer) {
this.set("isDeveloper", true);
}
return this.set(
"uniqueUsernameValidation",
EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.username.not_available", result),
})
)
EmberObject.create({
ok: true,
reason: I18n.t("user.username.available"),
})
);
} else {
return this.set(
"uniqueUsernameValidation",
EmberObject.create(
Object.assign(failedAttrs, {
reason: result.errors
? result.errors.join(" ")
: I18n.t("user.username.not_available_no_suggestion"),
})
)
);
const failedAttrs = {
failed: true,
element: document.querySelector("#new-account-username"),
};
if (result.suggestion) {
return this.set(
"uniqueUsernameValidation",
EmberObject.create(
Object.assign(failedAttrs, {
reason: I18n.t("user.username.not_available", result),
})
)
);
} else {
return this.set(
"uniqueUsernameValidation",
EmberObject.create(
Object.assign(failedAttrs, {
reason: result.errors
? result.errors.join(" ")
: I18n.t("user.username.not_available_no_suggestion"),
})
)
);
}
}
}
});
}
);
}
}, 500),
},
500
);
},
// Actually wait for the async name check before we're 100% sure we're good to go
@discourseComputed("uniqueUsernameValidation", "basicUsernameValidation")

View File

@ -1,7 +1,7 @@
import { Placeholder } from "discourse/lib/posts-with-placeholders";
import { addWidgetCleanCallback } from "discourse/components/mount-widget";
import { createWidget } from "discourse/widgets/widget";
import { debounce } from "@ember/runloop";
import discourseDebounce from "discourse-common/lib/debounce";
import { isTesting } from "discourse-common/config/environment";
import transformPost from "discourse/lib/transform-post";
@ -41,7 +41,7 @@ export function cloak(post, component) {
_heights[post.id] = $post.outerHeight();
component.dirtyKeys.keyDirty(`post-${post.id}`);
debounce(component, "queueRerender", 1000);
discourseDebounce(component, "queueRerender", 1000);
}
export function uncloak(post, component) {

View File

@ -1,7 +1,7 @@
import { isValidSearchTerm, searchForTerm } from "discourse/lib/search";
import DiscourseURL from "discourse/lib/url";
import { createWidget } from "discourse/widgets/widget";
import { debounce } from "@ember/runloop";
import discourseDebounce from "discourse-common/lib/debounce";
import { get } from "@ember/object";
import getURL from "discourse-common/lib/get-url";
import { h } from "virtual-dom";
@ -284,7 +284,7 @@ export default createWidget("search-menu", {
searchData.noResults = false;
this.searchService().set("highlightTerm", searchData.term);
searchData.loading = true;
debounce(SearchHelper, SearchHelper.perform, this, 400);
discourseDebounce(SearchHelper, SearchHelper.perform, this, 400);
},
moreOfType(type) {

View File

@ -1,5 +1,5 @@
import I18n from "I18n";
import { debounce } from "@ember/runloop";
import discourseDebounce from "discourse-common/lib/debounce";
let _cache = {};
@ -184,7 +184,7 @@ export function resolveAllShortUrls(ajax, siteSettings, scope, opts) {
shortUploadElements = scope.querySelectorAll(attributes);
if (shortUploadElements.length > 0) {
// this is carefully batched so we can do a leading debounce (trigger right away)
return debounce(
return discourseDebounce(
null,
_loadShortUrls,
shortUploadElements,

View File

@ -3,14 +3,7 @@ import PluginApiMixin, {
applyContentPluginApiCallbacks,
applyOnChangePluginApiCallbacks,
} from "select-kit/mixins/plugin-api";
import {
bind,
cancel,
debounce,
next,
schedule,
throttle,
} from "@ember/runloop";
import { bind, cancel, next, schedule, throttle } from "@ember/runloop";
import { isEmpty, isNone, isPresent } from "@ember/utils";
import Component from "@ember/component";
import I18n from "I18n";
@ -19,6 +12,7 @@ import { Promise } from "rsvp";
import UtilsMixin from "select-kit/mixins/utils";
import { createPopper } from "@popperjs/core";
import deprecated from "discourse-common/lib/deprecated";
import discourseDebounce from "discourse-common/lib/debounce";
import { guidFor } from "@ember/object/internals";
import { makeArray } from "discourse-common/lib/helpers";
@ -386,7 +380,7 @@ export default Component.extend(
cancel(this._searchPromise);
}
debounce(this, this._debouncedInput, event.target.value, 200);
discourseDebounce(this, this._debouncedInput, event.target.value, 200);
},
_debouncedInput(filter) {

View File

@ -6,7 +6,7 @@ import I18n from "I18n";
import { INPUT_DELAY } from "discourse-common/config/environment";
import { Promise } from "rsvp";
import { cookAsync } from "discourse/lib/text";
import discourseDebounce from "discourse/lib/debounce";
import discourseDebounce from "discourse-common/lib/debounce";
import { isEmpty } from "@ember/utils";
import loadScript from "discourse/lib/load-script";
import { notEmpty } from "@ember/object/computed";
@ -56,18 +56,24 @@ export default Component.extend({
},
@observes("markup")
_renderPreview: discourseDebounce(function () {
const markup = this.markup;
_renderPreview() {
discourseDebounce(
this,
function () {
const markup = this.markup;
if (markup) {
cookAsync(markup).then((result) => {
this.set("currentPreview", result);
schedule("afterRender", () =>
this.$(".preview .discourse-local-date").applyLocalDates()
);
});
}
}, INPUT_DELAY),
if (markup) {
cookAsync(markup).then((result) => {
this.set("currentPreview", result);
schedule("afterRender", () =>
this.$(".preview .discourse-local-date").applyLocalDates()
);
});
}
},
INPUT_DELAY
);
},
@computed("date", "toDate", "toTime")
isRange(date, toDate, toTime) {