From 4d5de9f01d956b7d686660a080daa7090e516e15 Mon Sep 17 00:00:00 2001
From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com>
Date: Fri, 17 Oct 2025 11:43:52 -0400
Subject: [PATCH] Sync iframe forms with theme overrides
---
.../iframe_forms/iframe-application-form.html | 194 +-----------------
.../iframe_forms/iframe-bug-fix-form.html | 2 +-
.../iframe-content-appeals-form.html | 2 +-
.../iframe_forms/iframe-feedback-form.html | 2 +-
.../iframe_forms/iframe-request-form.html | 1 +
components/iframe_forms/theme-sync.js | 192 +++++++++++++++++
6 files changed, 197 insertions(+), 196 deletions(-)
create mode 100644 components/iframe_forms/theme-sync.js
diff --git a/components/iframe_forms/iframe-application-form.html b/components/iframe_forms/iframe-application-form.html
index 4959ac02..065516c7 100644
--- a/components/iframe_forms/iframe-application-form.html
+++ b/components/iframe_forms/iframe-application-form.html
@@ -3,199 +3,7 @@
bitvid Whitelist Application Form
-
+
diff --git a/components/iframe_forms/iframe-bug-fix-form.html b/components/iframe_forms/iframe-bug-fix-form.html
index 29afea88..5dc83a62 100644
--- a/components/iframe_forms/iframe-bug-fix-form.html
+++ b/components/iframe_forms/iframe-bug-fix-form.html
@@ -3,8 +3,8 @@
bitvid Bug Report Form
+
-
diff --git a/components/iframe_forms/iframe-content-appeals-form.html b/components/iframe_forms/iframe-content-appeals-form.html
index c437c7f3..179dd9a9 100644
--- a/components/iframe_forms/iframe-content-appeals-form.html
+++ b/components/iframe_forms/iframe-content-appeals-form.html
@@ -3,8 +3,8 @@
bitvid Content Appeals Form
+
-
diff --git a/components/iframe_forms/iframe-feedback-form.html b/components/iframe_forms/iframe-feedback-form.html
index 38ae6ccd..3de30227 100644
--- a/components/iframe_forms/iframe-feedback-form.html
+++ b/components/iframe_forms/iframe-feedback-form.html
@@ -3,8 +3,8 @@
bitvid General Feedback Form
+
-
diff --git a/components/iframe_forms/iframe-request-form.html b/components/iframe_forms/iframe-request-form.html
index 467ccd8f..754a9a84 100644
--- a/components/iframe_forms/iframe-request-form.html
+++ b/components/iframe_forms/iframe-request-form.html
@@ -3,6 +3,7 @@
bitvid Feature Request Form
+
diff --git a/components/iframe_forms/theme-sync.js b/components/iframe_forms/theme-sync.js
new file mode 100644
index 00000000..e9ca696c
--- /dev/null
+++ b/components/iframe_forms/theme-sync.js
@@ -0,0 +1,192 @@
+import { THEME_ACCENT_OVERRIDES } from "../../config/instance-config.js";
+
+(() => {
+ const VALID_THEMES = new Set(["light", "dark"]);
+ const STORAGE_KEY = "bitvid:theme";
+ const FALLBACK_THEME = "dark";
+ const ACCENT_CSS_VARIABLES = Object.freeze({
+ accent: "--color-accent",
+ accentStrong: "--color-accent-strong",
+ accentPressed: "--color-accent-pressed",
+ });
+ const ACCENT_TOKENS = Object.keys(ACCENT_CSS_VARIABLES);
+ const { documentElement: root } = document;
+
+ if (!(root instanceof HTMLElement)) {
+ return;
+ }
+
+ const sanitizeConfigOverrides = (overrides) => {
+ if (!overrides || typeof overrides !== "object") {
+ return {};
+ }
+
+ const sanitized = {};
+
+ Object.entries(overrides).forEach(([theme, themeOverrides]) => {
+ if (!VALID_THEMES.has(theme) || typeof themeOverrides !== "object") {
+ return;
+ }
+
+ const normalized = {};
+
+ ACCENT_TOKENS.forEach((token) => {
+ const value = themeOverrides[token];
+ if (typeof value === "string") {
+ const trimmed = value.trim();
+ if (trimmed !== "") {
+ normalized[token] = trimmed;
+ }
+ }
+ });
+
+ if (Object.keys(normalized).length > 0) {
+ sanitized[theme] = normalized;
+ }
+ });
+
+ return sanitized;
+ };
+
+ const CONFIG_ACCENT_OVERRIDES = sanitizeConfigOverrides(
+ THEME_ACCENT_OVERRIDES
+ );
+
+ const normalizeTheme = (value) => {
+ if (typeof value !== "string") {
+ return null;
+ }
+ const normalized = value.trim().toLowerCase();
+ if (normalized === "" || normalized === "default") {
+ return FALLBACK_THEME;
+ }
+ return VALID_THEMES.has(normalized) ? normalized : null;
+ };
+
+ const getParentRoot = () => {
+ try {
+ if (window.parent && window.parent !== window) {
+ const parentDocument = window.parent.document;
+ const parentRoot = parentDocument?.documentElement;
+ return parentRoot instanceof HTMLElement ? parentRoot : null;
+ }
+ } catch (error) {
+ return null;
+ }
+ return null;
+ };
+
+ const readParentTheme = () => {
+ const parentRoot = getParentRoot();
+ if (!parentRoot) {
+ return null;
+ }
+ return normalizeTheme(parentRoot.dataset?.theme);
+ };
+
+ const readStoredTheme = () => {
+ try {
+ return normalizeTheme(window.localStorage.getItem(STORAGE_KEY));
+ } catch (error) {
+ return null;
+ }
+ };
+
+ const applyTheme = (theme) => {
+ if (theme && VALID_THEMES.has(theme)) {
+ root.dataset.theme = theme;
+ } else {
+ root.removeAttribute("data-theme");
+ }
+ };
+
+ const readParentAccentOverrides = () => {
+ const parentRoot = getParentRoot();
+ if (!parentRoot) {
+ return null;
+ }
+
+ const overrides = {};
+ let hasOverride = false;
+
+ Object.values(ACCENT_CSS_VARIABLES).forEach((cssVariable) => {
+ try {
+ const value = parentRoot.style.getPropertyValue(cssVariable);
+ if (typeof value === "string") {
+ const trimmed = value.trim();
+ if (trimmed !== "") {
+ overrides[cssVariable] = trimmed;
+ hasOverride = true;
+ }
+ }
+ } catch (error) {
+ /* noop */
+ }
+ });
+
+ return hasOverride ? overrides : null;
+ };
+
+ const applyAccentOverrides = (theme) => {
+ const parentOverrides = readParentAccentOverrides();
+ const configOverrides = CONFIG_ACCENT_OVERRIDES[theme] || null;
+
+ ACCENT_TOKENS.forEach((token) => {
+ const cssVariable = ACCENT_CSS_VARIABLES[token];
+ const parentValue = parentOverrides?.[cssVariable];
+ const configValue = configOverrides?.[token];
+ const nextValue = parentValue || configValue || "";
+
+ if (typeof nextValue === "string" && nextValue.trim() !== "") {
+ root.style.setProperty(cssVariable, nextValue.trim());
+ } else {
+ root.style.removeProperty(cssVariable);
+ }
+ });
+ };
+
+ const syncTheme = () => {
+ const resolvedTheme =
+ readParentTheme() ?? readStoredTheme() ?? FALLBACK_THEME;
+ applyTheme(resolvedTheme);
+ applyAccentOverrides(resolvedTheme);
+ };
+
+ syncTheme();
+
+ const parentRoot = getParentRoot();
+ let observer;
+
+ if (parentRoot && typeof MutationObserver !== "undefined") {
+ observer = new MutationObserver(syncTheme);
+ observer.observe(parentRoot, {
+ attributes: true,
+ attributeFilter: ["data-theme", "style"],
+ });
+ }
+
+ window.addEventListener("storage", (event) => {
+ if (event?.key === STORAGE_KEY) {
+ syncTheme();
+ }
+ });
+
+ window.addEventListener(
+ "pageshow",
+ () => {
+ syncTheme();
+ },
+ { once: true }
+ );
+
+ window.addEventListener(
+ "beforeunload",
+ () => {
+ if (observer) {
+ observer.disconnect();
+ }
+ },
+ { once: true }
+ );
+})();
+