🌈 Sync 2026-09-24 15:19:50

This commit is contained in:
github-actions[bot] committed 2026-09-24 15:19:50 +08:00
1 parent 765ac2b267
commit 87101cc7f2
126 files changed
+4403 -2879

No files matched your search

@@ -27,22 +27,10 @@
</footer>
</div>
</div>
<script>
// thanks for Jo-Philipp Wich <jow@openwrt.org>
var luciLocation = {{ ctx.path }};
var winHeight = window.innerHeight;
window.addEventListener('resize', function () {
var winWidth = window.innerWidth;
if(winWidth < 600){
var newHeight = window.innerHeight;
var keyboradHeight = newHeight - winHeight;
var ftcElement = document.querySelector(".ftc");
if (ftcElement) {
ftcElement.style.bottom = (keyboradHeight + 30) + "px";
}
}
});
</script>
<script>
// thanks for Jo-Philipp Wich <jow@openwrt.org>
var luciLocation = {{ ctx.path }};
</script>
<script type="text/javascript">L.require('menu-argon')</script>
</body>
</html>
@@ -25,27 +25,15 @@
</footer>
</div>
</div>
<script>
// thanks for Jo-Philipp Wich <jow@openwrt.org>
var luciLocation = {{ ctx.path }};
var winHeight = window.innerHeight;
window.addEventListener('resize', function () {
var winWidth = window.innerWidth;
if(winWidth < 600){
var newHeight = window.innerHeight;
var keyboradHeight = newHeight - winHeight;
var ftcElement = document.querySelector(".ftc");
if (ftcElement) {
ftcElement.style.bottom = (keyboradHeight + 30) + "px";
}
}
});
<script>
// thanks for Jo-Philipp Wich <jow@openwrt.org>
var luciLocation = {{ ctx.path }};
const loginContainer = document.querySelector(
'div[class="login-container"][style*="backdrop-filter: blur(0px)"]'
);
if (loginContainer) {
loginContainer.style.margin = '0 auto';
}
</script>
</script>
</body>
</html>
@@ -17,7 +17,7 @@
-#}
{%
import { readfile, access } from 'fs';
import { access } from 'fs';
import { cursor } from 'uci';
import { getuid, getspnam } from 'luci.core';
@@ -30,37 +30,50 @@
http.prepare_content('text/html; charset=UTF-8');
//Custom settings
let mode = 'normal';
let bar_color = '#5e72e4';
let primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity, blur_opacity_dark;
const dark_css = readfile('/www/luci-static/argon/css/dark.css');
if (access('/etc/config/argon')) {
primary = cfg.get_first('argon', 'global', 'primary');
dark_primary = cfg.get_first('argon', 'global', 'dark_primary');
blur_radius = cfg.get_first('argon', 'global', 'blur');
blur_radius_dark = cfg.get_first('argon', 'global', 'blur_dark');
blur_opacity = cfg.get_first('argon', 'global', 'transparency');
blur_opacity_dark = cfg.get_first('argon', 'global', 'transparency_dark');
mode = cfg.get_first('argon', 'global', 'mode');
bar_color = (mode == 'dark') ? dark_primary : primary;
function validColor(value, fallback) {
return type(value) == 'string' && match(value, /^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/) ? value : fallback;
}
function validNumber(value, fallback, maximum) {
return type(value) == 'string' && match(value, /^(0|[1-9][0-9]*)(\.[0-9]+)?$/) && +value <= maximum ? value : fallback;
}
let mode = 'normal';
let primary = '#5e72e4';
let dark_primary = '#483d8b';
let blur_radius = '10';
let blur_radius_dark = '10';
let blur_opacity = '0.5';
let blur_opacity_dark = '0.5';
const has_argon_config = access('/etc/config/argon');
if (has_argon_config) {
primary = validColor(cfg.get_first('argon', 'global', 'primary'), primary);
dark_primary = validColor(cfg.get_first('argon', 'global', 'dark_primary'), dark_primary);
blur_radius = validNumber(cfg.get_first('argon', 'global', 'blur'), blur_radius, 100);
blur_radius_dark = validNumber(cfg.get_first('argon', 'global', 'blur_dark'), blur_radius_dark, 100);
blur_opacity = validNumber(cfg.get_first('argon', 'global', 'transparency'), blur_opacity, 1);
blur_opacity_dark = validNumber(cfg.get_first('argon', 'global', 'transparency_dark'), blur_opacity_dark, 1);
let configured_mode = cfg.get_first('argon', 'global', 'mode');
if (configured_mode == 'normal' || configured_mode == 'dark' || configured_mode == 'light')
mode = configured_mode;
}
const bar_color = mode == 'dark' ? dark_primary : primary;
-%}
<!DOCTYPE html>
<html lang="{{ dispatcher.lang }}"{% if (mode == 'light'): %} data-darkmode="false"{% else %} data-darkmode="true"{% endif %}>
<html lang="{{ dispatcher.lang }}"{% if (mode == 'dark'): %} data-darkmode="true"{% elif (mode == 'light'): %} data-darkmode="false"{% endif %}>
<head>
{% include("themes/" + theme + "/head_meta", { hostname: hostname, node: node, bar_color: bar_color, media: media }) %}
<link rel="stylesheet" href="{{ media }}/css/cascade.css{# ?v=PKG_VERSION #}">
{% if (mode == 'normal'): %}
<link rel="stylesheet" href="{{ media }}/css/dark.css{# ?v=PKG_VERSION #}" media="(prefers-color-scheme: dark)">
{% elif (mode == 'dark'): %}
<link rel="stylesheet" href="{{ media }}/css/dark.css{# ?v=PKG_VERSION #}">
{% endif %}
<style title="text/css">
{% if (mode == 'normal'): %}
{{ dark_css }}
{% endif %}
{% if (mode == 'dark'): %}
{{ dark_css }}
{% endif -%}
{% if (access('/etc/config/argon')): %}
{% if (has_argon_config): %}
:root {
--primary: {{ primary }};
--dark-primary: {{ dark_primary }};
@@ -111,7 +124,7 @@
<div class="fill">
<div class="container">
<div class="flex1">
<a class="showSide"></a>
<button type="button" class="showSide" aria-label="{{ entityencode(_('Toggle navigation'), true) }}" aria-controls="mainmenu" aria-expanded="false"></button>
<a class="brand" href="#">{{ hostname }}</a>
</div>
<div class="status" id="indicators"></div>
@@ -17,7 +17,7 @@
-#}
{%
import { readfile, access } from 'fs';
import { access } from 'fs';
import { cursor } from 'uci';
const boardinfo = ubus.call("system", "board");
@@ -29,37 +29,50 @@
http.prepare_content('text/html; charset=UTF-8');
//Custom settings
let mode = 'normal';
let bar_color = '#5e72e4';
let primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity, blur_opacity_dark;
const dark_css = readfile('/www/luci-static/argon/css/dark.css');
if (access('/etc/config/argon')) {
primary = cfg.get_first('argon', 'global', 'primary');
dark_primary = cfg.get_first('argon', 'global', 'dark_primary');
blur_radius = cfg.get_first('argon', 'global', 'blur');
blur_radius_dark = cfg.get_first('argon', 'global', 'blur_dark');
blur_opacity = cfg.get_first('argon', 'global', 'transparency');
blur_opacity_dark = cfg.get_first('argon', 'global', 'transparency_dark');
mode = cfg.get_first('argon', 'global', 'mode');
bar_color = (mode == 'dark') ? dark_primary : primary;
function validColor(value, fallback) {
return type(value) == 'string' && match(value, /^#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?$/) ? value : fallback;
}
function validNumber(value, fallback, maximum) {
return type(value) == 'string' && match(value, /^(0|[1-9][0-9]*)(\.[0-9]+)?$/) && +value <= maximum ? value : fallback;
}
let mode = 'normal';
let primary = '#5e72e4';
let dark_primary = '#483d8b';
let blur_radius = '10';
let blur_radius_dark = '10';
let blur_opacity = '0.5';
let blur_opacity_dark = '0.5';
const has_argon_config = access('/etc/config/argon');
if (has_argon_config) {
primary = validColor(cfg.get_first('argon', 'global', 'primary'), primary);
dark_primary = validColor(cfg.get_first('argon', 'global', 'dark_primary'), dark_primary);
blur_radius = validNumber(cfg.get_first('argon', 'global', 'blur'), blur_radius, 100);
blur_radius_dark = validNumber(cfg.get_first('argon', 'global', 'blur_dark'), blur_radius_dark, 100);
blur_opacity = validNumber(cfg.get_first('argon', 'global', 'transparency'), blur_opacity, 1);
blur_opacity_dark = validNumber(cfg.get_first('argon', 'global', 'transparency_dark'), blur_opacity_dark, 1);
let configured_mode = cfg.get_first('argon', 'global', 'mode');
if (configured_mode == 'normal' || configured_mode == 'dark' || configured_mode == 'light')
mode = configured_mode;
}
const bar_color = mode == 'dark' ? dark_primary : primary;
-%}
<!DOCTYPE html>
<html lang="{{ dispatcher.lang }}"{% if (mode == 'light'): %} data-darkmode="false"{% else %} data-darkmode="true"{% endif %}>
<html lang="{{ dispatcher.lang }}"{% if (mode == 'dark'): %} data-darkmode="true"{% elif (mode == 'light'): %} data-darkmode="false"{% endif %}>
<head>
{% include("themes/" + theme + "/head_meta", { hostname: hostname, node: node, bar_color: bar_color, media: media }) %}
<link rel="stylesheet" href="{{ media }}/css/cascade.css{# ?v=PKG_VERSION #}">
{% if (mode == 'normal'): %}
<link rel="stylesheet" href="{{ media }}/css/dark.css{# ?v=PKG_VERSION #}" media="(prefers-color-scheme: dark)">
{% elif (mode == 'dark'): %}
<link rel="stylesheet" href="{{ media }}/css/dark.css{# ?v=PKG_VERSION #}">
{% endif %}
<style title="text/css">
{% if (mode == 'normal'): %}
{{ dark_css }}
{% endif %}
{% if (mode == 'dark'): %}
{{ dark_css }}
{% endif -%}
{% if (access('/etc/config/argon')): %}
{% if (has_argon_config): %}
:root {
--primary: {{ primary }};
--dark-primary: {{ dark_primary }};
@@ -45,11 +45,12 @@
function fetchMedia(path, themeDir) {
let backgroundTable = [];
for (f in (fs.lsdir(path))) {
let ext = lc(split(f, '.')?.[1]);
let parts = split(f, '.');
let ext = lc(parts?.[length(parts) - 1]);
if (ext && index(allTypes, " " + ext + " ") != -1) {
let bg = {};
bg.type = ext;
bg.url = themeDir + f;
bg.url = themeDir + http.urlencode(f);
push(backgroundTable, bg);
}
}
@@ -65,7 +66,7 @@
let online_wallpaper = cfg.get_first('argon', 'global', 'online_wallpaper') ?? (cfg.get_first('argon', 'global', 'bing_background') == '1' ? 'bing' : null);
if (online_wallpaper && online_wallpaper != "none") {
const picurl = ubus.call("luci.argon_wallpaper", "get_url") ?? {};
if (picurl?.url) {
if (type(picurl?.url) == 'string' && match(picurl.url, /^https:\/\/[^[:space:]"'<>]+$/)) {
bgUrl = picurl.url;
return {bgUrl, backgroundType, mimeType};
}
@@ -96,19 +97,39 @@
{% if ( bgArry.backgroundType == "Video" ): %}
<!-- Video Player Start -->
<div class="video">
<video autoplay loop muted id="video">
<source src="{{ bgArry.bgUrl }}" type="{{ bgArry.mimeType }}">
<video loop muted playsinline id="video" poster="{{ media }}/img/bg1.jpg">
<source src="{{ entityencode(bgArry.bgUrl, true) }}" type="{{ bgArry.mimeType }}">
</video>
</div>
<div class="volume-control mute"></div>
<button type="button" class="volume-control mute" aria-label="{{ entityencode(_('Mute background video'), true) }}" aria-pressed="true"></button>
<script>
var backgroundVideo = document.getElementById("video");
var motionPreference = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)');
function updateBackgroundMotion() {
if (motionPreference && motionPreference.matches)
backgroundVideo.pause();
else {
var playResult = backgroundVideo.play();
if (playResult && playResult.catch)
playResult.catch(function() {});
}
}
updateBackgroundMotion();
if (motionPreference) {
if (motionPreference.addEventListener)
motionPreference.addEventListener('change', updateBackgroundMotion);
else if (motionPreference.addListener)
motionPreference.addListener(updateBackgroundMotion);
}
document.querySelector(".volume-control").addEventListener("click", function(){
if(this.classList.contains("mute")){
this.classList.remove("mute");
document.getElementById("video").muted = false;
backgroundVideo.muted = false;
this.setAttribute('aria-pressed', 'false');
}else{
this.classList.add("mute");
document.getElementById("video").muted = true;
backgroundVideo.muted = true;
this.setAttribute('aria-pressed', 'true');
}
});
</script>
@@ -116,7 +137,8 @@
{% else %}
<!-- Image Background Start -->
{% online_wallpaper = cfg.get_first('argon', 'global', 'online_wallpaper') ?? 'default' %}
<div class="main-bg" id="main-bg" {% if (online_wallpaper != 'default'): %}style="background-image:url({{ bgArry.bgUrl }})"{% endif %}></div>
<div class="main-bg" id="main-bg"><img src="{{ entityencode(bgArry.bgUrl, true) }}" data-fallback="{{ media }}/img/bg1.jpg" onerror="this.onerror=null;this.src=this.dataset.fallback" alt=""></div>
<div class="main-bg" id="main-bg">{% if (online_wallpaper != 'default'): %}<img src="{{ entityencode(bgArry.bgUrl, true) }}" data-fallback="{{ media }}/img/bg1.jpg" onerror="this.onerror=null;this.src=this.dataset.fallback" alt="">{% endif %}</div>
<!-- Image Background End -->
{% endif %}
<!-- Login Container Start -->
@@ -128,25 +150,70 @@
</a>
<!-- Logo End -->
<!-- Login Form Start -->
<form class="form-login" method="post" action="{{ http.getenv("REQUEST_URI") }}">
<form class="form-login" method="post" action="{{ entityencode(http.getenv("REQUEST_URI"), true) }}">
{%- if (fuser): %}
{#-
`auth_plugin` is set only on the render that follows an ACCEPTED password
(dispatcher.uc), so it is what separates "the password was wrong" from "the
password was right and a plugin wants more". Gating the credentials alert on
`!auth_plugin` and showing `auth_message` beside it rather than instead of it
covers all four states: a wrong password, a wrong password with a challenge
already pending, the challenge prompt itself, and a failed challenge.
-#}
{%- if (fuser && !auth_plugin): %}
<div class="errorbox">{{ _('Invalid username and/or password! Please try again.') }}</div>
{% endif -%}
{%- if (auth_message): %}
<div class="errorbox">{{ auth_message }}</div>
{% endif -%}
<div class="input-container">
<div class="input-group user-icon">
<label class="visually-hidden" for="cbi-input-user">{{ _('Username') }}</label>
<input class="cbi-input-user" id="cbi-input-user" type="text" name="luci_username" value="{{ entityencode(duser, true) }}" />
<label class="border" for="cbi-input-user"></label>
<span class="border" aria-hidden="true"></span>
</div>
<div class="input-group pass-icon">
<label class="visually-hidden" for="cbi-input-password">{{ _('Password') }}</label>
<input class="cbi-input-password" id="cbi-input-password" type="password" name="luci_password" />
<label class="border" for="cbi-input-password"></label>
<span class="border" aria-hidden="true"></span>
</div>
{%- if (auth_fields): %}
{%- for (let field in auth_fields): %}
{#- Keep a plugin's format hint as the placeholder, while its label or
field name provides an accessible name for the input. -#}
<div class="input-group pass-icon">
<label class="visually-hidden" for="{{ entityencode(field.name, true) }}">{{ entityencode(_(field.label || field.name)) }}</label>
<input class="cbi-input-text" id="{{ entityencode(field.name, true) }}" type="{{ entityencode(field.type ?? 'text', true) }}" name="{{ entityencode(field.name, true) }}"
placeholder="{{ entityencode(_(field.label ?? field.placeholder ?? field.name), true) }}"
{% if (field.placeholder): %}title="{{ entityencode(field.placeholder, true) }}"{% endif %}
{% if (field.inputmode): %}inputmode="{{ entityencode(field.inputmode, true) }}"{% endif %}
{% if (field.pattern): %}pattern="{{ entityencode(field.pattern, true) }}"{% endif %}
{% if (field.maxlength): %}maxlength="{{ entityencode('' + field.maxlength, true) }}"{% endif %}
{% if (field.autocomplete): %}autocomplete="{{ entityencode(field.autocomplete, true) }}"{% endif %}
{% if (field.required): %}required{% endif %} />
<span class="border" aria-hidden="true"></span>
</div>
{%- endfor %}
{%- endif %}
</div>
{%- if (auth_html): %}
<div class="auth-plugin">{{ auth_html }}</div>
{% endif -%}
<div>
<input type="submit" value="{{ _('Log in') }}" class="cbi-button cbi-button-apply" />
</div>
{#- Loaded last so the markup a plugin emitted through `auth_html` is already
in the document when its script runs. -#}
{%- if (auth_assets): %}
{%- for (let asset in auth_assets): %}
{%- if (asset.type == 'script'): %}
<script src="{{ asset.src }}"></script>
{%- endif %}
{%- endfor %}
{%- endif %}
</form>
<!-- Login Form End -->
<script type="text/javascript">//<![CDATA[