diff --git a/javascripts/discourse/components/custom-header-icon.gjs b/javascripts/discourse/components/custom-header-icon.gjs
new file mode 100644
index 0000000..5338acc
--- /dev/null
+++ b/javascripts/discourse/components/custom-header-icon.gjs
@@ -0,0 +1,72 @@
+import Component from "@glimmer/component";
+import { service } from "@ember/service";
+import { htmlSafe } from "@ember/template";
+import { eq } from "truth-helpers";
+import concatClass from "discourse/helpers/concat-class";
+import icon from "discourse/helpers/d-icon";
+import dasherize from "discourse/helpers/dasherize";
+import { escapeExpression } from "discourse/lib/utilities";
+import isValidUrl from "../lib/isValidUrl";
+
+const MOBILE_VIEWS = new Set(["vmo", "vdm"]);
+const DESKTOP_VIEWS = new Set(["vdo", "vdm"]);
+
+function shouldRenderViewMode(view, isMobile) {
+ return isMobile ? MOBILE_VIEWS.has(view) : DESKTOP_VIEWS.has(view);
+}
+
+export default class CustomHeaderIcon extends Component {
+ static shouldRender(args, context) {
+ return shouldRenderViewMode(args.link.view, context.site.mobileView);
+ }
+
+ @service site;
+
+ get iconClassName() {
+ return `header-icon-${dasherize(this.args.link.title)}`;
+ }
+
+ get isLastLink() {
+ return this.args.link === this.visibleLinks.at(-1);
+ }
+
+ get style() {
+ const numericWidth = Number(this.args.link.width);
+ return Number.isFinite(numericWidth)
+ ? htmlSafe(`width: ${escapeExpression(numericWidth)}px`)
+ : undefined;
+ }
+
+ get visibleLinks() {
+ return this.args.links.filter((link) =>
+ shouldRenderViewMode(link.view, this.site.mobileView)
+ );
+ }
+
+
+
+
+ {{#if (isValidUrl @link.icon)}}
+
+ {{@link.title}}
+ {{else}}
+ {{icon @link.icon label=@link.title}}
+ {{/if}}
+
+
+
+}
diff --git a/javascripts/discourse/initializers/initialize-for-header-icon-links.gjs b/javascripts/discourse/initializers/initialize-for-header-icon-links.gjs
index 90c73bc..3819e9b 100644
--- a/javascripts/discourse/initializers/initialize-for-header-icon-links.gjs
+++ b/javascripts/discourse/initializers/initialize-for-header-icon-links.gjs
@@ -1,78 +1,29 @@
-import { dasherize } from "@ember/string";
-import concatClass from "discourse/helpers/concat-class";
-import icon from "discourse/helpers/d-icon";
+import curryComponent from "ember-curry-component";
+import { getOwnerWithFallback } from "discourse/lib/get-owner";
import { withPluginApi } from "discourse/lib/plugin-api";
-import { escapeExpression } from "discourse/lib/utilities";
-import isValidUrl from "../lib/isValidUrl";
+import CustomHeaderIcon from "../components/custom-header-icon";
-function buildIcon(iconNameOrImageUrl, title) {
- if (isValidUrl(iconNameOrImageUrl)) {
- return
-
- {{title}}
- ;
- } else {
- return {{icon iconNameOrImageUrl label=title}};
- }
-}
+const BEFORE_ICONS = ["chat", "search", "hamburger", "user-menu"];
export default {
name: "header-icon-links",
initialize() {
- withPluginApi("0.8.41", (api) => {
+ withPluginApi((api) => {
try {
- const site = api.container.lookup("service:site");
- let links = settings.header_links;
- if (site.mobileView) {
- links = links.filter(
- (link) => link.view === "vmo" || link.view === "vdm"
- );
- } else {
- links = links.filter(
- (link) => link.view === "vdo" || link.view === "vdm"
- );
- }
-
- links.forEach((link, index) => {
- const iconTemplate = buildIcon(link.icon, link.title);
- const className = `header-icon-${dasherize(link.title)}`;
- const target = link.target === "blank" ? "_blank" : "";
- const rel = link.target ? "noopener" : "";
- const isLastLink =
- index === links.length - 1 ? "last-custom-icon" : "";
-
- let style = "";
- if (link.width) {
- style = `width: ${escapeExpression(link.width)}px`;
- }
+ const links = settings.header_links || [];
- const iconComponent =
-
-
- {{iconTemplate}}
-
-
- ;
-
- const beforeIcon = ["chat", "search", "hamburger", "user-menu"];
-
- api.headerIcons.add(link.title, iconComponent, {
- before: beforeIcon,
- });
+ links.forEach((link) => {
+ api.headerIcons.add(
+ link.title,
+ curryComponent(
+ CustomHeaderIcon,
+ { link, links },
+ getOwnerWithFallback()
+ ),
+ {
+ before: BEFORE_ICONS,
+ }
+ );
});
} catch (error) {
// eslint-disable-next-line no-console