diff --git a/app/assets/javascripts/admin/addon/components/admin-flag-item.gjs b/app/assets/javascripts/admin/addon/components/admin-flag-item.gjs index d7fc69a5da4..075c6eba78c 100644 --- a/app/assets/javascripts/admin/addon/components/admin-flag-item.gjs +++ b/app/assets/javascripts/admin/addon/components/admin-flag-item.gjs @@ -88,6 +88,7 @@ export default class AdminFlagItem extends Component { this.dMenu.close(); }); } + @action edit() { this.router.transitionTo("adminConfig.flags.edit", this.args.flag); diff --git a/app/assets/javascripts/admin/addon/components/embeddable-host.js b/app/assets/javascripts/admin/addon/components/embeddable-host.js index 467b928f826..8d4ae85cdfe 100644 --- a/app/assets/javascripts/admin/addon/components/embeddable-host.js +++ b/app/assets/javascripts/admin/addon/components/embeddable-host.js @@ -44,10 +44,12 @@ export default class EmbeddableHost extends Component.extend( edit() { this.set("editToggled", true); } + @action onUserChange(user) { this.set("user", user); } + @action save() { if (this.cantSave) { diff --git a/app/assets/javascripts/admin/addon/components/modal/install-theme.gjs b/app/assets/javascripts/admin/addon/components/modal/install-theme.gjs index 534c6ca63a7..9fd13ca761a 100644 --- a/app/assets/javascripts/admin/addon/components/modal/install-theme.gjs +++ b/app/assets/javascripts/admin/addon/components/modal/install-theme.gjs @@ -46,6 +46,11 @@ export default class InstallThemeModal extends Component { keyGenUrl = this.args.model.keyGenUrl || "/admin/themes/generate_key_pair"; importUrl = this.args.model.importUrl || "/admin/themes/import"; + willDestroy() { + super.willDestroy(...arguments); + this.args.model.clearParams?.(); + } + get showPublicKey() { return this.uploadUrl?.match?.(/^ssh:\/\/.+@.+$|.+@.+:.+$/); } @@ -125,11 +130,6 @@ export default class InstallThemeModal extends Component { ); } - willDestroy() { - super.willDestroy(...arguments); - this.args.model.clearParams?.(); - } - @action async generatePublicKey() { try { diff --git a/app/assets/javascripts/admin/addon/components/site-settings/file-types-list.gjs b/app/assets/javascripts/admin/addon/components/site-settings/file-types-list.gjs index 9ddf7d785cf..2d5ea461726 100644 --- a/app/assets/javascripts/admin/addon/components/site-settings/file-types-list.gjs +++ b/app/assets/javascripts/admin/addon/components/site-settings/file-types-list.gjs @@ -96,6 +96,7 @@ export default class FileTypesList extends Component { this.args.changeValueCallback(newTypes.join(TOKEN_SEPARATOR)); } + <template> <ListSetting @value={{this.settingValue}} diff --git a/app/assets/javascripts/admin/addon/components/themes-list.js b/app/assets/javascripts/admin/addon/components/themes-list.js index d35e6f38261..bcfed2ee1dd 100644 --- a/app/assets/javascripts/admin/addon/components/themes-list.js +++ b/app/assets/javascripts/admin/addon/components/themes-list.js @@ -166,6 +166,7 @@ export default class ThemesList extends Component { results = this._applyFilter(results); return this._searchThemes(results, this.searchTerm); } + @discourseComputed("themesList.@each.markedToDelete") someInactiveSelected() { return ( diff --git a/app/assets/javascripts/admin/addon/controllers/admin-user-badges.js b/app/assets/javascripts/admin/addon/controllers/admin-user-badges.js index acd33ca7b9e..e0edecd5818 100644 --- a/app/assets/javascripts/admin/addon/controllers/admin-user-badges.js +++ b/app/assets/javascripts/admin/addon/controllers/admin-user-badges.js @@ -26,6 +26,7 @@ export default class AdminUserBadgesController extends Controller { availableBadges() { return grantableBadges(this.get("allBadges"), this.get("userBadges")); } + @discourseComputed("model", "model.[]", "model.expandedBadges.[]") groupedBadges() { const allBadges = this.model; @@ -71,6 +72,7 @@ export default class AdminUserBadgesController extends Controller { return expanded.sortBy("granted_at").reverse(); } + @action expandGroup(userBadge) { const model = this.model; diff --git a/app/assets/javascripts/dialog-holder/addon/services/dialog.js b/app/assets/javascripts/dialog-holder/addon/services/dialog.js index 4e8f7e4a170..5ea9429a848 100644 --- a/app/assets/javascripts/dialog-holder/addon/services/dialog.js +++ b/app/assets/javascripts/dialog-holder/addon/services/dialog.js @@ -27,6 +27,11 @@ export default class DialogService extends Service { class = null; _confirming = false; + willDestroy() { + this.dialogInstance?.destroy(); + this.reset(); + } + async dialog(params) { const { message, @@ -171,11 +176,6 @@ export default class DialogService extends Service { }); } - willDestroy() { - this.dialogInstance?.destroy(); - this.reset(); - } - @bind didConfirmWrapped() { if (this.didConfirm) { diff --git a/app/assets/javascripts/discourse/app/components/basic-topic-list.js b/app/assets/javascripts/discourse/app/components/basic-topic-list.js index 8c40b76a51d..e5bbf7c4361 100644 --- a/app/assets/javascripts/discourse/app/components/basic-topic-list.js +++ b/app/assets/javascripts/discourse/app/components/basic-topic-list.js @@ -9,6 +9,14 @@ export default class BasicTopicList extends Component { @not("loaded") loading; + init() { + super.init(...arguments); + const topicList = this.topicList; + if (topicList) { + this._initFromTopicList(topicList); + } + } + @discourseComputed("topicList.loaded") loaded() { let topicList = this.topicList; @@ -31,14 +39,6 @@ export default class BasicTopicList extends Component { } } - init() { - super.init(...arguments); - const topicList = this.topicList; - if (topicList) { - this._initFromTopicList(topicList); - } - } - didInsertElement() { super.didInsertElement(...arguments); diff --git a/app/assets/javascripts/discourse/app/components/d-editor.js b/app/assets/javascripts/discourse/app/components/d-editor.js index 6802f5bdbc8..9909cd22e49 100644 --- a/app/assets/javascripts/discourse/app/components/d-editor.js +++ b/app/assets/javascripts/discourse/app/components/d-editor.js @@ -76,6 +76,12 @@ export default class DEditor extends Component { }, }; + init() { + super.init(...arguments); + + this.register = getRegister(this); + } + @computed("formTemplateIds") get selectedFormTemplateId() { if (this._selectedFormTemplateId) { @@ -116,12 +122,6 @@ export default class DEditor extends Component { } } - init() { - super.init(...arguments); - - this.register = getRegister(this); - } - didInsertElement() { super.didInsertElement(...arguments); diff --git a/app/assets/javascripts/discourse/app/components/d-lightbox.js b/app/assets/javascripts/discourse/app/components/d-lightbox.js index e8f57ff7089..b09d89fddca 100644 --- a/app/assets/javascripts/discourse/app/components/d-lightbox.js +++ b/app/assets/javascripts/discourse/app/components/d-lightbox.js @@ -48,6 +48,11 @@ export default class DLightbox extends Component { animationDuration = ANIMATION_DURATION; scrollPosition = 0; + willDestroy() { + super.willDestroy(...arguments); + this.cleanup(); + } + get layoutType() { return window.innerWidth > window.innerHeight ? LAYOUT_TYPES.HORIZONTAL @@ -487,9 +492,4 @@ export default class DLightbox extends Component { }); } } - - willDestroy() { - super.willDestroy(...arguments); - this.cleanup(); - } } diff --git a/app/assets/javascripts/discourse/app/components/discourse-topic.js b/app/assets/javascripts/discourse/app/components/discourse-topic.js index 15e753a29f7..77f927c2877 100644 --- a/app/assets/javascripts/discourse/app/components/discourse-topic.js +++ b/app/assets/javascripts/discourse/app/components/discourse-topic.js @@ -26,6 +26,20 @@ export default class DiscourseTopic extends Component.extend(Scrolling) { SHORT_POST = 1200; dockAt = 0; + init() { + super.init(...arguments); + this.appEvents.on("discourse:focus-changed", this, "gotFocus"); + this.appEvents.on("post:highlight", this, "_highlightPost"); + } + + willDestroy() { + super.willDestroy(...arguments); + + // this happens after route exit, stuff could have trickled in + this.appEvents.off("discourse:focus-changed", this, "gotFocus"); + this.appEvents.off("post:highlight", this, "_highlightPost"); + } + @observes("enteredAt") _enteredTopic() { // Ember is supposed to only call observers when values change but something @@ -43,12 +57,6 @@ export default class DiscourseTopic extends Component.extend(Scrolling) { } } - init() { - super.init(...arguments); - this.appEvents.on("discourse:focus-changed", this, "gotFocus"); - this.appEvents.on("post:highlight", this, "_highlightPost"); - } - didInsertElement() { super.didInsertElement(...arguments); @@ -61,14 +69,6 @@ export default class DiscourseTopic extends Component.extend(Scrolling) { ); } - willDestroy() { - super.willDestroy(...arguments); - - // this happens after route exit, stuff could have trickled in - this.appEvents.off("discourse:focus-changed", this, "gotFocus"); - this.appEvents.off("post:highlight", this, "_highlightPost"); - } - willDestroyElement() { super.willDestroyElement(...arguments); diff --git a/app/assets/javascripts/discourse/app/components/glimmer-site-header.gjs b/app/assets/javascripts/discourse/app/components/glimmer-site-header.gjs index d6b5fc5be6c..d4c5cb26586 100644 --- a/app/assets/javascripts/discourse/app/components/glimmer-site-header.gjs +++ b/app/assets/javascripts/discourse/app/components/glimmer-site-header.gjs @@ -49,6 +49,25 @@ export default class GlimmerSiteHeader extends Component { schedule("afterRender", () => this.animateMenu()); } + willDestroy() { + super.willDestroy(...arguments); + this.appEvents.off("user-menu:rendered", this, this.animateMenu); + + if (this.dropDownHeaderEnabled) { + this.appEvents.off( + "sidebar-hamburger-dropdown:rendered", + this, + this.animateMenu + ); + } + + this._itsatrap?.destroy(); + this._itsatrap = null; + + window.removeEventListener("scroll", this._recalculateHeaderOffset); + this._resizeObserver?.disconnect(); + } + get dropDownHeaderEnabled() { return !this.sidebarEnabled || this.site.narrowDesktopView; } @@ -361,25 +380,6 @@ export default class GlimmerSiteHeader extends Component { ); } - willDestroy() { - super.willDestroy(...arguments); - this.appEvents.off("user-menu:rendered", this, this.animateMenu); - - if (this.dropDownHeaderEnabled) { - this.appEvents.off( - "sidebar-hamburger-dropdown:rendered", - this, - this.animateMenu - ); - } - - this._itsatrap?.destroy(); - this._itsatrap = null; - - window.removeEventListener("scroll", this._recalculateHeaderOffset); - this._resizeObserver?.disconnect(); - } - <template> <div class={{concatClass diff --git a/app/assets/javascripts/discourse/app/components/modal/bookmark.js b/app/assets/javascripts/discourse/app/components/modal/bookmark.js index 0abbf266104..4310383566a 100644 --- a/app/assets/javascripts/discourse/app/components/modal/bookmark.js +++ b/app/assets/javascripts/discourse/app/components/modal/bookmark.js @@ -53,6 +53,13 @@ export default class BookmarkModal extends Component { _itsatrap = new ItsATrap(); + willDestroy() { + super.willDestroy(...arguments); + this._itsatrap?.destroy(); + this._itsatrap = null; + KeyboardShortcuts.unpause(); + } + get bookmark() { return this.args.model.bookmark; } @@ -127,13 +134,6 @@ export default class BookmarkModal extends Component { return labels; } - willDestroy() { - super.willDestroy(...arguments); - this._itsatrap?.destroy(); - this._itsatrap = null; - KeyboardShortcuts.unpause(); - } - @action didInsert() { discourseLater(() => { diff --git a/app/assets/javascripts/discourse/app/components/modal/change-owner.js b/app/assets/javascripts/discourse/app/components/modal/change-owner.js index 62ca41d60bf..a2c908dea67 100644 --- a/app/assets/javascripts/discourse/app/components/modal/change-owner.js +++ b/app/assets/javascripts/discourse/app/components/modal/change-owner.js @@ -26,6 +26,7 @@ export default class ChangeOwnerModal extends Component { get selectedPostsCount() { return this.args.model.selectedPostsCount; } + @action async changeOwnershipOfPosts() { this.saving = true; diff --git a/app/assets/javascripts/discourse/app/components/plugin-outlet.js b/app/assets/javascripts/discourse/app/components/plugin-outlet.js index aa50a47a5b1..42e65f51af9 100644 --- a/app/assets/javascripts/discourse/app/components/plugin-outlet.js +++ b/app/assets/javascripts/discourse/app/components/plugin-outlet.js @@ -141,9 +141,11 @@ export default class PluginOutletComponent extends GlimmerComponentWithDeprecate }); return this.#parentView; } + set parentView(value) { this.#parentView = value; } + get _parentView() { return this.parentView; } @@ -166,9 +168,11 @@ class PluginOutletWithTagNameWrapper extends ClassicComponent { return this.#parentView.parentView; } } + set parentView(value) { this.#parentView = value; } + get _parentView() { return this.parentView; } diff --git a/app/assets/javascripts/discourse/app/components/search-menu.js b/app/assets/javascripts/discourse/app/components/search-menu.js index aa4ed7386fc..a15aec68804 100644 --- a/app/assets/javascripts/discourse/app/components/search-menu.js +++ b/app/assets/javascripts/discourse/app/components/search-menu.js @@ -47,6 +47,14 @@ export default class SearchMenu extends Component { _debouncer = null; _activeSearch = null; + willDestroy() { + if (!this.args.inlineResults) { + document.removeEventListener("mousedown", this.onDocumentPress); + document.removeEventListener("touchend", this.onDocumentPress); + } + super.willDestroy(...arguments); + } + @bind setupEventListeners() { // We only need to register click events when the search menu is rendered outside of the header. @@ -57,14 +65,6 @@ export default class SearchMenu extends Component { } } - willDestroy() { - if (!this.args.inlineResults) { - document.removeEventListener("mousedown", this.onDocumentPress); - document.removeEventListener("touchend", this.onDocumentPress); - } - super.willDestroy(...arguments); - } - @bind onDocumentPress(event) { if (!this.menuPanelOpen) { diff --git a/app/assets/javascripts/discourse/app/components/sidebar.js b/app/assets/javascripts/discourse/app/components/sidebar.js index e11fd067f1c..72adad415e0 100644 --- a/app/assets/javascripts/discourse/app/components/sidebar.js +++ b/app/assets/javascripts/discourse/app/components/sidebar.js @@ -17,6 +17,13 @@ export default class Sidebar extends Component { } } + willDestroy() { + super.willDestroy(...arguments); + if (this.site.mobileView) { + document.removeEventListener("click", this.collapseSidebar); + } + } + get showSwitchPanelButtonsOnTop() { return this.siteSettings.default_sidebar_switch_panel_position === "top"; } @@ -55,11 +62,4 @@ export default class Sidebar extends Component { this.args.toggleSidebar(); } } - - willDestroy() { - super.willDestroy(...arguments); - if (this.site.mobileView) { - document.removeEventListener("click", this.collapseSidebar); - } - } } diff --git a/app/assets/javascripts/discourse/app/components/sidebar/section-form-link.gjs b/app/assets/javascripts/discourse/app/components/sidebar/section-form-link.gjs index f258a0ab318..4de63801d0f 100644 --- a/app/assets/javascripts/discourse/app/components/sidebar/section-form-link.gjs +++ b/app/assets/javascripts/discourse/app/components/sidebar/section-form-link.gjs @@ -44,6 +44,7 @@ export default class SectionFormLink extends Component { } } } + @action dragEnter() { this.dragCount++; diff --git a/app/assets/javascripts/discourse/app/components/topic-map/private-message-map.gjs b/app/assets/javascripts/discourse/app/components/topic-map/private-message-map.gjs index 1564c8b4c8e..210ea5925d2 100644 --- a/app/assets/javascripts/discourse/app/components/topic-map/private-message-map.gjs +++ b/app/assets/javascripts/discourse/app/components/topic-map/private-message-map.gjs @@ -205,6 +205,7 @@ class PmRemoveLink extends Component { didConfirm: () => this.args.removeAllowedUser(this.args.model), }); } + <template> <DButton class="remove-invited" diff --git a/app/assets/javascripts/discourse/app/controllers/preferences/tracking.js b/app/assets/javascripts/discourse/app/controllers/preferences/tracking.js index 76f261094da..acc176f58e2 100644 --- a/app/assets/javascripts/discourse/app/controllers/preferences/tracking.js +++ b/app/assets/javascripts/discourse/app/controllers/preferences/tracking.js @@ -101,6 +101,7 @@ export default class extends Controller { ) .filter((t) => t); } + @computed( "model.watchedCategories", "model.mutedCategories", diff --git a/app/assets/javascripts/discourse/app/controllers/preferences/users.js b/app/assets/javascripts/discourse/app/controllers/preferences/users.js index 7a70d328128..03f1353a78c 100644 --- a/app/assets/javascripts/discourse/app/controllers/preferences/users.js +++ b/app/assets/javascripts/discourse/app/controllers/preferences/users.js @@ -12,6 +12,17 @@ export default class UsersController extends Controller { ) allowPmUsersEnabled; + init() { + super.init(...arguments); + + this.saveAttrNames = [ + "allow_private_messages", + "muted_usernames", + "allowed_pm_usernames", + "enable_allowed_pm_users", + ]; + } + @computed("model.muted_usernames") get mutedUsernames() { let usernames = this.model.muted_usernames; @@ -34,17 +45,6 @@ export default class UsersController extends Controller { return makeArray(usernames).uniq(); } - init() { - super.init(...arguments); - - this.saveAttrNames = [ - "allow_private_messages", - "muted_usernames", - "allowed_pm_usernames", - "enable_allowed_pm_users", - ]; - } - @action onChangeMutedUsernames(usernames) { this.model.set("muted_usernames", usernames.uniq().join(",")); diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.gjs b/app/assets/javascripts/discourse/app/lib/plugin-api.gjs index 2c3066b9433..b4d1afa2ca5 100644 --- a/app/assets/javascripts/discourse/app/lib/plugin-api.gjs +++ b/app/assets/javascripts/discourse/app/lib/plugin-api.gjs @@ -2273,6 +2273,7 @@ class PluginApi { addSaveableUserField(fieldName) { addSaveableUserField(fieldName); } + addSaveableUserOptionField(fieldName) { addSaveableUserOptionField(fieldName); } diff --git a/app/assets/javascripts/discourse/app/lib/user-menu/base-item.js b/app/assets/javascripts/discourse/app/lib/user-menu/base-item.js index 803ad35c0de..63af0a7cb4a 100644 --- a/app/assets/javascripts/discourse/app/lib/user-menu/base-item.js +++ b/app/assets/javascripts/discourse/app/lib/user-menu/base-item.js @@ -7,6 +7,7 @@ export default class UserMenuBaseItem { this.site = site; this.siteSettings = siteSettings; } + get className() {} get linkHref() { diff --git a/app/assets/javascripts/discourse/app/models/site.js b/app/assets/javascripts/discourse/app/models/site.js index c5628d57d4d..ad11d0ffd31 100644 --- a/app/assets/javascripts/discourse/app/models/site.js +++ b/app/assets/javascripts/discourse/app/models/site.js @@ -81,13 +81,6 @@ export default class Site extends RestModel.extend().reopenClass(Singleton) { @sort("categories", "topicCountDesc") categoriesByCount; - @computed("categories.[]") - get categoriesById() { - const map = new Map(); - this.categories.forEach((c) => map.set(c.id, c)); - return map; - } - init() { super.init(...arguments); @@ -95,6 +88,13 @@ export default class Site extends RestModel.extend().reopenClass(Singleton) { this.categories = this.categories || []; } + @computed("categories.[]") + get categoriesById() { + const map = new Map(); + this.categories.forEach((c) => map.set(c.id, c)); + return map; + } + @discourseComputed("notification_types") notificationLookup(notificationTypes) { const result = []; diff --git a/app/assets/javascripts/discourse/app/services/client-error-handler.js b/app/assets/javascripts/discourse/app/services/client-error-handler.js index 51f5307ef2c..62ec75eddc9 100644 --- a/app/assets/javascripts/discourse/app/services/client-error-handler.js +++ b/app/assets/javascripts/discourse/app/services/client-error-handler.js @@ -26,10 +26,6 @@ export default class ClientErrorHandlerService extends Service { document.addEventListener("discourse-error", this.handleDiscourseError); } - get rootElement() { - return document.querySelector(getOwner(this).rootElement); - } - willDestroy() { document.removeEventListener("discourse-error", this.handleDiscourseError); this.rootElement @@ -37,6 +33,10 @@ export default class ClientErrorHandlerService extends Service { .forEach((e) => e.remove()); } + get rootElement() { + return document.querySelector(getOwner(this).rootElement); + } + @bind handleDiscourseError(e) { if (e.detail?.themeId) { diff --git a/app/assets/javascripts/discourse/app/services/lightbox.js b/app/assets/javascripts/discourse/app/services/lightbox.js index b398a065af6..8337a02b913 100644 --- a/app/assets/javascripts/discourse/app/services/lightbox.js +++ b/app/assets/javascripts/discourse/app/services/lightbox.js @@ -60,6 +60,10 @@ export default class LightboxService extends Service { ); } + willDestroy() { + this.#reset(); + } + @bind async onLightboxOpened({ items, currentItem }) { this.originalSiteThemeColor = await getSiteThemeColor(); @@ -268,8 +272,4 @@ export default class LightboxService extends Service { event.target.toggleAttribute(SELECTORS.DOCUMENT_LAST_FOCUSED_ELEMENT); } - - willDestroy() { - this.#reset(); - } } diff --git a/app/assets/javascripts/discourse/app/services/notifications.js b/app/assets/javascripts/discourse/app/services/notifications.js index edd614c8da8..a924fb4136d 100644 --- a/app/assets/javascripts/discourse/app/services/notifications.js +++ b/app/assets/javascripts/discourse/app/services/notifications.js @@ -16,6 +16,10 @@ export default class NotificationsService extends Service { this._checkDoNotDisturb(); } + willDestroy() { + clearTimeout(this.#dndTimer); + } + _checkDoNotDisturb() { clearTimeout(this.#dndTimer); @@ -38,8 +42,4 @@ export default class NotificationsService extends Service { this.isInDoNotDisturb = false; } } - - willDestroy() { - clearTimeout(this.#dndTimer); - } } diff --git a/app/assets/javascripts/discourse/app/services/presence.js b/app/assets/javascripts/discourse/app/services/presence.js index d1dec361942..7968c4167c5 100644 --- a/app/assets/javascripts/discourse/app/services/presence.js +++ b/app/assets/javascripts/discourse/app/services/presence.js @@ -277,10 +277,6 @@ export default class PresenceService extends Service { } } - get _presentChannels() { - return new Set(this._presentProxies.keys()); - } - willDestroy() { super.willDestroy(...arguments); window.removeEventListener("beforeunload", this._beaconLeaveAll); @@ -288,6 +284,10 @@ export default class PresenceService extends Service { cancel(this._debounceTimer); } + get _presentChannels() { + return new Set(this._presentProxies.keys()); + } + // Get a PresenceChannel object representing a single channel getChannel(channelName) { return PresenceChannel.create({ diff --git a/app/assets/javascripts/discourse/app/services/route-scroll-manager.js b/app/assets/javascripts/discourse/app/services/route-scroll-manager.js index e20233e9a15..79a6dfda8a3 100644 --- a/app/assets/javascripts/discourse/app/services/route-scroll-manager.js +++ b/app/assets/javascripts/discourse/app/services/route-scroll-manager.js @@ -24,6 +24,17 @@ export default class RouteScrollManager extends Service { ? document.getElementById("ember-testing-container") : document.scrollingElement; + init() { + super.init(...arguments); + this.router.on("routeDidChange", this.routeDidChange); + this.router.on("routeWillChange", this.routeWillChange); + } + + willDestroy() { + this.router.off("routeDidChange", this.routeDidChange); + this.router.off("routeWillChange", this.routeWillChange); + } + @bind routeWillChange() { this.historyStore.set(STORE_KEY, [ @@ -63,15 +74,4 @@ export default class RouteScrollManager extends Service { // No overrides - default to true return true; } - - init() { - super.init(...arguments); - this.router.on("routeDidChange", this.routeDidChange); - this.router.on("routeWillChange", this.routeWillChange); - } - - willDestroy() { - this.router.off("routeDidChange", this.routeDidChange); - this.router.off("routeWillChange", this.routeWillChange); - } } diff --git a/app/assets/javascripts/discourse/app/widgets/post-cooked.js b/app/assets/javascripts/discourse/app/widgets/post-cooked.js index e4cdb7d0a70..5a03038bc5d 100644 --- a/app/assets/javascripts/discourse/app/widgets/post-cooked.js +++ b/app/assets/javascripts/discourse/app/widgets/post-cooked.js @@ -52,15 +52,6 @@ export default class PostCooked { : null; } - update(prev) { - if ( - prev.attrs.cooked !== this.attrs.cooked || - prev.attrs.highlightTerm !== this.attrs.highlightTerm - ) { - return this.init(); - } - } - init() { this.originalQuoteContents = null; // todo should be a better way of detecting if it is composer preview @@ -77,6 +68,15 @@ export default class PostCooked { return this.cookedDiv; } + update(prev) { + if ( + prev.attrs.cooked !== this.attrs.cooked || + prev.attrs.highlightTerm !== this.attrs.highlightTerm + ) { + return this.init(); + } + } + destroy() { this._stopTrackingMentionedUsersStatus(); destroyUserStatusOnMentions(); diff --git a/app/assets/javascripts/discourse/app/widgets/widget.js b/app/assets/javascripts/discourse/app/widgets/widget.js index 941891d9c92..f595717c2d5 100644 --- a/app/assets/javascripts/discourse/app/widgets/widget.js +++ b/app/assets/javascripts/discourse/app/widgets/widget.js @@ -183,6 +183,7 @@ export default class Widget { } } + init() {} transform() { return {}; } @@ -191,8 +192,6 @@ export default class Widget { return {}; } - init() {} - destroy() {} get(propertyPath) { diff --git a/app/assets/javascripts/discourse/lib/with-side-watch.js b/app/assets/javascripts/discourse/lib/with-side-watch.js index 459549ba247..d11a5959886 100644 --- a/app/assets/javascripts/discourse/lib/with-side-watch.js +++ b/app/assets/javascripts/discourse/lib/with-side-watch.js @@ -8,6 +8,7 @@ class BroccoliNoOp extends Plugin { constructor(path) { super([new WatchedDir(path)]); } + build() {} } diff --git a/app/assets/javascripts/discourse/tests/acceptance/sidebar-plugin-api-test.js b/app/assets/javascripts/discourse/tests/acceptance/sidebar-plugin-api-test.js index a9818abd6f7..9a9252010f5 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/sidebar-plugin-api-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/sidebar-plugin-api-test.js @@ -50,8 +50,6 @@ acceptance("Sidebar - Plugin API", function (needs) { }, ]; - willDestroy = () => (sectionDestroy = "section test"); - links = [ new (class extends BaseCustomSidebarSectionLink { name = "random-channel"; @@ -99,6 +97,7 @@ acceptance("Sidebar - Plugin API", function (needs) { text = "Homepage"; })(), ]; + willDestroy = () => (sectionDestroy = "section test"); }; } ); diff --git a/app/assets/javascripts/discourse/tests/acceptance/topic-post-decorate-cooked-test.js b/app/assets/javascripts/discourse/tests/acceptance/topic-post-decorate-cooked-test.js index 86acd205e70..66eebe53dfa 100644 --- a/app/assets/javascripts/discourse/tests/acceptance/topic-post-decorate-cooked-test.js +++ b/app/assets/javascripts/discourse/tests/acceptance/topic-post-decorate-cooked-test.js @@ -14,6 +14,7 @@ acceptance("Acceptance | decorateCookedElement", function () { DemoComponent.eventLog.push("created"); super(...arguments); } + willDestroy() { super.willDestroy(...arguments); DemoComponent.eventLog.push("willDestroy"); diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/render-glimmer-test.js b/app/assets/javascripts/discourse/tests/integration/components/widgets/render-glimmer-test.js index d8f56926ff7..9f8c56e6a57 100644 --- a/app/assets/javascripts/discourse/tests/integration/components/widgets/render-glimmer-test.js +++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/render-glimmer-test.js @@ -47,6 +47,7 @@ class DemoWidget extends Widget { ), ]; } + dummyAction() {} @bind @@ -67,6 +68,11 @@ class DemoComponent extends ClassicComponent { super.init(...arguments); } + willDestroy() { + super.willDestroy(...arguments); + DemoComponent.eventLog.push("willDestroy"); + } + didInsertElement() { super.didInsertElement(...arguments); DemoComponent.eventLog.push("didInsertElement"); @@ -81,11 +87,6 @@ class DemoComponent extends ClassicComponent { super.didReceiveAttrs(...arguments); DemoComponent.eventLog.push("didReceiveAttrs"); } - - willDestroy() { - super.willDestroy(...arguments); - DemoComponent.eventLog.push("willDestroy"); - } } class ToggleDemoWidget extends Widget { diff --git a/app/assets/javascripts/discourse/tests/unit/lib/plugin-api-test.js b/app/assets/javascripts/discourse/tests/unit/lib/plugin-api-test.js index 4240487ca0a..f18c408cad5 100644 --- a/app/assets/javascripts/discourse/tests/unit/lib/plugin-api-test.js +++ b/app/assets/javascripts/discourse/tests/unit/lib/plugin-api-test.js @@ -123,9 +123,11 @@ module("Unit | Utility | plugin-api", function (hooks) { static someStaticMethod() { return "original static method"; } + someFunction() { return "original function"; } + get someGetter() { return "original getter"; } diff --git a/app/assets/javascripts/select-kit/addon/components/category-row.gjs b/app/assets/javascripts/select-kit/addon/components/category-row.gjs index be6c6e3ef4d..f62e34b37b9 100644 --- a/app/assets/javascripts/select-kit/addon/components/category-row.gjs +++ b/app/assets/javascripts/select-kit/addon/components/category-row.gjs @@ -253,6 +253,7 @@ export default class CategoryRow extends Component { description.length > limit ? "…" : "" }`; } + _isValidInput(eventKey) { // relying on passing the event to the input is risky as it could not work // dispatching the event won't work as the event won't be trusted diff --git a/app/assets/javascripts/select-kit/addon/components/tag-chooser.js b/app/assets/javascripts/select-kit/addon/components/tag-chooser.js index 5395e059f34..07ef028ec6f 100644 --- a/app/assets/javascripts/select-kit/addon/components/tag-chooser.js +++ b/app/assets/javascripts/select-kit/addon/components/tag-chooser.js @@ -23,6 +23,16 @@ export default class TagChooser extends MultiSelectComponent.extend(TagsMixin) { excludeSynonyms = false; excludeHasSynonyms = false; + init() { + super.init(...arguments); + + this.setProperties({ + blockedTags: this.blockedTags || [], + termMatchesForbidden: false, + termMatchErrorMessage: null, + }); + } + modifyComponentForRow(collection, item) { if (this.getValue(item) === this.selectKit.filter && !item.count) { return "select-kit/select-kit-row"; @@ -50,16 +60,6 @@ export default class TagChooser extends MultiSelectComponent.extend(TagsMixin) { return null; } - init() { - super.init(...arguments); - - this.setProperties({ - blockedTags: this.blockedTags || [], - termMatchesForbidden: false, - termMatchErrorMessage: null, - }); - } - @computed("tags.[]") get value() { return makeArray(this.tags).uniq(); diff --git a/app/assets/javascripts/select-kit/addon/components/tag-drop.js b/app/assets/javascripts/select-kit/addon/components/tag-drop.js index 52519efb95e..aa604bdda02 100644 --- a/app/assets/javascripts/select-kit/addon/components/tag-drop.js +++ b/app/assets/javascripts/select-kit/addon/components/tag-drop.js @@ -40,6 +40,12 @@ export default class TagDrop extends ComboBoxComponent.extend(TagsMixin) { @readOnly("tagId") value; + init() { + super.init(...arguments); + + this.insertAfterCollection(MAIN_COLLECTION, MORE_TAGS_COLLECTION); + } + @computed("maxTagsInFilterList", "topTags.[]", "mainCollection.[]") get shouldShowMoreTags() { if (this.selectKit.filter?.length > 0) { @@ -49,12 +55,6 @@ export default class TagDrop extends ComboBoxComponent.extend(TagsMixin) { } } - init() { - super.init(...arguments); - - this.insertAfterCollection(MAIN_COLLECTION, MORE_TAGS_COLLECTION); - } - modifyComponentForCollection(collection) { if (collection === MORE_TAGS_COLLECTION) { return FilterForMore; diff --git a/package.json b/package.json index c816e553416..f8d57e49330 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "license": "GPL-2.0-only", "devDependencies": { "@babel/plugin-proposal-decorators": "^7.25.9", - "@discourse/lint-configs": "^2.1.0", + "@discourse/lint-configs": "^2.2.0", "@discourse/moment-timezone-names-translations": "^1.0.0", "@fortawesome/fontawesome-free": "6.6.0", "@glint/core": "^1.5.0", @@ -45,8 +45,8 @@ "lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"", "lint:js": "eslint ./app/assets/javascripts $(script/list_bundled_plugins) --cache --no-error-on-unmatched-pattern", "lint:js:fix": "eslint --fix ./app/assets/javascripts $(script/list_bundled_plugins) --no-error-on-unmatched-pattern", - "lint:hbs": "ember-template-lint 'app/assets/javascripts/**/*.{gjs,hbs}' 'plugins/**/assets/javascripts/**/*.{gjs,hbs}' --no-error-on-unmatched-pattern", - "lint:hbs:fix": "ember-template-lint 'app/assets/javascripts/**/*.{gjs,hbs}' 'plugins/**/assets/javascripts/**/*.{gjs,hbs}' --no-error-on-unmatched-pattern --fix", + "lint:hbs": "ember-template-lint 'app/assets/javascripts/**/*.{gjs,hbs}' $(script/list_bundled_plugins '/assets/javascripts/**/*.{gjs,hbs}') --no-error-on-unmatched-pattern", + "lint:hbs:fix": "ember-template-lint 'app/assets/javascripts/**/*.{gjs,hbs}' $(script/list_bundled_plugins '/assets/javascripts/**/*.{gjs,hbs}') --no-error-on-unmatched-pattern --fix", "lint:prettier": "pnpm pprettier --list-different 'app/assets/stylesheets/**/*.scss' 'app/assets/javascripts/**/*.{js,gjs,hbs}' $(script/list_bundled_plugins '/assets/stylesheets/**/*.scss') $(script/list_bundled_plugins '/assets/javascripts/**/*.{js,gjs,hbs}')", "lint:prettier:fix": "pnpm prettier -w 'app/assets/stylesheets/**/*.scss' 'app/assets/javascripts/**/*.{js,gjs,hbs}' $(script/list_bundled_plugins '/assets/stylesheets/**/*.scss') $(script/list_bundled_plugins '/assets/javascripts/**/*.{js,gjs,hbs}')", "lttf:ignore": "lint-to-the-future ignore", diff --git a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-edit.hbs b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-edit.hbs index d43749415d6..8a784c63c56 100644 --- a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-edit.hbs +++ b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-edit.hbs @@ -106,7 +106,7 @@ </div> {{/if}} - {{#each triggerFields as |field|}} + {{#each this.triggerFields as |field|}} <AutomationField @automation={{this.automation}} @field={{field}} diff --git a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-index.hbs b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-index.hbs index 96c4e5cf2a2..294913e6b65 100644 --- a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-index.hbs +++ b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation-index.hbs @@ -1,4 +1,4 @@ -{{#if model.length}} +{{#if this.model.length}} <table class="automations"> <thead> <tr> @@ -13,7 +13,7 @@ </tr> </thead> <tbody> - {{#each model as |automation|}} + {{#each this.model as |automation|}} <tr> {{#if automation.script.not_found}} <td colspan="5" class="alert alert-danger"> diff --git a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation.hbs b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation.hbs index 516c8183c9c..12e31b5ca26 100644 --- a/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation.hbs +++ b/plugins/automation/admin/assets/javascripts/admin/templates/admin-plugins-discourse-automation.hbs @@ -38,7 +38,7 @@ {{i18n "discourse_automation.title"}} </h1> - {{#if showNewAutomation}} + {{#if this.showNewAutomation}} <DButton @label="discourse_automation.create" @icon="plus" diff --git a/plugins/automation/admin/assets/javascripts/admin/templates/components/topic-trigger.hbs b/plugins/automation/admin/assets/javascripts/admin/templates/components/topic-trigger.hbs index 3c893a1284d..bf89f192936 100644 --- a/plugins/automation/admin/assets/javascripts/admin/templates/components/topic-trigger.hbs +++ b/plugins/automation/admin/assets/javascripts/admin/templates/components/topic-trigger.hbs @@ -5,8 +5,8 @@ <div class="controls"> <Input - @value={{metadata.topic_id}} - {{on "input" (action (mut metadata.topic_id) value="target.value")}} + @value={{this.metadata.topic_id}} + {{on "input" (action (mut this.metadata.topic_id) value="target.value")}} /> </div> </div> \ No newline at end of file diff --git a/plugins/chat/admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-chat-incoming-webhooks/new.hbs b/plugins/chat/admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-chat-incoming-webhooks/new.hbs index 2ed27eeb6c6..5fc3a1706b4 100644 --- a/plugins/chat/admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-chat-incoming-webhooks/new.hbs +++ b/plugins/chat/admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-chat-incoming-webhooks/new.hbs @@ -5,5 +5,5 @@ class="incoming-chat-webhooks-back" /> - <ChatIncomingWebhookEditForm @chatChannels={{model.chat_channels}} /> + <ChatIncomingWebhookEditForm @chatChannels={{this.model.chat_channels}} /> </div> \ No newline at end of file diff --git a/plugins/chat/admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-chat-incoming-webhooks/show.hbs b/plugins/chat/admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-chat-incoming-webhooks/show.hbs index b4b1220ba1e..4a47bdc1345 100644 --- a/plugins/chat/admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-chat-incoming-webhooks/show.hbs +++ b/plugins/chat/admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-chat-incoming-webhooks/show.hbs @@ -5,10 +5,10 @@ class="incoming-chat-webhooks-back" /> - <ConditionalLoadingSpinner @condition={{not model.webhook}}> + <ConditionalLoadingSpinner @condition={{not this.model.webhook}}> <ChatIncomingWebhookEditForm - @webhook={{model.webhook}} - @chatChannels={{model.chat_channels}} + @webhook={{this.model.webhook}} + @chatChannels={{this.model.chat_channels}} /> </ConditionalLoadingSpinner> </div> \ No newline at end of file diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-message-emoji-picker.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-channel-message-emoji-picker.gjs index 7a8316176f9..0d83337d0a0 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-message-emoji-picker.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-message-emoji-picker.gjs @@ -24,6 +24,12 @@ export default class ChatChannelMessageEmojiPicker extends Component { }; }); + @action + willDestroy() { + super.willDestroy(...arguments); + this._popper?.destroy(); + } + @action didSelectEmoji(emoji) { this.chatEmojiPickerManager.picker?.didSelectEmoji(emoji); @@ -58,12 +64,6 @@ export default class ChatChannelMessageEmojiPicker extends Component { element.classList.remove("hidden"); } - @action - willDestroy() { - super.willDestroy(...arguments); - this._popper?.destroy(); - } - <template> <ChatEmojiPicker {{this.listenToBodyScroll}} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-footer.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-footer.gjs index e20f64f34ef..8111199502e 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-footer.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-footer.gjs @@ -43,6 +43,7 @@ export default class ChatFooter extends Component { this.siteSettings.enable_public_channels, ].filter(Boolean).length; } + get shouldRenderFooter() { return ( (this.site.mobileView || this.chatStateManager.isDrawerExpanded) && diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-header.gjs b/plugins/chat/assets/javascripts/discourse/components/chat-header.gjs index 1d661a10ec6..002035b4c05 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-header.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/chat-header.gjs @@ -21,17 +21,17 @@ export default class ChatHeader extends Component { this.router.on("routeDidChange", this, this.#updatePreviousURL); } + willDestroy() { + super.willDestroy(...arguments); + this.router.off("routeDidChange", this, this.#updatePreviousURL); + } + get shouldRender() { return ( this.siteSettings.chat_enabled && this.site.mobileView && this.isChatOpen ); } - willDestroy() { - super.willDestroy(...arguments); - this.router.off("routeDidChange", this, this.#updatePreviousURL); - } - get isChatOpen() { return this.router.currentURL.startsWith("/chat"); } diff --git a/plugins/chat/assets/javascripts/discourse/components/user-threads/index.gjs b/plugins/chat/assets/javascripts/discourse/components/user-threads/index.gjs index e16d517287f..bbca6f82d4c 100644 --- a/plugins/chat/assets/javascripts/discourse/components/user-threads/index.gjs +++ b/plugins/chat/assets/javascripts/discourse/components/user-threads/index.gjs @@ -21,11 +21,6 @@ export default class UserThreads extends Component { trackedChannels = {}; - @cached - get threadsCollection() { - return this.chatApi.userThreads(this.handleLoadedThreads); - } - willDestroy() { super.willDestroy(...arguments); @@ -36,6 +31,11 @@ export default class UserThreads extends Component { this.trackedChannels = {}; } + @cached + get threadsCollection() { + return this.chatApi.userThreads(this.handleLoadedThreads); + } + @bind handleLoadedThreads(result) { return result.threads.map((threadObject) => { diff --git a/plugins/chat/assets/javascripts/discourse/controllers/chat.js b/plugins/chat/assets/javascripts/discourse/controllers/chat.js index 8ba83db0e44..c9a733038b6 100644 --- a/plugins/chat/assets/javascripts/discourse/controllers/chat.js +++ b/plugins/chat/assets/javascripts/discourse/controllers/chat.js @@ -27,6 +27,7 @@ export default class ChatController extends Controller { this.chatStateManager.hasPreloadedChannels ); } + get shouldUseCoreSidebar() { return this.siteSettings.navigation_menu === "sidebar"; } diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-drafts-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-drafts-manager.js index 4e2f6c2f4fd..b7b7efcdfd6 100644 --- a/plugins/chat/assets/javascripts/discourse/services/chat-drafts-manager.js +++ b/plugins/chat/assets/javascripts/discourse/services/chat-drafts-manager.js @@ -6,6 +6,10 @@ export default class ChatDraftsManager extends Service { drafts = {}; + willDestroy() { + cancel(this?._persistHandler); + } + async add(message, channelId, threadId) { try { this.drafts[this.key(channelId, threadId)] = message; @@ -46,8 +50,4 @@ export default class ChatDraftsManager extends Service { // We don't want to throw an error if the draft fails to save } } - - willDestroy() { - cancel(this?._persistHandler); - } } diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-notification-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-notification-manager.js index 8c253066d84..74a8f483546 100644 --- a/plugins/chat/assets/javascripts/discourse/services/chat-notification-manager.js +++ b/plugins/chat/assets/javascripts/discourse/services/chat-notification-manager.js @@ -20,6 +20,28 @@ export default class ChatNotificationManager extends Service { _subscribedToChat = false; _countChatInDocTitle = true; + willDestroy() { + super.willDestroy(...arguments); + + if (!this._shouldRun()) { + return; + } + + this._chatPresenceChannel.off( + "change", + this._subscribeToCorrectNotifications + ); + this._chatPresenceChannel.unsubscribe(); + this._chatPresenceChannel.leave(); + + this._corePresenceChannel.off( + "change", + this._subscribeToCorrectNotifications + ); + this._corePresenceChannel.unsubscribe(); + this._corePresenceChannel.leave(); + } + start() { if (!this._shouldRun()) { return; @@ -52,28 +74,6 @@ export default class ChatNotificationManager extends Service { ); } - willDestroy() { - super.willDestroy(...arguments); - - if (!this._shouldRun()) { - return; - } - - this._chatPresenceChannel.off( - "change", - this._subscribeToCorrectNotifications - ); - this._chatPresenceChannel.unsubscribe(); - this._chatPresenceChannel.leave(); - - this._corePresenceChannel.off( - "change", - this._subscribeToCorrectNotifications - ); - this._corePresenceChannel.unsubscribe(); - this._corePresenceChannel.leave(); - } - shouldCountChatInDocTitle() { return this._countChatInDocTitle; } diff --git a/plugins/chat/assets/javascripts/discourse/services/chat-tracking-state-manager.js b/plugins/chat/assets/javascripts/discourse/services/chat-tracking-state-manager.js index 2ba505b8e2f..ddb2c2738db 100644 --- a/plugins/chat/assets/javascripts/discourse/services/chat-tracking-state-manager.js +++ b/plugins/chat/assets/javascripts/discourse/services/chat-tracking-state-manager.js @@ -23,6 +23,11 @@ export default class ChatTrackingStateManager extends Service { // NOTE: In future, we may want to preload some thread tracking state // as well, but for now we do that on demand when the user opens a channel, + willDestroy() { + super.willDestroy(...arguments); + cancel(this._onTriggerNotificationDebounceHandler); + } + // to avoid having to load all the threads across all channels into memory at once. setupWithPreloadedState({ channel_tracking = {} }) { this.chatChannelsManager.channels.forEach((channel) => { @@ -87,11 +92,6 @@ export default class ChatTrackingStateManager extends Service { }, 0); } - willDestroy() { - super.willDestroy(...arguments); - cancel(this._onTriggerNotificationDebounceHandler); - } - /** * Some reactivity in the app such as the document title * updates are only done via appEvents -- rather than diff --git a/plugins/chat/assets/javascripts/discourse/services/chat.js b/plugins/chat/assets/javascripts/discourse/services/chat.js index 64e8b3204ae..f976fb7615e 100644 --- a/plugins/chat/assets/javascripts/discourse/services/chat.js +++ b/plugins/chat/assets/javascripts/discourse/services/chat.js @@ -43,6 +43,29 @@ export default class Chat extends Service { @tracked _activeMessage = null; @tracked _activeChannel = null; + init() { + super.init(...arguments); + + if (this.userCanChat) { + this.presenceChannel = this.presence.getChannel("/chat/online"); + + onPresenceChange({ + callback: this.onPresenceChangeCallback, + browserHiddenTime: 150000, + userUnseenTime: 150000, + }); + } + } + + willDestroy() { + super.willDestroy(...arguments); + + if (this.userCanChat) { + this.chatSubscriptionsManager.stopChannelsSubscriptions(); + removeOnPresenceChange(this.onPresenceChangeCallback); + } + } + get activeChannel() { return this._activeChannel; } @@ -94,20 +117,6 @@ export default class Chat extends Service { } } - init() { - super.init(...arguments); - - if (this.userCanChat) { - this.presenceChannel = this.presence.getChannel("/chat/online"); - - onPresenceChange({ - callback: this.onPresenceChangeCallback, - browserHiddenTime: 150000, - userUnseenTime: 150000, - }); - } - } - @bind onPresenceChangeCallback(present) { if (present) { @@ -245,15 +254,6 @@ export default class Chat extends Service { ); } - willDestroy() { - super.willDestroy(...arguments); - - if (this.userCanChat) { - this.chatSubscriptionsManager.stopChannelsSubscriptions(); - removeOnPresenceChange(this.onPresenceChangeCallback); - } - } - updatePresence() { next(() => { if (this.isDestroyed || this.isDestroying) { diff --git a/plugins/discourse-presence/assets/javascripts/discourse/services/composer-presence-manager.js b/plugins/discourse-presence/assets/javascripts/discourse/services/composer-presence-manager.js index e099f522b34..09e8600aafa 100644 --- a/plugins/discourse-presence/assets/javascripts/discourse/services/composer-presence-manager.js +++ b/plugins/discourse-presence/assets/javascripts/discourse/services/composer-presence-manager.js @@ -8,6 +8,10 @@ const KEEP_ALIVE_DURATION_SECONDS = 10; export default class ComposerPresenceManager extends Service { @service presence; + willDestroy() { + this.leave(); + } + notifyState(intent, id) { if ( this.siteSettings.allow_users_to_hide_profile && @@ -57,8 +61,4 @@ export default class ComposerPresenceManager extends Service { this._presentChannel = this.presence.getChannel(channelName); this._presentChannel.enter(); } - - willDestroy() { - this.leave(); - } } diff --git a/plugins/poll/assets/javascripts/discourse/components/poll-breakdown-chart.gjs b/plugins/poll/assets/javascripts/discourse/components/poll-breakdown-chart.gjs index 04d6244f169..ab03382ddd4 100644 --- a/plugins/poll/assets/javascripts/discourse/components/poll-breakdown-chart.gjs +++ b/plugins/poll/assets/javascripts/discourse/components/poll-breakdown-chart.gjs @@ -28,6 +28,14 @@ export default class PollBreakdownChart extends Component { this._optionToSlice = {}; } + willDestroy() { + super.willDestroy(...arguments); + + if (this._chart) { + this._chart.destroy(); + } + } + didInsertElement() { super.didInsertElement(...arguments); @@ -44,14 +52,6 @@ export default class PollBreakdownChart extends Component { } } - willDestroy() { - super.willDestroy(...arguments); - - if (this._chart) { - this._chart.destroy(); - } - } - @discourseComputed("optionColors", "index") colorStyle(optionColors, index) { return htmlSafe(`background: ${optionColors[index]};`); diff --git a/plugins/poll/assets/javascripts/discourse/components/poll-info.gjs b/plugins/poll/assets/javascripts/discourse/components/poll-info.gjs index ffe5db6cece..2b9d5332d4e 100644 --- a/plugins/poll/assets/javascripts/discourse/components/poll-info.gjs +++ b/plugins/poll/assets/javascripts/discourse/components/poll-info.gjs @@ -155,6 +155,7 @@ export default class PollInfoComponent extends Component { this.publicTitle ); } + <template> <div class="poll-info"> <div class="poll-info_counts"> diff --git a/plugins/poll/assets/javascripts/discourse/components/poll-results-pie.gjs b/plugins/poll/assets/javascripts/discourse/components/poll-results-pie.gjs index 967f73a290c..8eaebe03eca 100644 --- a/plugins/poll/assets/javascripts/discourse/components/poll-results-pie.gjs +++ b/plugins/poll/assets/javascripts/discourse/components/poll-results-pie.gjs @@ -104,6 +104,7 @@ export default class PollResultsPieComponent extends Component { registerCanvasElement = modifier((element) => { this.canvasElement = element; }); + get canvasId() { return htmlSafe(`poll-results-chart-${this.args.id}`); } @@ -125,6 +126,7 @@ export default class PollResultsPieComponent extends Component { // eslint-disable-next-line no-undef this._chart = new Chart(el.getContext("2d"), config); } + <template> <div class="poll-results-chart"> <canvas diff --git a/plugins/poll/assets/javascripts/discourse/components/poll-results-standard.gjs b/plugins/poll/assets/javascripts/discourse/components/poll-results-standard.gjs index ef7772df5bf..5de41c2b25c 100644 --- a/plugins/poll/assets/javascripts/discourse/components/poll-results-standard.gjs +++ b/plugins/poll/assets/javascripts/discourse/components/poll-results-standard.gjs @@ -72,6 +72,7 @@ export default class PollResultsStandardComponent extends Component { get isMultiple() { return this.args.pollType === "multiple"; } + <template> <ul class="results"> {{#each this.orderedOptions key="voters" as |option|}} diff --git a/plugins/poll/assets/javascripts/discourse/components/poll-results-tabs.gjs b/plugins/poll/assets/javascripts/discourse/components/poll-results-tabs.gjs index 9a6d710aab4..263eb4a7449 100644 --- a/plugins/poll/assets/javascripts/discourse/components/poll-results-tabs.gjs +++ b/plugins/poll/assets/javascripts/discourse/components/poll-results-tabs.gjs @@ -20,6 +20,7 @@ export default class TabsComponent extends Component { ? this.tabs[1] : this.tabs[0]; } + get tabs() { let tabs = []; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b094cc0c1cb..3a37b6f391f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,8 +32,8 @@ importers: specifier: ^7.25.9 version: 7.25.9(@babel/core@7.26.0) '@discourse/lint-configs': - specifier: ^2.1.0 - version: 2.1.0(ember-template-lint@6.0.0)(eslint@9.14.0)(prettier@2.8.8) + specifier: ^2.2.0 + version: 2.2.0(ember-template-lint@6.0.0)(eslint@9.14.0)(prettier@2.8.8) '@discourse/moment-timezone-names-translations': specifier: ^1.0.0 version: 1.0.0 @@ -1836,8 +1836,8 @@ packages: '@discourse/itsatrap@2.0.10': resolution: {integrity: sha512-Jn1gdiyHMGUsmUfLFf4Q7VnTAv0l7NePbegU6pKhKHEmbzV3FosGxq30fTOYgVyTS1bxqGjlA6LvQttJpv3ROw==} - '@discourse/lint-configs@2.1.0': - resolution: {integrity: sha512-VoZ/+kV1F/nO+bdKN3a/LSFcJTXGwUUVw3yaJiiJCc/+k4fcPaOgcI3z+Ow0ld+DPFZUVkqmxj18r86ThCLyCA==} + '@discourse/lint-configs@2.2.0': + resolution: {integrity: sha512-lj13X+3/DRV2ZBQe3eJvxOO23e87DPfUSSqm0UPfP04VJ7141BHwWn9VVF0rOr+bMe2eiirsqlg2AbMn7gMb+A==} peerDependencies: ember-template-lint: 6.0.0 eslint: ^9.14.0 @@ -2547,6 +2547,12 @@ packages: '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + '@stylistic/eslint-plugin-js@2.11.0': + resolution: {integrity: sha512-btchD0P3iij6cIk5RR5QMdEhtCCV0+L6cNheGhGCd//jaHILZMTi/EOqgEDAf1s4ZoViyExoToM+S2Iwa3U9DA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: '>=8.40.0' + '@swc/core-darwin-arm64@1.9.2': resolution: {integrity: sha512-nETmsCoY29krTF2PtspEgicb3tqw7Ci5sInTI03EU5zpqYbPjoPH99BVTjj0OsF53jP5MxwnLI5Hm21lUn1d6A==} engines: {node: '>=10'} @@ -9341,11 +9347,12 @@ snapshots: '@discourse/itsatrap@2.0.10': {} - '@discourse/lint-configs@2.1.0(ember-template-lint@6.0.0)(eslint@9.14.0)(prettier@2.8.8)': + '@discourse/lint-configs@2.2.0(ember-template-lint@6.0.0)(eslint@9.14.0)(prettier@2.8.8)': dependencies: '@babel/core': 7.26.0(supports-color@8.1.1) '@babel/eslint-parser': 7.25.8(@babel/core@7.26.0)(eslint@9.14.0) '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.0) + '@stylistic/eslint-plugin-js': 2.11.0(eslint@9.14.0) ember-template-lint: 6.0.0 eslint: 9.14.0 eslint-plugin-decorator-position: 6.0.0(@babel/eslint-parser@7.25.8(@babel/core@7.26.0)(eslint@9.14.0))(eslint@9.14.0) @@ -10306,6 +10313,12 @@ snapshots: '@socket.io/component-emitter@3.1.2': {} + '@stylistic/eslint-plugin-js@2.11.0(eslint@9.14.0)': + dependencies: + eslint: 9.14.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + '@swc/core-darwin-arm64@1.9.2': optional: true