Add a .env option to skip the load splash

This commit is contained in:
MrAlders0n
2026-07-13 11:50:57 -04:00
parent 8344f3c8d2
commit 04f1757daa
8 changed files with 35 additions and 2 deletions
+1
View File
@@ -10,6 +10,7 @@ ENV VITE_MAP_ZOOM=__VITE_MAP_ZOOM__
ENV VITE_DISABLED_TABS=__VITE_DISABLED_TABS__
ENV VITE_ENABLED_THEMES=__VITE_ENABLED_THEMES__
ENV VITE_APP_NAME=__VITE_APP_NAME__
ENV VITE_SKIP_SPLASH=__VITE_SKIP_SPLASH__
RUN npm run build
FROM caddy:2-alpine
+2
View File
@@ -9,6 +9,7 @@ MAP_ZOOM="${VITE_MAP_ZOOM:-}"
# Optional branding/customization — empty means default behaviour (all tabs, hidden themes hidden).
DISABLED_TABS="${VITE_DISABLED_TABS:-}"
ENABLED_THEMES="${VITE_ENABLED_THEMES:-}"
SKIP_SPLASH="${VITE_SKIP_SPLASH:-}"
# APP_NAME is substituted verbatim; avoid '&' and '|' (sed replacement metachar and delimiter).
APP_NAME="${VITE_APP_NAME:-BEACON}"
@@ -20,6 +21,7 @@ find /srv -name '*.js' -exec sed -i \
-e "s|__VITE_DISABLED_TABS__|${DISABLED_TABS}|g" \
-e "s|__VITE_ENABLED_THEMES__|${ENABLED_THEMES}|g" \
-e "s|__VITE_APP_NAME__|${APP_NAME}|g" \
-e "s|__VITE_SKIP_SPLASH__|${SKIP_SPLASH}|g" \
{} +
exec "$@"
+3
View File
@@ -22,3 +22,6 @@
# Custom top-left app name (default: BEACON). Avoid the & and | characters.
# VITE_APP_NAME=Beacon - MeshMapper
# Skip the once-per-session load splash. Unset = shown.
# VITE_SKIP_SPLASH=true
+3
View File
@@ -22,3 +22,6 @@ VITE_ENABLED_THEMES=
# Custom app name shown in the top-left wordmark. Default: BEACON. Avoid the & and | characters.
VITE_APP_NAME=
# Skip the once-per-session load splash. Set to true to skip; leave empty to show it.
VITE_SKIP_SPLASH=
+2
View File
@@ -24,4 +24,6 @@ services:
- VITE_DISABLED_TABS=${VITE_DISABLED_TABS:-}
- VITE_ENABLED_THEMES=${VITE_ENABLED_THEMES:-}
- VITE_APP_NAME=${VITE_APP_NAME:-BEACON}
# Skip the once-per-session load splash; unset = shown
- VITE_SKIP_SPLASH=${VITE_SKIP_SPLASH:-}
restart: unless-stopped
+4 -1
View File
@@ -1,11 +1,13 @@
// Page-load splash: pulsing BEACON wordmark over a themed backdrop, shown once
// per browser session, then faded out and removed from the DOM.
// per browser session, then faded out and removed from the DOM. Set VITE_SKIP_SPLASH
// to skip it entirely for a deployment.
//
// To remove the splash entirely: delete this file and remove its import +
// <SplashScreen /> line from src/App.tsx. Nothing else references it.
import { useState, useEffect } from "react";
import { BeaconLogo } from "./BeaconLogo";
import { SKIP_SPLASH } from "../lib/constants";
const SPLASH_KEY = "beacon-splash-shown";
const VISIBLE_MS = 2000;
@@ -15,6 +17,7 @@ export function SplashScreen() {
// Synchronous gate: decided before first paint so StrictMode's double-mount
// (and any same-session reload) never re-shows it.
const [render, setRender] = useState(() => {
if (SKIP_SPLASH) return false;
try {
if (typeof sessionStorage === "undefined") return false;
return sessionStorage.getItem(SPLASH_KEY) !== "1";
+9
View File
@@ -31,6 +31,12 @@ export function filterEnabledTabs(tabs: readonly string[], disabledRaw: string |
return tabs.filter((t) => !disabled.has(t.toLowerCase()));
}
// Truthy env flag: "1"/"true"/"yes"/"on" (case-insensitive). Anything else — empty, unset, or an
// un-substituted sentinel — is false, so the gated behaviour only turns on when explicitly asked for.
export function parseEnvBool(raw: string | undefined): boolean {
return ["1", "true", "yes", "on"].includes((raw ?? "").trim().toLowerCase());
}
// The themes offered in the picker. When VITE_ENABLED_THEMES lists ids it's an EXCLUSIVE allowlist —
// only those show (e.g. a branded deployment that wants just its own themes). Otherwise every
// non-hidden theme shows and `hidden` ones (like the MeshMapper pair) stay out.
@@ -55,3 +61,6 @@ export const ENABLED_THEME_IDS = new Set(
// "||" (not "??") so an empty sed substitution falls back to the default too.
export const APP_NAME = import.meta.env.VITE_APP_NAME || "BEACON";
export const GITHUB_URL = "https://github.com/MeshCore-Beacon";
// Skip the once-per-session load splash entirely (e.g. an embedded/branded deployment).
export const SKIP_SPLASH = parseEnvBool(import.meta.env.VITE_SKIP_SPLASH);
+11 -1
View File
@@ -1,5 +1,5 @@
import { describe, it, expect } from "vitest";
import { TABS, parseEnvList, filterEnabledTabs, selectableThemes } from "../../src/lib/constants";
import { TABS, parseEnvList, filterEnabledTabs, parseEnvBool, selectableThemes } from "../../src/lib/constants";
describe("parseEnvList", () => {
it("returns [] for undefined or empty", () => {
@@ -37,6 +37,16 @@ describe("filterEnabledTabs", () => {
});
});
describe("parseEnvBool", () => {
it("is true for common truthy strings (case-insensitive)", () => {
for (const v of ["1", "true", "TRUE", "Yes", "on", " on "]) expect(parseEnvBool(v)).toBe(true);
});
it("is false for unset, empty, sentinel, or other values", () => {
for (const v of [undefined, "", "0", "false", "no", "__VITE_SKIP_SPLASH__"]) expect(parseEnvBool(v)).toBe(false);
});
});
describe("selectableThemes", () => {
const THEMES = [
{ id: "neutral-blue", name: "Neutral Blue" },