/* Copyright 2026 Lotus Guild SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ /** * Shared helpers for the Lotus fork's widget extensions. * * Everything here is **opt-in**: each feature is gated behind a `lotus*` URL * param that the Lotus host (cinny) appends to the widget iframe URL. With no * param present, none of this code changes Element Call's behaviour — which * keeps the fork a minimal, additive, easy-to-rebase diff over upstream. */ import { logger } from "matrix-js-sdk/lib/logger"; import { widget } from "../widget"; import type { LotusWidgetActions } from "./lotusActions"; export { LotusWidgetActions } from "./lotusActions"; /** * Read a URL param from either the query string or the hash fragment (Element * Call passes widget params via both depending on host), without depending on * EC's own `getUrlParams` parser (keeps the rebase surface small). * * [lotus #33] Re-parsed from `window.location` on every call instead of being * cached at first use: parsing is cheap, and caching risked returning a * stale value if `location.hash`/`search` are ever rewritten after first * read (e.g. during in-iframe navigation). */ export function lotusParam(name: string): string | null { // Match EC's own ParamParser precedence: the hash fragment wins over the // query string. So seed from the fragment first, then fill gaps from query. const hash = window.location.hash.replace(/^#\/?/, ""); const hashQuery = hash.includes("?") ? hash.slice(hash.indexOf("?") + 1) : ""; const params = new URLSearchParams(hashQuery); for (const [k, v] of new URLSearchParams(window.location.search)) { if (!params.has(k)) params.append(k, v); } return params.get(name); } /** Whether a boolean-ish Lotus feature flag is enabled. */ export function lotusFlag(name: string): boolean { const v = lotusParam(name); return v === "1" || v === "true"; } /** * Send a fromWidget message to the Lotus host, swallowing the inevitable * rejection when the host hasn't (yet) registered a handler for it. Returns * true if the widget transport was available to attempt the send. */ export function lotusSendToHost( action: LotusWidgetActions, data: unknown, ): boolean { const api = widget?.api; if (!api) return false; void api.transport .send(action, data as Record) .catch((e) => { logger.debug(`[lotus] host did not ack ${action}`, e); }); return true; }