diff --git a/doc/lucky1.png b/doc/lucky1.png new file mode 100644 index 00000000..a5b41b6e Binary files /dev/null and b/doc/lucky1.png differ diff --git a/doc/lucky2.png b/doc/lucky2.png new file mode 100644 index 00000000..ba4c026f Binary files /dev/null and b/doc/lucky2.png differ diff --git a/doc/lucky3.png b/doc/lucky3.png new file mode 100644 index 00000000..6fa7982f Binary files /dev/null and b/doc/lucky3.png differ diff --git a/doc/taskplan1.png b/doc/taskplan1.png deleted file mode 100644 index 1f8db7be..00000000 Binary files a/doc/taskplan1.png and /dev/null differ diff --git a/doc/taskplan2.png b/doc/taskplan2.png deleted file mode 100644 index edb45d6d..00000000 Binary files a/doc/taskplan2.png and /dev/null differ diff --git a/doc/taskplan3.png b/doc/taskplan3.png deleted file mode 100644 index d4794702..00000000 Binary files a/doc/taskplan3.png and /dev/null differ diff --git a/doc/view.png b/doc/view.png deleted file mode 100644 index 169e112f..00000000 Binary files a/doc/view.png and /dev/null differ diff --git a/doc/view2.png b/doc/view2.png deleted file mode 100644 index 9058c632..00000000 Binary files a/doc/view2.png and /dev/null differ diff --git a/luci-app-daede/Makefile b/luci-app-daede/Makefile index 909f48cd..abbf2cda 100644 --- a/luci-app-daede/Makefile +++ b/luci-app-daede/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-daede PKG_VERSION:=1.15 -PKG_RELEASE:=9 +PKG_RELEASE:=11 PKG_MAINTAINER:=kenzok8 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) diff --git a/luci-app-daede/htdocs/luci-static/resources/view/daede/updates.js b/luci-app-daede/htdocs/luci-static/resources/view/daede/updates.js index 4ece1ae5..f4df1c52 100644 --- a/luci-app-daede/htdocs/luci-static/resources/view/daede/updates.js +++ b/luci-app-daede/htdocs/luci-static/resources/view/daede/updates.js @@ -35,6 +35,8 @@ const HEALTH_PATHS = { btfDetached: '/usr/lib/debug/boot/vmlinux', netns: '/run/netns/daens' }; +const INDEX_STATUS_PATH = '/tmp/luci-app-daede.idx.status'; +let indexStartFailed = false; const CSS = [ '.dd-up-wrap{padding:6px 0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC",sans-serif}', @@ -122,10 +124,19 @@ function probeFile(path) { function probePkg(pkg) { return fs.exec('/usr/share/luci-app-daede/pkg-info.sh', [pkg]).then(function(res) { - const out = (res.stdout || '').trim().split('\t'); - return { installed: out[0] || '', latest: out[1] || '' }; + if (res.code !== 0) throw new Error('package probe failed'); + const out = (res.stdout || '').replace(/[\r\n]+$/, '').split('\t'); + return { installed: out[0] || '', latest: out[1] || '', state: out[2] || 'absent' }; }).catch(function() { - return { installed: '', latest: '' }; + return { installed: '', latest: '', state: 'error' }; + }); +} + +function probeIndex() { + if (indexStartFailed) return Promise.resolve('failed'); + return L.resolveDefault(fs.read_direct(INDEX_STATUS_PATH, 'text'), '').then(function(out) { + const state = String(out).trim(); + return state === 'success' || state === 'failed' ? state : 'running'; }); } @@ -137,14 +148,16 @@ function stamp() { return view.extend({ load: function() { - // background apk update so new versions show on next poll - fs.exec('/usr/share/luci-app-daede/refresh-index.sh', []).catch(function() {}); + // The script starts a background refresh and returns after writing its state. return Promise.all([ + fs.exec('/usr/share/luci-app-daede/refresh-index.sh', []).then(function(res) { + indexStartFailed = res.code !== 0; + }).catch(function() { indexStartFailed = true; }), backend.detectBackend(), uci.load('daed').catch(function() {}), uci.load('daede').catch(function() {}) ]).then(function(r) { - return r[0]; + return r[1]; }); }, @@ -342,6 +355,7 @@ return view.extend({ probes.push(probePkg(pkg)); }); probes.push(probePkg('luci-app-daede')); + probes.push(probeIndex()); if (ctx.backend.useNetns) probes.push(probeFile(HEALTH_PATHS.netns)); @@ -354,7 +368,8 @@ return view.extend({ coreInfo[pkg] = r[pkgOffset + i]; }); const luci = r[pkgOffset + corePkgs.length]; - const ns = r[pkgOffset + corePkgs.length + 1]; + const indexState = r[pkgOffset + corePkgs.length + 1]; + const ns = r[pkgOffset + corePkgs.length + 2]; // data rows while (dataBody.firstChild) dataBody.removeChild(dataBody.firstChild); @@ -391,26 +406,36 @@ return view.extend({ // a stale compile-jell build) must never be offered as an upgrade. const cmp = (entry.r.installed && entry.r.latest) ? cmpVer(entry.r.latest, entry.r.installed) : null; - const updatable = cmp !== null && cmp > 0; + const updatable = indexState === 'success' && cmp !== null && cmp > 0; let meta; if (!entry.r.installed) { - meta = _('not installed via package manager'); + meta = entry.r.state === 'manual' ? _('not installed via package manager') + : entry.r.state === 'foreign' ? _('unsupported package version') + : entry.r.state === 'error' ? _('package status unavailable') : _('Not installed'); btn.disabled = true; btn.textContent = _('Unavailable'); + } else if (indexState === 'failed') { + meta = _('installed') + ': ' + entry.r.installed + ' · ' + _('package index refresh failed'); + btn.disabled = true; + } else if (indexState !== 'success') { + meta = _('installed') + ': ' + entry.r.installed + ' · ' + _('refreshing package indexes'); + btn.disabled = true; } else if (!entry.r.latest) { - // latest unknown (registry unreachable) - nothing to upgrade to - meta = _('installed') + ': ' + entry.r.installed + ' · ' + _('latest version unknown'); + meta = _('installed') + ': ' + entry.r.installed + ' · ' + _('package not found in configured feeds'); btn.disabled = true; } else if (updatable) { meta = _('installed') + ': ' + entry.r.installed + ' → ' + _('latest') + ': ' + entry.r.latest; + } else if (cmp < 0) { + meta = _('installed') + ': ' + entry.r.installed + ' · ' + _('feed version older: %s').format(entry.r.latest); + btn.disabled = true; } else { - // installed >= feed: already up to date (feed may even be older) meta = _('installed') + ': ' + entry.r.installed + ' · ' + _('up to date'); btn.disabled = true; } + const uncertain = entry.r.installed && (indexState !== 'success' || !entry.r.latest || cmp < 0); pkgBody.appendChild(mkRow( - updatable ? '↑' : (entry.r.installed ? '✓' : '✗'), - updatable ? 'dd-up-new' : (entry.r.installed ? 'dd-up-ok' : 'dd-up-err'), + updatable ? '↑' : (uncertain ? '⚠' : (entry.r.installed ? '✓' : '✗')), + updatable ? 'dd-up-new' : (uncertain ? 'dd-up-warn' : (entry.r.installed ? 'dd-up-ok' : 'dd-up-err')), entry.name, meta, btn diff --git a/luci-app-daede/po/zh-cn/daede.po b/luci-app-daede/po/zh-cn/daede.po index 7d33beda..82648e1f 100644 --- a/luci-app-daede/po/zh-cn/daede.po +++ b/luci-app-daede/po/zh-cn/daede.po @@ -314,6 +314,24 @@ msgstr "已是最新" msgid "not installed via package manager" msgstr "非包管理器安装" +msgid "unsupported package version" +msgstr "已安装其他版本,无法在此升级" + +msgid "package status unavailable" +msgstr "软件包状态读取失败" + +msgid "package index refresh failed" +msgstr "软件源刷新失败,请检查网络和软件源" + +msgid "refreshing package indexes" +msgstr "正在刷新软件源" + +msgid "package not found in configured feeds" +msgstr "当前软件源中没有此包" + +msgid "feed version older: %s" +msgstr "软件源版本较旧:%s" + msgid "Unavailable" msgstr "不可用" diff --git a/luci-app-daede/root/usr/share/luci-app-daede/pkg-info.sh b/luci-app-daede/root/usr/share/luci-app-daede/pkg-info.sh index aec2c1bb..ea6b2618 100755 --- a/luci-app-daede/root/usr/share/luci-app-daede/pkg-info.sh +++ b/luci-app-daede/root/usr/share/luci-app-daede/pkg-info.sh @@ -1,8 +1,8 @@ #!/bin/sh # pkg-info.sh -# Prints "\t" for the named package, where either field is -# empty when unknown. Used by the Updates view to decide whether to enable -# the [Upgrade] button. +# Prints "\t\t" for the named package, where either +# version is empty when unknown. Used by the Updates view to decide whether to +# enable the [Upgrade] button. PKG="$1" case "$PKG" in @@ -12,22 +12,26 @@ esac installed="" latest="" +state="absent" if command -v apk >/dev/null 2>&1; then if apk info -e "$PKG" >/dev/null 2>&1; then + state="managed" installed=$(apk list -I "$PKG" 2>/dev/null | awk -v p="$PKG" ' - $1 ~ "^" p "-" { + $1 ~ "^" p "-[0-9]" { sub("^" p "-", "", $1); print $1; exit } ') + [ -n "$installed" ] || state="error" fi # apk search treats ^ and $ as literal chars (not regex anchors), so the old # `apk search "^pkg$"` matched nothing. Enumerate the exact-name package - # across all feeds via `apk list` and take the highest version. Restricting - # to "-" avoids sibling names like -geoip / luci-app-. - latest=$(apk list "$PKG" 2>/dev/null | awk -v p="$PKG" ' + # across configured feeds via `apk list -a` and take the highest version. + # The -a flag excludes locally installed packages that are absent from feeds. + # Restricting to "-" avoids sibling names like -geoip. + latest=$(apk list -a "$PKG" 2>/dev/null | awk -v p="$PKG" ' $1 ~ "^" p "-[0-9]" { v = $1; sub("^" p "-", "", v); print v @@ -36,15 +40,22 @@ if command -v apk >/dev/null 2>&1; then elif command -v opkg >/dev/null 2>&1; then installed=$(opkg status "$PKG" 2>/dev/null | awk -F': ' '$1=="Version"{print $2; exit}') latest=$(opkg info "$PKG" 2>/dev/null | awk -F': ' '$1=="Version"{print $2; exit}') + [ -n "$installed" ] && state="managed" fi case "$PKG" in dae|daed) case "$installed" in 20[0-9][0-9].[0-9]*) ;; - *) installed="" ;; + *) [ -n "$installed" ] && state="foreign"; installed="" ;; esac ;; esac -printf '%s\t%s\n' "$installed" "$latest" +if [ "$state" = "absent" ]; then + case "$PKG" in + dae|daed) [ -x "/usr/bin/$PKG" ] && state="manual" ;; + esac +fi + +printf '%s\t%s\t%s\n' "$installed" "$latest" "$state" diff --git a/luci-app-daede/root/usr/share/luci-app-daede/refresh-index.sh b/luci-app-daede/root/usr/share/luci-app-daede/refresh-index.sh index cf6c26cc..a9aaddb2 100644 --- a/luci-app-daede/root/usr/share/luci-app-daede/refresh-index.sh +++ b/luci-app-daede/root/usr/share/luci-app-daede/refresh-index.sh @@ -2,20 +2,39 @@ # Background apk/opkg update for the Updates view. Returns at once; throttled. LOCK=/tmp/luci-app-daede.idx.lock +STATUS=/tmp/luci-app-daede.idx.status +LOG=/tmp/luci-app-daede.idx.log -if [ -f "$LOCK" ]; then +write_status() { + printf '%s\n' "$1" > "${STATUS}.$$" && mv "${STATUS}.$$" "$STATUS" +} + +if [ -f "$LOCK" ] && [ -f "$STATUS" ]; then mtime=$(date -r "$LOCK" +%s 2>/dev/null || echo 0) [ "$(( $(date +%s) - mtime ))" -lt 90 ] && exit 0 fi : > "$LOCK" +write_status running ( - # -n: skip if a package op holds the shared apk lock (no need to refresh then) + flock -n 9 || exit 0 + umask 077 + # Wait for package upgrades before refreshing the same apk database. if command -v apk >/dev/null 2>&1; then - flock -n /tmp/luci-app-daede.apk.lock apk update + flock /tmp/luci-app-daede.apk.lock apk update > "$LOG" 2>&1 + rc=$? elif command -v opkg >/dev/null 2>&1; then - opkg update + opkg update > "$LOG" 2>&1 + rc=$? + else + printf '%s\n' 'No supported package manager' > "$LOG" + rc=127 fi -) >/dev/null 2>&1 /tmp/luci-app-daede.idx.run.lock >/dev/null 2>&1 /dev/null 2>&1; then # shared apk lock with the bg index refresh (avoid "Unable to lock database") ( - flock 9 - apk update 2>&1 - ver=$(apk list "$PKG" 2>/dev/null | awk -v p="$PKG" '$1 ~ "^" p "-[0-9]" { v=$1; sub("^" p "-", "", v); print v }' | sort -V | tail -1) + flock 9 || exit 1 + if ! apk info -e "$PKG" >/dev/null 2>&1; then + echo "result: $PKG 未通过包管理器安装,不能在线升级" + exit 1 + fi + if ! apk update 2>&1; then + echo "result: 软件源刷新失败,请检查网络和软件源配置" + exit 1 + fi + ver=$(apk list -a "$PKG" 2>/dev/null | awk -v p="$PKG" '$1 ~ "^" p "-[0-9]" { v=$1; sub("^" p "-", "", v); print v }' | sort -V | tail -1) if [ -n "$ver" ]; then constraint="$PKG=$ver" else echo "result: 软件源中没有找到 $PKG,请检查网络或软件源配置" exit 1 fi + installed=$(apk list -I "$PKG" 2>/dev/null | awk -v p="$PKG" '$1 ~ "^" p "-[0-9]" { v=$1; sub("^" p "-", "", v); print v; exit }') + if [ -n "$installed" ] && [ "$(printf '%s\n%s\n' "$ver" "$installed" | sort -V | tail -1)" = "$installed" ]; then + echo "result: $PKG 已安装版本不低于软件源版本,无需升级" + exit 2 + fi echo "--- apk add -s $constraint ---" if ! apk add -s "$constraint" 2>&1; then @@ -66,14 +78,19 @@ fi fi echo "--- apk add $constraint ---" apk add "$constraint" 2>&1 + add_rc=$? + [ "$add_rc" -eq 0 ] || exit 1 + if ! apk list -I "$PKG" 2>/dev/null | awk -v p="$PKG" -v v="$ver" '$1 == p "-" v { found = 1 } END { exit !found }'; then + echo "result: $PKG was not upgraded to $ver" + exit 1 + fi exit 0 ) 9>/tmp/luci-app-daede.apk.lock rc=$? - if [ "$rc" != 0 ]; then + if [ "$rc" = 2 ]; then + : + elif [ "$rc" != 0 ]; then : - elif ! apk list --installed 2>/dev/null | grep -q "^${PKG}-"; then - echo "result: $PKG is not installed" - rc=1 elif apk list -u 2>/dev/null | grep -q "^${PKG}-"; then echo "result: $PKG still has a pending upgrade" rc=1 @@ -83,16 +100,26 @@ fi fi elif command -v opkg >/dev/null 2>&1; then echo "--- opkg update ---" - opkg update 2>&1 - echo "--- opkg upgrade $PKG ---" - opkg upgrade "$PKG" 2>&1 - rc=$? + if opkg update 2>&1; then + echo "--- opkg upgrade $PKG ---" + opkg upgrade "$PKG" 2>&1 + rc=$? + else + echo "result: 软件源刷新失败,请检查网络和软件源配置" + rc=1 + fi else echo "no package manager found" - exit 3 + rc=3 fi - if [ "$rc" = 0 ]; then echo "$(date '+%F %T') ✓ 完成"; else echo "$(date '+%F %T') ✗ 失败 (rc=$rc)"; fi + if [ "$rc" = 0 ]; then + echo "$(date '+%F %T') ✓ 完成" + elif [ "$rc" = 2 ]; then + echo "$(date '+%F %T') ✓ 无需升级" + else + echo "$(date '+%F %T') ✗ 失败 (rc=$rc)" + fi # luci-app-daede upgrade replaces ACL JSON — reload rpcd so changes apply. if [ "$PKG" = "luci-app-daede" ] && [ "$rc" = "0" ]; then diff --git a/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json b/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json index 01775956..2caddd74 100644 --- a/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json +++ b/luci-app-daede/root/usr/share/rpcd/acl.d/luci-app-daede.json @@ -20,6 +20,7 @@ "/tmp/luci-app-daede.pkg-dae.log": [ "read" ], "/tmp/luci-app-daede.pkg-daed.log": [ "read" ], "/tmp/luci-app-daede.pkg-luci-app-daede.log": [ "read" ], + "/tmp/luci-app-daede.idx.status": [ "read" ], "/tmp/luci-app-daede.backup.log": [ "read" ], "/bin/pidof dae": [ "exec" ], "/bin/pidof daed": [ "exec" ], diff --git a/luci-app-ssr-plus/Makefile b/luci-app-ssr-plus/Makefile index a619a8ff..34bc3c93 100644 --- a/luci-app-ssr-plus/Makefile +++ b/luci-app-ssr-plus/Makefile @@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus LUCI_PKGARCH:=all PKG_NAME:=luci-app-ssr-plus PKG_VERSION:=196 -PKG_RELEASE:=19 +PKG_RELEASE:=21 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua index bfb92e1d..ce860231 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua @@ -472,6 +472,8 @@ end o:value("shadowsocks", translate("ShadowSocks")) if is_finded("xray") then o:value("wireguard", translate("WireGuard")) + o:value("naive", "NaiveProxy (Xray / Cronet)") + o:value("shadowsocksr", "ShadowsocksR (Xray)") end if is_finded("xray") then o:value("hysteria2", translate("Hysteria2")) @@ -543,6 +545,7 @@ o:depends({type = "v2ray", v2ray_protocol = "socks"}) o = s:option(Value, "username", translate("Username")) o.rmempty = true o:depends("type", "naiveproxy") +o:depends({type = "v2ray", v2ray_protocol = "naive"}) o:depends({type = "socks5", auth_enable = true}) o:depends({type = "v2ray", v2ray_protocol = "http", auth_enable = true}) o:depends({type = "v2ray", v2ray_protocol = "socks", auth_enable = true}) @@ -562,6 +565,8 @@ o:depends({type = "v2ray", v2ray_protocol = "socks", socks_ver = "5", auth_enabl o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"}) o:depends({type = "v2ray", v2ray_protocol = "trojan"}) o:depends({type = "v2ray", v2ray_protocol = "anytls"}) +o:depends({type = "v2ray", v2ray_protocol = "naive"}) +o:depends({type = "v2ray", v2ray_protocol = "shadowsocksr"}) for _, field in ipairs({ {"anytls_idle_session_check_interval", "Idle session check interval (seconds)", "30"}, @@ -662,6 +667,7 @@ o:depends("type", "ssr") o = s:option(Value, "protocol_param", translate("Protocol param (optional)")) o:depends("type", "ssr") +o:depends({type = "v2ray", v2ray_protocol = "shadowsocksr"}) o = s:option(ListValue, "obfs", translate("Obfs")) for _, v in ipairs(obfs) do @@ -672,7 +678,20 @@ o:depends("type", "ssr") o = s:option(Value, "obfs_param", translate("Obfs param (optional)")) o:depends("type", "ssr") +o:depends({type = "v2ray", v2ray_protocol = "shadowsocksr"}) +-- Xray uses Mihomo's SSR registry, which differs from legacy libev. +for _, field in ipairs({ + {"ssr_method", "Encrypt Method", {"aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", "rc4-md5", "chacha20", "chacha20-ietf", "xchacha20", "none"}}, + {"ssr_protocol", "Protocol", {"origin", "auth_sha1_v4", "auth_aes128_md5", "auth_aes128_sha1", "auth_chain_a", "auth_chain_b"}}, + {"ssr_obfs", "Obfs", {"plain", "http_simple", "http_post", "random_head", "tls1.2_ticket_auth", "tls1.2_ticket_fastauth"}} +}) do + o = s:option(ListValue, field[1], translate(field[2])) + for _, value in ipairs(field[3]) do o:value(value) end + o.default = field[3][1] + o.rmempty = false + o:depends({type = "v2ray", v2ray_protocol = "shadowsocksr"}) +end -- [[ Hysteria2 ]]-- o = s:option(Flag, "hysteria2_realms", translate("Hysteria2 Realms")) @@ -1418,7 +1437,7 @@ if protocols and type(protocols) == "table" and #protocols > 0 then if not proto:find("^_") then if proto == "hysteria2" then o:depends({type = "v2ray", v2ray_protocol = "hysteria2", hysteria2_realms = false}) - elseif proto ~= "socks" and proto ~= "http" then + elseif proto ~= "socks" and proto ~= "http" and proto ~= "shadowsocksr" then o:depends({type = "v2ray", v2ray_protocol = proto}) end end @@ -1584,7 +1603,10 @@ o:depends("xtls", true) o:depends("reality", true) o.rmempty = true +o:depends({type = "v2ray", v2ray_protocol = "naive"}) + -- TLS ALPN + o = s:option(ListValue, "tls_alpn", translate("TLS ALPN")) o.default = "" o:value("", translate("Default")) @@ -1852,4 +1874,23 @@ if is_finded("kcptun-client") then o:depends("type", "ss") end + +-- Naive uses Cronet TLS and multiplexing, independently of Xray stream TLS. +for _, field in ipairs({ + {"naive_quic", "Naive HTTP/3 (QUIC)"}, + {"naive_udp_over_tcp", "Naive UDP over TCP (server support required)"} +}) do + o = s:option(Flag, field[1], translate(field[2])) + o.default = "0" + o:depends({type = "v2ray", v2ray_protocol = "naive"}) +end +for _, field in ipairs({ + {"naive_certificate_file", "Naive trusted CA certificate file"}, + {"naive_ech_config", "Naive ECH config list (base64)"} +}) do + o = s:option(Value, field[1], translate(field[2])) + o.rmempty = true + o:depends({type = "v2ray", v2ray_protocol = "naive"}) +end + return m diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua index 4c8fcca1..0afbfc55 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua @@ -72,6 +72,9 @@ then o:value("trojan", "Trojan (Mihomo/Xray)") o:value("shadowsocks", "Shadowsocks (Mihomo/Xray)") end +if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/libexec/xray") then + o:value("naive", "NaiveProxy (Xray)") +end o.default = "socks5" o = s:option(Value, "server_port", translate("Server Port")) @@ -91,11 +94,13 @@ o:depends("type", "ssr") o = s:option(Value, "username", translate("Username")) o.rmempty = false o:depends("type", "socks5") +o:depends("type", "naive") o = s:option(Value, "password", translate("Password")) o.password = true o.rmempty = false o:depends("type", "socks5") +o:depends("type", "naive") o:depends("type", "ss") o:depends("type", "ssr") o:depends("type", "trojan") @@ -231,12 +236,16 @@ o.description = translate("e.g.: /etc/ssl/fullchain.pem") o.rmempty = true o:depends("tls", "1") +o:depends("type", "naive") + o = s:option(Value, "tls_keyFile", translate("Private Key File Path")) o.description = translate("e.g.: /etc/ssl/private.key") o.rmempty = true o:depends("tls", "1") -- ========== 传输层设置 (Transport) ========== +o:depends("type", "naive") + o = s:option(ListValue, "transport", translate("Transport Protocol")) o:value("tcp", "TCP") o:value("mkcp", "mKCP") @@ -395,4 +404,11 @@ o:depends("type", "vless") o:depends("type", "trojan") o:depends("type", "shadowsocks") +o = s:option(ListValue, "naive_alpn", translate("Naive transport")) +o:value("h2", "HTTP/2") +o:value("h3", "HTTP/3") +o:value("h2,h3", "HTTP/2 + HTTP/3") +o.default = "h2" +o:depends("type", "naive") + return m \ No newline at end of file diff --git a/luci-app-ssr-plus/po/templates/ssr-plus.pot b/luci-app-ssr-plus/po/templates/ssr-plus.pot index baaf4cd8..ce5cdf34 100644 --- a/luci-app-ssr-plus/po/templates/ssr-plus.pot +++ b/luci-app-ssr-plus/po/templates/ssr-plus.pot @@ -3378,3 +3378,18 @@ msgstr "" msgid "Minimum idle sessions" msgstr "" + +msgid "Naive HTTP/3 (QUIC)" +msgstr "" + +msgid "Naive UDP over TCP (server support required)" +msgstr "" + +msgid "Naive trusted CA certificate file" +msgstr "" + +msgid "Naive ECH config list (base64)" +msgstr "" + +msgid "Naive transport" +msgstr "" diff --git a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po index 831ac7fe..903ae55e 100644 --- a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po +++ b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po @@ -3885,3 +3885,18 @@ msgstr "国内 IPv6 地址库更新地址" msgid "China IPv6 Data" msgstr "国内 IPv6 地址库" + +msgid "Naive HTTP/3 (QUIC)" +msgstr "Naive HTTP/3(QUIC)" + +msgid "Naive UDP over TCP (server support required)" +msgstr "Naive UDP over TCP(需要服务端支持)" + +msgid "Naive trusted CA certificate file" +msgstr "Naive 信任的 CA 证书文件" + +msgid "Naive ECH config list (base64)" +msgstr "Naive ECH 配置列表(Base64)" + +msgid "Naive transport" +msgstr "Naive 传输协议" diff --git a/luci-app-ssr-plus/root/etc/init.d/shadowsocksr b/luci-app-ssr-plus/root/etc/init.d/shadowsocksr index 98d34df5..36cb409d 100755 --- a/luci-app-ssr-plus/root/etc/init.d/shadowsocksr +++ b/luci-app-ssr-plus/root/etc/init.d/shadowsocksr @@ -992,6 +992,8 @@ use_mihomo_for_ss_rust_server() { } start_v2ray_with_mihomo() { + # These nodes use Xray-specific settings. + case "$(uci_get_by_name "$1" v2ray_protocol)" in naive|shadowsocksr) return 1 ;; esac local sid="$1" local local_port="$2" local socks_port="$3" @@ -1796,7 +1798,7 @@ start_udp() { ;; v2ray) enable_mihomo=$(uci_get_by_type server_subscribe enable_mihomo "") - if [ "$enable_mihomo" = "1" ] && has_mihomo_binary; then + if [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "naive" ] && [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "shadowsocksr" ] && [ "$enable_mihomo" = "1" ] && has_mihomo_binary; then redir_udp=0 ARG_UDP="" echolog "UDP TPROXY Relay:V2Ray/Xray 单节点由主 Mihomo 实例处理。" @@ -1809,7 +1811,7 @@ start_udp() { echolog "UDP TPROXY Relay:$($(first_type xray) version | head -1) Started!" else # Xray 不存在但 Mihomo 存在,回退到 Mihomo(当 enable_mihomo=0 时) - if has_mihomo_binary; then + if [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "naive" ] && [ "$(uci_get_by_name "$UDP_RELAY_SERVER" v2ray_protocol)" != "shadowsocksr" ] && has_mihomo_binary; then redir_udp=0 ARG_UDP="" echolog "UDP TPROXY Relay:Xray 内核不存在,已回退到 Mihomo 内核启动。" @@ -2249,6 +2251,10 @@ get_udp_relay_mode() { v2ray) proto=$(uci_get_by_name "$node" v2ray_protocol) case "$proto" in + naive) + [ "$(uci_get_by_name "$node" naive_udp_over_tcp 0)" = "1" ] && echo "native" || echo "disabled" + ;; + http) echo "disabled" ;; @@ -2736,6 +2742,16 @@ start_server() { fi echolog "Server:Socks5 Server$server_count Started!" ;; + naive) + xray_bin="$(first_type xray)" + [ -x "$xray_bin" ] || return 1 + config_file="$TMP_PATH/xray-server-$server_count.json" + lua /usr/share/shadowsocksr/gen_naive_server.lua "$1" > "$config_file" || return 1 + "$xray_bin" run -test -c "$config_file" >> /var/ssrplus.log 2>&1 || return 1 + ln_start_bin "$xray_bin" xray-server-$server_count run -c "$config_file" + echolog "Server: Xray NaiveProxy Server$server_count Started!" + ;; + vmess|vless|trojan|shadowsocks) # Xray 服务端支持 port=$(uci_get_by_name "$1" server_port) diff --git a/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua b/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua index 9284efc9..710cb824 100755 --- a/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua +++ b/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua @@ -363,6 +363,14 @@ function outbound:handleIndex(index) trojan = function() trojan_shadowsocks() end, + shadowsocksr = function() + outbound_settings = { + address = server.server, port = tonumber(server.server_port), + password = server.password, method = server.ssr_method or "aes-128-cfb", + protocol = server.ssr_protocol or "origin", protocolParam = server.protocol_param, + obfs = server.ssr_obfs or "plain", obfsParam = server.obfs_param + } + end, shadowsocks = function() trojan_shadowsocks() end, @@ -375,6 +383,19 @@ function outbound:handleIndex(index) wireguard = function() wireguard() end, + naive = function() + outbound_settings = { + address = server.server, port = tonumber(server.server_port), + username = server.username, password = server.password, + serverName = server.tls_host, + certificateFile = server.naive_certificate_file, + quic = server.naive_quic == "1", + udpOverTcp = server.naive_udp_over_tcp == "1", + insecureConcurrency = tonumber(server.naive_concurrency), + quicCongestionControl = server.naive_quic_congestion, + echConfigList = server.naive_ech_config + } + end, anytls = function() outbound_settings = { address = server.server, @@ -878,6 +899,14 @@ Xray.outbounds = { } } +-- Naive owns TLS/multiplexing; SSR owns obfuscation and uses native UDP. +-- Preserve Xray socket marks and dialer chains for both. +if server.v2ray_protocol == "naive" or server.v2ray_protocol == "shadowsocksr" then + local ob = Xray.outbounds[1] + ob.streamSettings = { network = "raw", sockopt = ob.streamSettings.sockopt } + ob.mux = nil +end + if xray_builtin_dns then table.insert(Xray.outbounds, { protocol = "dns", diff --git a/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_naive_server.lua b/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_naive_server.lua new file mode 100644 index 00000000..2b7fe86b --- /dev/null +++ b/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_naive_server.lua @@ -0,0 +1,20 @@ +#!/usr/bin/lua +local uci = require("luci.model.uci").cursor() +local json = require "luci.jsonc" +local s = assert(uci:get_all("shadowsocksr", arg[1]), "missing server section") +assert(s.username and s.username ~= "" and s.password and s.password ~= "", "Naive credentials required") +assert(s.tls_certificateFile and s.tls_keyFile, "Naive TLS certificate and key required") +local alpn = {} +local selected = s.naive_alpn or "h2" +assert(selected == "h2" or selected == "h3" or selected == "h2,h3", "invalid Naive transport") +for value in selected:gmatch("[^,]+") do alpn[#alpn + 1] = value end +print(json.stringify({ + log = {loglevel = "warning"}, + inbounds = {{listen = "::", port = assert(tonumber(s.server_port)), protocol = "naive", + settings = {users = {{username = s.username, password = s.password}}}, + streamSettings = {network = "naive", security = "tls", tlsSettings = { + alpn = alpn, certificates = {{certificateFile = s.tls_certificateFile, keyFile = s.tls_keyFile}} + }} + }}, + outbounds = {{protocol = "freedom", settings = {}}} +}, 1)) diff --git a/luci-theme-aurora/.claude/agents/aurora-runtime-reviewer.md b/luci-theme-aurora/.claude/agents/aurora-runtime-reviewer.md deleted file mode 100644 index a3d1181f..00000000 --- a/luci-theme-aurora/.claude/agents/aurora-runtime-reviewer.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -name: aurora-runtime-reviewer -description: Reviews a diff in this repository for the client runtime of the Aurora theme — menu-aurora.js, router-aurora.js, page JS patches, header inline scripts — against L.require semantics, router invariants, SPA teardown, polling hygiene and keyboard/ARIA reachability. Read-only. -tools: Read, Grep, Glob, Bash -effort: high -skills: luci-knowledge -color: purple ---- - -You review changes to `.dev/src/resource/**`, inline ` - - {% include('footer') %} - ``` - -2. luci-base `ucode/template/header.ut` first includes the **theme** header - (`include(\`themes/${theme}/header\`)`, same scope — the theme renders the - whole `` and opens ``), then emits (header.ut:10-31): - - ``` - - - ``` - - Consequences: the theme `` is parsed **before** `luci.js` exists; - `luci.js` itself sits in the body region after `#tabmenu`; the `?v=` of - `luci.js` (and therefore `L.env.resource_version`, used for every - `L.require` URL) changes whenever any package is installed, because - `pkgs_update_time` is the mtime of `/lib/apk/db/installed` or - `/usr/lib/opkg/status` (`ucode/runtime.uc:182`). On `openwrt-23.05` the - tag is a bare `luci.js` (preceded by `promis.min.js`) and - `pkgs_update_time` does not exist (`23.05 header.ut:10-11`, - `runtime.uc:179-182`), so `resource_version` is undefined and module - URLs are unversioned there. - - `_()` is **not** in `luci.js`: it is defined by `cbi.js` - (`resources/cbi.js:154-157`), reads `window.TR` lazily at call time and - falls back to the source string. The catalog script and `cbi.js` must - therefore have executed before any module that calls `_()` runs — and - this theme's `menu-aurora.js` calls `_()` synchronously in `__init__`. - -3. `view.ut`'s inline `L.require('ui')` runs synchronously in parser order - right after `luci.js`. A wrapper installed from the theme **footer** is too - late for that call, but early enough for `ui.instantiateView(view)` → - `L.require(view)` and for `L.require('menu-aurora')`. - -4. luci-base `ucode/template/footer.ut` includes the theme footer and, when - an apply/revert/rollback is pending, an inline script bound to the - `luci-loaded` event. - -## 2. Template scope the theme can use - -Globals set by `runtime.uc` / `dispatcher.uc` and visible inside -`themes//header.ut`: `media`, `resource`, `theme`, `dispatcher` -(`.lang`, `.build_url()`, `.lookup()`), `dispatched` (the node: `title`, -`css`, …), `ctx.request_path`, `ctx.path`, `config`, `version`, -`pkgs_update_time`, `http`, `ubus`, `_()`, `striptags()`, `entityencode()`. -Callers may add scope: `sysauth.ut` passes `blank_page`, and the theme adds -its own `prefetched_*` (aurora `sysauth.ut:17-21`). - -`{{ expr }}` prints raw — the shipped templates call `entityencode(v, true)` -for attributes and `striptags()` for text explicitly. Do the same. - -## 3. Module loader — `L.require` - -- URL: `${env.base_url}/${name.replace(/\./g,'/')}.js` + `?v=${env.resource_version}` - (`luci.js:2474`); both env values are parsed from the `luci.js` script src - at boot (`luci.js:2257`). -- Loads the source, lexes the leading string literals `'require x [as y]'` - (works on a minified one-line head), then loads dependencies **serially per - level** — a dependency depth of *n* costs *n* round trips. -- Returns the **instance**: `__init__` has already run, so re-requiring a - view returns the rendered singleton. To render again use - `new instance.constructor()` (aurora `router-aurora.js:713`). -- Six names are seeded in memory (`luci.js:2237-2244`) and have **no file** - on disk: `baseclass`, `dom`, `poll`, `request`, `session`, `view`. - Prefetchers must skip them or they 404 on every page. - -## 4. Menu, session store, polling - -- `ui.menu.load()` (`ui.js:3733`): `session.getLocalData('menu')` first — - sessionStorage key `luci-session-store`, namespaced by session id - (`luci.js:1883-1932`) — else one `GET admin/menu` per **session**, not per - page. `ui.menu.flushCache()` (`ui.js:3748`) has no caller in luci-base or - the bootstrap theme. -- `L.Poll` is a singleton inside `luci.js` (`luci.js:1067`): `queue` - (`:1070`), `start()` (`:1158`, dispatches `poll-start` at `:1167`), - `stop()` (`:1183`, dispatches `poll-stop`), `active()`, `tick`. Core's - `setupDOM` shows the `poll-status` indicator on `poll-start` - (`luci.js:2743`) and flips it to "Paused" on `poll-stop` (`:2749`); nothing - in luci-base hides it. -- `dom.content(node, children)` (`luci.js:1442-1449`) deletes the - `data-idref` registry entries under `node` — the only call that does; - without it a departed subtree and its class instances stay referenced. -- Session expiry is signalled two ways (`luci.js:2715-2733`): a ubus error - `-32002` on anything but `session.access` triggers a `session.access` - probe, and an HTTP 403 carrying `X-LuCI-Login-Required: yes` is the - login-required path. -- `hasViewPermission()` is `!env.nodespec.readonly` (`luci.js:3263-3267`); - the form footer's Save/Apply state reads it (`luci.js:2195`). -- `env.pollinterval` defaults to 5 s; a hidden tab keeps polling unless a - theme stops it. - -## 5. Dispatcher responses and caching - -- `http.uc` `write_headers()` (`http.uc:497-512`): unless the action set - its own, every dispatcher response gets `Cache-Control: no-cache` and - `Expires: 0`, plus `X-Frame-Options: SAMEORIGIN`, `X-XSS-Protection`, - `X-Content-Type-Options: nosniff`. No `ETag`, no `Last-Modified` — nothing - to revalidate against, so browsers refetch every dispatcher response. -- `admin/translations/` (`ucode/controller/admin/index.uc:124-136`, - `action_translations`) streams `window.TR={"%08x":"…",…};`. It is a full - CGI dispatch per document and uncacheable by the rule above. Themes link it - as a synchronous `` script (bootstrap `header.ut:44`, aurora - `header.ut:222`), so it is parser-blocking on every MPA navigation. Its - menu node is `type: function` with `auth: {}` (`menu.d/luci-base.json:62-69`), - which only skips the login redirect: `resolve_page()` still runs - `is_authenticated()` for the `admin` node's cookie methods - (`dispatcher.uc:650-651`, `:533-551`), so the dispatch pays the - `session.get` + `session.access` round-trip like any page. -- An action can override the default: `http.header()` stores keys - lower-cased (`http.uc:466-469`), so a `Cache-Control` set by the action - suppresses the `no-cache` default. No `.lmo` exists for `en` - (`luci.mk:10`, `src/lib/lmo.c:237`), so a file-mtime cache key is - undefined for the English catalog; `pkgs_update_time` is not. -- A query string never changes which node is dispatched: uhttpd splits it - off before path lookup and the dispatcher reads `PATH_INFO` only - (`dispatcher.uc:929`; `QUERY_STRING` is parsed separately, `http.uc:606`). - `?v=` on a dispatcher URL is therefore safe. -- Menu tree: `dispatcher.uc:19,366-374` — index cache - `/tmp/luci-indexcache..json`, hashed over the `menu.d` file list; each - dispatch stats the `menu.d` files and parses the cached JSON. -- ACL: `dispatcher.uc` folds every `depends.acl` on the dispatch path into a - single `check_acl_depends()`; `env.nodespec.readonly` is what - `hasViewPermission()` reads, which is what disables Save/Apply. -- Alias / firstchild are resolved server-side **without a redirect**: the - URL stays, `requestpath`/`dispatchpath`/`nodespec`/`ctx.path` already point - at the leaf. `resolve_firstchild()` / `node_weight()` semantics are ported - line for line in `router-aurora.js:25-98`. - -## 6. Branch differences (23.05 / 24.10 / 25.12 / master) - -Source-checked 2026-08 (see `.dev/docs/router.md` §Compatibility): - -| Surface | 23.05 | 24.10 | 25.12 | master | -|---|---|---|---|---| -| `node.css` in the page tree | — | — | — | yes (7c6d8ff, 2026-08) | -| `wildcardaction` + descend-into-satisfied-child rule | — | — | yes | yes (df90c60a7, 2026-01-17) | -| `pkgs_update_time` template global; `luci.js?v=PKG-mtime` (so `L.env.resource_version` and versioned `L.require` URLs) | — (`runtime.uc:179-182`, `header.ut:11`) | yes | yes | yes | -| `action_translations` body, `http.uc` `no-cache` default | same | same | same | same | -| everything else the router uses (`L.require` instance cache, `dom.content`, `Poll`, `ui.menu.load` session cache, interceptors, `-32002` probe, `view.ut` shell) | same | same | same | same | - -The theme targets 23.05+ (ucode templates); anything relying on a newer -surface must degrade to the older behaviour, and the finding must name the -branch. - -## 7. Where to look - -- `$LUCI_SRC/modules/luci-base/ucode/{dispatcher,http,runtime}.uc` -- `$LUCI_SRC/modules/luci-base/ucode/template/{header,footer,view}.ut` -- `$LUCI_SRC/modules/luci-base/ucode/controller/admin/index.uc` -- `$LUCI_SRC/modules/luci-base/ucode/uhttpd.uc` (in-process handler entry) -- `$LUCI_SRC/modules/luci-base/htdocs/luci-static/resources/{luci,ui,rpc,uci,form,network}.js` (`Poll`, `dom`, `session`, `view` live inside `luci.js`) -- `$LUCI_SRC/luci.mk`, `$LUCI_SRC/themes/luci-theme-bootstrap/` -- Other branches: `git -C $LUCI_SRC show :` (fetch - `openwrt-23.05`, `openwrt-24.10`, `openwrt-25.12` first if missing). diff --git a/luci-theme-aurora/.claude/skills/luci-knowledge/references/packaging.md b/luci-theme-aurora/.claude/skills/luci-knowledge/references/packaging.md deleted file mode 100644 index 5e3a4118..00000000 --- a/luci-theme-aurora/.claude/skills/luci-knowledge/references/packaging.md +++ /dev/null @@ -1,35 +0,0 @@ -# Packaging facts (luci.mk, Makefile, feed) - -## luci.mk rewrites at package build (`$LUCI_SRC/luci.mk:287-298`, `SubstituteVersion`) - -Applied to every `*.ut` / `*.htm` under the installed template dir: - -1. `{# PKG_VERSION #}` → the package version (aurora `header.ut:227` uses it - for `body[data-asset-version]`; luci-base `header.ut:10` for `luci.js?v=`). -2. Quoted `"{{ media }}…/x.css"` and `"{{ resource }}…/x.js"` links get - `?v=$(PKG_VERSION)` appended. The regex requires the literal `.css"`/`.js"` - at the end of the quoted string, so `{{ resource }}/{{ dispatched.css }}` - is **not** rewritten (same as bootstrap) while - `{{ media }}/patches/{{ patch }}.css` **is**. - -Never judge versioning from the source `.ut`; inspect the installed file or -the live HTML. - -## Theme Makefile - -- `PKG_VERSION` / `PKG_RELEASE` (date) in `Makefile`. `LUCI_MINIFY_CSS:=` - blanks luci.mk's default `LUCI_MINIFY_CSS?=1` (`luci.mk:18`), so the - csstidy pass (`luci.mk:274-280`) is skipped for the already-minified - `htdocs/`. `LUCI_MINIFY_JS` is **not** blanked: with `CONFIG_LUCI_JSMIN` - the package build runs jsmin over `htdocs/**/*.js` (`luci.mk:261-268`), - so on-device JS sizes can differ from the repo's — measure on the device - when a JS budget is the question. -- `root/etc/uci-defaults/30_luci-theme-aurora` sets `luci.themes.Aurora` and - `luci.main.mediaurlbase` on fresh installs only (`PKG_UPGRADE != 1`). -- The OpenWrt buildbot has no Node: `htdocs/luci-static/` is the committed - output of `pnpm build`; the package copies it verbatim. -- Floors: OpenWrt 23.05 (ucode templates); Chrome 111 / Safari 16.4 / - Firefox 128; the Navigation API is an optional enhancement. -- CI: `.github/workflows/build-theme-package.yml` builds ipk + apk on tags, - manual dispatch, and branch pushes whose head commit message contains - `[build]`. diff --git a/luci-theme-aurora/.claude/skills/luci-knowledge/references/spa-pitfalls.md b/luci-theme-aurora/.claude/skills/luci-knowledge/references/spa-pitfalls.md deleted file mode 100644 index 08a168a9..00000000 --- a/luci-theme-aurora/.claude/skills/luci-knowledge/references/spa-pitfalls.md +++ /dev/null @@ -1,29 +0,0 @@ -# SPA pitfalls that apply to this router - -Distilled from luci-theme-footstrap's router work (public: -https://github.com/VizzleTF/luci-theme-footstrap/blob/main/docs/spa-router.md) -and re-checked against this theme's implementation; Aurora's handling is -specified in `.dev/docs/router.md`. Self-contained — no other note is needed. - -| pitfall | why it bites | aurora | -|---|---|---| -| `L.require()` returns the rendered **instance** | re-requiring a view paints nothing; `new` on the instance's class without teardown = double render + double pollers, invisible to the eye | `new instance.constructor()` only after teardown, `router-aurora.js:713` | -| the class rendered by the full load must be marked "seen" | otherwise the first return to that page takes the cold path and renders twice | `initialRoute()` | -| generation check at **paint** time, and a superseded render must never resolve | an empty node blanks the live page, a throw lets luci-base paint an error box into the new page | `navigate()` gen gate | -| poll teardown is three steps: `queue.length = 0`, `stop()`, `start()` | `start()` resets the tick that arms the incoming view's first poll | `teardown()` | -| the `poll-status` indicator outlives polling | core shows it on `poll-start` and never hides it | `hideIndicator('poll-status')` | -| bare `setInterval` in apps survives a same-document swap | a full load killed it; the router must | `hookIntervals()` | -| `alias` / `firstchild` are the most-clicked links and resolve server-side **without a redirect** | `requestpath`/`dispatchpath`/`nodespec` already point at the leaf while the URL stays; port `resolve_firstchild()`/`node_weight()` literally | `resolve()` | -| `env.nodespec.readonly` is not decoration | `hasViewPermission()` reads it → Save/Apply enabled for read-only users if lost | `readonlyAlong()` | -| links with `?query` / `#hash` stay full loads | views read `location.search`; a hash-only change is not a navigation | `onNavigate()` | -| content lands outside `#view` | `

` siblings from server templates, `ui.addNotification()` inserted into `#maincontent` — a full load cleared them, a swap must | `region()`, `commit()` | -| `body[data-page]` and `document.title` | restamp `data-page` from the resolved leaf (page-scoped CSS keys on it); cache the title host once, third-party views overwrite `document.title` | `setEnvironment()` | -| view-injected ` - - - -
-
-
- -
-
PartitionType / FilesystemMount PointLabelSizeUsedUnusedFlags
0BOOTCONFIG--256.00 KiB---
SQUASHFS/rom-2.00 GiB110.0 MiB0-
Ext4/mnt/mmcblk0p6-113.26 GiB2.0 MiB105.2 GiBstorage
-
-
-
-
- - diff --git a/luci-theme-aurora/.dev/compat/pages/admin-dashboard.md b/luci-theme-aurora/.dev/compat/pages/admin-dashboard.md deleted file mode 100644 index 041328ec..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-dashboard.md +++ /dev/null @@ -1,25 +0,0 @@ -# admin-dashboard - -Patch file: `.dev/src/media/patches/admin-dashboard.css` (scope `[data-page="admin-dashboard"] .Dashboard > .section-content`, line 8-10). Route: main.css `@layer luci-mod-dashboard` (7f25128) → `_patches.css` (aedf3dc, 7d9f6a1) → own on-demand file with `@reference`/`@apply` (1c924cf, PR #82) → native CSS (e14cfcd). Page package: stock luci-mod-dashboard (menu.d "admin/dashboard" "Dashboard"); it ships its own `view/dashboard/css/custom.css`. - -## dashboard-cards-and-dark — card decoration on `.dashboard-bg`, dark-mode svg invert, title rule, wifi device cell -- page: admin-dashboard · Dashboard -- package: stock luci-mod-dashboard -- dom: `.dashboard-bg` (card), `.dashboard-bg.tr` (row variant, no radius), `img[src*=".svg"]`, `.title h3`, `.router-status-wifi .wifi-info .devices-info .tr .td:nth-child(3)` -- symptom: not recorded beyond the subjects ("dark mode display issue in luci-mod-dashboard"; 56db83c: "Adapt for missing data-page="admin-dashboard" on default login redirect to dashboard", "Remove border-radius on .dashboard-bg for mobile view") -- cause: unknown for the card/wifi/h3 rules (7f25128 has subject only). For the scope: 56db83c body says the `[data-page="admin-dashboard"]` attribute was missing when the login redirect landed on the dashboard, so the scope was dropped; 1c924cf restored it when the patch became on-demand (PR #82: "Backfilled missing data-page scoping in the original patches (… dashboard)"), and header.ut now computes the page name from `ctx.path` when `request_path` is empty (DEVELOPMENT.md §On-Demand Third-Party Patches, item 1) -- fix: patches/admin-dashboard.css — `.dashboard-bg { background: var(--surface-overlay) }` + `&.tr { border-radius: 0 }` + `&:not(.tr) { border: 1px solid var(--hairline); box-shadow: var(--app-shadow-lg); &:hover {…} }` (line 11-27); `img[src*=".svg"] { [data-darkmode="true"] & { filter: invert(100%) } }` (line 38-42); `.title h3 { color: var(--text); border: 0; padding-bottom: 1rem; @media (width < 48rem) { margin-inline: 0; padding-bottom: 0.5rem } }` (line 93-102); `.router-status-wifi .wifi-info .devices-info .tr .td { &:nth-child(3) { position: relative; top: 0; width: 100%; padding-inline: 0 } @media (width < 48rem) { flex: 1 1 50% } }` (line 104-117) · 7f25128 2025-09-28 · 0.5.1_beta (first tag v0.5.5_beta); 56db83c 2025-10-12 · 0.5.9_beta (first tag v0.6.0_beta) dropped the scope and added `.tr { rounded-none }`; the original `.router-status-lan .devices-info tr th { max-md:flex-[1_1_50%] }` from 7f25128 was removed by c3fae55 2025-09-29 "fix: mobile display issue in luci-mod-dashboard th" (subject only) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -## dashboard-dark-text-and-inline-tables — force theme text colour in dark mode, compact assoclist cells, undecorate inline info tables -- page: admin-dashboard · Dashboard (issue #66 names the System, DHCP Devices and Wireless panels) -- package: stock luci-mod-dashboard -- dom: `.dashboard-bg span/td/th` (dark mode), `.dashboard-bg .td/.th` (assoclist cells carry `.td/.th` classes), `.dashboard-bg .table:not(.assoclist)` with its `tr` and `td` (the DNS-style inline info tables) -- symptom: issue #66: "Using luci-mod-dashboard with aurora in dark mode results in multiple UI readability and layout issues … Some elements are rendered with very low contrast (almost black on dark background), and spacing/padding in certain tables and panels (System, DHCP Devices, Wireless) appears inconsistent." (OpenWrt 25.12.4, two screenshots) -- cause: the patch's own comment: "Dark mode: override custom.css hardcoded light-mode colors on all text nodes" — luci-mod-dashboard's `custom.css` sets text colours the theme's dark palette does not reach; the spacing/inline-table rules have no recorded cause (944e7c5 has subject only) -- fix: patches/admin-dashboard.css — `& span, & td, & th { [data-darkmode="true"] & { color: var(--text) !important } }` (line 30-36); `& .td { padding-block: 0.5rem; @media (width < 48rem) { padding-block: 0.25rem } }` and `& .th { padding-block: 0.5rem }` (line 45-54); `& .table:not(.assoclist) { margin-bottom: 0; border-radius: 0; border: 0; background: transparent; box-shadow: none; & tr { &:hover { background: transparent } @media (width < 48rem) { display: table-row; border: 0; padding: 0 } } & td { border: 0; padding: 0.125rem 0; @media (width < 48rem) { display: table-cell } &:first-child { padding-right: 0.5rem; white-space: nowrap; opacity: 0.7 } } }` (line 57-91) · 944e7c5 2026-05-31 (in `_patches.css`) · 0.11.10 (first tag v0.12.0) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: #66 (still open) · mirror: pending · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-modem-modemdata-modempreview.md b/luci-theme-aurora/.dev/compat/pages/admin-modem-modemdata-modempreview.md deleted file mode 100644 index 7737b130..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-modem-modemdata-modempreview.md +++ /dev/null @@ -1,12 +0,0 @@ -# admin-modem-modemdata-modempreview - -## modemdata-badge-width — let signal badges inside info cards size to content -- page: admin-modem-modemdata-modempreview · Modem → Modem Data → (preview) (menu path inferred from the page name; not in the local LuCI checkouts) -- package: luci-app-modemdata (third-party; named in the patch header and PR #80) -- dom: `.ifacebox-body .ifacebadge` on the "General Information" cards (PR #80 text) -- symptom: PR #80 body: "Aurora's default ifacebox styles spread modemdata rows apart, wrap signal badges vertically, and leave cards at uneven heights." -- cause: unknown beyond the PR wording — the merged diff (910c85d, 12 lines) contains only the badge width override; the row-spacing and card-height parts of the PR description have no rule in the commit -- fix: patches/admin-modem-modemdata-modempreview.css line 8-12 `[data-page="admin-modem-modemdata-modempreview"] { & .ifacebox-body .ifacebadge { width: auto !important; } }` · 910c85d 2026-06-28 (author CJay D Acopra, PR #80) · 1.0.2 (first tag v1.1.0) — added to `_patches.css` as `@apply w-auto!`, split into its own file by 1c924cf, native CSS by e14cfcd -- verified: not measured (no record) -- fixture: none (backfill) -- issue: PR #80 · mirror: pending · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-modem-qmodem.md b/luci-theme-aurora/.dev/compat/pages/admin-modem-qmodem.md deleted file mode 100644 index 3cdb0249..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-modem-qmodem.md +++ /dev/null @@ -1,12 +0,0 @@ -# admin-modem-qmodem - -## qmodem-theming — colours, borders, hover states, tab and table styling across the QModem pages -- page: admin-modem-qmodem (prefix; covers `-overview`, `-sms`, `-sms-conversation-`, `-sms_sim`, `-config_advanced`, `-settings`, `-network_config`) · Modem → QModem → … (menu paths inferred from the page names; the app is not in the local LuCI checkouts) -- package: luci-app-qmodem (third-party; named in the patch header and PR #92) -- dom: `[data-page^="admin-modem-qmodem"]`: `.copyright-section`, `fieldset.cbi-section > legend`, `fieldset.cbi-section`, `.cbi-section-table-titles.named::before` (line 9-42); `[data-page^="admin-modem-qmodem-sms-conversation"]`: `#sms-messages-area`, `.sms-message-bubble`, `.sms-message-content`, `.sms-message-meta` (line 44-64); `[data-page="admin-modem-qmodem-config_advanced"]`: `.cbi-tabmenu li` and `.cbi-tab` (line 66-96; the file's comment: "targets
  • directly (not li > a) because qmodem's tab markup has no inside tabs"); `[data-page="admin-modem-qmodem-sms"]`: `.td > div`, `.td > span[style*="margin-left"]`, `.sms-conversations` (+ `> .cbi-section`, `fieldset.cbi-section`, `.table.cbi-section-table`), `.cbi-section-table-row.tr` (+ hover), `.sms-unread-conversation`, `.sms-unread-badge` (line 98-175); `[data-page="admin-modem-qmodem-sms_sim"]`: `.cbi-section-table-row.tr` (+ hover) (line 177-197); `[data-page="admin-modem-qmodem-settings"]`: `.cbi-section-table-descr.named::before` (line 201-206) -- symptom: not recorded per rule. PR #92 body: "Styles qmodem overview, SMS, conversation, advanced config, network config, and settings pages with consistent theming (borders, colors, hover states, table formatting, and tab styling)." -- cause: unknown (commit 7066351 has subject only; the PR body lists scope, not what each page did wrong) -- fix: patches/admin-modem-qmodem.css (whole file) · 7066351 2026-07-25 (author shiraneko, PR #92 by cjayacopra) · 1.1.2 (first tag v1.2.0) — written with `@reference`/`@apply`, rewritten natively by e14cfcd 2026-07-27 (1.1.8; radii became `calc(var(--radius-base) * n)`) -- verified: not measured (no record) -- fixture: none (backfill; DOM snapshots exist in `.dev/mocks/admin-modem-qmodem*.html` — overview, sms, sms_sim, config_advanced, settings, network_config) -- issue: PR #92 · mirror: pending · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-network-network.md b/luci-theme-aurora/.dev/compat/pages/admin-network-network.md deleted file mode 100644 index e16eeed0..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-network-network.md +++ /dev/null @@ -1,47 +0,0 @@ -# admin-network-network - -## bridge-vlan-descr-hidden — hide the table description row on mobile -- page: admin-network-network · Network → Interfaces → Devices → Bridge VLAN Filtering (efa07d8 body: "Network -> Interfaces -> Devices -> Bridge VLAN Filtering") -- package: stock luci-mod-network -- dom: `.table tr.cbi-section-table-descr` — global selector, added for this page -- symptom: not recorded beyond "to improve layout" (efa07d8 body) -- cause: unknown (efa07d8 body states the action, not what the descr row did wrong) -- fix: components/_table.css `&.table-titles, &.cbi-section-table-titles, &.cbi-section-table-descr { max-md:hidden }` (line 58-62) — `.cbi-section-table-descr` was added to the existing list · efa07d8 2025-09-18 · 0.3.7_alpha (first tag v0.4.0-alpha) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -## ifacebox-cells-full-row — interface status/box cells stack full-width on mobile -- page: admin-network-network · Network → Interfaces (menu.d title "Interfaces") -- package: stock luci-mod-network -- dom: `td[data-name="_ifacebox"]`, `td[data-name="_ifacestat"]` — DummyValue cells of the `interface` GridSection (interfaces.js:296-297 query `[data-name="_ifacestat"] > div` and `[data-name="_ifacebox"] .ifacebox-body`) -- symptom: not recorded (bec6830 subject: "feat: enhance ifacebox display in td") -- cause: unknown (commit bec6830 has subject only) -- fix: components/_table.css `[data-page="admin-network-network"] & { &[data-name="_ifacebox"], &[data-name="_ifacestat"] { … } }` nested under `& td, & .td` (line 214-219) `max-md:basis-[100%]` · bec6830 2025-09-23 · 0.4.3_alpha (first tag v0.5.0_beta). The same commit added the `td &` variants of `.ifacebox` that 397e46b later moved under `#cbi-network-interface` (next entry) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -## interface-cards-floor — equal-width interface cards, horizontal card layout on mobile -- page: admin-network-network · Network → Interfaces -- package: stock luci-mod-network -- dom: `#cbi-network-interface` (id of `form.Map('network')` + GridSection `'interface'`, interfaces.js:497-501) — five descendant rules on `.ifacebox`, `.ifacebox-head`, `.ifacebox-body`, `.ifacebox-body > div`, `.ifacebox-body small` -- symptom: 397e46b body: "The interfaces overview sizes every card by its content, so a bridge carrying seven device icons rendered far wider than a single-port one." -- cause: 397e46b body: "The shared `.ifacebox` min-width had been masking half of that until 1.2.7 lowered it to stop the port status grid overlapping. The floor now sits on the overview's own section instead — `#cbi-network-interface`, the scope luci-theme-bootstrap already uses for this page — at 152px, and the five `td &` rules that only ever applied there move under it too rather than reaching every `.ifacebox` inside any table cell." -- fix: components/_card.css `#cbi-network-interface &` at line 72-74 (`.ifacebox`: `max-md:flex-row md:min-w-38`), 83-85 (`.ifacebox-head`: `max-md:flex max-md:w-auto max-md:shrink-0 max-md:items-center max-md:justify-center max-md:rounded-l-3xl max-md:rounded-tr-none max-md:border-r max-md:border-b-0`), 107-109 (`.ifacebox-body`: `max-md:flex-row max-md:items-center max-md:rounded-r-3xl max-md:rounded-bl-none max-md:py-2 max-md:pr-2 max-md:pl-4`), 144-146 (`.ifacebox-body > div`: `max-md:w-auto max-md:flex-1 max-md:space-y-1`), 163-165 (`.ifacebox-body small`: `max-md:mt-0`) · 397e46b 2026-08-30 · 1.2.10 (first tag v1.3.0). The mobile rules were first written as `td &` in bec6830 (2025-09-23) -- verified: no before/after measurement of the card widths recorded; the body states the size changes it made: "icons 24px -> 20px, the gap between adjacent ones 8px -> 4px, card padding 16px -> 12px and the label line spacing 16px -> 4px", floor 152px, `.ifacebox-body > img` / badge icons "intrinsic 32px" → 20px, zone swatch 33px tall → vertical padding 2px -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -## bridge-vlan-dropdown-clip — let the Bridge VLAN table's dropdowns escape their wrapper on mobile -- page: admin-network-network · Network → Interfaces → Devices → Configure → Bridge VLAN filtering (path from efa07d8's wording of the same table; c5a2dff itself only says "bridge-vlan table") -- package: stock luci-mod-network -- dom: `[data-name="bridge-vlan"] > div` — the SectionValue option `bridge-vlan` wrapping the Bridge VLAN TableSection (tools/network.js:1354); patch rule under `@media (width < 48rem)` -- symptom: dropdown clipped on mobile (c5a2dff subject: "fix(mobile): resolve clipped dropdown in bridge-vlan table") -- cause: unknown (commit c5a2dff has subject only; the diff shows only the override, not which rule clipped the dropdown) -- fix: patches/admin-network-network.css line 8-12 `@media (width < 48rem) { [data-name="bridge-vlan"] > div { overflow: visible !important; } }` · c5a2dff 2025-10-19 · 0.6.1_beta (first tag v0.7.0_beta) — written as `@layer patches > admin-network-network { … @apply max-md:!overflow-visible }` in main.css, moved to `_patches.css` by aedf3dc, split into its own on-demand file by 1c924cf (#82, `@reference` + `@apply`), rewritten as native CSS by e14cfcd -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -See also: e86b70f lists "Network => (Interfaces, Wireless, Firewall)" for the `.cbi-section-actions` mobile rule — recorded in `admin-status-overview.md`. diff --git a/luci-theme-aurora/.dev/compat/pages/admin-network-wireless.md b/luci-theme-aurora/.dev/compat/pages/admin-network-wireless.md deleted file mode 100644 index d5a0eec5..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-network-wireless.md +++ /dev/null @@ -1,14 +0,0 @@ -# admin-network-wireless - -## assoclist-full-row-cells — Associated Stations cells take a full row on mobile -- page: admin-network-wireless · Network → Wireless, "Associated Stations" table (wireless.js:2667 creates `#wifi_assoclist_table`, h3 at :2680). The same id is also created by luci-mod-status 60_wifi.js:243 on Status → Overview; 1dbd95a does not say which page it was written against -- package: stock luci-mod-network (and luci-mod-status for the overview copy) -- dom: `#wifi_assoclist_table td`, `#wifi_assoclist_table .td` (class `table assoclist`); rule also moves the `data-title` ::before label (`before:max-md:mb-1.5`) -- symptom: not recorded (1dbd95a subject: "Ensure each table cell in Associated Stations takes up a full row on mobile") -- cause: unknown (commit 1dbd95a has subject only) -- fix: components/_table.css `#wifi_assoclist_table &` nested under `& td, & .td` (line 156-158) `max-md:flex-[0_0_100%] max-md:px-3 max-md:py-2 before:max-md:mb-1.5` · 1dbd95a 2025-10-17 · 0.5.14_beta (first tag v0.6.0_beta) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -See also: 50c2b84 lists "Network => Wireless host: Fix overflow when td text is too long" as one motivation for `.td.cbi-value-field { break-all }` — that lineage is recorded in `admin-services-dockerman.md` (the rule's current form comes from a2d110a). e86b70f lists "Network => (Interfaces, Wireless, Firewall)" for the `.cbi-section-actions` mobile rule — recorded in `admin-status-overview.md`. diff --git a/luci-theme-aurora/.dev/compat/pages/admin-services-dockerman.md b/luci-theme-aurora/.dev/compat/pages/admin-services-dockerman.md deleted file mode 100644 index d77fe8f1..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-services-dockerman.md +++ /dev/null @@ -1,13 +0,0 @@ -# admin-services-dockerman - -## info-table-entry-column — value cells break only words that do not fit - -- page: admin-services-dockerman-overview · Services → Dockerman JS → Overview -- package: luci-app-dockerman (openwrt/luci, the JS rewrite) -- dom: `.cbi-section.cbi-tblsection > table.table.cbi-section-table > tr.cbi-section-table-row > td.td.cbi-value-field[data-name=entry|value]` — `docker info` rendered as two-column TableSections; the value column holds multi-KB JSON with no spaces (Runtimes, Plugins) -- symptom: the entry column collapsed to ~42px and showed one character per line (`MemoryLimit` over 7–8 lines) beside the JSON values -- cause: `.td.cbi-value-field` carried `word-break: break-all` at every width (added in 50c2b84 as an overflow guard). `break-all` drops every cell's min-content to about one character; auto table layout then hands spare width out by max-content, so the JSON took nearly all of it. bootstrap sets no word-break on desktop cells — its labels stay whole but the JSON stretches the table to ~3.5k px and the page scrolls sideways. -- fix: `components/_table.css` `& td, & .td { &.cbi-value-field { wrap-anywhere md:max-w-prose } }` — `wrap-anywhere` keeps break-all's min-content (same overflow guard) but only breaks a word that does not fit; `md:max-w-prose` caps each cell's intrinsic contribution so one huge value cannot starve the other columns (the used width may still exceed it: 944px measured) · a2d110a · 1.3.2. Lineage: 50c2b84 2025-10-12 (0.5.8_beta) added `&.cbi-value-field { break-all }` for "System => (Software, Mount Points): Fix overflow when td text is too long" and "Network => Wireless host: Fix overflow when td text is too long", replacing the global `td max-w-94` it removed for passwall (see `admin-services-passwall.md`); 031283c 2026-07-09 added the mobile-card utilities on the same rule (`max-md:mb-1 max-md:basis-full max-md:self-start max-md:text-left` and the `[data-widget=…] max-md:basis-1/2` sub-rule) -- verified: device, Chromium, Environment table before → after: entry column 42 → 260px at 1440, 42 → 196 at 1024, 41 → 152 at 800; short words split across lines 41 → 0 / 0 / 2; mobile cards unchanged; section height 8301 → 3797px at 1440; firewall zone and rule GridSections kept identical column widths at 1440/1024/800/390; a file:// fixture gave the same result in Chromium, WebKit and Firefox. Side effect noted, not measured: on admin-system-mounts the GridSection value cells take the 65ch cap instead of the page's `max-w-104` (same specificity, later rule). -- fixture: fixtures/admin-services-dockerman-overview--info-table.html (entry column `nowrap` at 1440/1024/390 — at 800 two short words still split, so that width is not asserted) -- issue: #96 · mirror: shadcn f4d7219 · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-services-mini-diskmanager.md b/luci-theme-aurora/.dev/compat/pages/admin-services-mini-diskmanager.md deleted file mode 100644 index c5f9a11d..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-services-mini-diskmanager.md +++ /dev/null @@ -1,25 +0,0 @@ -# admin-services-mini-diskmanager - -## partition-table-font — the table's own font-size reaches its cells - -- page: admin-services-mini-diskmanager-minidiskmanager · Services → Disk Manager -- package: luci-app-mini-diskmanager (4IceG/luci-app-mini-diskmanager) -- dom: `table#partition-table- > tr.tr > td.td` — the `` carries inline `table-layout:fixed; width:100%; font-size:12px`; first `th` 180px, the other seven `width:12.5%; min-width:90px`; the type cell is ` NAME` -- symptom: type/filesystem and mount-point cells wrap — swatch on one line, name below; long names break mid-word (`0BOOTCONFIG` / `1`, `/mnt/mmcblk0` / `p6`) -- cause: `td, .td` set `text-base` (16px) directly, so the table's inline 12px never reached the cells; fixed columns sized for 12px got 16px text and `wrap-break-word` split what did not fit. bootstrap puts its font size on `.table` and lets cells inherit. -- fix: `components/_table.css` `table.table, .table` `text-base max-md:text-sm` (moved off `td, .td`, which now inherit) · dd7c64b · 1.3.3 -- verified: device 192.168.8.1, CDP before/after in one page load — cells 16 → 12px; wrapped cells 5 → 1 at 1280 (the remaining `0BOOTCONFIG1` wraps under bootstrap at that width too), 5 → 0 at 1920, 0 → 0 at 390; eleven stock pages (overview, routes, processes, interfaces, firewall zones/rules, DHCP, wireless, mounts, startup, SSH keys) showed zero font-size/line-height changes on any text-bearing table element at 1280 and 390 -- fixture: fixtures/admin-services-mini-diskmanager-minidiskmanager--partition-table.html -- issue: #65 · mirror: shadcn 4f1c7f4 · status: active - -## partition-table-gutter — the stable scrollbar gutter leaves the type cell 0.9px short at 1280 - -- page: admin-services-mini-diskmanager-minidiskmanager · Services → Disk Manager -- package: luci-app-mini-diskmanager (4IceG/luci-app-mini-diskmanager) -- dom: `table#partition-table-` (inline `table-layout:fixed; width:100%`); type cell ` 0BOOTCONFIG` -- symptom: with classic scrollbars at a 1280px viewport the swatch and `0BOOTCONFIG` split onto two lines; overlay scrollbars are unaffected -- cause: `_elements.css` `html` `[scrollbar-gutter:stable]` (added so short pages and open modals stop shifting the layout) reserves the 11px thin scrollbar on every page, which is what a scrolling page already paid; the #65 fit had 0.6px to spare -- fix: none on the page; the fixture pins `html { scrollbar-gutter: auto }` because its 1153px width was measured without a scrollbar, so it keeps guarding #65's inherited 12px -- verified: headless Chrome, fixture at 1280 — table 1152.7 → 1142.1px, cell content 114.9 → 113.4px against a 114.3px line (fits → wraps); `pnpm test` compat fails without the pin and passes with it -- fixture: fixtures/admin-services-mini-diskmanager-minidiskmanager--partition-table.html -- issue: — · mirror: shadcn 50c53a9 · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-config.md b/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-config.md deleted file mode 100644 index cad46a72..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-config.md +++ /dev/null @@ -1,12 +0,0 @@ -# admin-services-openclash-config - -## openclash-subinfo-icons — fix the subscription-info icon size -- page: admin-services-openclash-config · Services → OpenClash → Config Manage (controller openclash.lua:84 entry title "Config Manage") -- package: luci-app-openclash (vernesong; the ImmortalWrt feed copy was checked) -- dom: `.sub_div img` — `.sub_div` comes from `luasrc/view/openclash/sub_info_show.htm`, the template used by config.lua:191 -- symptom: not recorded (87522d8 subject: "feat: add openclash patch and remove btn spacing") -- cause: unknown (commit 87522d8 has subject only) -- fix: patches/admin-services-openclash-config.css line 8-13 `[data-page="admin-services-openclash-config"] { .sub_div img { height: 1.25rem; width: 1.25rem; } }` · 87522d8 2025-09-17 · 0.3.6_alpha (first tag v0.4.0-alpha) — written as `@layer patches > luci-app-openclash { [data-page=…] .sub_div img { @apply h-5 w-5 } }` in main.css; `_patches.css` via aedf3dc; own file via 1c924cf; native via e14cfcd -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-log.md b/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-log.md deleted file mode 100644 index dedf9066..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-log.md +++ /dev/null @@ -1,12 +0,0 @@ -# admin-services-openclash-log - -## openclash-log-dark-bg — dark page background on the Server Logs page -- page: admin-services-openclash-log · Services → OpenClash → Server Logs (controller openclash.lua:85 entry title "Server Logs") -- package: luci-app-openclash (vernesong) -- dom: `[data-page="admin-services-openclash-log"]` (the body element itself) -- symptom: not recorded (87522d8 subject only) -- cause: unknown (commit 87522d8 has subject only) -- fix: (historic, main.css `@layer patches > luci-app-openclash`) `[data-page="admin-services-openclash-log"] { @apply dark:bg-aurora-night-teal; }` · 87522d8 2025-09-17 · 0.3.6_alpha (first tag v0.4.0-alpha) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: n/a · status: removed 30f922d (2025-11-09 "chore: remove patch styles and adjust DOM indentation" — body: "Removed temporary patch styles … Test case: openclash → Server Logs (dark mode background)"; 0.7.9_beta, first tag v0.8.0_beta) diff --git a/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-settings.md b/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-settings.md deleted file mode 100644 index a93392b4..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-services-openclash-settings.md +++ /dev/null @@ -1,23 +0,0 @@ -# admin-services-openclash-settings - -## openclash-settings-select-full — selects fill the value field on mobile -- page: admin-services-openclash-settings · Services → OpenClash → Plugin Settings (controller openclash.lua:71 entry title "Plugin Settings") -- package: luci-app-openclash (vernesong) -- dom: `.cbi-value-field .cbi-input-select` under `@media (width < 48rem)` -- symptom: not recorded (a667f02 subject: "feat: add openclash cbi-input-select style patch") -- cause: unknown (commit a667f02 has subject only; its diff is a whole-file rewrite of main.css, the rule as first written was `[data-page="admin-services-openclash-settings"] .cbi-value-field .cbi-input-select { @apply max-md:!w-full }`) -- fix: patches/admin-services-openclash-settings.css line 9-13 `@media (width < 48rem) { .cbi-value-field .cbi-input-select { width: 100% !important; } }` · a667f02 2025-09-26 · 0.4.6_alpha (first tag v0.5.0_beta) — `_patches.css` via aedf3dc; own file via 1c924cf; native via e14cfcd -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -## openclash-diag-grid — stack the Debug Logs diagnostic controls in one column on mobile -- page: admin-services-openclash-settings · Services → OpenClash → Plugin Settings → Debug Logs tab (settings.lua:81 tab "debug", :1308 DummyValue rendering `debug.htm`) -- package: luci-app-openclash (vernesong) -- dom: `.diag-style` and `.diag-style > div` — from `luasrc/view/openclash/debug.htm` (which itself styles `.diag-style` for `[data-darkmode="true"]` at its line 12-17) -- symptom: not recorded (87522d8 subject only) -- cause: unknown (commit 87522d8 has subject only) -- fix: patches/admin-services-openclash-settings.css line 15-33 `.diag-style { & > div { display: flex; flex-direction: column; align-items: center; gap: 0.5rem } @media (width < 48rem) { display: grid; grid-template-columns: repeat(1, minmax(0, 1fr)); gap: 1rem; & > div { width: 100% !important; gap: 0.25rem } } }` · 87522d8 2025-09-17 · 0.3.6_alpha (first tag v0.4.0-alpha) — first written unscoped under `@layer plugins > luci-app-openclash` (applied on every page); 7d9f6a1 merged `_plugins.css` into `_patches.css`; 1c924cf scoped it to this page (PR #82: "openclash `.diag-style` → settings"); native via e14cfcd -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-services-passwall.md b/luci-theme-aurora/.dev/compat/pages/admin-services-passwall.md deleted file mode 100644 index 85bba9fd..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-services-passwall.md +++ /dev/null @@ -1,14 +0,0 @@ -# admin-services-passwall - -## td-global-max-width — a global `max-w-94` on every table cell -- page: admin-services-passwall-node_list · Services → PassWall → Node List (controller passwall.lua:39 entry title "Node List") — the page that got the rule removed; the page it was added for is not recorded -- package: luci-app-passwall (xiaorouji; the ImmortalWrt feed copy was checked) -- dom: `.table td, .table .td` (global) — on Node List the `td.cbi-section-actions` cell holds the row's action buttons -- symptom: on removal — 50c2b84 subject: "Services => passwall => Node List cbi-section-actions: Fix overflow beyond td max width" (the action buttons ran past the capped cell). On addition — not recorded -- cause: addition: unknown (efa07d8's body describes two other changes — "Removed conflicting styling that prevented setting `overflow-auto`, which was necessary to maintain the sticky positioning of `th` elements" and hiding `.cbi-section-table-descr` on the Bridge VLAN page — and says nothing about `max-w-94`, which the diff adds to td alongside `max-md:max-w-full` and col caps). Removal: the fixed cap could not hold the Node List action cell (50c2b84 subject); d276fd3 later restates the lesson: "the fix avoids applying a global maximum width to table data cells (`td`) to prevent regressions in CBI section actions (e.g., in Services -> passwall -> Node List)" -- fix: (historic, main.css `& td, & .td`) `max-w-94` · efa07d8 2025-09-18 · 0.3.7_alpha (first tag v0.4.0-alpha) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: n/a · status: removed 50c2b84 (2025-10-12 "fix: table content overflow", 0.5.8_beta, first tag v0.6.0_beta). The same commit added `.td.cbi-value-field { break-all }` as the replacement overflow guard for "System => (Software, Mount Points)" and "Network => Wireless host" — see `admin-services-dockerman.md`; per-page caps came back scoped: `[data-page="admin-system-mounts"]` (d276fd3, `admin-system-mounts.md`) and `[id*="status_leases"]` (80be54c, `admin-status-overview.md`) - -See also: bbb355b 2025-10-26 "fix: resolve tooltip flicker and add footer spacing" — body: "added top margin to the footer to avoid overlap with main content in plugins that lack proper view containers (e.g., PassWall)"; a global `footer` rule (currently _layout.css line 644), not traced further here. diff --git a/luci-theme-aurora/.dev/compat/pages/admin-services-samba4.md b/luci-theme-aurora/.dev/compat/pages/admin-services-samba4.md deleted file mode 100644 index d283801c..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-services-samba4.md +++ /dev/null @@ -1,23 +0,0 @@ -# admin-services-samba4 - -## samba4-cell-padding — tighter th/td padding inside the Network Shares form -- page: admin-services-samba4 · Services → Network Shares (title from luci-app-samba4 menu.d; 1dbd95a writes it as "NAS => Network Shares => Shared Directories") -- package: stock luci-app-samba4 -- dom: `#cbi-samba4` (id of `form.Map('samba4')`, samba4.js:23) containing the `sambashare` TableSection "Shared Directories" (samba4.js:93); rule hits every `th/.th` and `td/.td` under it -- symptom: not recorded (1dbd95a subject: "Reduce cell padding in NAS => Network Shares => Shared Directories") -- cause: unknown (commit 1dbd95a has subject only; no symptom or measurement) -- fix: components/_table.css `#cbi-samba4 &` (nested under `& th, & .th`, line 114-116, and under `& td, & .td`, line 148-150) `px-0.5 py-1.5` · 1dbd95a 2025-10-17 · 0.5.14_beta (first tag v0.6.0_beta) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -## samba4-section-overflow — horizontal scroll on the samba4 card -- page: admin-services-samba4 · Services → Network Shares (menu path inferred from the page name) -- package: stock luci-app-samba4 -- dom: `#cbi-samba4 .cbi-section` -- symptom: not recorded (2e1d18a subject: "table overflow issue on samba4, package, and autoreboot pages") -- cause: unknown (commit 2e1d18a has subject only). The diff shows the section went from `overflow-x-auto` to `overflow-visible` globally and got `#cbi-samba4 & { @apply overflow-x-auto; }` back for this page only, alongside dropping `table-fixed` from `.table` -- fix: (historic, main.css `.cbi-section`) `#cbi-samba4 & { @apply overflow-x-auto; }` · 2e1d18a 2025-08-31 · 0.1.3_alpha (first tag v0.2.0-alpha) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: n/a · status: removed 6b9b328 (2025-09-03 "feat: make dropdown fill based on content, simplify table" — `.cbi-section` went back to global `overflow-x-auto`, so the per-page override was deleted with it) diff --git a/luci-theme-aurora/.dev/compat/pages/admin-statistics-graphs.md b/luci-theme-aurora/.dev/compat/pages/admin-statistics-graphs.md deleted file mode 100644 index a2cfa2ae..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-statistics-graphs.md +++ /dev/null @@ -1,12 +0,0 @@ -# admin-statistics-graphs - -## rrd-graphs-dark — invert and hue-rotate the rendered graph images in dark mode -- page: admin-statistics-graphs · Statistics → Graphs (menu.d title "Graphs"; edf378d: "Affected pages: Statistics => Graphs") -- package: stock luci-app-statistics -- dom: `[data-plugin] img` — the per-plugin tab containers built in graphs.js:75 (`'data-plugin': plugin`) holding the rrdtool PNGs; dark scope is `[data-darkmode="true"]` on `` -- symptom: not recorded beyond "Adapt img background color for dark mode" (edf378d body) -- cause: edf378d body: "Adapt img background color for dark mode" — the graphs are server-rendered images whose light background does not follow the theme; nothing further recorded -- fix: patches/admin-statistics-graphs.css line 8-10 `[data-darkmode="true"] [data-page="admin-statistics-graphs"] [data-plugin] img { filter: hue-rotate(150deg) invert(100%); }` · edf378d 2025-10-17 · 0.5.16_beta (first tag v0.6.0_beta) — written as `@layer luci-app-statistics { [data-page=…] [data-plugin] img { @apply dark:hue-rotate-150 dark:invert } }` in main.css; `_plugins.css` after aedf3dc, merged into `_patches.css` by 7d9f6a1, own file via 1c924cf, native via e14cfcd (the e14cfcd body cites this file: "the two-rule statistics patch alone went 1,609 B → 110 B") -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-status-logs.md b/luci-theme-aurora/.dev/compat/pages/admin-status-logs.md deleted file mode 100644 index 2b9e35ca..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-status-logs.md +++ /dev/null @@ -1,12 +0,0 @@ -# admin-status-logs - -## log-viewer — parse the read-only `#syslog` textarea into a column-aligned, colour-coded view -- page: admin-status-logs (prefix; covers `admin-status-logs-syslog`, `admin-status-logs-dmesg` and the bare `/logs` alias) · Status → System Log / Kernel Log (menu.d: "admin/status/logs" "System Log" alias → "…/syslog" "System Log", "…/dmesg" "Kernel Log") -- package: stock luci-mod-status -- dom: `textarea#syslog` inside `#content_syslog`; the patch inserts `div.syslog-view` (rows `.log-row.lv-*` with `.log-time/.log-sev/.log-tag/.log-msg`) after the textarea and adds `.log-enhanced` to the container. Styling lives in components/_syslog.css in main.css, not in a patch -- symptom: none — this is an enhancement, not a breakage fix (a5b44da: "The first payload reworks the System/Kernel Log pages") -- cause: a5b44da body: "the read-only #syslog textarea stays in place as LuCI's polled data source while a dirty-checked viewer parses each line (classic logread and the bracketed RPC format, whitelist-gated) into aligned time/level/source columns with per-severity colors, whole lines scrolling sideways, and a flash-free takeover via an insertion observer. Unknown formats trip a parse gate and the stock textarea simply shows again. One admin-status-logs name covers both tabs on every supported release — 23.05, 24.10 and master all mount the pages under admin/status/logs/*." Why the CSS is not a patch: "The viewer's CSS is core-page styling, not third-party compat, so it lives in components/_syslog.css inside main.css where the full utility pipeline applies" -- fix: src/resource/patches/admin-status-logs.js (whole file; router lifecycle `window.luciPatches["admin-status-logs"] = { mount, unmount }` at line 292-295, `mount()` at line 296) · a5b44da 2026-07-27 · 1.1.7 (first tag v1.2.0). Follow-ups: ee16953 2026-07-29 (1.1.9) "contain select-all, follow the tail, leave dmesg unsplit" — Ctrl+A grabbed the whole page, tail-follow when pinned to the bottom, dmesg rendered verbatim because "kernel lines have no uniform tag grammar"; e681ecb 2026-07-29 (1.1.10) "render every log token verbatim, copies byte-identical" — timestamps/colons were being rewritten, now "joining the rendered tokens with single spaces reproduces the source line byte for byte, and a test pins that round-trip"; 664c795 2026-08-16 (1.2.1) and e748f7c 2026-08-26 (1.2.6) wired the mount/unmount lifecycle for the same-document router (subjects only read) -- verified: a5b44da: "Node tests pin the parser against each format family and the payload's home" (`.dev/tests/log-patch.test.js`); e681ecb: round-trip test. No rendering measurement recorded -- fixture: none (backfill; DOM snapshot exists in `.dev/mocks/admin-status-logs-syslog.html`) -- issue: — · mirror: pending · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-status-overview.md b/luci-theme-aurora/.dev/compat/pages/admin-status-overview.md deleted file mode 100644 index bf369a08..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-status-overview.md +++ /dev/null @@ -1,34 +0,0 @@ -# admin-status-overview - -## leases-td-max-width — cap DHCP lease cells so DUID/IAID columns cannot widen the table -- page: admin-status-overview · Status → Overview, "Active DHCP Leases" / "Active DHCPv6 Leases" tables (luci-mod-status 40_dhcp.js:110 `#status_leases`, :169 `#status_leases6`; `[id*=]` matches both). The commit subject says "DHCP > Leases"; the ids exist only in this status include -- package: stock luci-mod-status -- dom: `.table[id*="status_leases"] .td` (class `table leases` / `table leases6`, div-based `.td` cells) -- symptom: table overflow from the DUID/IAID columns (80be54c subject) -- cause: unknown (commit 80be54c has subject only; no DOM or widths recorded) -- fix: components/_table.css `&[id*="status_leases"] { & .td { … } }` (line 137-141) `max-w-62 max-md:max-w-full` · 80be54c 2025-12-12 · 0.9.1_beta (first tag v0.10.0) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -## section-actions-mobile — action-button cell spans the mobile card, buttons share the row -- page: admin-status-overview · Status → Overview → Active DHCP Leases; also System → Mount Points and Network → Interfaces / Wireless / Firewall (all five listed in e86b70f) -- package: stock luci-mod-status / luci-mod-system / luci-mod-network (per the pages listed) -- dom: `.table td.cbi-section-actions` (`> div` wrapper, `> div > .cbi-button`) and `.table td > .cbi-button` -- symptom: not recorded (e86b70f subject: "cbi-button display on mobile for cell view") -- cause: unknown (commit e86b70f has subject only) -- fix: components/_table.css `&.cbi-section-actions` nested under `& td, & .td` (line 190-200) `max-md:flex-[0_0_100%]`, `& > div` `max-md:w-full`, `& > div > .cbi-button` `max-md:flex-1`; plus `& > .cbi-button` (line 202-204) `max-md:w-full` · e86b70f 2025-10-17 · 0.5.15_beta (first tag v0.6.0_beta) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: pending · status: active - -## section-actions-mobile-v0 — original scaffold rule for the actions cell on mobile -- page: unknown (076281f is the initial scaffold commit; no page recorded) -- package: unknown -- dom: `.table td.cbi-section-actions` (`& div`, `& .btn, & .cbi-button`) and a sibling `.td.cbi-section-actions { p-2 max-md:p-1 … }` block in the button layer -- symptom: not recorded -- cause: unknown (076281f "chore: setup luci-theme-aurora with Vite and TailwindCSS" has subject only) -- fix: (historic, main.css) `&.cbi-section-actions { @apply max-md:mt-3 max-md:border-t max-md:pt-3; & div { max-md:flex max-md:flex-wrap max-md:justify-start max-md:gap-2 } & .btn, & .cbi-button { max-md:min-w-0 max-md:flex-1 … } }` · 076281f 2025-08-25 · 0.1.0 (first tag v0.2.0-alpha) -- verified: not measured (no record) -- fixture: none (backfill) -- issue: — · mirror: n/a · status: removed 386dec5 (2025-08-30 "feat: optimize mobile display for table" rewrote the mobile table block and dropped it; the `.td.cbi-section-actions` button-layer block was dropped by 4c99ac8 2025-09-05 "chore: adjust button nesting style structure", which replaced it with the generic `.cbi-section-actions > div { flex flex-row … }`). e86b70f re-added a different rule seven weeks later — see the entry above diff --git a/luci-theme-aurora/.dev/compat/pages/admin-system-diskman.md b/luci-theme-aurora/.dev/compat/pages/admin-system-diskman.md deleted file mode 100644 index 496a2102..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-system-diskman.md +++ /dev/null @@ -1,12 +0,0 @@ -# admin-system-diskman - -## diskman-partition-bar — keep the injected partition bar inside the card on small screens, clip segment labels -- page: admin-system-diskman (prefix; also `-partition-`, `-btrfs-`) · System → Disk Man (controller diskman.lua:24 entry title "Disk Man", alias to `disks`; issue #58 calls it the storage area on the home page) -- package: luci-app-diskman (lisaac; the ImmortalWrt feed copy was checked) -- dom: `td[colspan]:has(> div[title])` and `td[colspan] > div[title]`, `.tr > div[style*="nowrap"] > div[title]` — disk_info.htm:34/88 emit `
    ` and :36 `
    `, with one inline-block `div[title]` per partition sized in percent -- symptom: issue #58: "首页的存储区域会超出宽度,导致页面可以左右滑动" (the storage area exceeds the width; page scrolls sideways), Safari 26 / iOS 26, OpenWrt 24.10.5, theme 0.11; 49fff90 body: "drags the page ~300px wide" -- cause: 49fff90 body: "luci-app-diskman injects the partition bar as a full-span row whose cell carries an inline white-space:nowrap. Once .tr becomes a flex row on mobile, that cell's automatic minimum size is its min-content — the whole unwrapped bar — so it cannot shrink and drags the page ~300px wide (reported in #58 with the page DOM). … clip each segment so its label stops spilling onto the neighbouring one (visible on desktop too)". The file adds: "The segments are inline-blocks sized in percent: any whitespace between them adds a word space on top of the 100% they already sum to" (hence `font-size: 0` on the cell) -- fix: patches/admin-system-diskman.css line 9-35 `[data-page^="admin-system-diskman"] { td[colspan]:has(> div[title]) { flex: 0 0 100%; min-width: 0; overflow: hidden; border-radius: var(--radius-base); font-size: 0 } td[colspan] > div[title], .tr > div[style*="nowrap"] > div[title] { overflow: hidden; font-size: 0.75rem; line-height: 1.5rem; text-overflow: ellipsis } }` · 49fff90 2026-08-02 · 1.1.13 (first tag v1.2.0) -- verified: not measured (the body states the before width, "~300px wide", from the reporter's DOM; no after-number recorded) -- fixture: none (backfill; DOM snapshot exists in `.dev/mocks/admin-system-diskman.html`) -- issue: #58 · mirror: pending · status: active diff --git a/luci-theme-aurora/.dev/compat/pages/admin-system-filemanager.md b/luci-theme-aurora/.dev/compat/pages/admin-system-filemanager.md deleted file mode 100644 index aa7dc893..00000000 --- a/luci-theme-aurora/.dev/compat/pages/admin-system-filemanager.md +++ /dev/null @@ -1,12 +0,0 @@ -# admin-system-filemanager - -## filemanager-container-scroll — scrollable file-manager container, flat status bar -- page: admin-system-filemanager · System → File Manager (menu.d title "File Manager") -- package: luci-app-filemanager (in openwrt/luci applications) -- dom: `#file-manager-container` (the app's own ` - {% endif %} - - {% if (favicon_png): %} - - {% endif %} - - - - - - - - - {% if (dispatched?.css): %} - - {% endif %} - {% if (css): %} - - {% endif %} - {% if (token_css_light || token_css_dark): %} - - {% endif %} - {% if (!blank_page): %} - - - {% endif %} - - - - {% if (!blank_page): %} - {% if (nav_type == 'sidebar'): %} - {# First in body: once anything resolves body's style (the page-bg script does), the column would ease shut on load. #} - - {% endif %} - {% if (tokens.struct_main_bg): %} - - - {% endif %} -
    -
    - - {{ hostname }} - - {% if (nav_type == 'sidebar'): %} -
      - {% endif %} - -
      -
      - - {% if (nav_type == 'mega-menu'): %} - {% - /* boardinfo fields are not guaranteed on every platform; the - summary tolerates a missing model/firmware line (hostname is - always set by the kernel). */ - const board_model = boardinfo.model ?? boardinfo.system ?? boardinfo.board_name; - const board_firmware = boardinfo.release?.description ?? - trim(`${boardinfo.release?.distribution ?? ''} ${boardinfo.release?.version ?? ''}`); - -%} -
      - {# - Curtain-reveal layer pair: .desktop-menu-sheet is the opaque - surface that slides down (translateY -100% → 0) and clips its - content; .desktop-menu-canvas counter-translates (100% → 0) so - the panels menu-aurora.js reparents into it appear static while - the sheet edge wipes over them — see _layout.css. - #} -
      - -
      -
      - -
      - {% else %} - - {% endif %} - - {% if (nav_type == 'sidebar'): %} - - {% endif %} - - -
      - -
      - - {% if (toolbar_enabled && length(toolbar_items)): %} -
      -
      - {% for (let i = 0; i < length(toolbar_items); i++): %} - {% let item = toolbar_items[i]; %} - - - - {% endfor %} -
      - - {# - The tooltip is a short state-dependent verb — "Hide" while the - shortcuts are shown, "Show" once collapsed. Both strings ship - in luci-base's po (the theme carries none of its own); the - verbose static label stays on aria-label only. - #} - -
      - - - {% endif %} - -
      - {% if (getuid() == 0 && getspnam('root')?.pwdp === ''): %} -
      -

      {{ _('No password set!') }}

      -

      {{ _('There is no password set on this router. Please configure a root password to protect the web interface.') }}

      - {% if (dispatcher.lookup("admin/system/admin")): %} - - {% endif %} -
      - {% endif %} - - {% if (boardinfo.rootfs_type == "initramfs"): %} -
      -

      {{ _('System running in recovery (initramfs) mode.') }}

      -

      {{ _('No changes to settings will be stored and are lost after rebooting. This mode should only be used to install a firmware upgrade') }}

      - {% if (dispatcher.lookup("admin/system/flash")): %} - - {% endif %} -
      - {% endif %} - - - - - {% endif %} diff --git a/luci-theme-aurora/ucode/template/themes/aurora/sysauth.ut b/luci-theme-aurora/ucode/template/themes/aurora/sysauth.ut deleted file mode 100644 index 121e4add..00000000 --- a/luci-theme-aurora/ucode/template/themes/aurora/sysauth.ut +++ /dev/null @@ -1,90 +0,0 @@ -{# - luci-theme-aurora: - Copyright 2025 eamonxg - This theme is derived from luci-theme-bootstrap UT template. - luci-theme-bootstrap: - Copyright 2022 Jo-Philipp Wich - Licensed to the public under the Apache License 2.0. --#} - -{% -import { cursor } from 'uci'; -const boardinfo = ubus.call('system', 'board') ?? {}; -const themeTokens = cursor().get_all('aurora', 'theme') || {}; -const loginLogoSvg = themeTokens.logo_svg || 'logo.svg'; -const loginIconVer = themeTokens.icon_cache_version || '0'; --%} -{% include('header', { - blank_page: true, - prefetched_boardinfo: boardinfo, - prefetched_tokens: themeTokens -}) %} - -{% if (themeTokens.struct_login_bg): %} - -{% endif %} - -
      - - - -
      - - - -{% include('footer', { blank_page: true }) %} diff --git a/v2ray-geodata/Makefile b/v2ray-geodata/Makefile index a87f099f..e63fe26a 100644 --- a/v2ray-geodata/Makefile +++ b/v2ray-geodata/Makefile @@ -21,13 +21,13 @@ define Download/geoip HASH:=4ff4b2ec242a9e87b296ba27ddb85f8311e8d3e071eaebac5be9231c60e408dd endef -GEOSITE_VER:=20261020081451 +GEOSITE_VER:=20261020135944 GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER) define Download/geosite URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/ URL_FILE:=dlc.dat FILE:=$(GEOSITE_FILE) - HASH:=e687d2f31f16ddb759eb250187230354ab0542407fd786fbe9483f2302002671 + HASH:=bddbeb5f0980a7c852a79e5ae403757199157bb61d7f3b6640cce8a4c83b8e7b endef GEOSITE_IRAN_VER:=202610120242