mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-09-11 19:05:11 +08:00
🍓 Sync 2026-08-11 20:54:16
This commit is contained in:
@@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=UnblockNeteaseMusic
|
||||
PKG_BASE_VERSION:=0.27.0
|
||||
PKG_RELEASE:=2
|
||||
PKG_RELEASE:=3
|
||||
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_URL:=https://github.com/UnblockNeteaseMusic/server.git
|
||||
PKG_SOURCE_DATE:=2022-10-09
|
||||
PKG_SOURCE_VERSION:=39e21bfb4b7581f39785b190aeced201d23f0d41
|
||||
PKG_SOURCE_VERSION:=c29ff1bfaf138afe3c41ee1be43daa91097afc9f
|
||||
PKG_MIRROR_HASH:=skip
|
||||
|
||||
PKG_VERSION:=$(PKG_BASE_VERSION)-$(PKG_SOURCE_DATE)-$(call version_abbrev,$(PKG_SOURCE_VERSION))
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ include $(TOPDIR)/rules.mk
|
||||
PKG_ARCH_BAIDUDRIVE:=$(ARCH)
|
||||
|
||||
PKG_NAME:=baidudrive
|
||||
PKG_VERSION:=linkeasefull-runtime-v3.0.5
|
||||
PKG_RELEASE:=7
|
||||
PKG_VERSION:=baidudrive-runtime-v1.0.5
|
||||
PKG_RELEASE:=8
|
||||
PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz
|
||||
PKG_SOURCE_URL:=https://github.com/istoreos/istoreos-app-hub/releases/download/baidudrive-runtime-v$(PKG_VERSION)/
|
||||
PKG_HASH:=skip
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.8.10
|
||||
PKG_RELEASE:=213
|
||||
PKG_VERSION:=26.8.11
|
||||
PKG_RELEASE:=214
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -471,7 +471,7 @@ function socks_status()
|
||||
e.use_http = 0
|
||||
if tonumber(use_http) > 0 then
|
||||
e.use_http = 1
|
||||
e.http_status = luci.sys.call(string.format("/bin/busybox top -bn1 | grep -v 'grep' | grep '/tmp/etc/passwall/bin/' | grep -v '_acl_' | grep '%s' | grep -E 'HTTP_|HTTP2SOCKS' > /dev/null", id)) == 0
|
||||
e.http_status = luci.sys.call(string.format("/bin/busybox top -bn1 | grep -v -E 'grep|acl/|acl_' | grep '%s/bin/' | grep '%s' | grep -E '\\+http|_http' > /dev/null", appname, id)) == 0
|
||||
end
|
||||
http_write_json(e)
|
||||
end
|
||||
|
||||
@@ -64,8 +64,12 @@ uci -q delete passwall.@global_xray[0].route_only
|
||||
for sid in $(uci show passwall | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}'); do
|
||||
if [ -z "$(echo ${sid} | grep '^socks_')" ]; then
|
||||
new_id="socks_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5)"
|
||||
old_ref="Socks_${sid}"
|
||||
uci -q rename passwall.${sid}="${new_id}"
|
||||
unset sid new_id
|
||||
for item in $(uci show passwall | grep "='${old_ref}'\$" | cut -d '=' -sf 1); do
|
||||
uci -q set ${item}="${new_id}"
|
||||
done
|
||||
unset sid new_id old_ref item
|
||||
fi
|
||||
done
|
||||
for sid in $(uci show passwall | grep "@acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
|
||||
|
||||
@@ -407,7 +407,7 @@ run_socks() {
|
||||
fi
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
json_add_string "local_http_address" "$bind"
|
||||
json_add_string "local_http_port" "$http_port"
|
||||
}
|
||||
@@ -438,7 +438,7 @@ run_socks() {
|
||||
sing-box)
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
local _args="http_address=$bind http_port=$http_port"
|
||||
}
|
||||
[ -n "$relay_port" ] && _args="${_args} server_host=$server_host server_port=$server_port"
|
||||
@@ -448,7 +448,7 @@ run_socks() {
|
||||
xray)
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
local _args="http_address=$bind http_port=$http_port"
|
||||
}
|
||||
[ -n "$relay_port" ] && _args="${_args} server_host=$server_host server_port=$server_port"
|
||||
@@ -471,7 +471,7 @@ run_socks() {
|
||||
ss-rust)
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
json_add_string "local_http_address" "$bind"
|
||||
json_add_string "local_http_port" "$http_port"
|
||||
}
|
||||
@@ -487,7 +487,7 @@ run_socks() {
|
||||
hysteria2)
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
json_add_string "local_http_address" "$bind"
|
||||
json_add_string "local_http_port" "$http_port"
|
||||
}
|
||||
@@ -1003,7 +1003,7 @@ start_socks() {
|
||||
local log=$(config_n_get $id log 1)
|
||||
[ "$log" = "0" ] && log_file=""
|
||||
local http_port=$(config_n_get $id http_port 0)
|
||||
local http_config_file="HTTP2SOCKS_${id}.json"
|
||||
local http_config_file="${flag}_http.json"
|
||||
local enable_autoswitch=$(config_n_get $id enable_autoswitch 0)
|
||||
local no_rec=0
|
||||
[ "$enable_autoswitch" = "1" ] && no_rec=1
|
||||
@@ -1020,16 +1020,16 @@ socks_node_switch() {
|
||||
local flag new_node
|
||||
eval_set_val "$@"
|
||||
[ -n "$flag" ] && [ -n "$new_node" ] && {
|
||||
local prefix pf filename
|
||||
local suffix pf filename
|
||||
# 结束 SS 插件进程
|
||||
for prefix in "" "HTTP_"; do
|
||||
pf="$TMP_PATH/${prefix}${flag}_plugin.pid"
|
||||
for suffix in "" "+http"; do
|
||||
pf="$TMP_PATH/${flag}${suffix}_plugin.pid"
|
||||
[ -s "$pf" ] && kill -9 "$(head -n1 "$pf")" >/dev/null 2>&1
|
||||
done
|
||||
|
||||
busybox pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1 && !/acl\/|acl_/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
for prefix in "" "HTTP_" "HTTP2"; do
|
||||
rm -rf "$TMP_PATH/${prefix}${flag}"*
|
||||
for suffix in "" "+http" "_http"; do
|
||||
rm -rf "$TMP_PATH/${flag}${suffix}"*
|
||||
done
|
||||
|
||||
for filename in $(ls ${TMP_SCRIPT_FUNC_PATH}); do
|
||||
@@ -1045,7 +1045,7 @@ socks_node_switch() {
|
||||
local log=$(config_n_get $flag log 1)
|
||||
[ "$log" = "0" ] && log_file=""
|
||||
local http_port=$(config_n_get $flag http_port 0)
|
||||
local http_config_file="HTTP2SOCKS_${flag}.json"
|
||||
local http_config_file="${flag}_http.json"
|
||||
LOG_FILE="/dev/null"
|
||||
run_socks flag=$flag node=$new_node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file
|
||||
set_cache_var "${flag}" "$new_node"
|
||||
|
||||
@@ -236,15 +236,15 @@ load_acl() {
|
||||
[ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_fakedns")" ] && use_fakedns=$(get_cache_var "ACL_${sid}_fakedns")
|
||||
[ -n "$tcp_node" ] && {
|
||||
if is_socks_wrap "$tcp_node"; then
|
||||
tcp_node_remark="Socks 配置($(config_n_get ${tcp_node#Socks_} port) 端口)"
|
||||
if [ "$(config_get_type $tcp_node)" = "socks" ]; then
|
||||
tcp_node_remark="Socks 配置($(config_n_get $tcp_node port) 端口)"
|
||||
else
|
||||
tcp_node_remark=$(config_n_get $tcp_node remarks)
|
||||
fi
|
||||
}
|
||||
[ -n "$udp_node" ] && {
|
||||
if is_socks_wrap "$udp_node"; then
|
||||
udp_node_remark="Socks 配置($(config_n_get ${udp_node#Socks_} port) 端口)"
|
||||
if [ "$(config_get_type $udp_node)" = "socks" ]; then
|
||||
udp_node_remark="Socks 配置($(config_n_get $udp_node port) 端口)"
|
||||
else
|
||||
udp_node_remark=$(config_n_get $udp_node remarks)
|
||||
fi
|
||||
@@ -256,13 +256,13 @@ load_acl() {
|
||||
[ -n "$udp_node" ] && [ "$(config_n_get $udp_node protocol)" = "_shunt" ] && use_shunt_udp=1
|
||||
|
||||
[ "${use_global_config}" = "1" ] && {
|
||||
if is_socks_wrap "$TCP_NODE"; then
|
||||
tcp_node_remark="Socks 配置($(config_n_get ${TCP_NODE#Socks_} port) 端口)"
|
||||
if [ "$(config_get_type $TCP_NODE)" = "socks" ]; then
|
||||
tcp_node_remark="Socks 配置($(config_n_get $TCP_NODE} port) 端口)"
|
||||
else
|
||||
tcp_node_remark=$(config_n_get $TCP_NODE remarks)
|
||||
fi
|
||||
if is_socks_wrap "$UDP_NODE"; then
|
||||
udp_node_remark="Socks 配置($(config_n_get ${UDP_NODE#Socks_} port) 端口)"
|
||||
if [ "$(config_get_type $UDP_NODE)" = "socks" ]; then
|
||||
udp_node_remark="Socks 配置($(config_n_get $UDP_NODE port) 端口)"
|
||||
else
|
||||
udp_node_remark=$(config_n_get $UDP_NODE remarks)
|
||||
fi
|
||||
@@ -651,8 +651,8 @@ load_acl() {
|
||||
# 加载TCP默认代理模式
|
||||
if [ -n "${TCP_PROXY_MODE}" ]; then
|
||||
[ -n "$TCP_NODE" ] && {
|
||||
if is_socks_wrap "$TCP_NODE"; then
|
||||
msg2="${msg}使用 TCP 节点[Socks 配置($(config_n_get ${TCP_NODE#Socks_} port) 端口)]"
|
||||
if [ "$(config_get_type $TCP_NODE)" = "socks" ]; then
|
||||
msg2="${msg}使用 TCP 节点[Socks 配置($(config_n_get $TCP_NODE port) 端口)]"
|
||||
else
|
||||
msg2="${msg}使用 TCP 节点[$(config_n_get $TCP_NODE remarks)]"
|
||||
fi
|
||||
@@ -710,8 +710,8 @@ load_acl() {
|
||||
# 加载UDP默认代理模式
|
||||
if [ -n "${UDP_PROXY_MODE}" ]; then
|
||||
[ -n "$UDP_NODE" ] || [ "$TCP_UDP" = "1" ] && {
|
||||
if is_socks_wrap "$UDP_NODE"; then
|
||||
msg2="${msg}使用 UDP 节点[Socks 配置($(config_n_get ${UDP_NODE#Socks_} port) 端口)](TPROXY:${UDP_REDIR_PORT})"
|
||||
if [ "$(config_get_type $UDP_NODE)" = "socks" ]; then
|
||||
msg2="${msg}使用 UDP 节点[Socks 配置($(config_n_get $UDP_NODE port) 端口)](TPROXY:${UDP_REDIR_PORT})"
|
||||
else
|
||||
msg2="${msg}使用 UDP 节点[$(config_n_get $UDP_NODE remarks)](TPROXY:${UDP_REDIR_PORT})"
|
||||
fi
|
||||
|
||||
@@ -296,15 +296,15 @@ load_acl() {
|
||||
[ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
|
||||
[ -n "$(get_cache_var "ACL_${sid}_fakedns")" ] && use_fakedns=$(get_cache_var "ACL_${sid}_fakedns")
|
||||
[ -n "$tcp_node" ] && {
|
||||
if is_socks_wrap "$tcp_node"; then
|
||||
tcp_node_remark="Socks 配置($(config_n_get ${tcp_node#Socks_} port) 端口)"
|
||||
if [ "$(config_get_type $tcp_node)" = "socks" ]; then
|
||||
tcp_node_remark="Socks 配置($(config_n_get $tcp_node port) 端口)"
|
||||
else
|
||||
tcp_node_remark=$(config_n_get $tcp_node remarks)
|
||||
fi
|
||||
}
|
||||
[ -n "$udp_node" ] && {
|
||||
if is_socks_wrap "$udp_node"; then
|
||||
udp_node_remark="Socks 配置($(config_n_get ${udp_node#Socks_} port) 端口)"
|
||||
if [ "$(config_get_type $udp_node)" = "socks" ]; then
|
||||
udp_node_remark="Socks 配置($(config_n_get $udp_node port) 端口)"
|
||||
else
|
||||
udp_node_remark=$(config_n_get $udp_node remarks)
|
||||
fi
|
||||
@@ -315,13 +315,13 @@ load_acl() {
|
||||
[ -n "$udp_node" ] && [ "$(config_n_get $udp_node protocol)" = "_shunt" ] && use_shunt_udp=1
|
||||
|
||||
[ "${use_global_config}" = "1" ] && {
|
||||
if is_socks_wrap "$TCP_NODE"; then
|
||||
tcp_node_remark="Socks 配置($(config_n_get ${TCP_NODE#Socks_} port) 端口)"
|
||||
if [ "$(config_get_type $TCP_NODE)" = "socks" ]; then
|
||||
tcp_node_remark="Socks 配置($(config_n_get $TCP_NODE port) 端口)"
|
||||
else
|
||||
tcp_node_remark=$(config_n_get $TCP_NODE remarks)
|
||||
fi
|
||||
if is_socks_wrap "$UDP_NODE"; then
|
||||
udp_node_remark="Socks 配置($(config_n_get ${UDP_NODE#Socks_} port) 端口)"
|
||||
if [ "$(config_get_type $UDP_NODE)" = "socks" ]; then
|
||||
udp_node_remark="Socks 配置($(config_n_get $UDP_NODE port) 端口)"
|
||||
else
|
||||
udp_node_remark=$(config_n_get $UDP_NODE remarks)
|
||||
fi
|
||||
@@ -709,8 +709,8 @@ load_acl() {
|
||||
# 加载TCP默认代理模式
|
||||
if [ -n "${TCP_PROXY_MODE}" ]; then
|
||||
[ -n "$TCP_NODE" ] && {
|
||||
if is_socks_wrap "$TCP_NODE"; then
|
||||
msg2="${msg}使用 TCP 节点[Socks 配置($(config_n_get ${TCP_NODE#Socks_} port) 端口)]"
|
||||
if [ "$(config_get_type $TCP_NODE)" = "socks" ]; then
|
||||
msg2="${msg}使用 TCP 节点[Socks 配置($(config_n_get $TCP_NODE port) 端口)]"
|
||||
else
|
||||
msg2="${msg}使用 TCP 节点[$(config_n_get $TCP_NODE remarks)]"
|
||||
fi
|
||||
@@ -773,8 +773,8 @@ load_acl() {
|
||||
# 加载UDP默认代理模式
|
||||
if [ -n "${UDP_PROXY_MODE}" ]; then
|
||||
[ -n "$UDP_NODE" ] || [ "$TCP_UDP" = "1" ] && {
|
||||
if is_socks_wrap "$UDP_NODE"; then
|
||||
msg2="${msg}使用 UDP 节点[Socks 配置($(config_n_get ${UDP_NODE#Socks_} port) 端口)](TPROXY:${UDP_REDIR_PORT})"
|
||||
if [ "$(config_get_type $UDP_NODE)" = "socks" ]; then
|
||||
msg2="${msg}使用 UDP 节点[Socks 配置($(config_n_get $UDP_NODE port) 端口)](TPROXY:${UDP_REDIR_PORT})"
|
||||
else
|
||||
msg2="${msg}使用 UDP 节点[$(config_n_get $UDP_NODE remarks)](TPROXY:${UDP_REDIR_PORT})"
|
||||
fi
|
||||
|
||||
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=26.8.10
|
||||
PKG_RELEASE:=77
|
||||
PKG_RELEASE:=78
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -370,7 +370,7 @@ function socks_status()
|
||||
e.use_http = 0
|
||||
if tonumber(use_http) > 0 then
|
||||
e.use_http = 1
|
||||
e.http_status = luci.sys.call(string.format("/bin/busybox top -bn1 | grep -v -E 'grep|acl/|acl_' | grep '%s/bin/' | grep '%s' | grep -E 'HTTP_|HTTP2SOCKS' > /dev/null", appname, id)) == 0
|
||||
e.http_status = luci.sys.call(string.format("/bin/busybox top -bn1 | grep -v -E 'grep|acl/|acl_' | grep '%s/bin/' | grep '%s' | grep -E '\\+http|_http' > /dev/null", appname, id)) == 0
|
||||
end
|
||||
http_write_json(e)
|
||||
end
|
||||
|
||||
@@ -68,11 +68,15 @@ frag_dly=$(uci -q get passwall2.@global_xray[0].fragment_delay)
|
||||
[ -n "$frag_dly" ] && uci -q set passwall2.@global_xray[0].fragment_delays="$frag_dly" && uci -q delete passwall2.@global_xray[0].fragment_delay
|
||||
|
||||
for sid in $(uci show passwall2 | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}'); do
|
||||
if [ -z "$(echo ${sid} | grep '^socks_')" ]; then
|
||||
new_id="socks_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5)"
|
||||
uci -q rename passwall2.${sid}="${new_id}"
|
||||
unset sid new_id
|
||||
fi
|
||||
if [ -z "$(echo ${sid} | grep '^socks_')" ]; then
|
||||
new_id="socks_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5)"
|
||||
old_ref="Socks_${sid}"
|
||||
uci -q rename passwall2.${sid}="${new_id}"
|
||||
for item in $(uci show passwall2 | grep "='${old_ref}'\$" | cut -d '=' -sf 1); do
|
||||
uci -q set ${item}="${new_id}"
|
||||
done
|
||||
unset sid new_id old_ref item
|
||||
fi
|
||||
done
|
||||
for sid in $(uci show passwall2 | grep "@acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
|
||||
new_id="acl_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5)"
|
||||
|
||||
@@ -402,7 +402,7 @@ run_socks() {
|
||||
sing-box)
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
json_add_string "local_http_address" "${bind}"
|
||||
json_add_string "local_http_port" "${http_port}"
|
||||
}
|
||||
@@ -430,7 +430,7 @@ run_socks() {
|
||||
xray)
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
json_add_string "local_http_address" "${bind}"
|
||||
json_add_string "local_http_port" "${http_port}"
|
||||
}
|
||||
@@ -474,7 +474,7 @@ run_socks() {
|
||||
json_add_string "local_socks_port" "${socks_port}"
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
json_add_string "local_http_address" "${bind}"
|
||||
json_add_string "local_http_port" "${http_port}"
|
||||
}
|
||||
@@ -491,7 +491,7 @@ run_socks() {
|
||||
json_add_string "local_socks_port" "${socks_port}"
|
||||
[ "$http_port" != "0" ] && {
|
||||
http_flag=1
|
||||
config_file="${config_file//SOCKS/HTTP_SOCKS}"
|
||||
config_file="${config_file%%.*}+http${config_file#${config_file%%.*}}"
|
||||
json_add_string "local_http_address" "${bind}"
|
||||
json_add_string "local_http_port" "${http_port}"
|
||||
}
|
||||
@@ -535,16 +535,16 @@ socks_node_switch() {
|
||||
local flag new_node
|
||||
eval_set_val $@
|
||||
[ -n "$flag" ] && [ -n "$new_node" ] && {
|
||||
local prefix pf filename
|
||||
local suffix pf filename
|
||||
# Kill the SS plugin process
|
||||
for prefix in "" "HTTP_"; do
|
||||
pf="$TMP_PATH/${prefix}${flag}_plugin.pid"
|
||||
for suffix in "" "+http"; do
|
||||
pf="$TMP_PATH/${flag}${suffix}_plugin.pid"
|
||||
[ -s "$pf" ] && kill -9 "$(head -n1 "$pf")" >/dev/null 2>&1
|
||||
done
|
||||
|
||||
busybox pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1 && !/acl\/|acl_/{print $1}' | xargs kill -9 >/dev/null 2>&1
|
||||
for prefix in "" "HTTP_" "HTTP2"; do
|
||||
rm -rf "$TMP_PATH/${prefix}${flag}"*
|
||||
for suffix in "" "+http" "_http"; do
|
||||
rm -rf "$TMP_PATH/${flag}${suffix}"*
|
||||
done
|
||||
|
||||
for filename in $(ls ${TMP_SCRIPT_FUNC_PATH}); do
|
||||
@@ -560,7 +560,7 @@ socks_node_switch() {
|
||||
local log=$(config_n_get $flag log 1)
|
||||
[ "$log" == "0" ] && log_file=""
|
||||
local http_port=$(config_n_get $flag http_port 0)
|
||||
local http_config_file="HTTP2SOCKS_${flag}.json"
|
||||
local http_config_file="${flag}_http.json"
|
||||
LOG_FILE="/dev/null"
|
||||
run_socks flag=$flag node=$new_node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file
|
||||
set_cache_var "${flag}" "$new_node"
|
||||
@@ -727,7 +727,7 @@ start_socks() {
|
||||
local log=$(config_n_get $id log 1)
|
||||
[ "$log" == "0" ] && log_file=""
|
||||
local http_port=$(config_n_get $id http_port 0)
|
||||
local http_config_file="HTTP2SOCKS_${id}.json"
|
||||
local http_config_file="${id}_http.json"
|
||||
run_socks flag=$id node=$node bind=$bind socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file log_file=$log_file
|
||||
set_cache_var "${id}" "$node"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus
|
||||
LUCI_PKGARCH:=all
|
||||
PKG_NAME:=luci-app-ssr-plus
|
||||
PKG_VERSION:=196
|
||||
PKG_RELEASE:=55
|
||||
PKG_RELEASE:=56
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||
|
||||
@@ -519,7 +519,7 @@ local function anytls_to_mihomo_node(entry)
|
||||
return nil
|
||||
end
|
||||
|
||||
return {
|
||||
local result = {
|
||||
type = "anytls",
|
||||
alias = entry.name,
|
||||
raw_alias = entry.name,
|
||||
@@ -530,6 +530,12 @@ local function anytls_to_mihomo_node(entry)
|
||||
insecure = entry.allow_insecure and "1" or "0",
|
||||
fingerprint = entry.client_fingerprint
|
||||
}
|
||||
|
||||
local saved_alias = result.alias
|
||||
result.alias = nil
|
||||
result.hashkey = md5(jsonStringify(result) .. "_" .. (saved_alias or ""))
|
||||
result.alias = saved_alias
|
||||
return result
|
||||
end
|
||||
|
||||
local function split_csv_values(value)
|
||||
|
||||
@@ -17,7 +17,7 @@ LUCI_NAME:=luci-theme-footstrap
|
||||
FOOTSTRAP_VERSION?=
|
||||
ifneq ($(FOOTSTRAP_VERSION),)
|
||||
PKG_VERSION:=$(FOOTSTRAP_VERSION)
|
||||
PKG_RELEASE:=11
|
||||
PKG_RELEASE:=12
|
||||
endif
|
||||
|
||||
LUCI_TITLE:=Footstrap Theme
|
||||
|
||||
@@ -381,33 +381,6 @@ function seed() {
|
||||
adoptEntry();
|
||||
}
|
||||
|
||||
/* Does this document already carry the stylesheet a menu.d node names?
|
||||
*
|
||||
* The value is a path under /luci-static/resources (`view/foo/foo.css`), and head.ut prints it with
|
||||
* a `?v=` cache key, so compare the PATH only and by suffix — the theme does not get to assume the
|
||||
* resource base, and a re-hosted sheet keeps its element and its href (fs-sheets.js disables the
|
||||
* <link>, it never removes it), which is exactly the "already here" this asks about. */
|
||||
function documentHasSheet(css) {
|
||||
const want = '/' + css.replace(/^\/+/, '');
|
||||
for (const link of document.querySelectorAll('link[rel~="stylesheet"][href]')) {
|
||||
/* A <link> INSIDE the view tree dies with the swap — it is the one shape fs-sheets.js needs
|
||||
* no handling for, and every scan there skips it for the same reason (VIEW_SHEETS, and the
|
||||
* `closest('#view')` guards in documentPoisoned/scopeToCurrentPage/dedupeViewSheets).
|
||||
* Counting it here would answer the wrong question: `luci-app-nlbwmon` returns
|
||||
* `E('link', { rel: 'stylesheet', href: L.resource('view/nlbw.css') })` from render(), so
|
||||
* standing on that page its sheet IS in the document — and it is exactly the sheet the next
|
||||
* dom.content() throws away. An app in that shape moving to a menu.d `css` is the migration
|
||||
* #8920 was written for, so the guard has to survive it: leaving from that page must be a
|
||||
* full load, not a swap into an unstyled document. */
|
||||
if (link.closest('#view'))
|
||||
continue;
|
||||
const href = (link.getAttribute('href') || '').split('?')[0];
|
||||
if (href.endsWith(want))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Attempt an in-place navigation to `pathname`. Returns true if handled as a
|
||||
* SPA nav (caller should preventDefault), false to let the browser do a normal
|
||||
* full navigation. `push` adds a history entry (false when replaying popstate).
|
||||
@@ -432,25 +405,29 @@ function navigate(pathname, push, kbd) {
|
||||
|
||||
/* A PAGE WHOSE STYLESHEET ONLY THE SERVER CAN EMIT IS NOT OURS TO SWAP INTO.
|
||||
*
|
||||
* A menu.d node may name its own sheet (`"css": "view/foo/foo.css"`), and the server links it
|
||||
* from <head> on a full load (partials/head.ut). Nothing here can: a swap replaces #view's
|
||||
* children, it does not re-render a document, so reaching such a page by CLICK would show it
|
||||
* with the app's CSS missing — while reaching the same page by URL or F5 showed it styled. One
|
||||
* page, two appearances, decided by how the user got there.
|
||||
* A menu.d node may name its own sheet (`"css": "view/foo/foo.css"`), and the server links it from
|
||||
* <head> on a full load (partials/head.ut). Nothing here can: a swap replaces #view's children, it
|
||||
* does not re-render a document, so reaching such a page by CLICK would show it with the app's CSS
|
||||
* missing — while reaching the same page by URL or F5 showed it styled. One page, two appearances,
|
||||
* decided by how the user got there.
|
||||
*
|
||||
* So decline, exactly as the poisoned-document bail above does: speed is traded for
|
||||
* correctness, never the other way. It costs ONE full load per such page — after it the <link>
|
||||
* is in the document, this test passes, and every later visit is a swap again (fs-sheets.js
|
||||
* owns the sheet from then on and re-lights it per page).
|
||||
* So decline, exactly as the poisoned-document bail above does: speed is traded for correctness,
|
||||
* never the other way. It costs ONE full load per such page — after it the <link> is in the
|
||||
* document, this test passes, and every later visit is a swap again (fs-sheets.js owns the sheet
|
||||
* from then on and re-lights it per page).
|
||||
*
|
||||
* Injecting the <link> here instead would work and is deliberately not done: it would put the
|
||||
* theme in charge of fetching and ordering a foreign stylesheet, which is the job fs-sheets.js
|
||||
* exists to keep out of the theme. The server already does it correctly.
|
||||
* Injecting the <link> here instead would work and is deliberately not done: it would put the theme
|
||||
* in charge of fetching and ordering a foreign stylesheet, which is the job fs-sheets.js exists to
|
||||
* keep out of the theme. The server already does it correctly.
|
||||
*
|
||||
* `node.css` reaches the client because /admin/menu serves the dispatcher's own tree and
|
||||
* ui.js's scrubMenu() only rewrites `satisfied`. On a luci-base that predates the `css` schema
|
||||
* entry the property is dropped server-side, so this is simply never true there. */
|
||||
if (typeof node.css === 'string' && node.css !== '' && !documentHasSheet(node.css))
|
||||
* The QUESTION is fs-sheets.js's, not this module's: which sheets a document carries, and which of
|
||||
* them a swap is about to delete, is the one thing that file knows — see documentCarries(). What is
|
||||
* decided here is only what to do about the answer.
|
||||
*
|
||||
* `node.css` reaches the client because /admin/menu serves the dispatcher's own tree and ui.js's
|
||||
* scrubMenu() only rewrites `satisfied`. On a luci-base that predates the `css` schema entry the
|
||||
* property is dropped server-side, so this is simply never true there. */
|
||||
if (typeof node.css === 'string' && node.css !== '' && !sheets.documentCarries(node.css))
|
||||
return false;
|
||||
|
||||
const rsegs = res.segs;
|
||||
|
||||
@@ -307,6 +307,37 @@ function judgeSheet(el, universe) {
|
||||
* <link> INSIDE the view tree (`luci-app-nlbwmon`) needs no handling: it dies with the swap. */
|
||||
const VIEW_SHEETS = 'style:not([data-fs-shell]), link[rel~="stylesheet"]:not([data-fs-shell])';
|
||||
|
||||
/* DOES THIS SHEET OUTLIVE THE PAGE IT ARRIVED WITH? Everything this module decides hangs off that
|
||||
* one question, and the answer is where the element sits: a <style>/<link> inside the view tree
|
||||
* dies with the swap (dom.content() replaces #view's children), so it can neither poison the next
|
||||
* page, nor need scoping to this one, nor be a duplicate worth removing. Only sheets outside it
|
||||
* are this module's business. Named because it is asked in four places and read wrong in none of
|
||||
* them only by luck: `!el.closest('#view')` states where an element is, not what follows from it. */
|
||||
function outlivesPage(el) {
|
||||
return !el.closest('#view');
|
||||
}
|
||||
|
||||
/* Is `path` — a menu.d node's `css`, i.e. a path under /luci-static/resources — already carried by
|
||||
* this document in a form that SURVIVES a swap?
|
||||
*
|
||||
* The router asks before committing a client navigation: only a server render emits that <link>, so
|
||||
* a page whose stylesheet is missing must arrive by full load (see fs-router.js). The question is
|
||||
* this module's because the answer is: a link inside #view is about to be deleted with the rest of
|
||||
* the view, and counting it would hand the router a sheet the next dom.content() throws away —
|
||||
* `luci-app-nlbwmon` returns E('link', …, L.resource('view/nlbw.css')) from render(), so that shape
|
||||
* is real. Compared by PATH and by suffix: head.ut prints `{{ resource }}/{{ dispatched.css }}?v=…`,
|
||||
* so neither the resource base nor the cache key is anyone's to assume. */
|
||||
function documentCarries(path) {
|
||||
const want = '/' + String(path).replace(/^\/+/, '');
|
||||
for (const link of document.querySelectorAll('link[rel~="stylesheet"][href]')) {
|
||||
if (!outlivesPage(link))
|
||||
continue;
|
||||
if ((link.getAttribute('href') || '').split('?')[0].endsWith(want))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* An invasive sheet we OWN is contained — scopeToCurrentPage() darkens it the moment the router
|
||||
* stamps the new page, so it cannot reach the next page and the document is not spent. One we could
|
||||
* not attribute (not re-hostable, so never owned: an @import at the top, a sheet built with
|
||||
@@ -331,7 +362,7 @@ function documentPoisoned() {
|
||||
const names = themeNames();
|
||||
return Array.prototype.some.call(
|
||||
document.querySelectorAll(VIEW_SHEETS),
|
||||
(el) => !el.closest('#view')
|
||||
(el) => outlivesPage(el)
|
||||
&& (!names || (invasiveSheet(el, names) && !_owner.has(el) && !_silenced.has(el))));
|
||||
}
|
||||
|
||||
@@ -623,7 +654,7 @@ function scopeToCurrentPage(segs) {
|
||||
if (segs) _curKey = appKey(segs);
|
||||
const key = currentKey();
|
||||
document.querySelectorAll(VIEW_SHEETS).forEach((el) => {
|
||||
if (el.closest('#view') || !_owner.has(el)) return;
|
||||
if (!outlivesPage(el) || !_owner.has(el)) return;
|
||||
setEnabled(el, _owner.get(el) === key);
|
||||
});
|
||||
}
|
||||
@@ -731,7 +762,7 @@ function sheetKey(el) {
|
||||
function dedupeViewSheets() {
|
||||
const seen = new Set();
|
||||
document.querySelectorAll(VIEW_SHEETS).forEach((el) => {
|
||||
if (el.closest('#view')) return;
|
||||
if (!outlivesPage(el)) return;
|
||||
const key = sheetKey(el);
|
||||
if (key === null) return;
|
||||
if (seen.has(key)) el.remove();
|
||||
@@ -841,6 +872,7 @@ function watchViewSheets() {
|
||||
}
|
||||
|
||||
return baseclass.extend({
|
||||
documentCarries,
|
||||
documentPoisoned,
|
||||
scopeToCurrentPage,
|
||||
watchViewSheets
|
||||
|
||||
@@ -60,6 +60,13 @@
|
||||
--fs-focus-ring: 0 0 0 3px var(--fs-accent-soft);
|
||||
--fs-focus-ring-solo: 0 0 0 2px var(--fs-panel), 0 0 0 5px var(--fs-accent);
|
||||
--fs-focus-ring-invalid: 0 0 0 3px var(--fs-danger-fill);
|
||||
/* THE CHOSEN-ROW RAIL, the same ladder one rung along: a chosen row in a list says so with an
|
||||
* opaque surface and an inset bar, never with a tint of the accent under accent text (that
|
||||
* measured 4.21:1 in dark — see theme/65-dropdown.css). Named because it is written in three
|
||||
* places that cannot be one rule: the open dropdown's row, a native `select option:checked`,
|
||||
* and the ring the FOCUSED row wears on top of it. The first two are pinned to each other by
|
||||
* tools/mirror.mjs; the third restated the literal until it had a name. */
|
||||
--fs-row-rail: inset 2px 0 0 var(--fs-accent);
|
||||
|
||||
/* the theme's ONE colour literal, deliberately: black at .7 is the absence of light
|
||||
* behind a dialog, not a tint of any token — a palette-tinted scrim over a dark page
|
||||
|
||||
@@ -1,32 +1,34 @@
|
||||
@layer page {
|
||||
/* THE FILTER BAR, which LuCI writes as a run of inline text.
|
||||
*
|
||||
* `tools/views.js` (LogreadBox, shared by System Log, Kernel Log and every third-party page
|
||||
* built on it) emits two bare `<div style="margin-bottom:10px">`, each holding label / control
|
||||
* pairs with nothing around a pair: `<label>Не</label><input type=checkbox><label>объект:</label>
|
||||
* <select>…`. Inline flow then breaks wherever the line runs out, and on a phone that is between
|
||||
* a label and the control it names — reported from a 390px screen, where the second `Не` sat
|
||||
* alone at the end of one line, `уровень:` opened the next one without it, and `Макс. строк:`
|
||||
* broke INSIDE the label, leaving `Макс.` on one line and `строк:` on the next with the field it
|
||||
* belongs to.
|
||||
* Both log views build one: `tools/views.js` (LogreadBox — the System Log, and every third-party
|
||||
* page built on it) and `view/status/dmesg.js` (the Kernel Log). Each emits bare
|
||||
* `<div style="margin-bottom:10px">` rows holding label / control pairs with nothing around a
|
||||
* pair: `<label>Не</label><input type=checkbox><label>объект:</label><select>…`. Inline flow then
|
||||
* breaks wherever the line runs out, and on a phone that is between a label and the control it
|
||||
* names — reported from a 390px screen, where the second `Не` sat alone at the end of one line,
|
||||
* `уровень:` opened the next one without it, and `Макс. строк:` broke INSIDE the label, leaving
|
||||
* `Макс.` above `строк:` and the field they belong to.
|
||||
*
|
||||
* Flex with wrapping fixes both halves: a wrap can now only happen BETWEEN items, and a label is
|
||||
* one unbreakable item, so a pair still separates at worst onto two lines instead of a label
|
||||
* cutting in half. The fields shrink instead of forcing that: `min-width: 0` undoes the field
|
||||
* box in theme/60-inputs.css for this row only.
|
||||
* ONE RULE OF LAYOUT, TWO TIERS, NO PER-FIELD EXCEPTIONS. The rows are flex, so a wrap can only
|
||||
* fall BETWEEN items and a label is one unbreakable item. A field may SHRINK to share the line
|
||||
* (`min-width: 0` undoes the field box in theme/60-inputs.css for these rows) but none of them
|
||||
* GROWS past its own width — that is what keeps `Макс. строк:` a small box beside a wide search
|
||||
* field without anything having to name it. The one exception states itself: the free-text filter
|
||||
* is the only field whose content has no length, so it takes the leftover space.
|
||||
*
|
||||
* Keyed on the ROW's SHAPE, not on the page and not on the controls' ids. `data-page` differs
|
||||
* between the system and the kernel log and a third-party LogreadBox has neither — but the ids
|
||||
* are no better: only the System Log is built by `tools/views.js`, and Status → Kernel Log is a
|
||||
* view of its own (`view/status/dmesg.js`) whose four rows carry `logFromTime`, `logToTime`,
|
||||
* `invertLogRangeTime`, `invertSeverity` and `invertAscendingSort`, of which an id list written
|
||||
* against LogreadBox catches none — `logFacilitySelect` appears there only as a `for=`, on a
|
||||
* label whose control is a time field. Both views wrap their rows in `#content_syslog`, and a
|
||||
* filter row is exactly one that opens with a `<label>`; the scroll-to-end button's row and the
|
||||
* log itself do not. That shape holds for any view built the same way.
|
||||
* `input:not([type])` IS that filter, in both views and in that order of certainty: every other
|
||||
* input under `#content_syslog` states a type (`checkbox` for the four inverts and the sort flag,
|
||||
* `number` for Max rows and for the Kernel Log's boot-time range), and both views leave the text
|
||||
* one untyped. Nothing here keys on an id, so a third-party LogreadBox gets the same layout, and
|
||||
* no rule has to know how many fields a row holds.
|
||||
*
|
||||
* The inline `margin: 0 5px` LuCI writes on the labels stays as the horizontal spacing — only
|
||||
* the ROW gap is ours, so nothing here has to fight an inline style. */
|
||||
* Scoped by SHAPE for the same reason: `data-page` differs between the two logs and a third-party
|
||||
* box has neither, while both wrap their rows in `#content_syslog` and a filter row is exactly one
|
||||
* that opens with a `<label>` — the scroll-to-end button's row and the log itself do not.
|
||||
*
|
||||
* The inline `margin: 0 5px` LuCI writes on the labels stays as the horizontal spacing — only the
|
||||
* ROW gap is ours, so nothing here has to fight an inline style. */
|
||||
#content_syslog > div:has(> label) {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -35,50 +37,32 @@
|
||||
}
|
||||
#content_syslog > div:has(> label) > label { white-space: nowrap; }
|
||||
#content_syslog > div:has(> label) > :is(select, input) {
|
||||
flex: 1 1 auto;
|
||||
/* both halves are needed and they answer different layouts: `min-width: 0` lets a FLEX item
|
||||
* shrink past its content, `max-width: 100%` clamps a GRID item to its track. A <select>
|
||||
* carries the theme's own 210px field width, which a `minmax(0, 1fr)` track does not
|
||||
* override — measured at 360px, where both selects hung 3px past the view. */
|
||||
/* shrink, never grow. `max-width` is not the same lever as `min-width` and both are needed:
|
||||
* one lets a flex item go below its content, the other clamps a `<select>` that carries the
|
||||
* theme's own 210px width — measured at 360px, where both selects hung 3px past the view. */
|
||||
flex: 0 1 auto;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
/* a checkbox is not a field: left to its own 16px, it would otherwise flex to fill the line. */
|
||||
#content_syslog > div:has(> label) > input[type="checkbox"] { flex: 0 0 auto; }
|
||||
/* The max-rows box keeps a sane ceiling: as wide as the free-text filter it reads as a second
|
||||
* search field. Selected as the row's `number` input, not by its id: `#logMaxRows` alone is
|
||||
* (1,0,0) and the field rule above is (1,0,3), so the id LOSES — and re-anchoring it under
|
||||
* `#content_syslog` would put two ids in one selector, [2,0,x], past the [1,7,0] ceiling
|
||||
* `npm run css-metrics` holds this sheet to. `[type="number"]` is the only one in either log's
|
||||
* filter bar and it out-specifies at (1,1,3). */
|
||||
#content_syslog > div:has(> label) > input[type="number"] { flex-basis: 6ch; max-width: 12ch; }
|
||||
|
||||
/* ON A PHONE, ONE FILTER PER LINE. Wrapping alone still fills each line greedily, so the second
|
||||
* `Не` rode the end of the first line while the `уровень:` it inverts opened the next one. The
|
||||
* first row is a fixed alternation of exactly two filters — invert label, checkbox, name label,
|
||||
* control, twice — so a four-column grid puts one filter on each line.
|
||||
*
|
||||
* EVERY OTHER ROW is deliberately left to the wrapping above, because none of them is that
|
||||
* shape. The System Log's second row holds a checkbox filter beside a bare `Макс. строк:` pair,
|
||||
* and the same four tracks are then sized by items that are not each other's counterparts:
|
||||
* measured, the max-rows box defined column 2 and pushed `содержит:` and its field off the card.
|
||||
* The Kernel Log's rows are three different shapes again — a range with two time fields, a
|
||||
* severity select with a trailing `and above`, and a lone sort checkbox. Wrapping puts each of
|
||||
* those on as many lines as it needs, which is all the grid was ever for; the grid is worth its
|
||||
* one selector only where the alternation is exact. */
|
||||
@container fs-view (max-width: 560px) {
|
||||
/* THE ROW WITH TWO SELECTS, which is the same row `#logFacilitySelect` names — by shape
|
||||
* because neither spelling of the id survives the arithmetic: `div:has(> #logFacilitySelect)`
|
||||
* is (1,0,1) and loses to the flex rule above at (1,0,2), while `#content_syslog >` in front
|
||||
* of it is two ids, [2,0,1], past the [1,7,0] ceiling `npm run css-metrics` holds. Two
|
||||
* sibling selects is what the `auto auto auto minmax(0, 1fr)` template is sized for — eight
|
||||
* children, two filters — and it is unique to the System Log's first row: the Kernel Log's
|
||||
* severity row carries one select, its range row two time fields. (1,0,4) beats the flex
|
||||
* rule on specificity, not on source order. */
|
||||
#content_syslog > div:has(> label):has(> select ~ select) {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto minmax(0, 1fr);
|
||||
column-gap: var(--fs-space-1);
|
||||
/* THE TWO TIERS ARE DISJOINT CONTAINER QUERIES, not a base rule and an override: each states one
|
||||
* layout in full, so neither can win or lose against the other by source order — the trap the
|
||||
* first version of this file fell into, where a later generalisation silently out-specified two
|
||||
* rules that were meant to override it. */
|
||||
@container fs-view (width > 560px) {
|
||||
/* room for a filter and a half at least: the search box takes what the named fields leave. */
|
||||
#content_syslog > div:has(> label) > input:not([type]) { flex: 1 1 12rem; }
|
||||
}
|
||||
@container fs-view (width <= 560px) {
|
||||
/* ONE FIELD PER LINE, its labels on the line above it. Wrapping alone fills each line greedily,
|
||||
* so the second `Не` rode the end of the first line while the `уровень:` it inverts opened the
|
||||
* next one — and no flex rule can bind a label to the field that follows it. A full-width basis
|
||||
* can: the field always starts a line, so whatever labels precede it sit together above it. It
|
||||
* costs one line per filter on a phone and holds for every row of both views — the range pair,
|
||||
* the severity select with its trailing `and above`, the lone sort checkbox — without any of
|
||||
* them being named or counted. A checkbox is not a field and keeps its 16px. */
|
||||
#content_syslog > div:has(> label) > :is(select, input:not([type="checkbox"])) {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,50 +21,50 @@
|
||||
}
|
||||
.cbi-progressbar::after {
|
||||
content: attr(title);
|
||||
position: absolute; inset-inline: auto 0; bottom: calc(100% + 4px); top: auto;
|
||||
/* the gap is a scale step, not a literal 4: every other gap in the theme scales with the
|
||||
* density axis and this one sat outside it. Identical at the default density. */
|
||||
position: absolute; inset-inline: auto 0; bottom: calc(100% + var(--fs-space-1)); top: auto;
|
||||
font-family: var(--fs-font-mono); font-size: var(--fs-type-xs); font-weight: var(--fs-weight-normal);
|
||||
color: var(--fs-dim); white-space: nowrap; text-shadow: none;
|
||||
}
|
||||
|
||||
/* THE BAR IS THE FIELD OF A LABELLED ROW — put the value BESIDE it, not above it.
|
||||
/* THE VALUE SITS BESIDE THE BAR wherever the bar already shares its line with a name.
|
||||
*
|
||||
* The placement above the bar (and the stock one it replaced: bootstrap floats the same title
|
||||
* at `top: -1.4em; left: 0`) assumes the shape the Overview has, where the bar owns a full-width
|
||||
* line and its name sits on the line above — there the value lands at the far end of the name's
|
||||
* own line and the two read as one row. A `.cbi-value` row is the other shape: the name is
|
||||
* already in the LEFT column, on the bar's own line, so a value floating above the bar has
|
||||
* nothing to pair with. It lands against the row divider instead, nearer the row above than the
|
||||
* bar it belongs to — reported against luci-app-modeminfo's Antennas page, three of these rows
|
||||
* per card and every dBm figure reading as though it belonged to the meter above it.
|
||||
* The default above puts it over the bar's far edge, and that assumes the shape the Overview has:
|
||||
* the meter owns a full-width line and its name sits on the line above, so the value lands at the
|
||||
* far end of that name's own line and the two read as one row. (Stock bootstrap assumes the same,
|
||||
* floating the title at `top: -1.4em; left: 0`.) Two shapes are not that, and they are not each
|
||||
* other either — CSS cannot ask "does this row carry its own label" — so each is named:
|
||||
*
|
||||
* Inline, then: the row becomes `name | meter | value`, one line, values aligned to a single
|
||||
* column because the reserve is fixed rather than shrink-wrapped. The reserve is
|
||||
* `2 x --fs-space-10` because the value can be `-140.0 dBm`, half again as wide as the
|
||||
* `100% (1.2 GiB)` a single step covers in the data-table rule below.
|
||||
* `.cbi-value-field > .cbi-progressbar` the meter IS the field of a CBI form row, an app
|
||||
* building `.cbi-value` with ui.js. Reported against luci-app-modeminfo's Antennas page:
|
||||
* three such rows per card, every dBm figure reading as though it belonged to the meter above
|
||||
* it, because the value lands against the row divider rather than beside its own bar.
|
||||
* `.table:has(.tr.table-titles) .td …` a meter COLUMN in a multi-column data table
|
||||
* (luci-app-cpu-status's per-CPU load), where the floated value lands on the row divider too.
|
||||
*
|
||||
* Not the same selector as that rule and deliberately so: this is the CBI FORM row (an app
|
||||
* building a `.cbi-value` with ui.js), that one is a multi-column data table. Both end up
|
||||
* inline-right; neither can be expressed as the other, because CSS cannot ask "does this row
|
||||
* carry its own label". The Overview and the package manager keep the value above the bar:
|
||||
* their meters sit in a `.td` and a bare `.controls` div, neither of which is a field. */
|
||||
.cbi-value-field > .cbi-progressbar { margin-inline-end: calc(var(--fs-space-10) * 2); }
|
||||
.cbi-value-field > .cbi-progressbar::after {
|
||||
* Both want the same geometry and differ in ONE number, so the geometry is written once and the
|
||||
* number is the knob: `--fs-meter-value` is the room the out-of-flow value needs. A form row holds
|
||||
* `-140.0 dBm`, half again as wide as the `100% (1.2 GiB)` of a table cell. The Overview and the
|
||||
* package manager keep the value above the bar — their meters sit in a `.td` and a bare
|
||||
* `.controls` div, which is neither shape. */
|
||||
.cbi-value-field > .cbi-progressbar,
|
||||
.cbi-section .table:has(.tr.table-titles) .td .cbi-progressbar {
|
||||
margin-inline-end: var(--fs-meter-value);
|
||||
}
|
||||
.cbi-value-field > .cbi-progressbar::after,
|
||||
.cbi-section .table:has(.tr.table-titles) .td .cbi-progressbar::after {
|
||||
inset-inline: calc(100% + var(--fs-space-2)) auto; bottom: auto; top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
.cbi-value-field > .cbi-progressbar { --fs-meter-value: calc(var(--fs-space-10) * 2); }
|
||||
.cbi-section .table:has(.tr.table-titles) .td .cbi-progressbar {
|
||||
--fs-meter-value: var(--fs-space-10);
|
||||
/* narrower than this it stops reading as a meter at all; the column gives up the rest. */
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
/* Progressbar rows in a section table (luci-app-cpu-status): keep the native label | bar
|
||||
* row, just centre the cells vertically. */
|
||||
.cbi-section .table:not([id]):not(.cbi-section-table) .tr:has(.cbi-progressbar) .td { vertical-align: middle; }
|
||||
|
||||
/* Multi-column DATA tables with a progressbar column (cpu-status per-CPU load): the
|
||||
* generic meter floats its value ABOVE the bar, which here lands on the row divider.
|
||||
* Shrink the bar and put the value INLINE to its right, clear of the border. */
|
||||
.cbi-section .table:has(.tr.table-titles) .td .cbi-progressbar {
|
||||
min-width: 60px; margin-inline-end: var(--fs-space-10);
|
||||
}
|
||||
.cbi-section .table:has(.tr.table-titles) .td .cbi-progressbar::after {
|
||||
inset-inline: calc(100% + 8px) auto; bottom: auto; top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,7 +429,7 @@
|
||||
* under AA — the tint of the accent eats its own contrast. */
|
||||
.cbi-value-field select option:checked {
|
||||
/* @mirror selected-row/paint */
|
||||
background: var(--fs-panel2); color: var(--fs-accent); box-shadow: inset 2px 0 0 var(--fs-accent);
|
||||
background: var(--fs-panel2); color: var(--fs-accent); box-shadow: var(--fs-row-rail);
|
||||
/* @endmirror */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@
|
||||
* with a chosen value; the widget shipped that way on every dark router. */
|
||||
.cbi-dropdown[open] > ul.dropdown > li[selected] {
|
||||
/* @mirror selected-row/paint */
|
||||
background: var(--fs-panel2); color: var(--fs-accent); box-shadow: inset 2px 0 0 var(--fs-accent);
|
||||
background: var(--fs-panel2); color: var(--fs-accent); box-shadow: var(--fs-row-rail);
|
||||
/* @endmirror */
|
||||
}
|
||||
/* THE FOCUSED ROW WEARS THE THEME'S RING, not the browser's.
|
||||
@@ -375,8 +375,9 @@
|
||||
* browser shipped.
|
||||
*
|
||||
* Inset rather than the token's outer 3px: the menu clips its own overflow, so an outer ring is
|
||||
* cut on the first and last rows. The rail is restated INSIDE this ring so a focused row that is
|
||||
* also selected keeps its rail — a shorthand cannot merge with the one below.
|
||||
* cut on the first and last rows. The rail rides INSIDE this ring so a focused row that is also
|
||||
* selected keeps it — a shorthand cannot merge with the one below, so the two are listed
|
||||
* together, and `--fs-row-rail` is why that is a reference rather than a third copy.
|
||||
*
|
||||
* Both selectors carry `[selected]`-level weight on purpose: the selected-row paint below is
|
||||
* (0,4,1) and a bare `li:focus-visible` ties with it, which would leave the focus ring to source
|
||||
@@ -384,7 +385,7 @@
|
||||
.cbi-dropdown[open] > ul.dropdown > li[selected]:focus-visible,
|
||||
.cbi-dropdown[open] > ul.dropdown > li:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: inset 2px 0 0 var(--fs-accent), inset 0 0 0 2px var(--fs-accent-soft);
|
||||
box-shadow: var(--fs-row-rail), inset 0 0 0 2px var(--fs-accent-soft);
|
||||
}
|
||||
|
||||
/* A MULTI-select row says "chosen" with its CHECKBOX, so it does not also need the rail.
|
||||
|
||||
+2
-2
@@ -10,12 +10,12 @@ include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=natflow
|
||||
PKG_VERSION:=20260531
|
||||
PKG_RELEASE:=63
|
||||
PKG_RELEASE:=64
|
||||
|
||||
PKG_SOURCE:=$(PKG_VERSION).tar.xz
|
||||
PKG_SOURCE_URL:=https://github.com/ptpt52/natflow.git
|
||||
PKG_SOURCE_PROTO:=git
|
||||
PKG_SOURCE_VERSION:=a2e7cbafc787ba9a0e86550bd3f4d03207fb9678
|
||||
PKG_SOURCE_VERSION:=b3e749ae53becc4d31596e40d18e4875e518adc1
|
||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
|
||||
PKG_MAINTAINER:=Chen Minqiang <ptpt52@gmail.com>
|
||||
PKG_LICENSE:=GPL-2.0
|
||||
|
||||
Reference in New Issue
Block a user