mirror of
https://github.com/MeshCore-Beacon/beacon-web.git
synced 2026-09-16 18:32:36 +00:00
Add a .env option to skip the load splash
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 "$@"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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" },
|
||||
|
||||
Reference in New Issue
Block a user