diff --git a/app/assets/javascripts/discourse/app/mixins/docking.js b/app/assets/javascripts/discourse/app/mixins/docking.js deleted file mode 100644 index de39ae3a8b1..00000000000 --- a/app/assets/javascripts/discourse/app/mixins/docking.js +++ /dev/null @@ -1,59 +0,0 @@ -// Deprecated in favor of app/assets/javascripts/discourse/app/services/docking.js -import Mixin from "@ember/object/mixin"; -import { cancel } from "@ember/runloop"; -import discourseDebounce from "discourse-common/lib/debounce"; -import discourseLater from "discourse-common/lib/later"; -import { bind } from "discourse-common/utils/decorators"; - -const INITIAL_DELAY_MS = 50; -const DEBOUNCE_MS = 5; - -export default Mixin.create({ - _initialTimer: null, - _queuedTimer: null, - - didInsertElement() { - this._super(...arguments); - - window.addEventListener("scroll", this.queueDockCheck, { passive: true }); - document.addEventListener("touchmove", this.queueDockCheck, { - passive: true, - }); - - // dockCheck might happen too early on full page refresh - this._initialTimer = discourseLater( - this, - this.safeDockCheck, - INITIAL_DELAY_MS - ); - }, - - willDestroyElement() { - this._super(...arguments); - - if (this._queuedTimer) { - cancel(this._queuedTimer); - } - - cancel(this._initialTimer); - window.removeEventListener("scroll", this.queueDockCheck); - document.removeEventListener("touchmove", this.queueDockCheck); - }, - - @bind - queueDockCheck() { - this._queuedTimer = discourseDebounce( - this, - this.safeDockCheck, - DEBOUNCE_MS - ); - }, - - @bind - safeDockCheck() { - if (this.isDestroyed || this.isDestroying) { - return; - } - this.dockCheck(); - }, -}); diff --git a/app/assets/javascripts/discourse/app/mixins/load-more.js b/app/assets/javascripts/discourse/app/mixins/load-more.js index a64c4e0931e..91ce89caf0a 100644 --- a/app/assets/javascripts/discourse/app/mixins/load-more.js +++ b/app/assets/javascripts/discourse/app/mixins/load-more.js @@ -1,7 +1,7 @@ +import { on } from "@ember/object/evented"; import Mixin from "@ember/object/mixin"; import Eyeline from "discourse/lib/eyeline"; import Scrolling from "discourse/mixins/scrolling"; -import { on } from "discourse-common/utils/decorators"; // Provides the ability to load more items for a view which is scrolled to the bottom. export default Mixin.create(Scrolling, { @@ -9,8 +9,7 @@ export default Mixin.create(Scrolling, { return this.eyeline?.update(); }, - @on("didInsertElement") - _bindEyeline() { + _bindEyeline: on("didInsertElement", function () { const eyeline = Eyeline.create({ selector: `${this.eyelineSelector}:last`, }); @@ -20,10 +19,9 @@ export default Mixin.create(Scrolling, { eyeline.update(); // update once to consider current position this.bindScrolling(); - }, + }), - @on("willDestroyElement") - _removeEyeline() { + _removeEyeline: on("willDestroyElement", function () { this.unbindScrolling(); - }, + }), }); diff --git a/app/assets/javascripts/discourse/app/mixins/name-validation.js b/app/assets/javascripts/discourse/app/mixins/name-validation.js index da5420a38cd..99586ce10e3 100644 --- a/app/assets/javascripts/discourse/app/mixins/name-validation.js +++ b/app/assets/javascripts/discourse/app/mixins/name-validation.js @@ -1,12 +1,10 @@ -import EmberObject from "@ember/object"; +import EmberObject, { computed } from "@ember/object"; import Mixin from "@ember/object/mixin"; import { isEmpty } from "@ember/utils"; -import discourseComputed from "discourse-common/utils/decorators"; import I18n from "discourse-i18n"; export default Mixin.create({ - @discourseComputed() - nameTitle() { + get nameTitle() { return I18n.t( this.siteSettings.full_name_required ? "user.name.title" @@ -15,8 +13,8 @@ export default Mixin.create({ }, // Validate the name. - @discourseComputed("accountName", "forceValidationReason") - nameValidation(accountName, forceValidationReason) { + nameValidation: computed("accountName", "forceValidationReason", function () { + const { accountName, forceValidationReason } = this; if (this.siteSettings.full_name_required && isEmpty(accountName)) { return EmberObject.create({ failed: true, @@ -28,5 +26,5 @@ export default Mixin.create({ } return EmberObject.create({ ok: true }); - }, + }), }); diff --git a/app/assets/javascripts/discourse/app/mixins/password-validation.js b/app/assets/javascripts/discourse/app/mixins/password-validation.js index d329576d822..dd9b2145e77 100644 --- a/app/assets/javascripts/discourse/app/mixins/password-validation.js +++ b/app/assets/javascripts/discourse/app/mixins/password-validation.js @@ -1,7 +1,6 @@ -import EmberObject from "@ember/object"; +import EmberObject, { computed } from "@ember/object"; import Mixin from "@ember/object/mixin"; import { isEmpty } from "@ember/utils"; -import discourseComputed from "discourse-common/utils/decorators"; import I18n from "discourse-i18n"; export default Mixin.create({ @@ -13,101 +12,98 @@ export default Mixin.create({ this.set("rejectedPasswordsMessages", new Map()); }, - @discourseComputed("passwordMinLength") - passwordInstructions() { + passwordInstructions: computed("passwordMinLength", function () { return I18n.t("user.password.instructions", { count: this.passwordMinLength, }); - }, + }), - @discourseComputed("isDeveloper", "admin") - passwordMinLength(isDeveloper, admin) { + passwordMinLength: computed("isDeveloper", "admin", function () { + const { isDeveloper, admin } = this; return isDeveloper || admin ? this.siteSettings.min_admin_password_length : this.siteSettings.min_password_length; - }, + }), - @discourseComputed( + passwordValidation: computed( "accountPassword", "passwordRequired", "rejectedPasswords.[]", "accountUsername", "accountEmail", "passwordMinLength", - "forceValidationReason" - ) - passwordValidation( - password, - passwordRequired, - rejectedPasswords, - accountUsername, - accountEmail, - passwordMinLength, - forceValidationReason - ) { - const failedAttrs = { - failed: true, - ok: false, - element: document.querySelector("#new-account-password"), - }; + "forceValidationReason", + function () { + const failedAttrs = { + failed: true, + ok: false, + element: document.querySelector("#new-account-password"), + }; - if (!passwordRequired) { - return EmberObject.create({ ok: true }); + if (!this.passwordRequired) { + return EmberObject.create({ ok: true }); + } + + if (this.rejectedPasswords.includes(this.accountPassword)) { + return EmberObject.create( + Object.assign(failedAttrs, { + reason: + this.rejectedPasswordsMessages.get(this.accountPassword) || + I18n.t("user.password.common"), + }) + ); + } + + // If blank, fail without a reason + if (isEmpty(this.accountPassword)) { + return EmberObject.create( + Object.assign(failedAttrs, { + message: I18n.t("user.password.required"), + reason: this.forceValidationReason + ? I18n.t("user.password.required") + : null, + }) + ); + } + + // If too short + if (this.accountPassword.length < this.passwordMinLength) { + return EmberObject.create( + Object.assign(failedAttrs, { + reason: I18n.t("user.password.too_short", { + count: this.passwordMinLength, + }), + }) + ); + } + + if ( + !isEmpty(this.accountUsername) && + this.accountPassword === this.accountUsername + ) { + return EmberObject.create( + Object.assign(failedAttrs, { + reason: I18n.t("user.password.same_as_username"), + }) + ); + } + + if ( + !isEmpty(this.accountEmail) && + this.accountPassword === this.accountEmail + ) { + return EmberObject.create( + Object.assign(failedAttrs, { + reason: I18n.t("user.password.same_as_email"), + }) + ); + } + + // Looks good! + return EmberObject.create({ + ok: true, + reason: I18n.t("user.password.ok"), + }); } - - if (rejectedPasswords.includes(password)) { - return EmberObject.create( - Object.assign(failedAttrs, { - reason: - this.rejectedPasswordsMessages.get(password) || - I18n.t("user.password.common"), - }) - ); - } - - // If blank, fail without a reason - if (isEmpty(password)) { - return EmberObject.create( - Object.assign(failedAttrs, { - message: I18n.t("user.password.required"), - reason: forceValidationReason - ? I18n.t("user.password.required") - : null, - }) - ); - } - - // If too short - if (password.length < passwordMinLength) { - return EmberObject.create( - Object.assign(failedAttrs, { - reason: I18n.t("user.password.too_short", { - count: passwordMinLength, - }), - }) - ); - } - - if (!isEmpty(accountUsername) && password === accountUsername) { - return EmberObject.create( - Object.assign(failedAttrs, { - reason: I18n.t("user.password.same_as_username"), - }) - ); - } - - if (!isEmpty(accountEmail) && password === accountEmail) { - return EmberObject.create( - Object.assign(failedAttrs, { - reason: I18n.t("user.password.same_as_email"), - }) - ); - } - - // Looks good! - return EmberObject.create({ - ok: true, - reason: I18n.t("user.password.ok"), - }); - }, + ), }); diff --git a/app/assets/javascripts/discourse/app/mixins/user-fields-validation.js b/app/assets/javascripts/discourse/app/mixins/user-fields-validation.js index 17d10d154f4..40abe71bae7 100644 --- a/app/assets/javascripts/discourse/app/mixins/user-fields-validation.js +++ b/app/assets/javascripts/discourse/app/mixins/user-fields-validation.js @@ -1,7 +1,7 @@ -import EmberObject from "@ember/object"; +import EmberObject, { computed } from "@ember/object"; +import { on } from "@ember/object/evented"; import Mixin from "@ember/object/mixin"; import { isEmpty } from "@ember/utils"; -import discourseComputed, { on } from "discourse-common/utils/decorators"; import I18n from "discourse-i18n"; const addCustomUserFieldValidationCallbacks = []; @@ -10,8 +10,7 @@ export function addCustomUserFieldValidationCallback(callback) { } export default Mixin.create({ - @on("init") - _createUserFields() { + _createUserFields: on("init", function () { if (!this.site) { return; } @@ -23,10 +22,9 @@ export default Mixin.create({ .map((f) => EmberObject.create({ value: null, field: f })); } this.set("userFields", userFields); - }, + }), - @discourseComputed("userFields.@each.value") - userFieldsValidation() { + userFieldsValidation: computed("userFields.@each.value", function () { if (!this.userFields) { return EmberObject.create({ ok: true }); } @@ -76,5 +74,5 @@ export default Mixin.create({ } return EmberObject.create({ ok: true }); - }, + }), }); diff --git a/app/assets/javascripts/discourse/app/mixins/username-validation.js b/app/assets/javascripts/discourse/app/mixins/username-validation.js index 7d53241e79d..2480094dd6a 100644 --- a/app/assets/javascripts/discourse/app/mixins/username-validation.js +++ b/app/assets/javascripts/discourse/app/mixins/username-validation.js @@ -1,10 +1,9 @@ -import EmberObject from "@ember/object"; +import EmberObject, { computed } from "@ember/object"; import Mixin from "@ember/object/mixin"; import { isEmpty } from "@ember/utils"; import { setting } from "discourse/lib/computed"; import User from "discourse/models/user"; import discourseDebounce from "discourse-common/lib/debounce"; -import discourseComputed from "discourse-common/utils/decorators"; import I18n from "discourse-i18n"; function failedResult(attrs) { @@ -43,27 +42,27 @@ export default Mixin.create({ } }, - @discourseComputed( + usernameValidation: computed( "usernameValidationResult", "accountUsername", - "forceValidationReason" - ) - usernameValidation() { - if ( - this.usernameValidationResult && - this.checkedUsername === this.accountUsername - ) { - return this.usernameValidationResult; + "forceValidationReason", + function () { + if ( + this.usernameValidationResult && + this.checkedUsername === this.accountUsername + ) { + return this.usernameValidationResult; + } + + const result = this.basicUsernameValidation(this.accountUsername); + + if (result.shouldCheck) { + discourseDebounce(this, this.checkUsernameAvailability, 500); + } + + return result; } - - const result = this.basicUsernameValidation(this.accountUsername); - - if (result.shouldCheck) { - discourseDebounce(this, this.checkUsernameAvailability, 500); - } - - return result; - }, + ), basicUsernameValidation(username) { if (username && username === this.prefilledUsername) {