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.