DEV: Add the registerHomeLogoHrefCallback plugin API (#27056)

The `registerHomeLogoHrefCallback` API allows setting a callback function that specifies the URL used in the home logo.
This commit is contained in:
Sérgio Saquetim 2024-05-17 13:06:47 -03:00 committed by GitHub
parent b908abe35a
commit 501781c2e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 146 additions and 3 deletions

View File

@ -11,14 +11,31 @@ import icon from "discourse-common/helpers/d-icon";
import getURL from "discourse-common/lib/get-url"; import getURL from "discourse-common/lib/get-url";
import Logo from "./logo"; import Logo from "./logo";
let hrefCallback;
export function registerHomeLogoHrefCallback(callback) {
hrefCallback = callback;
}
export function clearHomeLogoHrefCallback() {
hrefCallback = null;
}
export default class HomeLogo extends Component { export default class HomeLogo extends Component {
@service session; @service session;
@service site; @service site;
@service siteSettings; @service siteSettings;
href = getURL("/");
darkModeAvailable = this.session.darkModeAvailable; darkModeAvailable = this.session.darkModeAvailable;
get href() {
if (hrefCallback) {
return hrefCallback();
}
return getURL("/");
}
get showMobileLogo() { get showMobileLogo() {
return this.site.mobileView && this.logoResolver("mobile_logo").length > 0; return this.site.mobileView && this.logoResolver("mobile_logo").length > 0;
} }

View File

@ -13,6 +13,7 @@ import { addCategorySortCriteria } from "discourse/components/edit-category-sett
import { forceDropdownForMenuPanels as glimmerForceDropdownForMenuPanels } from "discourse/components/glimmer-site-header"; import { forceDropdownForMenuPanels as glimmerForceDropdownForMenuPanels } from "discourse/components/glimmer-site-header";
import { addGlobalNotice } from "discourse/components/global-notice"; import { addGlobalNotice } from "discourse/components/global-notice";
import { headerButtonsDAG } from "discourse/components/header"; import { headerButtonsDAG } from "discourse/components/header";
import { registerHomeLogoHrefCallback } from "discourse/components/header/home-logo";
import { headerIconsDAG } from "discourse/components/header/icons"; import { headerIconsDAG } from "discourse/components/header/icons";
import { _addBulkButton } from "discourse/components/modal/topic-bulk-actions"; import { _addBulkButton } from "discourse/components/modal/topic-bulk-actions";
import MountWidget, { import MountWidget, {
@ -108,6 +109,7 @@ import { setNewCategoryDefaultColors } from "discourse/routes/new-category";
import { setNotificationsLimit } from "discourse/routes/user-notifications"; import { setNotificationsLimit } from "discourse/routes/user-notifications";
import { addComposerSaveErrorCallback } from "discourse/services/composer"; import { addComposerSaveErrorCallback } from "discourse/services/composer";
import { attachAdditionalPanel } from "discourse/widgets/header"; import { attachAdditionalPanel } from "discourse/widgets/header";
import { registerHomeLogoHrefCallback as registerHomeLogoHrefCallbackOnWidget } from "discourse/widgets/home-logo";
import { addPostClassesCallback } from "discourse/widgets/post"; import { addPostClassesCallback } from "discourse/widgets/post";
import { addDecorator } from "discourse/widgets/post-cooked"; import { addDecorator } from "discourse/widgets/post-cooked";
import { import {
@ -150,7 +152,7 @@ import { modifySelectKit } from "select-kit/mixins/plugin-api";
// docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md whenever you change the version // docs/CHANGELOG-JAVASCRIPT-PLUGIN-API.md whenever you change the version
// using the format described at https://keepachangelog.com/en/1.0.0/. // 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 = [ const DEPRECATED_HEADER_WIDGETS = [
"header", "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". * Adds an item to the quick access profile panel, before "Log Out".
* *

View File

@ -7,6 +7,16 @@ import { createWidget } from "discourse/widgets/widget";
import getURL from "discourse-common/lib/get-url"; import getURL from "discourse-common/lib/get-url";
import { iconNode } from "discourse-common/lib/icon-library"; 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", { export default createWidget("home-logo", {
services: ["session"], services: ["session"],
tagName: "div.title", tagName: "div.title",
@ -23,6 +33,11 @@ export default createWidget("home-logo", {
href() { href() {
const href = this.settings.href; const href = this.settings.href;
if (hrefCallback) {
return hrefCallback();
}
return typeof href === "function" ? href() : href; return typeof href === "function" ? href() : href;
}, },

View File

@ -1,8 +1,12 @@
import { getOwner } from "@ember/application"; import { getOwner } from "@ember/application";
import { render } from "@ember/test-helpers"; import { render } from "@ember/test-helpers";
import { module, test } from "qunit"; 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 { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { query } from "discourse/tests/helpers/qunit-helpers";
const bigLogo = "/images/d-logo-sketch.png?test"; const bigLogo = "/images/d-logo-sketch.png?test";
const smallLogo = "/images/d-logo-sketch-small.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 = getOwner(this).lookup("service:session");
this.session.set("darkModeAvailable", null); this.session.set("darkModeAvailable", null);
this.session.set("defaultColorSchemeIsDark", null); this.session.set("defaultColorSchemeIsDark", null);
clearHomeLogoHrefCallback();
}); });
test("basics", async function (assert) { 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" "uses regular logo on dark scheme if no dark logo"
); );
}); });
test("the home logo href url defaults to /", async function (assert) {
await render(<template><HomeLogo @minimized={{false}} /></template>);
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(<template><HomeLogo @minimized={{false}} /></template>);
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"
);
});
}); });

View File

@ -3,8 +3,10 @@ import { getOwner } from "@ember/application";
import { render } from "@ember/test-helpers"; import { render } from "@ember/test-helpers";
import { module, test } from "qunit"; import { module, test } from "qunit";
import MountWidget from "discourse/components/mount-widget"; import MountWidget from "discourse/components/mount-widget";
import { withPluginApi } from "discourse/lib/plugin-api";
import { setupRenderingTest } from "discourse/tests/helpers/component-test"; import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import { count, exists, query } from "discourse/tests/helpers/qunit-helpers"; 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 bigLogo = "/images/d-logo-sketch.png?test";
const smallLogo = "/images/d-logo-sketch-small.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 = getOwner(this).lookup("service:session");
this.session.set("darkModeAvailable", null); this.session.set("darkModeAvailable", null);
this.session.set("defaultColorSchemeIsDark", null); this.session.set("defaultColorSchemeIsDark", null);
clearHomeLogoHrefCallback();
}); });
test("basics", async function (assert) { 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" "uses regular logo on dark scheme if no dark logo"
); );
}); });
test("the home logo href url defaults to /", async function (assert) {
await render(<template><MountWidget @widget="home-logo" /></template>);
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(<template><MountWidget @widget="home-logo" /></template>);
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"
);
});
}); });

View File

@ -7,6 +7,10 @@ in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 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). 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 ## [1.31.0] - 2024-04-22
- Adds `addTopicAdminMenuButton` which allows to register a new button in the topic admin menu. - Adds `addTopicAdminMenuButton` which allows to register a new button in the topic admin menu.