From 583c932173d6c141e1dc25a5ec10dacade727c11 Mon Sep 17 00:00:00 2001 From: David Taylor Date: Mon, 2 Sep 2024 10:08:07 +0100 Subject: [PATCH] DEV: Refactor complex initializers into classes (#28661) We're working to remove all decorators from object-literal-properties. This commit refactors all initializers which were using these decorators into classes, where decorators are allowed. Also adds cleanup logic to the local-dates initializer, which was previously missing. --- .../app/instance-initializers/banner.js | 29 +++++++--- .../instance-initializers/live-development.js | 30 ++++++++--- .../app/instance-initializers/logout.js | 31 ++++++++--- .../app/instance-initializers/read-only.js | 29 +++++++--- .../subscribe-user-notifications.js | 53 +++++++++++-------- .../discourse/initializers/chat-setup.js | 49 ++++++++++------- .../initializers/discourse-local-dates.js | 47 +++++++++------- 7 files changed, 180 insertions(+), 88 deletions(-) diff --git a/app/assets/javascripts/discourse/app/instance-initializers/banner.js b/app/assets/javascripts/discourse/app/instance-initializers/banner.js index ffc2a4bd5ba..084c44af82a 100644 --- a/app/assets/javascripts/discourse/app/instance-initializers/banner.js +++ b/app/assets/javascripts/discourse/app/instance-initializers/banner.js @@ -1,23 +1,25 @@ import EmberObject from "@ember/object"; +import { setOwner } from "@ember/owner"; +import { service } from "@ember/service"; import PreloadStore from "discourse/lib/preload-store"; import { bind } from "discourse-common/utils/decorators"; -export default { - after: "message-bus", +class BannerInit { + @service site; + @service messageBus; - initialize(owner) { - this.site = owner.lookup("service:site"); - this.messageBus = owner.lookup("service:message-bus"); + constructor(owner) { + setOwner(this, owner); const banner = EmberObject.create(PreloadStore.get("banner") || {}); this.site.set("banner", banner); this.messageBus.subscribe("/site/banner", this.onMessage); - }, + } teardown() { this.messageBus.unsubscribe("/site/banner", this.onMessage); - }, + } @bind onMessage(data) { @@ -26,5 +28,18 @@ export default { } else { this.site.set("banner", null); } + } +} + +export default { + after: "message-bus", + + initialize(owner) { + this.instance = new BannerInit(owner); + }, + + teardown() { + this.instance.teardown(); + this.instance = null; }, }; diff --git a/app/assets/javascripts/discourse/app/instance-initializers/live-development.js b/app/assets/javascripts/discourse/app/instance-initializers/live-development.js index d1ef0d3b525..220cd14fc35 100644 --- a/app/assets/javascripts/discourse/app/instance-initializers/live-development.js +++ b/app/assets/javascripts/discourse/app/instance-initializers/live-development.js @@ -1,11 +1,15 @@ +import { setOwner } from "@ember/owner"; +import { service } from "@ember/service"; import discourseLater from "discourse-common/lib/later"; import { bind } from "discourse-common/utils/decorators"; -// Use the message bus for live reloading of components for faster development. -export default { - initialize(owner) { - this.messageBus = owner.lookup("service:message-bus"); - this.session = owner.lookup("service:session"); +// Use the message bus for live reloading of components for faster development. +class LiveDevelopmentInit { + @service messageBus; + @service session; + + constructor(owner) { + setOwner(this, owner); const PRESERVED_QUERY_PARAMS = ["preview_theme_id", "pp", "safe_mode"]; const params = new URLSearchParams(window.location.search); @@ -34,11 +38,11 @@ export default { this.onFileChange, this.session.mbLastFileChangeId ); - }, + } teardown() { this.messageBus.unsubscribe("/file-change", this.onFileChange); - }, + } @bind onFileChange(data) { @@ -75,12 +79,22 @@ export default { } } }); - }, + } refreshCSS(node, newHref) { const reloaded = node.cloneNode(true); reloaded.href = newHref; node.insertAdjacentElement("afterend", reloaded); discourseLater(() => node?.parentNode?.removeChild(node), 500); + } +} + +export default { + initialize(owner) { + this.instance = new LiveDevelopmentInit(owner); + }, + teardown() { + this.instance.teardown(); + this.instance = null; }, }; diff --git a/app/assets/javascripts/discourse/app/instance-initializers/logout.js b/app/assets/javascripts/discourse/app/instance-initializers/logout.js index d270c2e9055..6a00e33d69c 100644 --- a/app/assets/javascripts/discourse/app/instance-initializers/logout.js +++ b/app/assets/javascripts/discourse/app/instance-initializers/logout.js @@ -1,3 +1,5 @@ +import { setOwner } from "@ember/owner"; +import { service } from "@ember/service"; import logout from "discourse/lib/logout"; import { bind } from "discourse-common/utils/decorators"; import I18n from "discourse-i18n"; @@ -5,13 +7,13 @@ import I18n from "discourse-i18n"; let _showingLogout = false; // Subscribe to "logout" change events via the Message Bus -export default { - after: "message-bus", +class LogoutInit { + @service messageBus; + @service dialog; + @service currentUser; - initialize(owner) { - this.messageBus = owner.lookup("service:message-bus"); - this.dialog = owner.lookup("service:dialog"); - this.currentUser = owner.lookup("service:current-user"); + constructor(owner) { + setOwner(this, owner); if (this.currentUser) { this.messageBus.subscribe( @@ -19,7 +21,7 @@ export default { this.onMessage ); } - }, + } teardown() { if (this.currentUser) { @@ -28,7 +30,7 @@ export default { this.onMessage ); } - }, + } @bind onMessage() { @@ -45,5 +47,18 @@ export default { didCancel: logout, shouldDisplayCancel: false, }); + } +} + +export default { + after: "message-bus", + + initialize(owner) { + this.instance = new LogoutInit(owner); + }, + + teardown() { + this.instance.teardown(); + this.instance = null; }, }; diff --git a/app/assets/javascripts/discourse/app/instance-initializers/read-only.js b/app/assets/javascripts/discourse/app/instance-initializers/read-only.js index de339ff2146..54affdeee9e 100644 --- a/app/assets/javascripts/discourse/app/instance-initializers/read-only.js +++ b/app/assets/javascripts/discourse/app/instance-initializers/read-only.js @@ -1,22 +1,37 @@ +import { setOwner } from "@ember/owner"; +import { service } from "@ember/service"; import { bind } from "discourse-common/utils/decorators"; // Subscribe to "read-only" status change events via the Message Bus -export default { - after: "message-bus", +class ReadOnlyInit { + @service messageBus; + @service site; - initialize(owner) { - this.messageBus = owner.lookup("service:message-bus"); - this.site = owner.lookup("service:site"); + constructor(owner) { + setOwner(this, owner); this.messageBus.subscribe("/site/read-only", this.onMessage); - }, + } teardown() { this.messageBus.unsubscribe("/site/read-only", this.onMessage); - }, + } @bind onMessage(enabled) { this.site.set("isReadOnly", enabled); + } +} + +export default { + after: "message-bus", + + initialize(owner) { + this.instance = new ReadOnlyInit(owner); + }, + + teardown() { + this.instance.teardown(); + this.instance = null; }, }; diff --git a/app/assets/javascripts/discourse/app/instance-initializers/subscribe-user-notifications.js b/app/assets/javascripts/discourse/app/instance-initializers/subscribe-user-notifications.js index 2b4f680ffae..7bb98e9ec22 100644 --- a/app/assets/javascripts/discourse/app/instance-initializers/subscribe-user-notifications.js +++ b/app/assets/javascripts/discourse/app/instance-initializers/subscribe-user-notifications.js @@ -1,4 +1,6 @@ // Subscribes to user events on the message bus +import { setOwner } from "@ember/owner"; +import { service } from "@ember/service"; import { alertChannel, disable as disableDesktopNotifications, @@ -14,24 +16,22 @@ import Notification from "discourse/models/notification"; import { isTesting } from "discourse-common/config/environment"; import { bind } from "discourse-common/utils/decorators"; -export default { - after: "message-bus", +class SubscribeUserNotificationsInit { + @service currentUser; + @service messageBus; + @service store; + @service appEvents; + @service siteSettings; + @service site; + @service router; - initialize(owner) { - this.currentUser = owner.lookup("service:current-user"); + constructor(owner) { + setOwner(this, owner); if (!this.currentUser) { return; } - this.messageBus = owner.lookup("service:message-bus"); - this.store = owner.lookup("service:store"); - this.messageBus = owner.lookup("service:message-bus"); - this.appEvents = owner.lookup("service:app-events"); - this.siteSettings = owner.lookup("service:site-settings"); - this.site = owner.lookup("service:site"); - this.router = owner.lookup("service:router"); - this.reviewableCountsChannel = `/reviewable_counts/${this.currentUser.id}`; this.messageBus.subscribe( @@ -82,7 +82,7 @@ export default { unsubscribePushNotifications(this.currentUser); } } - }, + } teardown() { if (!this.currentUser) { @@ -116,7 +116,7 @@ export default { this.messageBus.unsubscribe("/client_settings", this.onClientSettings); this.messageBus.unsubscribe(alertChannel(this.currentUser), this.onAlert); - }, + } @bind onReviewableCounts(data) { @@ -128,7 +128,7 @@ export default { "unseen_reviewable_count", data.unseen_reviewable_count ); - }, + } @bind onNotification(data) { @@ -210,22 +210,22 @@ export default { stale.results.set("content", newNotifications); } - }, + } @bind onUserDrafts(data) { this.currentUser.updateDraftProperties(data); - }, + } @bind onDoNotDisturb(data) { this.currentUser.updateDoNotDisturbStatus(data.ends_at); - }, + } @bind onUserStatus(data) { this.appEvents.trigger("user-status:changed", data); - }, + } @bind onCategories(data) { @@ -251,12 +251,12 @@ export default { (data.deleted_categories || []).forEach((id) => this.site.removeCategory(id) ); - }, + } @bind onClientSettings(data) { this.siteSettings[data.name] = data.value; - }, + } @bind onAlert(data) { @@ -268,5 +268,16 @@ export default { this.appEvents ); } + } +} + +export default { + after: "message-bus", + initialize(owner) { + this.instance = new SubscribeUserNotificationsInit(owner); + }, + teardown() { + this.instance.teardown(); + this.instance = null; }, }; diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js index 35eab70329d..a51aad398a1 100644 --- a/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js +++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-setup.js @@ -1,3 +1,5 @@ +import { setOwner } from "@ember/owner"; +import { service } from "@ember/service"; import { number } from "discourse/lib/formatter"; import { withPluginApi } from "discourse/lib/plugin-api"; import { getOwnerWithFallback } from "discourse-common/lib/get-owner"; @@ -14,18 +16,17 @@ const MIN_REFRESH_DURATION_MS = 180000; // 3 minutes replaceIcon("d-chat", "comment"); -export default { - name: "chat-setup", - before: "hashtag-css-generator", +class ChatSetupInit { + @service router; + @service("chat") chatService; + @service chatHistory; + @service site; + @service siteSettings; + @service currentUser; + @service appEvents; - initialize(container) { - this.router = container.lookup("service:router"); - this.chatService = container.lookup("service:chat"); - this.chatHistory = container.lookup("service:chat-history"); - this.site = container.lookup("service:site"); - this.siteSettings = container.lookup("service:site-settings"); - this.currentUser = container.lookup("service:current-user"); - this.appEvents = container.lookup("service:app-events"); + constructor(owner) { + setOwner(this, owner); this.appEvents.on("discourse:focus-changed", this, "_handleFocusChanged"); if (!this.chatService.userCanChat) { @@ -40,7 +41,7 @@ export default { } }); - api.registerHashtagType("channel", new ChannelHashtagType(container)); + api.registerHashtagType("channel", new ChannelHashtagType(owner)); api.registerChatComposerButton({ id: "chat-upload-btn", @@ -75,7 +76,7 @@ export default { position: this.site.desktopView ? "inline" : "dropdown", context: "channel", action() { - const chatEmojiPickerManager = container.lookup( + const chatEmojiPickerManager = owner.lookup( "service:chat-emoji-picker-manager" ); chatEmojiPickerManager.open({ context: "channel" }); @@ -90,7 +91,7 @@ export default { position: "dropdown", context: "thread", action() { - const chatEmojiPickerManager = container.lookup( + const chatEmojiPickerManager = owner.lookup( "service:chat-emoji-picker-manager" ); chatEmojiPickerManager.open({ context: "thread" }); @@ -135,7 +136,7 @@ export default { this.chatService.loadChannels(); - const chatNotificationManager = container.lookup( + const chatNotificationManager = owner.lookup( "service:chat-notification-manager" ); chatNotificationManager.start(); @@ -172,12 +173,12 @@ export default { } }); }); - }, + } @bind documentTitleCountCallback() { return this.chatService.getDocumentTitleCount(); - }, + } teardown() { this.appEvents.off("discourse:focus-changed", this, "_handleFocusChanged"); @@ -188,7 +189,7 @@ export default { _lastForcedRefreshAt = null; clearChatComposerButtons(); - }, + } @bind _handleFocusChanged(hasFocus) { @@ -209,5 +210,17 @@ export default { } _lastForcedRefreshAt = Date.now(); + } +} + +export default { + name: "chat-setup", + before: "hashtag-css-generator", + initialize(owner) { + this.instance = new ChatSetupInit(owner); + }, + teardown() { + this.instance.teardown(); + this.instance = null; }, }; diff --git a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js index 9fd0acec80e..4ca311f6f31 100644 --- a/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js +++ b/plugins/discourse-local-dates/assets/javascripts/initializers/discourse-local-dates.js @@ -1,3 +1,4 @@ +import { setOwner } from "@ember/owner"; import { service } from "@ember/service"; import { htmlSafe } from "@ember/template"; import { downloadCalendar } from "discourse/lib/download-calendar"; @@ -343,13 +344,22 @@ function _calculateDuration(element) { return element.dataset === startDataset ? duration : -duration; } -export default { - name: "discourse-local-dates", +class LocalDatesInit { + @service siteSettings; + @service tooltip; + + constructor(owner) { + setOwner(this, owner); + + window.addEventListener("click", this.showDatePopover, { passive: true }); + + if (this.siteSettings.discourse_local_dates_enabled) { + withPluginApi("0.8.8", initializeDiscourseLocalDates); + } + } @bind showDatePopover(event) { - const tooltip = this.container.lookup("service:tooltip"); - if (event?.target?.classList?.contains("download-calendar")) { const dataset = event.target.dataset; downloadCalendar(dataset.title, [ @@ -359,31 +369,30 @@ export default { }, ]); - return tooltip.close("local-date"); + return this.tooltip.close("local-date"); } if (!event?.target?.classList?.contains("discourse-local-date")) { return; } - const siteSettings = this.container.lookup("service:site-settings"); - return tooltip.show(event.target, { + return this.tooltip.show(event.target, { identifier: "local-date", - content: htmlSafe(buildHtmlPreview(event.target, siteSettings)), + content: htmlSafe(buildHtmlPreview(event.target, this.siteSettings)), }); - }, - - initialize(container) { - this.container = container; - window.addEventListener("click", this.showDatePopover, { passive: true }); - - const siteSettings = container.lookup("service:site-settings"); - if (siteSettings.discourse_local_dates_enabled) { - withPluginApi("0.8.8", initializeDiscourseLocalDates); - } - }, + } teardown() { window.removeEventListener("click", this.showDatePopover); + } +} + +export default { + initialize(owner) { + this.instance = new LocalDatesInit(owner); + }, + teardown() { + this.instance.teardown(); + this.instance = null; }, };