From 2ebc248acfe885ed878ccd78fe4a5e363894d8e1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 21 Aug 2026 09:02:18 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=84=20Sync=202026-08-21=2009:02:18?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- luci-theme-footstrap/Makefile | 40 +--- .../luci-static/resources/fs-appearance.js | 4 +- .../htdocs/luci-static/resources/fs-prefs.js | 2 +- .../etc/uci-defaults/30_luci-theme-footstrap | 180 +++--------------- luci-theme-footstrap/styles/03-palettes.css | 69 +++++++ .../ucode/template/themes/footstrap/header.ut | 4 +- .../themes/footstrap/partials/head.ut | 4 +- 7 files changed, 113 insertions(+), 190 deletions(-) diff --git a/luci-theme-footstrap/Makefile b/luci-theme-footstrap/Makefile index 990200f9..905d63da 100644 --- a/luci-theme-footstrap/Makefile +++ b/luci-theme-footstrap/Makefile @@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap FOOTSTRAP_VERSION?= ifneq ($(FOOTSTRAP_VERSION),) PKG_VERSION:=$(FOOTSTRAP_VERSION) -PKG_RELEASE:=30 +PKG_RELEASE:=31 endif LUCI_TITLE:=Footstrap Theme @@ -93,8 +93,7 @@ define Package/luci-theme-footstrap/postinst # uci-defaults registers the theme; refresh rpcd + drop caches so LuCI sees it without a # reboot. Calling it ourselves is belt-and-braces: OpenWrt's default_postinst also runs # (then deletes) every /etc/uci-defaults/* we ship, so it executes twice per install. It is - # idempotent, and its fresh-vs-upgrade marker is written at the end of the first pass, so - # that pass still sees a fresh install. + # idempotent: the second pass finds the theme already registered and changes nothing. [ -f /etc/uci-defaults/30_luci-theme-footstrap ] && \ sh /etc/uci-defaults/30_luci-theme-footstrap >/dev/null 2>&1 || true rm -f /tmp/luci-indexcache* /tmp/luci-modulecache/* >/dev/null 2>&1 || true @@ -107,33 +106,15 @@ define Package/luci-theme-footstrap/postrm #!/bin/sh # opkg runs the OLD package's postrm with arg "upgrade" during a version upgrade (proven on 24.10: # `prerm upgrade`, then `postrm upgrade`, then the new `postinst configure`) and "remove" on a real -# removal. On upgrade this script MUST change nothing: reverting mediaurlbase to bootstrap, wiping -# the theme registration and deleting the .installed marker here is what flipped every updating -# 24.10 user back to bootstrap — and it defeated uci-defaults' own upgrade guard, because with the -# marker gone uci-defaults treated the run as "fresh", yet postrm had already set mediaurlbase to -# bootstrap, which no "fresh" branch re-activates. apk never runs this on upgrade (it uses the new -# package's pre/post-upgrade), so guarding on the arg is correct for both managers; real removal -# passes "remove" (opkg) or no arg and proceeds below. +# removal. On upgrade this script MUST change nothing: reverting mediaurlbase and wiping the theme +# registration here is what flipped every updating 24.10 user back to bootstrap. apk never runs this +# on upgrade (it uses the new package's pre/post-upgrade), so guarding on the arg is correct for both +# managers; real removal passes "remove" (opkg) or no arg and proceeds below. case "$$1" in *upgrade*) exit 0 ;; esac [ -n "$${IPKG_INSTROOT}" ] || { - # Every theme name this package has ever registered. postrm runs when uci-defaults is - # already deleted, so it cannot source the list: it is duplicated by necessity and - # mirror-pinned so it cannot drift. Only the assignment is byte-identical — the `$$` is - # make's escaping. -# @mirror theme/legacy-names -LEGACY_THEMES="Footstrap FootstrapDark FootstrapLight FootstrapTop FootstrapTopDark FootstrapTopLight FootstrapSidebar FootstrapOnTop" -# @endmirror - for t in $$LEGACY_THEMES; do - uci -q delete "luci.themes.$$t" - done - # The router's DEFAULT layout, set by uci-defaults when migrating an old top-nav install. - # It means nothing to any other theme, and left behind it would silently re-apply the top - # bar on a later reinstall. - uci -q delete luci.main.footstrap_layout - # Don't leave the active theme pointing at the media dir we just removed. The same TWO-part - # check uci-defaults uses: a theme needs its media dir AND its ucode template to render, so - # a one-part check could hand the UI to a half-removed bootstrap — the blank page this - # branch exists to avoid. + uci -q delete luci.themes.Footstrap + # Don't leave the active theme pointing at the media dir we just removed: a theme needs its + # media dir AND its ucode template to render, so both are checked before handing the UI over. case "$$(uci -q get luci.main.mediaurlbase)" in /luci-static/footstrap*) [ -d /www/luci-static/bootstrap ] && \ @@ -141,9 +122,6 @@ LEGACY_THEMES="Footstrap FootstrapDark FootstrapLight FootstrapTop FootstrapTopD uci set luci.main.mediaurlbase=/luci-static/bootstrap ;; esac uci commit luci - # The "installed before" marker uci-defaults writes to tell fresh from upgrade. Removing it - # makes uninstall-then-reinstall count as fresh again. - rm -rf /usr/share/luci-theme-footstrap >/dev/null 2>&1 || true # The admin-uploaded login background (kept out of the package on purpose, so it survives an # upgrade). A real removal is the one time it should go — this branch never runs on upgrade. rm -rf /etc/footstrap >/dev/null 2>&1 || true diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-appearance.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-appearance.js index 4571fde3..bcaa03ef 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-appearance.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-appearance.js @@ -179,7 +179,9 @@ function build() { hicontrast: 'Hi-Contrast', /* names the OTHER package, luci-theme-bootstrap, whose colours this palette is — * so it is a proper noun and stays untranslated, like the two above it */ - bootstrap: 'Bootstrap' + bootstrap: 'Bootstrap', + /* names the OTHER package again, luci-theme-openwrt-2020, whose colourway this is */ + '2020': 'OpenWrt 2020' }, bump(repaint(prefs.applyPalette)), label)), /* Density: how much air the UI uses. Pure token axis — 02-tokens.css multiplies the type and diff --git a/luci-theme-footstrap/htdocs/luci-static/resources/fs-prefs.js b/luci-theme-footstrap/htdocs/luci-static/resources/fs-prefs.js index 439c66d5..42b32e3f 100644 --- a/luci-theme-footstrap/htdocs/luci-static/resources/fs-prefs.js +++ b/luci-theme-footstrap/htdocs/luci-static/resources/fs-prefs.js @@ -350,7 +350,7 @@ function propAxis(key, sdKey, prop, min, max, dfl, fmt) { * * Legacy 'rvht'/'roman'/'github' are migrated to explicit values by head.ut before paint, so they * never reach currentPalette() on a loaded page; the stray fallthrough covers them anyway. */ -const PALETTES = [ 'hicontrast', 'bootstrap' ]; /* the non-default values; 'footstrap' = bare :root */ +const PALETTES = [ 'hicontrast', 'bootstrap', '2020' ]; /* the non-default values; 'footstrap' = bare :root */ function paletteDefault() { const d = sd('palette'); return (PALETTES.indexOf(d) >= 0) ? d : 'footstrap'; diff --git a/luci-theme-footstrap/root/etc/uci-defaults/30_luci-theme-footstrap b/luci-theme-footstrap/root/etc/uci-defaults/30_luci-theme-footstrap index 8fd77a12..0ba30758 100755 --- a/luci-theme-footstrap/root/etc/uci-defaults/30_luci-theme-footstrap +++ b/luci-theme-footstrap/root/etc/uci-defaults/30_luci-theme-footstrap @@ -1,162 +1,36 @@ #!/bin/sh -# FRESH INSTALL OR UPGRADE? A fresh install may activate this theme; an upgrade must NEVER change -# the theme the user is on. The guard used to be `[ "$PKG_UPGRADE" = 1 ]` alone — apk never sets -# that and neither does postinst, so only dev-sync.sh (which exports it by hand) ever took the -# upgrade branch: on a real router the guard was DEAD, and an upgrade that found an empty -# mediaurlbase would activate this theme behind the user's back. The marker file is the state that -# really tells the two apart — it exists iff this script has completed at least once. -# `${PKG_UPGRADE:-}`, not `$PKG_UPGRADE`: the variable is unset on every real path (that is the -# point of the paragraph above), and this file is `sh`-run by the Makefile today but sourced by -# whatever runs uci-defaults tomorrow — under `set -u` a bare expansion aborts the script here, -# the theme is never registered, and the Makefile's `>/dev/null 2>&1` swallows the reason. -FS_MARKER=/usr/share/luci-theme-footstrap/.installed -if [ "${PKG_UPGRADE:-}" = 1 ] || [ -f "$FS_MARKER" ]; then - PKG_UPGRADE=1 -else - PKG_UPGRADE=0 +# Registration, and the three symlinks that expose what the admin uploads. Nothing here migrates a +# router off an older footstrap: OpenWrt expects a sysupgrade rather than a package upgrade, so +# leftovers go with the image, and the cleanup that is worth doing is config rather than files. + +changed=0 + +set_opt() { + uci -q get "luci.$1" >/dev/null 2>&1 && return + uci set "luci.$1=$2" + changed=1 +} + +set_opt themes.Footstrap /luci-static/footstrap + +# A fresh install may pick the theme; an upgrade must never move a router off the theme it is on. +# `changed` is what tells the two apart — on an upgrade the entry is already there — and it carries +# the decision on its own, because apk exports no PKG_UPGRADE. +if [ "${PKG_UPGRADE:-}" != 1 ] && [ "$changed" = 1 ]; then + set_opt main.mediaurlbase /luci-static/footstrap fi -# Every theme name this package has EVER registered — delete them all; the ONE surviving entry -# is re-added below (layout, mode and palette are client-side axes on the Footstrap tab of -# System -> System, so they are not theme entries). The Makefile's postrm must delete the same set (it runs when -# this file is already gone, so it cannot source it) and the two lists had already drifted into a -# different ORDER — which is how one of them would quietly lose a name. Only the assignment is -# pinned: the Makefile writes `$$t` where this writes `$t`. -# @mirror theme/legacy-names -LEGACY_THEMES="Footstrap FootstrapDark FootstrapLight FootstrapTop FootstrapTopDark FootstrapTopLight FootstrapSidebar FootstrapOnTop" -# @endmirror -for t in $LEGACY_THEMES; do - uci -q delete "luci.themes.$t" -done +[ "$changed" = 1 ] && uci commit luci -# WHETHER THE REGISTRATION ACTUALLY LANDED. Every uci WRITE below is checked into this flag, and a -# run that ends with it set refuses to write the marker and exits non-zero — which is what makes the -# failure survivable: OpenWrt's default_postinst deletes a uci-defaults script only when it exits 0 -# (`( . "$i" ) && rm -f "$i"`), so a non-zero run is retried on the next boot. Without this the -# script reported success on a full or read-only overlay, on a locked /etc/config/luci and mid- -# upgrade: the theme was never registered, the script was deleted so nothing retried it, AND the -# marker was written anyway — so the next install took the upgrade branch, which never activates a -# theme. One unwritable file turned into a permanently unthemed router, silently. Deletes are NOT -# counted: `uci -q delete` on an absent entry exits 1 and that is the normal case here. -fail=0 - -# The ONE theme entry: sidebar and top bar are one template morphed by :root[data-layout]. -uci set luci.themes.Footstrap=/luci-static/footstrap || fail=1 - -# Normalise the active theme. Every legacy media path below is now neither registered in -# luci.themes nor on disk, so an install left pointing at one is stranded: the Design page does -# not list it (it cannot be switched away from) and its media dir 404s. They all map onto the one -# surviving path. Non-footstrap themes are left alone; a fresh install defaults to footstrap. -# -# MIGRATION — a router that was on the top-nav theme must STAY on the top bar. The layout lives -# in the browser (localStorage 'fs-layout') and a shell script cannot write that, so carry it -# server-side: footstrap_layout is the router's DEFAULT layout, which head.ut stamps onto -# and the client's own choice then overrides. Set only when the old path says -# top-nav, and only if unset, so a re-run never clobbers a deliberate change. -cur=$(uci -q get luci.main.mediaurlbase) -new=$cur -case "$cur" in - # was on the top-nav theme (incl. its legacy dark/light variants) -> keep the bar - /luci-static/footstrap-top*) - [ -n "$(uci -q get luci.main.footstrap_layout)" ] || \ - uci set luci.main.footstrap_layout=top || fail=1 - new=/luci-static/footstrap ;; - # any other footstrap path (incl. the legacy -dark/-light) -> the built-in default (the bar): - # this branch deliberately sets no footstrap_layout, and absent means top (head.ut) - /luci-static/footstrap*) new=/luci-static/footstrap ;; - "") [ "$PKG_UPGRADE" = 1 ] || new=/luci-static/footstrap ;; -esac - -# Last-resort guard against a blank UI: whatever stays active must be on disk — media dir AND -# ucode template. If a partial upgrade or a hand-edited mediaurlbase points at neither, fall back -# to stock bootstrap (a plain UI beats no UI); skipped if bootstrap is not installed either. -# -# SCOPED TO OUR OWN THEME, and the scoping is the point: `new` defaults to whatever the router -# already had, so without the case this guard judged OTHER PEOPLE'S themes — installing footstrap -# would inspect an active luci-theme-argon and, if its template dir was not named after its media -# basename (or it was mid-upgrade), quietly rewrite mediaurlbase to bootstrap. -case "$new" in - /luci-static/footstrap*) - theme=${new##*/} - if [ ! -d "/www/luci-static/$theme" ] || - [ ! -f "/usr/share/ucode/luci/template/themes/$theme/header.ut" ]; then - [ -d /www/luci-static/bootstrap ] && - [ -f /usr/share/ucode/luci/template/themes/bootstrap/header.ut ] && - new=/luci-static/bootstrap - fi - ;; -esac - -[ "$new" = "$cur" ] || uci set luci.main.mediaurlbase="$new" || fail=1 - -uci commit luci || fail=1 - -# Appearance "Save as default" writes the router-wide axis defaults into /etc/config/footstrap -# through the scoped uci ACL (config 'footstrap' only). The rpcd uci `set` backend the browser -# calls needs the section to ALREADY EXIST, so guarantee it here — the shipped conffile carries it, -# but a router that installed a footstrap predating this feature has no such file. `uci set` refuses -# to CREATE the config file (only the section within one), so touch it first. Idempotent. -[ -f /etc/config/footstrap ] || touch /etc/config/footstrap -if ! uci -q get footstrap.settings >/dev/null 2>&1; then - uci set footstrap.settings=footstrap || fail=1 - uci commit footstrap || fail=1 -fi - -# Login/page background upload (Appearance -> Wallpaper -> File). cgi-upload writes the image to -# /etc/footstrap/login-bg (a fixed, ACL-scoped path — kept in /etc so it survives a package upgrade -# and, via lib/upgrade/keep.d, a sysupgrade). uhttpd serves only /www, so a symlink there exposes it -# at /luci-static/footstrap/bg (uhttpd follows symlinks). Both are recreated on every install/upgrade -# (postinst re-runs this script) and are idempotent; /www is repopulated from firmware on sysupgrade, -# so recreating the symlink here rather than shipping it is what makes it reliable on both filesystems. -mkdir -p /etc/footstrap 2>/dev/null -[ -d /www/luci-static/footstrap ] && ln -sf /etc/footstrap/login-bg /www/luci-static/footstrap/bg 2>/dev/null -# The uploaded PATTERN (Appearance -> Wallpaper -> Pattern) is the same arrangement, with ONE -# difference that is not cosmetic: the exposed name KEEPS THE .svg EXTENSION. uhttpd types a -# response by extension, and an SVG served as application/octet-stream is one no browser will -# paint — as a CSS mask, as a background image or at all. -[ -d /www/luci-static/footstrap ] && ln -sf /etc/footstrap/pattern.svg /www/luci-static/footstrap/pattern.svg 2>/dev/null -# The admin-installed webfonts (/etc/footstrap/fonts, see partials/head.ut) are a whole DIRECTORY -# rather than one file: the faces plus an @font-face sheet beside them. Same arrangement as the two -# images above, and linking a directory has TWO traps, both of which end with `ln` exiting 0 and -# the link sitting one level too deep, at .../fonts/fonts — where no browser looks, so the fonts -# silently do not serve and nothing reports a thing: -# - the link already exists and points at a directory: `ln -sf` follows it. `-n` is the fix. -# - the path is a REAL directory, which every footstrap before 0.12.1 shipped here full of -# woff2 files. `-n` does not help — measured on a 25.12 router: exit 0, link created inside. -# So clear the path first unless it is already the symlink we want. What is being deleted can only -# be ours, and its contents are package files of a version that no longer exists. -# -# DO NOT DELETE THIS AS "an old migration". It is needed for every router whose last footstrap was -# v0.12.0 or older, because that is where the package still SHIPPED files in that directory — and -# there is no floor on how old an installed footstrap can be. Without it `ln -sfn` exits 0 with the -# link planted one level down, the admin's webfonts stop serving, and footstrap.settings.fonts -# points at a 404 with nothing reporting anything. The doodle cleanup below is the opposite case: -# dropping it costs 200 kB of flash and nothing else. +# uhttpd serves /www only, so the admin's own uploads live in /etc — where a sysupgrade keeps them +# (lib/upgrade/keep.d) — and are reached through symlinks. The pattern keeps its .svg name: uhttpd +# types a response by extension, and an SVG sent as octet-stream paints nowhere. +mkdir -p /etc/footstrap if [ -d /www/luci-static/footstrap ]; then - [ ! -e /www/luci-static/footstrap/fonts ] || [ -L /www/luci-static/footstrap/fonts ] || - rm -rf /www/luci-static/footstrap/fonts - ln -sfn /etc/footstrap/fonts /www/luci-static/footstrap/fonts 2>/dev/null + ln -sf /etc/footstrap/login-bg /www/luci-static/footstrap/bg + ln -sf /etc/footstrap/pattern.svg /www/luci-static/footstrap/pattern.svg + ln -sfn /etc/footstrap/fonts /www/luci-static/footstrap/fonts fi -# The two doodle wallpapers earlier versions downloaded into /www on demand. They were never -# package files, so no package manager will ever remove them, and nothing serves them any more — -# the axis they belonged to now paints an admin-uploaded SVG. Left behind they are 200 kB of a -# router's flash held by a feature that no longer exists. -rm -f /www/luci-static/footstrap/cats.svg /www/luci-static/footstrap/dinos.svg 2>/dev/null - -# these caches embed theme paths — drop them so the switch applies on the next request -rm -f /tmp/luci-indexcache* 2>/dev/null -rm -rf /tmp/luci-modulecache 2>/dev/null - -# Write the marker LAST, so a run that dies half-way is still a fresh install next -# time rather than an upgrade. -if [ "$fail" = 1 ]; then - echo "luci-theme-footstrap: a uci write failed — not marking this install as complete;" >&2 - echo " this script stays in /etc/uci-defaults and runs again on the next boot." >&2 - exit 1 -fi - -mkdir -p "$(dirname "$FS_MARKER")" 2>/dev/null -: > "$FS_MARKER" 2>/dev/null exit 0 diff --git a/luci-theme-footstrap/styles/03-palettes.css b/luci-theme-footstrap/styles/03-palettes.css index e3a8702c..d97fb9c9 100644 --- a/luci-theme-footstrap/styles/03-palettes.css +++ b/luci-theme-footstrap/styles/03-palettes.css @@ -478,4 +478,73 @@ --fs-on-warn: #222222; --fs-on-danger: #222222; } + /* ============================================================ + * 2020 — the OpenWrt 2020 theme's colourway + * + * `luci-theme-openwrt-2020` is one colour scheme and no dark mode: the OpenWrt CI cyan + * (#00B5E2) on the deep navy (#002B49), white content, and three semantic colours + * (#5CB85C / #CC8800 / #CC1111). This palette is that identity carried onto footstrap's + * surfaces — proposed in review as the way its look survives the theme itself. + * + * WHAT MOVED, AND WHY EACH ONE HAD TO. The cyan is the whole identity and it is unreadable as + * text on white: #00B5E2 measures 2.09:1, where the export tier every app prints text in wants + * 4.5:1. So the LIGHT mode keeps the hue and darkens it, while the DARK mode — whose surfaces + * are the navy the cyan was designed against — carries it near enough its own value. That + * split is the point of the pair: 2020's own scheme IS the dark one, and the light mode is + * what footstrap needs to show the same identity on a white page. + * + * The three semantic colours get the same treatment for the same reason: on white, 2020's + * green is 2.28:1, its amber 3.42:1 and its red 5.25:1 — only the red clears AA, and it is the + * only one kept close to its original. + * + * The navy is not the chrome here. In 2020 it is the header and the sidebar; a palette cannot + * give the chrome its own colour (that reads --fs-panel), so in dark mode the navy is the + * CANVAS and the chrome sits on it, which is the nearest thing this theme's structure has. */ + :root[data-palette="2020"] { + /* LIGHT — white content, the CI cyan darkened until it can be read on it */ + --fs-bg-base: #ffffff; + --fs-panel-base: #ffffff; + --fs-panel2-base: #eef4f8; + --fs-border-base: #c3d2dd; + /* navy-tinted neutrals rather than grey: the ink belongs to the same scheme as the accent */ + --fs-text: #10202b; + --fs-dim: #2c4150; + --fs-faint: #3d5566; + --fs-select-chevron: url('data:image/svg+xml;utf8,'); + /* #00B5E2 held at hue, taken down until it reads: 5.89:1 on white against its own 2.09:1 */ + --fs-accent-base: #036c92; + --fs-accent-soft: color-mix(in srgb, var(--fs-accent) 10%, transparent); + --fs-track: #e3ebf1; + --fs-good-base: #276e2a; /* #5CB85C darkened; 2.28:1 as text is not a rounding error */ + --fs-warn-base: #8a5a00; /* #CC8800, same move */ + --fs-danger-base: #c1121f; /* #CC1111 is 5.25:1 already — the one that stays where it was */ + /* ink ON the fills above — white clears AA on all four */ + --fs-on-accent: #fff; + --fs-on-good: #fff; + --fs-on-warn: #fff; + --fs-on-danger: #fff; + } + :root[data-palette="2020"][data-darkmode="true"] { + /* DARK — 2020's own scheme: the navy is the canvas and the cyan is nearly untouched */ + --fs-bg-base: #002b49; + --fs-panel-base: #0a3a58; + --fs-panel2-base: #0e4362; + --fs-border-base: #1d5a7d; + --fs-text: #e6f1f7; + --fs-dim: #b8cfdd; + --fs-faint: #9dbccd; + --fs-select-chevron: url('data:image/svg+xml;utf8,'); + /* the CI cyan, one step up so it clears AA on the lightest of the three surfaces too */ + --fs-accent-base: #35c6ea; + --fs-accent-soft: color-mix(in srgb, var(--fs-accent) 15%, transparent); + --fs-track: #123c56; + --fs-good-base: #74cc74; /* #5CB85C lifted for the same reason */ + --fs-warn-base: #eab346; + --fs-danger-base: #ff9d9d; + /* these fills are LIGHT, so the ink is the canvas navy itself */ + --fs-on-accent: #002b49; + --fs-on-good: #002b49; + --fs-on-warn: #002b49; + --fs-on-danger: #002b49; + } } diff --git a/luci-theme-footstrap/ucode/template/themes/footstrap/header.ut b/luci-theme-footstrap/ucode/template/themes/footstrap/header.ut index 1b34b90c..1fd7e398 100644 --- a/luci-theme-footstrap/ucode/template/themes/footstrap/header.ut +++ b/luci-theme-footstrap/ucode/template/themes/footstrap/header.ut @@ -31,7 +31,7 @@ /* The ROUTER's saved Appearance defaults (Appearance -> Save as default, in /etc/config/footstrap): head.ut stamps them before paint and the client's own localStorage overrides every one — the browser choice always wins. Layout falls back to the legacy migration seed - luci.main.footstrap_layout=top, which uci-defaults sets for a router upgraded from the old + luci.main.footstrap_layout=top, which an admin may set to give the router a default top-nav theme (a shell script cannot write localStorage). Absent = the built-in defaults. `uci` and `config` come from the render scope, which dispatcher.uc builds per request: `uci` is @@ -77,7 +77,7 @@ for (let k in FS_AXES) fs_defaults[k] = fsd[k] || ''; /* the one value with a fallback of its own: the legacy migration seed - luci.main.footstrap_layout=top, which uci-defaults sets for a router upgraded from the old + luci.main.footstrap_layout=top, which an admin may set to give the router a default top-nav theme (a shell script cannot write localStorage). `config.main?.` and not `config.main.`: ucode raises a hard reference error on a property read diff --git a/luci-theme-footstrap/ucode/template/themes/footstrap/partials/head.ut b/luci-theme-footstrap/ucode/template/themes/footstrap/partials/head.ut index b0b03602..be58db91 100644 --- a/luci-theme-footstrap/ucode/template/themes/footstrap/partials/head.ut +++ b/luci-theme-footstrap/ucode/template/themes/footstrap/partials/head.ut @@ -20,7 +20,7 @@ it. */ let _sd_lay = index([ 'sidebar', 'top' ], fs_defaults.layout) >= 0 ? fs_defaults.layout : ''; let _sd_dark = index([ 'auto', 'light', 'dark' ], fs_defaults.darkmode) >= 0 ? fs_defaults.darkmode : ''; - let _sd_pal = index([ 'footstrap', 'hicontrast', 'bootstrap' ], fs_defaults.palette) >= 0 ? fs_defaults.palette : ''; + let _sd_pal = index([ 'footstrap', 'hicontrast', 'bootstrap', '2020' ], fs_defaults.palette) >= 0 ? fs_defaults.palette : ''; let _sd_wall = index([ 'off', 'pattern', 'file' ], fs_defaults.wallpaper) >= 0 ? fs_defaults.wallpaper : ''; let _sd_pink = index([ 'theme', 'original' ], fs_defaults.pattern_ink) >= 0 ? fs_defaults.pattern_ink : ''; let _sd_ac = index([ 'on', 'off' ], fs_defaults.autocollapse) >= 0 ? fs_defaults.autocollapse : ''; @@ -265,7 +265,7 @@ against — a name in one and not the other paints here and is taken away by the first live change. */ if (p === null) p = sd.palette || null; - if (p === 'hicontrast' || p === 'bootstrap') root.setAttribute('data-palette', p); + if (p === 'hicontrast' || p === 'bootstrap' || p === '2020') root.setAttribute('data-palette', p); else root.removeAttribute('data-palette'); /* Wallpaper: off | pattern (the uploaded SVG, tiled and recoloured) | file (the