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) + ); + } + + +} 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 ; - } else { - return ; - } -} +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 = ; - - 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