diff --git a/app/assets/javascripts/discourse/app/components/header/home-logo.gjs b/app/assets/javascripts/discourse/app/components/header/home-logo.gjs
index 1c6a5cb1763..2f6b5ec5d91 100644
--- a/app/assets/javascripts/discourse/app/components/header/home-logo.gjs
+++ b/app/assets/javascripts/discourse/app/components/header/home-logo.gjs
@@ -11,14 +11,31 @@ import icon from "discourse-common/helpers/d-icon";
import getURL from "discourse-common/lib/get-url";
import Logo from "./logo";
+let hrefCallback;
+
+export function registerHomeLogoHrefCallback(callback) {
+ hrefCallback = callback;
+}
+
+export function clearHomeLogoHrefCallback() {
+ hrefCallback = null;
+}
+
export default class HomeLogo extends Component {
@service session;
@service site;
@service siteSettings;
- href = getURL("/");
darkModeAvailable = this.session.darkModeAvailable;
+ get href() {
+ if (hrefCallback) {
+ return hrefCallback();
+ }
+
+ return getURL("/");
+ }
+
get showMobileLogo() {
return this.site.mobileView && this.logoResolver("mobile_logo").length > 0;
}
diff --git a/app/assets/javascripts/discourse/app/lib/plugin-api.gjs b/app/assets/javascripts/discourse/app/lib/plugin-api.gjs
index 9dbcff62e0b..204b3eea61e 100644
--- a/app/assets/javascripts/discourse/app/lib/plugin-api.gjs
+++ b/app/assets/javascripts/discourse/app/lib/plugin-api.gjs
@@ -13,6 +13,7 @@ import { addCategorySortCriteria } from "discourse/components/edit-category-sett
import { forceDropdownForMenuPanels as glimmerForceDropdownForMenuPanels } from "discourse/components/glimmer-site-header";
import { addGlobalNotice } from "discourse/components/global-notice";
import { headerButtonsDAG } from "discourse/components/header";
+import { registerHomeLogoHrefCallback } from "discourse/components/header/home-logo";
import { headerIconsDAG } from "discourse/components/header/icons";
import { _addBulkButton } from "discourse/components/modal/topic-bulk-actions";
import MountWidget, {
@@ -108,6 +109,7 @@ import { setNewCategoryDefaultColors } from "discourse/routes/new-category";
import { setNotificationsLimit } from "discourse/routes/user-notifications";
import { addComposerSaveErrorCallback } from "discourse/services/composer";
import { attachAdditionalPanel } from "discourse/widgets/header";
+import { registerHomeLogoHrefCallback as registerHomeLogoHrefCallbackOnWidget } from "discourse/widgets/home-logo";
import { addPostClassesCallback } from "discourse/widgets/post";
import { addDecorator } from "discourse/widgets/post-cooked";
import {
@@ -150,7 +152,7 @@ import { modifySelectKit } from "select-kit/mixins/plugin-api";
// docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md whenever you change the version
// using the format described at https://keepachangelog.com/en/1.0.0/.
-export const PLUGIN_API_VERSION = "1.31.0";
+export const PLUGIN_API_VERSION = "1.32.0";
const DEPRECATED_HEADER_WIDGETS = [
"header",
@@ -1943,6 +1945,51 @@ class PluginApi {
);
}
+ /**
+ * Set a callback function to specify the URL used in the home logo.
+ *
+ * This API allows you change the URL of the home logo. As it receives a callback function, you can
+ * dynamically change the URL based on the current user, site settings, or any other context.
+ *
+ * Example: return a static URL
+ * ```
+ * api.registerHomeLogoHrefCallback(() => "https://example.com");
+ * ```
+ *
+ * Example: return a dynamic URL based on the current user
+ * ```
+ * api.registerHomeLogoHrefCallback(() => {
+ * const currentUser = api.getCurrentUser();
+ * return `https://example.com/${currentUser.username}`;
+ * });
+ * ```
+ *
+ * Example: return a URL based on a theme-component setting
+ * ```
+ * api.registerHomeLogoHrefCallback(() => {
+ * return settings.example_logo_url_setting;
+ * });
+ * ```
+ *
+ * Example: return a URL based on the route
+ * ```
+ * api.registerHomeLogoHrefCallback(() => {
+ * if (api.container.lookup("service:discovery").onDiscoveryRoute) {
+ * return "https://forum.example.com/categories";
+ * }
+ *
+ * return "https://forum.example.com/";
+ * });
+ * ```
+ *
+ * @param {Function} callback - A function that returns the URL to be used in the home logo.
+ *
+ */
+ registerHomeLogoHrefCallback(callback) {
+ registerHomeLogoHrefCallback(callback);
+ registerHomeLogoHrefCallbackOnWidget(callback); // for compatibility with the legacy header
+ }
+
/**
* Adds an item to the quick access profile panel, before "Log Out".
*
diff --git a/app/assets/javascripts/discourse/app/widgets/home-logo.js b/app/assets/javascripts/discourse/app/widgets/home-logo.js
index 6e5b1c8ae89..d3ef69c7799 100644
--- a/app/assets/javascripts/discourse/app/widgets/home-logo.js
+++ b/app/assets/javascripts/discourse/app/widgets/home-logo.js
@@ -7,6 +7,16 @@ import { createWidget } from "discourse/widgets/widget";
import getURL from "discourse-common/lib/get-url";
import { iconNode } from "discourse-common/lib/icon-library";
+let hrefCallback;
+
+export function registerHomeLogoHrefCallback(callback) {
+ hrefCallback = callback;
+}
+
+export function clearHomeLogoHrefCallback() {
+ hrefCallback = null;
+}
+
export default createWidget("home-logo", {
services: ["session"],
tagName: "div.title",
@@ -23,6 +33,11 @@ export default createWidget("home-logo", {
href() {
const href = this.settings.href;
+
+ if (hrefCallback) {
+ return hrefCallback();
+ }
+
return typeof href === "function" ? href() : href;
},
diff --git a/app/assets/javascripts/discourse/tests/integration/components/home-logo-test.gjs b/app/assets/javascripts/discourse/tests/integration/components/home-logo-test.gjs
index ec4b970244e..1a2f77a0f93 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/home-logo-test.gjs
+++ b/app/assets/javascripts/discourse/tests/integration/components/home-logo-test.gjs
@@ -1,8 +1,12 @@
import { getOwner } from "@ember/application";
import { render } from "@ember/test-helpers";
import { module, test } from "qunit";
-import HomeLogo from "discourse/components/header/home-logo";
+import HomeLogo, {
+ clearHomeLogoHrefCallback,
+} from "discourse/components/header/home-logo";
+import { withPluginApi } from "discourse/lib/plugin-api";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
+import { query } from "discourse/tests/helpers/qunit-helpers";
const bigLogo = "/images/d-logo-sketch.png?test";
const smallLogo = "/images/d-logo-sketch-small.png?test";
@@ -18,6 +22,7 @@ module("Integration | Component | home-logo", function (hooks) {
this.session = getOwner(this).lookup("service:session");
this.session.set("darkModeAvailable", null);
this.session.set("defaultColorSchemeIsDark", null);
+ clearHomeLogoHrefCallback();
});
test("basics", async function (assert) {
@@ -172,4 +177,30 @@ module("Integration | Component | home-logo", function (hooks) {
"uses regular logo on dark scheme if no dark logo"
);
});
+
+ test("the home logo href url defaults to /", async function (assert) {
+ await render();
+
+ const anchorElement = query("#site-logo").closest("a");
+ assert.strictEqual(
+ anchorElement.getAttribute("href"),
+ "/",
+ "home logo href equals /"
+ );
+ });
+
+ test("api.registerHomeLogoHrefCallback can be used to change the logo href url", async function (assert) {
+ withPluginApi("1.32.0", (api) => {
+ api.registerHomeLogoHrefCallback(() => "https://example.com");
+ });
+
+ await render();
+
+ const anchorElement = query("#site-logo").closest("a");
+ assert.strictEqual(
+ anchorElement.getAttribute("href"),
+ "https://example.com",
+ "home logo href equals the one set by the callback"
+ );
+ });
});
diff --git a/app/assets/javascripts/discourse/tests/integration/components/widgets/home-logo-test.gjs b/app/assets/javascripts/discourse/tests/integration/components/widgets/home-logo-test.gjs
index 31458483b88..dd49b693e67 100644
--- a/app/assets/javascripts/discourse/tests/integration/components/widgets/home-logo-test.gjs
+++ b/app/assets/javascripts/discourse/tests/integration/components/widgets/home-logo-test.gjs
@@ -3,8 +3,10 @@ import { getOwner } from "@ember/application";
import { render } from "@ember/test-helpers";
import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget";
+import { withPluginApi } from "discourse/lib/plugin-api";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { count, exists, query } from "discourse/tests/helpers/qunit-helpers";
+import { clearHomeLogoHrefCallback } from "discourse/widgets/home-logo";
const bigLogo = "/images/d-logo-sketch.png?test";
const smallLogo = "/images/d-logo-sketch-small.png?test";
@@ -20,6 +22,7 @@ module("Integration | Component | Widget | home-logo", function (hooks) {
this.session = getOwner(this).lookup("service:session");
this.session.set("darkModeAvailable", null);
this.session.set("defaultColorSchemeIsDark", null);
+ clearHomeLogoHrefCallback();
});
test("basics", async function (assert) {
@@ -201,4 +204,30 @@ module("Integration | Component | Widget | home-logo", function (hooks) {
"uses regular logo on dark scheme if no dark logo"
);
});
+
+ test("the home logo href url defaults to /", async function (assert) {
+ await render();
+
+ const anchorElement = query("#site-logo").closest("a");
+ assert.strictEqual(
+ anchorElement.getAttribute("href"),
+ "/",
+ "home logo href equals /"
+ );
+ });
+
+ test("api.registerHomeLogoHrefCallback can be used to change the logo href url", async function (assert) {
+ withPluginApi("1.32.0", (api) => {
+ api.registerHomeLogoHrefCallback(() => "https://example.com");
+ });
+
+ await render();
+
+ const anchorElement = query("#site-logo").closest("a");
+ assert.strictEqual(
+ anchorElement.getAttribute("href"),
+ "https://example.com",
+ "home logo href equals the one set by the callback"
+ );
+ });
});
diff --git a/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md b/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md
index 307d8a0b86f..bff260560c0 100644
--- a/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md
+++ b/docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md
@@ -7,6 +7,10 @@ in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.32.0] - 2024-05-16
+
+- Adds `registerHomeLogoHrefCallback` which allows to set a callback to change the home logo URL.
+
## [1.31.0] - 2024-04-22
- Adds `addTopicAdminMenuButton` which allows to register a new button in the topic admin menu.