From 08155500fcf512a8ad37e33c52805cb106116e88 Mon Sep 17 00:00:00 2001 From: eric Date: Thu, 28 May 2026 15:59:03 -0500 Subject: [PATCH] 's' --- LsRzcR3pHoA9.yaml | 441 ++++++++++++++++++ d2ypp2/.gitattributes | 23 + d2ypp2/config/system-stack.env.example | 12 + d2ypp2/docs/install-profiles.md | 2 +- d2ypp2/pyproject.toml | 3 +- d2ypp2/requirements.txt | 9 +- d2ypp2/scripts/launch.py | 1 + d2ypp2/scripts/linux/install_all.sh | 1 + d2ypp2/scripts/linux/lib/common.sh | 217 +++++++-- d2ypp2/scripts/linux/service_ctl.sh | 169 ++++++- d2ypp2/services/neko/browser-launch.sh | 23 +- d2ypp2/services/neko/docker-compose.yml | 9 - d2ypp2/src/control_plane.py | 88 ++++ .../tools/bootstrap_remote_repo_paramiko.py | 8 +- d2ypp2/tools/deploy_live_paramiko.py | 61 ++- d2ypp2/tools/probe_board_stack.py | 18 +- d2ypp2/tools/render_neko_compose.py | 10 +- d2ypp2/tools/ssh_neko_start.py | 8 +- d2ypp2/tools/verify_live_console.py | 6 +- d2ypp2/tools/verify_local_install.py | 8 +- .../console/LiveConsoleWorkspace.tsx | 49 ++ d2ypp2/web-console/out/.build-stamp.json | 6 +- d2ypp2/web-console/out/404.html | 2 +- .../static/chunks/246-316dc23346e75be8.js | 1 + .../static/chunks/246-b5d14933cf331e85.js | 1 - ...abda18d658.js => page-69ff6e74a15b80d9.js} | 2 +- ...a154677dbc.js => page-db00fd3a990c6a05.js} | 2 +- .../chunks/app/layout-809a834918419a40.js | 1 - .../chunks/app/layout-d9acbcf8f9ab58b1.js | 1 + ...6f49d462b3.js => page-abd70046db11ff5c.js} | 2 +- .../app/shellcrash/page-3d8615ae919b9119.js | 1 - .../app/shellcrash/page-766863ba520c08ee.js | 1 + ...d9a1f2.js => main-app-5ec094bd229d9247.js} | 2 +- ...8419d30.js => webpack-8b48d63693aaff80.js} | 2 +- .../out/_next/static/css/693f7950f3222bce.css | 3 - .../out/_next/static/css/f7eb93299e7a4c6e.css | 3 + .../_buildManifest.js | 0 .../_ssgManifest.js | 0 d2ypp2/web-console/out/android.html | 2 +- d2ypp2/web-console/out/android.txt | 6 +- d2ypp2/web-console/out/console.html | 2 +- d2ypp2/web-console/out/console.txt | 6 +- d2ypp2/web-console/out/index.html | 2 +- d2ypp2/web-console/out/index.txt | 6 +- d2ypp2/web-console/out/shellcrash.html | 2 +- d2ypp2/web-console/out/shellcrash.txt | 6 +- d2ypp2/web.py | 20 + 47 files changed, 1126 insertions(+), 122 deletions(-) create mode 100644 LsRzcR3pHoA9.yaml create mode 100644 d2ypp2/.gitattributes create mode 100644 d2ypp2/web-console/out/_next/static/chunks/246-316dc23346e75be8.js delete mode 100644 d2ypp2/web-console/out/_next/static/chunks/246-b5d14933cf331e85.js rename d2ypp2/web-console/out/_next/static/chunks/app/android/{page-84550dabda18d658.js => page-69ff6e74a15b80d9.js} (54%) rename d2ypp2/web-console/out/_next/static/chunks/app/console/{page-75d851a154677dbc.js => page-db00fd3a990c6a05.js} (54%) delete mode 100644 d2ypp2/web-console/out/_next/static/chunks/app/layout-809a834918419a40.js create mode 100644 d2ypp2/web-console/out/_next/static/chunks/app/layout-d9acbcf8f9ab58b1.js rename d2ypp2/web-console/out/_next/static/chunks/app/{page-4d705a6f49d462b3.js => page-abd70046db11ff5c.js} (99%) delete mode 100644 d2ypp2/web-console/out/_next/static/chunks/app/shellcrash/page-3d8615ae919b9119.js create mode 100644 d2ypp2/web-console/out/_next/static/chunks/app/shellcrash/page-766863ba520c08ee.js rename d2ypp2/web-console/out/_next/static/chunks/{main-app-862a0795add9a1f2.js => main-app-5ec094bd229d9247.js} (58%) rename d2ypp2/web-console/out/_next/static/chunks/{webpack-7691246368419d30.js => webpack-8b48d63693aaff80.js} (76%) delete mode 100644 d2ypp2/web-console/out/_next/static/css/693f7950f3222bce.css create mode 100644 d2ypp2/web-console/out/_next/static/css/f7eb93299e7a4c6e.css rename d2ypp2/web-console/out/_next/static/{DBO2lufGEkC0vKztt3KO1 => gGPi9R7eKZcpHz_wmmWrF}/_buildManifest.js (100%) rename d2ypp2/web-console/out/_next/static/{DBO2lufGEkC0vKztt3KO1 => gGPi9R7eKZcpHz_wmmWrF}/_ssgManifest.js (100%) diff --git a/LsRzcR3pHoA9.yaml b/LsRzcR3pHoA9.yaml new file mode 100644 index 0000000..40e2e1c --- /dev/null +++ b/LsRzcR3pHoA9.yaml @@ -0,0 +1,441 @@ +port: 7890 +socks-port: 7891 +allow-lan: false +mode: rule +log-level: info +geodata-mode: true +geo-auto-update: true +geodata-loader: standard +geo-update-interval: 24 +geox-url: + geoip: https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geoip.dat + geosite: >- + https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/geosite.dat + mmdb: >- + https://testingcf.jsdelivr.net/gh/MetaCubeX/meta-rules-dat@release/country.mmdb + asn: >- + https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb +rule-providers: + geolocation-cn: + type: http + format: mrs + behavior: domain + url: >- + https://gh.sageer.me/https://github.com/MetaCubeX/meta-rules-dat/raw/refs/heads/meta/geo/geosite/geolocation-cn.mrs + path: ./ruleset/geolocation-cn.mrs + interval: 86400 + geolocation-!cn: + type: http + format: mrs + behavior: domain + url: >- + https://gh.sageer.me/https://github.com/MetaCubeX/meta-rules-dat/raw/refs/heads/meta/geo/geosite/geolocation-!cn.mrs + path: ./ruleset/geolocation-!cn.mrs + interval: 86400 + private: + type: http + format: mrs + behavior: ipcidr + url: >- + https://gh.sageer.me/https://github.com/MetaCubeX/meta-rules-dat/raw/refs/heads/meta/geo/geoip/private.mrs + path: ./ruleset/private.mrs + interval: 86400 + cn: + type: http + format: mrs + behavior: domain + url: >- + https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/meta/geo/geosite/cn.yaml + path: ./ruleset/cn.mrs + interval: 86400 +dns: + enable: true + ipv6: false + respect-rules: true + enhanced-mode: fake-ip + nameserver: + - https://120.53.53.53/dns-query + - https://223.5.5.5/dns-query + proxy-server-nameserver: + - https://120.53.53.53/dns-query + - https://223.5.5.5/dns-query + nameserver-policy: + geosite:cn,private: + - https://120.53.53.53/dns-query + - https://223.5.5.5/dns-query + geosite:geolocation-!cn: + - https://dns.cloudflare.com/dns-query + - https://dns.google/dns-query +proxies: + + # 落地代理 + - name: proxycheap + # 前置代理 + dialer-proxy: dialer + type: socks5 + server: 192.204.0.72 + port: 12324 + username: 14acc9ad9e029 + password: 65ab9719f5 + # tls: true + # fingerprint: xxxx + # skip-cert-verify: true + # udp: true + # ip-version: ipv6 + + - name: socks5 + type: socks5 + server: 92.112.6.88 + port: 12324 + username: 14acc9ad9e029 + password: 65ab9719f5 + # tls: true + # fingerprint: xxxx + # skip-cert-verify: true + # udp: true + # ip-version: ipv6 + + + - name: "242af835-singbox_hysteria" + type: hysteria2 + server: 107.173.7.226 + # server: hy2.nomadro.com + port: 34814 + ports: 30000-31000 + password: 1f28cd23-d223-4eaa-a786-4a010d674cbc + sni: hy2.nomadro.com + skip-cert-verify: true + alpn: + - h3 + up: "1000 Mbps" + down: "1000 Mbps" + # congestion_control: bbr # 优化带宽利用率 + - name: hackrobot-singbox_tuic + type: tuic + server: 107.173.7.226 + port: 33935 + ports: 32000-40000 + uuid: 1f28cd23-d223-4eaa-a786-4a010d674cbc + password: 1f28cd23-d223-4eaa-a786-4a010d674cbc + + # 可选优化字段(以下均为官方推荐写法) + alpn: + - h3 + udp-relay-mode: native # 原生 UDP 转发模式 + congestion-controller: bbr # 拥塞控制算法:bbr/cubic/new_reno + disable-sni: false # 保留 SNI,用于伪装域名 + reduce-rtt: true # 启用 0-RTT 握手以降低延迟 + request-timeout: 8000 # 连接超时时间(毫秒) + heartbeat-interval: 10000 # 心跳包间隔(毫秒) + tls: true + sni: hy2.nomadro.com # 若使用域名证书建议填写 + skip-cert-verify: true # 测试阶段跳过证书验证 + fast-open: true # 启用 TCP Fast-Open + max-open-streams: 20 # 最大并发流数量 + max-udp-relay-packet-size: 1500 # 最大 UDP 包大小(字节) + udp: true # 启用 UDP 支持 + - name: "VLESS_Reality_Vision" + type: vless + server: 107.173.7.226 # 替换为域名 + port: 21730 # 修改端口为21730 + uuid: 1f28cd23-d223-4eaa-a786-4a010d674cbc + flow: xtls-rprx-vision + encryption: none + network: tcp + + tls: true + servername: hy2.nomadro.com + alpn: + - h2 + - http/1.1 + client-fingerprint: chrome + skip-cert-verify: true + + reality-opts: + public-key: ppipIkuEvHMBaMMg42C1lsRX_igSZPlDDZDBVY1UdzM + short-id: 6ba85179e30d4fc2 + server-names: + - hy2.nomadro.com + flow: xtls-rprx-vision + + smux: + enabled: false + + - name: "242af835-singbox_hysteria2" + type: hysteria2 + server: 23.94.99.206 + # server: hy2.nomadro.com + port: 32941 + ports: 30000-31000 + password: fda6eb84-7b47-473f-abcb-82a5addece55 + sni: web3.nomadro.com + skip-cert-verify: true + alpn: + - h3 + up: "1000 Mbps" + down: "1000 Mbps" + # congestion_control: bbr # 优化带宽利用率 + - name: hackrobot-singbox_tuic2 + type: tuic + server: 23.94.99.206 + port: 10831 + ports: 32000-33000 + uuid: fda6eb84-7b47-473f-abcb-82a5addece55 + password: fda6eb84-7b47-473f-abcb-82a5addece55 + + # 可选优化字段(以下均为官方推荐写法) + alpn: + - h3 + udp-relay-mode: native # 原生 UDP 转发模式 + congestion-controller: bbr # 拥塞控制算法:bbr/cubic/new_reno + disable-sni: false # 保留 SNI,用于伪装域名 + reduce-rtt: true # 启用 0-RTT 握手以降低延迟 + request-timeout: 8000 # 连接超时时间(毫秒) + heartbeat-interval: 10000 # 心跳包间隔(毫秒) + tls: true + sni: web3.nomadro.com # 若使用域名证书建议填写 + skip-cert-verify: true # 测试阶段跳过证书验证 + fast-open: true # 启用 TCP Fast-Open + max-open-streams: 20 # 最大并发流数量 + max-udp-relay-packet-size: 1500 # 最大 UDP 包大小(字节) + udp: true # 启用 UDP 支持 + - name: "VLESS_Reality_Vision2" + type: vless + server: 23.94.99.206 # 替换为域名 + port: 35925 # 修改端口为21730 + uuid: fda6eb84-7b47-473f-abcb-82a5addece55 + flow: xtls-rprx-vision + encryption: none + network: tcp + + tls: true + servername: web3.nomadro.com + alpn: + - h2 + - http/1.1 + client-fingerprint: chrome + skip-cert-verify: true + + reality-opts: + public-key: JhJEy3-xC5sux3iBJ1Ryc8jO5F6CKsZsQjzG0BSN_g0 + short-id: 6ba85179e30d4fc2 + server-names: + - web3.nomadro.com + flow: xtls-rprx-vision + + smux: + enabled: false + + - name: "5d723acc-singbox_hysteria2" + type: hysteria2 + server: vpn.nomadro.live + port: 42220 + password: 5d723acc-7454-4d36-8c95-7dd4ac7345f0 + sni: vpn.nomadro.live + skip-cert-verify: true + alpn: + - h3 + up: "1000 Mbps" + down: "1000 Mbps" + + - name: "5d723acc-singbox_hysteria3" + type: hysteria2 + server: vpn.nomadro.live + port: 42220 + password: 5d723acc-7454-4d36-8c95-7dd4ac7345f0 + sni: vpn.nomadro.live + skip-cert-verify: true + alpn: + - h3 + up: "1000 Mbps" + down: "1000 Mbps" + - name: "5d723acc-singbox_tuic3" + type: tuic + server: vpn.nomadro.live + port: 11090 + ports: 32000-40000 + uuid: 5d723acc-7454-4d36-8c95-7dd4ac7345f0 + password: 5d723acc-7454-4d36-8c95-7dd4ac7345f0 + alpn: + - h3 + udp-relay-mode: native + congestion-controller: bbr + disable-sni: false + reduce-rtt: true + request-timeout: 8000 + heartbeat-interval: 10000 + tls: true + sni: vpn.nomadro.live + skip-cert-verify: true + fast-open: true + max-open-streams: 20 + max-udp-relay-packet-size: 1500 + udp: true + - name: "5d723acc-VLESS_Reality_Vision3" + type: vless + server: vpn.nomadro.live + port: 10166 + uuid: 5d723acc-7454-4d36-8c95-7dd4ac7345f0 + flow: xtls-rprx-vision + encryption: none + network: tcp + tls: true + servername: vpn.nomadro.live + alpn: + - h2 + - http/1.1 + client-fingerprint: chrome + skip-cert-verify: true + reality-opts: + public-key: O7N27RFEB0aZA22B9MCaMuScNL8o4mEJ1L59ckwMdQo + short-id: 6ba85179e30d4fc2 + server-names: + - vpn.nomadro.live + flow: xtls-rprx-vision + smux: + enabled: false + + - name: leafHY2 + type: hysteria2 + server: proxy.smallzhiyuns.com + port: 25050 + ports: 30000-31000 # 保持这个范围 + password: 1c8bafc8-f9cc-4168-a6c2-a57fc6a76eee + sni: proxy.smallzhiyuns.com + up: "200 Mbps" # 先降低测试 + down: "200 Mbps" + alpn: + - h3 # 只留 h3 + skip-cert-verify: false # 先试不跳过(如果证书正规);如果还是超时,再改回 true + fast-open: true + retry: 60 + retry_interval: 5 + + + - name: "leafvless" + type: vless + server: 104.223.57.113 + port: 31364 + uuid: d8165fe1-57e4-424c-8674-4559e22790dc + flow: xtls-rprx-vision + udp: true + packet-encoding: xudp + + tls: true + servername: proxy.smallzhiyuns.com + client-fingerprint: chrome + skip-cert-verify: true + reality-opts: + public-key: W-2MnNH5XiSstFwh9IyMcMFcdvTH32brc0N9d7e1Q3w + short-id: 6ba85179e30d4fc2 + network: tcp + smux: + enabled: false + + - name: leaftuic + type: tuic + server: proxy.smallzhiyuns.com + port: 29121 + uuid: d8165fe1-57e4-424c-8674-4559e22790dc + password: d8165fe1-57e4-424c-8674-4559e22790dc + + # 可选优化字段(参考官方推荐) + alpn: + - h3 + udp-relay-mode: native + congestion-controller: bbr + disable-sni: false + reduce-rtt: true + request-timeout: 8000 + heartbeat-interval: 10000 + tls: true + sni: hy2.smallzhiyuns.com + skip-cert-verify: true + fast-open: true + max-open-streams: 20 + max-udp-relay-packet-size: 1500 + udp: true + +proxy-groups: + - type: select + name: 🚀 节点选择 + proxies: + - DIRECT + - REJECT + - ⚡ 自动选择 + - proxycheap + - 242af835-singbox_hysteria + - hackrobot-singbox_tuic + - VLESS_Reality_Vision + - 242af835-singbox_hysteria2 + - hackrobot-singbox_tuic2 + - VLESS_Reality_Vision2 + - 5d723acc-singbox_hysteria3 + - 5d723acc-singbox_tuic3 + - 5d723acc-VLESS_Reality_Vision3 + - leafHY2 + - leafvless + - leaftuic + - name: dialer + type: select + proxies: + - 242af835-singbox_hysteria + - hackrobot-singbox_tuic + - VLESS_Reality_Vision + - 242af835-singbox_hysteria2 + - hackrobot-singbox_tuic2 + - VLESS_Reality_Vision2 + - 5d723acc-singbox_hysteria3 + - 5d723acc-singbox_tuic3 + - 5d723acc-VLESS_Reality_Vision3 + - leafHY2 + - leafvless + - leaftuic + + - name: ⚡ 自动选择 + type: url-test + proxies: + - 242af835-singbox_hysteria + - hackrobot-singbox_tuic + - VLESS_Reality_Vision + url: https://www.gstatic.com/generate_204 + interval: 300 + lazy: false + - type: select + name: 🏠 私有网络 + proxies: + - 🚀 节点选择 + - DIRECT + - REJECT + - ⚡ 自动选择 + - 242af835-singbox_hysteria2 + - type: select + name: 🔒 国内服务 + proxies: + - 🚀 节点选择 + - DIRECT + - REJECT + - ⚡ 自动选择 + - 242af835-singbox_hysteria2 + - type: select + name: 🌐 非中国 + proxies: + - 🚀 节点选择 + - DIRECT + - REJECT + - ⚡ 自动选择 + - 242af835-singbox_hysteria2 + - type: select + name: 🐟 漏网之鱼 + proxies: + - 🚀 节点选择 + - DIRECT + - REJECT + - ⚡ 自动选择 + - 242af835-singbox_hysteria2 +rules: + - RULE-SET,geolocation-cn,🔒 国内服务 + - RULE-SET,geolocation-!cn,🌐 非中国 + - RULE-SET,private,🏠 私有网络,no-resolve + - RULE-SET,cn,🔒 国内服务,no-resolve + - MATCH,🐟 漏网之鱼 \ No newline at end of file diff --git a/d2ypp2/.gitattributes b/d2ypp2/.gitattributes new file mode 100644 index 0000000..7474048 --- /dev/null +++ b/d2ypp2/.gitattributes @@ -0,0 +1,23 @@ +*.sh text eol=lf +*.bash text eol=lf +*.py text eol=lf +*.md text eol=lf +install*.sh text eol=lf +start.sh text eol=lf +dev.sh text eol=lf +web.sh text eol=lf +doctor.sh text eol=lf +probe-live.sh text eol=lf +refresh-live-unit.sh text eol=lf +upgrade*.sh text eol=lf +uninstall.sh text eol=lf +services/neko/browser-launch.sh text eol=lf +requirements*.txt text eol=lf +Dockerfile text eol=lf +*.json text eol=lf +*.mjs text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.css text eol=lf +*.yml text eol=lf +*.yaml text eol=lf diff --git a/d2ypp2/config/system-stack.env.example b/d2ypp2/config/system-stack.env.example index 21b8133..1587bc7 100644 --- a/d2ypp2/config/system-stack.env.example +++ b/d2ypp2/config/system-stack.env.example @@ -65,8 +65,14 @@ NEKO_HTTP_PORT_1=9200 NEKO_HTTP_PORT_2=9201 NEKO_HTTP_PORT_3=9202 NEKO_START_URL=https://accounts.google.com/ServiceLogin?continue=https://www.youtube.com/ +# Optional explicit image override. When set, it takes precedence over NEKO_IMAGE_X86 / NEKO_IMAGE_ARM64. +# Example for slow GHCR networks: NEKO_IMAGE=ghcr.nju.edu.cn/m1k1o/neko/chromium:3.0.0 +# ARM64 mirror example: NEKO_IMAGE=swr.cn-north-4.myhuaweicloud.com/ddn-k8s/ghcr.io/m1k1o/neko/chromium:3.0.6-linuxarm64 +NEKO_IMAGE= NEKO_IMAGE_X86=ghcr.io/m1k1o/neko/google-chrome:3.0.0 NEKO_IMAGE_ARM64=ghcr.io/m1k1o/neko/chromium:3.0.0 +# Seconds before install continues if the Neko image registry is slow. Set 0 to wait forever. +NEKO_INSTALL_TIMEOUT=900 NEKO_INSTANCE_COUNT=2 NEKO_MAX_INSTANCE_COUNT=64 # Neko 浏览器登录:显示昵称可填 live / admin;密码与全站策略一致(默认 12345678) @@ -79,6 +85,8 @@ NEKO_DESKTOP_SCREEN=1280x720@15 NEKO_MAX_FPS=15 NEKO_VIDEO_BITRATE=1200 NEKO_BROWSER_RENDER_MODE=auto +# Keep disabled by default: managed policies plus the seeded profile install Tampermonkey without Chromium wrapper --load-extension flags. +NEKO_EXTERNAL_EXTENSIONS=0 # 默认使用官方 Chrome policy 给 Tampermonkey 下发 YouTube 脚本,保证新建频道也自动可用。 # 如必须隐藏“由组织管理”提示,可改为 0;此时只保留个人 profile 种子,脚本导入为 best-effort。 NEKO_MANAGED_POLICIES=1 @@ -122,6 +130,8 @@ REDROID_IMAGE_X86=fahaddz/redroid:13 REDROID_IMAGE_X86_ALT=fahaddz/redroid:13 REDROID_IMAGE_ARM64=fahaddz/redroid:13-arm-pi5 REDROID_IMAGE_ARM64_ALT=fahaddz/redroid:13-arm-pi5 +# Seconds before install continues if Redroid image pull/create is slow. Set 0 to wait forever. +REDROID_INSTALL_TIMEOUT=900 # Android gateway mode(仅双网口直连安卓板时需要;单网口留空 ANDROID_DOWNLINK_IF 即可,控制台为「跳过」) ANDROID_GATEWAY_NAME=live-android-gateway @@ -133,6 +143,8 @@ ANDROID_PANEL_DIR=/opt/live-modules/web-scrcpy ANDROID_PANEL_VIDEO_BIT_RATE=1024000 # Optional modules +# Shared timeout for optional Docker modules during install. Set 0 to wait forever. +DOCKER_OPTIONAL_INSTALL_TIMEOUT=900 # Shared ENABLE_SHELLCRASH=1 ENABLE_WEBTTY=1 diff --git a/d2ypp2/docs/install-profiles.md b/d2ypp2/docs/install-profiles.md index b37a728..fd168f9 100644 --- a/d2ypp2/docs/install-profiles.md +++ b/d2ypp2/docs/install-profiles.md @@ -45,7 +45,7 @@ It focuses on the real delivery path for this project: 刷新依赖、重建前端、重启 `live-console` 与 `live-edge`(**不要**为此再跑 `install-all.sh`,除非你要重做整机栈): ```bash -cd /home/live/douyinyoutube # 或你的克隆路径 +cd /home/orangepi/d2ypp2-src # 或你的克隆路径 sudo bash upgrade-live.sh ``` diff --git a/d2ypp2/pyproject.toml b/d2ypp2/pyproject.toml index b2340a6..337a6bc 100644 --- a/d2ypp2/pyproject.toml +++ b/d2ypp2/pyproject.toml @@ -13,7 +13,8 @@ dependencies = [ "distro>=1.9.0", "tqdm>=4.67.1", "httpx[http2]>=0.28.1", - "PyExecJS>=1.5.1" + "PyExecJS>=1.5.1", + "PyYAML>=5.4.1" ] [project.urls] diff --git a/d2ypp2/requirements.txt b/d2ypp2/requirements.txt index d711db5..323a38d 100644 --- a/d2ypp2/requirements.txt +++ b/d2ypp2/requirements.txt @@ -3,9 +3,12 @@ loguru>=0.7.3 pycryptodome>=3.20.0 distro>=1.9.0 tqdm>=4.67.1 -httpx[http2]>=0.28.1 +httpx[http2]>=0.28.1,<0.29.0 PyExecJS>=1.5.1 -fastapi>=0.115.0 +fastapi>=0.115.0,<0.116.0 +starlette>=0.40.0,<0.47.0 +pydantic>=2.9.0,<3.0.0 eval-type-backport>=0.2.0 -uvicorn[standard]>=0.30.0 +uvicorn[standard]>=0.30.0,<0.36.0 python-multipart>=0.0.9 +PyYAML>=5.4.1 diff --git a/d2ypp2/scripts/launch.py b/d2ypp2/scripts/launch.py index f33554d..bdc188d 100644 --- a/d2ypp2/scripts/launch.py +++ b/d2ypp2/scripts/launch.py @@ -155,6 +155,7 @@ def _runtime_env(runtime: NodeRuntime, extra: dict[str, str] | None = None) -> d path = env.get("PATH", "") node_dir = str(runtime.node.parent) env["PATH"] = f"{node_dir}{os.pathsep}{path}" if path else node_dir + env.setdefault("NEXT_TELEMETRY_DISABLED", "1") if runtime.npm is not None: env["npm_config_script_shell"] = env.get("npm_config_script_shell", "/bin/sh") if extra: diff --git a/d2ypp2/scripts/linux/install_all.sh b/d2ypp2/scripts/linux/install_all.sh index 8fa8a05..e9803fe 100755 --- a/d2ypp2/scripts/linux/install_all.sh +++ b/d2ypp2/scripts/linux/install_all.sh @@ -26,6 +26,7 @@ configure_wifi_profile install_shellcrash install_browser_stack install_neko_browser +install_neko_ip_watch_service install_redroid prepare_mitmproxy prepare_vscode_server diff --git a/d2ypp2/scripts/linux/lib/common.sh b/d2ypp2/scripts/linux/lib/common.sh index f105173..cf8bc6a 100755 --- a/d2ypp2/scripts/linux/lib/common.sh +++ b/d2ypp2/scripts/linux/lib/common.sh @@ -57,14 +57,18 @@ apt_update_once() { apt_install() { apt_update_once - if apt-get install -y --no-install-recommends "$@"; then + export DEBIAN_FRONTEND=noninteractive + local -a dpkg_opts=( + -o Dpkg::Options::=--force-confdef + -o Dpkg::Options::=--force-confold + ) + if apt-get install -y --no-install-recommends "${dpkg_opts[@]}" "$@"; then return 0 fi log "apt install failed; trying dpkg --configure -a and apt -f install" - export DEBIAN_FRONTEND=noninteractive - dpkg --configure -a 2>/dev/null || true - apt-get -f install -y || true - apt-get install -y --no-install-recommends "$@" + dpkg --force-confdef --force-confold --configure -a 2>/dev/null || true + apt-get -f install -y "${dpkg_opts[@]}" || true + apt-get install -y --no-install-recommends "${dpkg_opts[@]}" "$@" } allow_tcp_port_if_firewall_active() { @@ -159,6 +163,37 @@ compose_in_service_dir() { ) } +run_optional_with_timeout() { + local seconds="$1" + shift + if [ -z "$seconds" ] || [ "$seconds" = "0" ] || ! have timeout; then + "$@" + else + timeout "$seconds" "$@" + fi +} + +compose_in_service_dir_timed() { + local seconds="$1" + local compose_file="$2" + shift 2 + if [ -z "$seconds" ] || [ "$seconds" = "0" ] || ! have timeout; then + compose_in_service_dir "$compose_file" "$@" + return + fi + local d base + d="$(cd "$(dirname "$compose_file")" && pwd)" + base="$(basename "$compose_file")" + ( + cd "$d" + if docker compose version >/dev/null 2>&1; then + timeout "$seconds" docker compose -f "$base" "$@" + else + timeout "$seconds" docker-compose -f "$base" "$@" + fi + ) +} + as_live() { runuser -u live -- bash -lc "cd '$ROOT_DIR' && $*" } @@ -326,6 +361,10 @@ load_env() { } resolve_neko_image() { + if [ -n "${NEKO_IMAGE:-}" ]; then + printf '%s' "$NEKO_IMAGE" + return 0 + fi case "$(uname -m)" in x86_64|amd64) printf '%s' "$NEKO_IMAGE_X86" @@ -797,9 +836,14 @@ install_base_packages() { git curl wget jq unzip xz-utils ca-certificates sudo \ python3 python3-venv python3-pip build-essential \ avahi-daemon avahi-utils libnss-mdns \ - network-manager dnsmasq net-tools \ + network-manager dnsmasq-base net-tools \ bluez usbutils v4l-utils systemctl enable --now NetworkManager 2>/dev/null || true + if systemctl is-active --quiet systemd-resolved 2>/dev/null && systemctl is-enabled dnsmasq >/dev/null 2>&1; then + log "Disabling dnsmasq.service because systemd-resolved already owns port 53" + systemctl disable --now dnsmasq >/dev/null 2>&1 || true + systemctl reset-failed dnsmasq >/dev/null 2>&1 || true + fi } install_media_packages() { @@ -862,6 +906,8 @@ install_docker_stack() { return 0 fi if have docker; then + systemctl enable --now docker >/dev/null 2>&1 || true + usermod -aG docker live 2>/dev/null || true if docker compose version >/dev/null 2>&1; then return 0 fi @@ -1256,12 +1302,67 @@ configure_wifi_profile() { fi } +shellcrash_cpu_core() { + case "$(uname -m)" in + aarch64|arm64) printf '%s\n' arm64 ;; + armv7l|armv7*) printf '%s\n' armv7 ;; + x86_64|amd64) printf '%s\n' amd64 ;; + *) printf '%s\n' "$(uname -m)" ;; + esac +} + +shellcrash_set_cfg_default() { + local cfg="$1" key="$2" value="$3" + if ! grep -q "^${key}=" "$cfg" 2>/dev/null; then + printf '%s=%s\n' "$key" "$value" >>"$cfg" + fi +} + +harden_shellcrash_runtime() { + if [ ! -d "$SHELLCRASH_DIR" ]; then + return 0 + fi + log "Hardening ShellCrash runtime defaults" + mkdir -p "$SHELLCRASH_DIR/yamls" "$SHELLCRASH_DIR/configs" /tmp/ShellCrash + local cfg="$SHELLCRASH_DIR/configs/ShellCrash.cfg" + [ -f "$cfg" ] || printf '%s\n' "#ShellCrash配置文件,不明勿动!" >"$cfg" + + shellcrash_set_cfg_default "$cfg" crashcore meta + shellcrash_set_cfg_default "$cfg" cpucore "$(shellcrash_cpu_core)" + shellcrash_set_cfg_default "$cfg" redir_mod "Redir模式" + shellcrash_set_cfg_default "$cfg" firewall_area 3 + shellcrash_set_cfg_default "$cfg" dns_mod redir_host + shellcrash_set_cfg_default "$cfg" mix_port 7890 + shellcrash_set_cfg_default "$cfg" redir_port 7892 + shellcrash_set_cfg_default "$cfg" tproxy_port 7893 + shellcrash_set_cfg_default "$cfg" db_port 9999 + shellcrash_set_cfg_default "$cfg" dns_port 1053 + shellcrash_set_cfg_default "$cfg" network_check OFF + + if ! grep -q '^crashcore=.*singbox' "$cfg" 2>/dev/null; then + cat >"$SHELLCRASH_DIR/configs/command.env" </dev/null | grep -q '^shellcrash.service'; then + local unit_path + unit_path="$(systemctl show -p FragmentPath shellcrash.service 2>/dev/null | sed 's/^FragmentPath=//')" + if [ -n "$unit_path" ] && [ -f "$unit_path" ]; then + sed -i "s#^ExecStart=.*#ExecStart=/tmp/ShellCrash/CrashCore -d $SHELLCRASH_DIR -f /tmp/ShellCrash/config.yaml#" "$unit_path" + systemctl daemon-reload + fi + fi + fi +} + install_shellcrash() { if [ "${ENABLE_SHELLCRASH:-1}" != "1" ]; then return 0 fi if [ -x "$SHELLCRASH_DIR/start.sh" ]; then log "ShellCrash already installed" + harden_shellcrash_runtime return 0 fi log "Installing ShellCrash" @@ -1284,6 +1385,7 @@ install_shellcrash() { log "ShellCrash install script returned error — continuing; configure manually under $SHELLCRASH_DIR if needed" return 0 fi + harden_shellcrash_runtime } install_browser_stack() { @@ -1292,6 +1394,10 @@ install_browser_stack() { fi log "Installing browser stack" export DEBIAN_FRONTEND=noninteractive + local chromium_browser_is_snap=0 + if apt-cache show chromium-browser 2>/dev/null | grep -qiE 'snap|transitional'; then + chromium_browser_is_snap=1 + fi case "$(uname -m)" in x86_64|amd64) if ! have google-chrome && ! have google-chrome-stable; then @@ -1307,7 +1413,13 @@ install_browser_stack() { fi ;; *) - apt_install chromium || apt_install chromium-browser || true + if apt-cache policy chromium 2>/dev/null | awk '/Candidate:/ && $2 != "(none)" { found = 1 } END { exit(found ? 0 : 1) }'; then + apt_install chromium || true + elif [ "$chromium_browser_is_snap" != 1 ] && apt-cache policy chromium-browser 2>/dev/null | awk '/Candidate:/ && $2 != "(none)" { found = 1 } END { exit(found ? 0 : 1) }'; then + apt_install chromium-browser || true + else + log "Host Chromium skipped: apt package unavailable or snap-only on this architecture; Neko Docker browsers remain available" + fi ;; esac mkdir -p /etc/chromium/policies/managed /etc/chromium-browser/policies/managed /etc/opt/chrome/policies/managed @@ -1341,7 +1453,7 @@ install_neko_browser() { set -a [ -f "$STACK_ENV" ] && . "$STACK_ENV" set +a - local idx neko_prof instance_count port mux udp range compose_file + local idx neko_prof instance_count port mux udp range compose_file neko_timeout instance_count="$(resolve_neko_instance_count)" export NEKO_HTTP_PORT="${NEKO_HTTP_PORT:-9200}" export NEKO_HTTP_PORT_1="${NEKO_HTTP_PORT_1:-$NEKO_HTTP_PORT}" @@ -1402,7 +1514,10 @@ install_neko_browser() { done remove_legacy_neko_container compose_file="$(render_neko_compose_file)" - compose_in_service_dir "$compose_file" up -d + neko_timeout="${NEKO_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" + if ! compose_in_service_dir_timed "$neko_timeout" "$compose_file" up -d; then + log "WARN: Neko start timed out or failed after ${neko_timeout}s; continuing. Run: sudo bash $ROOT_DIR/scripts/linux/service_ctl.sh neko start" + fi } install_redroid() { @@ -1413,7 +1528,7 @@ install_redroid() { log "Redroid skipped: docker unavailable" return 0 fi - local image name data_dir + local image name data_dir redroid_timeout case "$(uname -m)" in x86_64|amd64) image="${REDROID_IMAGE:-${REDROID_IMAGE_X86_ALT:-$REDROID_IMAGE_X86}}" ;; aarch64|arm64) image="${REDROID_IMAGE:-${REDROID_IMAGE_ARM64_ALT:-$REDROID_IMAGE_ARM64}}" ;; @@ -1428,6 +1543,8 @@ install_redroid() { log "Removing incompatible Redroid container (${name})" docker rm -f "$name" >/dev/null 2>&1 || true fi + systemctl disable --now live-redroid-host.service >/dev/null 2>&1 || true + systemctl reset-failed live-redroid-host.service >/dev/null 2>&1 || true return 0 fi mkdir -p "$data_dir" @@ -1451,7 +1568,8 @@ install_redroid() { fi fi log "Installing Redroid container (${image})" - docker run -d \ + redroid_timeout="${REDROID_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" + run_optional_with_timeout "$redroid_timeout" docker run -d \ --name "$name" \ --privileged \ --pull always \ @@ -1468,7 +1586,7 @@ install_redroid() { $( redroid_legacy_binder_devices_ready && printf '%s ' '--device' '/dev/binder' '--device' '/dev/hwbinder' '--device' '/dev/vndbinder' ) \ $( [ -e /dev/rga ] && printf '%s ' '--device /dev/rga' ) \ $( [ -e /dev/mpp_service ] && printf '%s ' '--device /dev/mpp_service' ) \ - "$image" ${REDROID_BOOT_ARGS:-} >/dev/null 2>&1 || log "WARN: Redroid create failed; check /dev/kvm, binderfs, and image availability" + "$image" ${REDROID_BOOT_ARGS:-} >/dev/null 2>&1 || log "WARN: Redroid create timed out or failed after ${redroid_timeout}s; check /dev/kvm, binderfs, and image availability" } configure_adb_udev() { @@ -1488,17 +1606,27 @@ install_android_panel() { log "Installing Android web panel (ws-scrcpy)" mkdir -p "$(dirname "$ANDROID_PANEL_DIR")" ANDROID_PANEL_GIT_URL="${ANDROID_PANEL_GIT_URL:-https://github.com/baixin1228/web-scrcpy.git}" + ANDROID_PANEL_GIT_TIMEOUT="${ANDROID_PANEL_GIT_TIMEOUT:-60}" if [ "$(id -u)" -eq 0 ] && ! git config --global --get-all safe.directory 2>/dev/null | grep -qxF "$ANDROID_PANEL_DIR"; then git config --global --add safe.directory "$ANDROID_PANEL_DIR" fi if [ ! -d "$ANDROID_PANEL_DIR/.git" ]; then - rm -rf "$ANDROID_PANEL_DIR" - if ! retry_run 3 5 git clone "$ANDROID_PANEL_GIT_URL" "$ANDROID_PANEL_DIR"; then + local clone_ok=0 attempt + for attempt in 1 2 3; do + rm -rf "$ANDROID_PANEL_DIR" + if timeout "$ANDROID_PANEL_GIT_TIMEOUT" git -c http.version=HTTP/1.1 clone --depth 1 "$ANDROID_PANEL_GIT_URL" "$ANDROID_PANEL_DIR"; then + clone_ok=1 + break + fi + log "retry ${attempt}/3 failed command: git clone $ANDROID_PANEL_GIT_URL $ANDROID_PANEL_DIR" + sleep 5 + done + if [ "$clone_ok" != 1 ]; then log "WARN: Android web panel clone failed; skipping ws-scrcpy install for now" return 0 fi else - if ! retry_run 3 5 git -C "$ANDROID_PANEL_DIR" pull --ff-only; then + if ! retry_run 3 5 timeout "$ANDROID_PANEL_GIT_TIMEOUT" git -C "$ANDROID_PANEL_DIR" -c http.version=HTTP/1.1 pull --ff-only; then log "WARN: Android web panel update failed; keeping previous ws-scrcpy checkout" return 0 fi @@ -1836,7 +1964,8 @@ prepare_homepage() { fi fi render_homepage_services - compose_in_service_dir "$ROOT_DIR/services/homepage/docker-compose.yml" up -d + compose_in_service_dir_timed "${HOMEPAGE_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" "$ROOT_DIR/services/homepage/docker-compose.yml" up -d || \ + log "WARN: Homepage failed to start before timeout; continuing" } prepare_filebrowser() { @@ -1849,20 +1978,24 @@ prepare_filebrowser() { local fb_cfg_dir="$ROOT_DIR/services/filebrowser/config" local fb_db="$fb_db_dir/filebrowser.db" local fb_settings="$fb_cfg_dir/settings.json" - local fb_tmp_json fb_hash + local fb_tmp_json fb_hash fb_timeout + fb_timeout="${FILEBROWSER_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" mkdir -p "$ROOT_DIR/services/filebrowser/database" "$ROOT_DIR/services/filebrowser/config" rm -f "$fb_db" touch "$fb_db" chmod -R 0777 "$ROOT_DIR/services/filebrowser/database" "$ROOT_DIR/services/filebrowser/config" compose_in_service_dir "$ROOT_DIR/services/filebrowser/docker-compose.yml" down >/dev/null 2>&1 || true - docker run --rm \ + if ! run_optional_with_timeout "$fb_timeout" docker run --rm \ -v "$fb_db_dir:/database" \ -v "$fb_cfg_dir:/config" \ "$fb_image" \ - config init --config /config/settings.json --database /database/filebrowser.db >/dev/null 2>&1 || true + config init --config /config/settings.json --database /database/filebrowser.db >/dev/null 2>&1; then + log "WARN: File Browser config init failed before timeout; skipping File Browser startup" + return 0 + fi - docker run --rm \ + if ! run_optional_with_timeout "$fb_timeout" docker run --rm \ -v "$fb_db_dir:/database" \ -v "$fb_cfg_dir:/config" \ "$fb_image" \ @@ -1875,9 +2008,15 @@ prepare_filebrowser() { --hideLoginButton=false \ --branding.name "Live File Browser" \ --config /config/settings.json \ - --database /database/filebrowser.db >/dev/null + --database /database/filebrowser.db >/dev/null; then + log "WARN: File Browser config set failed before timeout; skipping File Browser startup" + return 0 + fi - fb_hash="$(docker run --rm "$fb_image" hash "$FILEBROWSER_PASS" | tail -n 1)" + fb_hash="$(run_optional_with_timeout "$fb_timeout" docker run --rm "$fb_image" hash "$FILEBROWSER_PASS" | tail -n 1)" || { + log "WARN: File Browser password hash failed before timeout; skipping File Browser startup" + return 0 + } fb_tmp_json="$fb_cfg_dir/filebrowser-users.import.json" FILEBROWSER_HASH="$fb_hash" FILEBROWSER_USER="$FILEBROWSER_USER" python3 - <<'PY' >"$fb_tmp_json" import json @@ -1921,16 +2060,20 @@ print( PY chmod 0666 "$fb_tmp_json" - docker run --rm \ + if ! run_optional_with_timeout "$fb_timeout" docker run --rm \ -w /config \ -v "$fb_db_dir:/database" \ -v "$fb_cfg_dir:/config" \ "$fb_image" \ - users import $(basename "$fb_tmp_json") --overwrite --config /config/settings.json --database /database/filebrowser.db >/dev/null + users import $(basename "$fb_tmp_json") --overwrite --config /config/settings.json --database /database/filebrowser.db >/dev/null; then + log "WARN: File Browser user import failed before timeout; skipping File Browser startup" + return 0 + fi rm -f "$fb_cfg_dir/users.backup.json" rm -f "$fb_tmp_json" - compose_in_service_dir "$ROOT_DIR/services/filebrowser/docker-compose.yml" up -d + compose_in_service_dir_timed "${FILEBROWSER_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" "$ROOT_DIR/services/filebrowser/docker-compose.yml" up -d || \ + log "WARN: File Browser failed to start before timeout; continuing" } prepare_mitmproxy() { @@ -1941,7 +2084,7 @@ prepare_mitmproxy() { mkdir -p "$ROOT_DIR/services/mitmproxy/data" allow_tcp_port_if_firewall_active "$MITMPROXY_WEB_PORT" allow_tcp_port_if_firewall_active "$MITMPROXY_PROXY_PORT" - compose_in_service_dir "$ROOT_DIR/services/mitmproxy/docker-compose.yml" up -d || \ + compose_in_service_dir_timed "${MITMPROXY_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" "$ROOT_DIR/services/mitmproxy/docker-compose.yml" up -d || \ log "WARN: mitmproxy failed to start" } @@ -1952,7 +2095,7 @@ prepare_vscode_server() { log "Preparing code-server" mkdir -p "$ROOT_DIR/services/vscode-server/config" allow_tcp_port_if_firewall_active "$VSCODE_SERVER_PORT" - compose_in_service_dir "$ROOT_DIR/services/vscode-server/docker-compose.yml" up -d || \ + compose_in_service_dir_timed "${VSCODE_SERVER_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" "$ROOT_DIR/services/vscode-server/docker-compose.yml" up -d || \ log "WARN: code-server failed to start" } @@ -1963,7 +2106,7 @@ prepare_uptime_kuma() { log "Preparing Uptime Kuma" mkdir -p "$ROOT_DIR/services/uptime-kuma/data" allow_tcp_port_if_firewall_active "$UPTIME_KUMA_PORT" - compose_in_service_dir "$ROOT_DIR/services/uptime-kuma/docker-compose.yml" up -d || \ + compose_in_service_dir_timed "${UPTIME_KUMA_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" "$ROOT_DIR/services/uptime-kuma/docker-compose.yml" up -d || \ log "WARN: Uptime Kuma failed to start" } @@ -1976,7 +2119,7 @@ prepare_openclaw() { chmod -R 0777 "$OPENCLAW_CONFIG_DIR" "$OPENCLAW_WORKSPACE_DIR" 2>/dev/null || true allow_tcp_port_if_firewall_active "$OPENCLAW_GATEWAY_PORT" allow_tcp_port_if_firewall_active "$OPENCLAW_BRIDGE_PORT" - compose_in_service_dir "$ROOT_DIR/services/openclaw/docker-compose.yml" up -d || \ + compose_in_service_dir_timed "${OPENCLAW_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" "$ROOT_DIR/services/openclaw/docker-compose.yml" up -d || \ log "WARN: OpenClaw failed to start" } @@ -2056,7 +2199,8 @@ prepare_srs() { fi fi mkdir -p "$ROOT_DIR/services/srs/data" - compose_in_service_dir "$ROOT_DIR/services/srs/docker-compose.yml" up -d + compose_in_service_dir_timed "${SRS_INSTALL_TIMEOUT:-${DOCKER_OPTIONAL_INSTALL_TIMEOUT:-900}}" "$ROOT_DIR/services/srs/docker-compose.yml" up -d || \ + log "WARN: SRS failed to start before timeout; continuing" } run_hardware_probe() { @@ -2121,7 +2265,18 @@ install_live_edge_proxy() { esac local ver="2.8.4" local tmp="/tmp/caddy-${ver}-linux-${arch}.tar.gz" - curl -fsSL "https://github.com/caddyserver/caddy/releases/download/v${ver}/caddy_${ver}_linux_${arch}.tar.gz" -o "$tmp" + local url="https://github.com/caddyserver/caddy/releases/download/v${ver}/caddy_${ver}_linux_${arch}.tar.gz" + rm -f "$tmp" /tmp/caddy + if ! retry_run 4 10 curl -fL --connect-timeout 20 --max-time 240 --retry 3 --retry-delay 3 --retry-all-errors "$url" -o "$tmp"; then + if have wget; then + retry_run 4 10 wget -O "$tmp" "$url" || true + fi + fi + if [ ! -s "$tmp" ] || ! tar -tzf "$tmp" caddy >/dev/null 2>&1; then + log "WARN: Caddy download failed or archive is invalid; skipping edge proxy install for now" + rm -f "$tmp" /tmp/caddy + return 0 + fi tar -xzf "$tmp" -C /tmp caddy install -m0755 /tmp/caddy /usr/local/bin/caddy rm -f "$tmp" /tmp/caddy diff --git a/d2ypp2/scripts/linux/service_ctl.sh b/d2ypp2/scripts/linux/service_ctl.sh index ca6913e..d155ae1 100755 --- a/d2ypp2/scripts/linux/service_ctl.sh +++ b/d2ypp2/scripts/linux/service_ctl.sh @@ -3,6 +3,8 @@ set -euo pipefail SERVICE_ID="${1:-}" ACTION="${2:-status}" +ACTION_ARG1="${3:-}" +ACTION_ARG2="${4:-}" ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)" CONFIG_DIR="$ROOT_DIR/config" @@ -254,6 +256,10 @@ docker_container_status() { } resolve_neko_image() { + if [ -n "${NEKO_IMAGE:-}" ]; then + printf '%s' "$NEKO_IMAGE" + return 0 + fi case "$(uname -m)" in x86_64|amd64) printf '%s' "$NEKO_IMAGE_X86" @@ -766,7 +772,7 @@ service_shellcrash_status() { return 0 fi running=0 - detail="$(filtered_pgrep 'CrashCore|shellcrash' | tr '\n' ';' || true)" + detail="$(filtered_pgrep '(^|[ /])CrashCore([ ]|$)' | tr '\n' ';' || true)" if unit_active shellcrash.service || [ -n "$detail" ]; then running=1 fi @@ -781,10 +787,10 @@ service_shellcrash_status() { } service_shellcrash_start() { - if unit_exists shellcrash.service; then - systemctl enable --now shellcrash.service - elif [ -x "$SHELLCRASH_DIR/start.sh" ]; then + if [ -x "$SHELLCRASH_DIR/start.sh" ]; then "$SHELLCRASH_DIR/start.sh" start + elif unit_exists shellcrash.service; then + systemctl enable --now shellcrash.service else kv message "ShellCrash is not installed" exit 1 @@ -792,6 +798,18 @@ service_shellcrash_start() { kv message "ShellCrash started" } +service_shellcrash_restart() { + if [ -x "$SHELLCRASH_DIR/start.sh" ]; then + "$SHELLCRASH_DIR/start.sh" restart + elif unit_exists shellcrash.service; then + systemctl restart shellcrash.service + else + kv message "ShellCrash is not installed" + exit 1 + fi + kv message "ShellCrash restarted" +} + service_shellcrash_stop() { if unit_exists shellcrash.service; then systemctl stop shellcrash.service @@ -801,6 +819,149 @@ service_shellcrash_stop() { kv message "ShellCrash stopped" } +service_shellcrash_apply_profile() { + local src="${ACTION_ARG1:-$SHELLCRASH_DIR/yamls/LsRzcR3pHoA9.yaml}" + local target_node="${ACTION_ARG2:-5d723acc-singbox_tuic3}" + local src_real stage_root shell_yaml_root profile_name cfg unit_path selected + + if [ -z "$target_node" ] || printf '%s' "$target_node" | grep -q '[[:cntrl:]]'; then + kv message "Invalid ShellCrash target node" + exit 1 + fi + if ! have realpath; then + kv message "realpath is required to apply ShellCrash profile" + exit 1 + fi + + src_real="$(realpath -m "$src")" + stage_root="$(realpath -m "$ROOT_DIR/.process_runner")" + shell_yaml_root="$(realpath -m "$SHELLCRASH_DIR/yamls")" + case "$src_real" in + "$stage_root"/*|"$shell_yaml_root"/*) ;; + *) + kv message "ShellCrash profile path must be staged under $stage_root or $shell_yaml_root" + exit 1 + ;; + esac + if [ ! -s "$src_real" ]; then + kv message "ShellCrash profile is missing or empty: $src_real" + exit 1 + fi + + mkdir -p "$SHELLCRASH_DIR/yamls" "$SHELLCRASH_DIR/configs" /tmp/ShellCrash + profile_name="$(basename "$src_real")" + case "$profile_name" in + *.yaml|*.yml) ;; + *) profile_name="LsRzcR3pHoA9.yaml" ;; + esac + install -m 0644 "$src_real" "$SHELLCRASH_DIR/yamls/$profile_name" + install -m 0644 "$src_real" "$SHELLCRASH_DIR/yamls/config.yaml" + rm -f "$SHELLCRASH_DIR/configs/web_save" "$SHELLCRASH_DIR/.start_error" + + cfg="$SHELLCRASH_DIR/configs/ShellCrash.cfg" + [ -f "$cfg" ] || printf '%s\n' "#ShellCrash配置文件,不明勿动!" >"$cfg" + set_shellcrash_cfg() { + local key="$1" value="$2" + sed -i "/^${key}=.*/d" "$cfg" + printf '%s=%s\n' "$key" "$value" >>"$cfg" + } + set_shellcrash_cfg crashcore meta + set_shellcrash_cfg cpucore arm64 + set_shellcrash_cfg redir_mod "Redir模式" + set_shellcrash_cfg firewall_area 3 + set_shellcrash_cfg dns_mod redir_host + set_shellcrash_cfg mix_port 7890 + set_shellcrash_cfg redir_port 7892 + set_shellcrash_cfg tproxy_port 7893 + set_shellcrash_cfg db_port 9999 + set_shellcrash_cfg dns_port 1053 + set_shellcrash_cfg proxies_bypass ON + set_shellcrash_cfg sniffer ON + set_shellcrash_cfg skip_cert ON + set_shellcrash_cfg common_ports ON + set_shellcrash_cfg multiport "22,53,80,123,443,8080,8443" + set_shellcrash_cfg network_check OFF + + cat >"$SHELLCRASH_DIR/configs/command.env" </dev/null 2>&1 || true + systemctl restart shellcrash.service + elif [ -x "$SHELLCRASH_DIR/start.sh" ]; then + "$SHELLCRASH_DIR/start.sh" restart + else + kv message "ShellCrash is not installed" + exit 1 + fi + + selected="" + if have python3; then + selected="$(python3 - "$target_node" "$SHELLCRASH_DIR/configs/ShellCrash.cfg" <<'PY' || true +import json +import sys +import time +import urllib.parse +import urllib.request + +target = sys.argv[1] +cfg_path = sys.argv[2] +base = "http://127.0.0.1:9999" +secret = "" +try: + with open(cfg_path, encoding="utf-8", errors="replace") as fh: + for line in fh: + if line.startswith("secret="): + secret = line.split("=", 1)[1].strip() + break +except OSError: + pass + +headers = {"Content-Type": "application/json"} +if secret: + headers["Authorization"] = f"Bearer {secret}" + +def request(path, *, data=None, method="GET"): + req = urllib.request.Request(base + path, data=data, headers=headers, method=method) + return urllib.request.urlopen(req, timeout=3).read() + +last = None +for _ in range(30): + try: + payload = json.loads(request("/proxies").decode("utf-8")) + break + except Exception as exc: # noqa: BLE001 + last = exc + time.sleep(1) +else: + raise SystemExit(f"api unavailable: {last}") + +changed = [] +for name, item in payload.get("proxies", {}).items(): + all_nodes = item.get("all") or [] + if target in all_nodes and item.get("type") in ("Selector", "URLTest", "Fallback", "LoadBalance"): + body = json.dumps({"name": target}).encode("utf-8") + request("/proxies/" + urllib.parse.quote(name, safe=""), data=body, method="PUT") + changed.append(name) +print("|".join(changed)) +PY +)" + fi + + kv message "ShellCrash profile applied" + kv profile "$SHELLCRASH_DIR/yamls/config.yaml" + kv target_node "$target_node" + kv selected "$selected" +} + service_srs_status() { if ! have docker || [ ! -f "$SRS_COMPOSE" ]; then kv available 0 diff --git a/d2ypp2/services/neko/browser-launch.sh b/d2ypp2/services/neko/browser-launch.sh index 6c583a3..38f2f93 100755 --- a/d2ypp2/services/neko/browser-launch.sh +++ b/d2ypp2/services/neko/browser-launch.sh @@ -248,14 +248,31 @@ visible_window_count() { DISPLAY="${DISPLAY:?DISPLAY is required}" xdotool search --onlyvisible --class "$browser_class" 2>/dev/null | wc -l | tr -d ' ' } +devtools_ready() { + if command -v curl >/dev/null 2>&1; then + curl -fsS --max-time 1 http://127.0.0.1:9222/json/version >/dev/null 2>&1 && return 0 + fi + if command -v wget >/dev/null 2>&1; then + wget -q -T 1 -O /dev/null http://127.0.0.1:9222/json/version >/dev/null 2>&1 && return 0 + fi + return 1 +} + +browser_healthy() { + window_count="$(visible_window_count || true)" + if [ -n "${window_count:-}" ] && [ "$window_count" -gt 0 ] 2>/dev/null; then + return 0 + fi + devtools_ready +} + launch_browser seen_window=0 startup_misses=0 closed_misses=0 while kill -0 "$browser_pid" 2>/dev/null; do - window_count="$(visible_window_count || true)" - if [ -n "${window_count:-}" ] && [ "$window_count" -gt 0 ] 2>/dev/null; then + if browser_healthy; then seen_window=1 startup_misses=0 closed_misses=0 @@ -263,12 +280,14 @@ while kill -0 "$browser_pid" 2>/dev/null; do if [ "$seen_window" -eq 0 ]; then startup_misses=$((startup_misses + 1)) if [ "$startup_misses" -ge 15 ]; then + echo "Chromium did not expose a visible window or DevTools endpoint; restarting" kill -TERM "$browser_pid" 2>/dev/null || true break fi else closed_misses=$((closed_misses + 1)) if [ "$closed_misses" -ge 3 ]; then + echo "Chromium health check failed after startup; restarting" kill -TERM "$browser_pid" 2>/dev/null || true break fi diff --git a/d2ypp2/services/neko/docker-compose.yml b/d2ypp2/services/neko/docker-compose.yml index ce590be..ff2c626 100644 --- a/d2ypp2/services/neko/docker-compose.yml +++ b/d2ypp2/services/neko/docker-compose.yml @@ -42,9 +42,6 @@ services: - "${NEKO_POLICY_DIR:-./policies}:/etc/chromium/policies/managed:ro" - "${NEKO_POLICY_DIR:-./policies}:/etc/chromium-browser/policies/managed:ro" - "${NEKO_POLICY_DIR:-./policies}:/etc/opt/chrome/policies/managed:ro" - - "./external-extensions:/opt/google/chrome/extensions:ro" - - "./external-extensions:/usr/share/chromium/extensions:ro" - - "./external-extensions:/usr/share/chromium-browser/extensions:ro" - "./tampermonkey-seed:/etc/neko/tampermonkey-seed:ro" - "./provisioning:/var/www/provisioning:ro" - "./browser-launch.sh:/etc/neko/browser-launch.sh:ro" @@ -69,9 +66,6 @@ services: - "${NEKO_POLICY_DIR:-./policies}:/etc/chromium/policies/managed:ro" - "${NEKO_POLICY_DIR:-./policies}:/etc/chromium-browser/policies/managed:ro" - "${NEKO_POLICY_DIR:-./policies}:/etc/opt/chrome/policies/managed:ro" - - "./external-extensions:/opt/google/chrome/extensions:ro" - - "./external-extensions:/usr/share/chromium/extensions:ro" - - "./external-extensions:/usr/share/chromium-browser/extensions:ro" - "./tampermonkey-seed:/etc/neko/tampermonkey-seed:ro" - "./provisioning:/var/www/provisioning:ro" - "./browser-launch.sh:/etc/neko/browser-launch.sh:ro" @@ -96,9 +90,6 @@ services: - "${NEKO_POLICY_DIR:-./policies}:/etc/chromium/policies/managed:ro" - "${NEKO_POLICY_DIR:-./policies}:/etc/chromium-browser/policies/managed:ro" - "${NEKO_POLICY_DIR:-./policies}:/etc/opt/chrome/policies/managed:ro" - - "./external-extensions:/opt/google/chrome/extensions:ro" - - "./external-extensions:/usr/share/chromium/extensions:ro" - - "./external-extensions:/usr/share/chromium-browser/extensions:ro" - "./tampermonkey-seed:/etc/neko/tampermonkey-seed:ro" - "./provisioning:/var/www/provisioning:ro" - "./browser-launch.sh:/etc/neko/browser-launch.sh:ro" diff --git a/d2ypp2/src/control_plane.py b/d2ypp2/src/control_plane.py index bd79a5c..0694d28 100644 --- a/d2ypp2/src/control_plane.py +++ b/d2ypp2/src/control_plane.py @@ -26,6 +26,9 @@ HW_PROFILE_JSON = CONFIG_DIR / "hardware-profile.json" STACK_ENV = CONFIG_DIR / "system-stack.env" MAX_FILES_PER_ROOT = 256 BASH_BIN = "/bin/bash" if Path("/bin/bash").is_file() else (shutil.which("bash") or "bash") +SHELLCRASH_DEFAULT_PROFILE = "LsRzcR3pHoA9.yaml" +SHELLCRASH_DEFAULT_NODE = "5d723acc-singbox_tuic3" +SHELLCRASH_PROFILE_STAGE = BASE_DIR / ".process_runner" / "shellcrash-profile.yaml" _PRO_URL_CONFIG_INI = re.compile(r"^URL_config\.[a-zA-Z0-9_.-]+\.ini$") _PRO_YOUTUBE_INI = re.compile(r"^youtube\.[a-zA-Z0-9_.-]+\.ini$") @@ -320,6 +323,91 @@ def delete_root_file(root_id: str, relative_path: str) -> dict: } +def _normalize_shellcrash_yaml(content: str, target_node: str) -> tuple[str, dict[str, Any]]: + try: + import yaml + except ImportError as exc: # pragma: no cover - depends on deployment image + raise RuntimeError("PyYAML is required to apply ShellCrash YAML profiles") from exc + + data = yaml.safe_load(content) + if not isinstance(data, dict): + raise ValueError("ShellCrash YAML must be a mapping") + proxies = data.get("proxies") or [] + if not any(isinstance(item, dict) and item.get("name") == target_node for item in proxies): + raise ValueError(f"Target proxy node not found: {target_node}") + + default_groups: list[str] = [] + for group in data.get("proxy-groups") or []: + if not isinstance(group, dict) or group.get("type") != "select": + continue + group_proxies = group.get("proxies") + if not isinstance(group_proxies, list) or target_node not in group_proxies: + continue + group["proxies"] = [target_node] + [item for item in group_proxies if item != target_node] + default_groups.append(str(group.get("name") or "")) + + data["allow-lan"] = True + data["mode"] = "rule" + data["mixed-port"] = int(data.get("mixed-port") or data.get("port") or 7890) + data["external-controller"] = "0.0.0.0:9999" + data["log-level"] = "info" + normalized = yaml.safe_dump(data, allow_unicode=True, sort_keys=False, width=4096) + return normalized, { + "target_node": target_node, + "default_groups": default_groups, + "bytes": len(normalized.encode("utf-8")), + } + + +async def apply_shellcrash_profile( + relative_path: str = SHELLCRASH_DEFAULT_PROFILE, + target_node: str = SHELLCRASH_DEFAULT_NODE, +) -> dict: + _, rel, source = _resolve_managed_file("shellcrash-yamls", relative_path) + if not source.is_file(): + raise FileNotFoundError(relative_path) + normalized, meta = _normalize_shellcrash_yaml(source.read_text(encoding="utf-8"), target_node) + + stage_path = SHELLCRASH_PROFILE_STAGE.with_name(rel.name or SHELLCRASH_PROFILE_STAGE.name) + stage_path.parent.mkdir(parents=True, exist_ok=True) + stage_path.write_text(normalized, encoding="utf-8", newline="\n") + with contextlib.suppress(OSError): + stage_path.chmod(0o600) + + cmd = [ + BASH_BIN, + str(SERVICE_CTL), + "shellcrash", + "apply_profile", + str(stage_path), + target_node, + ] + if not SERVICE_CTL.is_file(): + raise RuntimeError("Service controller script is missing") + + if hasattr(os, "geteuid") and os.geteuid() == 0: + code, output = await _run_command(cmd, timeout=180.0) + elif shutil.which("sudo"): + code, output = await _run_command(["sudo", "-n", *cmd], timeout=180.0) + else: + code, output = await _run_command(cmd, timeout=180.0) + + info = _parse_kv_output(output) + if code != 0: + raise RuntimeError(info.get("message") or output or "ShellCrash profile apply failed") + + status = await query_service(next(item for item in SERVICE_SPECS if item.service_id == "shellcrash")) + return { + "message": info.get("message", "ShellCrash profile applied"), + "path": rel.as_posix(), + "target_node": target_node, + "default_groups": meta["default_groups"], + "bytes": meta["bytes"], + "selected": info.get("selected", ""), + "service": status, + } + + def _parse_kv_output(text: str) -> dict[str, str]: data: dict[str, str] = {} for raw in text.splitlines(): diff --git a/d2ypp2/tools/bootstrap_remote_repo_paramiko.py b/d2ypp2/tools/bootstrap_remote_repo_paramiko.py index a711060..335c6c6 100644 --- a/d2ypp2/tools/bootstrap_remote_repo_paramiko.py +++ b/d2ypp2/tools/bootstrap_remote_repo_paramiko.py @@ -12,10 +12,10 @@ except ImportError: print("请先安装: pip install paramiko", file=sys.stderr) sys.exit(1) -HOST = os.environ.get("LIVE_DEPLOY_HOST", "192.168.21.105") -USER = os.environ.get("LIVE_DEPLOY_USER", "live") -PASS = os.environ.get("LIVE_DEPLOY_PASS", "12345678") -REMOTE_BASE = os.environ.get("LIVE_DEPLOY_PATH", "/home/live/douyinyoutube").rstrip("/") +HOST = os.environ.get("LIVE_DEPLOY_HOST", "192.168.31.56") +USER = os.environ.get("LIVE_DEPLOY_USER", "orangepi") +PASS = os.environ.get("LIVE_DEPLOY_PASS", "orangepi") +REMOTE_BASE = os.environ.get("LIVE_DEPLOY_PATH", "/home/orangepi/d2ypp2-src").rstrip("/") def main() -> int: diff --git a/d2ypp2/tools/deploy_live_paramiko.py b/d2ypp2/tools/deploy_live_paramiko.py index a2ccaf0..f749285 100644 --- a/d2ypp2/tools/deploy_live_paramiko.py +++ b/d2ypp2/tools/deploy_live_paramiko.py @@ -17,22 +17,49 @@ except ImportError: print("请先安装: pip install paramiko", file=sys.stderr) sys.exit(1) -HOST = os.environ.get("LIVE_DEPLOY_HOST", "192.168.21.105") -USER = os.environ.get("LIVE_DEPLOY_USER", "live") -PASS = os.environ.get("LIVE_DEPLOY_PASS", "12345678") -REMOTE_BASE = os.environ.get("LIVE_DEPLOY_PATH", "/home/live/douyinyoutube").rstrip("/") +HOST = os.environ.get("LIVE_DEPLOY_HOST", "192.168.31.56") +USER = os.environ.get("LIVE_DEPLOY_USER", "orangepi") +PASS = os.environ.get("LIVE_DEPLOY_PASS", "orangepi") +REMOTE_BASE = os.environ.get("LIVE_DEPLOY_PATH", "/home/orangepi/d2ypp2-src").rstrip("/") REPO_ROOT = Path(__file__).resolve().parent.parent def _discover_repo_files() -> list[str]: - """与 youtube.py 运行相关的源码,避免只同步白名单时缺模块。""" - extra: list[str] = [] - backup_dir = REPO_ROOT / "backup" - if backup_dir.is_dir(): - for p in sorted(backup_dir.glob("*.py")): - extra.append(str(p.relative_to(REPO_ROOT)).replace("\\", "/")) - return extra + """Collect files needed for incremental board deployment without copying caches.""" + extra: set[str] = { + ".gitattributes", + "Dockerfile", + "docker-compose.yaml", + "docker-compose.yml", + "install.sh", + "package.json", + "package-lock.json", + "pyproject.toml", + "requirements.txt", + } + for pattern in ( + "*.sh", + "backup/*.py", + "live-platform/scripts/**/*.sh", + "live-platform/tools/*.py", + "scripts/**/*.py", + "scripts/**/*.sh", + "services/**/*.sh", + "src/**/*.py", + "tiktok/**/*.sh", + "tools/*.py", + "web-console/*.json", + "web-console/*.mjs", + "web-console/*.ts", + "web-console/app/**/*", + "web-console/components/**/*", + "web-console/lib/**/*", + ): + for candidate in REPO_ROOT.glob(pattern): + if candidate.is_file(): + extra.add(str(candidate.relative_to(REPO_ROOT)).replace("\\", "/")) + return sorted(extra) FILES = [ @@ -166,7 +193,7 @@ def mkdir_p(sftp: paramiko.SFTPClient, remote_dir: str) -> None: pass -def _shell_bytes_lf(data: bytes) -> bytes: +def _text_bytes_lf(data: bytes) -> bytes: """Windows 工作区常见 CRLF;上传到 Linux 后 bash 会把 pipefail\\r 当成非法选项。""" return data.replace(b"\r\n", b"\n").replace(b"\r", b"\n") @@ -175,8 +202,14 @@ def sftp_put(sftp: paramiko.SFTPClient, local: Path, remote: str) -> None: remote = remote.replace("\\", "/") parent = posixpath.dirname(remote) mkdir_p(sftp, parent) - if local.suffix.lower() == ".sh": - sftp.putfo(io.BytesIO(_shell_bytes_lf(local.read_bytes())), remote) + if local.suffix.lower() in {".sh", ".py"} or local.name in { + ".gitattributes", + "Dockerfile", + "requirements.txt", + "docker-compose.yaml", + "docker-compose.yml", + }: + sftp.putfo(io.BytesIO(_text_bytes_lf(local.read_bytes())), remote) else: sftp.put(str(local), remote) diff --git a/d2ypp2/tools/probe_board_stack.py b/d2ypp2/tools/probe_board_stack.py index 6c96174..c2fab7f 100644 --- a/d2ypp2/tools/probe_board_stack.py +++ b/d2ypp2/tools/probe_board_stack.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 -"""SSH 到板子:打印 ENABLE_NEKO 与 Docker 中与 srs/neko 相关的容器。 +"""Probe ENABLE_NEKO and Docker service state on the ARM board. -环境变量与 deploy_live_paramiko.py 一致: - LIVE_DEPLOY_HOST(默认 192.168.21.105) - LIVE_DEPLOY_USER(默认 live) - LIVE_DEPLOY_PASS(默认 12345678) +Environment defaults match deploy_live_paramiko.py: + LIVE_DEPLOY_HOST: 192.168.31.56 + LIVE_DEPLOY_USER: orangepi + LIVE_DEPLOY_PASS: orangepi """ from __future__ import annotations @@ -17,13 +17,13 @@ except ImportError: print("请先执行: pip install paramiko", file=sys.stderr) sys.exit(1) -HOST = os.environ.get("LIVE_DEPLOY_HOST", "192.168.21.105") -USER = os.environ.get("LIVE_DEPLOY_USER", "live") -PASS = os.environ.get("LIVE_DEPLOY_PASS", "12345678") +HOST = os.environ.get("LIVE_DEPLOY_HOST", "192.168.31.56") +USER = os.environ.get("LIVE_DEPLOY_USER", "orangepi") +PASS = os.environ.get("LIVE_DEPLOY_PASS", "orangepi") REMOTE_SH = r""" echo "--- ENABLE_NEKO in known env files ---" -for f in /opt/live/config/system-stack.env /opt/live/generated/system-stack.env /home/live/douyinyoutube/config/system-stack.env; do +for f in /opt/live/config/system-stack.env /opt/live/generated/system-stack.env /home/orangepi/d2ypp2-src/config/system-stack.env; do if [ -f "$f" ]; then echo "=== $f ===" grep -E '^ENABLE_NEKO=' "$f" 2>/dev/null || echo '(no ENABLE_NEKO line)' diff --git a/d2ypp2/tools/render_neko_compose.py b/d2ypp2/tools/render_neko_compose.py index 17fd41a..97f5aa5 100644 --- a/d2ypp2/tools/render_neko_compose.py +++ b/d2ypp2/tools/render_neko_compose.py @@ -57,6 +57,7 @@ def render(count: int) -> str: http_base = int(env("NEKO_HTTP_PORT", "9200")) mux_base = int(env("NEKO_WEBRTC_TCPMUX", "52300")) managed_policies = env_enabled("NEKO_MANAGED_POLICIES", True) + external_extensions = env_enabled("NEKO_EXTERNAL_EXTENSIONS", False) policy_dir = "./policies" if managed_policies else "./no-managed-policies" lines = [ @@ -109,15 +110,18 @@ def render(count: int) -> str: f" - {q(f'{policy_dir}:/etc/chromium/policies/managed:ro')}", f" - {q(f'{policy_dir}:/etc/chromium-browser/policies/managed:ro')}", f" - {q(f'{policy_dir}:/etc/opt/chrome/policies/managed:ro')}", - ' - "./external-extensions:/opt/google/chrome/extensions:ro"', - ' - "./external-extensions:/usr/share/chromium/extensions:ro"', - ' - "./external-extensions:/usr/share/chromium-browser/extensions:ro"', ' - "./tampermonkey-seed:/etc/neko/tampermonkey-seed:ro"', ' - "./provisioning:/var/www/provisioning:ro"', ' - "./browser-launch.sh:/etc/neko/browser-launch.sh:ro"', f" - {q(f'./{supervisor_conf}:/etc/neko/supervisord/{supervisor_conf}:ro')}", ] ) + if external_extensions: + lines[-3:-3] = [ + ' - "./external-extensions:/opt/google/chrome/extensions:ro"', + ' - "./external-extensions:/usr/share/chromium/extensions:ro"', + ' - "./external-extensions:/usr/share/chromium-browser/extensions:ro"', + ] return "\n".join(lines) + "\n" diff --git a/d2ypp2/tools/ssh_neko_start.py b/d2ypp2/tools/ssh_neko_start.py index 230276e..f0d26fb 100644 --- a/d2ypp2/tools/ssh_neko_start.py +++ b/d2ypp2/tools/ssh_neko_start.py @@ -7,10 +7,10 @@ import sys import paramiko -HOST = os.environ.get("LIVE_DEPLOY_HOST", "192.168.21.105") -USER = os.environ.get("LIVE_DEPLOY_USER", "live") -PASS = os.environ.get("LIVE_DEPLOY_PASS", "12345678") -REMOTE_BASE = os.environ.get("LIVE_DEPLOY_PATH", "/home/live/douyinyoutube").rstrip("/") +HOST = os.environ.get("LIVE_DEPLOY_HOST", "192.168.31.56") +USER = os.environ.get("LIVE_DEPLOY_USER", "orangepi") +PASS = os.environ.get("LIVE_DEPLOY_PASS", "orangepi") +REMOTE_BASE = os.environ.get("LIVE_DEPLOY_PATH", "/home/orangepi/d2ypp2-src").rstrip("/") CMD = ( f"export LC_ALL=C.UTF-8 LANG=C.UTF-8; " diff --git a/d2ypp2/tools/verify_live_console.py b/d2ypp2/tools/verify_live_console.py index 326d39a..c03b982 100644 --- a/d2ypp2/tools/verify_live_console.py +++ b/d2ypp2/tools/verify_live_console.py @@ -15,9 +15,9 @@ except ImportError: print("请先安装: pip install paramiko", file=sys.stderr) raise SystemExit(1) -HOST = os.environ.get("LIVE_DEPLOY_HOST", os.environ.get("LIVE_VERIFY_HOST", "192.168.21.105")) -USER = os.environ.get("LIVE_DEPLOY_USER", os.environ.get("LIVE_VERIFY_USER", "live")) -PASS = os.environ.get("LIVE_DEPLOY_PASS", os.environ.get("LIVE_VERIFY_PASS", "12345678")) +HOST = os.environ.get("LIVE_DEPLOY_HOST", os.environ.get("LIVE_VERIFY_HOST", "192.168.31.56")) +USER = os.environ.get("LIVE_DEPLOY_USER", os.environ.get("LIVE_VERIFY_USER", "orangepi")) +PASS = os.environ.get("LIVE_DEPLOY_PASS", os.environ.get("LIVE_VERIFY_PASS", "orangepi")) PORT = os.environ.get("LIVE_VERIFY_PORT", os.environ.get("PORT", "8001")) MDNS_HOST = os.environ.get("LIVE_VERIFY_DOMAIN", f"{os.environ.get('LIVE_VERIFY_ALIAS', 'live')}.local") LOG = Path(__file__).resolve().parent.parent / ".deploy_logs" / "verify_live_console.log" diff --git a/d2ypp2/tools/verify_local_install.py b/d2ypp2/tools/verify_local_install.py index 5a5a6a1..25665d6 100755 --- a/d2ypp2/tools/verify_local_install.py +++ b/d2ypp2/tools/verify_local_install.py @@ -490,7 +490,6 @@ def verify_neko(checks: list[dict[str, Any]], env: dict[str, str], *, timeout: f "python3 - <<'PY'\n" "import os\n" "skip = {os.getpid(), os.getppid()}\n" - "bad = [b'--load-' + b'extension=', b'youtube-auto-' + b'dismiss-extension']\n" "for name in os.listdir('/proc'):\n" " if not name.isdigit() or int(name) in skip:\n" " continue\n" @@ -498,7 +497,10 @@ def verify_neko(checks: list[dict[str, Any]], env: dict[str, str], *, timeout: f " cmdline = open(f'/proc/{name}/cmdline', 'rb').read()\n" " except OSError:\n" " continue\n" - " if any(marker in cmdline for marker in bad):\n" + " args = [arg for arg in cmdline.split(b'\\0') if arg]\n" + " has_unpacked_ext = any(arg.startswith(b'--load-extension=') and arg.split(b'=', 1)[1].strip() for arg in args)\n" + " has_legacy_youtube_ext = b'youtube-auto-' + b'dismiss-extension' in cmdline\n" + " if has_unpacked_ext or has_legacy_youtube_ext:\n" " print(cmdline.replace(b'\\0', b' ').decode('utf-8', errors='replace'))\n" " raise SystemExit(1)\n" "print('no standalone youtube extension')\n" @@ -527,7 +529,7 @@ def verify_neko(checks: list[dict[str, Any]], env: dict[str, str], *, timeout: f f"neko_{idx}_tm_storage", f"{name} Tampermonkey YouTube script imported", code == 0 and bool(out.strip()), - required=True, + required=not managed_policies, detail=out.strip() or err2.strip() or "not found", hint=( "Open Neko once or restart the browser so Chrome policy imports the provisioning payload." diff --git a/d2ypp2/web-console/components/console/LiveConsoleWorkspace.tsx b/d2ypp2/web-console/components/console/LiveConsoleWorkspace.tsx index 39aaa50..0af505e 100644 --- a/d2ypp2/web-console/components/console/LiveConsoleWorkspace.tsx +++ b/d2ypp2/web-console/components/console/LiveConsoleWorkspace.tsx @@ -60,6 +60,14 @@ type ServiceItem = { port?: string; message?: string; }; +type ShellCrashApplyResponse = { + message?: string; + path?: string; + target_node?: string; + default_groups?: string[]; + selected?: string; + service?: ServiceItem; +}; type SystemSnapshot = { cpu_load?: LoadAvg; disk?: Capacity; @@ -120,6 +128,8 @@ type PreviewMode = "tap" | "double_tap" | "long_press"; const TABS: TabKey[] = ["overview", "business", "modules", "shellcrash", "android", "config"]; const SHELLCRASH_ROOT_IDS = new Set(["shellcrash-configs", "shellcrash-yamls", "shellcrash-jsons"]); +const SHELLCRASH_DEFAULT_PROFILE = "LsRzcR3pHoA9.yaml"; +const SHELLCRASH_DEFAULT_NODE = "5d723acc-singbox_tuic3"; const apiBase = () => (typeof process !== "undefined" && process.env.NEXT_PUBLIC_API_URL) || ""; @@ -711,6 +721,37 @@ export function LiveConsoleWorkspace({ embeddedShellCrash = false, portalLang }: } }; + const applyShellCrashProfile = async (profilePath?: string) => { + const nextPath = + profilePath || + (rootId === "shellcrash-yamls" && filePath ? filePath : SHELLCRASH_DEFAULT_PROFILE); + setBusy("shellcrash:apply"); + try { + if (rootId === "shellcrash-yamls" && filePath === nextPath) { + await fetchJson("/managed_file", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ root: rootId, path: filePath, content: fileContent }), + }); + } + const data = await fetchJson("/shellcrash/apply_profile", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ path: nextPath, target_node: SHELLCRASH_DEFAULT_NODE }), + }); + const selected = data.selected ? ` | ${data.selected}` : ""; + notify(`${data.message || tr("ShellCrash 配置已应用", "ShellCrash profile applied")}${selected}`); + await Promise.all([refreshServices(), refreshFiles("shellcrash-yamls", "config.yaml")]); + setRootId("shellcrash-yamls"); + setFilePath("config.yaml"); + setConfigInsightVersion((value) => value + 1); + } catch (reason) { + notify((reason as Error).message); + } finally { + setBusy(null); + } + }; + const saveFile = async () => { if (!rootId || !filePath) return; setBusy("file:save"); @@ -1301,12 +1342,19 @@ export function LiveConsoleWorkspace({ embeddedShellCrash = false, portalLang }: + ) : null} +
+

{tr("默认代理节点", "Default proxy node")}

+

{SHELLCRASH_DEFAULT_NODE}

+

{tr("应用后会写入 config.yaml、重启 ShellCrash,并把包含该节点的选择组切到此节点。", "Applying writes config.yaml, restarts ShellCrash, and selects this node in matching groups.")}

+

{tr("快捷文件", "Quick Files")}

+ @@ -1325,6 +1373,7 @@ export function LiveConsoleWorkspace({ embeddedShellCrash = false, portalLang }: {busy === "file:import" ? tr("导入中...", "Importing...") : tr("导入/替换", "Import/Replace")} void importManagedFile(event)} /> +
diff --git a/d2ypp2/web-console/out/.build-stamp.json b/d2ypp2/web-console/out/.build-stamp.json index 82db516..589bdcc 100644 --- a/d2ypp2/web-console/out/.build-stamp.json +++ b/d2ypp2/web-console/out/.build-stamp.json @@ -1,6 +1,6 @@ { - "built_at": 1779192557.0621758, - "source_mtime": 1779192388.9499156, + "built_at": 1779981918.3005943, + "source_mtime": 1779981583.0854018, "toolchain": "local", - "node_major": 20 + "node_major": 22 } \ No newline at end of file diff --git a/d2ypp2/web-console/out/404.html b/d2ypp2/web-console/out/404.html index 498972e..aa50aff 100644 --- a/d2ypp2/web-console/out/404.html +++ b/d2ypp2/web-console/out/404.html @@ -1 +1 @@ -404: This page could not be found.无人直播系统 · live.local

404

This page could not be found.

\ No newline at end of file +404: This page could not be found.无人直播系统 · live.local

404

This page could not be found.

\ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/246-316dc23346e75be8.js b/d2ypp2/web-console/out/_next/static/chunks/246-316dc23346e75be8.js new file mode 100644 index 0000000..b2af945 --- /dev/null +++ b/d2ypp2/web-console/out/_next/static/chunks/246-316dc23346e75be8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[246],{9170:function(e,t,l){l.d(t,{Z:function(){return r}});var s=l(7437),a=l(2265);function r(e){let{snapshot:t,theme:r,tr:n}=e,i=(0,a.useRef)(null);return((0,a.useEffect)(()=>{let e=i.current;if(!e||!t)return;let s=!1,a=null,o="light"===r?"#0f172a":"#e2e8f0",c="light"===r?"#64748b":"#94a3b8",d="light"===r?"rgba(15,23,42,0.1)":"rgba(148,163,184,0.12)";l.e(614).then(l.bind(l,9614)).then(e=>{var l,r,h,x,m,u,p,b,g,f,v,j,w;if(s||!i.current)return;a=e.init(i.current,void 0,{renderer:"canvas"});let N=null!==(g=null===(l=t.cpu_load)||void 0===l?void 0:l["1m"])&&void 0!==g?g:0,y=null!==(f=null===(r=t.cpu_load)||void 0===r?void 0:r["5m"])&&void 0!==f?f:0,k=null!==(v=null===(h=t.cpu_load)||void 0===h?void 0:h["15m"])&&void 0!==v?v:0,C=(null===(x=t.memory)||void 0===x?void 0:x.total)||1,S=null!==(w=null!==(j=null===(m=t.memory)||void 0===m?void 0:m.available)&&void 0!==j?j:null===(u=t.memory)||void 0===u?void 0:u.free)&&void 0!==w?w:0,_=(null===(p=t.disk)||void 0===p?void 0:p.total)||1,D=(null===(b=t.disk)||void 0===b?void 0:b.free)||0;a.setOption({animationDurationUpdate:450,textStyle:{color:o},title:{text:n("无人直播节点 \xb7 资源","Unmanned live \xb7 resources"),left:12,top:8,textStyle:{color:o,fontSize:12,fontWeight:600}},tooltip:{trigger:"axis"},grid:{left:52,right:"48%",top:52,bottom:36},xAxis:{type:"category",data:["1m","5m","15m"],axisLabel:{color:c,fontSize:10},axisLine:{lineStyle:{color:d}}},yAxis:{type:"value",name:n("负载","Load"),nameTextStyle:{color:c,fontSize:10},axisLabel:{color:c,fontSize:10},splitLine:{lineStyle:{color:d}}},series:[{name:n("CPU","CPU"),type:"bar",data:[N,y,k],barMaxWidth:28,itemStyle:{borderRadius:[6,6,0,0],color:new e.graphic.LinearGradient(0,0,0,1,[{offset:0,color:"#22d3ee"},{offset:1,color:"#6366f1"}])}},{name:n("内存","RAM"),type:"pie",radius:["26%","40%"],center:["78%","38%"],label:{color:o,fontSize:9},data:[{value:Math.max(0,C-S),name:n("已用","Used")},{value:Math.max(0,S),name:n("可用","Free")}]},{name:n("磁盘","Disk"),type:"pie",radius:["20%","32%"],center:["78%","72%"],label:{color:o,fontSize:9},data:[{value:Math.max(0,_-D),name:n("已用","Used")},{value:Math.max(0,D),name:n("空闲","Free")}]}]})});let h=new ResizeObserver(()=>null==a?void 0:a.resize());return h.observe(e),()=>{s=!0,h.disconnect(),null==a||a.dispose()}},[t,r,n]),t)?(0,s.jsxs)("div",{className:"mt-4",children:[(0,s.jsx)("p",{className:"mb-2 text-xs opacity-70",children:n("ECharts 动态图表","ECharts live charts")}),(0,s.jsx)("div",{ref:i,className:"chart-surface h-64 w-full rounded-2xl border border-white/[0.08] bg-black/15 md:h-72"})]}):null}},2246:function(e,t,l){l.d(t,{d:function(){return S}});var s=l(7437),a=l(3145),r=l(2265),n=l(9170),i=l(2023),o=l(1817),c=l(7168),d=l(6865),h=l(5621),x=l(9076);function m(e){let{lang:t,rootId:l,filePath:a,fileContent:n,refreshKey:m,busy:u,fetchJson:p,notify:b,onChangeContent:g,onRefreshListing:f}=e,[v,j]=(0,r.useState)(null),[w,N]=(0,r.useState)(!1),[y,k]=(0,r.useState)(!1),[C,S]=(0,r.useState)(null),[_,D]=(0,r.useState)(null),E=(0,r.useCallback)((e,l)=>"zh"===t?e:l,[t]),O=(0,r.useCallback)(async()=>{if(!l||!a){j(null);return}N(!0);try{let e=new URLSearchParams({root:l,path:a}),t=await p("/config_insights?".concat(e.toString()));j(t)}catch(e){j(null),b(e.message)}finally{N(!1)}},[p,a,b,l]);(0,r.useEffect)(()=>{O()},[O,m]);let R=async()=>{if(l&&a){k(!0);try{let e=await p("/config_insights",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:l,path:a,content:n})});j(e),b(E("已分析当前编辑内容","Analyzed current editor draft"))}catch(e){b(e.message)}finally{k(!1)}}},T=async e=>{if(l&&a){S(e);try{let t=await p("/config_optimize",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:l,path:a,content:n,action:e})});"string"==typeof t.content&&g(t.content),t.insights&&j(e=>({...e,...t.insights,backups:(null==e?void 0:e.backups)||[]})),b(t.message||E("已应用优化","Optimization applied"))}catch(e){b(e.message)}finally{S(null)}}},A=async e=>{if(l&&a){D(e);try{let t=await p("/config_restore",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:l,path:a,backup_id:e})});"string"==typeof t.content&&g(t.content),await Promise.resolve(null==f?void 0:f()),await O(),b(t.message||E("已恢复历史版本","Backup restored"))}catch(e){b(e.message)}finally{D(null)}}};if(!a)return(0,s.jsx)("div",{className:"rounded-2xl border border-white/8 bg-black/20 p-4 text-sm text-slate-400",children:E("选择文件后显示诊断、回滚和一键优化。","Pick a file to see diagnostics, rollback, and one-click optimizations.")});let U=(null==v?void 0:v.issues)||[],P=(null==v?void 0:v.actions)||[],L=(null==v?void 0:v.backups)||[],I=(null==v?void 0:v.stats)||[];return(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-gradient-to-br from-cyan-500/[0.08] via-black/25 to-transparent p-4",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-white",children:[(0,s.jsx)(i.Z,{className:"h-4 w-4 text-cyan-300"}),(0,s.jsx)("h3",{className:"text-sm font-semibold",children:E("配置治理","Config governance")}),(null==v?void 0:v.source)?(0,s.jsx)("span",{className:"rounded-full border border-white/10 bg-black/25 px-2 py-0.5 text-[10px] uppercase tracking-wider text-slate-400",children:v.source}):null]}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:(null==v?void 0:v.summary)||E("校验配置风险、查看历史快照,并将常见优化应用到编辑器。","Validate risks, inspect snapshots, and apply optimizations into the editor.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsxs)("button",{type:"button",disabled:!!u||w,onClick:()=>void O(),className:"btn-focus inline-flex items-center gap-2 rounded-xl border border-white/10 bg-black/25 px-3 py-2 text-xs text-slate-100 disabled:opacity-40",children:[w?(0,s.jsx)(o.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,s.jsx)(c.Z,{className:"h-3.5 w-3.5"}),E("刷新已保存状态","Refresh saved state")]}),(0,s.jsxs)("button",{type:"button",disabled:!!u||y,onClick:()=>void R(),className:"btn-focus inline-flex items-center gap-2 rounded-xl border border-cyan-500/30 bg-cyan-500/15 px-3 py-2 text-xs text-cyan-100 disabled:opacity-40",children:[y?(0,s.jsx)(o.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,s.jsx)(d.Z,{className:"h-3.5 w-3.5"}),E("分析当前编辑器","Analyze editor draft")]})]})]}),(0,s.jsx)("div",{className:"mt-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-4",children:I.slice(0,8).map(e=>(0,s.jsxs)("div",{className:"rounded-xl border border-white/8 bg-black/20 px-3 py-2.5",children:[(0,s.jsx)("div",{className:"text-[10px] uppercase tracking-wider text-slate-500",children:e.label}),(0,s.jsx)("div",{className:"mt-1 truncate font-mono text-sm text-white",children:e.value})]},e.key))})]}),(0,s.jsxs)("div",{className:"grid gap-4 xl:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/8 bg-black/20 p-4",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-white",children:[(0,s.jsx)(d.Z,{className:"h-4 w-4 text-amber-300"}),(0,s.jsx)("h4",{className:"text-sm font-semibold",children:E("风险与建议","Risks & guidance")})]}),U.length?(0,s.jsx)("div",{className:"mt-3 space-y-2",children:U.map((e,t)=>{var l;return(0,s.jsxs)("div",{className:"rounded-xl border px-3 py-2 text-xs ".concat("error"===(l=e.level)?"border-rose-500/30 bg-rose-500/10 text-rose-100":"warning"===l?"border-amber-500/30 bg-amber-500/10 text-amber-100":"border-cyan-500/30 bg-cyan-500/10 text-cyan-100"),children:[(0,s.jsxs)("div",{className:"font-medium",children:[e.message,e.line?" (L".concat(e.line,")"):""]}),(0,s.jsx)("div",{className:"mt-1 font-mono opacity-70",children:e.code})]},"".concat(e.code,"-").concat(t))})}):(0,s.jsx)("p",{className:"mt-3 text-xs text-emerald-300/90",children:E("当前没有发现明显配置风险。","No obvious config risks were detected.")}),(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:P.length?P.map(e=>(0,s.jsx)("button",{type:"button",disabled:!!u||!!C,onClick:()=>void T(e.id),className:"btn-focus rounded-xl border border-violet-500/30 bg-violet-500/15 px-3 py-2 text-xs text-violet-100 disabled:opacity-40",title:e.description,children:C===e.id?E("处理中...","Working..."):e.label},e.id)):(0,s.jsx)("span",{className:"text-xs text-slate-500",children:E("当前文件没有可自动应用的预设。","No auto-applicable presets for this file.")})})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/8 bg-black/20 p-4",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-white",children:[(0,s.jsx)(h.Z,{className:"h-4 w-4 text-cyan-300"}),(0,s.jsx)("h4",{className:"text-sm font-semibold",children:E("历史快照","Backup snapshots")})]}),L.length?(0,s.jsx)("div",{className:"mt-3 space-y-2",children:L.slice(0,8).map(e=>(0,s.jsx)("div",{className:"rounded-xl border border-white/8 bg-black/25 px-3 py-2.5",children:(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-xs text-white",children:new Date(e.created_at).toLocaleString("zh"===t?"zh-CN":"en-US",{hour12:!1})}),(0,s.jsxs)("div",{className:"mt-1 text-[11px] text-slate-500",children:[e.reason," \xb7 ",function(e){if(!e)return"0 B";let t=["B","KB","MB","GB"],l=e,s=0;for(;l>=1024&&s=10||0===s?0:1)," ").concat(t[s])}(e.size),"legacy"===e.source?" \xb7 ".concat(E("旧备份","legacy")):""]})]}),(0,s.jsxs)("button",{type:"button",disabled:!!u||!!_,onClick:()=>void A(e.id),className:"btn-focus inline-flex items-center gap-1 rounded-lg border border-white/10 bg-white/5 px-3 py-1.5 text-xs text-slate-100 disabled:opacity-40",children:[_===e.id?(0,s.jsx)(o.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,s.jsx)(x.Z,{className:"h-3.5 w-3.5"}),E("恢复","Restore")]})]})},e.id))}):(0,s.jsx)("p",{className:"mt-3 text-xs text-slate-500",children:E("当前文件还没有 Web 侧快照。保存、删除或恢复后会自动累积历史。","No Web snapshots yet. Saving, deleting, or restoring will accumulate history automatically.")})]})]})]})}var u=l(1387),p=l(90),b=l(8401),g=l(257);let f=["overview","business","modules","shellcrash","android","config"],v=new Set(["shellcrash-configs","shellcrash-yamls","shellcrash-jsons"]),j="LsRzcR3pHoA9.yaml",w="5d723acc-singbox_tuic3",N=()=>void 0!==g&&g.env.NEXT_PUBLIC_API_URL||"";function y(e){if(!e)return"0 B";let t=["B","KB","MB","GB","TB"],l=e,s=0;for(;l>=1024&&s=10||0===s?0:1)," ").concat(t[s])}function k(e){return"online"===e?"border-emerald-500/30 bg-emerald-500/10 text-emerald-200":"stopped"===e?"border-slate-500/30 bg-slate-500/10 text-slate-300":"configured"===e?"border-violet-500/30 bg-violet-500/10 text-violet-200":"unavailable"===e?"border-slate-700/30 bg-slate-800/50 text-slate-500":"error"===e?"border-rose-500/30 bg-rose-500/10 text-rose-200":"border-cyan-500/30 bg-cyan-500/10 text-cyan-200"}function C(e){let{children:t,className:l,disabled:a,onClick:r,title:n}=e;return(0,s.jsx)("button",{type:"button",className:"btn-focus rounded-xl px-3 py-2 text-xs font-semibold text-white disabled:cursor-not-allowed disabled:opacity-40 ".concat(l||""),disabled:a,onClick:r,title:n,children:t})}function S(e){var t,l,i,o,c,d,h,x,g,S,_,D,E,O,R,T;let{embeddedShellCrash:A=!1,portalLang:U}=e,P=N(),[L,I]=(0,r.useState)("zh"),[M,B]=(0,r.useState)("dark"),[z,F]=(0,r.useState)("overview"),W=(0,r.useCallback)((e,t)=>"zh"===L?e:t,[L]),[H,K]=(0,r.useState)(!0),[Y,J]=(0,r.useState)(null),[Z,V]=(0,r.useState)(null),[G,Q]=(0,r.useState)(null),[q,X]=(0,r.useState)(!0),$=(0,r.useRef)(null),[ee,et]=(0,r.useState)([]),[el,es]=(0,r.useState)(""),[ea,er]=(0,r.useState)("unknown"),[en,ei]=(0,r.useState)(""),[eo,ec]=(0,r.useState)(""),[ed,eh]=(0,r.useState)(null),[ex,em]=(0,r.useState)([]),[eu,ep]=(0,r.useState)(null),[eb,eg]=(0,r.useState)(null),[ef,ev]=(0,r.useState)([]),[ej,ew]=(0,r.useState)(""),[eN,ey]=(0,r.useState)([]),[ek,eC]=(0,r.useState)(""),[eS,e_]=(0,r.useState)(""),[eD,eE]=(0,r.useState)(!1),[eO,eR]=(0,r.useState)([]),[eT,eA]=(0,r.useState)(""),[eU,eP]=(0,r.useState)(null),[eL,eI]=(0,r.useState)([]),[eM,eB]=(0,r.useState)([]),[ez,eF]=(0,r.useState)(""),[eW,eH]=(0,r.useState)(""),[eK,eY]=(0,r.useState)("com.zhiliaoapp.musically"),[eJ,eZ]=(0,r.useState)("https://www.tiktok.com"),[eV,eG]=(0,r.useState)(""),[eQ,eq]=(0,r.useState)(""),[eX,e$]=(0,r.useState)(Date.now()),[e0,e2]=(0,r.useState)("tap"),[e1,e3]=(0,r.useState)(null),[e5,e4]=(0,r.useState)(0),[e8,e6]=(0,r.useState)(0),[e9,e7]=(0,r.useState)(null),[te,tt]=(0,r.useState)(null),[tl,ts]=(0,r.useState)(!1),ta=null!==(O=ef.find(e=>e.root_id===ej))&&void 0!==O?O:null,tr=ef.filter(e=>v.has(e.root_id)),tn=ef.filter(e=>!v.has(e.root_id)),ti=null!==(R=ex.find(e=>"shellcrash"===e.service_id))&&void 0!==R?R:null,to=null!==(T=ex.find(e=>"android_panel"===e.service_id))&&void 0!==T?T:null,tc=(0,r.useMemo)(()=>{var e;let t=null!==(e=null==ed?void 0:ed.quick_links)&&void 0!==e?e:{},l={};for(let[e,s]of Object.entries(t)){let t=String(s);l[e]=/^https?:\/\//i.test(t)?(0,b.p)(t):t}return l},[ed]),td=(0,r.useMemo)(()=>(0,p.O0)(tc),[tc]),th=(0,r.useMemo)(()=>(0,p.Tc)(td),[td]),tx=(0,r.useMemo)(()=>{let e=tc.ws_scrcpy||((null==to?void 0:to.host)&&to.port?"http://".concat(to.host,":").concat(to.port):(null==ed?void 0:ed.mdns_host)?"http://".concat(ed.mdns_host,":5000"):"");return e?(0,b.p)(e):""},[null==to?void 0:to.host,null==to?void 0:to.port,tc.ws_scrcpy,null==ed?void 0:ed.mdns_host]),tm=function(e){let t=null==e?void 0:e.match(/(\d+)x(\d+)/);return t?{width:Number(t[1]),height:Number(t[2])}:null}(null==eU?void 0:eU.resolution),tu=(0,r.useCallback)(e=>{V(e),null!=$.current&&window.clearTimeout($.current),$.current=window.setTimeout(()=>{V(null),$.current=null},2500)},[]),tp=(0,r.useCallback)(async(e,t)=>(0,u.N)("".concat(P).concat(e),t),[P]),tb=(0,r.useCallback)((e,t)=>{let l=new URL(window.location.href);l.pathname="shellcrash"===e?"/shellcrash":"android"===e?"/android":"/console","/console"===l.pathname?l.searchParams.set("tab",e):l.searchParams.delete("tab"),l.searchParams.set("lang",t),window.history.replaceState(null,"",l.toString()),window.localStorage.setItem("live-console-lang",t)},[]),tg=(0,r.useCallback)(async()=>{if(!el)return;let e=await tp("/status?process=".concat(encodeURIComponent(el)));er(e.process_status||"unknown"),ei(e.recent_log||""),ec(e.recent_error||"")},[el,tp]),tf=(0,r.useCallback)(async()=>{let[e,t,l]=await Promise.all([tp("/stack/services"),tp("/system_snapshot"),tp("/hardware_profile")]);em(e.services||[]),ep(t),eg(l)},[tp]),tv=(0,r.useCallback)(async(e,t)=>{if(!e)return;let l=(await tp("/managed_files?root=".concat(encodeURIComponent(e)))).files||[];ey(l);let s=t||ek;if(s&&l.some(e=>e.path===s))eC(s);else{var a;eC((null===(a=l[0])||void 0===a?void 0:a.path)||"")}},[tp,ek]),tj=(0,r.useCallback)(async()=>{var e;let t=await tp("/android/devices"),l=t.devices||[],s=eT&&l.some(e=>e.serial===eT)?eT:(null===(e=l[0])||void 0===e?void 0:e.serial)||"";return eE(!!t.available),eR(l),eA(s),s},[eT,tp]),tw=(0,r.useCallback)(async e=>{if(!e){eP(null);return}eP(await tp("/android/overview?serial=".concat(encodeURIComponent(e))))},[tp]),tN=(0,r.useCallback)(async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ez;if(!e){eB([]);return}eB((await tp("/android/packages?serial=".concat(encodeURIComponent(e),"&query=").concat(encodeURIComponent(t),"&limit=60"))).packages||[])},[ez,tp]),ty=(0,r.useCallback)(async e=>{if(!e){eI([]);return}eI((await tp("/android/ui?serial=".concat(encodeURIComponent(e),"&limit=80"))).nodes||[])},[tp]),tk=(0,r.useCallback)(async(e,t)=>{ew(e),eC(t),await tv(e,t)},[tv]),tC=(0,r.useCallback)((e,t)=>{F("config"),window.setTimeout(()=>{tk(e,t)},0)},[tk]),tS=(0,r.useCallback)(async()=>{Q("hardware:probe");try{let e=await tp("/hardware_profile?refresh=true");eg(e),tu(W("硬件探测已更新","Hardware profile refreshed"))}catch(e){tu(e.message)}finally{Q(null)}},[tp,tu,W]),t_=(0,r.useCallback)(async()=>{K(!0),J(null);try{var e,t,l,s;let[a,r,n]=await Promise.all([tp("/process_monitor"),tp("/server_info"),tp("/managed_roots")]);et(a.entries||[]),es((null===(t=a.entries)||void 0===t?void 0:null===(e=t[0])||void 0===e?void 0:e.pm2)||""),eh(r.stack||null),ev(n.roots||[]),ew((null===(s=n.roots)||void 0===s?void 0:null===(l=s[0])||void 0===l?void 0:l.root_id)||""),await Promise.all([tf(),tj()])}catch(e){J(e.message)}finally{K(!1)}},[tp,tj,tf]);(0,r.useEffect)(()=>{if(A){if(F("shellcrash"),"zh"===U||"en"===U)I(U);else{let e=window.localStorage.getItem("live-hub-lang");("zh"===e||"en"===e)&&I(e)}return}let e=new URLSearchParams(window.location.search),t=function(e){let t=e.replace(/\/+$/,"")||"/";return"/shellcrash"===t?"shellcrash":"/android"===t?"android":null}(window.location.pathname),l=e.get("tab"),s=e.get("lang"),a=window.localStorage.getItem("live-console-lang");t?F(t):null!==l&&f.includes(l)&&F(l),"zh"===s||"en"===s?I(s):("zh"===a||"en"===a)&&I(a);let r=window.localStorage.getItem("live-console-theme");("light"===r||"dark"===r)&&B(r)},[A,U]),(0,r.useEffect)(()=>{A||(document.documentElement.setAttribute("data-theme",M),window.localStorage.setItem("live-console-theme",M))},[M,A]),(0,r.useEffect)(()=>{let e=()=>X("visible"===document.visibilityState);return e(),document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[]),(0,r.useEffect)(()=>()=>{null!=$.current&&window.clearTimeout($.current)},[]),(0,r.useEffect)(()=>{A&&("zh"===U||"en"===U)&&I(U)},[A,U]),(0,r.useEffect)(()=>{A||tb(z,L)},[A,L,tb,z]),(0,r.useEffect)(()=>{t_()},[t_]),(0,r.useEffect)(()=>{if(!el||!q)return;tg();let e=window.setInterval(()=>void tg(),1500);return()=>window.clearInterval(e)},[el,q,tg]),(0,r.useEffect)(()=>{if(H||Y||!q||"overview"!==z&&"modules"!==z&&"shellcrash"!==z)return;tf();let e=window.setInterval(()=>void tf(),1e4);return()=>clearInterval(e)},[H,Y,q,tf,z]),(0,r.useEffect)(()=>{let e="shellcrash"===z?tr:"config"===z?tn:ef;e.length&&!e.some(e=>e.root_id===ej)&&(ew(e[0].root_id),eC(""))},[tn,ej,ef,tr,z]),(0,r.useEffect)(()=>{ej&&tv(ej)},[tv,ej]),(0,r.useEffect)(()=>{if(!ej||!ek){e_("");return}(async()=>{try{let e=await tp("/managed_file?root=".concat(encodeURIComponent(ej),"&path=").concat(encodeURIComponent(ek)));e_(e.content||"")}catch(e){tu(e.message)}})()},[tp,ek,tu,ej]),(0,r.useEffect)(()=>{"android"===z&&(async()=>{let e=await tj();e&&(await Promise.all([tw(e),ty(e),tN(e)]),e$(Date.now()))})()},[tj,tw,tN,ty,z]),(0,r.useEffect)(()=>{if("android"!==z||!eT||!q)return;tw(eT),e$(Date.now());let e=window.setInterval(()=>{tw(eT),e$(Date.now())},5e3);return()=>window.clearInterval(e)},[eT,q,tw,z]),(0,r.useEffect)(()=>{if(!eT){e7(e=>(e&&URL.revokeObjectURL(e),null)),tt(null),ts(!1);return}let e=new AbortController,t="".concat(P,"/android/screenshot?serial=").concat(encodeURIComponent(eT),"&ts=").concat(eX);return ts(!0),tt(null),fetch(t,{signal:e.signal}).then(async e=>{if(!e.ok)throw Error(await (0,u.e)(e));return e.blob()}).then(e=>{if(!e.type.startsWith("image/"))throw Error("Not an image");let t=URL.createObjectURL(e);e7(e=>(e&&URL.revokeObjectURL(e),t))}).catch(e=>{"AbortError"!==e.name&&(tt(e.message),e7(e=>(e&&URL.revokeObjectURL(e),null)))}).finally(()=>{e.signal.aborted||ts(!1)}),()=>{e.abort()}},[eT,eX,P]);let tD=async e=>{if(el){Q("process:".concat(e));try{let t=await tp("/".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({process:el})});tu(String(t.output||t.pm2_output||t.message||"OK")),await tg()}catch(e){tu(e.message)}finally{Q(null)}}},tE=async(e,t)=>{Q("".concat(e,":").concat(t));try{let l=await tp("/service_action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({service:e,action:t})});tu(l.message||"OK"),await tf()}catch(e){tu(e.message)}finally{Q(null)}},tO=async e=>{let t=e||("shellcrash-yamls"===ej&&ek?ek:j);Q("shellcrash:apply");try{"shellcrash-yamls"===ej&&ek===t&&await tp("/managed_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:ej,path:ek,content:eS})});let e=await tp("/shellcrash/apply_profile",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:t,target_node:w})}),l=e.selected?" | ".concat(e.selected):"";tu("".concat(e.message||W("ShellCrash 配置已应用","ShellCrash profile applied")).concat(l)),await Promise.all([tf(),tv("shellcrash-yamls","config.yaml")]),ew("shellcrash-yamls"),eC("config.yaml"),e6(e=>e+1)}catch(e){tu(e.message)}finally{Q(null)}},tR=async()=>{if(ej&&ek){Q("file:save");try{await tp("/managed_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:ej,path:ek,content:eS})}),tu(W("文件已保存","File saved")),await tv(ej,ek),e6(e=>e+1)}catch(e){tu(e.message)}finally{Q(null)}}},tT=async()=>{if(!(null==ta?void 0:ta.allow_create)){tu(W("当前目录不允许新建文件","The current root does not allow new files"));return}let e=window.prompt(W("请输入新的相对路径","Enter a new relative path"),ta.default_file||"");if(e){Q("file:create");try{await tp("/managed_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:ej,path:e,content:""})}),tu(W("文件已创建","File created")),await tv(ej,e),e6(e=>e+1)}catch(e){tu(e.message)}finally{Q(null)}}},tA=async()=>{if(ej&&ek){if(!(null==ta?void 0:ta.allow_delete)){tu(W("当前目录不允许删除文件","The current root does not allow deletion"));return}if(window.confirm(W("确定删除该文件?","Delete this file?"))){Q("file:delete");try{await tp("/managed_file?root=".concat(encodeURIComponent(ej),"&path=").concat(encodeURIComponent(ek)),{method:"DELETE"}),tu(W("文件已删除","File deleted")),await tv(ej),e6(e=>e+1)}catch(e){tu(e.message)}finally{Q(null)}}}},tU=async e=>{var t;let l=null===(t=e.target.files)||void 0===t?void 0:t[0];if(e.target.value="",e4(e=>e+1),l&&ej){Q("file:import");try{let e=await l.text();await tp("/managed_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:ej,path:l.name,content:e})}),tu(W("导入完成,已替换同名文件","Import finished and replaced matching file")),eC(l.name),await tv(ej,l.name),e6(e=>e+1)}catch(e){tu(e.message)}finally{Q(null)}}},tP=async(e,t)=>{if(!eT){tu(W("当前没有可用的 ADB 设备","No active ADB device"));return}Q("android:".concat(e));try{let l=await tp("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,serial:eT,payload:t||{}})});tu(l.message||"OK"),l.output&&eq(l.output),e$(Date.now()),await tw(eT)}catch(e){tu(e.message)}finally{Q(null)}},tL="tap"===e0?W("点击","Tap"):"double_tap"===e0?W("双击","Double Tap"):W("长按","Long Press"),tI=async e=>{if(!eT){tu(W("当前没有可用的 ADB 设备","No active ADB device"));return}let t=function(e,t,l){let s,a,r,n;let i=e.getBoundingClientRect(),o=e.naturalWidth,c=e.naturalHeight;if(!o||!c||!i.width||!i.height)return null;let d=i.width/i.height,h=o/c;h>d?(s=i.width,a=i.width/h,r=0,n=(i.height-a)/2):(a=i.height,s=i.height*h,r=(i.width-s)/2,n=0);let x=t-i.left-r,m=l-i.top-n;return x<0||m<0||x>s||m>a?null:{x:Math.max(0,Math.min(o-1,Math.round(x/s*o))),y:Math.max(0,Math.min(c-1,Math.round(m/a*c)))}}(e.currentTarget,e.clientX,e.clientY);if(!t){tu(W("请点击画面有效区域","Tap inside the visible frame"));return}let l=(null==tm?void 0:tm.width)||e.currentTarget.naturalWidth,s=(null==tm?void 0:tm.height)||e.currentTarget.naturalHeight,a=l>0?l/Math.max(1,e.currentTarget.naturalWidth):1,r=s>0?s/Math.max(1,e.currentTarget.naturalHeight):1,n=Math.max(0,Math.min(l||t.x,Math.round(t.x*a))),i=Math.max(0,Math.min(s||t.y,Math.round(t.y*r)));if(e3({x:n,y:i}),"long_press"===e0){await tP("long_press",{x:n,y:i,duration:750});return}await tP(e0,{x:n,y:i})},tM=e=>"shellcrash"===e.service_id&&(null==ed?void 0:ed.control_url)?"".concat(ed.control_url,"/shellcrash?lang=").concat(L):"android_panel"===e.service_id&&(null==ed?void 0:ed.control_url)?"".concat(ed.control_url,"/android?lang=").concat(L):e.url||"",tB=e=>({online:W("在线","Online"),stopped:W("已停止","Stopped"),configured:W("已配置","Configured"),unavailable:W("未安装","Unavailable")})[e]||e,tz="shellcrash"===z?tr:tn,tF={overview:"\uD83D\uDCCA",business:"\uD83C\uDFAC",modules:"\uD83E\uDDE9",shellcrash:"\uD83D\uDEE1️",android:"\uD83E\uDD16",config:"⚙️"};return(0,s.jsxs)(s.Fragment,{children:[A?null:(0,s.jsx)("div",{className:"border-b border-white/[0.08] bg-slate-950/80 backdrop-blur-md",children:(0,s.jsxs)("div",{className:"mx-auto flex max-w-7xl flex-wrap items-center justify-between gap-2 px-4 py-2.5 text-xs sm:px-6 lg:px-10",children:[(0,s.jsxs)("a",{className:"font-medium text-amber-400/95 transition hover:text-amber-300",href:"/",children:["← ",W("返回门户首页","Back to portal")]}),(0,s.jsx)("span",{className:"text-slate-500",children:W("无人直播 \xb7 本页需与 API 同域(推荐 live.local:8001)","Unmanned live \xb7 same origin as API (live.local:8001)")})]})}),(0,s.jsxs)("main",{className:A?"mx-auto min-h-0 max-w-7xl px-1 pb-4 pt-1 sm:px-3":"safe-pb-nav mx-auto min-h-screen max-w-7xl px-4 pb-16 pt-6 sm:px-6 lg:px-10",children:[Z?(0,s.jsx)("div",{role:"status","aria-live":"polite","aria-atomic":"true",className:"animate-toast-in fixed bottom-24 left-1/2 z-50 max-w-[min(92vw,28rem)] -translate-x-1/2 rounded-2xl border border-cyan-500/25 bg-slate-950/95 px-5 py-3 text-center text-sm text-cyan-50 shadow-lg md:bottom-6 [html[data-theme=light]_&]:border-cyan-600/25 [html[data-theme=light]_&]:bg-white/95 [html[data-theme=light]_&]:text-cyan-950",children:Z}):null,A?(0,s.jsxs)("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-2 border-b border-white/[0.08] pb-3",children:[(0,s.jsx)("h2",{className:"text-base font-semibold text-[color:var(--text)]",children:"ShellCrash"}),(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",onClick:()=>void t_(),children:W("刷新","Refresh")})]}):(0,s.jsxs)("header",{className:"mb-8 flex flex-col gap-4",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-[11px] font-semibold uppercase tracking-[0.22em] text-cyan-400/90",children:W("控制平面 \xb7 ARM Linux 开发板","Control plane \xb7 ARM Linux SBC")}),(0,s.jsx)("h1",{className:"mt-2 text-3xl font-bold text-[color:var(--text)] sm:text-4xl",children:W("无人直播控制中心","Unmanned live control center")}),(0,s.jsx)("p",{className:"mt-3 max-w-3xl text-sm text-slate-400",children:W("ShellCrash 负责代理上网;本机 FFmpeg 处理推流或 HDMI;Neko(Docker Chromium)或本机 Chromium 负责浏览器侧;开发板通过 USB 双头线 ADB 控制 AOSP。各模块独立,可分别启停。","ShellCrash for egress; FFmpeg for stream or HDMI; Neko (Docker Chromium) or host Chromium for browser; USB ADB to AOSP. Modules are isolated.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,s.jsx)("div",{className:"meta-chip max-w-full",children:((null==ed?void 0:ed.mdns_host)||"live.local")+" \xb7 "+((null==ed?void 0:ed.machine)||"unknown")+" \xb7 "+((null==ed?void 0:ed.kernel)||"unknown")}),(0,s.jsx)(C,{className:"zh"===L?"border border-cyan-400/50 bg-cyan-500/10":"border border-white/12 bg-black/20",onClick:()=>I("zh"),children:"中文"}),(0,s.jsx)(C,{className:"en"===L?"border border-cyan-400/50 bg-cyan-500/10":"border border-white/12 bg-black/20",onClick:()=>I("en"),children:"EN"}),(0,s.jsx)(C,{className:"light"===M?"border border-amber-400/50 bg-amber-500/15":"border border-white/12 bg-black/20",onClick:()=>B("light"),title:W("日间主题","Light theme"),children:W("☀️ 日间","☀️ Light")}),(0,s.jsx)(C,{className:"dark"===M?"border border-indigo-400/50 bg-indigo-500/15":"border border-white/12 bg-black/20",onClick:()=>B("dark"),title:W("夜间主题","Dark theme"),children:W("\uD83C\uDF19 夜间","\uD83C\uDF19 Dark")}),(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",onClick:()=>void t_(),children:W("刷新","Refresh")})]})]}),(0,s.jsx)("nav",{className:"tab-strip","aria-label":W("主导航","Primary navigation"),children:f.map(e=>(0,s.jsx)("button",{type:"button",className:"tab-btn ".concat(z===e?"tab-btn-active":""),onClick:()=>F(e),children:{overview:W("总览","Overview"),business:W("直播业务","Live ops"),modules:W("系统服务","Services"),shellcrash:"ShellCrash",android:W("安卓设备","Android"),config:W("配置中心","Config")}[e]},e))})]}),H?(0,s.jsx)("div",{className:"glass rounded-3xl py-24 text-center text-slate-400",children:W("正在连接控制台...","Connecting to the control plane...")}):null,!H&&Y?(0,s.jsx)("div",{className:"glass rounded-3xl border border-rose-500/25 bg-rose-950/20 p-8 text-center text-rose-200",children:Y}):null,H||Y?null:(0,s.jsxs)("div",{className:"grid gap-6",children:["overview"===z?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("section",{className:"glass rounded-3xl border border-amber-500/20 bg-gradient-to-br from-amber-500/[0.07] to-transparent p-6",children:[(0,s.jsx)("h2",{className:"section-title",children:W("第一次用?按这条线理解整套板子","New here? Follow this mental model")}),(0,s.jsxs)("ol",{className:"mt-4 list-decimal space-y-2 pl-5 text-sm leading-relaxed text-slate-300",children:[(0,s.jsx)("li",{children:W("插电、接网线或连好 Wi‑Fi 后,用浏览器打开本页(验收域名一般为 http://live.local:8001/ ,门户在根路径 /,控制台在 /console)。","After power and Ethernet/Wi‑Fi, open this stack in a browser (often http://live.local:8001/ — portal at /, full console at /console).")}),(0,s.jsx)("li",{children:W("「直播业务」里启停 PM2 脚本(抖音→YouTube、HDMI 等);「系统服务」看 ShellCrash、SRS、ws-scrcpy、Neko 等是否在跑。","Use Live ops for PM2 scripts; Services for ShellCrash, SRS, ws-scrcpy, Neko, etc.")}),(0,s.jsx)("li",{children:W("「安卓设备」需要 USB 调试授权;截图预览 + ws-scrcpy 低延迟画面二选一或同用。TikTok 等场景常配合板载 AOSP。","Android tab needs USB debugging; use screenshot taps and/or ws-scrcpy. TikTok workflows often use on-board AOSP.")}),(0,s.jsx)("li",{children:W("深度指标点 Netdata;命令行点 WebTTY;代理规则与 YAML 在 ShellCrash 页。","Netdata for metrics; WebTTY for shell; ShellCrash tab for proxy rules and YAML.")})]})]}),(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"section-title",children:W("\uD83D\uDEF0️ 流媒体与桌面入口","Streaming & desktop")}),(0,s.jsx)("p",{className:"section-lead",children:W("ws-scrcpy:浏览器里控安卓;Chromium:本机+油猴+RemoteDebug;Neko:Docker 里跑 Chromium 桌面(非 Firefox 版)。","ws-scrcpy: browser ADB; Chromium: host+Tampermonkey+9222; Neko: Chromium desktop in Docker (not the Firefox image).")}),(0,s.jsxs)("div",{className:"mt-4 flex max-h-[28rem] flex-col gap-2 overflow-y-auto pr-1 log-scroll",children:[(null==ed?void 0:ed.dashboard_url)?(0,s.jsx)("a",{className:"link-tile",href:ed.dashboard_url,target:"_blank",rel:"noreferrer",children:"\uD83C\uDFE0 Homepage"}):null,(null==ed?void 0:ed.control_url)?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("a",{className:"link-tile",href:"".concat(ed.control_url,"/console?tab=shellcrash&lang=").concat(L),target:"_blank",rel:"noreferrer",children:"\uD83D\uDEE1️ ShellCrash"}),(0,s.jsxs)("a",{className:"link-tile",href:"".concat(ed.control_url,"/console?tab=android&lang=").concat(L),target:"_blank",rel:"noreferrer",children:["\uD83E\uDD16 ",W("安卓中心 (含 ws-scrcpy)","Android hub + ws-scrcpy")]}),(0,s.jsxs)("a",{className:"link-tile",href:"".concat(ed.control_url,"/console?tab=config&lang=").concat(L),target:"_blank",rel:"noreferrer",children:["⚙️ ",W("配置中心","Config")]})]}):null,tc.ws_scrcpy?(0,s.jsxs)("a",{className:"link-tile link-tile-accent",href:tc.ws_scrcpy,target:"_blank",rel:"noreferrer",children:["\uD83D\uDCF1 ws-scrcpy (",W("原始流控制页","raw stream UI"),")"]}):null,tc.chromium_remote_debug?(0,s.jsxs)("a",{className:"link-tile",href:tc.chromium_remote_debug,target:"_blank",rel:"noreferrer",children:["\uD83E\uDDEA ",W("Chromium RemoteDebug (9222)","Chromium RemoteDebug")]}):null,td.map(e=>(0,s.jsxs)("a",{className:"link-tile link-tile-warn",href:e.url,target:"_blank",rel:"noreferrer",children:["\uD83D\uDC31 ",e.label," / ",W("Docker Chromium 桌面","Docker Chromium desktop")]},e.key)),tc.webtty?(0,s.jsx)("a",{className:"link-tile",href:tc.webtty,target:"_blank",rel:"noreferrer",children:"⌨️ WebTTY"}):null,tc.filebrowser?(0,s.jsx)("a",{className:"link-tile",href:tc.filebrowser,target:"_blank",rel:"noreferrer",children:"\uD83D\uDCC2 File Browser"}):null,tc.netdata?(0,s.jsx)("a",{className:"link-tile",href:tc.netdata,target:"_blank",rel:"noreferrer",children:"\uD83D\uDCC8 Netdata"}):null,tc.srs_http?(0,s.jsx)("a",{className:"link-tile",href:tc.srs_http,target:"_blank",rel:"noreferrer",children:"\uD83C\uDF9E️ SRS :8080"}):null,tc.srs_api?(0,s.jsx)("a",{className:"link-tile",href:tc.srs_api,target:"_blank",rel:"noreferrer",children:"\uD83C\uDF9E️ SRS API :1985"}):null]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"section-title",children:W("节点状态","Node Status")}),(0,s.jsxs)("div",{className:"panel-inset mt-4",children:[(0,s.jsx)("p",{children:(null==ed?void 0:ed.mdns_host)||"live.local"}),(0,s.jsxs)("p",{className:"mt-2",children:["IP: ",((null==ed?void 0:ed.ips)||[]).join(" / ")||"-"]}),(0,s.jsx)("p",{className:"mt-2",children:(null==ed?void 0:ed.machine)||"-"}),(0,s.jsx)("p",{className:"mt-2",children:(null==ed?void 0:ed.kernel)||"-"})]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"section-title",children:W("系统快照","System Snapshot")}),(0,s.jsx)("p",{className:"section-lead",children:W("总览页每 10 秒自动刷新服务与监控数据。","Overview auto-refreshes every 10s.")}),(0,s.jsxs)("div",{className:"panel-inset mt-4",children:[(0,s.jsxs)("p",{children:["CPU:"," ",[null==eu?void 0:null===(t=eu.cpu_load)||void 0===t?void 0:t["1m"],null==eu?void 0:null===(l=eu.cpu_load)||void 0===l?void 0:l["5m"],null==eu?void 0:null===(i=eu.cpu_load)||void 0===i?void 0:i["15m"]].map(e=>"number"==typeof e?e.toFixed(2):"0.00").join(" / ")]}),(0,s.jsxs)("p",{className:"mt-2",children:["RAM: ",y(null==eu?void 0:null===(o=eu.memory)||void 0===o?void 0:o.available)," / ",y(null==eu?void 0:null===(c=eu.memory)||void 0===c?void 0:c.total)]}),(0,s.jsxs)("p",{className:"mt-2",children:["Disk: ",y(null==eu?void 0:null===(d=eu.disk)||void 0===d?void 0:d.free)," / ",y(null==eu?void 0:null===(h=eu.disk)||void 0===h?void 0:h.total)]}),(0,s.jsxs)("p",{className:"mt-2",children:["Netdata: ",(null==eu?void 0:null===(x=eu.netdata)||void 0===x?void 0:x.available)?eu.netdata.version||"online":"offline"]})]}),(0,s.jsx)(n.Z,{snapshot:eu,theme:M,tr:W})]})]}),(0,s.jsxs)("section",{className:"glass rounded-3xl p-6",children:[(0,s.jsx)("h2",{className:"section-title",children:W("模块概况","Module Summary")}),(0,s.jsx)("div",{className:"mt-4 grid gap-4 md:grid-cols-2 xl:grid-cols-3",children:ex.map(e=>(0,s.jsxs)("div",{className:"service-card",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:e.label}),(0,s.jsx)("p",{className:"mt-1 text-xs text-slate-400",children:e.description})]}),(0,s.jsx)("span",{className:"rounded-full border px-2.5 py-1 text-xs ".concat(k(e.status)),children:tB(e.status)})]}),(0,s.jsx)("p",{className:"mt-3 min-h-[3rem] text-xs text-slate-500",children:e.detail||"-"}),tM(e)?(0,s.jsx)("a",{className:"btn-focus mt-3 inline-flex rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-200",href:tM(e),target:"_blank",rel:"noreferrer",children:W("打开","Open")}):null]},e.service_id))})]})]}):null,"business"===z?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-12",children:[(0,s.jsx)("h2",{className:"section-title",children:W("⚡ 快捷配置","Quick config")}),(0,s.jsx)("p",{className:"section-lead",children:W("跳转配置中心编辑推流与录制相关文件。","Jump to the config editor for stream keys and URLs.")}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(C,{className:"border border-cyan-500/30 bg-cyan-600/80",onClick:()=>tC("app-config","youtube.ini"),children:"youtube.ini"}),(0,s.jsx)(C,{className:"border border-cyan-500/30 bg-cyan-600/80",onClick:()=>tC("app-config","URL_config.ini"),children:"URL_config.ini"}),(0,s.jsx)(C,{className:"border border-white/15 bg-black/30",onClick:()=>tC("app-config","config.ini"),children:"config.ini"}),(0,s.jsx)(C,{className:"border border-white/15 bg-black/30",onClick:()=>tC("stack-config","system-stack.env"),children:"system-stack.env"})]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"section-title",children:W("业务运行时","Business Runtime")}),(0,s.jsx)("p",{className:"section-lead",children:W("这里只放业务脚本本身,Hub 基座可单独运行。","Only business processes live here.")}),ee.length>0?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("select",{className:"field-select mt-4",value:el,onChange:e=>es(e.target.value),children:ee.map(e=>(0,s.jsxs)("option",{value:e.pm2,children:[e.label," | ",e.script]},e.pm2))}),(0,s.jsxs)("div",{className:"mt-4 flex items-center justify-between rounded-2xl border border-white/8 bg-black/20 px-4 py-3",children:[(0,s.jsx)("span",{className:"rounded-full border px-3 py-1 text-xs ".concat(k(ea)),children:tB(ea)}),(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",onClick:()=>void tg(),children:W("轮询","Poll")})]}),(0,s.jsxs)("div",{className:"mt-4 grid grid-cols-2 gap-2",children:[(0,s.jsx)(C,{className:"bg-emerald-600",disabled:"process:start"===G,onClick:()=>void tD("start"),children:"process:start"===G?W("启动中...","Starting..."):W("启动","Start")}),(0,s.jsx)(C,{className:"bg-amber-600",disabled:"process:restart"===G,onClick:()=>void tD("restart"),children:"process:restart"===G?W("重启中...","Restarting..."):W("重启","Restart")}),(0,s.jsx)(C,{className:"col-span-2 bg-rose-600",disabled:"process:stop"===G,onClick:()=>void tD("stop"),children:"process:stop"===G?W("停止中...","Stopping..."):W("停止","Stop")})]})]}):(0,s.jsx)("div",{className:"mt-4 rounded-2xl border border-dashed border-white/12 bg-black/20 p-4 text-sm text-slate-400",children:W("未发现业务进程。若只部署了 Hub 基座,这是正常状态。","No business process discovered.")})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsx)("h2",{className:"section-title",children:W("业务日志","Process Logs")}),(0,s.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,s.jsx)("pre",{className:"log-scroll min-h-[22rem] rounded-2xl border border-emerald-500/15 bg-black/55 p-4 font-mono text-[11px] text-emerald-100/95",children:en||W("暂无输出","No stdout yet.")}),(0,s.jsx)("pre",{className:"log-scroll min-h-[22rem] rounded-2xl border border-rose-500/15 bg-black/55 p-4 font-mono text-[11px] text-rose-100/95",children:eo||W("暂无报错","No stderr yet.")})]})]})]}):null,"modules"===z?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"section-title",children:W("系统模块","System Modules")}),(0,s.jsx)("p",{className:"section-lead",children:W("每个模块都独立启停和降级,避免一个服务异常拖垮整套业务。","Each module starts and degrades independently.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",onClick:()=>void tf(),children:W("刷新服务","Refresh Services")}),(0,s.jsx)(C,{className:"border border-violet-500/35 bg-violet-600/70",disabled:"hardware:probe"===G,onClick:()=>void tS(),children:"hardware:probe"===G?W("探测中…","Probing…"):W("重探测硬件","Re-probe HW")})]})]}),(0,s.jsx)("div",{className:"mt-4 grid gap-4 md:grid-cols-2",children:ex.map(e=>(0,s.jsxs)("div",{className:"service-card",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:e.label}),(0,s.jsx)("p",{className:"mt-1 text-xs text-slate-400",children:e.description})]}),(0,s.jsx)("span",{className:"rounded-full border px-2.5 py-1 text-xs ".concat(k(e.status)),children:tB(e.status)})]}),(0,s.jsx)("p",{className:"mt-3 min-h-[3rem] text-xs text-slate-500",children:e.detail||"-"}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(C,{className:"bg-emerald-600",disabled:!e.available||!!G,onClick:()=>void tE(e.service_id,"start"),children:W("启动","Start")}),(0,s.jsx)(C,{className:"bg-amber-600",disabled:!e.available||!!G,onClick:()=>void tE(e.service_id,"restart"),children:W("重启","Restart")}),(0,s.jsx)(C,{className:"bg-rose-600",disabled:!e.available||!!G,onClick:()=>void tE(e.service_id,"stop"),children:W("停止","Stop")}),tM(e)?(0,s.jsx)("a",{className:"btn-focus rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-200",href:tM(e),target:"_blank",rel:"noreferrer",children:W("打开","Open")}):null]})]},e.service_id))})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:W("硬件与系统","Hardware and System")}),(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4 text-xs text-slate-400",children:[(0,s.jsxs)("p",{children:["Arch: ",(null==eb?void 0:eb.arch)||"-"]}),(0,s.jsxs)("p",{className:"mt-2",children:["FFmpeg: ",((null==eb?void 0:eb.ffmpeg_hwaccels)||[]).join(", ")||"-"]}),(0,s.jsxs)("p",{className:"mt-2",children:["GPU: ",(null==eb?void 0:null===(g=eb.gpu)||void 0===g?void 0:g.present)?eb.gpu.driver||"present":"none"]}),(0,s.jsxs)("p",{className:"mt-2",children:["NPU: ",(null==eb?void 0:null===(S=eb.npu)||void 0===S?void 0:S.present)?(eb.npu.devices||[]).join(", "):"none"]}),(0,s.jsxs)("p",{className:"mt-2",children:["Decoder: ",(null==eb?void 0:null===(_=eb.recommendation)||void 0===_?void 0:_.video_decoder)||"cpu"]}),(0,s.jsxs)("p",{className:"mt-2",children:["HDMI: ",(null==eb?void 0:null===(D=eb.recommendation)||void 0===D?void 0:D.hdmi_player)||"cpu"]}),(0,s.jsxs)("p",{className:"mt-2",children:["Mode: ",(null==eb?void 0:null===(E=eb.recommendation)||void 0===E?void 0:E.stability_mode)||"safe"]})]})]})]}):null,"shellcrash"===z?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:"ShellCrash"}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:W("这里不再依赖命令行菜单,直接做 YAML / JSON / CFG 编辑与服务控制。","Manage ShellCrash from the web instead of the shell menu.")}),ti?(0,s.jsxs)("div",{className:"mt-4 rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:ti.label}),(0,s.jsx)("p",{className:"mt-1 text-xs text-slate-400",children:ti.description})]}),(0,s.jsx)("span",{className:"rounded-full border px-2.5 py-1 text-xs ".concat(k(ti.status)),children:tB(ti.status)})]}),(0,s.jsx)("p",{className:"mt-3 text-xs text-slate-500",children:ti.detail||"-"}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(C,{className:"bg-emerald-600",disabled:!ti.available||!!G,onClick:()=>void tE("shellcrash","start"),children:W("启动","Start")}),(0,s.jsx)(C,{className:"bg-amber-600",disabled:!ti.available||!!G,onClick:()=>void tE("shellcrash","restart"),children:W("重启","Restart")}),(0,s.jsx)(C,{className:"bg-rose-600",disabled:!ti.available||!!G,onClick:()=>void tE("shellcrash","stop"),children:W("停止","Stop")}),(0,s.jsx)(C,{className:"bg-sky-600",disabled:!ti.available||!!G,onClick:()=>void tO(j),children:"shellcrash:apply"===G?W("应用中...","Applying..."):W("应用默认配置","Apply Default")})]})]}):null,(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-sky-400/20 bg-sky-500/10 p-4 text-xs text-sky-100",children:[(0,s.jsx)("p",{className:"font-semibold",children:W("默认代理节点","Default proxy node")}),(0,s.jsx)("p",{className:"mt-2 break-all font-mono text-[11px] text-sky-200",children:w}),(0,s.jsx)("p",{className:"mt-2 text-sky-100/80",children:W("应用后会写入 config.yaml、重启 ShellCrash,并把包含该节点的选择组切到此节点。","Applying writes config.yaml, restarts ShellCrash, and selects this node in matching groups.")})]}),(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4 text-xs text-slate-400",children:[(0,s.jsx)("p",{className:"text-white",children:W("快捷文件","Quick Files")}),(0,s.jsxs)("div",{className:"mt-3 grid gap-2",children:[(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tk("shellcrash-yamls",j),children:j}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tk("shellcrash-yamls","config.yaml"),children:"config.yaml"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tk("shellcrash-configs","ShellCrash.cfg"),children:"ShellCrash.cfg"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tk("shellcrash-configs","servers.list"),children:"servers.list"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tk("shellcrash-configs","command.env"),children:"command.env"})]})]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:W("ShellCrash 文件编辑器","ShellCrash Editor")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:W("支持查看、修改、新建、删除,路径被限制在 ShellCrash 托管目录内。","View, edit, create and delete files inside managed ShellCrash roots.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsxs)("label",{className:"btn-focus rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-100 ".concat(G?"cursor-not-allowed opacity-40":""),children:["file:import"===G?W("导入中...","Importing..."):W("导入/替换","Import/Replace"),(0,s.jsx)("input",{className:"hidden",disabled:!!G,type:"file",accept:".yaml,.yml,.json,.cfg,.env,.list,.txt",onChange:e=>void tU(e)},e5)]}),(0,s.jsx)(C,{className:"bg-sky-600",disabled:"shellcrash-yamls"!==ej||!ek||!!G,onClick:()=>void tO(ek),children:"shellcrash:apply"===G?W("应用中...","Applying..."):W("应用当前 YAML","Apply YAML")}),(0,s.jsx)(C,{className:"bg-cyan-600",disabled:!ek||!!G,onClick:()=>void tR(),children:"file:save"===G?W("保存中...","Saving..."):W("保存","Save")})]})]}),(0,s.jsxs)("div",{className:"mt-4 grid gap-6 xl:grid-cols-[18rem,1fr]",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("select",{className:"w-full rounded-2xl border border-white/12 bg-slate-950/60 px-4 py-3 text-sm text-white",value:ej,onChange:e=>{ew(e.target.value),eC("")},children:tr.map(e=>(0,s.jsxs)("option",{value:e.root_id,children:[e.label," | ",e.file_count]},e.root_id))}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(C,{className:"bg-cyan-600",disabled:!!G,onClick:()=>void tT(),children:W("新建","New")}),(0,s.jsx)(C,{className:"bg-rose-600",disabled:!ek||!!G,onClick:()=>void tA(),children:W("删除","Delete")})]}),(0,s.jsx)("div",{className:"mt-4 space-y-2",children:eN.map(e=>(0,s.jsxs)("button",{className:"btn-focus w-full rounded-2xl border px-4 py-3 text-left ".concat(ek===e.path?"border-cyan-500/40 bg-cyan-500/10":"border-white/8 bg-black/20"),onClick:()=>eC(e.path),children:[(0,s.jsx)("div",{className:"truncate text-sm text-white",children:e.path}),(0,s.jsx)("div",{className:"mt-1 text-[11px] text-slate-500",children:y(e.size)})]},e.path))})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"rounded-2xl border border-white/8 bg-black/20 px-4 py-3 font-mono text-[11px] text-slate-500",children:ek?"".concat(ej," / ").concat(ek):W("请选择文件","Pick a file")}),(0,s.jsx)("textarea",{className:"log-scroll mt-4 min-h-[32rem] w-full resize-y rounded-2xl border border-white/10 bg-black/45 p-4 font-mono text-xs leading-relaxed text-slate-200",spellCheck:!1,value:eS,onChange:e=>e_(e.target.value)})]})]})]})]}):null,"android"===z?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:W("安卓设备中心","Android Device Center")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:W("把设备发现、截图预览、ADB 动作和原始 web-scrcpy 放到一个模块里。","Combine discovery, preview, ADB actions and raw web-scrcpy in one module.")})]}),(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",onClick:()=>void(async()=>{let e=await tj();e&&await Promise.all([tw(e),ty(e),tN(e)]),e$(Date.now())})(),children:W("刷新设备","Refresh")})]}),(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4",children:[(0,s.jsx)("p",{className:"text-sm font-semibold text-white",children:W("已连接设备","Devices")}),eD&&0!==eO.length?(0,s.jsx)("div",{className:"mt-3 space-y-2",children:eO.map(e=>(0,s.jsxs)("button",{className:"btn-focus w-full rounded-2xl border px-4 py-3 text-left ".concat(eT===e.serial?"border-cyan-500/40 bg-cyan-500/10":"border-white/8 bg-black/20"),onClick:()=>{eA(e.serial),Promise.all([tw(e.serial),ty(e.serial),tN(e.serial)]),e$(Date.now())},children:[(0,s.jsx)("div",{className:"text-sm text-white",children:e.model||e.device||e.serial}),(0,s.jsxs)("div",{className:"mt-1 text-[11px] text-slate-500",children:[e.serial," | ",e.state]})]},e.serial))}):(0,s.jsx)("p",{className:"mt-3 text-sm text-slate-400",children:W("当前没有可用的 ADB 设备。","No active ADB device.")})]}),(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4 text-xs text-slate-400",children:[(0,s.jsx)("p",{className:"text-white",children:W("设备状态","Device Status")}),(0,s.jsxs)("p",{className:"mt-2",children:[(null==eU?void 0:eU.brand)||"-"," ",(null==eU?void 0:eU.model)||"-"]}),(0,s.jsxs)("p",{className:"mt-2",children:["Android ",(null==eU?void 0:eU.android_version)||"-"," / SDK ",(null==eU?void 0:eU.sdk)||"-"]}),(0,s.jsx)("p",{className:"mt-2 whitespace-pre-wrap",children:(null==eU?void 0:eU.battery)||"-"}),(0,s.jsx)("p",{className:"mt-2 whitespace-pre-wrap",children:(null==eU?void 0:eU.resolution)||"-"}),(0,s.jsx)("p",{className:"mt-2 whitespace-pre-wrap",children:(null==eU?void 0:eU.focus)||"-"})]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:W("屏幕预览与动作","Screen Preview and Actions")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:W("预览图支持直接点按/双击/长按,配合 UI 节点和包管理形成更完整的安卓控制台。","The preview supports tap, double tap and long press, backed by UI nodes and package tools.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)(C,{className:"border border-white/12 ".concat("tap"===e0?"bg-cyan-600":"bg-black/20"),disabled:!eT||!!G,onClick:()=>e2("tap"),children:W("点击","Tap")}),(0,s.jsx)(C,{className:"border border-white/12 ".concat("double_tap"===e0?"bg-cyan-600":"bg-black/20"),disabled:!eT||!!G,onClick:()=>e2("double_tap"),children:W("双击","Double Tap")}),(0,s.jsx)(C,{className:"border border-white/12 ".concat("long_press"===e0?"bg-cyan-600":"bg-black/20"),disabled:!eT||!!G,onClick:()=>e2("long_press"),children:W("长按","Long Press")}),(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",disabled:!eT,onClick:()=>e$(Date.now()),children:W("刷新截图","Refresh Shot")})]})]}),(0,s.jsx)("div",{className:"mt-4 overflow-hidden rounded-3xl border border-white/8 bg-black/35 p-4",children:eT?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:"mb-3 flex flex-wrap items-center gap-3 text-xs text-slate-400",children:[(0,s.jsxs)("span",{children:[W("当前动作","Current action"),": ",tL]}),(0,s.jsxs)("span",{children:[W("分辨率","Resolution"),": ",(null==eU?void 0:eU.resolution)||"-"]}),(0,s.jsxs)("span",{children:[W("最近坐标","Last point"),": ",e1?"".concat(e1.x,", ").concat(e1.y):"-"]}),tl?(0,s.jsx)("span",{className:"text-cyan-400/90",children:W("截图刷新中…","Refreshing…")}):null]}),te?(0,s.jsxs)("div",{className:"mb-3 rounded-xl border border-rose-500/30 bg-rose-950/25 px-4 py-3 text-sm text-rose-100",children:[W("截图不可用:","Screenshot unavailable: "),te]}):null,e9?(0,s.jsx)(a.default,{alt:"Android preview",className:"max-h-[min(70vh,48rem)] min-h-[14rem] w-full cursor-crosshair rounded-2xl object-contain bg-black",onClick:e=>void tI(e),src:e9,unoptimized:!0,width:(null==tm?void 0:tm.width)||1080,height:(null==tm?void 0:tm.height)||1920}):te?null:(0,s.jsx)("div",{className:"flex min-h-[18rem] items-center justify-center rounded-2xl border border-dashed border-white/10 bg-black/30 text-sm text-slate-500",children:W("正在拉取截图…","Fetching screenshot…")})]}):(0,s.jsx)("div",{className:"flex min-h-[18rem] items-center justify-center rounded-2xl border border-dashed border-white/10 bg-black/20 text-sm text-slate-500",children:W("当前没有可用的 ADB 设备。","No active ADB device.")})}),(0,s.jsxs)("div",{className:"mt-6 grid gap-6 xl:grid-cols-3",children:[(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:W("快捷控制","Quick Controls")}),(0,s.jsxs)("div",{className:"mt-4 grid grid-cols-3 gap-2",children:[[["HOME","KEYCODE_HOME"],["BACK","KEYCODE_BACK"],["RECENTS","KEYCODE_APP_SWITCH"],["POWER","KEYCODE_POWER"],["NOTIFY","KEYCODE_NOTIFICATION"],["VOL+","KEYCODE_VOLUME_UP"],["VOL-","KEYCODE_VOLUME_DOWN"]].map(e=>{let[t,l]=e;return(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs text-slate-100",disabled:!eT||!!G,onClick:()=>void tP("key",{keycode:l}),children:t},t)}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs text-slate-100",disabled:!eT||!!G,onClick:()=>void tP("wake"),children:"WAKE"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs text-slate-100",disabled:!eT||!!G,onClick:()=>void tP("rotate",{rotation:"0"}),children:"Portrait"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs text-slate-100",disabled:!eT||!!G,onClick:()=>void tP("rotate",{rotation:"1"}),children:"Landscape"})]}),(0,s.jsx)("div",{className:"mt-4 grid grid-cols-2 gap-2",children:["up","down","left","right"].map(e=>(0,s.jsxs)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs uppercase text-slate-100",disabled:!eT||!!G,onClick:()=>void tP("swipe",{direction:e}),children:["Swipe ",e]},e))})]}),(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:W("输入与跳转","Input and Launch")}),(0,s.jsx)("textarea",{className:"mt-4 min-h-[6rem] w-full rounded-2xl border border-white/10 bg-black/45 p-4 text-sm text-slate-200",placeholder:W("输入要发送到安卓输入框的文字","Text to send to Android"),value:eW,onChange:e=>eH(e.target.value)}),(0,s.jsx)(C,{className:"mt-3 bg-cyan-600",disabled:!eW.trim()||!eT||!!G,onClick:()=>void tP("text",{text:eW}),children:W("发送文本","Send Text")}),(0,s.jsx)("input",{className:"mt-4 w-full rounded-2xl border border-white/10 bg-black/45 px-4 py-3 text-sm text-slate-200",placeholder:"com.zhiliaoapp.musically",value:eK,onChange:e=>eY(e.target.value)}),(0,s.jsxs)("div",{className:"mt-3 grid grid-cols-3 gap-2",children:[(0,s.jsx)(C,{className:"bg-emerald-600",disabled:!eK.trim()||!eT||!!G,onClick:()=>void tP("launch_package",{package:eK}),children:W("启动","Launch")}),(0,s.jsx)(C,{className:"bg-amber-600",disabled:!eK.trim()||!eT||!!G,onClick:()=>void tP("force_stop",{package:eK}),children:W("停应用","Stop App")}),(0,s.jsx)(C,{className:"bg-rose-600",disabled:!eK.trim()||!eT||!!G,onClick:()=>void tP("clear_app",{package:eK}),children:W("清数据","Clear Data")})]}),(0,s.jsx)("input",{className:"mt-4 w-full rounded-2xl border border-white/10 bg-black/45 px-4 py-3 text-sm text-slate-200",placeholder:"https://www.tiktok.com",value:eJ,onChange:e=>eZ(e.target.value)}),(0,s.jsx)(C,{className:"mt-3 bg-violet-600",disabled:!eJ.trim()||!eT||!!G,onClick:()=>void tP("open_url",{url:eJ}),children:W("打开链接","Open URL")})]}),(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:W("应用工作台","App Workspace")}),(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",disabled:!eT||!!G,onClick:()=>void ty(eT),children:W("刷新UI","Refresh UI")})]}),(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:[["TikTok","com.zhiliaoapp.musically"],["Chrome","com.android.chrome"],["Settings","com.android.settings"],["YouTube","com.google.android.youtube"],["Play","com.android.vending"]].map(e=>{let[t,l]=e;return(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-2 text-xs text-slate-100",disabled:!eT||!!G,onClick:()=>{eY(l),tP("launch_package",{package:l})},children:t},l)})}),(0,s.jsxs)("div",{className:"mt-4 flex gap-2",children:[(0,s.jsx)("input",{className:"w-full rounded-2xl border border-white/10 bg-black/45 px-4 py-3 text-sm text-slate-200",placeholder:W("搜索包名,例如 tiktok","Search package, e.g. tiktok"),value:ez,onChange:e=>eF(e.target.value)}),(0,s.jsx)(C,{className:"bg-cyan-600",disabled:!eT||!!G,onClick:()=>void tN(eT),children:W("搜索","Search")})]}),(0,s.jsx)("div",{className:"mt-4 space-y-2",children:0===eM.length?(0,s.jsx)("div",{className:"rounded-2xl border border-dashed border-white/10 px-4 py-6 text-sm text-slate-500",children:W("还没有查询结果。","No package results yet.")}):eM.slice(0,8).map(e=>(0,s.jsxs)("div",{className:"rounded-2xl border border-white/8 bg-slate-950/30 p-3",children:[(0,s.jsx)("div",{className:"text-sm text-white",children:e.label||e.package.split(".").pop()}),(0,s.jsx)("div",{className:"mt-1 truncate font-mono text-[11px] text-slate-500",children:e.package}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eT||!!G,onClick:()=>{eY(e.package),tP("launch_package",{package:e.package})},children:W("启动","Launch")}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eT||!!G,onClick:()=>{eY(e.package),tP("force_stop",{package:e.package})},children:W("停应用","Stop")}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eT||!!G,onClick:()=>{eY(e.package),tP("clear_app",{package:e.package})},children:W("清数据","Clear")})]})]},e.package))})]})]}),(0,s.jsxs)("div",{className:"mt-6 grid gap-6 xl:grid-cols-[0.95fr,1.05fr]",children:[(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:"ADB Shell"}),(0,s.jsxs)("div",{className:"mt-4 flex flex-col gap-3 lg:flex-row",children:[(0,s.jsx)("input",{className:"w-full rounded-2xl border border-white/10 bg-black/45 px-4 py-3 text-sm text-slate-200",placeholder:"input keyevent KEYCODE_HOME",value:eV,onChange:e=>eG(e.target.value)}),(0,s.jsx)(C,{className:"bg-amber-600",disabled:!eV.trim()||!eT||!!G,onClick:()=>void tP("shell",{command:eV}),children:W("执行命令","Run Command")})]}),(0,s.jsx)("pre",{className:"log-scroll mt-4 min-h-[14rem] rounded-2xl border border-white/10 bg-black/45 p-4 font-mono text-[11px] text-slate-200",children:eQ||W("动作结果会显示在这里。","Action output will appear here.")})]}),(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:W("UI 节点","UI Nodes")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:W("用 uiautomator 抓当前页面结构,快速定位可点击元素。","Inspect the current UI hierarchy and act on clickable nodes.")})]}),(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",disabled:!eT||!!G,onClick:()=>void ty(eT),children:W("刷新节点","Refresh Nodes")})]}),(0,s.jsx)("div",{className:"mt-4 space-y-3",children:0===eL.length?(0,s.jsx)("div",{className:"rounded-2xl border border-dashed border-white/10 px-4 py-6 text-sm text-slate-500",children:W("还没有抓到 UI 节点。","No UI nodes yet.")}):eL.slice(0,12).map((e,t)=>(0,s.jsxs)("div",{className:"rounded-2xl border border-white/8 bg-slate-950/30 p-3",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-sm text-white",children:e.label||e.resource_id||e.class_name||"node"}),(0,s.jsx)("div",{className:"mt-1 text-[11px] text-slate-500",children:e.resource_id||e.class_name||"-"}),(0,s.jsxs)("div",{className:"mt-1 text-[11px] text-slate-500",children:[e.bounds," | ",e.center_x,",",e.center_y]})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eT||!!G,onClick:()=>void tP("tap",{x:e.center_x,y:e.center_y}),children:W("点击","Tap")}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eT||!!G,onClick:()=>void tP("long_press",{x:e.center_x,y:e.center_y,duration:750}),children:W("长按","Long Press")})]})]}),e.text||e.content_desc?(0,s.jsx)("div",{className:"mt-2 whitespace-pre-wrap text-xs text-slate-400",children:e.text||e.content_desc}):null]},"".concat(e.resource_id||e.label,"-").concat(t)))})]})]}),tx?(0,s.jsxs)("div",{className:"mt-6 rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:"ws-scrcpy"}),(0,s.jsx)("a",{className:"btn-focus rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-200",href:tx,target:"_blank",rel:"noreferrer",children:W("新标签全屏打开","Open full tab")})]}),(0,s.jsx)("p",{className:"mt-2 text-xs leading-relaxed text-slate-500",children:W(th?"内嵌若黑屏:多为 WebSocket 未连上或服务未启动。请先确认「系统服务」里 android_panel 在线,并尝试新标签打开;Neko(Chromium)实例通常为 ".concat(th,"。"):"内嵌若黑屏:多为 WebSocket 未连上或服务未启动。请先确认「系统服务」里 android_panel 在线,并尝试新标签打开;Neko(Chromium)在 ENABLE_NEKO=1 且容器运行后一般为 9200 端口。",th?"Black iframe: often WebSocket or service down. Check android_panel in Services, try opening in a new tab; Neko Chromium instances are usually on ".concat(th,"."):"Black iframe: often WebSocket or service down. Check android_panel in Services, try opening in a new tab; Neko Chromium is often :9200 when ENABLE_NEKO=1 and the container is up.")}),(0,s.jsx)("iframe",{className:"mt-4 h-[30rem] w-full rounded-2xl border border-white/10 bg-black",src:tx,title:"ws-scrcpy"})]}):null]})]}):null,"config"===z?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:W("配置中心","Config Center")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:W("系统级与业务级配置文件分目录托管,避免大杂烩。","System and business configs are isolated by managed roots.")})]}),(0,s.jsx)(C,{className:"border border-white/12 bg-black/20",onClick:()=>void tv(ej),children:W("刷新","Refresh")})]}),(0,s.jsx)("select",{className:"mt-4 w-full rounded-2xl border border-white/12 bg-slate-950/60 px-4 py-3 text-sm text-white",value:ej,onChange:e=>{ew(e.target.value),eC("")},children:tz.map(e=>(0,s.jsxs)("option",{value:e.root_id,children:[e.label," | ",e.file_count]},e.root_id))}),ta?(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4 text-xs text-slate-400",children:[(0,s.jsx)("p",{className:"text-white",children:ta.label}),(0,s.jsx)("p",{className:"mt-2",children:ta.description}),(0,s.jsx)("p",{className:"mt-2 font-mono text-[11px] text-slate-500",children:ta.path})]}):null,(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(C,{className:"bg-cyan-600",disabled:!!G,onClick:()=>void tT(),children:W("新建","New")}),(0,s.jsx)(C,{className:"bg-rose-600",disabled:!ek||!!G,onClick:()=>void tA(),children:W("删除","Delete")})]}),(0,s.jsx)("div",{className:"mt-4 space-y-2",children:eN.map(e=>(0,s.jsxs)("button",{className:"btn-focus w-full rounded-2xl border px-4 py-3 text-left ".concat(ek===e.path?"border-cyan-500/40 bg-cyan-500/10":"border-white/8 bg-black/20"),onClick:()=>eC(e.path),children:[(0,s.jsx)("div",{className:"truncate text-sm text-white",children:e.path}),(0,s.jsxs)("div",{className:"mt-1 text-[11px] text-slate-500",children:[y(e.size)," | ",new Date(1e3*e.mtime).toLocaleString("zh"===L?"zh-CN":"en-US",{hour12:!1})]})]},e.path))})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:W("文件编辑器","Config Editor")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:W("仅允许编辑受管目录中的配置文件。","Only approved config roots are editable.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsxs)("label",{className:"btn-focus rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-100 ".concat(G?"cursor-not-allowed opacity-40":""),children:["file:import"===G?W("导入中...","Importing..."):W("导入/替换","Import/Replace"),(0,s.jsx)("input",{className:"hidden",disabled:!!G,type:"file",accept:".yaml,.yml,.json,.cfg,.env,.list,.txt,.ini",onChange:e=>void tU(e)},"config-".concat(e5))]}),(0,s.jsx)(C,{className:"bg-cyan-600",disabled:!ek||!!G,onClick:()=>void tR(),children:"file:save"===G?W("保存中...","Saving..."):W("保存","Save")})]})]}),(0,s.jsx)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 px-4 py-3 font-mono text-[11px] text-slate-500",children:ek?"".concat(ej," / ").concat(ek):W("请选择文件","Pick a file")}),(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(m,{lang:L,rootId:ej,filePath:ek,fileContent:eS,refreshKey:e8,busy:G,fetchJson:tp,notify:tu,onChangeContent:e_,onRefreshListing:()=>tv(ej,ek)})}),(0,s.jsx)("textarea",{className:"log-scroll mt-4 min-h-[32rem] w-full resize-y rounded-2xl border border-white/10 bg-black/45 p-4 font-mono text-xs leading-relaxed text-slate-200",spellCheck:!1,value:eS,onChange:e=>e_(e.target.value)})]})]}):null]})]}),A?null:(0,s.jsx)("nav",{className:"fixed bottom-0 left-0 right-0 z-40 flex justify-around border-t border-white/15 bg-black/75 py-1.5 backdrop-blur-lg [html[data-theme=light]_&]:border-slate-200/60 [html[data-theme=light]_&]:bg-white/90 md:hidden",style:{paddingBottom:"max(0.35rem, env(safe-area-inset-bottom))"},"aria-label":W("主导航","Main nav"),children:f.map(e=>(0,s.jsxs)("button",{type:"button",className:"btn-focus flex min-w-0 flex-1 flex-col items-center gap-0.5 rounded-xl px-1 py-1 text-[10px] font-medium ".concat(z===e?"text-cyan-300 [html[data-theme=light]_&]:text-cyan-700":"text-slate-400 [html[data-theme=light]_&]:text-slate-600"),onClick:()=>F(e),children:[(0,s.jsx)("span",{className:"text-lg leading-none","aria-hidden":!0,children:tF[e]}),(0,s.jsx)("span",{className:"truncate",children:{overview:W("总览","Home"),business:W("业务","Biz"),modules:W("模块","Mods"),shellcrash:"SC",android:W("安卓","Droid"),config:W("配置","Cfg")}[e]})]},e))})]})}},1387:function(e,t,l){function s(e,t,l){return"string"==typeof(null==l?void 0:l.error)&&l.error.trim()||"string"==typeof(null==l?void 0:l.message)&&l.message.trim()||"string"==typeof(null==l?void 0:l.detail)&&l.detail.trim()||function(e){let t=e.replace(/\s+/g," ").trim();return t?t.length<=240?t:"".concat(t.slice(0,237),"..."):""}(t)||function(e){var t;let l=(null===(t=e.statusText)||void 0===t?void 0:t.trim())?" ".concat(e.statusText.trim()):"";return"HTTP ".concat(e.status).concat(l)}(e)}async function a(e,t){let l=await fetch(e,{cache:"no-store",...t}),a=(await l.text()).trim(),r=null;if(a)try{r=JSON.parse(a)}catch(t){if(!l.ok)throw Error(s(l,a,null));throw Error("Invalid JSON response from ".concat(e))}if(!l.ok)throw Error(s(l,a,r));return null!==r?r:{}}async function r(e){let t=(await e.text()).trim(),l=null;if(t)try{l=JSON.parse(t)}catch(e){l=null}return s(e,t,l)}l.d(t,{N:function(){return a},e:function(){return r}})},90:function(e,t,l){l.d(t,{O0:function(){return a},Tc:function(){return n},U_:function(){return r}});let s=/^neko_browser(?:_(\d+))?$/i;function a(e){let t=new Map;for(let[l,a]of Object.entries(null!=e?e:{})){let e=l.match(s),r=a.trim();if(!e||!r)continue;let n="neko_browser"===l?1:Number(e[1]||1),i={id:n,key:l,label:"Neko ".concat(n),url:r,port:function(e){try{return new URL(e,"http://127.0.0.1").port||""}catch(e){return""}}(r)},o=t.get(n),c="neko_browser"!==l;(!o||c)&&t.set(n,i)}return Array.from(t.values()).sort((e,t)=>e.id-t.id)}function r(e,t){return e.length?!Number.isInteger(t)||t<0?{link:e[0],fallback:!1}:te.port).filter(Boolean);return t.length?t.map(e=>":".concat(e)).join(" / "):""}},8401:function(e,t,l){l.d(t,{p:function(){return s}});function s(e){let t=e.trim();if(!t)return t;try{let e=new URL(t,window.location.origin),l=e.hostname,s=window.location.hostname;if("0.0.0.0"===l||"::"===l||"[::]"===l)return e.hostname=s||l,e.toString();if(("127.0.0.1"===l||"localhost"===l)&&s&&"127.0.0.1"!==s&&"localhost"!==s)return e.hostname=s,e.toString();if(l.endsWith(".local")&&"8001"===e.port)return"".concat(e.pathname||"/").concat(e.search).concat(e.hash);if(l.endsWith(".local")&&s&&s!==l)return e.hostname=s,e.toString();return t}catch(e){return t}}}}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/246-b5d14933cf331e85.js b/d2ypp2/web-console/out/_next/static/chunks/246-b5d14933cf331e85.js deleted file mode 100644 index 525ebc2..0000000 --- a/d2ypp2/web-console/out/_next/static/chunks/246-b5d14933cf331e85.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[246],{9170:function(e,t,l){l.d(t,{Z:function(){return r}});var s=l(7437),a=l(2265);function r(e){let{snapshot:t,theme:r,tr:n}=e,i=(0,a.useRef)(null);return((0,a.useEffect)(()=>{let e=i.current;if(!e||!t)return;let s=!1,a=null,o="light"===r?"#0f172a":"#e2e8f0",c="light"===r?"#64748b":"#94a3b8",d="light"===r?"rgba(15,23,42,0.1)":"rgba(148,163,184,0.12)";l.e(614).then(l.bind(l,9614)).then(e=>{var l,r,x,h,m,u,b,p,g,f,v,j,w;if(s||!i.current)return;a=e.init(i.current,void 0,{renderer:"canvas"});let N=null!==(g=null===(l=t.cpu_load)||void 0===l?void 0:l["1m"])&&void 0!==g?g:0,y=null!==(f=null===(r=t.cpu_load)||void 0===r?void 0:r["5m"])&&void 0!==f?f:0,k=null!==(v=null===(x=t.cpu_load)||void 0===x?void 0:x["15m"])&&void 0!==v?v:0,C=(null===(h=t.memory)||void 0===h?void 0:h.total)||1,S=null!==(w=null!==(j=null===(m=t.memory)||void 0===m?void 0:m.available)&&void 0!==j?j:null===(u=t.memory)||void 0===u?void 0:u.free)&&void 0!==w?w:0,_=(null===(b=t.disk)||void 0===b?void 0:b.total)||1,D=(null===(p=t.disk)||void 0===p?void 0:p.free)||0;a.setOption({animationDurationUpdate:450,textStyle:{color:o},title:{text:n("无人直播节点 \xb7 资源","Unmanned live \xb7 resources"),left:12,top:8,textStyle:{color:o,fontSize:12,fontWeight:600}},tooltip:{trigger:"axis"},grid:{left:52,right:"48%",top:52,bottom:36},xAxis:{type:"category",data:["1m","5m","15m"],axisLabel:{color:c,fontSize:10},axisLine:{lineStyle:{color:d}}},yAxis:{type:"value",name:n("负载","Load"),nameTextStyle:{color:c,fontSize:10},axisLabel:{color:c,fontSize:10},splitLine:{lineStyle:{color:d}}},series:[{name:n("CPU","CPU"),type:"bar",data:[N,y,k],barMaxWidth:28,itemStyle:{borderRadius:[6,6,0,0],color:new e.graphic.LinearGradient(0,0,0,1,[{offset:0,color:"#22d3ee"},{offset:1,color:"#6366f1"}])}},{name:n("内存","RAM"),type:"pie",radius:["26%","40%"],center:["78%","38%"],label:{color:o,fontSize:9},data:[{value:Math.max(0,C-S),name:n("已用","Used")},{value:Math.max(0,S),name:n("可用","Free")}]},{name:n("磁盘","Disk"),type:"pie",radius:["20%","32%"],center:["78%","72%"],label:{color:o,fontSize:9},data:[{value:Math.max(0,_-D),name:n("已用","Used")},{value:Math.max(0,D),name:n("空闲","Free")}]}]})});let x=new ResizeObserver(()=>null==a?void 0:a.resize());return x.observe(e),()=>{s=!0,x.disconnect(),null==a||a.dispose()}},[t,r,n]),t)?(0,s.jsxs)("div",{className:"mt-4",children:[(0,s.jsx)("p",{className:"mb-2 text-xs opacity-70",children:n("ECharts 动态图表","ECharts live charts")}),(0,s.jsx)("div",{ref:i,className:"chart-surface h-64 w-full rounded-2xl border border-white/[0.08] bg-black/15 md:h-72"})]}):null}},2246:function(e,t,l){l.d(t,{d:function(){return k}});var s=l(7437),a=l(3145),r=l(2265),n=l(9170),i=l(2023),o=l(1817),c=l(7168),d=l(6865),x=l(5621),h=l(9076);function m(e){let{lang:t,rootId:l,filePath:a,fileContent:n,refreshKey:m,busy:u,fetchJson:b,notify:p,onChangeContent:g,onRefreshListing:f}=e,[v,j]=(0,r.useState)(null),[w,N]=(0,r.useState)(!1),[y,k]=(0,r.useState)(!1),[C,S]=(0,r.useState)(null),[_,D]=(0,r.useState)(null),E=(0,r.useCallback)((e,l)=>"zh"===t?e:l,[t]),O=(0,r.useCallback)(async()=>{if(!l||!a){j(null);return}N(!0);try{let e=new URLSearchParams({root:l,path:a}),t=await b("/config_insights?".concat(e.toString()));j(t)}catch(e){j(null),p(e.message)}finally{N(!1)}},[b,a,p,l]);(0,r.useEffect)(()=>{O()},[O,m]);let R=async()=>{if(l&&a){k(!0);try{let e=await b("/config_insights",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:l,path:a,content:n})});j(e),p(E("已分析当前编辑内容","Analyzed current editor draft"))}catch(e){p(e.message)}finally{k(!1)}}},T=async e=>{if(l&&a){S(e);try{let t=await b("/config_optimize",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:l,path:a,content:n,action:e})});"string"==typeof t.content&&g(t.content),t.insights&&j(e=>({...e,...t.insights,backups:(null==e?void 0:e.backups)||[]})),p(t.message||E("已应用优化","Optimization applied"))}catch(e){p(e.message)}finally{S(null)}}},U=async e=>{if(l&&a){D(e);try{let t=await b("/config_restore",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:l,path:a,backup_id:e})});"string"==typeof t.content&&g(t.content),await Promise.resolve(null==f?void 0:f()),await O(),p(t.message||E("已恢复历史版本","Backup restored"))}catch(e){p(e.message)}finally{D(null)}}};if(!a)return(0,s.jsx)("div",{className:"rounded-2xl border border-white/8 bg-black/20 p-4 text-sm text-slate-400",children:E("选择文件后显示诊断、回滚和一键优化。","Pick a file to see diagnostics, rollback, and one-click optimizations.")});let A=(null==v?void 0:v.issues)||[],P=(null==v?void 0:v.actions)||[],I=(null==v?void 0:v.backups)||[],L=(null==v?void 0:v.stats)||[];return(0,s.jsxs)("div",{className:"space-y-4",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-gradient-to-br from-cyan-500/[0.08] via-black/25 to-transparent p-4",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-white",children:[(0,s.jsx)(i.Z,{className:"h-4 w-4 text-cyan-300"}),(0,s.jsx)("h3",{className:"text-sm font-semibold",children:E("配置治理","Config governance")}),(null==v?void 0:v.source)?(0,s.jsx)("span",{className:"rounded-full border border-white/10 bg-black/25 px-2 py-0.5 text-[10px] uppercase tracking-wider text-slate-400",children:v.source}):null]}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:(null==v?void 0:v.summary)||E("校验配置风险、查看历史快照,并将常见优化应用到编辑器。","Validate risks, inspect snapshots, and apply optimizations into the editor.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsxs)("button",{type:"button",disabled:!!u||w,onClick:()=>void O(),className:"btn-focus inline-flex items-center gap-2 rounded-xl border border-white/10 bg-black/25 px-3 py-2 text-xs text-slate-100 disabled:opacity-40",children:[w?(0,s.jsx)(o.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,s.jsx)(c.Z,{className:"h-3.5 w-3.5"}),E("刷新已保存状态","Refresh saved state")]}),(0,s.jsxs)("button",{type:"button",disabled:!!u||y,onClick:()=>void R(),className:"btn-focus inline-flex items-center gap-2 rounded-xl border border-cyan-500/30 bg-cyan-500/15 px-3 py-2 text-xs text-cyan-100 disabled:opacity-40",children:[y?(0,s.jsx)(o.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,s.jsx)(d.Z,{className:"h-3.5 w-3.5"}),E("分析当前编辑器","Analyze editor draft")]})]})]}),(0,s.jsx)("div",{className:"mt-4 grid gap-2 sm:grid-cols-2 xl:grid-cols-4",children:L.slice(0,8).map(e=>(0,s.jsxs)("div",{className:"rounded-xl border border-white/8 bg-black/20 px-3 py-2.5",children:[(0,s.jsx)("div",{className:"text-[10px] uppercase tracking-wider text-slate-500",children:e.label}),(0,s.jsx)("div",{className:"mt-1 truncate font-mono text-sm text-white",children:e.value})]},e.key))})]}),(0,s.jsxs)("div",{className:"grid gap-4 xl:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/8 bg-black/20 p-4",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-white",children:[(0,s.jsx)(d.Z,{className:"h-4 w-4 text-amber-300"}),(0,s.jsx)("h4",{className:"text-sm font-semibold",children:E("风险与建议","Risks & guidance")})]}),A.length?(0,s.jsx)("div",{className:"mt-3 space-y-2",children:A.map((e,t)=>{var l;return(0,s.jsxs)("div",{className:"rounded-xl border px-3 py-2 text-xs ".concat("error"===(l=e.level)?"border-rose-500/30 bg-rose-500/10 text-rose-100":"warning"===l?"border-amber-500/30 bg-amber-500/10 text-amber-100":"border-cyan-500/30 bg-cyan-500/10 text-cyan-100"),children:[(0,s.jsxs)("div",{className:"font-medium",children:[e.message,e.line?" (L".concat(e.line,")"):""]}),(0,s.jsx)("div",{className:"mt-1 font-mono opacity-70",children:e.code})]},"".concat(e.code,"-").concat(t))})}):(0,s.jsx)("p",{className:"mt-3 text-xs text-emerald-300/90",children:E("当前没有发现明显配置风险。","No obvious config risks were detected.")}),(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:P.length?P.map(e=>(0,s.jsx)("button",{type:"button",disabled:!!u||!!C,onClick:()=>void T(e.id),className:"btn-focus rounded-xl border border-violet-500/30 bg-violet-500/15 px-3 py-2 text-xs text-violet-100 disabled:opacity-40",title:e.description,children:C===e.id?E("处理中...","Working..."):e.label},e.id)):(0,s.jsx)("span",{className:"text-xs text-slate-500",children:E("当前文件没有可自动应用的预设。","No auto-applicable presets for this file.")})})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/8 bg-black/20 p-4",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-white",children:[(0,s.jsx)(x.Z,{className:"h-4 w-4 text-cyan-300"}),(0,s.jsx)("h4",{className:"text-sm font-semibold",children:E("历史快照","Backup snapshots")})]}),I.length?(0,s.jsx)("div",{className:"mt-3 space-y-2",children:I.slice(0,8).map(e=>(0,s.jsx)("div",{className:"rounded-xl border border-white/8 bg-black/25 px-3 py-2.5",children:(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-xs text-white",children:new Date(e.created_at).toLocaleString("zh"===t?"zh-CN":"en-US",{hour12:!1})}),(0,s.jsxs)("div",{className:"mt-1 text-[11px] text-slate-500",children:[e.reason," \xb7 ",function(e){if(!e)return"0 B";let t=["B","KB","MB","GB"],l=e,s=0;for(;l>=1024&&s=10||0===s?0:1)," ").concat(t[s])}(e.size),"legacy"===e.source?" \xb7 ".concat(E("旧备份","legacy")):""]})]}),(0,s.jsxs)("button",{type:"button",disabled:!!u||!!_,onClick:()=>void U(e.id),className:"btn-focus inline-flex items-center gap-1 rounded-lg border border-white/10 bg-white/5 px-3 py-1.5 text-xs text-slate-100 disabled:opacity-40",children:[_===e.id?(0,s.jsx)(o.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,s.jsx)(h.Z,{className:"h-3.5 w-3.5"}),E("恢复","Restore")]})]})},e.id))}):(0,s.jsx)("p",{className:"mt-3 text-xs text-slate-500",children:E("当前文件还没有 Web 侧快照。保存、删除或恢复后会自动累积历史。","No Web snapshots yet. Saving, deleting, or restoring will accumulate history automatically.")})]})]})]})}var u=l(1387),b=l(90),p=l(8401),g=l(257);let f=["overview","business","modules","shellcrash","android","config"],v=new Set(["shellcrash-configs","shellcrash-yamls","shellcrash-jsons"]),j=()=>void 0!==g&&g.env.NEXT_PUBLIC_API_URL||"";function w(e){if(!e)return"0 B";let t=["B","KB","MB","GB","TB"],l=e,s=0;for(;l>=1024&&s=10||0===s?0:1)," ").concat(t[s])}function N(e){return"online"===e?"border-emerald-500/30 bg-emerald-500/10 text-emerald-200":"stopped"===e?"border-slate-500/30 bg-slate-500/10 text-slate-300":"configured"===e?"border-violet-500/30 bg-violet-500/10 text-violet-200":"unavailable"===e?"border-slate-700/30 bg-slate-800/50 text-slate-500":"error"===e?"border-rose-500/30 bg-rose-500/10 text-rose-200":"border-cyan-500/30 bg-cyan-500/10 text-cyan-200"}function y(e){let{children:t,className:l,disabled:a,onClick:r,title:n}=e;return(0,s.jsx)("button",{type:"button",className:"btn-focus rounded-xl px-3 py-2 text-xs font-semibold text-white disabled:cursor-not-allowed disabled:opacity-40 ".concat(l||""),disabled:a,onClick:r,title:n,children:t})}function k(e){var t,l,i,o,c,d,x,h,g,k,C,S,_,D,E,O;let{embeddedShellCrash:R=!1,portalLang:T}=e,U=j(),[A,P]=(0,r.useState)("zh"),[I,L]=(0,r.useState)("dark"),[M,B]=(0,r.useState)("overview"),z=(0,r.useCallback)((e,t)=>"zh"===A?e:t,[A]),[F,W]=(0,r.useState)(!0),[K,H]=(0,r.useState)(null),[Y,J]=(0,r.useState)(null),[Z,V]=(0,r.useState)(null),[G,Q]=(0,r.useState)(!0),q=(0,r.useRef)(null),[X,$]=(0,r.useState)([]),[ee,et]=(0,r.useState)(""),[el,es]=(0,r.useState)("unknown"),[ea,er]=(0,r.useState)(""),[en,ei]=(0,r.useState)(""),[eo,ec]=(0,r.useState)(null),[ed,ex]=(0,r.useState)([]),[eh,em]=(0,r.useState)(null),[eu,eb]=(0,r.useState)(null),[ep,eg]=(0,r.useState)([]),[ef,ev]=(0,r.useState)(""),[ej,ew]=(0,r.useState)([]),[eN,ey]=(0,r.useState)(""),[ek,eC]=(0,r.useState)(""),[eS,e_]=(0,r.useState)(!1),[eD,eE]=(0,r.useState)([]),[eO,eR]=(0,r.useState)(""),[eT,eU]=(0,r.useState)(null),[eA,eP]=(0,r.useState)([]),[eI,eL]=(0,r.useState)([]),[eM,eB]=(0,r.useState)(""),[ez,eF]=(0,r.useState)(""),[eW,eK]=(0,r.useState)("com.zhiliaoapp.musically"),[eH,eY]=(0,r.useState)("https://www.tiktok.com"),[eJ,eZ]=(0,r.useState)(""),[eV,eG]=(0,r.useState)(""),[eQ,eq]=(0,r.useState)(Date.now()),[eX,e$]=(0,r.useState)("tap"),[e0,e2]=(0,r.useState)(null),[e1,e3]=(0,r.useState)(0),[e5,e4]=(0,r.useState)(0),[e8,e6]=(0,r.useState)(null),[e9,e7]=(0,r.useState)(null),[te,tt]=(0,r.useState)(!1),tl=null!==(D=ep.find(e=>e.root_id===ef))&&void 0!==D?D:null,ts=ep.filter(e=>v.has(e.root_id)),ta=ep.filter(e=>!v.has(e.root_id)),tr=null!==(E=ed.find(e=>"shellcrash"===e.service_id))&&void 0!==E?E:null,tn=null!==(O=ed.find(e=>"android_panel"===e.service_id))&&void 0!==O?O:null,ti=(0,r.useMemo)(()=>{var e;let t=null!==(e=null==eo?void 0:eo.quick_links)&&void 0!==e?e:{},l={};for(let[e,s]of Object.entries(t)){let t=String(s);l[e]=/^https?:\/\//i.test(t)?(0,p.p)(t):t}return l},[eo]),to=(0,r.useMemo)(()=>(0,b.O0)(ti),[ti]),tc=(0,r.useMemo)(()=>(0,b.Tc)(to),[to]),td=(0,r.useMemo)(()=>{let e=ti.ws_scrcpy||((null==tn?void 0:tn.host)&&tn.port?"http://".concat(tn.host,":").concat(tn.port):(null==eo?void 0:eo.mdns_host)?"http://".concat(eo.mdns_host,":5000"):"");return e?(0,p.p)(e):""},[null==tn?void 0:tn.host,null==tn?void 0:tn.port,ti.ws_scrcpy,null==eo?void 0:eo.mdns_host]),tx=function(e){let t=null==e?void 0:e.match(/(\d+)x(\d+)/);return t?{width:Number(t[1]),height:Number(t[2])}:null}(null==eT?void 0:eT.resolution),th=(0,r.useCallback)(e=>{J(e),null!=q.current&&window.clearTimeout(q.current),q.current=window.setTimeout(()=>{J(null),q.current=null},2500)},[]),tm=(0,r.useCallback)(async(e,t)=>(0,u.N)("".concat(U).concat(e),t),[U]),tu=(0,r.useCallback)((e,t)=>{let l=new URL(window.location.href);l.pathname="shellcrash"===e?"/shellcrash":"android"===e?"/android":"/console","/console"===l.pathname?l.searchParams.set("tab",e):l.searchParams.delete("tab"),l.searchParams.set("lang",t),window.history.replaceState(null,"",l.toString()),window.localStorage.setItem("live-console-lang",t)},[]),tb=(0,r.useCallback)(async()=>{if(!ee)return;let e=await tm("/status?process=".concat(encodeURIComponent(ee)));es(e.process_status||"unknown"),er(e.recent_log||""),ei(e.recent_error||"")},[ee,tm]),tp=(0,r.useCallback)(async()=>{let[e,t,l]=await Promise.all([tm("/stack/services"),tm("/system_snapshot"),tm("/hardware_profile")]);ex(e.services||[]),em(t),eb(l)},[tm]),tg=(0,r.useCallback)(async(e,t)=>{if(!e)return;let l=(await tm("/managed_files?root=".concat(encodeURIComponent(e)))).files||[];ew(l);let s=t||eN;if(s&&l.some(e=>e.path===s))ey(s);else{var a;ey((null===(a=l[0])||void 0===a?void 0:a.path)||"")}},[tm,eN]),tf=(0,r.useCallback)(async()=>{var e;let t=await tm("/android/devices"),l=t.devices||[],s=eO&&l.some(e=>e.serial===eO)?eO:(null===(e=l[0])||void 0===e?void 0:e.serial)||"";return e_(!!t.available),eE(l),eR(s),s},[eO,tm]),tv=(0,r.useCallback)(async e=>{if(!e){eU(null);return}eU(await tm("/android/overview?serial=".concat(encodeURIComponent(e))))},[tm]),tj=(0,r.useCallback)(async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:eM;if(!e){eL([]);return}eL((await tm("/android/packages?serial=".concat(encodeURIComponent(e),"&query=").concat(encodeURIComponent(t),"&limit=60"))).packages||[])},[eM,tm]),tw=(0,r.useCallback)(async e=>{if(!e){eP([]);return}eP((await tm("/android/ui?serial=".concat(encodeURIComponent(e),"&limit=80"))).nodes||[])},[tm]),tN=(0,r.useCallback)(async(e,t)=>{ev(e),ey(t),await tg(e,t)},[tg]),ty=(0,r.useCallback)((e,t)=>{B("config"),window.setTimeout(()=>{tN(e,t)},0)},[tN]),tk=(0,r.useCallback)(async()=>{V("hardware:probe");try{let e=await tm("/hardware_profile?refresh=true");eb(e),th(z("硬件探测已更新","Hardware profile refreshed"))}catch(e){th(e.message)}finally{V(null)}},[tm,th,z]),tC=(0,r.useCallback)(async()=>{W(!0),H(null);try{var e,t,l,s;let[a,r,n]=await Promise.all([tm("/process_monitor"),tm("/server_info"),tm("/managed_roots")]);$(a.entries||[]),et((null===(t=a.entries)||void 0===t?void 0:null===(e=t[0])||void 0===e?void 0:e.pm2)||""),ec(r.stack||null),eg(n.roots||[]),ev((null===(s=n.roots)||void 0===s?void 0:null===(l=s[0])||void 0===l?void 0:l.root_id)||""),await Promise.all([tp(),tf()])}catch(e){H(e.message)}finally{W(!1)}},[tm,tf,tp]);(0,r.useEffect)(()=>{if(R){if(B("shellcrash"),"zh"===T||"en"===T)P(T);else{let e=window.localStorage.getItem("live-hub-lang");("zh"===e||"en"===e)&&P(e)}return}let e=new URLSearchParams(window.location.search),t=function(e){let t=e.replace(/\/+$/,"")||"/";return"/shellcrash"===t?"shellcrash":"/android"===t?"android":null}(window.location.pathname),l=e.get("tab"),s=e.get("lang"),a=window.localStorage.getItem("live-console-lang");t?B(t):null!==l&&f.includes(l)&&B(l),"zh"===s||"en"===s?P(s):("zh"===a||"en"===a)&&P(a);let r=window.localStorage.getItem("live-console-theme");("light"===r||"dark"===r)&&L(r)},[R,T]),(0,r.useEffect)(()=>{R||(document.documentElement.setAttribute("data-theme",I),window.localStorage.setItem("live-console-theme",I))},[I,R]),(0,r.useEffect)(()=>{let e=()=>Q("visible"===document.visibilityState);return e(),document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[]),(0,r.useEffect)(()=>()=>{null!=q.current&&window.clearTimeout(q.current)},[]),(0,r.useEffect)(()=>{R&&("zh"===T||"en"===T)&&P(T)},[R,T]),(0,r.useEffect)(()=>{R||tu(M,A)},[R,A,tu,M]),(0,r.useEffect)(()=>{tC()},[tC]),(0,r.useEffect)(()=>{if(!ee||!G)return;tb();let e=window.setInterval(()=>void tb(),1500);return()=>window.clearInterval(e)},[ee,G,tb]),(0,r.useEffect)(()=>{if(F||K||!G||"overview"!==M&&"modules"!==M&&"shellcrash"!==M)return;tp();let e=window.setInterval(()=>void tp(),1e4);return()=>clearInterval(e)},[F,K,G,tp,M]),(0,r.useEffect)(()=>{let e="shellcrash"===M?ts:"config"===M?ta:ep;e.length&&!e.some(e=>e.root_id===ef)&&(ev(e[0].root_id),ey(""))},[ta,ef,ep,ts,M]),(0,r.useEffect)(()=>{ef&&tg(ef)},[tg,ef]),(0,r.useEffect)(()=>{if(!ef||!eN){eC("");return}(async()=>{try{let e=await tm("/managed_file?root=".concat(encodeURIComponent(ef),"&path=").concat(encodeURIComponent(eN)));eC(e.content||"")}catch(e){th(e.message)}})()},[tm,eN,th,ef]),(0,r.useEffect)(()=>{"android"===M&&(async()=>{let e=await tf();e&&(await Promise.all([tv(e),tw(e),tj(e)]),eq(Date.now()))})()},[tf,tv,tj,tw,M]),(0,r.useEffect)(()=>{if("android"!==M||!eO||!G)return;tv(eO),eq(Date.now());let e=window.setInterval(()=>{tv(eO),eq(Date.now())},5e3);return()=>window.clearInterval(e)},[eO,G,tv,M]),(0,r.useEffect)(()=>{if(!eO){e6(e=>(e&&URL.revokeObjectURL(e),null)),e7(null),tt(!1);return}let e=new AbortController,t="".concat(U,"/android/screenshot?serial=").concat(encodeURIComponent(eO),"&ts=").concat(eQ);return tt(!0),e7(null),fetch(t,{signal:e.signal}).then(async e=>{if(!e.ok)throw Error(await (0,u.e)(e));return e.blob()}).then(e=>{if(!e.type.startsWith("image/"))throw Error("Not an image");let t=URL.createObjectURL(e);e6(e=>(e&&URL.revokeObjectURL(e),t))}).catch(e=>{"AbortError"!==e.name&&(e7(e.message),e6(e=>(e&&URL.revokeObjectURL(e),null)))}).finally(()=>{e.signal.aborted||tt(!1)}),()=>{e.abort()}},[eO,eQ,U]);let tS=async e=>{if(ee){V("process:".concat(e));try{let t=await tm("/".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({process:ee})});th(String(t.output||t.pm2_output||t.message||"OK")),await tb()}catch(e){th(e.message)}finally{V(null)}}},t_=async(e,t)=>{V("".concat(e,":").concat(t));try{let l=await tm("/service_action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({service:e,action:t})});th(l.message||"OK"),await tp()}catch(e){th(e.message)}finally{V(null)}},tD=async()=>{if(ef&&eN){V("file:save");try{await tm("/managed_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:ef,path:eN,content:ek})}),th(z("文件已保存","File saved")),await tg(ef,eN),e4(e=>e+1)}catch(e){th(e.message)}finally{V(null)}}},tE=async()=>{if(!(null==tl?void 0:tl.allow_create)){th(z("当前目录不允许新建文件","The current root does not allow new files"));return}let e=window.prompt(z("请输入新的相对路径","Enter a new relative path"),tl.default_file||"");if(e){V("file:create");try{await tm("/managed_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:ef,path:e,content:""})}),th(z("文件已创建","File created")),await tg(ef,e),e4(e=>e+1)}catch(e){th(e.message)}finally{V(null)}}},tO=async()=>{if(ef&&eN){if(!(null==tl?void 0:tl.allow_delete)){th(z("当前目录不允许删除文件","The current root does not allow deletion"));return}if(window.confirm(z("确定删除该文件?","Delete this file?"))){V("file:delete");try{await tm("/managed_file?root=".concat(encodeURIComponent(ef),"&path=").concat(encodeURIComponent(eN)),{method:"DELETE"}),th(z("文件已删除","File deleted")),await tg(ef),e4(e=>e+1)}catch(e){th(e.message)}finally{V(null)}}}},tR=async e=>{var t;let l=null===(t=e.target.files)||void 0===t?void 0:t[0];if(e.target.value="",e3(e=>e+1),l&&ef){V("file:import");try{let e=await l.text();await tm("/managed_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:ef,path:l.name,content:e})}),th(z("导入完成,已替换同名文件","Import finished and replaced matching file")),ey(l.name),await tg(ef,l.name),e4(e=>e+1)}catch(e){th(e.message)}finally{V(null)}}},tT=async(e,t)=>{if(!eO){th(z("当前没有可用的 ADB 设备","No active ADB device"));return}V("android:".concat(e));try{let l=await tm("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,serial:eO,payload:t||{}})});th(l.message||"OK"),l.output&&eG(l.output),eq(Date.now()),await tv(eO)}catch(e){th(e.message)}finally{V(null)}},tU="tap"===eX?z("点击","Tap"):"double_tap"===eX?z("双击","Double Tap"):z("长按","Long Press"),tA=async e=>{if(!eO){th(z("当前没有可用的 ADB 设备","No active ADB device"));return}let t=function(e,t,l){let s,a,r,n;let i=e.getBoundingClientRect(),o=e.naturalWidth,c=e.naturalHeight;if(!o||!c||!i.width||!i.height)return null;let d=i.width/i.height,x=o/c;x>d?(s=i.width,a=i.width/x,r=0,n=(i.height-a)/2):(a=i.height,s=i.height*x,r=(i.width-s)/2,n=0);let h=t-i.left-r,m=l-i.top-n;return h<0||m<0||h>s||m>a?null:{x:Math.max(0,Math.min(o-1,Math.round(h/s*o))),y:Math.max(0,Math.min(c-1,Math.round(m/a*c)))}}(e.currentTarget,e.clientX,e.clientY);if(!t){th(z("请点击画面有效区域","Tap inside the visible frame"));return}let l=(null==tx?void 0:tx.width)||e.currentTarget.naturalWidth,s=(null==tx?void 0:tx.height)||e.currentTarget.naturalHeight,a=l>0?l/Math.max(1,e.currentTarget.naturalWidth):1,r=s>0?s/Math.max(1,e.currentTarget.naturalHeight):1,n=Math.max(0,Math.min(l||t.x,Math.round(t.x*a))),i=Math.max(0,Math.min(s||t.y,Math.round(t.y*r)));if(e2({x:n,y:i}),"long_press"===eX){await tT("long_press",{x:n,y:i,duration:750});return}await tT(eX,{x:n,y:i})},tP=e=>"shellcrash"===e.service_id&&(null==eo?void 0:eo.control_url)?"".concat(eo.control_url,"/shellcrash?lang=").concat(A):"android_panel"===e.service_id&&(null==eo?void 0:eo.control_url)?"".concat(eo.control_url,"/android?lang=").concat(A):e.url||"",tI=e=>({online:z("在线","Online"),stopped:z("已停止","Stopped"),configured:z("已配置","Configured"),unavailable:z("未安装","Unavailable")})[e]||e,tL="shellcrash"===M?ts:ta,tM={overview:"\uD83D\uDCCA",business:"\uD83C\uDFAC",modules:"\uD83E\uDDE9",shellcrash:"\uD83D\uDEE1️",android:"\uD83E\uDD16",config:"⚙️"};return(0,s.jsxs)(s.Fragment,{children:[R?null:(0,s.jsx)("div",{className:"border-b border-white/[0.08] bg-slate-950/80 backdrop-blur-md",children:(0,s.jsxs)("div",{className:"mx-auto flex max-w-7xl flex-wrap items-center justify-between gap-2 px-4 py-2.5 text-xs sm:px-6 lg:px-10",children:[(0,s.jsxs)("a",{className:"font-medium text-amber-400/95 transition hover:text-amber-300",href:"/",children:["← ",z("返回门户首页","Back to portal")]}),(0,s.jsx)("span",{className:"text-slate-500",children:z("无人直播 \xb7 本页需与 API 同域(推荐 live.local:8001)","Unmanned live \xb7 same origin as API (live.local:8001)")})]})}),(0,s.jsxs)("main",{className:R?"mx-auto min-h-0 max-w-7xl px-1 pb-4 pt-1 sm:px-3":"safe-pb-nav mx-auto min-h-screen max-w-7xl px-4 pb-16 pt-6 sm:px-6 lg:px-10",children:[Y?(0,s.jsx)("div",{role:"status","aria-live":"polite","aria-atomic":"true",className:"animate-toast-in fixed bottom-24 left-1/2 z-50 max-w-[min(92vw,28rem)] -translate-x-1/2 rounded-2xl border border-cyan-500/25 bg-slate-950/95 px-5 py-3 text-center text-sm text-cyan-50 shadow-lg md:bottom-6 [html[data-theme=light]_&]:border-cyan-600/25 [html[data-theme=light]_&]:bg-white/95 [html[data-theme=light]_&]:text-cyan-950",children:Y}):null,R?(0,s.jsxs)("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-2 border-b border-white/[0.08] pb-3",children:[(0,s.jsx)("h2",{className:"text-base font-semibold text-[color:var(--text)]",children:"ShellCrash"}),(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",onClick:()=>void tC(),children:z("刷新","Refresh")})]}):(0,s.jsxs)("header",{className:"mb-8 flex flex-col gap-4",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-[11px] font-semibold uppercase tracking-[0.22em] text-cyan-400/90",children:z("控制平面 \xb7 ARM Linux 开发板","Control plane \xb7 ARM Linux SBC")}),(0,s.jsx)("h1",{className:"mt-2 text-3xl font-bold text-[color:var(--text)] sm:text-4xl",children:z("无人直播控制中心","Unmanned live control center")}),(0,s.jsx)("p",{className:"mt-3 max-w-3xl text-sm text-slate-400",children:z("ShellCrash 负责代理上网;本机 FFmpeg 处理推流或 HDMI;Neko(Docker Chromium)或本机 Chromium 负责浏览器侧;开发板通过 USB 双头线 ADB 控制 AOSP。各模块独立,可分别启停。","ShellCrash for egress; FFmpeg for stream or HDMI; Neko (Docker Chromium) or host Chromium for browser; USB ADB to AOSP. Modules are isolated.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-3",children:[(0,s.jsx)("div",{className:"meta-chip max-w-full",children:((null==eo?void 0:eo.mdns_host)||"live.local")+" \xb7 "+((null==eo?void 0:eo.machine)||"unknown")+" \xb7 "+((null==eo?void 0:eo.kernel)||"unknown")}),(0,s.jsx)(y,{className:"zh"===A?"border border-cyan-400/50 bg-cyan-500/10":"border border-white/12 bg-black/20",onClick:()=>P("zh"),children:"中文"}),(0,s.jsx)(y,{className:"en"===A?"border border-cyan-400/50 bg-cyan-500/10":"border border-white/12 bg-black/20",onClick:()=>P("en"),children:"EN"}),(0,s.jsx)(y,{className:"light"===I?"border border-amber-400/50 bg-amber-500/15":"border border-white/12 bg-black/20",onClick:()=>L("light"),title:z("日间主题","Light theme"),children:z("☀️ 日间","☀️ Light")}),(0,s.jsx)(y,{className:"dark"===I?"border border-indigo-400/50 bg-indigo-500/15":"border border-white/12 bg-black/20",onClick:()=>L("dark"),title:z("夜间主题","Dark theme"),children:z("\uD83C\uDF19 夜间","\uD83C\uDF19 Dark")}),(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",onClick:()=>void tC(),children:z("刷新","Refresh")})]})]}),(0,s.jsx)("nav",{className:"tab-strip","aria-label":z("主导航","Primary navigation"),children:f.map(e=>(0,s.jsx)("button",{type:"button",className:"tab-btn ".concat(M===e?"tab-btn-active":""),onClick:()=>B(e),children:{overview:z("总览","Overview"),business:z("直播业务","Live ops"),modules:z("系统服务","Services"),shellcrash:"ShellCrash",android:z("安卓设备","Android"),config:z("配置中心","Config")}[e]},e))})]}),F?(0,s.jsx)("div",{className:"glass rounded-3xl py-24 text-center text-slate-400",children:z("正在连接控制台...","Connecting to the control plane...")}):null,!F&&K?(0,s.jsx)("div",{className:"glass rounded-3xl border border-rose-500/25 bg-rose-950/20 p-8 text-center text-rose-200",children:K}):null,F||K?null:(0,s.jsxs)("div",{className:"grid gap-6",children:["overview"===M?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("section",{className:"glass rounded-3xl border border-amber-500/20 bg-gradient-to-br from-amber-500/[0.07] to-transparent p-6",children:[(0,s.jsx)("h2",{className:"section-title",children:z("第一次用?按这条线理解整套板子","New here? Follow this mental model")}),(0,s.jsxs)("ol",{className:"mt-4 list-decimal space-y-2 pl-5 text-sm leading-relaxed text-slate-300",children:[(0,s.jsx)("li",{children:z("插电、接网线或连好 Wi‑Fi 后,用浏览器打开本页(验收域名一般为 http://live.local:8001/ ,门户在根路径 /,控制台在 /console)。","After power and Ethernet/Wi‑Fi, open this stack in a browser (often http://live.local:8001/ — portal at /, full console at /console).")}),(0,s.jsx)("li",{children:z("「直播业务」里启停 PM2 脚本(抖音→YouTube、HDMI 等);「系统服务」看 ShellCrash、SRS、ws-scrcpy、Neko 等是否在跑。","Use Live ops for PM2 scripts; Services for ShellCrash, SRS, ws-scrcpy, Neko, etc.")}),(0,s.jsx)("li",{children:z("「安卓设备」需要 USB 调试授权;截图预览 + ws-scrcpy 低延迟画面二选一或同用。TikTok 等场景常配合板载 AOSP。","Android tab needs USB debugging; use screenshot taps and/or ws-scrcpy. TikTok workflows often use on-board AOSP.")}),(0,s.jsx)("li",{children:z("深度指标点 Netdata;命令行点 WebTTY;代理规则与 YAML 在 ShellCrash 页。","Netdata for metrics; WebTTY for shell; ShellCrash tab for proxy rules and YAML.")})]})]}),(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"section-title",children:z("\uD83D\uDEF0️ 流媒体与桌面入口","Streaming & desktop")}),(0,s.jsx)("p",{className:"section-lead",children:z("ws-scrcpy:浏览器里控安卓;Chromium:本机+油猴+RemoteDebug;Neko:Docker 里跑 Chromium 桌面(非 Firefox 版)。","ws-scrcpy: browser ADB; Chromium: host+Tampermonkey+9222; Neko: Chromium desktop in Docker (not the Firefox image).")}),(0,s.jsxs)("div",{className:"mt-4 flex max-h-[28rem] flex-col gap-2 overflow-y-auto pr-1 log-scroll",children:[(null==eo?void 0:eo.dashboard_url)?(0,s.jsx)("a",{className:"link-tile",href:eo.dashboard_url,target:"_blank",rel:"noreferrer",children:"\uD83C\uDFE0 Homepage"}):null,(null==eo?void 0:eo.control_url)?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("a",{className:"link-tile",href:"".concat(eo.control_url,"/console?tab=shellcrash&lang=").concat(A),target:"_blank",rel:"noreferrer",children:"\uD83D\uDEE1️ ShellCrash"}),(0,s.jsxs)("a",{className:"link-tile",href:"".concat(eo.control_url,"/console?tab=android&lang=").concat(A),target:"_blank",rel:"noreferrer",children:["\uD83E\uDD16 ",z("安卓中心 (含 ws-scrcpy)","Android hub + ws-scrcpy")]}),(0,s.jsxs)("a",{className:"link-tile",href:"".concat(eo.control_url,"/console?tab=config&lang=").concat(A),target:"_blank",rel:"noreferrer",children:["⚙️ ",z("配置中心","Config")]})]}):null,ti.ws_scrcpy?(0,s.jsxs)("a",{className:"link-tile link-tile-accent",href:ti.ws_scrcpy,target:"_blank",rel:"noreferrer",children:["\uD83D\uDCF1 ws-scrcpy (",z("原始流控制页","raw stream UI"),")"]}):null,ti.chromium_remote_debug?(0,s.jsxs)("a",{className:"link-tile",href:ti.chromium_remote_debug,target:"_blank",rel:"noreferrer",children:["\uD83E\uDDEA ",z("Chromium RemoteDebug (9222)","Chromium RemoteDebug")]}):null,to.map(e=>(0,s.jsxs)("a",{className:"link-tile link-tile-warn",href:e.url,target:"_blank",rel:"noreferrer",children:["\uD83D\uDC31 ",e.label," / ",z("Docker Chromium 桌面","Docker Chromium desktop")]},e.key)),ti.webtty?(0,s.jsx)("a",{className:"link-tile",href:ti.webtty,target:"_blank",rel:"noreferrer",children:"⌨️ WebTTY"}):null,ti.filebrowser?(0,s.jsx)("a",{className:"link-tile",href:ti.filebrowser,target:"_blank",rel:"noreferrer",children:"\uD83D\uDCC2 File Browser"}):null,ti.netdata?(0,s.jsx)("a",{className:"link-tile",href:ti.netdata,target:"_blank",rel:"noreferrer",children:"\uD83D\uDCC8 Netdata"}):null,ti.srs_http?(0,s.jsx)("a",{className:"link-tile",href:ti.srs_http,target:"_blank",rel:"noreferrer",children:"\uD83C\uDF9E️ SRS :8080"}):null,ti.srs_api?(0,s.jsx)("a",{className:"link-tile",href:ti.srs_api,target:"_blank",rel:"noreferrer",children:"\uD83C\uDF9E️ SRS API :1985"}):null]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"section-title",children:z("节点状态","Node Status")}),(0,s.jsxs)("div",{className:"panel-inset mt-4",children:[(0,s.jsx)("p",{children:(null==eo?void 0:eo.mdns_host)||"live.local"}),(0,s.jsxs)("p",{className:"mt-2",children:["IP: ",((null==eo?void 0:eo.ips)||[]).join(" / ")||"-"]}),(0,s.jsx)("p",{className:"mt-2",children:(null==eo?void 0:eo.machine)||"-"}),(0,s.jsx)("p",{className:"mt-2",children:(null==eo?void 0:eo.kernel)||"-"})]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"section-title",children:z("系统快照","System Snapshot")}),(0,s.jsx)("p",{className:"section-lead",children:z("总览页每 10 秒自动刷新服务与监控数据。","Overview auto-refreshes every 10s.")}),(0,s.jsxs)("div",{className:"panel-inset mt-4",children:[(0,s.jsxs)("p",{children:["CPU:"," ",[null==eh?void 0:null===(t=eh.cpu_load)||void 0===t?void 0:t["1m"],null==eh?void 0:null===(l=eh.cpu_load)||void 0===l?void 0:l["5m"],null==eh?void 0:null===(i=eh.cpu_load)||void 0===i?void 0:i["15m"]].map(e=>"number"==typeof e?e.toFixed(2):"0.00").join(" / ")]}),(0,s.jsxs)("p",{className:"mt-2",children:["RAM: ",w(null==eh?void 0:null===(o=eh.memory)||void 0===o?void 0:o.available)," / ",w(null==eh?void 0:null===(c=eh.memory)||void 0===c?void 0:c.total)]}),(0,s.jsxs)("p",{className:"mt-2",children:["Disk: ",w(null==eh?void 0:null===(d=eh.disk)||void 0===d?void 0:d.free)," / ",w(null==eh?void 0:null===(x=eh.disk)||void 0===x?void 0:x.total)]}),(0,s.jsxs)("p",{className:"mt-2",children:["Netdata: ",(null==eh?void 0:null===(h=eh.netdata)||void 0===h?void 0:h.available)?eh.netdata.version||"online":"offline"]})]}),(0,s.jsx)(n.Z,{snapshot:eh,theme:I,tr:z})]})]}),(0,s.jsxs)("section",{className:"glass rounded-3xl p-6",children:[(0,s.jsx)("h2",{className:"section-title",children:z("模块概况","Module Summary")}),(0,s.jsx)("div",{className:"mt-4 grid gap-4 md:grid-cols-2 xl:grid-cols-3",children:ed.map(e=>(0,s.jsxs)("div",{className:"service-card",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:e.label}),(0,s.jsx)("p",{className:"mt-1 text-xs text-slate-400",children:e.description})]}),(0,s.jsx)("span",{className:"rounded-full border px-2.5 py-1 text-xs ".concat(N(e.status)),children:tI(e.status)})]}),(0,s.jsx)("p",{className:"mt-3 min-h-[3rem] text-xs text-slate-500",children:e.detail||"-"}),tP(e)?(0,s.jsx)("a",{className:"btn-focus mt-3 inline-flex rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-200",href:tP(e),target:"_blank",rel:"noreferrer",children:z("打开","Open")}):null]},e.service_id))})]})]}):null,"business"===M?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-12",children:[(0,s.jsx)("h2",{className:"section-title",children:z("⚡ 快捷配置","Quick config")}),(0,s.jsx)("p",{className:"section-lead",children:z("跳转配置中心编辑推流与录制相关文件。","Jump to the config editor for stream keys and URLs.")}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(y,{className:"border border-cyan-500/30 bg-cyan-600/80",onClick:()=>ty("app-config","youtube.ini"),children:"youtube.ini"}),(0,s.jsx)(y,{className:"border border-cyan-500/30 bg-cyan-600/80",onClick:()=>ty("app-config","URL_config.ini"),children:"URL_config.ini"}),(0,s.jsx)(y,{className:"border border-white/15 bg-black/30",onClick:()=>ty("app-config","config.ini"),children:"config.ini"}),(0,s.jsx)(y,{className:"border border-white/15 bg-black/30",onClick:()=>ty("stack-config","system-stack.env"),children:"system-stack.env"})]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"section-title",children:z("业务运行时","Business Runtime")}),(0,s.jsx)("p",{className:"section-lead",children:z("这里只放业务脚本本身,Hub 基座可单独运行。","Only business processes live here.")}),X.length>0?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("select",{className:"field-select mt-4",value:ee,onChange:e=>et(e.target.value),children:X.map(e=>(0,s.jsxs)("option",{value:e.pm2,children:[e.label," | ",e.script]},e.pm2))}),(0,s.jsxs)("div",{className:"mt-4 flex items-center justify-between rounded-2xl border border-white/8 bg-black/20 px-4 py-3",children:[(0,s.jsx)("span",{className:"rounded-full border px-3 py-1 text-xs ".concat(N(el)),children:tI(el)}),(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",onClick:()=>void tb(),children:z("轮询","Poll")})]}),(0,s.jsxs)("div",{className:"mt-4 grid grid-cols-2 gap-2",children:[(0,s.jsx)(y,{className:"bg-emerald-600",disabled:"process:start"===Z,onClick:()=>void tS("start"),children:"process:start"===Z?z("启动中...","Starting..."):z("启动","Start")}),(0,s.jsx)(y,{className:"bg-amber-600",disabled:"process:restart"===Z,onClick:()=>void tS("restart"),children:"process:restart"===Z?z("重启中...","Restarting..."):z("重启","Restart")}),(0,s.jsx)(y,{className:"col-span-2 bg-rose-600",disabled:"process:stop"===Z,onClick:()=>void tS("stop"),children:"process:stop"===Z?z("停止中...","Stopping..."):z("停止","Stop")})]})]}):(0,s.jsx)("div",{className:"mt-4 rounded-2xl border border-dashed border-white/12 bg-black/20 p-4 text-sm text-slate-400",children:z("未发现业务进程。若只部署了 Hub 基座,这是正常状态。","No business process discovered.")})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsx)("h2",{className:"section-title",children:z("业务日志","Process Logs")}),(0,s.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,s.jsx)("pre",{className:"log-scroll min-h-[22rem] rounded-2xl border border-emerald-500/15 bg-black/55 p-4 font-mono text-[11px] text-emerald-100/95",children:ea||z("暂无输出","No stdout yet.")}),(0,s.jsx)("pre",{className:"log-scroll min-h-[22rem] rounded-2xl border border-rose-500/15 bg-black/55 p-4 font-mono text-[11px] text-rose-100/95",children:en||z("暂无报错","No stderr yet.")})]})]})]}):null,"modules"===M?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"section-title",children:z("系统模块","System Modules")}),(0,s.jsx)("p",{className:"section-lead",children:z("每个模块都独立启停和降级,避免一个服务异常拖垮整套业务。","Each module starts and degrades independently.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",onClick:()=>void tp(),children:z("刷新服务","Refresh Services")}),(0,s.jsx)(y,{className:"border border-violet-500/35 bg-violet-600/70",disabled:"hardware:probe"===Z,onClick:()=>void tk(),children:"hardware:probe"===Z?z("探测中…","Probing…"):z("重探测硬件","Re-probe HW")})]})]}),(0,s.jsx)("div",{className:"mt-4 grid gap-4 md:grid-cols-2",children:ed.map(e=>(0,s.jsxs)("div",{className:"service-card",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:e.label}),(0,s.jsx)("p",{className:"mt-1 text-xs text-slate-400",children:e.description})]}),(0,s.jsx)("span",{className:"rounded-full border px-2.5 py-1 text-xs ".concat(N(e.status)),children:tI(e.status)})]}),(0,s.jsx)("p",{className:"mt-3 min-h-[3rem] text-xs text-slate-500",children:e.detail||"-"}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(y,{className:"bg-emerald-600",disabled:!e.available||!!Z,onClick:()=>void t_(e.service_id,"start"),children:z("启动","Start")}),(0,s.jsx)(y,{className:"bg-amber-600",disabled:!e.available||!!Z,onClick:()=>void t_(e.service_id,"restart"),children:z("重启","Restart")}),(0,s.jsx)(y,{className:"bg-rose-600",disabled:!e.available||!!Z,onClick:()=>void t_(e.service_id,"stop"),children:z("停止","Stop")}),tP(e)?(0,s.jsx)("a",{className:"btn-focus rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-200",href:tP(e),target:"_blank",rel:"noreferrer",children:z("打开","Open")}):null]})]},e.service_id))})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:z("硬件与系统","Hardware and System")}),(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4 text-xs text-slate-400",children:[(0,s.jsxs)("p",{children:["Arch: ",(null==eu?void 0:eu.arch)||"-"]}),(0,s.jsxs)("p",{className:"mt-2",children:["FFmpeg: ",((null==eu?void 0:eu.ffmpeg_hwaccels)||[]).join(", ")||"-"]}),(0,s.jsxs)("p",{className:"mt-2",children:["GPU: ",(null==eu?void 0:null===(g=eu.gpu)||void 0===g?void 0:g.present)?eu.gpu.driver||"present":"none"]}),(0,s.jsxs)("p",{className:"mt-2",children:["NPU: ",(null==eu?void 0:null===(k=eu.npu)||void 0===k?void 0:k.present)?(eu.npu.devices||[]).join(", "):"none"]}),(0,s.jsxs)("p",{className:"mt-2",children:["Decoder: ",(null==eu?void 0:null===(C=eu.recommendation)||void 0===C?void 0:C.video_decoder)||"cpu"]}),(0,s.jsxs)("p",{className:"mt-2",children:["HDMI: ",(null==eu?void 0:null===(S=eu.recommendation)||void 0===S?void 0:S.hdmi_player)||"cpu"]}),(0,s.jsxs)("p",{className:"mt-2",children:["Mode: ",(null==eu?void 0:null===(_=eu.recommendation)||void 0===_?void 0:_.stability_mode)||"safe"]})]})]})]}):null,"shellcrash"===M?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:"ShellCrash"}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:z("这里不再依赖命令行菜单,直接做 YAML / JSON / CFG 编辑与服务控制。","Manage ShellCrash from the web instead of the shell menu.")}),tr?(0,s.jsxs)("div",{className:"mt-4 rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:tr.label}),(0,s.jsx)("p",{className:"mt-1 text-xs text-slate-400",children:tr.description})]}),(0,s.jsx)("span",{className:"rounded-full border px-2.5 py-1 text-xs ".concat(N(tr.status)),children:tI(tr.status)})]}),(0,s.jsx)("p",{className:"mt-3 text-xs text-slate-500",children:tr.detail||"-"}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(y,{className:"bg-emerald-600",disabled:!tr.available||!!Z,onClick:()=>void t_("shellcrash","start"),children:z("启动","Start")}),(0,s.jsx)(y,{className:"bg-amber-600",disabled:!tr.available||!!Z,onClick:()=>void t_("shellcrash","restart"),children:z("重启","Restart")}),(0,s.jsx)(y,{className:"bg-rose-600",disabled:!tr.available||!!Z,onClick:()=>void t_("shellcrash","stop"),children:z("停止","Stop")})]})]}):null,(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4 text-xs text-slate-400",children:[(0,s.jsx)("p",{className:"text-white",children:z("快捷文件","Quick Files")}),(0,s.jsxs)("div",{className:"mt-3 grid gap-2",children:[(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tN("shellcrash-yamls","config.yaml"),children:"config.yaml"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tN("shellcrash-configs","ShellCrash.cfg"),children:"ShellCrash.cfg"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tN("shellcrash-configs","servers.list"),children:"servers.list"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-left text-slate-200",onClick:()=>void tN("shellcrash-configs","command.env"),children:"command.env"})]})]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:z("ShellCrash 文件编辑器","ShellCrash Editor")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:z("支持查看、修改、新建、删除,路径被限制在 ShellCrash 托管目录内。","View, edit, create and delete files inside managed ShellCrash roots.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsxs)("label",{className:"btn-focus rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-100 ".concat(Z?"cursor-not-allowed opacity-40":""),children:["file:import"===Z?z("导入中...","Importing..."):z("导入/替换","Import/Replace"),(0,s.jsx)("input",{className:"hidden",disabled:!!Z,type:"file",accept:".yaml,.yml,.json,.cfg,.env,.list,.txt",onChange:e=>void tR(e)},e1)]}),(0,s.jsx)(y,{className:"bg-cyan-600",disabled:!eN||!!Z,onClick:()=>void tD(),children:"file:save"===Z?z("保存中...","Saving..."):z("保存","Save")})]})]}),(0,s.jsxs)("div",{className:"mt-4 grid gap-6 xl:grid-cols-[18rem,1fr]",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("select",{className:"w-full rounded-2xl border border-white/12 bg-slate-950/60 px-4 py-3 text-sm text-white",value:ef,onChange:e=>{ev(e.target.value),ey("")},children:ts.map(e=>(0,s.jsxs)("option",{value:e.root_id,children:[e.label," | ",e.file_count]},e.root_id))}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(y,{className:"bg-cyan-600",disabled:!!Z,onClick:()=>void tE(),children:z("新建","New")}),(0,s.jsx)(y,{className:"bg-rose-600",disabled:!eN||!!Z,onClick:()=>void tO(),children:z("删除","Delete")})]}),(0,s.jsx)("div",{className:"mt-4 space-y-2",children:ej.map(e=>(0,s.jsxs)("button",{className:"btn-focus w-full rounded-2xl border px-4 py-3 text-left ".concat(eN===e.path?"border-cyan-500/40 bg-cyan-500/10":"border-white/8 bg-black/20"),onClick:()=>ey(e.path),children:[(0,s.jsx)("div",{className:"truncate text-sm text-white",children:e.path}),(0,s.jsx)("div",{className:"mt-1 text-[11px] text-slate-500",children:w(e.size)})]},e.path))})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"rounded-2xl border border-white/8 bg-black/20 px-4 py-3 font-mono text-[11px] text-slate-500",children:eN?"".concat(ef," / ").concat(eN):z("请选择文件","Pick a file")}),(0,s.jsx)("textarea",{className:"log-scroll mt-4 min-h-[32rem] w-full resize-y rounded-2xl border border-white/10 bg-black/45 p-4 font-mono text-xs leading-relaxed text-slate-200",spellCheck:!1,value:ek,onChange:e=>eC(e.target.value)})]})]})]})]}):null,"android"===M?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:z("安卓设备中心","Android Device Center")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:z("把设备发现、截图预览、ADB 动作和原始 web-scrcpy 放到一个模块里。","Combine discovery, preview, ADB actions and raw web-scrcpy in one module.")})]}),(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",onClick:()=>void(async()=>{let e=await tf();e&&await Promise.all([tv(e),tw(e),tj(e)]),eq(Date.now())})(),children:z("刷新设备","Refresh")})]}),(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4",children:[(0,s.jsx)("p",{className:"text-sm font-semibold text-white",children:z("已连接设备","Devices")}),eS&&0!==eD.length?(0,s.jsx)("div",{className:"mt-3 space-y-2",children:eD.map(e=>(0,s.jsxs)("button",{className:"btn-focus w-full rounded-2xl border px-4 py-3 text-left ".concat(eO===e.serial?"border-cyan-500/40 bg-cyan-500/10":"border-white/8 bg-black/20"),onClick:()=>{eR(e.serial),Promise.all([tv(e.serial),tw(e.serial),tj(e.serial)]),eq(Date.now())},children:[(0,s.jsx)("div",{className:"text-sm text-white",children:e.model||e.device||e.serial}),(0,s.jsxs)("div",{className:"mt-1 text-[11px] text-slate-500",children:[e.serial," | ",e.state]})]},e.serial))}):(0,s.jsx)("p",{className:"mt-3 text-sm text-slate-400",children:z("当前没有可用的 ADB 设备。","No active ADB device.")})]}),(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4 text-xs text-slate-400",children:[(0,s.jsx)("p",{className:"text-white",children:z("设备状态","Device Status")}),(0,s.jsxs)("p",{className:"mt-2",children:[(null==eT?void 0:eT.brand)||"-"," ",(null==eT?void 0:eT.model)||"-"]}),(0,s.jsxs)("p",{className:"mt-2",children:["Android ",(null==eT?void 0:eT.android_version)||"-"," / SDK ",(null==eT?void 0:eT.sdk)||"-"]}),(0,s.jsx)("p",{className:"mt-2 whitespace-pre-wrap",children:(null==eT?void 0:eT.battery)||"-"}),(0,s.jsx)("p",{className:"mt-2 whitespace-pre-wrap",children:(null==eT?void 0:eT.resolution)||"-"}),(0,s.jsx)("p",{className:"mt-2 whitespace-pre-wrap",children:(null==eT?void 0:eT.focus)||"-"})]})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:z("屏幕预览与动作","Screen Preview and Actions")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:z("预览图支持直接点按/双击/长按,配合 UI 节点和包管理形成更完整的安卓控制台。","The preview supports tap, double tap and long press, backed by UI nodes and package tools.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)(y,{className:"border border-white/12 ".concat("tap"===eX?"bg-cyan-600":"bg-black/20"),disabled:!eO||!!Z,onClick:()=>e$("tap"),children:z("点击","Tap")}),(0,s.jsx)(y,{className:"border border-white/12 ".concat("double_tap"===eX?"bg-cyan-600":"bg-black/20"),disabled:!eO||!!Z,onClick:()=>e$("double_tap"),children:z("双击","Double Tap")}),(0,s.jsx)(y,{className:"border border-white/12 ".concat("long_press"===eX?"bg-cyan-600":"bg-black/20"),disabled:!eO||!!Z,onClick:()=>e$("long_press"),children:z("长按","Long Press")}),(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",disabled:!eO,onClick:()=>eq(Date.now()),children:z("刷新截图","Refresh Shot")})]})]}),(0,s.jsx)("div",{className:"mt-4 overflow-hidden rounded-3xl border border-white/8 bg-black/35 p-4",children:eO?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)("div",{className:"mb-3 flex flex-wrap items-center gap-3 text-xs text-slate-400",children:[(0,s.jsxs)("span",{children:[z("当前动作","Current action"),": ",tU]}),(0,s.jsxs)("span",{children:[z("分辨率","Resolution"),": ",(null==eT?void 0:eT.resolution)||"-"]}),(0,s.jsxs)("span",{children:[z("最近坐标","Last point"),": ",e0?"".concat(e0.x,", ").concat(e0.y):"-"]}),te?(0,s.jsx)("span",{className:"text-cyan-400/90",children:z("截图刷新中…","Refreshing…")}):null]}),e9?(0,s.jsxs)("div",{className:"mb-3 rounded-xl border border-rose-500/30 bg-rose-950/25 px-4 py-3 text-sm text-rose-100",children:[z("截图不可用:","Screenshot unavailable: "),e9]}):null,e8?(0,s.jsx)(a.default,{alt:"Android preview",className:"max-h-[min(70vh,48rem)] min-h-[14rem] w-full cursor-crosshair rounded-2xl object-contain bg-black",onClick:e=>void tA(e),src:e8,unoptimized:!0,width:(null==tx?void 0:tx.width)||1080,height:(null==tx?void 0:tx.height)||1920}):e9?null:(0,s.jsx)("div",{className:"flex min-h-[18rem] items-center justify-center rounded-2xl border border-dashed border-white/10 bg-black/30 text-sm text-slate-500",children:z("正在拉取截图…","Fetching screenshot…")})]}):(0,s.jsx)("div",{className:"flex min-h-[18rem] items-center justify-center rounded-2xl border border-dashed border-white/10 bg-black/20 text-sm text-slate-500",children:z("当前没有可用的 ADB 设备。","No active ADB device.")})}),(0,s.jsxs)("div",{className:"mt-6 grid gap-6 xl:grid-cols-3",children:[(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:z("快捷控制","Quick Controls")}),(0,s.jsxs)("div",{className:"mt-4 grid grid-cols-3 gap-2",children:[[["HOME","KEYCODE_HOME"],["BACK","KEYCODE_BACK"],["RECENTS","KEYCODE_APP_SWITCH"],["POWER","KEYCODE_POWER"],["NOTIFY","KEYCODE_NOTIFICATION"],["VOL+","KEYCODE_VOLUME_UP"],["VOL-","KEYCODE_VOLUME_DOWN"]].map(e=>{let[t,l]=e;return(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs text-slate-100",disabled:!eO||!!Z,onClick:()=>void tT("key",{keycode:l}),children:t},t)}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs text-slate-100",disabled:!eO||!!Z,onClick:()=>void tT("wake"),children:"WAKE"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs text-slate-100",disabled:!eO||!!Z,onClick:()=>void tT("rotate",{rotation:"0"}),children:"Portrait"}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs text-slate-100",disabled:!eO||!!Z,onClick:()=>void tT("rotate",{rotation:"1"}),children:"Landscape"})]}),(0,s.jsx)("div",{className:"mt-4 grid grid-cols-2 gap-2",children:["up","down","left","right"].map(e=>(0,s.jsxs)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-3 text-xs uppercase text-slate-100",disabled:!eO||!!Z,onClick:()=>void tT("swipe",{direction:e}),children:["Swipe ",e]},e))})]}),(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:z("输入与跳转","Input and Launch")}),(0,s.jsx)("textarea",{className:"mt-4 min-h-[6rem] w-full rounded-2xl border border-white/10 bg-black/45 p-4 text-sm text-slate-200",placeholder:z("输入要发送到安卓输入框的文字","Text to send to Android"),value:ez,onChange:e=>eF(e.target.value)}),(0,s.jsx)(y,{className:"mt-3 bg-cyan-600",disabled:!ez.trim()||!eO||!!Z,onClick:()=>void tT("text",{text:ez}),children:z("发送文本","Send Text")}),(0,s.jsx)("input",{className:"mt-4 w-full rounded-2xl border border-white/10 bg-black/45 px-4 py-3 text-sm text-slate-200",placeholder:"com.zhiliaoapp.musically",value:eW,onChange:e=>eK(e.target.value)}),(0,s.jsxs)("div",{className:"mt-3 grid grid-cols-3 gap-2",children:[(0,s.jsx)(y,{className:"bg-emerald-600",disabled:!eW.trim()||!eO||!!Z,onClick:()=>void tT("launch_package",{package:eW}),children:z("启动","Launch")}),(0,s.jsx)(y,{className:"bg-amber-600",disabled:!eW.trim()||!eO||!!Z,onClick:()=>void tT("force_stop",{package:eW}),children:z("停应用","Stop App")}),(0,s.jsx)(y,{className:"bg-rose-600",disabled:!eW.trim()||!eO||!!Z,onClick:()=>void tT("clear_app",{package:eW}),children:z("清数据","Clear Data")})]}),(0,s.jsx)("input",{className:"mt-4 w-full rounded-2xl border border-white/10 bg-black/45 px-4 py-3 text-sm text-slate-200",placeholder:"https://www.tiktok.com",value:eH,onChange:e=>eY(e.target.value)}),(0,s.jsx)(y,{className:"mt-3 bg-violet-600",disabled:!eH.trim()||!eO||!!Z,onClick:()=>void tT("open_url",{url:eH}),children:z("打开链接","Open URL")})]}),(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:z("应用工作台","App Workspace")}),(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",disabled:!eO||!!Z,onClick:()=>void tw(eO),children:z("刷新UI","Refresh UI")})]}),(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:[["TikTok","com.zhiliaoapp.musically"],["Chrome","com.android.chrome"],["Settings","com.android.settings"],["YouTube","com.google.android.youtube"],["Play","com.android.vending"]].map(e=>{let[t,l]=e;return(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 bg-slate-950/50 px-3 py-2 text-xs text-slate-100",disabled:!eO||!!Z,onClick:()=>{eK(l),tT("launch_package",{package:l})},children:t},l)})}),(0,s.jsxs)("div",{className:"mt-4 flex gap-2",children:[(0,s.jsx)("input",{className:"w-full rounded-2xl border border-white/10 bg-black/45 px-4 py-3 text-sm text-slate-200",placeholder:z("搜索包名,例如 tiktok","Search package, e.g. tiktok"),value:eM,onChange:e=>eB(e.target.value)}),(0,s.jsx)(y,{className:"bg-cyan-600",disabled:!eO||!!Z,onClick:()=>void tj(eO),children:z("搜索","Search")})]}),(0,s.jsx)("div",{className:"mt-4 space-y-2",children:0===eI.length?(0,s.jsx)("div",{className:"rounded-2xl border border-dashed border-white/10 px-4 py-6 text-sm text-slate-500",children:z("还没有查询结果。","No package results yet.")}):eI.slice(0,8).map(e=>(0,s.jsxs)("div",{className:"rounded-2xl border border-white/8 bg-slate-950/30 p-3",children:[(0,s.jsx)("div",{className:"text-sm text-white",children:e.label||e.package.split(".").pop()}),(0,s.jsx)("div",{className:"mt-1 truncate font-mono text-[11px] text-slate-500",children:e.package}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eO||!!Z,onClick:()=>{eK(e.package),tT("launch_package",{package:e.package})},children:z("启动","Launch")}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eO||!!Z,onClick:()=>{eK(e.package),tT("force_stop",{package:e.package})},children:z("停应用","Stop")}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eO||!!Z,onClick:()=>{eK(e.package),tT("clear_app",{package:e.package})},children:z("清数据","Clear")})]})]},e.package))})]})]}),(0,s.jsxs)("div",{className:"mt-6 grid gap-6 xl:grid-cols-[0.95fr,1.05fr]",children:[(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:"ADB Shell"}),(0,s.jsxs)("div",{className:"mt-4 flex flex-col gap-3 lg:flex-row",children:[(0,s.jsx)("input",{className:"w-full rounded-2xl border border-white/10 bg-black/45 px-4 py-3 text-sm text-slate-200",placeholder:"input keyevent KEYCODE_HOME",value:eJ,onChange:e=>eZ(e.target.value)}),(0,s.jsx)(y,{className:"bg-amber-600",disabled:!eJ.trim()||!eO||!!Z,onClick:()=>void tT("shell",{command:eJ}),children:z("执行命令","Run Command")})]}),(0,s.jsx)("pre",{className:"log-scroll mt-4 min-h-[14rem] rounded-2xl border border-white/10 bg-black/45 p-4 font-mono text-[11px] text-slate-200",children:eV||z("动作结果会显示在这里。","Action output will appear here.")})]}),(0,s.jsxs)("div",{className:"rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:z("UI 节点","UI Nodes")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:z("用 uiautomator 抓当前页面结构,快速定位可点击元素。","Inspect the current UI hierarchy and act on clickable nodes.")})]}),(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",disabled:!eO||!!Z,onClick:()=>void tw(eO),children:z("刷新节点","Refresh Nodes")})]}),(0,s.jsx)("div",{className:"mt-4 space-y-3",children:0===eA.length?(0,s.jsx)("div",{className:"rounded-2xl border border-dashed border-white/10 px-4 py-6 text-sm text-slate-500",children:z("还没有抓到 UI 节点。","No UI nodes yet.")}):eA.slice(0,12).map((e,t)=>(0,s.jsxs)("div",{className:"rounded-2xl border border-white/8 bg-slate-950/30 p-3",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-sm text-white",children:e.label||e.resource_id||e.class_name||"node"}),(0,s.jsx)("div",{className:"mt-1 text-[11px] text-slate-500",children:e.resource_id||e.class_name||"-"}),(0,s.jsxs)("div",{className:"mt-1 text-[11px] text-slate-500",children:[e.bounds," | ",e.center_x,",",e.center_y]})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eO||!!Z,onClick:()=>void tT("tap",{x:e.center_x,y:e.center_y}),children:z("点击","Tap")}),(0,s.jsx)("button",{className:"btn-focus rounded-xl border border-white/10 px-3 py-2 text-xs text-slate-200",disabled:!eO||!!Z,onClick:()=>void tT("long_press",{x:e.center_x,y:e.center_y,duration:750}),children:z("长按","Long Press")})]})]}),e.text||e.content_desc?(0,s.jsx)("div",{className:"mt-2 whitespace-pre-wrap text-xs text-slate-400",children:e.text||e.content_desc}):null]},"".concat(e.resource_id||e.label,"-").concat(t)))})]})]}),td?(0,s.jsxs)("div",{className:"mt-6 rounded-3xl border border-white/8 bg-black/20 p-5",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:"ws-scrcpy"}),(0,s.jsx)("a",{className:"btn-focus rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-200",href:td,target:"_blank",rel:"noreferrer",children:z("新标签全屏打开","Open full tab")})]}),(0,s.jsx)("p",{className:"mt-2 text-xs leading-relaxed text-slate-500",children:z(tc?"内嵌若黑屏:多为 WebSocket 未连上或服务未启动。请先确认「系统服务」里 android_panel 在线,并尝试新标签打开;Neko(Chromium)实例通常为 ".concat(tc,"。"):"内嵌若黑屏:多为 WebSocket 未连上或服务未启动。请先确认「系统服务」里 android_panel 在线,并尝试新标签打开;Neko(Chromium)在 ENABLE_NEKO=1 且容器运行后一般为 9200 端口。",tc?"Black iframe: often WebSocket or service down. Check android_panel in Services, try opening in a new tab; Neko Chromium instances are usually on ".concat(tc,"."):"Black iframe: often WebSocket or service down. Check android_panel in Services, try opening in a new tab; Neko Chromium is often :9200 when ENABLE_NEKO=1 and the container is up.")}),(0,s.jsx)("iframe",{className:"mt-4 h-[30rem] w-full rounded-2xl border border-white/10 bg-black",src:td,title:"ws-scrcpy"})]}):null]})]}):null,"config"===M?(0,s.jsxs)("section",{className:"grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-4",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:z("配置中心","Config Center")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:z("系统级与业务级配置文件分目录托管,避免大杂烩。","System and business configs are isolated by managed roots.")})]}),(0,s.jsx)(y,{className:"border border-white/12 bg-black/20",onClick:()=>void tg(ef),children:z("刷新","Refresh")})]}),(0,s.jsx)("select",{className:"mt-4 w-full rounded-2xl border border-white/12 bg-slate-950/60 px-4 py-3 text-sm text-white",value:ef,onChange:e=>{ev(e.target.value),ey("")},children:tL.map(e=>(0,s.jsxs)("option",{value:e.root_id,children:[e.label," | ",e.file_count]},e.root_id))}),tl?(0,s.jsxs)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 p-4 text-xs text-slate-400",children:[(0,s.jsx)("p",{className:"text-white",children:tl.label}),(0,s.jsx)("p",{className:"mt-2",children:tl.description}),(0,s.jsx)("p",{className:"mt-2 font-mono text-[11px] text-slate-500",children:tl.path})]}):null,(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsx)(y,{className:"bg-cyan-600",disabled:!!Z,onClick:()=>void tE(),children:z("新建","New")}),(0,s.jsx)(y,{className:"bg-rose-600",disabled:!eN||!!Z,onClick:()=>void tO(),children:z("删除","Delete")})]}),(0,s.jsx)("div",{className:"mt-4 space-y-2",children:ej.map(e=>(0,s.jsxs)("button",{className:"btn-focus w-full rounded-2xl border px-4 py-3 text-left ".concat(eN===e.path?"border-cyan-500/40 bg-cyan-500/10":"border-white/8 bg-black/20"),onClick:()=>ey(e.path),children:[(0,s.jsx)("div",{className:"truncate text-sm text-white",children:e.path}),(0,s.jsxs)("div",{className:"mt-1 text-[11px] text-slate-500",children:[w(e.size)," | ",new Date(1e3*e.mtime).toLocaleString("zh"===A?"zh-CN":"en-US",{hour12:!1})]})]},e.path))})]}),(0,s.jsxs)("article",{className:"glass rounded-3xl p-6 xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold text-white",children:z("文件编辑器","Config Editor")}),(0,s.jsx)("p",{className:"mt-2 text-xs text-slate-400",children:z("仅允许编辑受管目录中的配置文件。","Only approved config roots are editable.")})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsxs)("label",{className:"btn-focus rounded-xl border border-white/12 px-3 py-2 text-xs text-slate-100 ".concat(Z?"cursor-not-allowed opacity-40":""),children:["file:import"===Z?z("导入中...","Importing..."):z("导入/替换","Import/Replace"),(0,s.jsx)("input",{className:"hidden",disabled:!!Z,type:"file",accept:".yaml,.yml,.json,.cfg,.env,.list,.txt,.ini",onChange:e=>void tR(e)},"config-".concat(e1))]}),(0,s.jsx)(y,{className:"bg-cyan-600",disabled:!eN||!!Z,onClick:()=>void tD(),children:"file:save"===Z?z("保存中...","Saving..."):z("保存","Save")})]})]}),(0,s.jsx)("div",{className:"mt-4 rounded-2xl border border-white/8 bg-black/20 px-4 py-3 font-mono text-[11px] text-slate-500",children:eN?"".concat(ef," / ").concat(eN):z("请选择文件","Pick a file")}),(0,s.jsx)("div",{className:"mt-4",children:(0,s.jsx)(m,{lang:A,rootId:ef,filePath:eN,fileContent:ek,refreshKey:e5,busy:Z,fetchJson:tm,notify:th,onChangeContent:eC,onRefreshListing:()=>tg(ef,eN)})}),(0,s.jsx)("textarea",{className:"log-scroll mt-4 min-h-[32rem] w-full resize-y rounded-2xl border border-white/10 bg-black/45 p-4 font-mono text-xs leading-relaxed text-slate-200",spellCheck:!1,value:ek,onChange:e=>eC(e.target.value)})]})]}):null]})]}),R?null:(0,s.jsx)("nav",{className:"fixed bottom-0 left-0 right-0 z-40 flex justify-around border-t border-white/15 bg-black/75 py-1.5 backdrop-blur-lg [html[data-theme=light]_&]:border-slate-200/60 [html[data-theme=light]_&]:bg-white/90 md:hidden",style:{paddingBottom:"max(0.35rem, env(safe-area-inset-bottom))"},"aria-label":z("主导航","Main nav"),children:f.map(e=>(0,s.jsxs)("button",{type:"button",className:"btn-focus flex min-w-0 flex-1 flex-col items-center gap-0.5 rounded-xl px-1 py-1 text-[10px] font-medium ".concat(M===e?"text-cyan-300 [html[data-theme=light]_&]:text-cyan-700":"text-slate-400 [html[data-theme=light]_&]:text-slate-600"),onClick:()=>B(e),children:[(0,s.jsx)("span",{className:"text-lg leading-none","aria-hidden":!0,children:tM[e]}),(0,s.jsx)("span",{className:"truncate",children:{overview:z("总览","Home"),business:z("业务","Biz"),modules:z("模块","Mods"),shellcrash:"SC",android:z("安卓","Droid"),config:z("配置","Cfg")}[e]})]},e))})]})}},1387:function(e,t,l){function s(e,t,l){return"string"==typeof(null==l?void 0:l.error)&&l.error.trim()||"string"==typeof(null==l?void 0:l.message)&&l.message.trim()||"string"==typeof(null==l?void 0:l.detail)&&l.detail.trim()||function(e){let t=e.replace(/\s+/g," ").trim();return t?t.length<=240?t:"".concat(t.slice(0,237),"..."):""}(t)||function(e){var t;let l=(null===(t=e.statusText)||void 0===t?void 0:t.trim())?" ".concat(e.statusText.trim()):"";return"HTTP ".concat(e.status).concat(l)}(e)}async function a(e,t){let l=await fetch(e,{cache:"no-store",...t}),a=(await l.text()).trim(),r=null;if(a)try{r=JSON.parse(a)}catch(t){if(!l.ok)throw Error(s(l,a,null));throw Error("Invalid JSON response from ".concat(e))}if(!l.ok)throw Error(s(l,a,r));return null!==r?r:{}}async function r(e){let t=(await e.text()).trim(),l=null;if(t)try{l=JSON.parse(t)}catch(e){l=null}return s(e,t,l)}l.d(t,{N:function(){return a},e:function(){return r}})},90:function(e,t,l){l.d(t,{O0:function(){return a},Tc:function(){return n},U_:function(){return r}});let s=/^neko_browser(?:_(\d+))?$/i;function a(e){let t=new Map;for(let[l,a]of Object.entries(null!=e?e:{})){let e=l.match(s),r=a.trim();if(!e||!r)continue;let n="neko_browser"===l?1:Number(e[1]||1),i={id:n,key:l,label:"Neko ".concat(n),url:r,port:function(e){try{return new URL(e,"http://127.0.0.1").port||""}catch(e){return""}}(r)},o=t.get(n),c="neko_browser"!==l;(!o||c)&&t.set(n,i)}return Array.from(t.values()).sort((e,t)=>e.id-t.id)}function r(e,t){return e.length?!Number.isInteger(t)||t<0?{link:e[0],fallback:!1}:te.port).filter(Boolean);return t.length?t.map(e=>":".concat(e)).join(" / "):""}},8401:function(e,t,l){l.d(t,{p:function(){return s}});function s(e){let t=e.trim();if(!t)return t;try{let e=new URL(t,window.location.origin),l=e.hostname,s=window.location.hostname;if("0.0.0.0"===l||"::"===l||"[::]"===l)return e.hostname=s||l,e.toString();if(("127.0.0.1"===l||"localhost"===l)&&s&&"127.0.0.1"!==s&&"localhost"!==s)return e.hostname=s,e.toString();if(l.endsWith(".local")&&"8001"===e.port)return"".concat(e.pathname||"/").concat(e.search).concat(e.hash);if(l.endsWith(".local")&&s&&s!==l)return e.hostname=s,e.toString();return t}catch(e){return t}}}}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/app/android/page-84550dabda18d658.js b/d2ypp2/web-console/out/_next/static/chunks/app/android/page-69ff6e74a15b80d9.js similarity index 54% rename from d2ypp2/web-console/out/_next/static/chunks/app/android/page-84550dabda18d658.js rename to d2ypp2/web-console/out/_next/static/chunks/app/android/page-69ff6e74a15b80d9.js index 5899f09..9294e09 100644 --- a/d2ypp2/web-console/out/_next/static/chunks/app/android/page-84550dabda18d658.js +++ b/d2ypp2/web-console/out/_next/static/chunks/app/android/page-69ff6e74a15b80d9.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[357],{4989:function(n,u,e){Promise.resolve().then(e.bind(e,3946))},3946:function(n,u,e){"use strict";e.r(u),e.d(u,{default:function(){return c}});var t=e(7437),r=e(2246);function c(){return(0,t.jsx)(r.d,{})}}},function(n){n.O(0,[500,246,971,117,744],function(){return n(n.s=4989)}),_N_E=n.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[357],{2849:function(n,u,e){Promise.resolve().then(e.bind(e,3946))},3946:function(n,u,e){"use strict";e.r(u),e.d(u,{default:function(){return c}});var t=e(7437),r=e(2246);function c(){return(0,t.jsx)(r.d,{})}}},function(n){n.O(0,[500,246,971,117,744],function(){return n(n.s=2849)}),_N_E=n.O()}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/app/console/page-75d851a154677dbc.js b/d2ypp2/web-console/out/_next/static/chunks/app/console/page-db00fd3a990c6a05.js similarity index 54% rename from d2ypp2/web-console/out/_next/static/chunks/app/console/page-75d851a154677dbc.js rename to d2ypp2/web-console/out/_next/static/chunks/app/console/page-db00fd3a990c6a05.js index a1f4d79..af7c4bb 100644 --- a/d2ypp2/web-console/out/_next/static/chunks/app/console/page-75d851a154677dbc.js +++ b/d2ypp2/web-console/out/_next/static/chunks/app/console/page-db00fd3a990c6a05.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[443],{1873:function(n,u,e){Promise.resolve().then(e.bind(e,6367))},6367:function(n,u,e){"use strict";e.r(u),e.d(u,{default:function(){return c}});var t=e(7437),r=e(2246);function c(){return(0,t.jsx)(r.d,{})}}},function(n){n.O(0,[500,246,971,117,744],function(){return n(n.s=1873)}),_N_E=n.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[443],{2820:function(n,u,e){Promise.resolve().then(e.bind(e,6367))},6367:function(n,u,e){"use strict";e.r(u),e.d(u,{default:function(){return c}});var t=e(7437),r=e(2246);function c(){return(0,t.jsx)(r.d,{})}}},function(n){n.O(0,[500,246,971,117,744],function(){return n(n.s=2820)}),_N_E=n.O()}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/app/layout-809a834918419a40.js b/d2ypp2/web-console/out/_next/static/chunks/app/layout-809a834918419a40.js deleted file mode 100644 index a2088ad..0000000 --- a/d2ypp2/web-console/out/_next/static/chunks/app/layout-809a834918419a40.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{5490:function(e,a,_){Promise.resolve().then(_.t.bind(_,9073,23)),Promise.resolve().then(_.t.bind(_,7455,23)),Promise.resolve().then(_.t.bind(_,7960,23))},7960:function(){},7455:function(e){e.exports={style:{fontFamily:"'__geistMono_c3aa02', '__geistMono_Fallback_c3aa02'"},className:"__className_c3aa02",variable:"__variable_c3aa02"}},9073:function(e){e.exports={style:{fontFamily:"'__geistSans_1e4310', '__geistSans_Fallback_1e4310'"},className:"__className_1e4310",variable:"__variable_1e4310"}}},function(e){e.O(0,[77,971,117,744],function(){return e(e.s=5490)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/app/layout-d9acbcf8f9ab58b1.js b/d2ypp2/web-console/out/_next/static/chunks/app/layout-d9acbcf8f9ab58b1.js new file mode 100644 index 0000000..9875ffc --- /dev/null +++ b/d2ypp2/web-console/out/_next/static/chunks/app/layout-d9acbcf8f9ab58b1.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[185],{8422:function(e,a,_){Promise.resolve().then(_.t.bind(_,1511,23)),Promise.resolve().then(_.t.bind(_,2221,23)),Promise.resolve().then(_.t.bind(_,7960,23))},7960:function(){},2221:function(e){e.exports={style:{fontFamily:"'__geistMono_c3aa02', '__geistMono_Fallback_c3aa02'"},className:"__className_c3aa02",variable:"__variable_c3aa02"}},1511:function(e){e.exports={style:{fontFamily:"'__geistSans_1e4310', '__geistSans_Fallback_1e4310'"},className:"__className_1e4310",variable:"__variable_1e4310"}}},function(e){e.O(0,[776,971,117,744],function(){return e(e.s=8422)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/app/page-4d705a6f49d462b3.js b/d2ypp2/web-console/out/_next/static/chunks/app/page-abd70046db11ff5c.js similarity index 99% rename from d2ypp2/web-console/out/_next/static/chunks/app/page-4d705a6f49d462b3.js rename to d2ypp2/web-console/out/_next/static/chunks/app/page-abd70046db11ff5c.js index b6a1627..4e0be90 100644 --- a/d2ypp2/web-console/out/_next/static/chunks/app/page-4d705a6f49d462b3.js +++ b/d2ypp2/web-console/out/_next/static/chunks/app/page-abd70046db11ff5c.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{4578:function(e,t,n){Promise.resolve().then(n.bind(n,1499))},1499:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return e7}});var s=n(7437),l=n(6247),i=n(7586),r=n(4401),a=n(6137),o=n(4372),c=n(5901),d=n(3388),x=n(3420),u=n(8728),m=n(2023),h=n(407),p=n(6840),b=n(7226),g=n(5929),f=n(7945),v=n(1817),y=n(7168),w=n(4822),N=n(4428),j=n(1723),k=n(2926),z=n(7580),S=n(2489),_=n(2265);function C(e){let{tr:t}=e,l=(0,_.useRef)(null);return(0,_.useEffect)(()=>{let e;if(!l.current)return;let t=!1,s=0;return n.e(689).then(n.bind(n,1448)).then(n=>{if(t||!l.current)return;let i=l.current,r=Math.max(i.clientWidth,280),a=Math.max(i.clientHeight,200),o=new n.Scene,c=new n.PerspectiveCamera(48,r/a,.1,80);c.position.set(0,1.1,7.2);let d=new n.WebGLRenderer({antialias:!0,alpha:!0});d.setPixelRatio(Math.min(window.devicePixelRatio,2)),d.setSize(r,a),d.setClearColor(0,0),i.appendChild(d.domElement);let x=new n.HemisphereLight(16762092,4482815,.85);o.add(x);let u=new n.DirectionalLight(16777215,.9);u.position.set(4,8,6),o.add(u);let m=new n.PointLight(8189439,.6,20);m.position.set(-3,2,-2),o.add(m);let h=new n.Group,p=new n.Mesh(new n.BoxGeometry(3.2,.35,2.2),new n.MeshStandardMaterial({color:2762048,metalness:.15,roughness:.55}));p.position.y=-.85,h.add(p);let b=new n.Mesh(new n.TorusGeometry(.72,.09,12,48),new n.MeshStandardMaterial({color:16724821,emissive:4456465,metalness:.35,roughness:.25}));b.rotation.x=Math.PI/2,b.position.set(-.85,.15,.2),h.add(b);let g=new n.Mesh(new n.ConeGeometry(.35,.5,3),new n.MeshStandardMaterial({color:16777215,emissive:2236962,metalness:.2,roughness:.3}));g.rotation.z=-Math.PI/2,g.rotation.y=Math.PI,g.position.set(-.55,.18,.2),h.add(g);let f=new n.Mesh(new n.CylinderGeometry(.22,.28,.95,20),new n.MeshStandardMaterial({color:2487534,emissive:340024,metalness:.25,roughness:.35}));f.position.set(1.05,.35,-.15),f.rotation.z=.12,h.add(f);let v=new n.Mesh(new n.SphereGeometry(.26,16,16),new n.MeshStandardMaterial({color:16657493,emissive:2229520,metalness:.2,roughness:.4}));v.position.set(1.05,.92,-.15),h.add(v);let y=new n.BufferGeometry,w=new Float32Array(360);for(let e=0;e<120;e++)w[3*e]=(Math.random()-.5)*14,w[3*e+1]=(Math.random()-.3)*8,w[3*e+2]=(Math.random()-.5)*8-2;y.setAttribute("position",new n.BufferAttribute(w,3));let N=new n.Points(y,new n.PointsMaterial({color:16777215,size:.06,transparent:!0,opacity:.7}));o.add(N),o.add(h);let j=performance.now(),k=()=>{if(t)return;s=requestAnimationFrame(k);let e=(performance.now()-j)/1e3;h.rotation.y=.25*Math.sin(.35*e)+.12*e,h.position.y=.06*Math.sin(.9*e),b.rotation.z=.4*e,N.rotation.y=.02*e,d.render(o,c)};k();let z=new ResizeObserver(()=>{if(!l.current||t)return;let e=Math.max(l.current.clientWidth,280),n=Math.max(l.current.clientHeight,200);c.aspect=e/n,c.updateProjectionMatrix(),d.setSize(e,n)});z.observe(i),e=()=>{cancelAnimationFrame(s),z.disconnect(),d.dispose(),y.dispose(),d.domElement.parentNode===i&&i.removeChild(d.domElement)}}),()=>{t=!0,cancelAnimationFrame(s),null==e||e()}},[]),(0,s.jsxs)("div",{className:"flex h-full min-h-[14rem] flex-col",children:[(0,s.jsx)("p",{className:"mb-2 px-1 text-[10px] font-medium uppercase tracking-wider text-fuchsia-200/80",children:t("直播工作室 \xb7 3D","Live studio \xb7 3D")}),(0,s.jsx)("div",{ref:l,className:"relative min-h-[12rem] flex-1 overflow-hidden rounded-xl bg-gradient-to-b from-fuchsia-950/40 to-cyan-950/20 ring-1 ring-white/10"})]})}var R=n(9170),P=n(2246),L=n(4286),M=n(4794),T=n(221),U=n(8867),E=n(8124),I=n(2101),D=n(3651),A=n(9985),Z=n(6362),O=n(3468),H=n(6443),B=n(5287),K=n(3276),F=n(9227),W=n(257),Y=n(1387);class J{reset(){if(this.buf=new Uint8Array(0),this.sps=null,this.pps=null,this.configured=!1,this.configuring=!1,this.ts=0,this.decoder){try{this.decoder.close()}catch(e){}this.decoder=null}}push(e){let t=new Uint8Array(e.byteLength);t.set(new Uint8Array(e)),this.buf=function(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}(this.buf,t),this.drainAvcc()}drainAvcc(){let e=this.buf,t=0;for(;t+4<=e.length;){var n;let s=e[n=t]<<24|e[n+1]<<16|e[n+2]<<8|e[n+3];if(s<=0||s>6291456){this.buf=new Uint8Array(e.subarray(t+1)),t=0;continue}if(t+4+s>e.length)break;let l=e.subarray(t+4,t+4+s);t+=4+s,this.handleNal(l)}t>0&&(this.buf=new Uint8Array(e.subarray(t)))}handleNal(e){if(e.length<2)return;let t=31&e[0];if(7===t?this.sps=new Uint8Array(e):8===t&&(this.pps=new Uint8Array(e)),this.sps&&this.pps&&!this.configured&&!this.configuring&&this.configure(),!this.configured||!this.decoder||1!==t&&5!==t&&7!==t&&8!==t||7===t||8===t)return;let n=new Uint8Array(4+e.length);new DataView(n.buffer).setUint32(0,e.length,!1),n.set(e,4);try{let e=new EncodedVideoChunk({type:5===t?"key":"delta",timestamp:this.ts,data:n});this.ts+=33333,this.decoder.decode(e)}catch(e){this.onDecodeError(e.message||String(e))}}async configure(){if(this.sps&&this.pps&&!this.configured&&!this.configuring){this.configuring=!0;try{let e=function(e,t){let n=e.subarray(1),s=t.subarray(1),l=new Uint8Array(11+n.length+3+s.length),i=0;return l[i++]=1,l[i++]=e[1],l[i++]=e[2],l[i++]=e[3],l[i++]=255,l[i++]=225,l[i++]=n.length>>8&255,l[i++]=255&n.length,l.set(n,i),i+=n.length,l[i++]=1,l[i++]=s.length>>8&255,l[i++]=255&s.length,l.set(s,i),l}(this.sps,this.pps),t=function(e){let t=e=>e.toString(16).padStart(2,"0").toUpperCase();return"avc1.".concat(t(e[1])).concat(t(e[2])).concat(t(e[3]))}(this.sps),n=new VideoDecoder({output:e=>{var t;let n=this.canvas.getContext("2d");if(!n){e.close();return}(this.canvas.width!==e.displayWidth||this.canvas.height!==e.displayHeight)&&(this.canvas.width=e.displayWidth,this.canvas.height=e.displayHeight),n.drawImage(e,0,0),e.close(),null===(t=this.onFrame)||void 0===t||t.call(this)},error:e=>this.onDecodeError(String(e.message||e))});await n.configure({codec:t,description:e,optimizeForLatency:!0}),this.decoder=n,this.configured=!0}catch(e){this.onDecodeError(e.message||String(e))}finally{this.configuring=!1}}}constructor(e,t,n){this.canvas=e,this.onDecodeError=t,this.onFrame=n,this.buf=new Uint8Array(0),this.decoder=null,this.configured=!1,this.configuring=!1,this.ts=0,this.sps=null,this.pps=null}}function G(){return"undefined"!=typeof VideoDecoder&&"undefined"!=typeof VideoFrame}let V="live-hub-adb-bookmarks-v1";function q(e,t,n){let s,l,i,r;let a=e.getBoundingClientRect(),o=e.width,c=e.height;if(!o||!c)return null;let d=a.width/a.height,x=o/c;x>d?(s=a.width,l=a.width/x,i=0,r=(a.height-l)/2):(l=a.height,s=a.height*x,i=(a.width-s)/2,r=0);let u=t-a.left-i,m=n-a.top-r;return u<0||m<0||u>s||m>l?null:{x:Math.max(0,Math.min(o-1,Math.round(u/s*o))),y:Math.max(0,Math.min(c-1,Math.round(m/l*c)))}}function X(e,t,n){let s,l,i,r;let a=e.getBoundingClientRect(),o=e.naturalWidth,c=e.naturalHeight;if(!o||!c)return null;let d=a.width/a.height,x=o/c;x>d?(s=a.width,l=a.width/x,i=0,r=(a.height-l)/2):(l=a.height,s=a.height*x,i=(a.width-s)/2,r=0);let u=t-a.left-i,m=n-a.top-r;return u<0||m<0||u>s||m>l?null:{x:Math.max(0,Math.min(o-1,Math.round(u/s*o))),y:Math.max(0,Math.min(c-1,Math.round(m/l*c)))}}let $=[0,280,450,700,1100];function Q(e){switch(e){case"usb":return{Icon:I.Z,zh:"USB",en:"USB",cls:"bg-amber-500/20 text-amber-100 ring-amber-500/35"};case"tcp":return{Icon:k.Z,zh:"网络",en:"TCP",cls:"bg-cyan-500/20 text-cyan-100 ring-cyan-500/35"};case"emulator":return{Icon:D.Z,zh:"模拟器",en:"Emu",cls:"bg-fuchsia-500/20 text-fuchsia-100 ring-fuchsia-500/35"};default:return{Icon:d.Z,zh:"?",en:"?",cls:"bg-zinc-600/30 text-zinc-400"}}}let ee="https://github.com/Genymobile/scrcpy",et="https://github.com/viarotel-org/escrcpy";function en(e,t){let n=t.startsWith("/")?t:"/".concat(t),s=(e||"").trim().replace(/\/$/,"");return s?"".concat(s).concat(n):n}function es(e){var t;let{t:n,apiBase:l,fetchJson:i,serial:r,devices:a,setSerial:o,adbAvailable:c,lock:x,overview:u,onAndroidAction:h,notify:p,onRefreshDevices:b}=e,[g,f]=(0,_.useState)(0),[v,w]=(0,_.useState)(450),[N,j]=(0,_.useState)(!1),[k,z]=(0,_.useState)(null),[S,C]=(0,_.useState)(null),[R,P]=(0,_.useState)(!0),[L,M]=(0,_.useState)(""),[T,U]=(0,_.useState)(""),[E,I]=(0,_.useState)("37777"),[D,es]=(0,_.useState)(""),[el,ei]=(0,_.useState)(!1),[er,ea]=(0,_.useState)([]),[eo,ec]=(0,_.useState)(!1),[ed,ex]=(0,_.useState)(null),[eu,em]=(0,_.useState)(!1),[eh,ep]=(0,_.useState)(null),[eb,eg]=(0,_.useState)(null),[ef,ev]=(0,_.useState)(!0),ey=(0,_.useRef)(null),ew=(0,_.useRef)(null),eN=(0,_.useRef)(null),ej=(0,_.useRef)(null),ek=(0,_.useRef)(null),ez=(0,_.useRef)(null),eS=(0,_.useRef)(0),e_=(0,_.useRef)(!1),eC=(0,_.useRef)(null),eR=(0,_.useRef)(!1),eP=null===(t=a.find(e=>e.serial===r))||void 0===t?void 0:t.transport,eL=v>0,eM=r?"".concat(en(l,"/android/screenshot"),"?serial=").concat(encodeURIComponent(r),"&ts=").concat(g).concat(eL?"&fast=1":""):"",eT=(0,_.useCallback)(()=>{f(e=>e+1)},[]),eU=(0,_.useCallback)(()=>{null!=eC.current&&(window.clearTimeout(eC.current),eC.current=null)},[]);(0,_.useEffect)(()=>{let e=()=>ev("visible"===document.visibilityState);return e(),document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[]),(0,_.useEffect)(()=>{try{let e=window.localStorage.getItem(V);if(e){let t=JSON.parse(e);Array.isArray(t)&&ea(t.map(String).filter(Boolean).slice(0,24))}}catch(e){}},[]);let eE=e=>{let t=e.trim();if(!t)return;let s=[t,...er.filter(e=>e!==t)].slice(0,16);ea(s);try{window.localStorage.setItem(V,JSON.stringify(s))}catch(e){}p(n("已保存快捷地址","Saved quick address"))};(0,_.useEffect)(()=>{if(!r||!c){C(null);return}let e=!1;return(async()=>{try{let t=await (0,Y.N)("".concat(en(l,"/android/display_metrics"),"?serial=").concat(encodeURIComponent(r)));if(e)return;"number"==typeof t.width&&"number"==typeof t.height&&C({width:t.width,height:t.height})}catch(e){}})(),()=>{e=!0}},[l,c,r]),(0,_.useEffect)(()=>{if(!c||!r||v<=0||eo||!ef)return;let e=window.setInterval(()=>f(e=>e+1),v);return()=>clearInterval(e)},[c,v,ef,r,eo]),(0,_.useEffect)(()=>{ef&&c&&r&&!eo&&eT()},[c,eT,ef,r,eo]),(0,_.useEffect)(()=>{if(!c){eg(null);return}let e=!1;return(async()=>{try{let t=await (0,Y.N)(en(l,"/android/scrcpy/info"));e||eg(t)}catch(e){}})(),()=>{e=!0}},[l,c]),(0,_.useEffect)(()=>{eo||ep(null)},[eo]),(0,_.useEffect)(()=>{ex(null),e_.current=!1},[r]),(0,_.useEffect)(()=>{let e=a.find(e=>e.serial===r),t=!!(r&&ed===r);if(c&&r&&(null==e?void 0:e.state)==="device"&&(null==eb?void 0:eb.server_jar)&&G()&&!t){ec(!0),w(0);return}if(t||!r||!c||eb&&!eb.server_jar||!G()||e&&"device"!==e.state){ec(!1);return}},[r,a,c,eb,ed]),(0,_.useEffect)(()=>{if(!eo||!r||!c){var e,t;eU(),e_.current=!0,eR.current=!1,null===(e=ej.current)||void 0===e||e.close(),ej.current=null,null===(t=ek.current)||void 0===t||t.reset(),ek.current=null,em(!1);return}if(!G()){ep(n("当前浏览器不支持 WebCodecs H.264","WebCodecs H.264 not supported in this browser")),ec(!1);return}let s=eN.current;if(!s)return;let i=e=>{var t;eU(),e_.current=!0,null===(t=ej.current)||void 0===t||t.close(),ep(e),ec(!1),w(450),ex(r),window.setTimeout(()=>eT(),120)},a=new J(s,e=>i("".concat(n("实时画面解码失败,已切回截图模式","Live stream decode failed, using screenshot mode"),": ").concat(e)),()=>{eR.current=!0,eU()});ek.current=a,e_.current=!1,eR.current=!1;let o=new WebSocket(function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1920,s=(function(e){let t=(e||"").trim();if(t)try{let e=new URL(t,window.location.href),n="https:"===e.protocol?"wss:":"ws:";return"".concat(n,"//").concat(e.host)}catch(e){}let n=void 0!==W&&W.env.NEXT_PUBLIC_API_URL?String(W.env.NEXT_PUBLIC_API_URL).trim():"";if(n)try{let e=new URL(n,window.location.href),t="https:"===e.protocol?"wss:":"ws:";return"".concat(t,"//").concat(e.host)}catch(e){}let s=window.location.port;if("3000"===s||"3001"===s){let e=window.location.hostname||"127.0.0.1";return"ws://".concat(e,":").concat("8001")}let{protocol:l,host:i}=window.location;return"".concat("https:"===l?"wss:":"ws:","//").concat(i)})(e).replace(/\/$/,""),l=new URLSearchParams({serial:t,max_size:String(n)});return"".concat(s,"/android/scrcpy/ws?").concat(l.toString())}(l,r));return ej.current=o,o.binaryType="arraybuffer",o.onopen=()=>{em(!0),ep(null),eU(),eC.current=window.setTimeout(()=>{eR.current||i(n("实时画面无首帧,已切回截图模式","No first live frame, using screenshot mode"))},5200)},o.onmessage=e=>{var t;if("string"==typeof e.data){try{let t=JSON.parse(e.data);t.error&&ep(t.error)}catch(e){}return}null===(t=ek.current)||void 0===t||t.push(e.data)},o.onerror=()=>{ep(n("WebSocket 异常","WebSocket error"))},o.onclose=()=>{var e;em(!1),null===(e=ek.current)||void 0===e||e.reset(),ek.current=null,eU(),eo&&!e_.current&&i(n("实时画面连接失败,已切回截图模式","Live stream failed, using screenshot mode"))},()=>{eU(),e_.current=!0,eR.current=!1,o.close(),ej.current=null,a.reset(),ek.current===a&&(ek.current=null)}},[eo,r,c,l,eT,eU,n]),(0,_.useEffect)(()=>{r&&c&&(eS.current=0,f(e=>e+1))},[r,c]);let eI=async()=>{let e=L.trim();if(!e){p(n("填写 host:port","Enter host:port"));return}ei(!0);try{let t=await i("/android/connect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({address:e})});p(t.message||(t.ok?"OK":n("连接结果见日志","See message"))),b(),eT()}catch(e){p(e.message)}finally{ei(!1)}},eD=async e=>{ei(!0);try{let t=await i("/android/disconnect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({address:e})});p(t.message||"OK"),b()}catch(e){p(e.message)}finally{ei(!1)}},eA=async()=>{let e=T.trim(),t=parseInt(E,10)||37777,s=D.trim();if(!e||!s){p(n("填写配对 IP 与码","Host + code required"));return}ei(!0);try{let l=await i("/android/pair",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({host:e,port:t,code:s})});p(l.message||(l.ok?n("配对成功后再点连接","Paired — now Connect"):"pair"))}catch(e){p(e.message)}finally{ei(!1)}},eZ=async e=>{if(!R||x||!c||!r)return;let t=ew.current;if(!t)return;let s=X(t,e.clientX,e.clientY);if(!s)return;let l=Date.now(),i=ey.current;i&&l-i.t<320&&28>Math.abs(i.x-s.x)&&28>Math.abs(i.y-s.y)?(ey.current=null,await h("double_tap",{x:s.x,y:s.y}),p(n("双击","Double tap"))):(ey.current={t:l,x:s.x,y:s.y},await h("tap",{x:s.x,y:s.y})),eT()},eO=async e=>{if(e.preventDefault(),x||!c||!r)return;let t=ew.current;if(!t)return;let s=X(t,e.clientX,e.clientY);s&&(await h("long_press",{x:s.x,y:s.y,duration:720}),p(n("长按","Long press")),eT())},eH=async e=>{if(!R||x||!c||!r)return;let t=eN.current;if(!t)return;let s=q(t,e.clientX,e.clientY);if(!s)return;let l=Date.now(),i=ey.current;i&&l-i.t<320&&28>Math.abs(i.x-s.x)&&28>Math.abs(i.y-s.y)?(ey.current=null,await h("double_tap",{x:s.x,y:s.y}),p(n("双击","Double tap"))):(ey.current={t:l,x:s.x,y:s.y},await h("tap",{x:s.x,y:s.y})),eo||eT()},eB=async e=>{if(e.preventDefault(),x||!c||!r)return;let t=eN.current;if(!t)return;let s=q(t,e.clientX,e.clientY);s&&(await h("long_press",{x:s.x,y:s.y,duration:720}),p(n("长按","Long press")),eo||eT())};if(!c)return(0,s.jsx)("div",{className:"rounded-2xl border border-amber-500/25 bg-amber-500/[0.06] p-6 text-center text-sm text-amber-200/90",children:n("宿主机未安装 adb,无法使用 Live 控制台。","adb is required for the Live console.")});let eK=Q(eP),eF=eK.Icon;return(0,s.jsxs)("div",{className:"space-y-5",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-sky-500/20 bg-gradient-to-br from-sky-500/[0.08] via-zinc-950/80 to-zinc-900/90 p-4 ring-1 ring-white/[0.05]",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-white/[0.06] pb-3",children:[(0,s.jsx)(A.Z,{className:"h-4 w-4 text-sky-400"}),(0,s.jsx)("h4",{className:"text-sm font-semibold text-white",children:n("链路管理","Link manager")}),(0,s.jsx)("span",{className:"text-[10px] text-zinc-500",children:n("USB / Redroid :5555 / 无线调试(先配对再连接)","USB \xb7 Redroid :5555 \xb7 wireless (pair then connect)")})]}),(0,s.jsxs)("div",{className:"mt-3 grid gap-3 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"space-y-2 rounded-xl border border-white/[0.06] bg-black/35 p-3",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"adb connect"}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("input",{className:"min-w-[12rem] flex-1 rounded-lg border border-white/10 bg-black/50 px-3 py-2 font-mono text-xs text-zinc-200",placeholder:"192.168.1.10:5555",value:L,onChange:e=>M(e.target.value),onKeyDown:e=>"Enter"===e.key&&void eI()}),(0,s.jsx)("button",{type:"button",disabled:el||x,onClick:()=>void eI(),className:"rounded-lg bg-sky-500/25 px-3 py-2 text-xs font-semibold text-sky-100 ring-1 ring-sky-400/40",children:el?"…":"Connect"}),(0,s.jsx)("button",{type:"button",disabled:el||x||!L.trim(),onClick:()=>eE(L),className:"rounded-lg border border-white/10 px-3 py-2 text-xs text-zinc-400 hover:text-zinc-200",children:n("存书签","Pin")})]}),er.length?(0,s.jsx)("div",{className:"flex flex-wrap gap-1.5 pt-1",children:er.map(e=>(0,s.jsx)("button",{type:"button",className:"rounded-md bg-white/[0.06] px-2 py-0.5 font-mono text-[10px] text-zinc-400 hover:bg-white/10",onClick:()=>M(e),children:e},e))}):null,(0,s.jsxs)("div",{className:"flex flex-wrap gap-2 pt-2",children:[(0,s.jsx)("button",{type:"button",disabled:el||x||!r,onClick:()=>void eD(r),className:"rounded-lg border border-rose-500/30 bg-rose-500/10 px-2.5 py-1.5 text-[10px] text-rose-200",children:n("断开当前 TCP","Disconnect current")}),(0,s.jsx)("button",{type:"button",disabled:el||x,onClick:()=>void eD(""),className:"rounded-lg border border-white/10 px-2.5 py-1.5 text-[10px] text-zinc-500 hover:text-zinc-300",children:n("断开全部 TCP","Disconnect all TCP")}),(0,s.jsxs)("button",{type:"button",disabled:el||x,onClick:()=>{b(),eT(),p(n("已刷新设备列表","Devices refreshed"))},className:"inline-flex items-center gap-1 rounded-lg border border-white/10 px-2.5 py-1.5 text-[10px] text-zinc-400",children:[(0,s.jsx)(y.Z,{className:"h-3 w-3"}),"ADB list"]})]})]}),(0,s.jsxs)("div",{className:"space-y-2 rounded-xl border border-white/[0.06] bg-black/35 p-3",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"adb pair(无线调试)"}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("input",{className:"w-32 rounded-lg border border-white/10 bg-black/50 px-2 py-1.5 font-mono text-xs",placeholder:"IP",value:T,onChange:e=>U(e.target.value)}),(0,s.jsx)("input",{className:"w-20 rounded-lg border border-white/10 bg-black/50 px-2 py-1.5 font-mono text-xs",placeholder:"port",value:E,onChange:e=>I(e.target.value)}),(0,s.jsx)("input",{className:"min-w-[6rem] flex-1 rounded-lg border border-white/10 bg-black/50 px-2 py-1.5 font-mono text-xs tracking-widest",placeholder:"123456",value:D,onChange:e=>es(e.target.value)}),(0,s.jsx)("button",{type:"button",disabled:el||x,onClick:()=>void eA(),className:"rounded-lg bg-violet-500/20 px-3 py-1.5 text-xs text-violet-100 ring-1 ring-violet-400/35",children:"Pair"})]}),(0,s.jsx)("p",{className:"text-[10px] leading-relaxed text-zinc-600",children:n("手机上「无线调试」会显示配对端口与 6 位码;配对成功后用上方 connect 连接 adb 显示的 IP:5555。","Use the pairing port + 6-digit code from Wireless debugging; then connect to the listed adb IP:5555.")})]})]})]}),(0,s.jsxs)("div",{className:"relative overflow-hidden rounded-3xl border border-emerald-500/25 bg-gradient-to-br from-emerald-500/[0.12] via-zinc-950/90 to-violet-500/[0.08] p-1 shadow-2xl shadow-emerald-900/20 ring-1 ring-white/[0.06]",children:[(0,s.jsx)("div",{className:"pointer-events-none absolute -right-20 -top-20 h-56 w-56 rounded-full bg-emerald-500/10 blur-3xl","aria-hidden":!0}),(0,s.jsxs)("div",{className:"relative rounded-[1.35rem] border border-white/[0.06] bg-zinc-950/80 p-4 backdrop-blur-sm",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between",children:[(0,s.jsxs)("div",{className:"flex items-start gap-3",children:[(0,s.jsx)("div",{className:"flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-gradient-to-br from-emerald-400/30 to-violet-500/25 ring-1 ring-white/10",children:(0,s.jsx)(m.Z,{className:"h-6 w-6 text-emerald-200"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold tracking-tight text-white",children:n("无人直播系统 \xb7 ADB 云控台","Unmanned Live System \xb7 ADB farm console")}),(0,s.jsxs)("p",{className:"mt-1 max-w-xl text-[11px] leading-relaxed text-zinc-500",children:[n("统一适配 USB / Redroid / 无线 adb:已授权设备默认走官方 scrcpy-server 的 WebSocket H.264 真流(与桌面 ","USB / Redroid / wireless adb: authorized devices default to official scrcpy-server WebSocket H.264 (same stack as "),(0,s.jsx)("a",{href:et,target:"_blank",rel:"noreferrer",className:"text-emerald-300/90 underline-offset-2 hover:underline",children:"escrcpy"}),n(" / "," / "),(0,s.jsx)("a",{href:ee,target:"_blank",rel:"noreferrer",className:"text-emerald-300/90 underline-offset-2 hover:underline",children:"scrcpy"}),n(");无 jar 或关闭真流时用截图。","); PNG screenshot when jar missing or stream off.")]})]})]}),(0,s.jsxs)("div",{className:"flex shrink-0 flex-col gap-1.5 self-start sm:flex-row",children:[(0,s.jsxs)("a",{href:et,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 rounded-xl border border-white/10 bg-white/[0.04] px-3 py-2 text-[11px] font-medium text-zinc-300 hover:bg-white/[0.07]",children:["escrcpy",(0,s.jsx)(Z.Z,{className:"h-3.5 w-3.5 opacity-70"})]}),(0,s.jsxs)("a",{href:ee,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 rounded-xl border border-white/10 bg-white/[0.04] px-3 py-2 text-[11px] font-medium text-zinc-300 hover:bg-white/[0.07]",children:["scrcpy",(0,s.jsx)(Z.Z,{className:"h-3.5 w-3.5 opacity-70"})]})]})]}),a.length>0?(0,s.jsxs)("div",{className:"mt-5",children:[(0,s.jsxs)("p",{className:"mb-2 flex items-center gap-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:[(0,s.jsx)(O.Z,{className:"h-3.5 w-3.5"}),n("设备矩阵","Device matrix")]}),(0,s.jsx)("div",{className:"flex gap-2 overflow-x-auto pb-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",children:a.map(e=>{let t="device"===e.state,l=r===e.serial,i=Q(e.transport),a=i.Icon;return(0,s.jsxs)("button",{type:"button",onClick:()=>o(e.serial),className:"flex min-w-[9rem] flex-col rounded-xl border px-3 py-2 text-left transition ".concat(l?"border-emerald-500/50 bg-emerald-500/15 ring-1 ring-emerald-400/30":"border-white/10 bg-black/30 hover:border-white/20"),children:[(0,s.jsxs)("span",{className:"flex items-center gap-1.5 text-xs font-medium text-zinc-200",children:[(0,s.jsx)(d.Z,{className:"h-3.5 w-3.5 text-emerald-400/80"}),(0,s.jsx)("span",{className:"truncate",children:e.model||e.serial.slice(0,10)})]}),(0,s.jsx)("span",{className:"mt-0.5 truncate font-mono text-[9px] text-zinc-600",children:e.serial}),(0,s.jsxs)("div",{className:"mt-1 flex flex-wrap gap-1",children:[(0,s.jsxs)("span",{className:"inline-flex items-center gap-0.5 rounded-md px-1.5 py-0.5 text-[9px] font-semibold ring-1 ".concat(i.cls),children:[(0,s.jsx)(a,{className:"h-2.5 w-2.5"}),n(i.zh,i.en)]}),(0,s.jsx)("span",{className:"rounded-md px-1.5 py-0.5 text-[9px] font-semibold ".concat(t?"bg-emerald-500/20 text-emerald-200":"bg-zinc-600/30 text-zinc-500"),children:e.state})]})]},e.serial)})})]}):null,(0,s.jsxs)("div",{className:"mt-6 grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("div",{className:"xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-white/[0.06] pb-3",children:[(0,s.jsx)("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:n("刷新间隔","Interval")}),$.map(e=>(0,s.jsx)("button",{type:"button",onClick:()=>w(e),className:"rounded-lg px-2.5 py-1 text-[10px] font-semibold transition ".concat(v===e?"bg-violet-500/25 text-violet-100 ring-1 ring-violet-400/35":"bg-black/30 text-zinc-500 hover:text-zinc-300"),children:0===e?n("手动","Manual"):"".concat(e,"ms")},e)),(0,s.jsxs)("span",{className:"ml-1 inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-[9px] font-medium ring-1 ".concat(eK.cls),children:[(0,s.jsx)(eF,{className:"h-3 w-3"}),"tcp"===eP?n("建议 ≥450ms","Suggest ≥450ms"):n("可试 280ms","Try 280ms")]}),(0,s.jsxs)("button",{type:"button",disabled:x,onClick:()=>void eT(),className:"ml-auto inline-flex items-center gap-1 rounded-lg border border-white/10 bg-white/[0.05] px-2.5 py-1 text-[10px] text-zinc-300 hover:bg-white/[0.08]",children:[(0,s.jsx)(y.Z,{className:"h-3 w-3 ".concat(N?"animate-spin":"")}),n("下一帧","Next frame")]}),(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>void h("wake"),className:"rounded-lg bg-amber-500/20 px-2.5 py-1 text-[10px] font-semibold text-amber-100 ring-1 ring-amber-500/30",children:"Wake"}),(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-1.5 text-[10px] text-zinc-400",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/50",checked:R,onChange:e=>P(e.target.checked)}),(0,s.jsx)(H.Z,{className:"h-3 w-3"}),n("点按穿透","Tap-through")]}),(0,s.jsxs)("button",{type:"button",disabled:x||!r||!(null==eb?void 0:eb.server_jar),title:eb&&!eb.server_jar&&eb.hint_zh?eb.hint_zh:n("官方 scrcpy-server + WebSocket H.264","Official scrcpy-server + WebSocket H.264"),onClick:()=>{ec(e=>{let t=!e;return t?(ex(null),p(n("已开启实时画面(H.264 WebSocket)","Live H.264 WebSocket stream on"))):(r&&ex(r),p(n("已关闭实时画面(将使用截图)","Live stream off — screenshot mode"))),t})},className:"inline-flex items-center gap-1 rounded-lg border px-2.5 py-1 text-[10px] font-semibold transition ".concat(eo?"border-cyan-400/50 bg-cyan-500/20 text-cyan-100 ring-1 ring-cyan-400/35":"border-white/10 bg-black/30 text-zinc-400 hover:text-zinc-200"),children:[(0,s.jsx)(B.Z,{className:"h-3 w-3"}),eo?n("关闭真流","Stop WS"):n("实时画面","Live H.264")]})]}),eb&&!eb.server_jar?(0,s.jsxs)("p",{className:"mt-2 text-[10px] text-amber-200/80",children:[n("未检测到 scrcpy-server:启动时会自动拉取;内网可在 runtime.env 配置 SCRCPY_SERVER_DOWNLOAD_URL(支持 {tag})。","scrcpy-server missing: auto-fetched on startup; set SCRCPY_SERVER_DOWNLOAD_URL ({tag}) for mirrors."),eb.server_version?" (".concat(n("期望版本","version")," ").concat(eb.server_version,")"):null]}):null,(0,s.jsx)("p",{className:"mt-2 text-[10px] text-zinc-600",children:n("快捷键(镜像区聚焦时):H Home \xb7 B Back \xb7 R 多任务 \xb7 W 唤醒 \xb7 M 菜单","Hotkeys (mirror focused): H Home \xb7 B Back \xb7 R Recents \xb7 W Wake \xb7 M Menu")}),(0,s.jsxs)("div",{className:"relative mx-auto mt-4 max-h-[min(78vh,720px)] min-h-[280px]",children:[r?(0,s.jsxs)("div",{ref:ez,tabIndex:0,onKeyDown:e=>{if(!r||x)return;let t=e.target.tagName;if("INPUT"===t||"TEXTAREA"===t||"SELECT"===t)return;let n={h:["key",{keycode:"3"}],b:["key",{keycode:"4"}],r:["key",{keycode:"187"}],w:["wake",void 0],m:["key",{keycode:"82"}]}[e.key.toLowerCase()];n&&(e.preventDefault(),(async()=>{await h(n[0],n[1]),eo||eT()})())},className:"relative flex justify-center outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/50",children:[(0,s.jsxs)("div",{className:"relative rounded-[2rem] border-[10px] border-zinc-800 bg-black shadow-inner shadow-black/80 ring-1 ring-white/10",style:{maxHeight:"min(72vh, 680px)"},children:[(0,s.jsx)("div",{className:"absolute left-1/2 top-0 z-10 h-5 w-24 -translate-x-1/2 rounded-b-xl bg-black/80"}),eo?(0,s.jsx)("canvas",{ref:eN,className:"max-h-[min(72vh,680px)] w-auto max-w-full rounded-[1.35rem] object-contain ".concat(R?"cursor-crosshair":"cursor-default"),draggable:!1,onClick:eH,onContextMenu:eB}):(0,s.jsx)("img",{ref:ew,src:eM||void 0,alt:"device",className:"max-h-[min(72vh,680px)] w-auto max-w-full rounded-[1.35rem] object-contain ".concat(R?"cursor-crosshair":"cursor-default"),draggable:!1,onLoadStart:()=>{j(!0)},onLoad:()=>{j(!1),eS.current=0,z(null)},onError:()=>{j(!1),eS.current+=1,eS.current<=3?(z(null),window.setTimeout(()=>eT(),380+200*eS.current)):z(n("截图连续失败:检查 USB 授权 / 无线是否断开 / Redroid 端口","Screenshot failed repeatedly"))},onClick:eZ,onContextMenu:eO})]}),eu?(0,s.jsxs)("div",{className:"pointer-events-none absolute bottom-3 right-3 flex items-center gap-1 rounded-full bg-cyan-500/90 px-2 py-0.5 text-[9px] font-bold text-cyan-950 shadow-lg",children:[(0,s.jsx)(B.Z,{className:"h-3 w-3"}),"SCRCPY\xb7WS"]}):v>0&&!eo?(0,s.jsxs)("div",{className:"pointer-events-none absolute bottom-3 right-3 flex items-center gap-1 rounded-full bg-emerald-500/90 px-2 py-0.5 text-[9px] font-bold text-emerald-950 shadow-lg",children:[(0,s.jsx)(K.Z,{className:"h-3 w-3"}),"LIVE"]}):eo?null:(0,s.jsxs)("div",{className:"pointer-events-none absolute bottom-3 right-3 flex items-center gap-1 rounded-full bg-zinc-700/90 px-2 py-0.5 text-[9px] font-bold text-zinc-200",children:[(0,s.jsx)(F.Z,{className:"h-3 w-3"}),n("单帧","Still")]})]}):(0,s.jsx)("p",{className:"py-16 text-center text-sm text-zinc-600",children:n("请选择或连接设备","Pick or connect a device")}),eh?(0,s.jsx)("p",{className:"mt-3 text-center text-xs text-rose-300",children:eh}):null,k&&!eo?(0,s.jsx)("p",{className:"mt-3 text-center text-xs text-rose-300",children:k}):null,(0,s.jsx)("p",{className:"mt-3 text-center text-[10px] text-zinc-600",children:n("左键单击 / 双击 \xb7 右键长按 \xb7 坐标对齐 PNG 像素","Left tap/double \xb7 right long-press \xb7 PNG pixel coords")})]})]}),(0,s.jsxs)("div",{className:"space-y-4 xl:col-span-4",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-black/40 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:n("遥测","Telemetry")}),u?(0,s.jsxs)("dl",{className:"mt-3 space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"device"}),(0,s.jsxs)("dd",{className:"text-right text-zinc-200",children:[u.brand," ",u.model]})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"Android"}),(0,s.jsxs)("dd",{className:"text-zinc-300",children:[u.android_version," (API ",u.sdk,")"]})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"wm size"}),(0,s.jsx)("dd",{className:"text-cyan-300/90",children:S?"".concat(S.width,"\xd7").concat(S.height):u.resolution||"—"})]}),(0,s.jsx)("div",{className:"whitespace-pre-wrap text-[10px] leading-snug text-zinc-500",children:u.battery})]}):(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-600",children:n("在上方点「刷新设备信息」","Use Refresh device info above")})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/20 bg-gradient-to-b from-violet-500/[0.08] to-black/40 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-violet-300/80",children:n("导航坞","Nav dock")}),(0,s.jsx)("div",{className:"mt-3 grid grid-cols-3 gap-2",children:[["3","Home"],["4","Back"],["187","Recents"]].map(e=>{let[t,n]=e;return(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>{h("key",{keycode:t}),eT()},className:"rounded-xl border border-white/10 bg-white/[0.06] py-3 text-xs font-semibold text-zinc-200 hover:bg-white/[0.1]",children:n},t)})}),(0,s.jsxs)("div",{className:"mt-2 grid grid-cols-2 gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>{h("key",{keycode:"24"}),eT()},className:"rounded-xl border border-white/10 bg-black/30 py-2 text-[11px] text-zinc-300",children:"Vol+"}),(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>{h("key",{keycode:"25"}),eT()},className:"rounded-xl border border-white/10 bg-black/30 py-2 text-[11px] text-zinc-300",children:"Vol−"})]})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-cyan-500/[0.05] p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-cyan-300/80",children:n("手势","Gestures")}),(0,s.jsx)("div",{className:"mt-2 grid grid-cols-2 gap-2",children:["up","down","left","right"].map(e=>(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>{h("swipe",{direction:e}),eT()},className:"rounded-lg border border-white/10 bg-black/30 py-2 font-mono text-[10px] uppercase text-zinc-300",children:e},e))})]})]})]})]})]})]})}let el=[{label:"getprop",cmd:"getprop ro.build.version.release"},{label:"top pkg",cmd:"dumpsys activity activities | grep -E 'mResumedActivity' | tail -n 1"},{label:"usb",cmd:"dumpsys usb | head -n 60"},{label:"surface",cmd:"dumpsys SurfaceFlinger | head -n 40"}];function ei(e,t,n){return e?(0,s.jsx)("span",{className:"rounded bg-emerald-500/15 px-2 py-0.5 text-[10px] text-emerald-200",children:t}):(0,s.jsx)("span",{className:"rounded bg-zinc-500/15 px-2 py-0.5 text-[10px] text-zinc-400",children:n})}function er(e){var t,n,l,i,r,a,o,c,d,x,u,m,h,p,b;let{t:g,notify:f,fetchJson:y,apiBase:w,busy:N,androidSerial:j,setAndroidSerial:k,devices:z,adbAvailable:S,apkPath:C,setApkPath:R,onAndroidAction:P,onCopy:I,onRefreshDevices:D}=e,[A,Z]=(0,_.useState)(null),[O,H]=(0,_.useState)(null),[B,K]=(0,_.useState)(null),[F,W]=(0,_.useState)(null),[Y,J]=(0,_.useState)(""),[G,V]=(0,_.useState)([]),[q,X]=(0,_.useState)("getprop ro.product.model"),[$,Q]=(0,_.useState)(""),[ee,et]=(0,_.useState)("300"),[en,er]=(0,_.useState)(""),[ea,eo]=(0,_.useState)(null),[ec,ed]=(0,_.useState)([]),[ex,eu]=(0,_.useState)(null),[em,eh]=(0,_.useState)("https://"),[ep,eb]=(0,_.useState)(""),[eg,ef]=(0,_.useState)(!1),[ev,ey]=(0,_.useState)(null),ew=!!(N||ev),eN=z.find(e=>e.serial===j)||null,ej=(0,_.useCallback)(async()=>{if(!j||!S){Z(null),H(null);return}ey("overview"),H(null);try{let e=await y("/android/overview?serial=".concat(encodeURIComponent(j)));Z(e)}catch(e){Z(null),H(e.message)}finally{ey(null)}},[S,j,y]),ek=(0,_.useCallback)(async()=>{W(null);try{let e=await y("/redroid/summary");K(e)}catch(e){K(null),W(e.message)}},[y]);(0,_.useEffect)(()=>{ej()},[ej]),(0,_.useEffect)(()=>{ek()},[ek]);let ez=async()=>{if(!j){f(g("请选择设备","Pick a device"));return}ey("packages");try{let e=encodeURIComponent(Y.trim()),t=await y("/android/packages?serial=".concat(encodeURIComponent(j),"&query=").concat(e,"&limit=80"));V(t.packages||[])}catch(e){f(e.message),V([])}finally{ey(null)}},eS=async()=>{if(!j){f(g("请选择设备","Pick a device"));return}let e=q.trim();if(e){ey("shell");try{var t,n;let s=await y("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"shell",serial:j,payload:{command:e}})});Q(null!==(n=null!==(t=s.output)&&void 0!==t?t:s.message)&&void 0!==n?n:"")}catch(e){Q(e.message)}finally{ey(null)}}},e_=(0,_.useCallback)(async e=>{if(!j)return;let t=Math.min(3e3,Math.max(1,parseInt(ee,10)||200)),n=!!(null==e?void 0:e.silent);n||ey("logcat"),eo(null);try{var s;let e=await y("/android/logcat?serial=".concat(encodeURIComponent(j),"&lines=").concat(t));er(null!==(s=e.text)&&void 0!==s?s:"")}catch(e){er(""),eo(e.message)}finally{n||ey(null)}},[j,y,ee]);(0,_.useEffect)(()=>{if(!eg||!j||!S)return;let e=window.setInterval(()=>void e_({silent:!0}),3e3);return e_({silent:!0}),()=>clearInterval(e)},[S,j,eg,e_]);let eC=async()=>{if(!j){f(g("请选择设备","Pick a device"));return}ey("ui"),eu(null);try{let e=await y("/android/ui?serial=".concat(encodeURIComponent(j),"&limit=100"));ed(e.nodes||[])}catch(e){ed([]),eu(e.message)}finally{ey(null)}},eR=async(e,t)=>{ey("redroid:".concat(e));try{let n=await y("/redroid/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,name:t||""})});n.summary&&K(n.summary),f(n.message||"OK"),await ek(),D()}catch(e){f(e.message)}finally{ey(null)}},eP=async e=>{await P("key",{keycode:e})},eL=async()=>{let e=ep.trim();if(!e){f(g("请输入文字","Enter text"));return}await P("text",{text:e})},eM=async()=>{let e=em.trim();if(!e||"https://"===e){f(g("请输入 URL","Enter URL"));return}await P("open_url",{url:e})};return(0,s.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("安卓设备工作台","Android workstation")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:g("USB 真机与 Redroid 共用一套控制面,优先保证 USB 真机稳定。","USB phone and Redroid share one control surface.")})]}),S?(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ew||!j,onClick:()=>void ej(),className:"rounded-lg border border-white/10 bg-white/[0.05] px-3 py-1.5 text-xs text-zinc-300",children:g("刷新设备","Refresh device")}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>{ek(),D()},className:"rounded-lg border border-white/10 bg-white/[0.05] px-3 py-1.5 text-xs text-zinc-300",children:g("刷新 Redroid","Refresh Redroid")})]}):(0,s.jsx)("span",{className:"text-xs text-amber-200/90",children:g("宿主机未检测到 adb","adb not found on host")})]}),(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:z.map(e=>(0,s.jsxs)("button",{type:"button",onClick:()=>k(e.serial),className:"rounded-xl border px-4 py-2 text-left text-xs ".concat(j===e.serial?"border-violet-500/50 bg-violet-500/10 text-white":"border-white/10 bg-black/30 text-zinc-400"),children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("span",{className:"font-medium text-zinc-200",children:e.model||e.serial}),e.transport?(0,s.jsx)("span",{className:"rounded bg-white/10 px-1.5 py-0.5 font-mono text-[9px] uppercase text-zinc-500",children:e.transport}):null,e.kind?(0,s.jsx)("span",{className:"rounded bg-cyan-500/10 px-1.5 py-0.5 font-mono text-[9px] uppercase text-cyan-200",children:e.kind}):null]}),(0,s.jsx)("div",{className:"text-[10px] text-zinc-600",children:e.serial}),"device"!==(e.state||"").toLowerCase()?(0,s.jsx)("div",{className:"mt-1 text-[10px] font-medium text-amber-200/90",children:"unauthorized"===e.state?g("未授权,请在手机上允许 USB 调试。","Unauthorized, allow USB debugging on device."):"".concat(g("状态","State"),": ").concat(e.state)}):null]},e.serial))}),S&&0===z.length?(0,s.jsx)("p",{className:"mt-4 rounded-lg border border-amber-500/20 bg-amber-500/5 p-3 text-xs leading-relaxed text-amber-200/90",children:g("当前没有已授权设备。USB 真机请检查调试授权;Redroid 请先启动实例,再 adb connect 127.0.0.1:5555。","No authorized devices. For USB phones, confirm USB debugging. For Redroid, start an instance then adb connect 127.0.0.1:5555.")}):null]}),(0,s.jsxs)("div",{className:"grid gap-4 xl:grid-cols-[1.1fr_0.9fr]",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/15 bg-zinc-950/50 p-5",children:[(0,s.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-violet-300/90",children:g("真机诊断","Phone diagnostics")}),O?(0,s.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:O}):null,A?(0,s.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,s.jsxs)("dl",{className:"space-y-1.5 font-mono text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"model"})," ",(0,s.jsxs)("dd",{className:"inline text-zinc-300",children:[A.brand," ",A.model]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"android"})," ",(0,s.jsxs)("dd",{className:"inline text-zinc-300",children:[A.android_version," (sdk ",A.sdk,")"]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"kind"})," ",(0,s.jsxs)("dd",{className:"inline text-zinc-300",children:[A.kind||(null==eN?void 0:eN.kind)||"unknown"," / ",A.transport||(null==eN?void 0:eN.transport)||"unknown"]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"display"})," ",(0,s.jsx)("dd",{className:"inline text-zinc-300",children:A.resolution})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"rotation"})," ",(0,s.jsx)("dd",{className:"inline text-zinc-300",children:A.rotation})]}),(0,s.jsx)("div",{className:"whitespace-pre-wrap text-[10px] leading-snug text-zinc-500",children:A.battery}),(0,s.jsx)("div",{className:"line-clamp-3 text-[10px] text-zinc-500",children:A.focus})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[ei(null===(t=A.diagnostics)||void 0===t?void 0:t.ready,g("已启动","Boot ready"),g("未完成启动","Boot pending")),ei(null===(n=A.diagnostics)||void 0===n?void 0:n.google_play,"Google Play","No Play"),ei(null===(l=A.diagnostics)||void 0===l?void 0:l.google_services,"GMS","No GMS"),ei(null===(i=A.diagnostics)||void 0===i?void 0:i.magisk,"Magisk","No Magisk"),ei(null===(r=A.diagnostics)||void 0===r?void 0:r.root,"Root","No root")]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/5 bg-black/20 p-3 text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{children:["boot_completed: ",(null===(a=A.diagnostics)||void 0===a?void 0:a.boot_completed)||"-"]}),(0,s.jsxs)("div",{children:["provisioned: ",(null===(o=A.diagnostics)||void 0===o?void 0:o.device_provisioned)||"-"]}),(0,s.jsxs)("div",{children:["setup_complete: ",(null===(c=A.diagnostics)||void 0===c?void 0:c.user_setup_complete)||"-"]}),(0,s.jsxs)("div",{children:["abi: ",(null===(d=A.diagnostics)||void 0===d?void 0:d.abi)||"-"]}),(0,s.jsxs)("div",{className:"truncate",children:["hardware: ",(null===(x=A.diagnostics)||void 0===x?void 0:x.hardware)||"-"]})]})]}):O?null:(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:g("加载中","Loading")})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-zinc-950/50 p-5",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-cyan-300/90",children:g("Redroid 板块","Redroid panel")}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("start"),className:"rounded-lg bg-emerald-500/20 px-3 py-1.5 text-xs text-emerald-100 ring-1 ring-emerald-500/30",children:g("启动默认实例","Start default")})]}),F?(0,s.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:F}):null,B?(0,s.jsxs)("div",{className:"mt-3 space-y-3 text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,s.jsxs)("div",{children:["arch: ",B.arch||"-"]}),(0,s.jsxs)("div",{className:"truncate",children:["image: ",B.image||"-"]}),(0,s.jsxs)("div",{children:["profile: ",B.device_profile||"-"]}),(0,s.jsxs)("div",{children:["gpu: ",B.gpu_mode||"-"]}),(0,s.jsxs)("div",{children:["adb: 127.0.0.1:",B.default_port||5555]})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[ei(null===(u=B.requirements)||void 0===u?void 0:u.docker_available,"Docker","No Docker"),ei(null===(m=B.requirements)||void 0===m?void 0:m.adb_available,"ADB","No ADB"),ei(null===(h=B.requirements)||void 0===h?void 0:h.kvm,"KVM","No KVM"),ei(null===(p=B.requirements)||void 0===p?void 0:p.binderfs,"binderfs","No binderfs")]}),(0,s.jsxs)("div",{className:"space-y-2",children:[(B.instances||[]).map(e=>{var t,n,l,i;return(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-3",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"font-medium text-zinc-100",children:e.name}),(0,s.jsxs)("div",{className:"font-mono text-[10px] text-zinc-500",children:[e.port?"127.0.0.1:".concat(e.port):"-"," / ",e.status_text||"-"]})]}),(0,s.jsxs)("div",{className:"flex gap-1",children:[(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("start",e.name),className:"rounded bg-emerald-500/15 px-2 py-1 text-[10px] text-emerald-200",children:"Start"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("restart",e.name),className:"rounded bg-amber-500/15 px-2 py-1 text-[10px] text-amber-200",children:"Restart"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("adb_connect",e.name),className:"rounded bg-cyan-500/15 px-2 py-1 text-[10px] text-cyan-200",children:"ADB"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("stop",e.name),className:"rounded bg-rose-500/15 px-2 py-1 text-[10px] text-rose-200",children:"Stop"})]})]}),(0,s.jsxs)("div",{className:"mt-2 flex flex-wrap gap-2",children:[ei(null===(t=e.diagnostics)||void 0===t?void 0:t.ready,g("系统就绪","System ready"),g("启动中","Booting")),ei(null===(n=e.diagnostics)||void 0===n?void 0:n.google_play,"Play","No Play"),ei(null===(l=e.diagnostics)||void 0===l?void 0:l.magisk,"Magisk","No Magisk"),ei(null===(i=e.diagnostics)||void 0===i?void 0:i.root,"Root","No root")]}),e.data_dir?(0,s.jsx)("div",{className:"mt-2 truncate font-mono text-[10px] text-zinc-500",children:e.data_dir}):null]},e.name)}),(null===(b=B.instances)||void 0===b?void 0:b.length)?null:(0,s.jsx)("p",{className:"rounded-xl border border-white/5 bg-black/20 p-3 text-xs text-zinc-500",children:g("当前没有 Redroid 实例。默认动作会创建 redroid13-1。","No Redroid instances yet. Default actions create redroid13-1.")})]})]}):(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:g("读取 Redroid 状态中","Loading Redroid status")})]})]}),(0,s.jsx)(es,{t:g,apiBase:w,fetchJson:y,serial:j,devices:z,setSerial:k,adbAvailable:S,lock:ew,overview:A,onAndroidAction:P,notify:f,onRefreshDevices:D}),S&&j?(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,s.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-emerald-300/90",children:g("快捷控制","Quick controls")}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("3"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Home"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("4"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Back"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("187"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Recents"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("wake"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Wake"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("launch_package",{package:"com.zhiliaoapp.musically"}),className:"rounded-lg bg-gradient-to-r from-pink-500/25 to-violet-500/25 px-3 py-1.5 text-xs ring-1 ring-white/10",children:"TikTok"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("24"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Vol+"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("25"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Vol-"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("66"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Enter"})]}),(0,s.jsx)("p",{className:"mt-3 text-[10px] text-zinc-600",children:g("滑动手势","Swipe gestures")}),(0,s.jsx)("div",{className:"mt-1 flex flex-wrap gap-2",children:["up","down","left","right"].map(e=>(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("swipe",{direction:e}),className:"rounded-lg border border-white/10 bg-black/30 px-2.5 py-1 font-mono text-[10px] uppercase text-zinc-300",children:e},e))}),(0,s.jsxs)("div",{className:"mt-4 rounded-lg border border-white/5 bg-black/20 p-3",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:g("ADB 文本输入","ADB text input")}),(0,s.jsxs)("div",{className:"mt-2 flex flex-col gap-2 sm:flex-row",children:[(0,s.jsx)("input",{className:"min-w-0 flex-1 rounded-lg border border-white/10 bg-black/40 px-3 py-2 text-xs",value:ep,onChange:e=>eb(e.target.value),placeholder:"hello / 123",onKeyDown:e=>{"Enter"===e.key&&eL()}}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eL(),className:"rounded-lg bg-emerald-500/20 px-3 py-2 text-xs text-emerald-100 ring-1 ring-emerald-500/30",children:g("发送","Send")})]})]}),(0,s.jsxs)("div",{className:"mt-4 flex flex-col gap-2 sm:flex-row sm:items-center",children:[(0,s.jsx)("input",{className:"min-w-0 flex-1 rounded-lg border border-white/10 bg-black/40 px-3 py-2 text-xs",value:em,onChange:e=>eh(e.target.value),placeholder:"https://"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eM(),className:"rounded-lg bg-violet-500/20 px-3 py-2 text-xs text-violet-100 ring-1 ring-violet-500/30",children:g("打开链接","Open URL")})]})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,s.jsxs)("h4",{className:"flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-cyan-300/90",children:[(0,s.jsx)(L.Z,{className:"h-4 w-4"}),g("USB 真机优化建议","USB optimization")]}),(0,s.jsxs)("ul",{className:"mt-3 space-y-2 text-xs leading-relaxed text-zinc-400",children:[(0,s.jsx)("li",{children:g("优先使用主板直连 USB,不要经过不稳的 HUB。","Prefer direct motherboard USB, not unstable hubs.")}),(0,s.jsx)("li",{children:g("开发板端固定 adb server,避免频繁 kill-server。","Keep adb server stable and avoid frequent kill-server.")}),(0,s.jsx)("li",{children:g("镜像页默认支持 scrcpy H.264 真流,截图模式作为回退。","Use scrcpy H.264 live stream first, screenshot mode as fallback.")}),(0,s.jsx)("li",{children:g("如果 TikTok / YouTube App 直播,要先确认屏幕常亮、分辨率稳定、USB 供电足够。","For TikTok / YouTube app live, keep screen on, resolution stable, and USB power sufficient.")})]})]})]}):null,S&&j?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(M.Z,{className:"h-4 w-4 text-emerald-400"}),g("包名搜索与启动","Packages")]}),(0,s.jsxs)("div",{className:"mt-3 flex flex-col gap-2 sm:flex-row",children:[(0,s.jsx)("input",{className:"min-w-0 flex-1 rounded-xl border border-white/10 bg-black/40 px-4 py-2 text-sm",value:Y,onChange:e=>J(e.target.value),placeholder:"tiktok / musically / youtube",onKeyDown:e=>{"Enter"===e.key&&ez()}}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void ez(),className:"rounded-xl bg-emerald-500/20 px-4 py-2 text-sm text-emerald-100 ring-1 ring-emerald-500/30",children:g("搜索","Search")})]}),(0,s.jsxs)("ul",{className:"mt-4 max-h-48 space-y-1 overflow-y-auto rounded-lg border border-white/5 bg-black/30 p-2 font-mono text-[11px]",children:[G.map(e=>(0,s.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 py-1 text-zinc-400",children:[(0,s.jsx)("span",{className:"min-w-0 truncate text-zinc-300",children:e.package}),(0,s.jsxs)("span",{className:"flex shrink-0 gap-1",children:[(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("launch_package",{package:e.package}),className:"rounded bg-white/10 px-2 py-0.5 text-[10px] text-zinc-200",children:g("启动","Launch")}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("force_stop",{package:e.package}),className:"rounded bg-rose-500/15 px-2 py-0.5 text-[10px] text-rose-200",children:g("停止","Stop")})]})]},e.package)),G.length?null:(0,s.jsx)("li",{className:"py-2 text-center text-zinc-600",children:g("暂无结果","No results")})]})]}):null,S&&j?(0,s.jsxs)("div",{className:"grid gap-6 xl:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(T.Z,{className:"h-4 w-4 text-amber-400"}),"ADB shell"]}),(0,s.jsx)("div",{className:"mt-2 flex flex-wrap gap-1.5",children:el.map(e=>(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>X(e.cmd),className:"rounded-md border border-white/10 bg-white/[0.04] px-2 py-1 text-[10px] text-zinc-400 hover:text-zinc-200",children:e.label},e.label))}),(0,s.jsx)("textarea",{className:"mt-3 min-h-[100px] w-full resize-y rounded-xl border border-white/10 bg-black/50 p-3 font-mono text-xs text-zinc-200",value:q,onChange:e=>X(e.target.value),spellCheck:!1,onKeyDown:e=>{"Enter"===e.key&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),eS())}}),(0,s.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eS(),className:"rounded-xl bg-amber-500/20 px-4 py-2 text-sm text-amber-100 ring-1 ring-amber-500/30",children:"shell"===ev?(0,s.jsxs)("span",{className:"inline-flex items-center gap-2",children:[(0,s.jsx)(v.Z,{className:"h-3.5 w-3.5 animate-spin"}),"Run"]}):"Run"}),$?(0,s.jsxs)("button",{type:"button",disabled:!$,onClick:()=>I($),className:"inline-flex items-center gap-1 rounded-lg border border-white/10 px-3 py-1.5 text-xs text-zinc-400 hover:text-zinc-200",children:[(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"}),g("复制输出","Copy")]}):null]}),$?(0,s.jsx)("pre",{className:"mt-3 max-h-64 overflow-auto whitespace-pre-wrap rounded-lg border border-white/5 bg-black/40 p-3 font-mono text-[11px] text-zinc-400 xl:max-h-[min(24rem,50vh)]",children:$}):null]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("Logcat","Logcat")}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[(0,s.jsx)("input",{className:"w-24 rounded-lg border border-white/10 bg-black/40 px-3 py-2 font-mono text-xs",value:ee,onChange:e=>et(e.target.value)}),(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 text-[11px] text-zinc-400",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:eg,onChange:e=>ef(e.target.checked)}),g("每 3 秒自动刷新","Auto every 3s")]}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void e_(),className:"rounded-xl bg-cyan-500/20 px-4 py-2 text-sm text-cyan-100 ring-1 ring-cyan-500/30",children:g("拉取日志","Pull logs")}),en?(0,s.jsxs)("button",{type:"button",onClick:()=>I(en),className:"inline-flex items-center gap-1 rounded-lg border border-white/10 px-3 py-1.5 text-xs text-zinc-400 hover:text-zinc-200",children:[(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"}),g("复制","Copy")]}):null]}),ea?(0,s.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:ea}):null,en?(0,s.jsx)("pre",{className:"mt-3 max-h-72 overflow-auto whitespace-pre-wrap rounded-lg border border-white/5 bg-black/50 p-3 font-mono text-[10px] leading-tight text-zinc-500 xl:max-h-[min(24rem,50vh)]",children:en}):null]})]}):null,S&&j?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(E.Z,{className:"h-4 w-4 text-fuchsia-400"}),g("界面节点","UI nodes")]}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eC(),className:"mt-3 rounded-xl border border-fuchsia-500/30 bg-fuchsia-500/10 px-4 py-2 text-sm text-fuchsia-100",children:g("刷新节点","Refresh nodes")}),ex?(0,s.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:ex}):null,(0,s.jsxs)("ul",{className:"mt-3 max-h-64 space-y-1 overflow-y-auto rounded-lg border border-white/5 bg-black/30 p-2 text-[11px]",children:[ec.map((e,t)=>(0,s.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 border-b border-white/[0.04] py-1.5 text-zinc-400 last:border-0",children:[(0,s.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,s.jsx)("span",{className:"text-zinc-200",children:e.label}),e.resource_id?(0,s.jsx)("span",{className:"ml-2 font-mono text-[10px] text-zinc-600",children:e.resource_id}):null,(0,s.jsxs)("div",{className:"font-mono text-[10px] text-zinc-600",children:["(",e.center_x,", ",e.center_y,")",e.clickable?" click":""]})]}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("tap",{x:e.center_x,y:e.center_y}),className:"shrink-0 rounded bg-white/10 px-2 py-1 text-[10px] text-zinc-200",children:"Tap"})]},"".concat(e.center_x,"-").concat(e.center_y,"-").concat(t))),ec.length||ex?null:(0,s.jsx)("li",{className:"py-4 text-center text-zinc-600",children:g("尚未加载","Not loaded")})]})]}):null,S&&j?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("安装 APK","Install APK")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:g("先 adb push 到 /sdcard/ 再执行安装。","Push the APK to /sdcard/ first.")}),(0,s.jsx)("input",{className:"mt-4 w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm",value:C,onChange:e=>R(e.target.value)}),(0,s.jsx)("button",{type:"button",disabled:ew||!S||!j,onClick:()=>void P("install_apk",{path:C}),className:"mt-3 rounded-xl bg-emerald-500/20 px-4 py-2 text-sm font-medium text-emerald-100 ring-1 ring-emerald-500/30",children:"pm install"})]}):null]})}var ea=n(9897),eo=n(4554),ec=n(7689),ed=n(8930),ex=n(8401);function eu(e){let{t,title:n,subtitle:l,steps:i,onNavigate:r}=e;return(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/25 bg-gradient-to-br from-violet-500/10 via-zinc-950/40 to-fuchsia-500/5 p-6 shadow-lg shadow-violet-900/10",children:[(0,s.jsx)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:n}),(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-400",children:l}),(0,s.jsx)("div",{className:"mt-6 flex flex-col items-center gap-4 sm:flex-row sm:flex-wrap sm:justify-center",children:i.map((e,t)=>(0,s.jsxs)("div",{className:"flex items-center gap-4",children:[e.openUrl||e.target&&r?(0,s.jsxs)("button",{type:"button",onClick:()=>{if(e.openUrl){window.open((0,ex.p)(e.openUrl),"_blank","noopener,noreferrer");return}e.target&&r&&r(e.target)},className:"flex min-h-[4rem] min-w-[7rem] flex-col items-center justify-center rounded-2xl bg-gradient-to-br px-4 py-2 text-center text-xs font-bold text-white shadow-lg ring-2 ring-white/10 transition hover:ring-violet-400/50 hover:brightness-110 ".concat(e.gradient),children:[(0,s.jsx)("span",{children:e.label}),e.sub?(0,s.jsx)("span",{className:"mt-1 text-[10px] font-normal text-white/80",children:e.sub}):null]}):(0,s.jsxs)("div",{className:"flex min-h-[4rem] min-w-[7rem] flex-col items-center justify-center rounded-2xl bg-gradient-to-br px-4 py-2 text-center text-xs font-bold text-white shadow-lg ".concat(e.gradient),children:[(0,s.jsx)("span",{children:e.label}),e.sub?(0,s.jsx)("span",{className:"mt-1 text-[10px] font-normal text-white/80",children:e.sub}):null]}),t8?e.slice(-8):e;if(e.includes("live2/")){let t=e.split("/"),n=t[t.length-1]||"";return n.length>8?n.slice(-8):n}}}let t=e.trim();return!t||t.includes("\n")||t.toLowerCase().startsWith("rtmp")?"":t.length>8?t.slice(-8):t}function eh(e){let t=[];for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith("#")||!/douyin\.com|v\.douyin\.com/i.test(e))continue;let s=e.match(/(https?:\/\/live\.douyin\.com\/[a-zA-Z0-9_-]+)/i);if(s){t.push(s[1].replace(/^http:\/\//i,"https://"));continue}let l=e.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);if(l){t.push("https://live.douyin.com/".concat(l[1]));continue}let i=e.match(/(\d{8,})/);i&&t.push("https://live.douyin.com/".concat(i[1]))}return Array.from(new Set(t)).slice(0,16)}function ep(e){let t="",n=!0,s="",l=!1,i=e.split(/\r?\n/),r=!1;for(let e of i){let i=e.trim();if(/^\[youtube\]/i.test(i)){r=!0;continue}if(/^\[/.test(i)){r=!1;continue}if(!r||!i||i.startsWith("#")||i.startsWith(";"))continue;let a=i.indexOf("=");if(a<0)continue;let o=i.slice(0,a).trim().toLowerCase(),c=i.slice(a+1).trim().split(/[#;]/)[0].trim();"key"===o||"stream_key"===o?t=c:"rtmps"===o?n=!/^(0|false|否)/i.test(c):"bitrate"===o?s=c:"fast_audio"===o&&(l=/^(1|true|yes|是|开|on)/i.test(c))}return{key:t,rtmps:n,bitrate:s,fastAudio:l}}function eb(e){return"URL_config.".concat(e.replace(/[^a-zA-Z0-9_.-]/g,"_"),".ini")}function eg(e){let t=e.bitrate.trim()?"bitrate = ".concat(e.bitrate.trim()):"# bitrate = 4000";return"[youtube]\n# YouTube 推流 key(工作室 → 直播 → 串流密钥)\nkey = ".concat(e.key.trim(),"\n\n# 使用 RTMPS;填 否 则 RTMP\nrtmps = ").concat(e.rtmps?"是":"否","\n\n# 视频比特率 kbps(可选)\n").concat(t,"\n\n# 轻量音频链,减轻 CPU:1 / 是\nfast_audio = ").concat(e.fastAudio?"1":"0","\n")}function ef(e){if(e<60)return"".concat(e,"s");let t=Math.floor(e/60);return t<60?"".concat(t,"m ").concat(e%60,"s"):"".concat(Math.floor(t/60),"h ").concat(t%60,"m")}function ev(e){var t,n,l;let{t:i,currentProc:r,fetchJson:a,urlListText:o,keySuffixUi:c,showKeyRow:d=!0,pollMs:x=1e3,refreshToken:u=0}=e,[m,h]=(0,_.useState)(""),[p,b]=(0,_.useState)(""),[g,f]=(0,_.useState)(""),[v,w]=(0,_.useState)(""),[N,j]=(0,_.useState)(""),[k,z]=(0,_.useState)([]),[S,C]=(0,_.useState)(null),[R,P]=(0,_.useState)(!1),[L,M]=(0,_.useState)(null),[T,U]=(0,_.useState)(0),[E,I]=(0,_.useState)(!0),D=(0,_.useRef)(null),A=(0,_.useRef)(null),O=(0,_.useRef)(!1),H=(0,_.useRef)(!1),B=(0,_.useRef)(!1),W=(0,_.useRef)(r),Y=(0,_.useRef)(0),J=function(e){let t=[];for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith("#")||!/douyin\.com|v\.douyin\.com/i.test(e))continue;let s=e.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);if(s){t.push(s[1]);continue}let l=e.match(/(\d{8,})/);t.push(l?l[1]:e.slice(0,96))}return Array.from(new Set(t)).slice(0,12)}(o),G=/^(online|running)$/i.test(m),V=function(e){if(!e)return null;let t=null;for(let n of e.split(/\r?\n/)){let e=n.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);e&&(t=e[1]);let s=n.match(/https?:\/\/[^/\s]*douyin\.com\/(\d{8,})/i);s&&(t=s[1])}return t}(p),q=null!==(n=eh(o)[0])&&void 0!==n?n:"",X=V||(null!==(l=null===(t=q.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i))||void 0===t?void 0:t[1])&&void 0!==l?l:null),$=X?"https://live.douyin.com/".concat(X):q||null,Q=(0,_.useCallback)(async()=>{let e=W.current.trim();if(!e)return;if(H.current){B.current=!0;return}H.current=!0;let t=++Y.current;try{let n=await a("/status?process=".concat(encodeURIComponent(e)));if(t!==Y.current||e!==W.current.trim())return;let s=n.process_status||"unknown";h(s),b(n.recent_log||""),f(n.recent_error||""),w(n.business_status||""),j(n.business_note||""),z(Array.isArray(n.ffmpeg_pids)?n.ffmpeg_pids:[]),C("number"==typeof n.log_age_seconds?n.log_age_seconds:null);let l=/^(online|running)$/i.test(s);l&&!O.current&&M(Date.now()),l||M(null),O.current=l}catch(n){if(t!==Y.current||e!==W.current.trim())return;h("error"),w("error"),j(""),z([]),C(null)}finally{H.current=!1,B.current&&(B.current=!1,window.setTimeout(()=>void Q(),0))}},[a]);(0,_.useEffect)(()=>{if(W.current=r,Y.current+=1,B.current=!1,!r){h(""),b(""),f(""),w(""),j(""),z([]),C(null),M(null),O.current=!1;return}h(""),b(""),f(""),w(""),j(""),z([]),C(null),M(null),O.current=!1,Q()},[r,Q]),(0,_.useEffect)(()=>{let e=()=>I("visible"===document.visibilityState);return e(),document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[]),(0,_.useEffect)(()=>{r&&Q()},[r,Q,u]),(0,_.useEffect)(()=>{if(R||!E||!r)return;let e=window.setInterval(()=>void Q(),x);return()=>clearInterval(e)},[R,E,r,Q,x]),(0,_.useEffect)(()=>{let e=()=>{"visible"===document.visibilityState&&Q()};return document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[Q]),(0,_.useEffect)(()=>{if(!L)return;let e=window.setInterval(()=>U(e=>e+1),1e3);return()=>clearInterval(e)},[L]),(0,_.useEffect)(()=>{if(R||!E)return;let e=D.current;e&&(e.scrollTop=e.scrollHeight)},[p,R,E]),(0,_.useEffect)(()=>{if(R||!E)return;let e=A.current;e&&(e.scrollTop=e.scrollHeight)},[g,R,E]);let ee=null==L?i("—(未检测到在线)","— (not online)"):ef(Math.max(0,Math.floor((Date.now()-L)/1e3))),et=R?i("已暂停刷新","Paused"):E?i("每秒刷新","~1s refresh"):i("后台暂停","Hidden"),en=R?"bg-amber-500/20 text-amber-100 ring-amber-500/35":E?"bg-emerald-500/15 text-emerald-200/90 ring-emerald-500/25":"bg-sky-500/15 text-sky-100 ring-sky-500/25";return(0,s.jsxs)("section",{className:"rounded-2xl border border-emerald-500/20 bg-gradient-to-b from-emerald-500/[0.07] to-zinc-950/80 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsx)("span",{className:"sr-only","aria-hidden":!0,children:T}),(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:i("当前直播日志","Live process log")}),(0,s.jsx)("span",{className:"rounded-full bg-white/10 px-2 py-0.5 font-mono text-[10px] text-zinc-300 ring-1 ring-white/10",children:r||"—"}),(0,s.jsx)("span",{className:"rounded-full px-2 py-0.5 text-[10px] font-medium ring-1 ".concat(en),children:et})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsxs)("button",{type:"button",onClick:()=>void Q(),className:"inline-flex items-center gap-1 rounded-lg border border-white/10 bg-white/[0.05] px-3 py-1.5 text-xs text-zinc-300 hover:bg-white/[0.08]",children:[(0,s.jsx)(y.Z,{className:"h-3.5 w-3.5"}),i("立即拉取","Refresh")]}),(0,s.jsxs)("button",{type:"button",onClick:()=>P(e=>!e),className:"inline-flex items-center gap-1 rounded-lg px-3 py-1.5 text-xs ring-1 ".concat(R?"bg-amber-500/20 text-amber-100 ring-amber-500/35":"border border-white/10 bg-black/30 text-zinc-300"),children:[R?(0,s.jsx)(K.Z,{className:"h-3.5 w-3.5"}):(0,s.jsx)(F.Z,{className:"h-3.5 w-3.5"}),R?i("继续自动刷新","Resume"):i("暂停自动刷新","Pause")]})]})]}),(0,s.jsxs)("div",{className:"mt-4 space-y-3 rounded-xl border border-white/[0.06] bg-black/25 p-4",children:[(0,s.jsxs)("div",{className:"grid gap-2 text-xs sm:grid-cols-2",children:[(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("进程状态","Status")}),(0,s.jsx)("span",{className:"font-medium text-zinc-200",children:function(e,t){let n=(t||"unknown").toLowerCase();return"online"===n||"running"===n?e("运行中(PM2/进程在线)","Running (process online)"):"stopped"===n||"stopping"===n?e("已停止","Stopped"):"not_found"===n||"errored"===n?e("未运行或未找到","Not running / not found"):"invalid"===n?e("无效进程名","Invalid process"):t||"—"}(i,m)})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("Business state","Business state")}),(0,s.jsx)("span",{className:"font-medium text-cyan-200/90",children:function(e,t,n){let s=(t||"").toLowerCase();return"streaming"===s?e("Pushing to YouTube","Pushing to YouTube"):"waiting_source"===s?e("Waiting for the upstream live source","Waiting for the upstream live source"):"source_live"===s?e("Source live detected, but no active FFmpeg relay worker","Source live detected, but no active FFmpeg relay worker"):"monitoring"===s?e("Process online and monitoring the source","Process online and monitoring the source"):"misconfigured"===s?e("YouTube key missing or invalid","YouTube key missing or invalid"):"stale"===s?e("Process online but the log heartbeat is stale","Process online but the log heartbeat is stale"):"error"===s?e("Recent process error detected","Recent process error detected"):(null==n?void 0:n.trim())?n.trim():e("No business-state hint yet","No business-state hint yet")}(i,v,N)})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("本次在线时长(估算)","Online duration (est.)")}),(0,s.jsx)("span",{className:"font-mono text-cyan-200/90",children:ee})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("FFmpeg workers","FFmpeg workers")}),(0,s.jsxs)("span",{className:"font-mono text-zinc-300",children:[k.length?k.join(", "):"none",null!=S?" \xb7 log ".concat(ef(Math.max(0,Math.floor(S)))):""]})]})]}),d?(0,s.jsxs)("div",{className:"flex flex-wrap gap-2 text-xs",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("YouTube key 尾码(参考)","YT key suffix")}),(0,s.jsx)("span",{className:"font-mono text-zinc-300",children:c||"—"})]}):null,$?(0,s.jsxs)("div",{className:"rounded-lg border border-violet-500/20 bg-violet-500/[0.06] px-3 py-2.5",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsx)("span",{className:"text-[11px] font-medium text-zinc-400",children:V?i("当前直播源站(日志)","Current source (from log)"):G?i("配置中的源站地址","Configured source URL"):i("源站快捷入口","Source quick link")}),(0,s.jsxs)("a",{href:$,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 rounded-lg bg-violet-500/20 px-3 py-1.5 text-xs font-medium text-violet-100 ring-1 ring-violet-500/35 transition hover:bg-violet-500/30",children:[(0,s.jsx)(Z.Z,{className:"h-3.5 w-3.5 shrink-0 opacity-90"}),X||i("打开抖音直播页","Open Douyin live")]})]}),J.length>1&&V?(0,s.jsxs)("p",{className:"mt-2 text-[10px] text-zinc-600",children:[i("配置中还有","Also in config:")," ",J.filter(e=>e!==X).slice(0,3).map(e=>(0,s.jsx)("a",{href:"https://live.douyin.com/".concat(e),target:"_blank",rel:"noreferrer",className:"ml-1 text-violet-400/90 underline-offset-2 hover:underline",children:e},e)),J.length>4?"…":null]}):null]}):(0,s.jsx)("p",{className:"text-[11px] text-zinc-600",children:i("(日志与地址列表中暂无抖音房间)","(No Douyin room in log or URL list)")})]}),"not_found"!==m&&"invalid"!==m?(0,s.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wider text-emerald-400/90",children:i("进程输出(stdout / 合并日志)","Process output")}),(0,s.jsx)("pre",{ref:D,className:"log-live-scroll mt-2 max-h-[min(22rem,42vh)] min-h-[12rem] overflow-auto whitespace-pre-wrap rounded-xl border border-emerald-500/20 bg-black/55 p-3 font-mono text-[10px] leading-relaxed text-emerald-100/95",children:p.trim()||i("(暂无)","(empty)")})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wider text-rose-400/90",children:i("异常信息(stderr)","Stderr")}),(0,s.jsx)("pre",{ref:A,className:"log-live-scroll mt-2 max-h-[min(22rem,42vh)] min-h-[12rem] overflow-auto whitespace-pre-wrap rounded-xl border border-rose-500/20 bg-black/55 p-3 font-mono text-[10px] leading-relaxed text-rose-100/95",children:g.trim()||i("(暂无)","(empty)")})]})]}):(0,s.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:i("进程未在 PM2 / 本地注册表中运行,日志区域已隐藏。","Process not running — log panes hidden.")})]})}function ey(e){return/tiktok/i.test(e.script)||/tiktok/i.test(e.pm2)}let ew=[{id:"720p60",labelZh:"720p @ 60Hz",labelEn:"720p @ 60Hz",spec:"1280x720, 59.94/60Hz, RGB/YUV 有限",hintZh:"板端 HDMI 输出时序与显示端一致;下游画布建议 1280\xd7720。",hintEn:"Match SoC HDMI timing to the display; downstream canvas e.g. 1280\xd7720."},{id:"1080p30",labelZh:"1080p @ 30Hz",labelEn:"1080p @ 30Hz",spec:"1920x1080, 30Hz",hintZh:"带宽紧张时可优先 1080p30;检查线材与接口规格。",hintEn:"Prefer 1080p30 when bandwidth is tight; check cable and port specs."},{id:"1080p60",labelZh:"1080p @ 60Hz",labelEn:"1080p @ 60Hz",spec:"1920x1080, 60Hz, 高刷转播",hintZh:"两端均需稳定支持 1080p60;长时间运行注意散热。",hintEn:"Both ends need stable 1080p60; mind thermals for long runs."}],eN="live-hub-tiktok-hdmi-check-v1",ej="live-hub-tiktok-hdmi-notes-v1",ek="live-hub-tiktok-source-mode-v1";function ez(e){var t;let{t:n,busy:l,entries:i,currentProc:r,setCurrentProc:a,urlConfig:o,setUrlConfig:c,onRunProcess:d,onSaveUrlConfig:x,onReplayGoLive:u,onCopy:m,fetchJson:h,apiPrefix:p,quickLinks:b,hdmiStatus:g,notify:f,onNavigate:v}=e,y=(0,_.useMemo)(()=>i.filter(ey),[i]),w=y.length?y:i,[N,j]=(0,_.useState)("srs"),[k,z]=(0,_.useState)([]),[S,C]=(0,_.useState)(!1),[R,P]=(0,_.useState)(!1),[L,M]=(0,_.useState)("1080p30"),[T,E]=(0,_.useState)("1080p30"),[I,A]=(0,_.useState)(!1),[Z,O]=(0,_.useState)(!0),[H,K]=(0,_.useState)(null),F=(0,_.useRef)(!1),W=(0,_.useRef)(o),[J,G]=(0,_.useState)(""),[V,q]=(0,_.useState)({}),X=(0,_.useCallback)(e=>{W.current=e,c(e)},[c]),$=(0,_.useCallback)(e=>{j(e);try{window.localStorage.setItem(ek,e)}catch(e){}},[]);(0,_.useEffect)(()=>{try{let e=window.localStorage.getItem(ek);("ffmpeg"===e||"replay"===e||"srs"===e)&&("ffmpeg"!==e&&"replay"!==e?j(e):j("srs"))}catch(e){}},[]),(0,_.useEffect)(()=>{F.current=!1},[r]),(0,_.useEffect)(()=>{W.current=o},[o]);let Q=(0,_.useCallback)(async()=>{if(r)try{var e;let t=new URLSearchParams({process:r,_ts:String(Date.now())}),n=await h("/get_url_config?".concat(t));X(null!==(e=n.content)&&void 0!==e?e:"")}catch(e){}},[X,r,h]);(0,_.useEffect)(()=>{if(!r||!Z||"ffmpeg"!==N)return;let e=window.setInterval(()=>{F.current||Q()},8e3);return()=>clearInterval(e)},[r,Z,Q,N]),(0,_.useEffect)(()=>{"ffmpeg"===N&&r&&Q()},[N,r,Q]);let ee=(0,_.useCallback)(async()=>{if(r){C(!0);try{var e;let t=await h("/tiktok_replay/list?process=".concat(encodeURIComponent(r)));z(null!==(e=t.files)&&void 0!==e?e:[])}catch(e){f(e.message),z([])}finally{C(!1)}}},[r,h,f]);(0,_.useEffect)(()=>{"replay"===N&&r&&ee()},[N,r,ee]),(0,_.useEffect)(()=>{try{let e=window.localStorage.getItem(eN);e&&q(JSON.parse(e))}catch(e){}try{G(window.localStorage.getItem(ej)||"")}catch(e){}},[]);let et=(0,_.useCallback)(e=>{q(e);try{window.localStorage.setItem(eN,JSON.stringify(e))}catch(e){}},[]),en=e=>{G(e);try{window.localStorage.setItem(ej,e)}catch(e){}},es=async()=>{if(r){A(!0),K(null),F.current=!1;try{var e;let t=new URLSearchParams({process:r,_ts:String(Date.now())}),s=await h("/get_url_config?".concat(t));X(null!==(e=s.content)&&void 0!==e?e:""),K(n("已从服务器读取 URL_config","Reloaded URL_config from server"))}catch(e){K(e.message)}finally{A(!1)}}},el=async()=>{try{await Promise.resolve(x(W.current)),F.current=!1}catch(e){}},ei=async e=>{if(r){P(!0);try{await h("/tiktok_replay/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({process:r,filename:e})}),f(n("已删除文件","File removed")),await ee()}catch(e){f(e.message)}finally{P(!1)}}},er=async e=>{var t;let s=null===(t=e.target.files)||void 0===t?void 0:t[0];if(e.target.value="",s&&r){P(!0);try{let e=new FormData;e.append("file",s);let t=await (0,Y.N)("".concat(p,"/tiktok_replay/upload?process=").concat(encodeURIComponent(r)),{method:"POST",body:e});f(t.message||n("上传成功","Uploaded")),await ee()}catch(e){f(e.message)}finally{P(!1)}}},ex=l||I||R,em=ew.find(e=>e.id===T),eh=!!(null==g?void 0:g.can_stream_hdmi),ep=(null==g?void 0:g.preferred_device)||(null==g?void 0:null===(t=g.video_devices)||void 0===t?void 0:t[0])||"";return(0,s.jsxs)("div",{className:"mx-auto max-w-4xl space-y-6",children:[v?(0,s.jsx)(eu,{t:n,title:n("TikTok HDMI 硬件链路","TikTok HDMI hardware chain"),subtitle:n("板端编码经 HDMI 到显示/下游设备;与「网络」页顶卡相同的箭头风格。","Encode on SoC → HDMI → display/downstream; same arrow style as Network header."),onNavigate:v,steps:[{label:"FFmpeg",sub:n("采集 / 推流","Capture"),gradient:"from-cyan-400 to-blue-500",target:"live_tiktok"},{label:"HDMI",sub:n("板载输出","SoC out"),gradient:"from-violet-500 to-fuchsia-500"},{label:"Android",sub:n("AOSP / 手机","AOSP"),gradient:"from-amber-400 to-orange-500",target:"android"}]}):null,(0,s.jsx)("div",{className:"rounded-2xl border border-cyan-500/25 bg-gradient-to-br from-cyan-500/[0.14] via-zinc-950/80 to-fuchsia-500/10 p-6 shadow-xl shadow-cyan-900/10",children:(0,s.jsx)("div",{className:"flex flex-wrap items-start gap-4",children:(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[(0,s.jsx)("div",{className:"flex h-11 w-11 items-center justify-center rounded-xl bg-gradient-to-br from-cyan-500/35 to-fuchsia-600/25 ring-1 ring-white/10",children:(0,s.jsx)(D.Z,{className:"h-5 w-5 text-cyan-200"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold tracking-tight text-white",children:n("TikTok 无人直播(单路)","TikTok unmanned (single lane)")}),(0,s.jsx)("p",{className:"mt-0.5 text-xs text-zinc-500",children:n("布局对齐 YouTube 单频道:直播开关 + 源站 + URL_config;无 stream key,输出走 HDMI 硬件链路。","Same layout as YouTube single: controls + URLs; no stream key — HDMI hardware path.")})]})]})})}),(0,s.jsx)("div",{className:"rounded-2xl border border-cyan-500/20 bg-cyan-500/[0.06] p-4 ring-1 ring-white/[0.04]",children:(0,s.jsx)("p",{className:"text-xs leading-relaxed text-cyan-100/90",children:n("HDMI 互斥:后端在「开始 / 重新开始」TikTok 或 obs*.sh(SRS 拉流上屏)时,会自动停止其它正在占用 HDMI 链路的同类进程;与 YouTube 推流互不干扰。","HDMI mutex: starting TikTok or obs*.sh stops other TikTok/OBS HDMI sinks; YouTube RTMP is unaffected.")})}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/10 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-300"}),n("X86 HDMI 采集状态","X86 HDMI capture status")]}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:n("这里直接显示主机是否识别到采集卡和 /dev/video 设备,可用于验证 ARM HDMI 进 X86 的链路。","Shows whether the host sees the capture card and /dev/video nodes for ARM-to-X86 HDMI ingest.")})]}),(0,s.jsx)("span",{className:"rounded-full px-3 py-1 text-[11px] font-semibold ring-1 ".concat(eh?"bg-emerald-500/20 text-emerald-200 ring-emerald-500/30":"bg-rose-500/15 text-rose-200 ring-rose-500/25"),children:eh?n("可推流","Ready"):n("未就绪","Not ready")})]}),(0,s.jsxs)("div",{className:"mt-4 grid gap-3 md:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-4 text-[11px] text-zinc-400",children:[(0,s.jsxs)("p",{children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"device: "}),(0,s.jsx)("span",{className:"font-mono text-zinc-200",children:ep||"—"})]}),(0,s.jsxs)("p",{className:"mt-2",children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"video nodes: "}),(0,s.jsx)("span",{className:"font-mono text-zinc-200",children:((null==g?void 0:g.video_devices)||[]).join(", ")||"—"})]}),(0,s.jsxs)("p",{className:"mt-2",children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"usb matches: "}),(0,s.jsx)("span",{className:"text-zinc-300",children:((null==g?void 0:g.usb_capture_matches)||[]).length||0})]})]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-4 text-[11px] text-zinc-400",children:[(0,s.jsx)("p",{className:"text-zinc-600",children:n("建议 FFmpeg","Suggested FFmpeg")}),(0,s.jsx)("p",{className:"mt-2 break-all font-mono text-zinc-200",children:(null==g?void 0:g.suggested_ffmpeg_cmd)||"—"}),(null==g?void 0:g.suggested_ffmpeg_cmd)?(0,s.jsxs)("button",{type:"button",onClick:()=>m(g.suggested_ffmpeg_cmd||""),className:"mt-3 inline-flex items-center gap-2 rounded-lg bg-cyan-500/15 px-3 py-2 text-xs font-medium text-cyan-100 ring-1 ring-cyan-500/25",children:[(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"}),n("复制命令","Copy command")]}):null]})]}),((null==g?void 0:g.issues)||[]).length?(0,s.jsx)("ul",{className:"mt-4 list-inside list-disc space-y-1 text-[11px] text-amber-200/85",children:((null==g?void 0:g.issues)||[]).map(e=>(0,s.jsx)("li",{children:e},e))}):null]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-amber-500/20 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-amber-200/90",children:[(0,s.jsx)(B.Z,{className:"h-4 w-4"}),(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:n("直播开关","Live control")})]}),(0,s.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:n("TikTok 进程(PM2)","TikTok PM2 process")}),(0,s.jsx)("select",{className:"mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm text-white",value:r,onChange:e=>a(e.target.value),children:w.map(e=>(0,s.jsxs)("option",{value:e.pm2,children:[e.label," (",e.pm2,")"]},e.pm2))}),(0,s.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:n("直播源","Video source")}),(0,s.jsxs)("select",{className:"mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm text-white",value:N,onChange:e=>$(e.target.value),children:[(0,s.jsx)("option",{value:"ffmpeg",hidden:!0,children:"FFmpeg(抖音 / TikTok 等直播间 URL)"}),(0,s.jsx)("option",{value:"replay",hidden:!0,children:n("录播素材(本地上传)","VOD upload")}),(0,s.jsx)("option",{value:"srs",children:n("SRS(OBS 推流)","SRS (OBS)")})]}),"srs"===N?(0,s.jsx)("p",{className:"mt-2 text-[11px] leading-relaxed text-amber-200/85",children:n("此模式不显示 URL_config:请在 OBS 中填写下方 RTMP 推流地址;板端 SRS 拉流上屏仍可能占用 HDMI,与 TikTok 进程互斥规则不变。","URL_config is hidden: set the RTMP URL in OBS. SRS pull-to-HDMI may still mutex with TikTok per server rules.")}):null,(0,s.jsx)("div",{className:"mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3",children:[["start",n("开始直播","Start"),"bg-emerald-500/20 text-emerald-200 ring-emerald-500/30"],["stop",n("停止直播","Stop"),"bg-rose-500/15 text-rose-200 ring-rose-500/25"],["restart",n("重新开始","Restart"),"bg-amber-500/15 text-amber-200 ring-amber-500/25"]].map(e=>{let[t,n,l]=e;return(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>d(t),className:"rounded-xl px-4 py-3 text-sm font-medium ring-1 ".concat(l),children:n},t)})}),(0,s.jsxs)("p",{className:"mt-3 text-center text-[11px] text-zinc-500",children:[n("当前 HDMI 预设(备忘)","HDMI preset (memo)"),":"," ",(0,s.jsx)("span",{className:"font-mono text-cyan-300/90",children:em?n(em.labelZh,em.labelEn):T})]})]}),"replay"===N?(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/25 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(eo.Z,{className:"h-4 w-4 text-violet-300"}),n("录播素材","VOD library")]}),(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,s.jsxs)("label",{className:"inline-flex cursor-pointer items-center gap-2 rounded-xl bg-violet-500/15 px-3 py-2 text-xs font-medium text-violet-100 ring-1 ring-violet-500/30",children:[(0,s.jsx)(ec.Z,{className:"h-3.5 w-3.5"}),(0,s.jsx)("span",{children:n("上传视频","Upload")}),(0,s.jsx)("input",{type:"file",accept:".mp4,.mkv,.ts,.flv,.mov,.m4v,.webm",className:"hidden",onChange:er})]}),(0,s.jsx)("button",{type:"button",disabled:ex||!r,onClick:()=>void ee(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-3 py-2 text-xs text-zinc-300",children:n("刷新列表","Refresh")})]})]}),(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:n("文件保存在服务器 config/tiktok_replay/对应进程目录;点「开始直播」会写入 replayfile 行并启动 PM2 进程。停播请用上方「停止直播」。","Files under config/tiktok_replay/. Go live writes replayfile + starts PM2. Use Stop above to stop.")}),S?(0,s.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:n("加载中…","Loading…")}):0===k.length?(0,s.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:n("暂无文件,请先上传。","No files yet.")}):(0,s.jsx)("ul",{className:"mt-4 space-y-2",children:k.map(e=>(0,s.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 rounded-xl border border-white/10 bg-black/30 px-3 py-2 text-xs text-zinc-300",children:[(0,s.jsx)("span",{className:"min-w-0 flex-1 truncate font-mono",children:e.name}),(0,s.jsxs)("span",{className:"shrink-0 text-zinc-500",children:[(e.size/1048576).toFixed(1)," MB"]}),(0,s.jsxs)("div",{className:"flex shrink-0 flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>void(async()=>{try{await Promise.resolve(u(e.replay_url,e.name))}catch(e){}})(),className:"rounded-lg bg-emerald-500/20 px-2 py-1 text-[11px] text-emerald-100 ring-1 ring-emerald-500/30",children:n("开始直播","Go live")}),(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>d("stop"),className:"rounded-lg bg-rose-500/15 px-2 py-1 text-[11px] text-rose-100 ring-1 ring-rose-500/25",children:n("停播","Stop")}),(0,s.jsxs)("button",{type:"button",disabled:ex,onClick:()=>void ei(e.name),className:"inline-flex items-center gap-1 rounded-lg bg-zinc-700/40 px-2 py-1 text-[11px] text-zinc-200",children:[(0,s.jsx)(ed.Z,{className:"h-3 w-3"}),n("删除","Del")]})]})]},e.name))})]}):null,"srs"===N?(0,s.jsxs)("div",{className:"rounded-2xl border border-emerald-500/25 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:n("SRS / OBS 推流","SRS / OBS ingest")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:n("OBS:设置 → 推流 → 服务选「自定义」,服务器填 RTMP 地址;串流密钥可与 SRS 应用配置一致(默认 live/livestream)。","OBS → Stream → Custom: RTMP URL as server; stream key per SRS app (default live/livestream).")}),(0,s.jsxs)("dl",{className:"mt-4 space-y-3 text-xs",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-500",children:n("RTMP 推流地址(OBS 服务器)","RTMP publish URL")}),(0,s.jsxs)("dd",{className:"mt-1 flex flex-wrap items-center gap-2 font-mono text-emerald-200/90",children:[(0,s.jsx)("span",{className:"break-all",children:b.srs_rtmp_publish||"—"}),b.srs_rtmp_publish?(0,s.jsx)("button",{type:"button",className:"shrink-0 text-cyan-300 hover:text-cyan-200",onClick:()=>m(b.srs_rtmp_publish),children:(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"})}):null]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-500",children:n("HTTP-FLV 预览","HTTP-FLV preview")}),(0,s.jsxs)("dd",{className:"mt-1 flex flex-wrap items-center gap-2 font-mono text-zinc-400",children:[(0,s.jsx)("span",{className:"break-all",children:b.srs_play_flv||b.srs_http||"—"}),b.srs_play_flv||b.srs_http?(0,s.jsx)("button",{type:"button",className:"shrink-0 text-cyan-300 hover:text-cyan-200",onClick:()=>m(b.srs_play_flv||b.srs_http),children:(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"})}):null]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-500",children:n("SRS 控制台","SRS web UI")}),(0,s.jsx)("dd",{className:"mt-1 font-mono text-zinc-400",children:(0,s.jsx)("a",{href:b.srs_http||"#",target:"_blank",rel:"noreferrer",className:"text-cyan-300 hover:underline",children:b.srs_http||"—"})})]})]})]}):null,(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-400"}),n("HDMI 硬件与时序","HDMI timing")]}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:n("点选一路作为现场备忘;与板端 ffmpeg/OBS 采集参数对齐。","Pick a preset as field memo; match capture settings.")}),(0,s.jsx)("div",{className:"mt-4 grid gap-3 md:grid-cols-3",children:ew.map(e=>{let t=L===e.id,l=T===e.id;return(0,s.jsxs)("button",{type:"button",onClick:()=>{M(t?null:e.id),E(e.id)},className:"rounded-2xl border p-4 text-left transition ".concat(l?"border-cyan-500/50 ring-1 ring-cyan-500/20":""," ").concat(t?"border-cyan-500/40 bg-cyan-500/10":"border-white/[0.08] bg-zinc-950/50 hover:border-white/15"),children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-400"}),n(e.labelZh,e.labelEn)]}),(0,s.jsx)("p",{className:"mt-2 font-mono text-[11px] text-zinc-400",children:e.spec}),t?(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:n(e.hintZh,e.hintEn)}):null]},e.id)})}),(0,s.jsxs)("div",{className:"mt-6 rounded-xl border border-white/5 bg-black/25 p-4",children:[(0,s.jsx)("p",{className:"text-xs font-semibold text-zinc-400",children:n("上线前检查清单(本地保存)","Pre-flight checklist (local)")}),(0,s.jsx)("ul",{className:"mt-3 space-y-2",children:[{id:"cable",zh:"HDMI 线材插紧、方向正确(如需转接头确认规格)",en:"HDMI cable seated; adapter specs OK"},{id:"thermal",zh:"长时间推流注意散热,过热会掉帧黑屏",en:"Thermal headroom for long runs"}].map(e=>(0,s.jsxs)("li",{className:"flex items-start gap-2 text-xs text-zinc-400",children:[(0,s.jsx)("input",{type:"checkbox",className:"mt-0.5 rounded border-white/20 bg-black/40",checked:!!V[e.id],onChange:t=>et({...V,[e.id]:t.target.checked})}),(0,s.jsx)("span",{children:n(e.zh,e.en)})]},e.id))}),(0,s.jsx)("label",{className:"mt-4 block text-[11px] text-zinc-500",children:n("HDMI / 走线备忘","HDMI / wiring notes")}),(0,s.jsx)("textarea",{className:"mt-1 min-h-[72px] w-full resize-y rounded-lg border border-white/10 bg-black/40 p-3 text-xs text-zinc-300",value:J,onChange:e=>en(e.target.value),spellCheck:!1,placeholder:n("接口、线长、显示器型号…","Ports, cable length, display model…")})]})]}),"ffmpeg"===N?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:n("直播地址列表 \xb7 URL_config.ini","URL_config.ini")}),(0,s.jsxs)("button",{type:"button",className:"inline-flex items-center gap-1 text-xs text-cyan-300 hover:text-cyan-200",onClick:()=>m(o),children:[(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"}),n("复制全文","Copy all")]})]}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:n("一行一个地址;可勾选自动从服务器刷新,或点「重新读取」手动同步。","One URL per line; enable auto-refresh or reload from server.")}),(0,s.jsx)("div",{className:"mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400",children:(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:Z,onChange:e=>O(e.target.checked)}),n("每 8 秒自动从服务器刷新","Auto-refresh from server every 8s")]})}),H?(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:H}):null,(0,s.jsx)("textarea",{className:"mt-4 min-h-[200px] w-full resize-y rounded-xl border border-white/10 bg-black/50 p-4 font-mono text-xs text-zinc-300",value:o,onChange:e=>{F.current=!0,X(e.target.value)},spellCheck:!1}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>void es(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-300",children:n("重新读取","Reload from server")}),(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>void el(),className:"rounded-xl bg-cyan-500/20 px-4 py-2 text-sm font-medium text-cyan-100 ring-1 ring-cyan-500/30",children:n("保存 URL 配置","Save URL config")})]})]}):null,(0,s.jsx)(ev,{t:n,currentProc:r,fetchJson:h,urlListText:"ffmpeg"===N?o:"",keySuffixUi:"",showKeyRow:!1})]})}var eS=n(5468),e_=n(9397),eC=n(90);let eR="live-hub-youtube-pro-v2",eP="youtube2__",eL=/[^a-zA-Z0-9_.-]+/g,eM=new Set(["youtube","douyin_youtube","tiktok","obs","web"]);function eT(e){return(e||"").trim().replace(eL,"_")}function eU(e,t){let n=eT(e);return!n||eM.has(n)||n===eP?eK(t):n.startsWith(eP)?n:eK(n)}function eE(e){return eU(String(e.pm2Name||""),String(e.id||""))}function eI(e){if(!e||"object"!=typeof e)return null;let t=String(e.id||"").trim();if(!t)return null;let n=String(e.name||"").trim()||t;return{id:t,name:n,streamKeySuffix:"string"==typeof e.streamKeySuffix?e.streamKeySuffix:void 0,streamKey:"string"==typeof e.streamKey?e.streamKey:void 0,urlLines:"string"==typeof e.urlLines?e.urlLines:void 0,pm2Name:eU("string"==typeof e.pm2Name?e.pm2Name:"",t),notes:"string"==typeof e.notes?e.notes:void 0}}function eD(e){if(!e)return[];try{let t=JSON.parse(e);if(!Array.isArray(t))return[];return t.map(e=>eI(e)).filter(e=>null!==e)}catch(e){return[]}}function eA(e){window.localStorage.setItem(eR,JSON.stringify(e))}let eZ=["/hub/youtube_pro_channels","/youtube_pro_channels"];async function eO(e){for(let n of eZ)try{var t;let s=await e(n);return{fetched:!0,channels:(t=s.channels,Array.isArray(t)?t.map(e=>eI(e)).filter(e=>null!==e):[])}}catch(e){}return{fetched:!1,channels:[]}}async function eH(e,t){let n=null;for(let l of eZ)try{var s;let i=await e(l,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channels:t})});if((null===(s=i.neko)||void 0===s?void 0:s.ok)===!1){let e=i.neko.desired?" desired=".concat(i.neko.desired):"",t=i.neko.current?" current=".concat(i.neko.current):"";n=Error("Neko capacity expansion failed:".concat(e).concat(t," ").concat(i.neko.reason||"unknown error").trim());break}return}catch(e){n=e instanceof Error?e:Error(String(e))}throw null!=n?n:Error("youtube_pro_channels sync failed")}function eB(){return"ch_".concat(Date.now().toString(36),"_").concat(Math.random().toString(36).slice(2,7))}function eK(e){return"".concat(eP).concat(eT(e)||"channel")}function eF(e){return/youtube/i.test(e.script)||/youtube/i.test(e.pm2)}function eW(e){return(e.split("/").pop()||e).replace(/\.[^.]+$/,"")}function eY(e){var t;return!!e&&(/youtube/i.test(e.pm2)||/youtube/i.test(null!==(t=e.script)&&void 0!==t?t:""))}function eJ(e,t){let n=((null==t?void 0:t.business_status)||"").trim().toLowerCase();return(null==t?void 0:t.is_pushing)||"streaming"===n?0:eX(null==t?void 0:t.process_status)?1:"youtube"===e.pm2.trim().toLowerCase()?2:"youtube"===eW(e.script).trim().toLowerCase()?3:10}let eG="live-hub-youtube-mode-v1",eV=new Set(["youtube","douyin_youtube","tiktok","obs","web"]);function eq(e){var t,n,s;return{name:e.name,streamKey:null!==(t=e.streamKey)&&void 0!==t?t:"",pm2Name:null!==(n=e.pm2Name)&&void 0!==n?n:eK(e.id),notes:null!==(s=e.notes)&&void 0!==s?s:""}}function eX(e){return/^(online|running)$/i.test((e||"").trim())}function e$(e,t){let n=((null==e?void 0:e.business_status)||"").trim().toLowerCase();return"ready"===n?t("已配置","Ready"):"streaming"===n?t("推流中","Pushing"):"waiting_source"===n?t("等待上游","Waiting source"):"source_live"===n?t("源已开播,转推未起","Source live, relay down"):"monitoring"===n?t("监控中","Monitoring"):"misconfigured"===n?t("密钥异常","Key invalid"):"stale"===n?t("心跳过期","Stale"):"error"===n?t("异常","Error"):eX(null==e?void 0:e.process_status)?t("运行中","Running"):((null==e?void 0:e.process_status)||"").trim()||t("未运行","Idle")}function eQ(e){return e.split(/\r?\n/).map(e=>e.trim()).filter(e=>e&&!e.startsWith("#"))}function e0(e,t){return eQ(e).length>0&&0===eQ(t).length}function e1(e){let{kind:t,busyKind:n,targetPm2:l,busy:i,online:r,label:a,className:o,baseLock:c,onRun:d,notify:x,t:u,compact:m}=e,h=function(e){if(!(null==e?void 0:e.startsWith("proc:")))return null;let t=e.slice(5),n=t.indexOf(":");if(n<=0)return null;let s=t.slice(0,n),l=t.slice(n+1);return l&&["start","stop","restart"].includes(s)?{action:s,pm2:l}:null}(i),p=h&&h.pm2===l,b=null!=n?n:t,g=!!(p&&h.action===b),f=!!(p&&h.action!==b),y="start"===t&&r,w="stop"===t&&!r,N="restart"===t&&!r,j=y||w||N;return(0,s.jsxs)("button",{type:"button",onClick:()=>{if(!g){if(f){x(u("请等待当前操作完成","Wait for the current action to finish"));return}if(y){x(u("已在直播中,无需重复开始","Already live"));return}if(w){x(u("当前未在直播,无法停止","Not live — cannot stop"));return}if(N){x(u("进程未运行时请使用「开始直播」","Use Start when the process is not running"));return}c||d()}},className:"relative overflow-hidden rounded-xl ring-1 transition ".concat(m?"min-h-[2rem] px-3 py-1.5 text-xs font-medium":"min-h-[2.75rem] px-4 py-3 text-sm font-medium"," ").concat(o," ").concat(j||c||g||f?"cursor-not-allowed":""," ").concat(j&&!g?"opacity-45":""," ").concat(f?"opacity-35":""," ").concat(g?"ring-violet-400/40":""),children:[g?(0,s.jsx)("span",{className:"absolute inset-0 flex items-center justify-center bg-black/25 backdrop-blur-[2px]",children:(0,s.jsx)(v.Z,{className:"".concat(m?"h-4 w-4":"h-6 w-6"," animate-spin text-white")})}):null,(0,s.jsxs)("span",{className:"inline-flex items-center justify-center gap-1.5 ".concat(g?"invisible":""),children:[j?(0,s.jsx)(eS.Z,{className:"".concat(m?"h-3 w-3":"h-4 w-4"," shrink-0 opacity-90"),"aria-hidden":!0}):null,a]})]})}function e5(e){var t,n,l,i,r;let{t:a,busy:o,entries:d,currentProc:x,setCurrentProc:u,urlConfig:m,setUrlConfig:h,onRunProcess:p,onSaveUrlConfig:b,fetchJson:g,liveProcesses:f,notify:w,onNavigate:N,quickLinks:j}=e,k=(0,_.useMemo)(()=>d.filter(eF),[d]),z=(0,_.useMemo)(()=>(function(e,t){let n=e.filter(eF),s=n.filter(e=>eF(e)&&e.pm2.trim()===eW(e.script).trim()),l=s.length?[...s]:n.length?[...n]:[...e],i=new Set(l.map(e=>e.pm2.trim()));for(let e of t.filter(eY)){var r,a,o,c;let t=e.pm2.trim();if(!t||i.has(t))continue;let s=(e.business_status||"").trim().toLowerCase();if(!e.is_pushing&&"streaming"!==s&&!eX(e.process_status))continue;let d=n.find(e=>e.pm2.trim()===t);l.push(null!=d?d:{pm2:t,script:null!==(o=null!==(a=e.script)&&void 0!==a?a:null===(r=n[0])||void 0===r?void 0:r.script)&&void 0!==o?o:"youtube.py",label:null!==(c=e.label)&&void 0!==c?c:t}),i.add(t)}return l})(k.length?k:d,f),[d,f,k]),S=(0,_.useMemo)(()=>(function(e,t){if(!e.length)return"";let n=new Map(t.filter(eY).map(e=>[e.pm2.trim(),e])),s=e[0],l=eJ(s,n.get(s.pm2.trim()));for(let t of e.slice(1)){let e=eJ(t,n.get(t.pm2.trim()));e"youtube"===e.pm2.trim().toLowerCase());if(s)return s.pm2;let l=e.find(e=>"youtube"===eW(e.script).trim().toLowerCase());return l?l.pm2:null!==(n=null===(t=e[0])||void 0===t?void 0:t.pm2)&&void 0!==n?n:""}(z),[f,z]),[C,R]=(0,_.useState)("single"),[P,L]=(0,_.useState)([]),[M,T]=(0,_.useState)(""),[U,E]=(0,_.useState)(""),[I,D]=(0,_.useState)({key:"",rtmps:!0,bitrate:"",fastAudio:!1}),[A,O]=(0,_.useState)(null),[H,K]=(0,_.useState)(!1),[F,W]=(0,_.useState)(""),[Y,J]=(0,_.useState)(!0),[G,V]=(0,_.useState)(!1),[q,X]=(0,_.useState)(!1),[$,Q]=(0,_.useState)(null),[ee,et]=(0,_.useState)({}),[en,es]=(0,_.useState)(!1),[el,ei]=(0,_.useState)(null),[er,ea]=(0,_.useState)(0),eo=(0,_.useRef)(!1),ec=(0,_.useRef)(m),ef=(0,_.useRef)(F),ey=(0,_.useRef)([]),ew=(0,_.useRef)(x),eN=(0,_.useRef)(0),ej=(0,_.useRef)(0),ek=(0,_.useCallback)(e=>{ec.current=e,h(e)},[h]),ez=(0,_.useCallback)(e=>{ef.current=e,W(e)},[]);(0,_.useEffect)(()=>{eo.current=!1},[x]),(0,_.useEffect)(()=>{ew.current=x},[x]),(0,_.useEffect)(()=>{ec.current=m},[m]),(0,_.useEffect)(()=>{ef.current=F},[F]),(0,_.useEffect)(()=>{ey.current=P},[P]);let eS=(0,_.useCallback)((e,t)=>{e&&L(n=>{let s=!1,l=n.map(n=>{var l;return n.id!==e||(null!==(l=n.urlLines)&&void 0!==l?l:"")===t?n:(s=!0,{...n,urlLines:t})});return s?(ey.current=l,eA(l),l):n})},[]),eP=(0,_.useCallback)(async()=>{let e=ew.current.trim();if(!e)return;let t=++eN.current;try{var n,s,l;let i=new URLSearchParams({process:e,_ts:String(Date.now())}),r=await g("/get_url_config?".concat(i));if(t!==eN.current||e!==ew.current.trim())return;let a=null!==(n=r.content)&&void 0!==n?n:"";if(eo.current)return;if("single"===C)ek(a);else{let e=null!==(l=null===(s=ey.current.find(e=>e.id===M))||void 0===s?void 0:s.urlLines)&&void 0!==l?l:"";if(e0(e,a)){ez(e);return}ez(a),eS(M,a)}}catch(e){}},[M,ez,ek,g,C,eS]);(0,_.useEffect)(()=>{if(!x||!Y)return;let e=window.setInterval(()=>{eo.current||eP()},8e3);return()=>clearInterval(e)},[x,Y,eP]);let eL=async()=>{let e=ew.current.trim();if(!e)return;V(!0),Q(null),eo.current=!1;let t=++eN.current;try{var n,s,l;let i=new URLSearchParams({process:e,_ts:String(Date.now())}),r=await g("/get_url_config?".concat(i));if(t!==eN.current||e!==ew.current.trim())return;let o=null!==(n=r.content)&&void 0!==n?n:"";if(eo.current){Q(a("检测到本地未保存修改,已保留当前草稿","Kept the local unsaved draft"));return}if("single"===C)ek(o);else{let e=null!==(l=null===(s=ey.current.find(e=>e.id===M))||void 0===s?void 0:s.urlLines)&&void 0!==l?l:"";if(e0(e,o)){ez(e),Q(a("服务器暂无已保存 URL,已保留本地草稿","Server has no saved URLs, kept the local draft"));return}ez(o),eS(M,o)}Q(a("已从服务器读取 URL_config","Reloaded URL_config from server"))}catch(n){if(t!==eN.current||e!==ew.current.trim())return;Q(n.message)}finally{t===eN.current&&V(!1)}};(0,_.useEffect)(()=>{try{let e=window.localStorage.getItem(eG);("pro"===e||"single"===e)&&R(e)}catch(e){}},[]),(0,_.useEffect)(()=>{let e=!1;return(async()=>{try{let t=await eO(g);if(t.fetched&&t.channels.length&&!e){ey.current=t.channels,L(t.channels),eA(t.channels);return}}catch(e){}if(e)return;let t=function(){let e=window.localStorage.getItem(eR);if(!e&&(e=window.localStorage.getItem("live-hub-youtube-pro-v1"))){let t=eD(e);if(t.length)return window.localStorage.setItem(eR,JSON.stringify(t)),t}return eD(e)}(),n=t.length>0?t:(()=>{let e=eB();return[{id:e,name:"线路 1",streamKey:"",urlLines:"",pm2Name:eK(e),notes:""}]})();ey.current=n,L(n),t.length||eA(n)})(),()=>{e=!0}},[g]),(0,_.useEffect)(()=>{if(!P.length){M&&T("");return}M&&P.some(e=>e.id===M)||T(P[0].id)},[P,M]);let eM=(0,_.useCallback)(e=>f.find(t=>t.pm2===e),[f]),eU=(0,_.useCallback)(e=>{var t;return null===(t=eM(e))||void 0===t?void 0:t.process_status},[eM]),eI=eM(x),eZ=(0,_.useMemo)(()=>{var e,t;return!!x&&(/youtube/i.test(x)||/youtube/i.test(null!==(e=null==eI?void 0:eI.script)&&void 0!==e?e:"")||/youtube/i.test(null!==(t=null==eI?void 0:eI.label)&&void 0!==t?t:""))},[x,eI]);(0,_.useEffect)(()=>{"single"!==C||!S||x&&eZ||u(S)},[x,eZ,C,S,u]);let e5=(0,_.useCallback)(e=>{ey.current=e,L(e),eA(e)},[]),e2=(0,_.useCallback)(async e=>{await eH(g,e)},[g]),e3=(0,_.useCallback)(e=>{e5(e),e2(e).catch(e=>{w("".concat(a("多频道列表未同步到服务器","Channel list not saved on server"),": ").concat(e.message))})},[e5,w,e2,a]),e4=P.find(e=>e.id===M)||P[0],e6=(0,_.useMemo)(()=>{var e;return e4?null!==(e=ee[e4.id])&&void 0!==e?e:eq(e4):null},[e4,ee]);(0,_.useEffect)(()=>{e4&&et(e=>e[e4.id]?e:{...e,[e4.id]:eq(e4)})},[e4]),(0,_.useEffect)(()=>{ei(null)},[M]);let e8=(0,_.useCallback)((e,t)=>{e4&&(et(n=>{var s;return{...n,[e4.id]:{...null!==(s=n[e4.id])&&void 0!==s?s:eq(e4),[e]:t}}}),ei(null))},[e4]),e9=e4?eE(e4):"",e7=e4&&e6?eE({id:e4.id,pm2Name:e6.pm2Name}):"",te=!!e4&&!!e6&&e7!==e9,tt=(0,_.useMemo)(()=>{if(!e4||!e6)return{ok:!1,message:a("请选择线路","Pick a lane"),normalizedName:"",normalizedPm2:"",normalizedStreamKey:"",normalizedNotes:""};let e=e6.name.trim()||"".concat(a("线路","Ch")," ").concat(P.findIndex(e=>e.id===e4.id)+1),t=eE({id:e4.id,pm2Name:e6.pm2Name});return t?eV.has(t)?{ok:!1,message:a("该进程名保留给系统模块,请换一个","This PM2 name is reserved"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e6.streamKey.trim(),normalizedNotes:e6.notes.trim()}:P.find(e=>e.id!==e4.id&&eE(e)===t)?{ok:!1,message:a("该进程名已被其它线路占用","Another lane already uses this PM2 name"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e6.streamKey.trim(),normalizedNotes:e6.notes.trim()}:{ok:!0,message:"",normalizedName:e,normalizedPm2:t,normalizedStreamKey:e6.streamKey.trim(),normalizedNotes:e6.notes.trim()}:{ok:!1,message:a("进程名不能为空","PM2 name is required"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e6.streamKey.trim(),normalizedNotes:e6.notes.trim()}},[e4,e6,P,a]),tn=(0,_.useMemo)(()=>{if(!e4||!e6)return!1;let e=eq(e4);return e6.name!==e.name||e6.streamKey!==e.streamKey||eT(e6.pm2Name)!==eT(e.pm2Name)||e6.notes!==e.notes},[e4,e6]),ts=(0,_.useCallback)(e=>{var t,n,s;if("single"===e&&"pro"===C&&e4){let e=ef.current;e!==(null!==(t=e4.urlLines)&&void 0!==t?t:"").trim()&&e3(P.map(t=>t.id===e4.id?{...t,urlLines:e}:t))}if("pro"===e&&P.length){let e=P[0],t=ec.current.trim(),l=eE(e),i=[{...e,streamKey:I.key.trim()||e.streamKey||"",urlLines:t||e.urlLines||"",pm2Name:l},...P.slice(1)];e3(i);let r=null!==(n=i.find(e=>e.id===M))&&void 0!==n?n:i[0];ez((null!==(s=null==r?void 0:r.urlLines)&&void 0!==s?s:"").trim()||t)}R(e);try{window.localStorage.setItem(eG,e)}catch(e){}},[C,e4,P,ez,I.key,M,e3]),tl=(0,_.useCallback)(e=>{var t,n;let s=ef.current;e4&&"pro"===C&&s!==(null!==(t=e4.urlLines)&&void 0!==t?t:"").trim()&&e3(P.map(e=>e.id===e4.id?{...e,urlLines:s}:e)),ez((null!==(n=e.urlLines)&&void 0!==n?n:"").trim()),T(e.id),u(eE(e))},[e4,ez,C,P,u,e3]);(0,_.useEffect)(()=>{if("pro"!==C||!M)return;let e=P.find(e=>e.id===M);e&&u(eE(e))},[C,M,P,u]);let ti=(0,_.useCallback)(async()=>{let e=ew.current.trim();if(!e)return;let t=++ej.current;K(!0),O(null);try{var n;let s=new URLSearchParams({process:e,_ts:String(Date.now())}),l=await g("/get_config?".concat(s));if(t!==ej.current||e!==ew.current.trim())return;let i=null!==(n=l.content)&&void 0!==n?n:"";E(i),D(ep(i))}catch(n){if(t!==ej.current||e!==ew.current.trim())return;O(n.message)}finally{t===ej.current&&K(!1)}},[g]);(0,_.useEffect)(()=>{x&&(eP(),ti(),ea(e=>e+1))},[M,x,ti,C,eP]);let tr=(0,_.useCallback)(async()=>{var e;if(!e4||!e6)throw Error(a("请选择线路","Pick a lane"));if(!tt.ok)throw Error(tt.message);let t=ef.current,n=P.map(e=>e.id===e4.id?{...e,name:tt.normalizedName,streamKey:tt.normalizedStreamKey,pm2Name:tt.normalizedPm2,notes:tt.normalizedNotes,urlLines:t}:e);return e5(n),await e2(n),et(e=>({...e,[e4.id]:{name:tt.normalizedName,streamKey:tt.normalizedStreamKey,pm2Name:tt.normalizedPm2,notes:tt.normalizedNotes}})),{next:n,savedLane:null!==(e=n.find(e=>e.id===e4.id))&&void 0!==e?e:{...e4,name:tt.normalizedName,streamKey:tt.normalizedStreamKey,pm2Name:tt.normalizedPm2,notes:tt.normalizedNotes,urlLines:t},pm2:tt.normalizedPm2}},[e4,e6,tt,e5,P,e2,a]),ta=(0,_.useCallback)(async()=>{if(e4){es(!0),ei(null);try{let e=await tr();u(e.pm2),ei(a("线路设置已保存","Lane settings saved"))}catch(t){let e=t.message;ei(e),w(e)}finally{es(!1)}}},[e4,w,tr,u,a]),to=async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ew.current,n=t.trim();if(!n){O(a("请选择进程","Pick a process"));return}K(!0),O(null);try{let t=new URLSearchParams({process:n});await g("/save_config?".concat(t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:e})}),E(e),O(a("youtube.ini 已保存","youtube.ini saved"))}catch(e){O(e.message)}finally{K(!1)}},tc=async()=>{let e=eg(I);await to(e)},td=async()=>{K(!0),O(null);try{var e,t;let n=U||eg(I),s=await g("/config_optimize",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:"app-config",path:(t=ew.current,"youtube.".concat(t.replace(/[^a-zA-Z0-9_.-]/g,"_"),".ini")),content:n,action:"youtube_balanced_preset"})}),l=null!==(e=s.content)&&void 0!==e?e:n;E(l),D(ep(l)),O(s.message||a("已应用 YouTube 预设","Applied YouTube preset"))}catch(e){O(e.message)}finally{K(!1)}},tx=(0,_.useMemo)(()=>{var e,t;if("single"===C)return em("key = ".concat(I.key));let n=null!==(t=null!==(e=null==e6?void 0:e6.streamKey)&&void 0!==e?e:null==e4?void 0:e4.streamKey)&&void 0!==t?t:"";return em("key = ".concat(n))},[C,I.key,null==e4?void 0:e4.streamKey,null==e6?void 0:e6.streamKey]),tu=async()=>{if(e4)try{es(!0),ei(null),eN.current+=1;let e=ef.current,t=await tr();u(t.pm2),await Promise.resolve(b(e,t.pm2)),eo.current=!1,ei(a("线路与地址已保存","Lane settings and URLs saved"))}catch(t){let e=t instanceof Error?t.message:String(t);ei(e),w(e)}finally{es(!1)}},tm=async()=>{let e=ew.current.trim();if(!e){w(a("请选择进程","Pick a process"));return}try{eN.current+=1,await Promise.resolve(b(ec.current,e)),eo.current=!1}catch(e){}},th=async()=>{let e="single"===C?ec.current:ef.current;X(!0),Q(null);try{var t;let n=await g("/config_optimize",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:"app-config",path:eb(ew.current),content:e,action:"dedupe_urls"})}),s=null!==(t=n.content)&&void 0!==t?t:e;"single"===C?ek(s):ez(s),eo.current=!0,Q(n.message||a("已去重当前 URL 列表","Deduplicated current URL list"))}catch(e){Q(e.message)}finally{X(!1)}},tp=async()=>{if(!e4||!e6)return;let e=ep(U||eg(I)),t=eg({key:e6.streamKey.trim(),rtmps:e.rtmps,bitrate:e.bitrate,fastAudio:e.fastAudio});es(!0),ei(null);try{let e=await tr();u(e.pm2),await to(t,e.pm2),ei(a("线路设置与 youtube.ini 已保存","Lane settings and youtube.ini saved"))}catch(t){let e=t.message;ei(e),w(e)}finally{es(!1)}},tb="single"===C?m:F,tg=(0,_.useMemo)(()=>eQ(tb).length,[tb]),tf=(0,_.useMemo)(()=>eh(tb).length,[tb]),tv=(0,_.useMemo)(()=>(0,eC.O0)(j),[j]),ty=(0,_.useMemo)(()=>(0,eC.U_)(tv,"pro"===C&&e4?P.findIndex(e=>e.id===e4.id):0),[e4,P,C,tv]),tw=ty.link?(0,ex.p)(ty.link.url):(0,ex.p)("http://live.local:9200/"),tN=(0,_.useMemo)(()=>(0,eC.Tc)(tv),[tv]),tj=(0,_.useMemo)(()=>{var e;return[null===(e=ty.link)||void 0===e?void 0:e.url,null==j?void 0:j.chromium_remote_debug,null==j?void 0:j.srs_api].filter(e=>!!e)},[j,null===(t=ty.link)||void 0===t?void 0:t.url]),tk=(0,_.useCallback)(async e=>{let t=e4?eE(e4):"";return e4&&e===t?await tr():(e5(P),await e2(P),{next:P,savedLane:null!=e4?e4:null,pm2:e})},[e4,e5,P,tr,e2]),tz=(0,_.useCallback)(async(e,t)=>{let n=!!e4&&eE(e4)===t;if("stop"!==e){var s,l;let e=P,n=t;try{let s=await tk(t);e=s.next,n=s.pm2}catch(e){w("".concat(a("当前线路保存失败","Failed to save the active lane"),": ").concat(e.message));return}let i=e.find(e=>eE(e)===n),r=null!==(s=null==i?void 0:i.urlLines)&&void 0!==s?s:"";if(!(null!==(l=null==i?void 0:i.streamKey)&&void 0!==l?l:"").trim()){w(a("请先填写当前线路的推流密钥","Fill the stream key before starting"));return}if(!eQ(r).length){w(a("请先填写当前线路的直播地址","Fill the source URLs before starting"));return}t=n}n&&u(t),p(e,t)},[e4,P,tk,w,p,u,a]),tS=!!o||H||G||q||en,t_=eX(eU(x)),tC=(0,s.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400",children:[(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:Y,onChange:e=>J(e.target.checked)}),a("每 8 秒自动从服务器刷新","Auto-refresh from server every 8s")]}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void eL(),className:"rounded-lg border border-white/10 px-3 py-1.5 text-zinc-200 hover:bg-white/5",children:a("手动重新读取","Reload from server")}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void th(),className:"rounded-lg border border-cyan-500/20 bg-cyan-500/10 px-3 py-1.5 text-cyan-100 hover:bg-cyan-500/15",children:q?a("去重中...","Deduplicating..."):a("智能去重","Deduplicate")})]});return(0,s.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6",children:[N?(0,s.jsx)(eu,{t:a,title:a("YouTube 转播链路","YouTube relay chain"),subtitle:a("与「网络」页相同风格的链路示意:代理 → 编码推流 → 浏览器侧操作工作室。","Same visual language as Network: proxy → encode → browser studio."),onNavigate:N,steps:[{label:"ShellCrash",sub:a("透明代理","Proxy"),gradient:"from-violet-500 to-fuchsia-500",target:"network"},{label:"FFmpeg",sub:a("推流 / 转码","Stream"),gradient:"from-cyan-400 to-blue-500",target:"live_youtube"},{label:"Neko",sub:ty.link?"".concat(a("Chromium 工作室","Chromium studio")," \xb7 ").concat(ty.link.label):a("Chromium 工作室","Chromium studio"),gradient:"from-emerald-400 to-teal-500",openUrl:tw}]}):null,(0,s.jsx)("div",{className:"rounded-2xl border border-violet-500/25 bg-gradient-to-br from-violet-500/[0.12] via-zinc-950/80 to-cyan-500/5 p-6 shadow-xl shadow-violet-900/10",children:(0,s.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[(0,s.jsx)("div",{className:"flex h-11 w-11 items-center justify-center rounded-xl bg-gradient-to-br from-red-500/30 to-violet-600/30 ring-1 ring-white/10",children:(0,s.jsx)(c.Z,{className:"h-5 w-5 text-red-200"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold tracking-tight text-white",children:a("YouTube 无人直播","YouTube unmanned live")}),(0,s.jsx)("p",{className:"mt-0.5 text-xs text-zinc-500",children:a("单路一条流;多路时每条线路独立保存自己的密钥、URL 列表和 PM2 任务。填好后保存,再点「开始」。Neko 浏览器仅作辅助工作室,不再阻塞推流。","Single lane or multi-lane: every lane keeps its own key, URL list, and PM2 task. Save, then Start. Neko is optional browser tooling and no longer blocks streaming.")})]})]}),(0,s.jsxs)("div",{className:"flex rounded-xl border border-white/10 bg-black/30 p-1 ".concat(""),"aria-hidden":!1,children:[(0,s.jsx)("button",{type:"button",onClick:()=>ts("single"),className:"rounded-lg px-4 py-2 text-xs font-medium transition ".concat("single"===C?"bg-violet-500/25 text-white":"text-zinc-500 hover:text-zinc-300"),children:a("单频道","Single")}),(0,s.jsx)("button",{type:"button",onClick:()=>ts("pro"),className:"rounded-lg px-4 py-2 text-xs font-medium transition ".concat("pro"===C?"bg-violet-500/25 text-white":"text-zinc-500 hover:text-zinc-300"),children:a("多频道 Pro","Multi Pro")})]})]})}),tj.length?(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[ty.link?(0,s.jsx)("a",{href:tw,target:"_blank",rel:"noreferrer",className:"rounded-lg border border-emerald-500/20 bg-emerald-500/10 px-3 py-2 text-xs text-emerald-100 ring-1 ring-emerald-500/20",children:a("打开当前线路 Neko 工作室","Open lane Neko studio")}):null,tv.length>1?(0,s.jsx)("div",{className:"flex flex-wrap gap-2",children:tv.map(e=>{var t;return(0,s.jsxs)("a",{href:(0,ex.p)(e.url),target:"_blank",rel:"noreferrer",className:"rounded-lg border px-3 py-2 text-xs ring-1 ".concat((null===(t=ty.link)||void 0===t?void 0:t.id)===e.id?"border-emerald-400/30 bg-emerald-500/15 text-emerald-50 ring-emerald-400/25":"border-white/10 bg-white/5 text-zinc-200 ring-white/10"),children:[e.label,e.port?" :".concat(e.port):""]},e.key)})}):null,(null==j?void 0:j.chromium_remote_debug)?(0,s.jsx)("a",{href:(0,ex.p)(j.chromium_remote_debug),target:"_blank",rel:"noreferrer",className:"rounded-lg border border-cyan-500/20 bg-cyan-500/10 px-3 py-2 text-xs text-cyan-100 ring-1 ring-cyan-500/20",children:a("打开 Chromium 调试","Open Chromium debug")}):null,(null==j?void 0:j.srs_api)?(0,s.jsx)("a",{href:(0,ex.p)(j.srs_api),target:"_blank",rel:"noreferrer",className:"rounded-lg border border-violet-500/20 bg-violet-500/10 px-3 py-2 text-xs text-violet-100 ring-1 ring-violet-500/20",children:a("打开 SRS API","Open SRS API")}):null]}):null,(0,s.jsxs)("div",{className:"rounded-2xl border border-amber-500/20 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-amber-200/90",children:[(0,s.jsx)(B.Z,{className:"h-4 w-4"}),(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播开关","Live control")})]}),"single"===C?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:a("转播任务","Relay task")}),(0,s.jsxs)("select",{className:"mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm text-white",value:x,onChange:e=>{let t=e.target.value;ew.current=t,u(t)},children:[x&&!z.some(e=>e.pm2===x)?(0,s.jsxs)("option",{value:x,children:[x,eI?" (".concat(e$(eI,a),")"):""]}):null,z.map(e=>(0,s.jsxs)("option",{value:e.pm2,children:[function(e,t){let n=eW(e.script).toLowerCase();return n.startsWith("douyin_youtube")?t("抖音→YouTube","Douyin → YouTube"):n.startsWith("youtube")?t("YouTube","YouTube"):e.label}(e,a)," (",e.pm2,")"]},e.pm2))]}),(0,s.jsxs)("div",{className:"mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3",children:[(0,s.jsx)(e1,{kind:"start",targetPm2:x,busy:o,online:t_,label:a("开始直播","Start"),className:"bg-emerald-500/20 text-emerald-200 ring-emerald-500/30",baseLock:!1,onRun:()=>p("start",x),notify:w,t:a}),(0,s.jsx)(e1,{kind:"stop",targetPm2:x,busy:o,online:t_,label:a("停止直播","Stop"),className:"bg-rose-500/15 text-rose-200 ring-rose-500/25",baseLock:!1,onRun:()=>p("stop",x),notify:w,t:a}),(0,s.jsx)(e1,{kind:"restart",targetPm2:x,busy:o,online:t_,label:a("重新开始","Restart"),className:"bg-amber-500/15 text-amber-200 ring-amber-500/25",baseLock:!1,onRun:()=>p("restart",x),notify:w,t:a})]}),(0,s.jsxs)("p",{className:"mt-3 text-center text-xs text-zinc-400",children:[a("当前状态","Current state"),": ",e$(eI,a)]}),(0,s.jsxs)("p",{className:"mt-3 text-center font-mono text-[11px] text-zinc-600",children:["key ",a("尾码","suffix"),": ",tx||"—"]})]}):(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)("div",{className:"mt-4 rounded-xl border border-cyan-500/25 bg-gradient-to-br from-cyan-500/[0.1] via-zinc-950/50 to-violet-500/[0.06] p-4 ring-1 ring-white/[0.04]",children:[(0,s.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-cyan-200/90",children:a("Pro 转播实况","Pro relay status")}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:a("对齐桌面端:每路独立 URL / youtube 配置文件;点左侧信息切换编辑,右侧控制进程。","Per-lane config files like desktop; click row info to edit, use right-side controls for PM2.")}),tN?(0,s.jsxs)("p",{className:"mt-2 text-[11px] text-zinc-500",children:[a("Neko 实例","Neko instances"),": ",tN]}):null,(0,s.jsx)("div",{className:"mt-3 max-h-[min(24rem,55vh)] space-y-2 overflow-y-auto pr-1",children:P.map(e=>{var t,n,l;let i=eE(e),r=eM(i),c=eU(i),d=eQ((null!==(t=e.urlLines)&&void 0!==t?t:"").trim()),x=eh((null!==(n=e.urlLines)&&void 0!==n?n:"").trim()),u=x[0],m=em("key = ".concat(null!==(l=e.streamKey)&&void 0!==l?l:"")),h=M===e.id,p=eX(c),b=P.findIndex(t=>t.id===e.id),g=(0,eC.U_)(tv,b).link;return(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2 rounded-lg border px-3 py-2.5 text-left text-xs transition sm:flex-nowrap ".concat(h?"border-violet-500/45 bg-violet-500/[0.1]":"border-white/10 bg-black/30 hover:border-white/18"),children:[(0,s.jsxs)("button",{type:"button",className:"min-w-0 flex-1 text-left",onClick:()=>{ew.current=eE(e),tl(e)},children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,s.jsx)("span",{className:"font-medium text-zinc-100",children:e.name}),(0,s.jsx)("span",{className:"shrink-0 rounded-md px-2 py-0.5 text-[10px] font-medium ring-1 ".concat(function(e){let t=((null==e?void 0:e.business_status)||"").trim().toLowerCase();return"ready"===t?"bg-sky-500/15 text-sky-100 ring-sky-500/25":"streaming"===t?"bg-emerald-500/15 text-emerald-200 ring-emerald-500/30":"waiting_source"===t||"monitoring"===t?"bg-amber-500/15 text-amber-100 ring-amber-500/25":"source_live"===t?"bg-sky-500/15 text-sky-100 ring-sky-500/25":"misconfigured"===t||"error"===t||"stale"===t?"bg-rose-500/15 text-rose-100 ring-rose-500/25":eX(null==e?void 0:e.process_status)?"bg-emerald-500/15 text-emerald-200 ring-emerald-500/30":"bg-zinc-600/20 text-zinc-400 ring-zinc-500/25"}(r)),children:e$(r,a)}),g?(0,s.jsx)("span",{className:"shrink-0 rounded-md bg-emerald-500/15 px-2 py-0.5 text-[10px] font-medium text-emerald-100 ring-1 ring-emerald-500/25",children:g.label}):null]}),(0,s.jsxs)("div",{className:"mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 font-mono text-[10px] text-zinc-500",children:[(0,s.jsxs)("span",{children:["key …",m||"—"]}),(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,s.jsx)("span",{className:"truncate",title:i,children:i}),(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,s.jsxs)("span",{children:["URL ",d.length]}),(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,s.jsxs)("span",{children:["DY ",x.length]})]}),u?(0,s.jsx)("a",{href:u,target:"_blank",rel:"noreferrer",className:"mt-1 block max-w-full truncate text-cyan-300/90 underline-offset-2 hover:underline",onClick:e=>e.stopPropagation(),title:u,children:u.replace(/^https?:\/\//,"")}):(0,s.jsx)("span",{className:"mt-1 block text-zinc-600",children:"—"})]}),(0,s.jsxs)("div",{className:"flex w-full shrink-0 flex-wrap items-center justify-end gap-1.5 sm:w-auto",onClick:e=>e.stopPropagation(),onKeyDown:e=>e.stopPropagation(),children:[(0,s.jsx)(e1,{kind:"start",targetPm2:i,busy:o,online:p,label:a("开始","Start"),className:"rounded-lg bg-emerald-500/20 text-emerald-100 ring-emerald-500/30",baseLock:!1,onRun:()=>void tz("start",i),notify:w,t:a,compact:!0}),(0,s.jsx)(e1,{kind:"stop",targetPm2:i,busy:o,online:p,label:a("停止","Stop"),className:"rounded-lg bg-rose-500/15 text-rose-100 ring-rose-500/25",baseLock:!1,onRun:()=>void tz("stop",i),notify:w,t:a,compact:!0}),(0,s.jsx)(e1,{kind:"restart",targetPm2:i,busy:o,online:p,label:a("重新开始","Restart"),className:"rounded-lg bg-amber-500/15 text-amber-100 ring-amber-500/25",baseLock:!1,onRun:()=>void tz("restart",i),notify:w,t:a,compact:!0}),g?(0,s.jsxs)("button",{type:"button",onClick:()=>{window.open((0,ex.p)(g.url),"_blank","noopener,noreferrer")},className:"inline-flex min-h-[2rem] items-center justify-center rounded-lg border border-emerald-500/25 bg-emerald-500/10 px-2.5 py-1.5 text-emerald-100 ring-1 ring-emerald-500/20 transition hover:bg-emerald-500/20",title:"".concat(a("打开该线路 Neko 工作室","Open this lane's Neko studio")," \xb7 ").concat(g.label).concat(g.port?" :".concat(g.port):""),"aria-label":"".concat(a("打开该线路 Neko 工作室","Open this lane's Neko studio")," \xb7 ").concat(g.label),children:[(0,s.jsx)("span",{className:"sr-only",children:a("打开该线路 Neko 工作室","Open this lane's Neko studio")}),(0,s.jsx)("span",{"aria-hidden":!0,className:"text-sm leading-none",children:"\uD83D\uDC31"}),(0,s.jsx)(Z.Z,{className:"ml-1 h-3.5 w-3.5 shrink-0","aria-hidden":!0})]}):null]})]},e.id)})})]})})]}),"single"===C?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("YouTube 相关设置","YouTube settings")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:a("串流参数写进 youtube.ini,无需 Google 登录。","Stream settings go to youtube.ini — no Google login.")}),(0,s.jsxs)("div",{className:"mt-4 space-y-3",children:[(0,s.jsx)("label",{className:"block text-xs text-zinc-400",children:a("串流密钥","Stream key")}),(0,s.jsx)("input",{className:"w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm font-mono text-zinc-200",spellCheck:!1,autoComplete:"off",value:I.key,onChange:e=>D(t=>({...t,key:e.target.value})),placeholder:"xxxx-xxxx-xxxx-xxxx-xxxx"}),(0,s.jsxs)("div",{className:"grid gap-3 sm:grid-cols-3",children:[(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-zinc-400",children:["RTMPS",(0,s.jsxs)("select",{className:"rounded-lg border border-white/10 bg-black/40 px-3 py-2 text-sm text-white",value:I.rtmps?"1":"0",onChange:e=>D(t=>({...t,rtmps:"1"===e.target.value})),children:[(0,s.jsx)("option",{value:"1",children:a("是(默认)","Yes")}),(0,s.jsx)("option",{value:"0",children:a("否 → RTMP","No")})]})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-zinc-400",children:[a("比特率 kbps","Bitrate kbps"),(0,s.jsx)("input",{className:"rounded-lg border border-white/10 bg-black/40 px-3 py-2 font-mono text-sm",value:I.bitrate,onChange:e=>D(t=>({...t,bitrate:e.target.value})),placeholder:"4000"})]}),(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 pt-6 text-xs text-zinc-300",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:I.fastAudio,onChange:e=>D(t=>({...t,fastAudio:e.target.checked}))}),"fast_audio(",a("轻量音频","lighter audio"),")"]})]})]}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsxs)("button",{type:"button",disabled:tS,onClick:()=>void ti(),className:"inline-flex items-center gap-2 rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-200",children:[(0,s.jsx)(y.Z,{className:"h-3.5 w-3.5 ".concat(H?"animate-spin":"")}),a("重新读取","Reload")]}),(0,s.jsxs)("button",{type:"button",disabled:tS,onClick:()=>void tc(),className:"inline-flex items-center gap-2 rounded-xl bg-violet-500/25 px-4 py-2 text-sm font-medium text-violet-100 ring-1 ring-violet-500/35",children:[H?(0,s.jsx)(v.Z,{className:"h-4 w-4 animate-spin"}):null,a("保存 youtube.ini","Save youtube.ini")]}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void td(),className:"rounded-xl border border-cyan-500/20 bg-cyan-500/10 px-4 py-2 text-sm text-cyan-100",children:a("平衡预设","Balanced preset")}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>{D(ep(U)),O(a("已从下方原文同步到表单","Synced from raw"))},className:"rounded-xl border border-white/10 px-4 py-2 text-sm text-zinc-400",children:a("从原文同步表单","Parse raw")})]}),(0,s.jsxs)("details",{className:"mt-4 rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,s.jsx)("summary",{className:"cursor-pointer text-xs text-zinc-500",children:a("高级:youtube.ini 原文","Raw youtube.ini")}),(0,s.jsx)("textarea",{className:"mt-2 h-36 w-full resize-y rounded-lg border border-white/10 bg-black/50 p-3 font-mono text-[11px] text-zinc-400",value:U,onChange:e=>E(e.target.value),spellCheck:!1}),(0,s.jsx)("button",{type:"button",disabled:tS,className:"mt-2 rounded-lg bg-cyan-500/15 px-3 py-1.5 text-xs text-cyan-200",onClick:()=>void to(U),children:a("保存原文","Save raw")})]}),A?(0,s.jsx)("p",{className:"mt-2 font-mono text-xs text-zinc-500",children:A}):null]}):(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("h3",{className:"text-sm font-semibold text-white",children:[a("当前线路","Current lane"),e4?(0,s.jsxs)("span",{className:"ml-2 font-normal text-zinc-400",children:["\xb7 ",e4.name]}):null,tn?(0,s.jsx)("span",{className:"ml-2 rounded-md bg-amber-500/15 px-2 py-0.5 text-[10px] font-medium text-amber-100 ring-1 ring-amber-500/25",children:a("有未保存修改","Unsaved")}):null]}),e4?(0,s.jsxs)("p",{className:"mt-0.5 font-mono text-[11px] text-zinc-500",children:["PM2: ",e9,te?" → ".concat(e7):""," \xb7 ","key ",tx||"—"]}):null]}),(0,s.jsxs)("button",{type:"button",disabled:tS,className:"inline-flex items-center gap-1 rounded-lg bg-violet-500/20 px-3 py-1.5 text-xs text-violet-100 ring-1 ring-violet-500/30",onClick:()=>{let e=eB(),t={id:e,name:"".concat(a("线路","Ch")," ").concat(P.length+1),streamKey:"",urlLines:"",pm2Name:eK(e),notes:""};et(n=>({...n,[e]:eq(t)})),e3([...P,t]),T(e),ew.current=eE(t),u(ew.current),ez("")},children:[(0,s.jsx)(e_.Z,{className:"h-3.5 w-3.5"}),a("新增线路","Add lane")]})]}),e4?(0,s.jsxs)("div",{className:"mt-4 space-y-3 border-t border-white/5 pt-4",children:[(0,s.jsx)("input",{className:"w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-sm",value:null!==(n=null==e6?void 0:e6.name)&&void 0!==n?n:"",onChange:e=>e8("name",e.target.value),placeholder:a("线路名称","Lane name")}),(0,s.jsx)("label",{className:"block text-xs text-zinc-500",children:a("串流密钥","Stream key")}),(0,s.jsx)("input",{className:"w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 font-mono text-sm",spellCheck:!1,value:null!==(l=null==e6?void 0:e6.streamKey)&&void 0!==l?l:"",onChange:e=>e8("streamKey",e.target.value),placeholder:"xxxx-xxxx… / rtmp(s)://…"}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void ta(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-100",children:en?a("保存中...","Saving..."):a("保存线路设置","Save lane")}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void tp(),className:"rounded-xl bg-violet-500/25 px-4 py-2 text-sm font-medium text-violet-100 ring-1 ring-violet-500/35",children:a("写入 youtube.ini","Write youtube.ini")})]}),tt.ok?null:(0,s.jsx)("p",{className:"text-xs text-rose-300",children:tt.message}),(0,s.jsxs)("details",{className:"rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,s.jsx)("summary",{className:"cursor-pointer text-xs text-zinc-500",children:a("高级:进程名","Advanced: process name")}),(0,s.jsx)("input",{className:"mt-2 w-full rounded-lg border border-white/10 bg-black/40 px-3 py-2 font-mono text-xs",value:null!==(i=null==e6?void 0:e6.pm2Name)&&void 0!==i?i:eK(e4.id),onChange:e=>e8("pm2Name",e.target.value),spellCheck:!1,placeholder:"youtube2__…"}),(0,s.jsxs)("p",{className:"mt-2 font-mono text-[11px] text-zinc-500",children:[a("实际生效","Effective"),": ",e7||"—"]}),tt.message&&!tt.ok?(0,s.jsx)("p",{className:"mt-2 text-[11px] text-rose-300",children:tt.message}):null]}),(0,s.jsx)("textarea",{className:"h-16 w-full resize-y rounded-xl border border-white/10 bg-black/40 p-3 text-xs text-zinc-300",value:null!==(r=null==e6?void 0:e6.notes)&&void 0!==r?r:"",onChange:e=>e8("notes",e.target.value),placeholder:a("备注(可选)","Notes (optional)")}),el?(0,s.jsx)("p",{className:"text-xs text-zinc-400",children:el}):null,(0,s.jsxs)("button",{type:"button",disabled:tS||P.length<2,className:"inline-flex items-center gap-1 text-xs text-rose-300 hover:text-rose-200 disabled:opacity-30",onClick:()=>{var e;let t=P.filter(e=>e.id!==e4.id);et(e=>{let t={...e};return delete t[e4.id],t}),e3(t),T((null===(e=t[0])||void 0===e?void 0:e.id)||"")},children:[(0,s.jsx)(ed.Z,{className:"h-3.5 w-3.5"}),a("删除此线路","Delete lane")]})]}):null]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播地址列表","URL list")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:a("每条线路独立写入自己的 URL_config..ini,不再复用或回填所谓“全局地址”。","Each lane writes to its own URL_config..ini with no shared global URL draft.")}),(0,s.jsx)("p",{className:"mt-1 font-mono text-[10px] text-zinc-600",children:x?eb(x):"URL_config.ini"}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2 text-[11px]",children:[(0,s.jsxs)("span",{className:"rounded-full border border-cyan-500/20 bg-cyan-500/10 px-2.5 py-1 text-cyan-100",children:[a("有效地址","Valid URLs"),": ",tg]}),(0,s.jsxs)("span",{className:"rounded-full border border-violet-500/20 bg-violet-500/10 px-2.5 py-1 text-violet-100",children:["Douyin: ",tf]})]}),tC,$?(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:$}):null,(0,s.jsx)("textarea",{className:"mt-4 min-h-[160px] w-full resize-y rounded-xl border border-white/10 bg-black/50 p-4 font-mono text-xs text-zinc-300",value:F,onChange:e=>{eo.current=!0,ez(e.target.value)},spellCheck:!1,placeholder:"https://live.douyin.com/..."}),(0,s.jsx)("div",{className:"mt-3 flex flex-wrap gap-2",children:(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void tu(),className:"rounded-xl bg-cyan-500/20 px-4 py-2 text-sm text-cyan-100 ring-1 ring-cyan-500/30",children:a("保存地址","Save URLs")})})]})]}),"single"===C?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播地址列表 \xb7 URL_config.ini","URL_config.ini")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:a("一行一个地址;可自动刷新或手动重新读取。","One URL per line; auto-refresh or reload.")}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2 text-[11px]",children:[(0,s.jsxs)("span",{className:"rounded-full border border-cyan-500/20 bg-cyan-500/10 px-2.5 py-1 text-cyan-100",children:[a("有效地址","Valid URLs"),": ",tg]}),(0,s.jsxs)("span",{className:"rounded-full border border-violet-500/20 bg-violet-500/10 px-2.5 py-1 text-violet-100",children:["Douyin: ",tf]})]}),tC,$?(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:$}):null,(0,s.jsx)("textarea",{className:"mt-4 min-h-[200px] w-full resize-y rounded-xl border border-white/10 bg-black/50 p-4 font-mono text-xs text-zinc-300",value:m,onChange:e=>{eo.current=!0,ek(e.target.value)},spellCheck:!1}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void tm(),className:"mt-3 rounded-xl bg-cyan-500/20 px-4 py-2 text-sm text-cyan-100 ring-1 ring-cyan-500/30",children:a("保存 URL 配置","Save URL config")})]}):null,(0,s.jsx)(ev,{t:a,currentProc:x,fetchJson:g,urlListText:"single"===C?m:F,keySuffixUi:tx,showKeyRow:!0,pollMs:800,refreshToken:er})]})}var e2=n(257);let e3=()=>void 0!==e2&&e2.env.NEXT_PUBLIC_API_URL||"";function e4(e){if(null==e||!Number.isFinite(e))return"—";if(0===e)return"0 B";let t=["B","KB","MB","GB","TB"],n=e,s=0;for(;n>=1024&&s=10||0===s?0:1)," ").concat(t[s])}function e6(e){let t=e4(e);return"—"===t?t:"".concat(t,"/s")}function e8(e){return"online"===e||"running"===e?"bg-emerald-500/15 text-emerald-300 ring-1 ring-emerald-500/30":"configured"===e?"bg-sky-500/15 text-sky-200 ring-1 ring-sky-500/25":"skipped"===e?"bg-slate-500/15 text-slate-300 ring-1 ring-slate-500/30":"stopped"===e||"not_found"===e?"bg-zinc-500/15 text-zinc-400 ring-1 ring-zinc-500/25":"error"===e?"bg-rose-500/15 text-rose-300 ring-1 ring-rose-500/35":"bg-violet-500/15 text-violet-200 ring-1 ring-violet-500/30"}function e9(e,t){let n=(e||"").trim().toLowerCase();return"online"===n||"running"===n?t("运行中","Running"):"configured"===n?t("已配置","Configured"):"not_found"===n?t("未注册","Unregistered"):"stopped"===n?t("已停止","Stopped"):"error"===n?t("异常","Error"):e||"—"}function e7(){var e,t,n,L,M,T,U,E,I,D,A,Z,O,H,B,K,F,W,J,G,V,q,X,$,Q,ee,et,en,es,el,ei,ea,eo,ec,ed,eu,em,eh,ep,eb,eg,ef,ev,ey,ew,eN,ej,ek,eS,e_,eR,eP,eL,eM,eT,eU,eE,eI,eD;let eA=e3(),[eZ,eO]=(0,_.useState)("zh"),[eH,eB]=(0,_.useState)("dark"),[eK,eF]=(0,_.useState)("dashboard"),[eW,eY]=(0,_.useState)(!1),[eJ,eG]=(0,_.useState)(null),[eV,eq]=(0,_.useState)(null),[eX,e$]=(0,_.useState)(!0),[eQ,e0]=(0,_.useState)(null),[e1,e2]=(0,_.useState)(null),[e7,te]=(0,_.useState)(null),[tt,tn]=(0,_.useState)(!0),[ts,tl]=(0,_.useState)([]),[ti,tr]=(0,_.useState)([]),[ta,to]=(0,_.useState)(""),[tc,td]=(0,_.useState)(""),[tx,tu]=(0,_.useState)("/sdcard/app.apk"),[tm,th]=(0,_.useState)(""),[tp,tb]=(0,_.useState)(null),[tg,tf]=(0,_.useState)(null),[tv,ty]=(0,_.useState)(!0),[tw,tN]=(0,_.useState)(!0),tj=(0,_.useRef)(null),tk=(0,_.useRef)(null),tz=(0,_.useRef)(ta),tS=(0,_.useRef)(0),t_=(0,_.useRef)(null),tC=(0,_.useCallback)((e,t)=>"zh"===eZ?e:t,[eZ]),tR=(0,_.useCallback)(e=>{e2(e),null!=t_.current&&window.clearTimeout(t_.current),t_.current=window.setTimeout(()=>{e2(null),t_.current=null},2800)},[]),tP=(0,_.useCallback)(async(e,t)=>(0,Y.N)("".concat(eA).concat(e),t),[eA]),tL=(0,_.useCallback)(async()=>{if(tj.current)return tj.current;let e=(async()=>{try{var e;let[t,n]=await Promise.allSettled([tP("/hub/dashboard"),tP("/deploy/check")]);if("fulfilled"!==t.status)throw t.reason;let s=t.value;eG(s),eq(null),te(Date.now()),"fulfilled"===n.status?tf(n.value):tf(null);let l=(null===(e=s.android)||void 0===e?void 0:e.devices)||[];if(l.length&&!tm){let e=l.find(e=>"device"===(e.state||"").toLowerCase());th((null!=e?e:l[0]).serial)}}catch(e){eq(e.message),tf(null)}finally{e$(!1),tj.current=null}})();return tj.current=e,e},[tm,tP]),tM=(0,_.useMemo)(()=>{let e=new URLSearchParams({light:"1"});return"live_youtube"===eK?e.set("family","youtube"):"live_tiktok"===eK&&e.set("family","tiktok"),"/process_monitor?".concat(e.toString())},[eK]),tT=(0,_.useCallback)(async()=>{if(tk.current)return tk.current;let e=(async()=>{try{let e=(await tP(tM)).entries||[];tr(e),tl(e.map(e=>({pm2:e.pm2,script:e.script,label:e.label}))),te(Date.now()),to(t=>!e.length||t&&e.some(e=>e.pm2===t)?t:e[0].pm2)}catch(e){}finally{tk.current=null}})();return tk.current=e,e},[tP,tM]);(0,_.useEffect)(()=>{let e=window.localStorage.getItem("live-hub-lang");("zh"===e||"en"===e)&&eO(e);let t=window.localStorage.getItem("live-hub-theme");("light"===t||"dark"===t)&&eB(t)},[]),(0,_.useEffect)(()=>{window.localStorage.setItem("live-hub-lang",eZ)},[eZ]),(0,_.useEffect)(()=>{document.documentElement.setAttribute("data-theme",eH);try{window.localStorage.setItem("live-hub-theme",eH)}catch(e){}},[eH]),(0,_.useEffect)(()=>{let e=()=>tn("visible"===document.visibilityState);return e(),document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[]),(0,_.useEffect)(()=>{if(!eW)return;let e=e=>{"Escape"===e.key&&eY(!1)};window.addEventListener("keydown",e);let t=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{window.removeEventListener("keydown",e),document.body.style.overflow=t}},[eW]),(0,_.useEffect)(()=>()=>{null!=t_.current&&window.clearTimeout(t_.current)},[]),(0,_.useEffect)(()=>{try{"0"===localStorage.getItem("livehub.autorefresh")&&ty(!1),"0"===localStorage.getItem("livehub.showStreamProbes")&&tN(!1)}catch(e){}},[]),(0,_.useEffect)(()=>{tL()},[tL]),(0,_.useEffect)(()=>{tT()},[tT]),(0,_.useEffect)(()=>{if(!tv||!tt||"live_youtube"===eK||"live_tiktok"===eK)return;let e=window.setInterval(()=>{tL()},1e4);return()=>clearInterval(e)},[tv,tt,tL,eK]),(0,_.useEffect)(()=>{if(!tv||!tt)return;let e=window.setInterval(()=>{tT()},"live_youtube"===eK||"live_tiktok"===eK?700:4e3);return()=>clearInterval(e)},[tv,tt,tT,eK]),(0,_.useEffect)(()=>{tz.current=ta},[ta]),(0,_.useEffect)(()=>{ta&&"live_youtube"===eK&&(async()=>{let e=tz.current.trim(),t=++tS.current;try{let n=new URLSearchParams({process:e,_ts:String(Date.now())}),s=await tP("/get_url_config?".concat(n));if(t!==tS.current||e!==tz.current.trim())return;td(s.content||"")}catch(e){}})()},[ta,tP,eK]),(0,_.useEffect)(()=>{"settings"===eK&&(async()=>{try{let e=await tP("/hub/config");tb(e)}catch(e){tb(null)}})()},[tP,eK]);let tU=(0,_.useMemo)(()=>{var e;let t=(null==eJ?void 0:null===(e=eJ.stack)||void 0===e?void 0:e.quick_links)||{},n={};for(let[e,s]of Object.entries(t))/^https?:\/\//i.test(s)?n[e]=(0,ex.p)(s):n[e]=s;return n},[null==eJ?void 0:null===(e=eJ.stack)||void 0===e?void 0:e.quick_links]),tE=(0,_.useMemo)(()=>(0,eC.O0)(tU),[tU]),tI=(0,_.useMemo)(()=>(0,eC.Tc)(tE),[tE]),tD=async(e,t)=>{e0("svc:".concat(e));try{let n=await tP("/service_action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({service:e,action:t})});"error"===n.status?tR(n.detail||n.message||tC("操作失败","Action failed")):tR(n.message||"OK"),await tL()}catch(e){tR(e.message)}finally{e0(null)}},tA=async(e,t)=>{let n=(null!=t?t:ta).trim();if(n){e0("proc:".concat(e,":").concat(n));try{let t=await tP("/".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({process:n})});tR(String(t.output||t.message||"OK")),await tT(),"live_youtube"===eK||"live_tiktok"===eK?tL():await tL()}catch(e){tR(e.message)}finally{e0(null)}}},tZ=async(e,t)=>{let n=(null!=t?t:ta).trim();if(!n)return;let s=null!=e?e:tc,l=++tS.current;e0("save:url");try{let e=new URLSearchParams({process:n});await tP("/save_url_config?".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:s})}),l===tS.current&&n===tz.current.trim()&&td(s),tR(tC("URL 配置已保存","URL config saved"))}catch(e){throw tR(e.message),e}finally{e0(null)}},tO=async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!tm){tR(tC("请选择设备","Pick a device"));return}e0("adb:".concat(e));try{let n=await tP("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,serial:tm,payload:t})});tR(n.message||"OK")}catch(e){tR(e.message)}finally{e0(null)}},tH=[{id:"dashboard",icon:r.Z,labelZh:"总览",labelEn:"Dashboard"},{id:"services",icon:a.Z,labelZh:"服务",labelEn:"Services"},{id:"live_youtube",icon:o.Z,labelZh:"YouTube 无人直播",labelEn:"YouTube unmanned"},{id:"live_tiktok",icon:c.Z,labelZh:"TikTok 无人直播",labelEn:"TikTok unmanned"},{id:"android",icon:d.Z,labelZh:"安卓",labelEn:"Android"},{id:"network",icon:x.Z,labelZh:"网络",labelEn:"Network"},{id:"settings",icon:u.Z,labelZh:"设置",labelEn:"Settings"}],tB=e=>{(async()=>{var t;if(null===(t=navigator.clipboard)||void 0===t?void 0:t.writeText){await navigator.clipboard.writeText(e);return}let n=document.createElement("textarea");n.value=e,n.readOnly=!0,n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),n.select(),document.execCommand("copy"),n.remove()})().then(()=>tR(tC("已复制","Copied")),()=>tR(tC("复制失败","Copy failed")))},tK=null!==(ev=null==eJ?void 0:null===(t=eJ.services)||void 0===t?void 0:t.filter(e=>e.running&&e.available).length)&&void 0!==ev?ev:0,tF=null!==(ey=null==eJ?void 0:null===(n=eJ.services)||void 0===n?void 0:n.length)&&void 0!==ey?ey:0,tW=e7?new Date(e7).toLocaleTimeString("zh"===eZ?"zh-CN":"en-US",{hour12:!1}):tC("未同步","Not synced"),tY=tt?tC("前台自动刷新","Auto refresh"):tC("后台已暂停刷新","Refresh paused in background");return(0,s.jsxs)("div",{className:"lp-root min-h-screen transition-colors duration-300 ".concat("light"===eH?"bg-slate-100 text-slate-900 selection:bg-violet-400/25":"bg-[#050508] text-zinc-100 selection:bg-violet-500/30"),children:[(0,s.jsx)("div",{className:"lp-noise pointer-events-none fixed inset-0 z-0 ".concat("light"===eH?"opacity-[0.06]":"opacity-[0.22]"),"aria-hidden":!0}),(0,s.jsx)("div",{className:"lp-aurora pointer-events-none fixed -left-1/4 top-0 h-[42rem] w-[42rem] rounded-full blur-[120px] ".concat("light"===eH?"bg-violet-400/15":"bg-violet-600/20"),"aria-hidden":!0}),(0,s.jsx)("div",{className:"lp-aurora2 pointer-events-none fixed bottom-0 right-0 h-[36rem] w-[36rem] rounded-full blur-[100px] ".concat("light"===eH?"bg-cyan-400/10":"bg-cyan-500/10"),"aria-hidden":!0}),e1?(0,s.jsx)(l.E.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},role:"status","aria-live":"polite","aria-atomic":"true",className:"fixed bottom-6 left-1/2 z-[100] max-w-md -translate-x-1/2 rounded-2xl border border-white/10 bg-zinc-950/95 px-5 py-3 text-center text-sm text-zinc-100 shadow-2xl shadow-black/50 backdrop-blur-xl",children:e1}):null,(0,s.jsxs)("div",{className:"relative z-10 flex min-h-screen",children:[(0,s.jsxs)("aside",{className:"hidden w-64 shrink-0 flex-col border-r px-4 py-6 backdrop-blur-2xl lg:flex ".concat("light"===eH?"border-slate-200/90 bg-white/70":"border-white/[0.06] bg-zinc-950/40"),children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-2",children:[(0,s.jsx)("div",{className:"flex h-9 w-9 items-center justify-center rounded-xl bg-gradient-to-br from-violet-500 to-cyan-400 shadow-lg shadow-violet-500/25",children:(0,s.jsx)(m.Z,{className:"h-4 w-4 text-white"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-[0.2em] ".concat("light"===eH?"text-slate-500":"text-zinc-500"),children:"live.local"}),(0,s.jsx)("p",{className:"text-sm font-semibold ".concat("light"===eH?"text-slate-900":"text-white"),children:tC("无人直播系统","Unmanned Live System")})]})]}),(0,s.jsx)("nav",{className:"mt-10 flex flex-1 flex-col gap-1",children:tH.map(e=>{let t=e.icon,n=eK===e.id;return(0,s.jsxs)("button",{type:"button",onClick:()=>eF(e.id),"aria-current":n?"page":void 0,className:"flex items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm font-medium transition ".concat("light"===eH?n?"bg-violet-100/90 text-slate-900 shadow-inner shadow-violet-200/50":"text-slate-600 hover:bg-slate-200/60 hover:text-slate-900":n?"bg-white/[0.08] text-white shadow-inner shadow-white/5":"text-zinc-500 hover:bg-white/[0.04] hover:text-zinc-200"),children:[(0,s.jsx)(t,{className:"h-4 w-4 ".concat("light"===eH?n?"text-violet-600":"text-slate-400":n?"text-violet-300":"text-zinc-600")}),tC(e.labelZh,e.labelEn),n?(0,s.jsx)(h.Z,{className:"ml-auto h-4 w-4 ".concat("light"===eH?"text-slate-400":"text-zinc-600")}):null]},e.id)})})]}),(0,s.jsxs)("div",{className:"flex min-w-0 flex-1 flex-col",children:[(0,s.jsxs)("header",{className:"sticky top-0 z-20 flex items-center justify-between gap-3 border-b px-4 py-3 backdrop-blur-xl lg:px-8 ".concat("light"===eH?"border-slate-200/80 bg-white/75 text-slate-900":"border-white/[0.06] bg-zinc-950/70 text-white"),children:[(0,s.jsxs)("div",{className:"flex min-w-0 items-center gap-3",children:[(0,s.jsx)("button",{type:"button",className:"rounded-xl border p-2 lg:hidden ".concat("light"===eH?"border-slate-200 bg-white/80":"border-white/10 bg-white/5"),onClick:()=>eY(!0),"aria-label":"Menu",children:(0,s.jsx)(p.Z,{className:"h-5 w-5"})}),(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsx)("h1",{className:"truncate text-lg font-semibold tracking-tight lg:text-xl ".concat("light"===eH?"text-slate-900":"text-white"),children:tC((null===(L=tH.find(e=>e.id===eK))||void 0===L?void 0:L.labelZh)||"",(null===(M=tH.find(e=>e.id===eK))||void 0===M?void 0:M.labelEn)||"")}),(0,s.jsxs)("p",{className:"truncate text-xs ".concat("light"===eH?"text-slate-500":"text-zinc-500"),children:[(null==eJ?void 0:null===(T=eJ.stack)||void 0===T?void 0:T.mdns_host)||"live.local"," \xb7"," ","dark"===eH?tC("夜间","Dark mode"):tC("日间","Light mode")," \xb7 ",tY," \xb7"," ",tC("最后同步","Last sync")," ",tW]})]})]}),(0,s.jsxs)("div",{className:"flex shrink-0 items-center gap-1.5 sm:gap-2",children:[(0,s.jsx)("button",{type:"button",onClick:()=>eB(e=>"dark"===e?"light":"dark"),className:"rounded-xl border p-2 transition ".concat("light"===eH?"border-slate-200 bg-white text-amber-500 shadow-sm":"border-white/10 bg-white/[0.06] text-violet-200"),title:"dark"===eH?tC("切换到日间","Switch to light"):tC("切换到夜间","Switch to dark"),"aria-label":"dark"===eH?tC("日间模式","Light mode"):tC("夜间模式","Dark mode"),"aria-pressed":"light"===eH,children:"dark"===eH?(0,s.jsx)(b.Z,{className:"h-5 w-5",strokeWidth:2}):(0,s.jsx)(g.Z,{className:"h-5 w-5",strokeWidth:2})}),(0,s.jsxs)("button",{type:"button",onClick:()=>eO(e=>"zh"===e?"en":"zh"),className:"relative rounded-xl border p-2 transition ".concat("light"===eH?"border-slate-200 bg-white text-cyan-600 shadow-sm":"border-white/10 bg-white/[0.06] text-cyan-200"),title:"zh"===eZ?"English":"中文","aria-label":tC("切换语言","Toggle language"),"aria-pressed":"en"===eZ,children:[(0,s.jsx)(f.Z,{className:"h-5 w-5",strokeWidth:2}),(0,s.jsx)("span",{className:"absolute -bottom-0.5 -right-0.5 flex h-4 min-w-[1rem] items-center justify-center rounded px-0.5 text-[9px] font-bold leading-none ".concat("light"===eH?"bg-cyan-100 text-cyan-800":"bg-cyan-500/30 text-cyan-100"),children:"zh"===eZ?"中":"A"})]}),(0,s.jsxs)("button",{type:"button",disabled:!!eQ,onClick:()=>void Promise.all([tL(),tT()]),className:"flex items-center gap-2 rounded-xl border px-3 py-2 text-xs font-medium transition disabled:opacity-40 ".concat("light"===eH?"border-slate-200 bg-white text-slate-700 hover:bg-slate-50":"border-white/10 bg-white/[0.04] text-zinc-300 hover:bg-white/[0.07]"),children:[eQ?(0,s.jsx)(v.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,s.jsx)(y.Z,{className:"h-3.5 w-3.5"}),(0,s.jsx)("span",{className:"hidden sm:inline",children:tC("刷新","Refresh")})]})]})]}),(0,s.jsx)("main",{className:"flex-1 px-4 py-6 lg:px-8 lg:py-8",children:(0,s.jsx)(i.M,{mode:"wait",children:(0,s.jsxs)(l.E.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},exit:{opacity:0,y:-6},transition:{duration:.28,ease:[.22,1,.36,1]},children:["dashboard"===eK?(0,s.jsxs)("div",{className:"space-y-6",children:[eV?(0,s.jsxs)("div",{className:"rounded-2xl border border-rose-500/25 bg-rose-950/20 p-4 text-sm text-rose-200",children:[tC("无法加载仪表盘:","Dashboard error: "),eV]}):null,(0,s.jsx)(l.E.div,{initial:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{delay:.02},className:"rounded-2xl border p-2 backdrop-blur-xl ".concat("light"===eH?"border-slate-200/90 bg-white/80 shadow-sm shadow-slate-200/30":"border-white/[0.07] bg-zinc-950/30"),children:(0,s.jsx)(R.Z,{snapshot:null!==(ew=null==eJ?void 0:eJ.snapshot)&&void 0!==ew?ew:null,theme:eH,tr:tC})}),(0,s.jsx)(l.E.div,{initial:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{delay:.05},className:"rounded-2xl border p-3 shadow-lg ".concat("light"===eH?"border-fuchsia-200/80 bg-gradient-to-br from-fuchsia-50/90 via-white to-cyan-50/70 shadow-fuchsia-100/40":"border-fuchsia-500/20 bg-gradient-to-br from-fuchsia-500/10 via-zinc-950/60 to-cyan-500/10 shadow-fuchsia-900/10"),children:(0,s.jsx)(C,{tr:tC})}),(0,s.jsx)("div",{className:"grid gap-2 sm:grid-cols-2 xl:grid-cols-5",children:[{icon:w.Z,label:tC("CPU 1m","CPU 1m"),value:null!==(eN=null==eJ?void 0:null===(I=eJ.snapshot)||void 0===I?void 0:null===(E=I.cpu_load)||void 0===E?void 0:null===(U=E["1m"])||void 0===U?void 0:U.toFixed(2))&&void 0!==eN?eN:"—",sub:tC("负载均值","Load avg")},{icon:r.Z,label:tC("内存","Memory"),value:e4(null==eJ?void 0:null===(A=eJ.snapshot)||void 0===A?void 0:null===(D=A.memory)||void 0===D?void 0:D.available),sub:"/ ".concat(e4(null==eJ?void 0:null===(O=eJ.snapshot)||void 0===O?void 0:null===(Z=O.memory)||void 0===Z?void 0:Z.total))},{icon:N.Z,label:tC("磁盘可用","Disk free"),value:e4(null==eJ?void 0:null===(B=eJ.snapshot)||void 0===B?void 0:null===(H=B.disk)||void 0===H?void 0:H.free),sub:"/ ".concat(e4(null==eJ?void 0:null===(F=eJ.snapshot)||void 0===F?void 0:null===(K=F.disk)||void 0===K?void 0:K.total))},{icon:a.Z,label:tC("服务在线","Services up"),value:"".concat(tK,"/").concat(tF||"—"),sub:tC("基础服务层","Infra layer")},{icon:j.Z,label:tC("运行时间","Uptime"),value:function(e){if(null==e||!Number.isFinite(e))return"—";let t=Math.max(0,Math.floor(e)),n=Math.floor(t/86400),s=Math.floor(t%86400/3600),l=Math.floor(t%3600/60);return n>0?"".concat(n,"d ").concat(s,"h"):s>0?"".concat(s,"h ").concat(l,"m"):"".concat(l,"m")}(null==eJ?void 0:null===(W=eJ.snapshot)||void 0===W?void 0:W.uptime_seconds),sub:tC("自开机","Since boot")}].map((e,t)=>(0,s.jsxs)(l.E.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},transition:{delay:.05*t,duration:.35,ease:[.22,1,.36,1]},whileHover:{y:-2},className:"group relative overflow-hidden rounded-xl border border-white/[0.07] bg-gradient-to-br from-white/[0.05] to-transparent p-3 shadow-lg shadow-black/20",children:[(0,s.jsx)("div",{className:"absolute -right-4 -top-4 h-16 w-16 rounded-full bg-violet-500/10 blur-xl transition group-hover:bg-violet-500/18"}),(0,s.jsx)(e.icon,{className:"h-4 w-4 text-violet-300/90"}),(0,s.jsx)("p",{className:"mt-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:e.label}),(0,s.jsx)("p",{className:"mt-0.5 font-mono text-lg font-semibold leading-tight text-white",children:eX?"…":e.value}),(0,s.jsx)("p",{className:"mt-0.5 text-[10px] text-zinc-500",children:e.sub})]},e.label))}),(null==eJ?void 0:eJ.hardware)&&"object"==typeof eJ.hardware?(0,s.jsxs)("div",{className:"rounded-2xl border border-indigo-500/25 bg-gradient-to-br from-indigo-500/[0.1] via-zinc-950/70 to-violet-500/[0.08] p-6 shadow-2xl shadow-indigo-500/5",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:tC("系统硬件与软件能力","Hardware & software profile")}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("来自 hardware_probe;用于直播/解码策略参考。","From hardware_probe; guides decode/streaming posture.")}),(0,s.jsxs)("div",{className:"mt-5 grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-indigo-300/90",children:tC("平台","Platform")}),(0,s.jsxs)("dl",{className:"space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"arch"}),(0,s.jsx)("dd",{className:"text-right text-zinc-200",children:String(null!==(ej=eJ.hardware.arch)&&void 0!==ej?ej:"—")})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"kernel"}),(0,s.jsx)("dd",{className:"text-right text-zinc-200",children:String(null!==(eS=null!==(ek=eJ.hardware.kernel)&&void 0!==ek?ek:null===(J=eJ.stack)||void 0===J?void 0:J.kernel)&&void 0!==eS?eS:"—")})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"Python"}),(0,s.jsx)("dd",{className:"text-right text-zinc-200",children:String(null!==(e_=null===(G=eJ.stack)||void 0===G?void 0:G.python)&&void 0!==e_?e_:"—")})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"mDNS"}),(0,s.jsx)("dd",{className:"text-right text-cyan-200/90",children:null!==(eR=null===(V=eJ.stack)||void 0===V?void 0:V.mdns_host)&&void 0!==eR?eR:"—"})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"IP"}),(0,s.jsx)("dd",{className:"text-right text-zinc-300",children:((null===(q=eJ.stack)||void 0===q?void 0:q.ips)||[]).join(" \xb7 ")||"—"})]})]})]}),(0,s.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-fuchsia-300/90",children:"GPU / NPU"}),(()=>{let e=eJ.hardware.gpu,t=eJ.hardware.npu;return(0,s.jsxs)("dl",{className:"space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"GPU"}),(0,s.jsxs)("dd",{className:"mt-0.5 text-zinc-200",children:[(null==e?void 0:e.present)?tC("已检测","present"):tC("未检测","absent"),(null==e?void 0:e.driver)?" \xb7 ".concat(e.driver):""]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"render"}),(0,s.jsx)("dd",{className:"mt-0.5 break-all text-zinc-500",children:((null==e?void 0:e.render_nodes)||[]).join(", ")||"—"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"NPU"}),(0,s.jsx)("dd",{className:"mt-0.5 break-all text-zinc-500",children:(null==t?void 0:t.present)?(t.devices||[]).join(", "):tC("—","—")})]})]})})()]}),(0,s.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4 lg:col-span-2",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-emerald-300/90",children:"ffmpeg / 建议策略"}),(()=>{var e,t,n,l;let i=eJ.hardware.ffmpeg_hwaccels||[],r=eJ.hardware.recommendation;return(0,s.jsxs)("div",{className:"space-y-2 text-[11px] text-zinc-400",children:[(0,s.jsxs)("p",{children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"hwaccels: "}),(0,s.jsx)("span",{className:"font-mono text-emerald-200/90",children:i.length?i.join(", "):"—"})]}),(0,s.jsxs)("div",{className:"grid gap-2 sm:grid-cols-2",children:[(0,s.jsxs)("p",{children:[(0,s.jsxs)("span",{className:"text-zinc-600",children:[tC("解码","Decoder"),": "]}),(0,s.jsx)("span",{className:"text-zinc-200",children:null!==(e=null==r?void 0:r.video_decoder)&&void 0!==e?e:"—"})]}),(0,s.jsxs)("p",{children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"HDMI: "}),(0,s.jsx)("span",{className:"text-zinc-200",children:null!==(t=null==r?void 0:r.hdmi_player)&&void 0!==t?t:"—"})]}),(0,s.jsxs)("p",{children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"Browser: "}),(0,s.jsx)("span",{className:"text-zinc-200",children:null!==(n=null==r?void 0:r.browser_hwaccel)&&void 0!==n?n:"—"})]}),(0,s.jsxs)("p",{children:[(0,s.jsxs)("span",{className:"text-zinc-600",children:[tC("稳定模式","Stability"),": "]}),(0,s.jsx)("span",{className:"text-amber-200/90",children:null!==(l=null==r?void 0:r.stability_mode)&&void 0!==l?l:"—"})]})]}),((null==r?void 0:r.degradation_reasons)||[]).length?(0,s.jsx)("ul",{className:"mt-2 list-inside list-disc space-y-1 text-[10px] text-amber-200/80",children:((null==r?void 0:r.degradation_reasons)||[]).map(e=>(0,s.jsx)("li",{children:e},e))}):null]})})()]})]})]}):null,tg?(0,s.jsxs)("div",{className:"rounded-2xl border p-5 ".concat(tg.ready?"border-emerald-500/25 bg-gradient-to-br from-emerald-500/[0.08] via-zinc-950/50 to-cyan-500/[0.05]":"border-amber-500/30 bg-gradient-to-br from-amber-500/[0.1] via-zinc-950/55 to-rose-500/[0.05]"),children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("安装验收","Deployment health")}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("一键脚本完成后,本机 API、局域网入口、反向代理与 mDNS 的可用性检查。","Post-install checks for loopback API, LAN access, reverse proxy, and mDNS.")})]}),(0,s.jsx)("span",{className:"rounded-full px-3 py-1 text-[10px] font-semibold ".concat(tg.ready?"bg-emerald-500/20 text-emerald-100 ring-1 ring-emerald-500/30":"bg-amber-500/20 text-amber-100 ring-1 ring-amber-500/30"),children:tg.ready?tC("可交付","Ready"):tC("需处理","Needs attention")})]}),(0,s.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:tC("验收摘要","Acceptance summary")}),(0,s.jsxs)("p",{className:"mt-2 font-mono text-sm text-white",children:[null!==(eP=tg.pass_count)&&void 0!==eP?eP:0,"/",null!==(eL=tg.total_count)&&void 0!==eL?eL:0,(0,s.jsx)("span",{className:"ml-2 text-[11px] text-zinc-500",children:tC("已通过","checks passed")})]}),(0,s.jsxs)("p",{className:"mt-1 text-[11px] text-zinc-500",children:[tC("必需项","Required"),": ",null!==(eM=tg.required_total)&&void 0!==eM?eM:0," \xb7 mDNS"," ",tg.mdns_enabled?tC("已启用","enabled"):tC("已关闭","disabled")," \xb7 edge"," ",tg.live_edge_enabled?tC("已启用","enabled"):tC("已关闭","disabled")]}),(0,s.jsx)("div",{className:"mt-3 flex flex-wrap gap-2",children:Object.entries(tg.urls||{}).filter(e=>{let[,t]=e;return!!t}).slice(0,4).map(e=>{let[t,n]=e;return(0,s.jsx)("a",{href:(0,ex.p)(n),target:"_blank",rel:"noreferrer",className:"rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-[11px] text-zinc-200 ring-1 ring-white/10",children:t},t)})})]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:(null===(X=tg.failing_checks)||void 0===X?void 0:X.length)?tC("失败项","Failing checks"):tC("当前状态","Current state")}),(null===($=tg.failing_checks)||void 0===$?void 0:$.length)?(0,s.jsx)("ul",{className:"mt-2 space-y-2 text-[11px] text-zinc-300",children:tg.failing_checks.slice(0,4).map(e=>(0,s.jsxs)("li",{className:"rounded-lg border border-amber-500/20 bg-amber-500/10 px-3 py-2",children:[(0,s.jsx)("span",{className:"font-semibold text-amber-100",children:e.label}),(0,s.jsx)("span",{className:"ml-2 text-zinc-400",children:e.detail||"—"})]},e.id))}):(0,s.jsx)("p",{className:"mt-2 text-[11px] text-emerald-200/90",children:tC("必需检查已全部通过,可直接用浏览器面板交付。","All required checks pass; browser control plane is ready.")}),(tg.hints||[]).length?(0,s.jsx)("ul",{className:"mt-3 list-inside list-disc space-y-1 text-[10px] text-zinc-400",children:(tg.hints||[]).slice(0,3).map(e=>(0,s.jsx)("li",{children:e},e))}):null]})]})]}):null,(null==eJ?void 0:null===(Q=eJ.stack)||void 0===Q?void 0:Q.neko_login)?(0,s.jsxs)("div",{className:"rounded-2xl border border-fuchsia-500/25 bg-gradient-to-r from-fuchsia-500/[0.08] to-violet-500/[0.06] p-5",children:[(0,s.jsxs)("h3",{className:"text-sm font-semibold text-white",children:["Neko ",tC("登录","sign-in")]}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:eJ.stack.neko_login.note_zh||tC(tI?"Neko Chromium ".concat(tI," 使用下列账号策略。"):"Neko Chromium 多实例使用下列账号策略。",tI?"Neko Chromium ".concat(tI," uses the policy below."):"Neko Chromium instances use the policy below.")}),(0,s.jsx)("p",{className:"mt-2 text-[11px] text-amber-200/85",children:tC("重要:两栏分开填——昵称随意,密码必须是环境变量里的口令(默认 12345678)。用错密码会像一直加载;勿把「用户名/密码」写在一行。","Use two fields: display name is free-form; password must match NEKO_* (default 12345678). Wrong password looks like infinite loading.")}),tE.length?(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:tE.map(e=>(0,s.jsxs)("a",{href:e.url,target:"_blank",rel:"noreferrer",className:"rounded-lg border border-fuchsia-400/20 bg-black/25 px-3 py-2 text-[11px] text-fuchsia-100 ring-1 ring-fuchsia-400/20",children:[e.label,e.port?" :".concat(e.port):""]},e.key))}):null,(0,s.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2 font-mono text-sm",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/40 px-4 py-3",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase text-zinc-500",children:tC("昵称示例","Display Name Example")}),(0,s.jsx)("p",{className:"mt-1 text-fuchsia-200",children:null!==(eT=eJ.stack.neko_login.user_login)&&void 0!==eT?eT:"live"}),(0,s.jsx)("p",{className:"mt-2 text-[10px] uppercase text-zinc-500",children:tC("连接口令","Access Password")}),(0,s.jsx)("p",{className:"mt-0.5 text-fuchsia-100",children:null!==(eU=eJ.stack.neko_login.user_password)&&void 0!==eU?eU:"—"})]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/40 px-4 py-3",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase text-zinc-500",children:tC("管理昵称示例","Admin Display Name Example")}),(0,s.jsx)("p",{className:"mt-1 text-violet-200",children:null!==(eE=eJ.stack.neko_login.admin_login)&&void 0!==eE?eE:"admin"}),(0,s.jsx)("p",{className:"mt-2 text-[10px] uppercase text-zinc-500",children:tC("管理口令","Admin Password")}),(0,s.jsx)("p",{className:"mt-0.5 text-violet-100",children:null!==(eI=eJ.stack.neko_login.admin_password)&&void 0!==eI?eI:"—"})]})]}),(0,s.jsx)("p",{className:"mt-3 text-[10px] text-zinc-600",children:tC("x86 默认使用 Neko 的 Chrome 镜像,ARM 默认使用 Chromium 镜像;默认保留管理员会话、开发者工具和 Tampermonkey 持久化。本栈未启用 Firefox 版 Neko。","x86 defaults to Neko’s Chrome image, ARM defaults to Chromium, and admin access, DevTools, plus persistent Tampermonkey stay enabled. This stack does not use Firefox Neko.")})]}):null,(null==eJ?void 0:null===(et=eJ.network)||void 0===et?void 0:null===(ee=et.interfaces)||void 0===ee?void 0:ee.length)?(0,s.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-gradient-to-br from-cyan-500/[0.07] to-transparent p-5",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(k.Z,{className:"h-4 w-4 text-cyan-300"}),tC("网络带宽 / 流量","Network bandwidth / traffic")]}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("实时速率由总览自动刷新间隔计算;累计值来自系统网卡计数器。","Live rates are calculated from dashboard refresh deltas; totals come from kernel counters.")}),(0,s.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase tracking-[0.08em] text-cyan-300/70",children:tC("实时下行","Live down")}),(0,s.jsx)("p",{className:"mt-1 text-lg font-semibold text-cyan-100",children:e6(eJ.network.total_rx_bps)}),(0,s.jsxs)("p",{className:"mt-1 text-zinc-500",children:[tC("累计","Total"),": ",e4(eJ.network.total_rx_bytes)]})]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase tracking-[0.08em] text-cyan-300/70",children:tC("实时上行","Live up")}),(0,s.jsx)("p",{className:"mt-1 text-lg font-semibold text-cyan-100",children:e6(eJ.network.total_tx_bps)}),(0,s.jsxs)("p",{className:"mt-1 text-zinc-500",children:[tC("累计","Total"),": ",e4(eJ.network.total_tx_bytes)]})]})]}),(0,s.jsx)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:(eJ.network.interfaces||[]).slice(0,6).map(e=>{var t,n,l,i;return(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,s.jsx)("p",{className:"text-xs font-semibold text-cyan-200/90",children:e.name}),(0,s.jsxs)("p",{className:"mt-2 text-zinc-500",children:[tC("链路","Link"),": ",e.operstate||"unknown"," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e.speed_mbps?"".concat(e.speed_mbps," Mbps"):tC("未知速率","unknown speed")]}),(0,s.jsxs)("p",{className:"mt-2 text-zinc-500",children:["↓ ",e6(e.rx_bps)," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e4(e.rx_bytes)," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",null!==(l=null===(t=e.rx_packets)||void 0===t?void 0:t.toLocaleString())&&void 0!==l?l:"—"," pkt"]}),(0,s.jsxs)("p",{className:"mt-0.5 text-zinc-500",children:["↑ ",e6(e.tx_bps)," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e4(e.tx_bytes)," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",null!==(i=null===(n=e.tx_packets)||void 0===n?void 0:n.toLocaleString())&&void 0!==i?i:"—"," pkt"]})]},e.name)})})]}):null,(null==eJ?void 0:null===(es=eJ.live_events)||void 0===es?void 0:null===(en=es.pm2_tail)||void 0===en?void 0:en.length)||(null==eJ?void 0:null===(ei=eJ.live_events)||void 0===ei?void 0:null===(el=ei.process_digest)||void 0===el?void 0:el.length)?(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-amber-500/15 bg-zinc-950/40 p-5",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("直播 / PM2 事件","Live / PM2 feed")}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("PM2 合并日志尾部","PM2 merged log tail")}),(0,s.jsx)("pre",{className:"mt-3 max-h-48 overflow-auto whitespace-pre-wrap rounded-lg border border-white/[0.05] bg-black/40 p-3 font-mono text-[10px] leading-relaxed text-zinc-400",children:((null==eJ?void 0:null===(ea=eJ.live_events)||void 0===ea?void 0:ea.pm2_tail)||[]).join("\n")||tC("暂无 PM2 输出","No PM2 output")})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/15 bg-zinc-950/40 p-5",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("进程快照","Process digest")}),(0,s.jsx)("ul",{className:"mt-3 space-y-2",children:((null==eJ?void 0:null===(eo=eJ.live_events)||void 0===eo?void 0:eo.process_digest)||[]).map(e=>(0,s.jsxs)("li",{className:"flex items-center justify-between gap-2 rounded-lg border border-white/[0.05] bg-black/30 px-3 py-2 text-xs",children:[(0,s.jsx)("span",{className:"truncate text-zinc-300",children:e.label||e.pm2}),(0,s.jsx)("span",{className:"shrink-0 rounded-md px-2 py-0.5 text-[10px] font-medium ".concat(e8(e.status||"")),children:e9(e.status||"",tC)})]},e.pm2))})]})]}):null,(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/20 bg-gradient-to-br from-violet-500/[0.12] via-zinc-950/50 to-fuchsia-500/[0.06] p-5 shadow-lg shadow-violet-500/5",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("直播进程","Live processes")}),(0,s.jsx)("span",{className:"rounded-full bg-white/10 px-2 py-0.5 text-[10px] font-medium text-zinc-300",children:(null==eJ?void 0:null===(ec=eJ.live)||void 0===ec?void 0:ec.backend_mode)||"—"})]}),(0,s.jsxs)("ul",{className:"mt-4 space-y-2.5",children:[((null==eJ?void 0:null===(ed=eJ.live)||void 0===ed?void 0:ed.processes)||[]).slice(0,10).map(e=>(0,s.jsxs)("li",{className:"group flex items-center gap-3 rounded-xl border border-white/[0.08] bg-black/35 px-3 py-2.5 transition hover:border-violet-400/25 hover:bg-black/45",children:[(0,s.jsx)("div",{className:"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-violet-500/30 to-fuchsia-500/20 text-[10px] font-bold text-violet-100 ring-1 ring-white/10",children:"LIVE"}),(0,s.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,s.jsx)("p",{className:"truncate text-sm font-medium text-zinc-100",children:e.label||e.pm2}),(0,s.jsx)("p",{className:"truncate font-mono text-[10px] text-zinc-600",children:e.script||e.pm2})]}),(0,s.jsx)("span",{className:"shrink-0 rounded-lg px-2.5 py-1 text-[10px] font-semibold ".concat(e8(e.process_status||"")),children:e9(e.process_status||"",tC)})]},e.pm2)),(null==eJ?void 0:null===(em=eJ.live)||void 0===em?void 0:null===(eu=em.processes)||void 0===eu?void 0:eu.length)?null:(0,s.jsx)("li",{className:"rounded-xl border border-dashed border-white/10 py-8 text-center text-xs text-zinc-600",children:tC("暂无直播进程","No live processes")})]}),(0,s.jsxs)("div",{className:"mt-5 grid grid-cols-2 gap-2",children:[(0,s.jsx)("button",{type:"button",onClick:()=>eF("live_youtube"),className:"rounded-xl border border-violet-400/35 bg-violet-500/15 py-2.5 text-[11px] font-semibold text-violet-100 shadow-inner shadow-black/20 transition hover:bg-violet-500/25",children:"YouTube"}),(0,s.jsx)("button",{type:"button",onClick:()=>eF("live_tiktok"),className:"rounded-xl border border-cyan-400/35 bg-cyan-500/15 py-2.5 text-[11px] font-semibold text-cyan-100 shadow-inner shadow-black/20 transition hover:bg-cyan-500/25",children:"TikTok"})]})]}),(null==eJ?void 0:eJ.probes)&&tw?(0,s.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:[eJ.probes.srs?(()=>{var e,t,n,l,i,r,a;let o=null===(e=eJ.probes)||void 0===e?void 0:e.srs,c=null==o?void 0:null===(t=o.tcp)||void 0===t?void 0:t.reachable,d=null==o?void 0:null===(n=o.tcp_api)||void 0===n?void 0:n.reachable,x=null==o?void 0:o.http_ui,u=null==o?void 0:o.http,m=null==o?void 0:o.api_port,h=null!==(i=null==o?void 0:o.api_ok)&&void 0!==i?i:(null==u?void 0:u.http_code)===200,p=null==x?void 0:x.http_code;return(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-zinc-950/40 p-4 backdrop-blur-sm",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,s.jsx)("p",{className:"text-xs font-semibold text-white",children:"SRS"}),(0,s.jsx)("span",{className:"rounded-full px-2 py-0.5 text-[10px] font-semibold ".concat(h?"bg-emerald-500/20 text-emerald-200 ring-1 ring-emerald-500/30":"bg-rose-500/15 text-rose-200 ring-1 ring-rose-500/25"),children:h?tC("API 正常","API OK"):tC("API 异常","API down")})]}),(0,s.jsxs)("p",{className:"mt-1 font-mono text-[11px] text-zinc-500",children:[":",null!==(r=null==o?void 0:o.port)&&void 0!==r?r:"—"," / API :",null!=m?m:"—"," \xb7 TCP ",c?"OK":"—"," \xb7 API TCP"," ",d?"OK":"—"]}),(0,s.jsxs)("p",{className:"mt-1 font-mono text-[11px] text-zinc-500",children:["API HTTP ",null!==(a=null==u?void 0:u.http_code)&&void 0!==a?a:"—"," \xb7 ",tC("根路径","root")," ",null!=p?p:"—",404===p?tC("(无首页不影响推流)"," (no index is OK for streaming)"):null]}),(0,s.jsxs)("p",{className:"mt-1 text-[11px] text-zinc-500",children:[tC("延迟","RTT")," ",(null==u?void 0:u.latency_ms)!=null?"".concat(u.latency_ms," ms"):(null==o?void 0:null===(l=o.tcp)||void 0===l?void 0:l.latency_ms)!=null?"".concat(o.tcp.latency_ms," ms"):"—"]}),!h&&(null==u?void 0:u.error)?(0,s.jsx)("p",{className:"mt-1 line-clamp-2 text-[10px] text-amber-200/80",children:u.error}):null]})})():null,eJ.probes.neko?(()=>{var e,t,n,l,i,r,a;let o=null===(e=eJ.probes)||void 0===e?void 0:e.neko,c=null==o?void 0:null===(t=o.tcp)||void 0===t?void 0:t.reachable,d=null==o?void 0:o.http,x=(null==o?void 0:o.instances)||[],u=null!==(l=null==o?void 0:o.running_count)&&void 0!==l?l:x.filter(e=>{var t;return null===(t=e.tcp)||void 0===t?void 0:t.reachable}).length,m=null!==(i=null==o?void 0:o.required_count)&&void 0!==i?i:x.length;return(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-zinc-950/40 p-4 backdrop-blur-sm",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,s.jsx)("p",{className:"text-xs font-semibold text-white",children:"Neko Chromium"}),(0,s.jsxs)("span",{className:"rounded-full px-2 py-0.5 text-[10px] font-semibold ".concat(u>0?"bg-emerald-500/20 text-emerald-200 ring-1 ring-emerald-500/30":"bg-rose-500/15 text-rose-200 ring-1 ring-rose-500/25"),children:[u,"/",m||"—"," ",tC("在线","online")]})]}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("Docker 内 Chromium(非 Chrome 品牌);arm64/x86 同一镜像。","Chromium in Docker (not Chrome branding); multi-arch.")}),(0,s.jsxs)("p",{className:"mt-2 font-mono text-[11px] text-zinc-500",children:[":",null!==(r=null==o?void 0:o.port)&&void 0!==r?r:"—"," \xb7 TCP ",c?"OK":"—"," \xb7 HTTP ",null!==(a=null==d?void 0:d.http_code)&&void 0!==a?a:"—"]}),(0,s.jsxs)("p",{className:"mt-1 text-[11px] text-zinc-500",children:[tC("延迟","RTT")," ",(null==d?void 0:d.latency_ms)!=null?"".concat(d.latency_ms," ms"):(null==o?void 0:null===(n=o.tcp)||void 0===n?void 0:n.latency_ms)!=null?"".concat(o.tcp.latency_ms," ms"):"—"]}),x.length?(0,s.jsx)("div",{className:"mt-3 space-y-2",children:x.map(e=>{var t,n,l,i,r,a,o;return(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3 rounded-lg border border-white/[0.05] bg-black/25 px-3 py-2",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsxs)("p",{className:"text-[11px] font-semibold text-zinc-200",children:["Neko ",null!==(r=e.id)&&void 0!==r?r:"?"]}),(0,s.jsxs)("p",{className:"font-mono text-[10px] text-zinc-500",children:[":",null!==(a=e.port)&&void 0!==a?a:"—"," \xb7 TCP ",(null===(t=e.tcp)||void 0===t?void 0:t.reachable)?"OK":"—"," \xb7 HTTP"," ",null!==(o=null===(n=e.http)||void 0===n?void 0:n.http_code)&&void 0!==o?o:"—"]})]}),(0,s.jsx)("span",{className:"shrink-0 rounded-full px-2 py-0.5 text-[10px] font-semibold ".concat((null===(l=e.tcp)||void 0===l?void 0:l.reachable)?"bg-emerald-500/15 text-emerald-200 ring-1 ring-emerald-500/25":"bg-zinc-500/15 text-zinc-400 ring-1 ring-zinc-500/25"),children:(null===(i=e.tcp)||void 0===i?void 0:i.reachable)?tC("运行中","Running"):tC("未连通","Offline")})]},"".concat(e.id,"-").concat(e.port))})}):null,!(null==d?void 0:d.reachable)&&(null==d?void 0:d.error)?(0,s.jsx)("p",{className:"mt-1 line-clamp-2 text-[10px] text-amber-200/80",children:d.error}):null]})})():null]}):null]}):null,"services"===eK?(0,s.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-3",children:[((null==eJ?void 0:eJ.services)||[]).map((e,t)=>(0,s.jsxs)(l.E.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},transition:{delay:.04*t},whileHover:{y:-2},className:"rounded-2xl border border-white/[0.07] bg-gradient-to-b from-white/[0.05] to-transparent p-5",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"font-semibold text-white",children:e.label}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500 line-clamp-2",children:e.description})]}),(0,s.jsx)("span",{className:"shrink-0 rounded-full px-2.5 py-1 text-[10px] font-semibold ".concat(e8(e.running?"online":e.status)),children:e.running?tC("运行中","Running"):e.status})]}),e.detail?(0,s.jsx)("p",{className:"mt-2 text-[11px] leading-snug line-clamp-6 ".concat("skipped"===e.status?"text-slate-300/90":"text-amber-200/85"),children:e.detail}):null,"shellcrash"===e.service_id&&e.available&&!e.running?(0,s.jsx)("p",{className:"mt-2 text-[11px] text-zinc-500",children:tC("stopped 为常态:仅当需要透明代理 / 规则分流时再点 Start(或 systemctl enable --now shellcrash)。","Stopped is normal; Start only when you need the proxy (or enable shellcrash.service).")}):null,(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap items-center gap-2",children:[e.url?(0,s.jsx)("a",{href:(0,ex.p)(e.url),target:"_blank",rel:"noreferrer",className:"rounded-lg bg-violet-500/15 px-3 py-1.5 text-xs font-medium text-violet-200 ring-1 ring-violet-500/25",children:tC("打开面板","Open panel")}):null,(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"start"),className:"rounded-lg bg-emerald-500/20 px-3 py-1.5 text-xs font-medium text-emerald-200 ring-1 ring-emerald-500/30 disabled:opacity-30",children:"Start"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"install"),className:"rounded-lg bg-sky-500/15 px-3 py-1.5 text-xs font-medium text-sky-200 ring-1 ring-sky-500/25 disabled:opacity-30",children:"Install"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"restart"),className:"rounded-lg bg-amber-500/15 px-3 py-1.5 text-xs font-medium text-amber-200 ring-1 ring-amber-500/25 disabled:opacity-30",children:"Restart"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"upgrade"),className:"rounded-lg bg-indigo-500/15 px-3 py-1.5 text-xs font-medium text-indigo-200 ring-1 ring-indigo-500/25 disabled:opacity-30",children:"Upgrade"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"stop"),className:"rounded-lg bg-rose-500/15 px-3 py-1.5 text-xs font-medium text-rose-200 ring-1 ring-rose-500/25 disabled:opacity-30",children:"Stop"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"uninstall"),className:"rounded-lg bg-zinc-500/15 px-3 py-1.5 text-xs font-medium text-zinc-200 ring-1 ring-zinc-500/25 disabled:opacity-30",children:"Uninstall"})]})]},e.service_id)),(null==eJ?void 0:null===(eh=eJ.services)||void 0===eh?void 0:eh.length)?null:(0,s.jsx)("p",{className:"text-sm text-zinc-500",children:tC("暂无服务数据","No services")})]}):null,"live_youtube"===eK?(0,s.jsx)(e5,{t:tC,busy:eQ,entries:ts,currentProc:ta,setCurrentProc:to,urlConfig:tc,setUrlConfig:td,onRunProcess:(e,t)=>void tA(e,t),onSaveUrlConfig:(e,t)=>tZ(e,t),fetchJson:tP,liveProcesses:ti.length?ti:null!==(eD=null==eJ?void 0:null===(ep=eJ.live)||void 0===ep?void 0:ep.processes)&&void 0!==eD?eD:[],notify:tR,quickLinks:tU,onNavigate:e=>eF(e)}):null,"live_tiktok"===eK?(0,s.jsx)(ez,{t:tC,busy:!!eQ,entries:ts,currentProc:ta,setCurrentProc:to,urlConfig:tc,setUrlConfig:td,onRunProcess:e=>void tA(e),onSaveUrlConfig:e=>tZ(e),onReplayGoLive:async(e,t)=>{let n=t.replace(/[,,|]/g,"_");await tZ("原画,".concat(e,",主播: ").concat(n)),await tA("start")},onCopy:tB,fetchJson:tP,apiPrefix:eA,quickLinks:tU,hdmiStatus:null==eJ?void 0:eJ.hdmi,notify:tR,onNavigate:e=>eF(e)}):null,"android"===eK?(0,s.jsx)(er,{t:tC,notify:tR,fetchJson:tP,apiBase:eA,busy:eQ,androidSerial:tm,setAndroidSerial:th,devices:(null==eJ?void 0:null===(eb=eJ.android)||void 0===eb?void 0:eb.devices)||[],adbAvailable:!!(null==eJ?void 0:null===(eg=eJ.android)||void 0===eg?void 0:eg.adb_available),apkPath:tx,setApkPath:tu,onAndroidAction:(e,t)=>tO(e,null!=t?t:{}),onCopy:tB,onRefreshDevices:()=>void tL()}):null,"network"===eK?(0,s.jsxs)("div",{className:"mx-auto max-w-7xl space-y-6",children:[(0,s.jsxs)("div",{className:"rounded-2xl border p-6 ".concat("light"===eH?"border-violet-200/90 bg-gradient-to-br from-violet-50 via-white to-fuchsia-50/80":"border-violet-500/25 bg-gradient-to-br from-violet-500/10 via-zinc-950/40 to-fuchsia-500/5"),children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold ".concat("light"===eH?"text-slate-900":"text-white"),children:[(0,s.jsx)(k.Z,{className:"h-4 w-4 ".concat("light"===eH?"text-violet-600":"text-violet-300")}),tC("ShellCrash 网络面板","ShellCrash panel")]}),(0,s.jsx)("p",{className:"mt-2 text-xs ".concat("light"===eH?"text-slate-600":"text-zinc-400"),children:tC("透明代理与规则分流直接在本页完成,无需跳转;流媒体与其它系统服务请在「服务」页管理。","Proxy rules and YAML editing are embedded here. Use Services for SRS/Neko/Chromium, etc.")}),(0,s.jsx)("div",{className:"mt-6 flex flex-col items-center gap-4 sm:flex-row sm:justify-center",children:[{tx:tC("互联网","Internet"),c:"from-cyan-400 to-blue-500"},{tx:"ShellCrash",c:"from-violet-500 to-fuchsia-500"},{tx:tC("本机 / 安卓","Host / Android"),c:"from-emerald-400 to-teal-500"}].map((e,t)=>(0,s.jsxs)("div",{className:"flex items-center gap-4",children:[(0,s.jsx)("div",{className:"flex h-16 w-28 items-center justify-center rounded-2xl bg-gradient-to-br ".concat(e.c," text-xs font-bold text-white shadow-lg"),children:e.tx}),t<2?(0,s.jsx)(h.Z,{className:"hidden h-5 w-5 sm:block ".concat("light"===eH?"text-slate-400":"text-zinc-600")}):null]},e.tx))})]}),(0,s.jsx)("div",{className:"overflow-hidden rounded-2xl border shadow-xl ".concat("light"===eH?"border-slate-200/90 bg-white shadow-slate-200/40":"border-white/[0.08] bg-zinc-950/50 shadow-black/30"),children:(0,s.jsx)("div",{className:"max-h-[min(78vh,56rem)] min-h-[22rem] overflow-y-auto overflow-x-hidden",children:(0,s.jsx)(P.d,{embeddedShellCrash:!0,portalLang:eZ})})})]}):null,"settings"===eK?(0,s.jsxs)("div",{className:"mx-auto max-w-lg space-y-6",children:[(0,s.jsx)("p",{className:"text-sm ".concat("light"===eH?"text-slate-600":"text-zinc-400"),children:tC("常用选项(本机偏好);完整文件与 JSON 编辑见下方链接。","Local preferences; full file/JSON editor via the link below.")}),(0,s.jsxs)("div",{className:"space-y-4 rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,s.jsxs)("label",{className:"flex cursor-pointer items-center justify-between gap-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-sm font-medium text-white",children:tC("总览自动刷新","Auto-refresh dashboard")}),(0,s.jsx)("p",{className:"text-[11px] text-zinc-500",children:"10s"})]}),(0,s.jsx)("input",{type:"checkbox",className:"h-5 w-5 accent-violet-500",checked:tv,onChange:e=>{let t=e.target.checked;ty(t);try{localStorage.setItem("livehub.autorefresh",t?"1":"0")}catch(e){}tR(t?tC("已开启刷新","Auto refresh on"):tC("已暂停刷新","Paused"))}})]}),(0,s.jsxs)("label",{className:"flex cursor-pointer items-center justify-between gap-4 border-t border-white/[0.06] pt-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-sm font-medium text-white",children:tC("总览显示 SRS / Neko 探针","Show SRS/Neko probes")}),(0,s.jsx)("p",{className:"text-[11px] text-zinc-500",children:tC("关闭可精简首页","Hide stream probe cards")})]}),(0,s.jsx)("input",{type:"checkbox",className:"h-5 w-5 accent-violet-500",checked:tw,onChange:e=>{let t=e.target.checked;tN(t);try{localStorage.setItem("livehub.showStreamProbes",t?"1":"0")}catch(e){}}})]})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/40 p-5",children:[(0,s.jsx)("p",{className:"text-xs font-semibold uppercase tracking-wider text-zinc-500",children:tC("配置快照","Config snapshot")}),(0,s.jsx)("p",{className:"mt-2 font-mono text-[11px] text-zinc-400",children:String((null==tp?void 0:tp.config_root)||"—")}),(0,s.jsxs)("p",{className:"mt-3 text-sm text-zinc-300",children:[tC("主机名","Hostname"),":"," ",(0,s.jsx)("span",{className:"font-mono text-violet-200",children:(()=>{var e,t,n;let s=null==tp?void 0:tp.system;return(null==s?void 0:null===(t=s.identity)||void 0===t?void 0:null===(e=t.hostname_alias)||void 0===e?void 0:e.trim())||((null==eJ?void 0:null===(n=eJ.stack)||void 0===n?void 0:n.mdns_host)||"").replace(/\.local$/i,"")||"—"})()})]}),(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:null==tp?void 0:null===(ef=tp.services)||void 0===ef?void 0:ef.slice(0,8).map(e=>(0,s.jsxs)("span",{className:"rounded-full px-2.5 py-1 text-[10px] font-medium ".concat(e.enabled?"bg-emerald-500/15 text-emerald-200 ring-1 ring-emerald-500/25":"bg-zinc-500/15 text-zinc-400"),children:[e.id," ",e.enabled?"ON":"off"]},e.id))})]}),(0,s.jsxs)("a",{href:"/console?tab=config",className:"inline-flex w-full items-center justify-center gap-2 rounded-xl border py-3 text-sm transition ".concat("light"===eH?"border-slate-200 bg-slate-50 text-violet-700 hover:bg-slate-100":"border-white/10 bg-white/[0.05] text-violet-200 hover:bg-white/[0.08]"),children:[tC("完整配置中心(文件 / JSON)","Full config center (files / JSON)"),(0,s.jsx)(z.Z,{className:"h-4 w-4"})]})]}):null]},eK)})})]})]}),(0,s.jsx)(i.M,{children:eW?(0,s.jsx)(l.E.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:"fixed inset-0 z-50 bg-black/60 backdrop-blur-sm lg:hidden",onClick:()=>eY(!1),children:(0,s.jsxs)(l.E.aside,{initial:{x:-280},animate:{x:0},exit:{x:-280},transition:{type:"spring",damping:28,stiffness:320},className:"absolute left-0 top-0 h-full w-[min(88vw,280px)] border-r border-white/10 bg-zinc-950 p-4 shadow-2xl",onClick:e=>e.stopPropagation(),children:[(0,s.jsx)("div",{className:"flex justify-end",children:(0,s.jsx)("button",{type:"button",onClick:()=>eY(!1),className:"rounded-lg p-2",children:(0,s.jsx)(S.Z,{className:"h-5 w-5"})})}),(0,s.jsx)("nav",{className:"mt-4 flex flex-col gap-1",children:tH.map(e=>{let t=e.icon,n=eK===e.id;return(0,s.jsxs)("button",{type:"button",onClick:()=>{eF(e.id),eY(!1)},"aria-current":n?"page":void 0,className:"flex items-center gap-3 rounded-xl px-3 py-3 text-left text-sm transition ".concat(n?"bg-white/[0.08] text-white shadow-inner shadow-white/5":"text-zinc-300 hover:bg-white/[0.04]"),children:[(0,s.jsx)(t,{className:"h-4 w-4 ".concat(n?"text-violet-300":"text-violet-400")}),tC(e.labelZh,e.labelEn)]},e.id)})})]})}):null})]})}}},function(e){e.O(0,[500,719,246,971,117,744],function(){return e(e.s=4578)}),_N_E=e.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{5052:function(e,t,n){Promise.resolve().then(n.bind(n,1499))},1499:function(e,t,n){"use strict";n.r(t),n.d(t,{default:function(){return e7}});var s=n(7437),l=n(6247),i=n(7586),r=n(4401),a=n(6137),o=n(4372),c=n(5901),d=n(3388),x=n(3420),u=n(8728),m=n(2023),h=n(407),p=n(6840),b=n(7226),g=n(5929),f=n(7945),v=n(1817),y=n(7168),w=n(4822),N=n(4428),j=n(1723),k=n(2926),z=n(7580),S=n(2489),_=n(2265);function C(e){let{tr:t}=e,l=(0,_.useRef)(null);return(0,_.useEffect)(()=>{let e;if(!l.current)return;let t=!1,s=0;return n.e(689).then(n.bind(n,1448)).then(n=>{if(t||!l.current)return;let i=l.current,r=Math.max(i.clientWidth,280),a=Math.max(i.clientHeight,200),o=new n.Scene,c=new n.PerspectiveCamera(48,r/a,.1,80);c.position.set(0,1.1,7.2);let d=new n.WebGLRenderer({antialias:!0,alpha:!0});d.setPixelRatio(Math.min(window.devicePixelRatio,2)),d.setSize(r,a),d.setClearColor(0,0),i.appendChild(d.domElement);let x=new n.HemisphereLight(16762092,4482815,.85);o.add(x);let u=new n.DirectionalLight(16777215,.9);u.position.set(4,8,6),o.add(u);let m=new n.PointLight(8189439,.6,20);m.position.set(-3,2,-2),o.add(m);let h=new n.Group,p=new n.Mesh(new n.BoxGeometry(3.2,.35,2.2),new n.MeshStandardMaterial({color:2762048,metalness:.15,roughness:.55}));p.position.y=-.85,h.add(p);let b=new n.Mesh(new n.TorusGeometry(.72,.09,12,48),new n.MeshStandardMaterial({color:16724821,emissive:4456465,metalness:.35,roughness:.25}));b.rotation.x=Math.PI/2,b.position.set(-.85,.15,.2),h.add(b);let g=new n.Mesh(new n.ConeGeometry(.35,.5,3),new n.MeshStandardMaterial({color:16777215,emissive:2236962,metalness:.2,roughness:.3}));g.rotation.z=-Math.PI/2,g.rotation.y=Math.PI,g.position.set(-.55,.18,.2),h.add(g);let f=new n.Mesh(new n.CylinderGeometry(.22,.28,.95,20),new n.MeshStandardMaterial({color:2487534,emissive:340024,metalness:.25,roughness:.35}));f.position.set(1.05,.35,-.15),f.rotation.z=.12,h.add(f);let v=new n.Mesh(new n.SphereGeometry(.26,16,16),new n.MeshStandardMaterial({color:16657493,emissive:2229520,metalness:.2,roughness:.4}));v.position.set(1.05,.92,-.15),h.add(v);let y=new n.BufferGeometry,w=new Float32Array(360);for(let e=0;e<120;e++)w[3*e]=(Math.random()-.5)*14,w[3*e+1]=(Math.random()-.3)*8,w[3*e+2]=(Math.random()-.5)*8-2;y.setAttribute("position",new n.BufferAttribute(w,3));let N=new n.Points(y,new n.PointsMaterial({color:16777215,size:.06,transparent:!0,opacity:.7}));o.add(N),o.add(h);let j=performance.now(),k=()=>{if(t)return;s=requestAnimationFrame(k);let e=(performance.now()-j)/1e3;h.rotation.y=.25*Math.sin(.35*e)+.12*e,h.position.y=.06*Math.sin(.9*e),b.rotation.z=.4*e,N.rotation.y=.02*e,d.render(o,c)};k();let z=new ResizeObserver(()=>{if(!l.current||t)return;let e=Math.max(l.current.clientWidth,280),n=Math.max(l.current.clientHeight,200);c.aspect=e/n,c.updateProjectionMatrix(),d.setSize(e,n)});z.observe(i),e=()=>{cancelAnimationFrame(s),z.disconnect(),d.dispose(),y.dispose(),d.domElement.parentNode===i&&i.removeChild(d.domElement)}}),()=>{t=!0,cancelAnimationFrame(s),null==e||e()}},[]),(0,s.jsxs)("div",{className:"flex h-full min-h-[14rem] flex-col",children:[(0,s.jsx)("p",{className:"mb-2 px-1 text-[10px] font-medium uppercase tracking-wider text-fuchsia-200/80",children:t("直播工作室 \xb7 3D","Live studio \xb7 3D")}),(0,s.jsx)("div",{ref:l,className:"relative min-h-[12rem] flex-1 overflow-hidden rounded-xl bg-gradient-to-b from-fuchsia-950/40 to-cyan-950/20 ring-1 ring-white/10"})]})}var R=n(9170),P=n(2246),L=n(4286),M=n(4794),T=n(221),U=n(8867),E=n(8124),I=n(2101),D=n(3651),A=n(9985),Z=n(6362),O=n(3468),H=n(6443),B=n(5287),K=n(3276),F=n(9227),W=n(257),Y=n(1387);class J{reset(){if(this.buf=new Uint8Array(0),this.sps=null,this.pps=null,this.configured=!1,this.configuring=!1,this.ts=0,this.decoder){try{this.decoder.close()}catch(e){}this.decoder=null}}push(e){let t=new Uint8Array(e.byteLength);t.set(new Uint8Array(e)),this.buf=function(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}(this.buf,t),this.drainAvcc()}drainAvcc(){let e=this.buf,t=0;for(;t+4<=e.length;){var n;let s=e[n=t]<<24|e[n+1]<<16|e[n+2]<<8|e[n+3];if(s<=0||s>6291456){this.buf=new Uint8Array(e.subarray(t+1)),t=0;continue}if(t+4+s>e.length)break;let l=e.subarray(t+4,t+4+s);t+=4+s,this.handleNal(l)}t>0&&(this.buf=new Uint8Array(e.subarray(t)))}handleNal(e){if(e.length<2)return;let t=31&e[0];if(7===t?this.sps=new Uint8Array(e):8===t&&(this.pps=new Uint8Array(e)),this.sps&&this.pps&&!this.configured&&!this.configuring&&this.configure(),!this.configured||!this.decoder||1!==t&&5!==t&&7!==t&&8!==t||7===t||8===t)return;let n=new Uint8Array(4+e.length);new DataView(n.buffer).setUint32(0,e.length,!1),n.set(e,4);try{let e=new EncodedVideoChunk({type:5===t?"key":"delta",timestamp:this.ts,data:n});this.ts+=33333,this.decoder.decode(e)}catch(e){this.onDecodeError(e.message||String(e))}}async configure(){if(this.sps&&this.pps&&!this.configured&&!this.configuring){this.configuring=!0;try{let e=function(e,t){let n=e.subarray(1),s=t.subarray(1),l=new Uint8Array(11+n.length+3+s.length),i=0;return l[i++]=1,l[i++]=e[1],l[i++]=e[2],l[i++]=e[3],l[i++]=255,l[i++]=225,l[i++]=n.length>>8&255,l[i++]=255&n.length,l.set(n,i),i+=n.length,l[i++]=1,l[i++]=s.length>>8&255,l[i++]=255&s.length,l.set(s,i),l}(this.sps,this.pps),t=function(e){let t=e=>e.toString(16).padStart(2,"0").toUpperCase();return"avc1.".concat(t(e[1])).concat(t(e[2])).concat(t(e[3]))}(this.sps),n=new VideoDecoder({output:e=>{var t;let n=this.canvas.getContext("2d");if(!n){e.close();return}(this.canvas.width!==e.displayWidth||this.canvas.height!==e.displayHeight)&&(this.canvas.width=e.displayWidth,this.canvas.height=e.displayHeight),n.drawImage(e,0,0),e.close(),null===(t=this.onFrame)||void 0===t||t.call(this)},error:e=>this.onDecodeError(String(e.message||e))});await n.configure({codec:t,description:e,optimizeForLatency:!0}),this.decoder=n,this.configured=!0}catch(e){this.onDecodeError(e.message||String(e))}finally{this.configuring=!1}}}constructor(e,t,n){this.canvas=e,this.onDecodeError=t,this.onFrame=n,this.buf=new Uint8Array(0),this.decoder=null,this.configured=!1,this.configuring=!1,this.ts=0,this.sps=null,this.pps=null}}function G(){return"undefined"!=typeof VideoDecoder&&"undefined"!=typeof VideoFrame}let V="live-hub-adb-bookmarks-v1";function q(e,t,n){let s,l,i,r;let a=e.getBoundingClientRect(),o=e.width,c=e.height;if(!o||!c)return null;let d=a.width/a.height,x=o/c;x>d?(s=a.width,l=a.width/x,i=0,r=(a.height-l)/2):(l=a.height,s=a.height*x,i=(a.width-s)/2,r=0);let u=t-a.left-i,m=n-a.top-r;return u<0||m<0||u>s||m>l?null:{x:Math.max(0,Math.min(o-1,Math.round(u/s*o))),y:Math.max(0,Math.min(c-1,Math.round(m/l*c)))}}function X(e,t,n){let s,l,i,r;let a=e.getBoundingClientRect(),o=e.naturalWidth,c=e.naturalHeight;if(!o||!c)return null;let d=a.width/a.height,x=o/c;x>d?(s=a.width,l=a.width/x,i=0,r=(a.height-l)/2):(l=a.height,s=a.height*x,i=(a.width-s)/2,r=0);let u=t-a.left-i,m=n-a.top-r;return u<0||m<0||u>s||m>l?null:{x:Math.max(0,Math.min(o-1,Math.round(u/s*o))),y:Math.max(0,Math.min(c-1,Math.round(m/l*c)))}}let $=[0,280,450,700,1100];function Q(e){switch(e){case"usb":return{Icon:I.Z,zh:"USB",en:"USB",cls:"bg-amber-500/20 text-amber-100 ring-amber-500/35"};case"tcp":return{Icon:k.Z,zh:"网络",en:"TCP",cls:"bg-cyan-500/20 text-cyan-100 ring-cyan-500/35"};case"emulator":return{Icon:D.Z,zh:"模拟器",en:"Emu",cls:"bg-fuchsia-500/20 text-fuchsia-100 ring-fuchsia-500/35"};default:return{Icon:d.Z,zh:"?",en:"?",cls:"bg-zinc-600/30 text-zinc-400"}}}let ee="https://github.com/Genymobile/scrcpy",et="https://github.com/viarotel-org/escrcpy";function en(e,t){let n=t.startsWith("/")?t:"/".concat(t),s=(e||"").trim().replace(/\/$/,"");return s?"".concat(s).concat(n):n}function es(e){var t;let{t:n,apiBase:l,fetchJson:i,serial:r,devices:a,setSerial:o,adbAvailable:c,lock:x,overview:u,onAndroidAction:h,notify:p,onRefreshDevices:b}=e,[g,f]=(0,_.useState)(0),[v,w]=(0,_.useState)(450),[N,j]=(0,_.useState)(!1),[k,z]=(0,_.useState)(null),[S,C]=(0,_.useState)(null),[R,P]=(0,_.useState)(!0),[L,M]=(0,_.useState)(""),[T,U]=(0,_.useState)(""),[E,I]=(0,_.useState)("37777"),[D,es]=(0,_.useState)(""),[el,ei]=(0,_.useState)(!1),[er,ea]=(0,_.useState)([]),[eo,ec]=(0,_.useState)(!1),[ed,ex]=(0,_.useState)(null),[eu,em]=(0,_.useState)(!1),[eh,ep]=(0,_.useState)(null),[eb,eg]=(0,_.useState)(null),[ef,ev]=(0,_.useState)(!0),ey=(0,_.useRef)(null),ew=(0,_.useRef)(null),eN=(0,_.useRef)(null),ej=(0,_.useRef)(null),ek=(0,_.useRef)(null),ez=(0,_.useRef)(null),eS=(0,_.useRef)(0),e_=(0,_.useRef)(!1),eC=(0,_.useRef)(null),eR=(0,_.useRef)(!1),eP=null===(t=a.find(e=>e.serial===r))||void 0===t?void 0:t.transport,eL=v>0,eM=r?"".concat(en(l,"/android/screenshot"),"?serial=").concat(encodeURIComponent(r),"&ts=").concat(g).concat(eL?"&fast=1":""):"",eT=(0,_.useCallback)(()=>{f(e=>e+1)},[]),eU=(0,_.useCallback)(()=>{null!=eC.current&&(window.clearTimeout(eC.current),eC.current=null)},[]);(0,_.useEffect)(()=>{let e=()=>ev("visible"===document.visibilityState);return e(),document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[]),(0,_.useEffect)(()=>{try{let e=window.localStorage.getItem(V);if(e){let t=JSON.parse(e);Array.isArray(t)&&ea(t.map(String).filter(Boolean).slice(0,24))}}catch(e){}},[]);let eE=e=>{let t=e.trim();if(!t)return;let s=[t,...er.filter(e=>e!==t)].slice(0,16);ea(s);try{window.localStorage.setItem(V,JSON.stringify(s))}catch(e){}p(n("已保存快捷地址","Saved quick address"))};(0,_.useEffect)(()=>{if(!r||!c){C(null);return}let e=!1;return(async()=>{try{let t=await (0,Y.N)("".concat(en(l,"/android/display_metrics"),"?serial=").concat(encodeURIComponent(r)));if(e)return;"number"==typeof t.width&&"number"==typeof t.height&&C({width:t.width,height:t.height})}catch(e){}})(),()=>{e=!0}},[l,c,r]),(0,_.useEffect)(()=>{if(!c||!r||v<=0||eo||!ef)return;let e=window.setInterval(()=>f(e=>e+1),v);return()=>clearInterval(e)},[c,v,ef,r,eo]),(0,_.useEffect)(()=>{ef&&c&&r&&!eo&&eT()},[c,eT,ef,r,eo]),(0,_.useEffect)(()=>{if(!c){eg(null);return}let e=!1;return(async()=>{try{let t=await (0,Y.N)(en(l,"/android/scrcpy/info"));e||eg(t)}catch(e){}})(),()=>{e=!0}},[l,c]),(0,_.useEffect)(()=>{eo||ep(null)},[eo]),(0,_.useEffect)(()=>{ex(null),e_.current=!1},[r]),(0,_.useEffect)(()=>{let e=a.find(e=>e.serial===r),t=!!(r&&ed===r);if(c&&r&&(null==e?void 0:e.state)==="device"&&(null==eb?void 0:eb.server_jar)&&G()&&!t){ec(!0),w(0);return}if(t||!r||!c||eb&&!eb.server_jar||!G()||e&&"device"!==e.state){ec(!1);return}},[r,a,c,eb,ed]),(0,_.useEffect)(()=>{if(!eo||!r||!c){var e,t;eU(),e_.current=!0,eR.current=!1,null===(e=ej.current)||void 0===e||e.close(),ej.current=null,null===(t=ek.current)||void 0===t||t.reset(),ek.current=null,em(!1);return}if(!G()){ep(n("当前浏览器不支持 WebCodecs H.264","WebCodecs H.264 not supported in this browser")),ec(!1);return}let s=eN.current;if(!s)return;let i=e=>{var t;eU(),e_.current=!0,null===(t=ej.current)||void 0===t||t.close(),ep(e),ec(!1),w(450),ex(r),window.setTimeout(()=>eT(),120)},a=new J(s,e=>i("".concat(n("实时画面解码失败,已切回截图模式","Live stream decode failed, using screenshot mode"),": ").concat(e)),()=>{eR.current=!0,eU()});ek.current=a,e_.current=!1,eR.current=!1;let o=new WebSocket(function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1920,s=(function(e){let t=(e||"").trim();if(t)try{let e=new URL(t,window.location.href),n="https:"===e.protocol?"wss:":"ws:";return"".concat(n,"//").concat(e.host)}catch(e){}let n=void 0!==W&&W.env.NEXT_PUBLIC_API_URL?String(W.env.NEXT_PUBLIC_API_URL).trim():"";if(n)try{let e=new URL(n,window.location.href),t="https:"===e.protocol?"wss:":"ws:";return"".concat(t,"//").concat(e.host)}catch(e){}let s=window.location.port;if("3000"===s||"3001"===s){let e=window.location.hostname||"127.0.0.1";return"ws://".concat(e,":").concat("8001")}let{protocol:l,host:i}=window.location;return"".concat("https:"===l?"wss:":"ws:","//").concat(i)})(e).replace(/\/$/,""),l=new URLSearchParams({serial:t,max_size:String(n)});return"".concat(s,"/android/scrcpy/ws?").concat(l.toString())}(l,r));return ej.current=o,o.binaryType="arraybuffer",o.onopen=()=>{em(!0),ep(null),eU(),eC.current=window.setTimeout(()=>{eR.current||i(n("实时画面无首帧,已切回截图模式","No first live frame, using screenshot mode"))},5200)},o.onmessage=e=>{var t;if("string"==typeof e.data){try{let t=JSON.parse(e.data);t.error&&ep(t.error)}catch(e){}return}null===(t=ek.current)||void 0===t||t.push(e.data)},o.onerror=()=>{ep(n("WebSocket 异常","WebSocket error"))},o.onclose=()=>{var e;em(!1),null===(e=ek.current)||void 0===e||e.reset(),ek.current=null,eU(),eo&&!e_.current&&i(n("实时画面连接失败,已切回截图模式","Live stream failed, using screenshot mode"))},()=>{eU(),e_.current=!0,eR.current=!1,o.close(),ej.current=null,a.reset(),ek.current===a&&(ek.current=null)}},[eo,r,c,l,eT,eU,n]),(0,_.useEffect)(()=>{r&&c&&(eS.current=0,f(e=>e+1))},[r,c]);let eI=async()=>{let e=L.trim();if(!e){p(n("填写 host:port","Enter host:port"));return}ei(!0);try{let t=await i("/android/connect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({address:e})});p(t.message||(t.ok?"OK":n("连接结果见日志","See message"))),b(),eT()}catch(e){p(e.message)}finally{ei(!1)}},eD=async e=>{ei(!0);try{let t=await i("/android/disconnect",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({address:e})});p(t.message||"OK"),b()}catch(e){p(e.message)}finally{ei(!1)}},eA=async()=>{let e=T.trim(),t=parseInt(E,10)||37777,s=D.trim();if(!e||!s){p(n("填写配对 IP 与码","Host + code required"));return}ei(!0);try{let l=await i("/android/pair",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({host:e,port:t,code:s})});p(l.message||(l.ok?n("配对成功后再点连接","Paired — now Connect"):"pair"))}catch(e){p(e.message)}finally{ei(!1)}},eZ=async e=>{if(!R||x||!c||!r)return;let t=ew.current;if(!t)return;let s=X(t,e.clientX,e.clientY);if(!s)return;let l=Date.now(),i=ey.current;i&&l-i.t<320&&28>Math.abs(i.x-s.x)&&28>Math.abs(i.y-s.y)?(ey.current=null,await h("double_tap",{x:s.x,y:s.y}),p(n("双击","Double tap"))):(ey.current={t:l,x:s.x,y:s.y},await h("tap",{x:s.x,y:s.y})),eT()},eO=async e=>{if(e.preventDefault(),x||!c||!r)return;let t=ew.current;if(!t)return;let s=X(t,e.clientX,e.clientY);s&&(await h("long_press",{x:s.x,y:s.y,duration:720}),p(n("长按","Long press")),eT())},eH=async e=>{if(!R||x||!c||!r)return;let t=eN.current;if(!t)return;let s=q(t,e.clientX,e.clientY);if(!s)return;let l=Date.now(),i=ey.current;i&&l-i.t<320&&28>Math.abs(i.x-s.x)&&28>Math.abs(i.y-s.y)?(ey.current=null,await h("double_tap",{x:s.x,y:s.y}),p(n("双击","Double tap"))):(ey.current={t:l,x:s.x,y:s.y},await h("tap",{x:s.x,y:s.y})),eo||eT()},eB=async e=>{if(e.preventDefault(),x||!c||!r)return;let t=eN.current;if(!t)return;let s=q(t,e.clientX,e.clientY);s&&(await h("long_press",{x:s.x,y:s.y,duration:720}),p(n("长按","Long press")),eo||eT())};if(!c)return(0,s.jsx)("div",{className:"rounded-2xl border border-amber-500/25 bg-amber-500/[0.06] p-6 text-center text-sm text-amber-200/90",children:n("宿主机未安装 adb,无法使用 Live 控制台。","adb is required for the Live console.")});let eK=Q(eP),eF=eK.Icon;return(0,s.jsxs)("div",{className:"space-y-5",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-sky-500/20 bg-gradient-to-br from-sky-500/[0.08] via-zinc-950/80 to-zinc-900/90 p-4 ring-1 ring-white/[0.05]",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-white/[0.06] pb-3",children:[(0,s.jsx)(A.Z,{className:"h-4 w-4 text-sky-400"}),(0,s.jsx)("h4",{className:"text-sm font-semibold text-white",children:n("链路管理","Link manager")}),(0,s.jsx)("span",{className:"text-[10px] text-zinc-500",children:n("USB / Redroid :5555 / 无线调试(先配对再连接)","USB \xb7 Redroid :5555 \xb7 wireless (pair then connect)")})]}),(0,s.jsxs)("div",{className:"mt-3 grid gap-3 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"space-y-2 rounded-xl border border-white/[0.06] bg-black/35 p-3",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"adb connect"}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("input",{className:"min-w-[12rem] flex-1 rounded-lg border border-white/10 bg-black/50 px-3 py-2 font-mono text-xs text-zinc-200",placeholder:"192.168.1.10:5555",value:L,onChange:e=>M(e.target.value),onKeyDown:e=>"Enter"===e.key&&void eI()}),(0,s.jsx)("button",{type:"button",disabled:el||x,onClick:()=>void eI(),className:"rounded-lg bg-sky-500/25 px-3 py-2 text-xs font-semibold text-sky-100 ring-1 ring-sky-400/40",children:el?"…":"Connect"}),(0,s.jsx)("button",{type:"button",disabled:el||x||!L.trim(),onClick:()=>eE(L),className:"rounded-lg border border-white/10 px-3 py-2 text-xs text-zinc-400 hover:text-zinc-200",children:n("存书签","Pin")})]}),er.length?(0,s.jsx)("div",{className:"flex flex-wrap gap-1.5 pt-1",children:er.map(e=>(0,s.jsx)("button",{type:"button",className:"rounded-md bg-white/[0.06] px-2 py-0.5 font-mono text-[10px] text-zinc-400 hover:bg-white/10",onClick:()=>M(e),children:e},e))}):null,(0,s.jsxs)("div",{className:"flex flex-wrap gap-2 pt-2",children:[(0,s.jsx)("button",{type:"button",disabled:el||x||!r,onClick:()=>void eD(r),className:"rounded-lg border border-rose-500/30 bg-rose-500/10 px-2.5 py-1.5 text-[10px] text-rose-200",children:n("断开当前 TCP","Disconnect current")}),(0,s.jsx)("button",{type:"button",disabled:el||x,onClick:()=>void eD(""),className:"rounded-lg border border-white/10 px-2.5 py-1.5 text-[10px] text-zinc-500 hover:text-zinc-300",children:n("断开全部 TCP","Disconnect all TCP")}),(0,s.jsxs)("button",{type:"button",disabled:el||x,onClick:()=>{b(),eT(),p(n("已刷新设备列表","Devices refreshed"))},className:"inline-flex items-center gap-1 rounded-lg border border-white/10 px-2.5 py-1.5 text-[10px] text-zinc-400",children:[(0,s.jsx)(y.Z,{className:"h-3 w-3"}),"ADB list"]})]})]}),(0,s.jsxs)("div",{className:"space-y-2 rounded-xl border border-white/[0.06] bg-black/35 p-3",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"adb pair(无线调试)"}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("input",{className:"w-32 rounded-lg border border-white/10 bg-black/50 px-2 py-1.5 font-mono text-xs",placeholder:"IP",value:T,onChange:e=>U(e.target.value)}),(0,s.jsx)("input",{className:"w-20 rounded-lg border border-white/10 bg-black/50 px-2 py-1.5 font-mono text-xs",placeholder:"port",value:E,onChange:e=>I(e.target.value)}),(0,s.jsx)("input",{className:"min-w-[6rem] flex-1 rounded-lg border border-white/10 bg-black/50 px-2 py-1.5 font-mono text-xs tracking-widest",placeholder:"123456",value:D,onChange:e=>es(e.target.value)}),(0,s.jsx)("button",{type:"button",disabled:el||x,onClick:()=>void eA(),className:"rounded-lg bg-violet-500/20 px-3 py-1.5 text-xs text-violet-100 ring-1 ring-violet-400/35",children:"Pair"})]}),(0,s.jsx)("p",{className:"text-[10px] leading-relaxed text-zinc-600",children:n("手机上「无线调试」会显示配对端口与 6 位码;配对成功后用上方 connect 连接 adb 显示的 IP:5555。","Use the pairing port + 6-digit code from Wireless debugging; then connect to the listed adb IP:5555.")})]})]})]}),(0,s.jsxs)("div",{className:"relative overflow-hidden rounded-3xl border border-emerald-500/25 bg-gradient-to-br from-emerald-500/[0.12] via-zinc-950/90 to-violet-500/[0.08] p-1 shadow-2xl shadow-emerald-900/20 ring-1 ring-white/[0.06]",children:[(0,s.jsx)("div",{className:"pointer-events-none absolute -right-20 -top-20 h-56 w-56 rounded-full bg-emerald-500/10 blur-3xl","aria-hidden":!0}),(0,s.jsxs)("div",{className:"relative rounded-[1.35rem] border border-white/[0.06] bg-zinc-950/80 p-4 backdrop-blur-sm",children:[(0,s.jsxs)("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between",children:[(0,s.jsxs)("div",{className:"flex items-start gap-3",children:[(0,s.jsx)("div",{className:"flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl bg-gradient-to-br from-emerald-400/30 to-violet-500/25 ring-1 ring-white/10",children:(0,s.jsx)(m.Z,{className:"h-6 w-6 text-emerald-200"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-base font-semibold tracking-tight text-white",children:n("无人直播系统 \xb7 ADB 云控台","Unmanned Live System \xb7 ADB farm console")}),(0,s.jsxs)("p",{className:"mt-1 max-w-xl text-[11px] leading-relaxed text-zinc-500",children:[n("统一适配 USB / Redroid / 无线 adb:已授权设备默认走官方 scrcpy-server 的 WebSocket H.264 真流(与桌面 ","USB / Redroid / wireless adb: authorized devices default to official scrcpy-server WebSocket H.264 (same stack as "),(0,s.jsx)("a",{href:et,target:"_blank",rel:"noreferrer",className:"text-emerald-300/90 underline-offset-2 hover:underline",children:"escrcpy"}),n(" / "," / "),(0,s.jsx)("a",{href:ee,target:"_blank",rel:"noreferrer",className:"text-emerald-300/90 underline-offset-2 hover:underline",children:"scrcpy"}),n(");无 jar 或关闭真流时用截图。","); PNG screenshot when jar missing or stream off.")]})]})]}),(0,s.jsxs)("div",{className:"flex shrink-0 flex-col gap-1.5 self-start sm:flex-row",children:[(0,s.jsxs)("a",{href:et,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 rounded-xl border border-white/10 bg-white/[0.04] px-3 py-2 text-[11px] font-medium text-zinc-300 hover:bg-white/[0.07]",children:["escrcpy",(0,s.jsx)(Z.Z,{className:"h-3.5 w-3.5 opacity-70"})]}),(0,s.jsxs)("a",{href:ee,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 rounded-xl border border-white/10 bg-white/[0.04] px-3 py-2 text-[11px] font-medium text-zinc-300 hover:bg-white/[0.07]",children:["scrcpy",(0,s.jsx)(Z.Z,{className:"h-3.5 w-3.5 opacity-70"})]})]})]}),a.length>0?(0,s.jsxs)("div",{className:"mt-5",children:[(0,s.jsxs)("p",{className:"mb-2 flex items-center gap-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:[(0,s.jsx)(O.Z,{className:"h-3.5 w-3.5"}),n("设备矩阵","Device matrix")]}),(0,s.jsx)("div",{className:"flex gap-2 overflow-x-auto pb-1 [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",children:a.map(e=>{let t="device"===e.state,l=r===e.serial,i=Q(e.transport),a=i.Icon;return(0,s.jsxs)("button",{type:"button",onClick:()=>o(e.serial),className:"flex min-w-[9rem] flex-col rounded-xl border px-3 py-2 text-left transition ".concat(l?"border-emerald-500/50 bg-emerald-500/15 ring-1 ring-emerald-400/30":"border-white/10 bg-black/30 hover:border-white/20"),children:[(0,s.jsxs)("span",{className:"flex items-center gap-1.5 text-xs font-medium text-zinc-200",children:[(0,s.jsx)(d.Z,{className:"h-3.5 w-3.5 text-emerald-400/80"}),(0,s.jsx)("span",{className:"truncate",children:e.model||e.serial.slice(0,10)})]}),(0,s.jsx)("span",{className:"mt-0.5 truncate font-mono text-[9px] text-zinc-600",children:e.serial}),(0,s.jsxs)("div",{className:"mt-1 flex flex-wrap gap-1",children:[(0,s.jsxs)("span",{className:"inline-flex items-center gap-0.5 rounded-md px-1.5 py-0.5 text-[9px] font-semibold ring-1 ".concat(i.cls),children:[(0,s.jsx)(a,{className:"h-2.5 w-2.5"}),n(i.zh,i.en)]}),(0,s.jsx)("span",{className:"rounded-md px-1.5 py-0.5 text-[9px] font-semibold ".concat(t?"bg-emerald-500/20 text-emerald-200":"bg-zinc-600/30 text-zinc-500"),children:e.state})]})]},e.serial)})})]}):null,(0,s.jsxs)("div",{className:"mt-6 grid gap-6 xl:grid-cols-12",children:[(0,s.jsxs)("div",{className:"xl:col-span-8",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-white/[0.06] pb-3",children:[(0,s.jsx)("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:n("刷新间隔","Interval")}),$.map(e=>(0,s.jsx)("button",{type:"button",onClick:()=>w(e),className:"rounded-lg px-2.5 py-1 text-[10px] font-semibold transition ".concat(v===e?"bg-violet-500/25 text-violet-100 ring-1 ring-violet-400/35":"bg-black/30 text-zinc-500 hover:text-zinc-300"),children:0===e?n("手动","Manual"):"".concat(e,"ms")},e)),(0,s.jsxs)("span",{className:"ml-1 inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-[9px] font-medium ring-1 ".concat(eK.cls),children:[(0,s.jsx)(eF,{className:"h-3 w-3"}),"tcp"===eP?n("建议 ≥450ms","Suggest ≥450ms"):n("可试 280ms","Try 280ms")]}),(0,s.jsxs)("button",{type:"button",disabled:x,onClick:()=>void eT(),className:"ml-auto inline-flex items-center gap-1 rounded-lg border border-white/10 bg-white/[0.05] px-2.5 py-1 text-[10px] text-zinc-300 hover:bg-white/[0.08]",children:[(0,s.jsx)(y.Z,{className:"h-3 w-3 ".concat(N?"animate-spin":"")}),n("下一帧","Next frame")]}),(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>void h("wake"),className:"rounded-lg bg-amber-500/20 px-2.5 py-1 text-[10px] font-semibold text-amber-100 ring-1 ring-amber-500/30",children:"Wake"}),(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-1.5 text-[10px] text-zinc-400",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/50",checked:R,onChange:e=>P(e.target.checked)}),(0,s.jsx)(H.Z,{className:"h-3 w-3"}),n("点按穿透","Tap-through")]}),(0,s.jsxs)("button",{type:"button",disabled:x||!r||!(null==eb?void 0:eb.server_jar),title:eb&&!eb.server_jar&&eb.hint_zh?eb.hint_zh:n("官方 scrcpy-server + WebSocket H.264","Official scrcpy-server + WebSocket H.264"),onClick:()=>{ec(e=>{let t=!e;return t?(ex(null),p(n("已开启实时画面(H.264 WebSocket)","Live H.264 WebSocket stream on"))):(r&&ex(r),p(n("已关闭实时画面(将使用截图)","Live stream off — screenshot mode"))),t})},className:"inline-flex items-center gap-1 rounded-lg border px-2.5 py-1 text-[10px] font-semibold transition ".concat(eo?"border-cyan-400/50 bg-cyan-500/20 text-cyan-100 ring-1 ring-cyan-400/35":"border-white/10 bg-black/30 text-zinc-400 hover:text-zinc-200"),children:[(0,s.jsx)(B.Z,{className:"h-3 w-3"}),eo?n("关闭真流","Stop WS"):n("实时画面","Live H.264")]})]}),eb&&!eb.server_jar?(0,s.jsxs)("p",{className:"mt-2 text-[10px] text-amber-200/80",children:[n("未检测到 scrcpy-server:启动时会自动拉取;内网可在 runtime.env 配置 SCRCPY_SERVER_DOWNLOAD_URL(支持 {tag})。","scrcpy-server missing: auto-fetched on startup; set SCRCPY_SERVER_DOWNLOAD_URL ({tag}) for mirrors."),eb.server_version?" (".concat(n("期望版本","version")," ").concat(eb.server_version,")"):null]}):null,(0,s.jsx)("p",{className:"mt-2 text-[10px] text-zinc-600",children:n("快捷键(镜像区聚焦时):H Home \xb7 B Back \xb7 R 多任务 \xb7 W 唤醒 \xb7 M 菜单","Hotkeys (mirror focused): H Home \xb7 B Back \xb7 R Recents \xb7 W Wake \xb7 M Menu")}),(0,s.jsxs)("div",{className:"relative mx-auto mt-4 max-h-[min(78vh,720px)] min-h-[280px]",children:[r?(0,s.jsxs)("div",{ref:ez,tabIndex:0,onKeyDown:e=>{if(!r||x)return;let t=e.target.tagName;if("INPUT"===t||"TEXTAREA"===t||"SELECT"===t)return;let n={h:["key",{keycode:"3"}],b:["key",{keycode:"4"}],r:["key",{keycode:"187"}],w:["wake",void 0],m:["key",{keycode:"82"}]}[e.key.toLowerCase()];n&&(e.preventDefault(),(async()=>{await h(n[0],n[1]),eo||eT()})())},className:"relative flex justify-center outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/50",children:[(0,s.jsxs)("div",{className:"relative rounded-[2rem] border-[10px] border-zinc-800 bg-black shadow-inner shadow-black/80 ring-1 ring-white/10",style:{maxHeight:"min(72vh, 680px)"},children:[(0,s.jsx)("div",{className:"absolute left-1/2 top-0 z-10 h-5 w-24 -translate-x-1/2 rounded-b-xl bg-black/80"}),eo?(0,s.jsx)("canvas",{ref:eN,className:"max-h-[min(72vh,680px)] w-auto max-w-full rounded-[1.35rem] object-contain ".concat(R?"cursor-crosshair":"cursor-default"),draggable:!1,onClick:eH,onContextMenu:eB}):(0,s.jsx)("img",{ref:ew,src:eM||void 0,alt:"device",className:"max-h-[min(72vh,680px)] w-auto max-w-full rounded-[1.35rem] object-contain ".concat(R?"cursor-crosshair":"cursor-default"),draggable:!1,onLoadStart:()=>{j(!0)},onLoad:()=>{j(!1),eS.current=0,z(null)},onError:()=>{j(!1),eS.current+=1,eS.current<=3?(z(null),window.setTimeout(()=>eT(),380+200*eS.current)):z(n("截图连续失败:检查 USB 授权 / 无线是否断开 / Redroid 端口","Screenshot failed repeatedly"))},onClick:eZ,onContextMenu:eO})]}),eu?(0,s.jsxs)("div",{className:"pointer-events-none absolute bottom-3 right-3 flex items-center gap-1 rounded-full bg-cyan-500/90 px-2 py-0.5 text-[9px] font-bold text-cyan-950 shadow-lg",children:[(0,s.jsx)(B.Z,{className:"h-3 w-3"}),"SCRCPY\xb7WS"]}):v>0&&!eo?(0,s.jsxs)("div",{className:"pointer-events-none absolute bottom-3 right-3 flex items-center gap-1 rounded-full bg-emerald-500/90 px-2 py-0.5 text-[9px] font-bold text-emerald-950 shadow-lg",children:[(0,s.jsx)(K.Z,{className:"h-3 w-3"}),"LIVE"]}):eo?null:(0,s.jsxs)("div",{className:"pointer-events-none absolute bottom-3 right-3 flex items-center gap-1 rounded-full bg-zinc-700/90 px-2 py-0.5 text-[9px] font-bold text-zinc-200",children:[(0,s.jsx)(F.Z,{className:"h-3 w-3"}),n("单帧","Still")]})]}):(0,s.jsx)("p",{className:"py-16 text-center text-sm text-zinc-600",children:n("请选择或连接设备","Pick or connect a device")}),eh?(0,s.jsx)("p",{className:"mt-3 text-center text-xs text-rose-300",children:eh}):null,k&&!eo?(0,s.jsx)("p",{className:"mt-3 text-center text-xs text-rose-300",children:k}):null,(0,s.jsx)("p",{className:"mt-3 text-center text-[10px] text-zinc-600",children:n("左键单击 / 双击 \xb7 右键长按 \xb7 坐标对齐 PNG 像素","Left tap/double \xb7 right long-press \xb7 PNG pixel coords")})]})]}),(0,s.jsxs)("div",{className:"space-y-4 xl:col-span-4",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-black/40 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:n("遥测","Telemetry")}),u?(0,s.jsxs)("dl",{className:"mt-3 space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"device"}),(0,s.jsxs)("dd",{className:"text-right text-zinc-200",children:[u.brand," ",u.model]})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"Android"}),(0,s.jsxs)("dd",{className:"text-zinc-300",children:[u.android_version," (API ",u.sdk,")"]})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"wm size"}),(0,s.jsx)("dd",{className:"text-cyan-300/90",children:S?"".concat(S.width,"\xd7").concat(S.height):u.resolution||"—"})]}),(0,s.jsx)("div",{className:"whitespace-pre-wrap text-[10px] leading-snug text-zinc-500",children:u.battery})]}):(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-600",children:n("在上方点「刷新设备信息」","Use Refresh device info above")})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/20 bg-gradient-to-b from-violet-500/[0.08] to-black/40 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-violet-300/80",children:n("导航坞","Nav dock")}),(0,s.jsx)("div",{className:"mt-3 grid grid-cols-3 gap-2",children:[["3","Home"],["4","Back"],["187","Recents"]].map(e=>{let[t,n]=e;return(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>{h("key",{keycode:t}),eT()},className:"rounded-xl border border-white/10 bg-white/[0.06] py-3 text-xs font-semibold text-zinc-200 hover:bg-white/[0.1]",children:n},t)})}),(0,s.jsxs)("div",{className:"mt-2 grid grid-cols-2 gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>{h("key",{keycode:"24"}),eT()},className:"rounded-xl border border-white/10 bg-black/30 py-2 text-[11px] text-zinc-300",children:"Vol+"}),(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>{h("key",{keycode:"25"}),eT()},className:"rounded-xl border border-white/10 bg-black/30 py-2 text-[11px] text-zinc-300",children:"Vol−"})]})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-cyan-500/[0.05] p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-cyan-300/80",children:n("手势","Gestures")}),(0,s.jsx)("div",{className:"mt-2 grid grid-cols-2 gap-2",children:["up","down","left","right"].map(e=>(0,s.jsx)("button",{type:"button",disabled:x||!r,onClick:()=>{h("swipe",{direction:e}),eT()},className:"rounded-lg border border-white/10 bg-black/30 py-2 font-mono text-[10px] uppercase text-zinc-300",children:e},e))})]})]})]})]})]})]})}let el=[{label:"getprop",cmd:"getprop ro.build.version.release"},{label:"top pkg",cmd:"dumpsys activity activities | grep -E 'mResumedActivity' | tail -n 1"},{label:"usb",cmd:"dumpsys usb | head -n 60"},{label:"surface",cmd:"dumpsys SurfaceFlinger | head -n 40"}];function ei(e,t,n){return e?(0,s.jsx)("span",{className:"rounded bg-emerald-500/15 px-2 py-0.5 text-[10px] text-emerald-200",children:t}):(0,s.jsx)("span",{className:"rounded bg-zinc-500/15 px-2 py-0.5 text-[10px] text-zinc-400",children:n})}function er(e){var t,n,l,i,r,a,o,c,d,x,u,m,h,p,b;let{t:g,notify:f,fetchJson:y,apiBase:w,busy:N,androidSerial:j,setAndroidSerial:k,devices:z,adbAvailable:S,apkPath:C,setApkPath:R,onAndroidAction:P,onCopy:I,onRefreshDevices:D}=e,[A,Z]=(0,_.useState)(null),[O,H]=(0,_.useState)(null),[B,K]=(0,_.useState)(null),[F,W]=(0,_.useState)(null),[Y,J]=(0,_.useState)(""),[G,V]=(0,_.useState)([]),[q,X]=(0,_.useState)("getprop ro.product.model"),[$,Q]=(0,_.useState)(""),[ee,et]=(0,_.useState)("300"),[en,er]=(0,_.useState)(""),[ea,eo]=(0,_.useState)(null),[ec,ed]=(0,_.useState)([]),[ex,eu]=(0,_.useState)(null),[em,eh]=(0,_.useState)("https://"),[ep,eb]=(0,_.useState)(""),[eg,ef]=(0,_.useState)(!1),[ev,ey]=(0,_.useState)(null),ew=!!(N||ev),eN=z.find(e=>e.serial===j)||null,ej=(0,_.useCallback)(async()=>{if(!j||!S){Z(null),H(null);return}ey("overview"),H(null);try{let e=await y("/android/overview?serial=".concat(encodeURIComponent(j)));Z(e)}catch(e){Z(null),H(e.message)}finally{ey(null)}},[S,j,y]),ek=(0,_.useCallback)(async()=>{W(null);try{let e=await y("/redroid/summary");K(e)}catch(e){K(null),W(e.message)}},[y]);(0,_.useEffect)(()=>{ej()},[ej]),(0,_.useEffect)(()=>{ek()},[ek]);let ez=async()=>{if(!j){f(g("请选择设备","Pick a device"));return}ey("packages");try{let e=encodeURIComponent(Y.trim()),t=await y("/android/packages?serial=".concat(encodeURIComponent(j),"&query=").concat(e,"&limit=80"));V(t.packages||[])}catch(e){f(e.message),V([])}finally{ey(null)}},eS=async()=>{if(!j){f(g("请选择设备","Pick a device"));return}let e=q.trim();if(e){ey("shell");try{var t,n;let s=await y("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"shell",serial:j,payload:{command:e}})});Q(null!==(n=null!==(t=s.output)&&void 0!==t?t:s.message)&&void 0!==n?n:"")}catch(e){Q(e.message)}finally{ey(null)}}},e_=(0,_.useCallback)(async e=>{if(!j)return;let t=Math.min(3e3,Math.max(1,parseInt(ee,10)||200)),n=!!(null==e?void 0:e.silent);n||ey("logcat"),eo(null);try{var s;let e=await y("/android/logcat?serial=".concat(encodeURIComponent(j),"&lines=").concat(t));er(null!==(s=e.text)&&void 0!==s?s:"")}catch(e){er(""),eo(e.message)}finally{n||ey(null)}},[j,y,ee]);(0,_.useEffect)(()=>{if(!eg||!j||!S)return;let e=window.setInterval(()=>void e_({silent:!0}),3e3);return e_({silent:!0}),()=>clearInterval(e)},[S,j,eg,e_]);let eC=async()=>{if(!j){f(g("请选择设备","Pick a device"));return}ey("ui"),eu(null);try{let e=await y("/android/ui?serial=".concat(encodeURIComponent(j),"&limit=100"));ed(e.nodes||[])}catch(e){ed([]),eu(e.message)}finally{ey(null)}},eR=async(e,t)=>{ey("redroid:".concat(e));try{let n=await y("/redroid/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,name:t||""})});n.summary&&K(n.summary),f(n.message||"OK"),await ek(),D()}catch(e){f(e.message)}finally{ey(null)}},eP=async e=>{await P("key",{keycode:e})},eL=async()=>{let e=ep.trim();if(!e){f(g("请输入文字","Enter text"));return}await P("text",{text:e})},eM=async()=>{let e=em.trim();if(!e||"https://"===e){f(g("请输入 URL","Enter URL"));return}await P("open_url",{url:e})};return(0,s.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("安卓设备工作台","Android workstation")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:g("USB 真机与 Redroid 共用一套控制面,优先保证 USB 真机稳定。","USB phone and Redroid share one control surface.")})]}),S?(0,s.jsxs)("div",{className:"flex gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ew||!j,onClick:()=>void ej(),className:"rounded-lg border border-white/10 bg-white/[0.05] px-3 py-1.5 text-xs text-zinc-300",children:g("刷新设备","Refresh device")}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>{ek(),D()},className:"rounded-lg border border-white/10 bg-white/[0.05] px-3 py-1.5 text-xs text-zinc-300",children:g("刷新 Redroid","Refresh Redroid")})]}):(0,s.jsx)("span",{className:"text-xs text-amber-200/90",children:g("宿主机未检测到 adb","adb not found on host")})]}),(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:z.map(e=>(0,s.jsxs)("button",{type:"button",onClick:()=>k(e.serial),className:"rounded-xl border px-4 py-2 text-left text-xs ".concat(j===e.serial?"border-violet-500/50 bg-violet-500/10 text-white":"border-white/10 bg-black/30 text-zinc-400"),children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("span",{className:"font-medium text-zinc-200",children:e.model||e.serial}),e.transport?(0,s.jsx)("span",{className:"rounded bg-white/10 px-1.5 py-0.5 font-mono text-[9px] uppercase text-zinc-500",children:e.transport}):null,e.kind?(0,s.jsx)("span",{className:"rounded bg-cyan-500/10 px-1.5 py-0.5 font-mono text-[9px] uppercase text-cyan-200",children:e.kind}):null]}),(0,s.jsx)("div",{className:"text-[10px] text-zinc-600",children:e.serial}),"device"!==(e.state||"").toLowerCase()?(0,s.jsx)("div",{className:"mt-1 text-[10px] font-medium text-amber-200/90",children:"unauthorized"===e.state?g("未授权,请在手机上允许 USB 调试。","Unauthorized, allow USB debugging on device."):"".concat(g("状态","State"),": ").concat(e.state)}):null]},e.serial))}),S&&0===z.length?(0,s.jsx)("p",{className:"mt-4 rounded-lg border border-amber-500/20 bg-amber-500/5 p-3 text-xs leading-relaxed text-amber-200/90",children:g("当前没有已授权设备。USB 真机请检查调试授权;Redroid 请先启动实例,再 adb connect 127.0.0.1:5555。","No authorized devices. For USB phones, confirm USB debugging. For Redroid, start an instance then adb connect 127.0.0.1:5555.")}):null]}),(0,s.jsxs)("div",{className:"grid gap-4 xl:grid-cols-[1.1fr_0.9fr]",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/15 bg-zinc-950/50 p-5",children:[(0,s.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-violet-300/90",children:g("真机诊断","Phone diagnostics")}),O?(0,s.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:O}):null,A?(0,s.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,s.jsxs)("dl",{className:"space-y-1.5 font-mono text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"model"})," ",(0,s.jsxs)("dd",{className:"inline text-zinc-300",children:[A.brand," ",A.model]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"android"})," ",(0,s.jsxs)("dd",{className:"inline text-zinc-300",children:[A.android_version," (sdk ",A.sdk,")"]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"kind"})," ",(0,s.jsxs)("dd",{className:"inline text-zinc-300",children:[A.kind||(null==eN?void 0:eN.kind)||"unknown"," / ",A.transport||(null==eN?void 0:eN.transport)||"unknown"]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"display"})," ",(0,s.jsx)("dd",{className:"inline text-zinc-300",children:A.resolution})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"inline text-zinc-600",children:"rotation"})," ",(0,s.jsx)("dd",{className:"inline text-zinc-300",children:A.rotation})]}),(0,s.jsx)("div",{className:"whitespace-pre-wrap text-[10px] leading-snug text-zinc-500",children:A.battery}),(0,s.jsx)("div",{className:"line-clamp-3 text-[10px] text-zinc-500",children:A.focus})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[ei(null===(t=A.diagnostics)||void 0===t?void 0:t.ready,g("已启动","Boot ready"),g("未完成启动","Boot pending")),ei(null===(n=A.diagnostics)||void 0===n?void 0:n.google_play,"Google Play","No Play"),ei(null===(l=A.diagnostics)||void 0===l?void 0:l.google_services,"GMS","No GMS"),ei(null===(i=A.diagnostics)||void 0===i?void 0:i.magisk,"Magisk","No Magisk"),ei(null===(r=A.diagnostics)||void 0===r?void 0:r.root,"Root","No root")]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/5 bg-black/20 p-3 text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{children:["boot_completed: ",(null===(a=A.diagnostics)||void 0===a?void 0:a.boot_completed)||"-"]}),(0,s.jsxs)("div",{children:["provisioned: ",(null===(o=A.diagnostics)||void 0===o?void 0:o.device_provisioned)||"-"]}),(0,s.jsxs)("div",{children:["setup_complete: ",(null===(c=A.diagnostics)||void 0===c?void 0:c.user_setup_complete)||"-"]}),(0,s.jsxs)("div",{children:["abi: ",(null===(d=A.diagnostics)||void 0===d?void 0:d.abi)||"-"]}),(0,s.jsxs)("div",{className:"truncate",children:["hardware: ",(null===(x=A.diagnostics)||void 0===x?void 0:x.hardware)||"-"]})]})]}):O?null:(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:g("加载中","Loading")})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-zinc-950/50 p-5",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,s.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-cyan-300/90",children:g("Redroid 板块","Redroid panel")}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("start"),className:"rounded-lg bg-emerald-500/20 px-3 py-1.5 text-xs text-emerald-100 ring-1 ring-emerald-500/30",children:g("启动默认实例","Start default")})]}),F?(0,s.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:F}):null,B?(0,s.jsxs)("div",{className:"mt-3 space-y-3 text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,s.jsxs)("div",{children:["arch: ",B.arch||"-"]}),(0,s.jsxs)("div",{className:"truncate",children:["image: ",B.image||"-"]}),(0,s.jsxs)("div",{children:["profile: ",B.device_profile||"-"]}),(0,s.jsxs)("div",{children:["gpu: ",B.gpu_mode||"-"]}),(0,s.jsxs)("div",{children:["adb: 127.0.0.1:",B.default_port||5555]})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[ei(null===(u=B.requirements)||void 0===u?void 0:u.docker_available,"Docker","No Docker"),ei(null===(m=B.requirements)||void 0===m?void 0:m.adb_available,"ADB","No ADB"),ei(null===(h=B.requirements)||void 0===h?void 0:h.kvm,"KVM","No KVM"),ei(null===(p=B.requirements)||void 0===p?void 0:p.binderfs,"binderfs","No binderfs")]}),(0,s.jsxs)("div",{className:"space-y-2",children:[(B.instances||[]).map(e=>{var t,n,l,i;return(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-3",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"font-medium text-zinc-100",children:e.name}),(0,s.jsxs)("div",{className:"font-mono text-[10px] text-zinc-500",children:[e.port?"127.0.0.1:".concat(e.port):"-"," / ",e.status_text||"-"]})]}),(0,s.jsxs)("div",{className:"flex gap-1",children:[(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("start",e.name),className:"rounded bg-emerald-500/15 px-2 py-1 text-[10px] text-emerald-200",children:"Start"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("restart",e.name),className:"rounded bg-amber-500/15 px-2 py-1 text-[10px] text-amber-200",children:"Restart"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("adb_connect",e.name),className:"rounded bg-cyan-500/15 px-2 py-1 text-[10px] text-cyan-200",children:"ADB"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eR("stop",e.name),className:"rounded bg-rose-500/15 px-2 py-1 text-[10px] text-rose-200",children:"Stop"})]})]}),(0,s.jsxs)("div",{className:"mt-2 flex flex-wrap gap-2",children:[ei(null===(t=e.diagnostics)||void 0===t?void 0:t.ready,g("系统就绪","System ready"),g("启动中","Booting")),ei(null===(n=e.diagnostics)||void 0===n?void 0:n.google_play,"Play","No Play"),ei(null===(l=e.diagnostics)||void 0===l?void 0:l.magisk,"Magisk","No Magisk"),ei(null===(i=e.diagnostics)||void 0===i?void 0:i.root,"Root","No root")]}),e.data_dir?(0,s.jsx)("div",{className:"mt-2 truncate font-mono text-[10px] text-zinc-500",children:e.data_dir}):null]},e.name)}),(null===(b=B.instances)||void 0===b?void 0:b.length)?null:(0,s.jsx)("p",{className:"rounded-xl border border-white/5 bg-black/20 p-3 text-xs text-zinc-500",children:g("当前没有 Redroid 实例。默认动作会创建 redroid13-1。","No Redroid instances yet. Default actions create redroid13-1.")})]})]}):(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:g("读取 Redroid 状态中","Loading Redroid status")})]})]}),(0,s.jsx)(es,{t:g,apiBase:w,fetchJson:y,serial:j,devices:z,setSerial:k,adbAvailable:S,lock:ew,overview:A,onAndroidAction:P,notify:f,onRefreshDevices:D}),S&&j?(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,s.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-emerald-300/90",children:g("快捷控制","Quick controls")}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("3"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Home"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("4"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Back"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("187"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Recents"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("wake"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Wake"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("launch_package",{package:"com.zhiliaoapp.musically"}),className:"rounded-lg bg-gradient-to-r from-pink-500/25 to-violet-500/25 px-3 py-1.5 text-xs ring-1 ring-white/10",children:"TikTok"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("24"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Vol+"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("25"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Vol-"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eP("66"),className:"rounded-lg border border-white/10 bg-white/[0.04] px-3 py-1.5 text-xs",children:"Enter"})]}),(0,s.jsx)("p",{className:"mt-3 text-[10px] text-zinc-600",children:g("滑动手势","Swipe gestures")}),(0,s.jsx)("div",{className:"mt-1 flex flex-wrap gap-2",children:["up","down","left","right"].map(e=>(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("swipe",{direction:e}),className:"rounded-lg border border-white/10 bg-black/30 px-2.5 py-1 font-mono text-[10px] uppercase text-zinc-300",children:e},e))}),(0,s.jsxs)("div",{className:"mt-4 rounded-lg border border-white/5 bg-black/20 p-3",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:g("ADB 文本输入","ADB text input")}),(0,s.jsxs)("div",{className:"mt-2 flex flex-col gap-2 sm:flex-row",children:[(0,s.jsx)("input",{className:"min-w-0 flex-1 rounded-lg border border-white/10 bg-black/40 px-3 py-2 text-xs",value:ep,onChange:e=>eb(e.target.value),placeholder:"hello / 123",onKeyDown:e=>{"Enter"===e.key&&eL()}}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eL(),className:"rounded-lg bg-emerald-500/20 px-3 py-2 text-xs text-emerald-100 ring-1 ring-emerald-500/30",children:g("发送","Send")})]})]}),(0,s.jsxs)("div",{className:"mt-4 flex flex-col gap-2 sm:flex-row sm:items-center",children:[(0,s.jsx)("input",{className:"min-w-0 flex-1 rounded-lg border border-white/10 bg-black/40 px-3 py-2 text-xs",value:em,onChange:e=>eh(e.target.value),placeholder:"https://"}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eM(),className:"rounded-lg bg-violet-500/20 px-3 py-2 text-xs text-violet-100 ring-1 ring-violet-500/30",children:g("打开链接","Open URL")})]})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,s.jsxs)("h4",{className:"flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-cyan-300/90",children:[(0,s.jsx)(L.Z,{className:"h-4 w-4"}),g("USB 真机优化建议","USB optimization")]}),(0,s.jsxs)("ul",{className:"mt-3 space-y-2 text-xs leading-relaxed text-zinc-400",children:[(0,s.jsx)("li",{children:g("优先使用主板直连 USB,不要经过不稳的 HUB。","Prefer direct motherboard USB, not unstable hubs.")}),(0,s.jsx)("li",{children:g("开发板端固定 adb server,避免频繁 kill-server。","Keep adb server stable and avoid frequent kill-server.")}),(0,s.jsx)("li",{children:g("镜像页默认支持 scrcpy H.264 真流,截图模式作为回退。","Use scrcpy H.264 live stream first, screenshot mode as fallback.")}),(0,s.jsx)("li",{children:g("如果 TikTok / YouTube App 直播,要先确认屏幕常亮、分辨率稳定、USB 供电足够。","For TikTok / YouTube app live, keep screen on, resolution stable, and USB power sufficient.")})]})]})]}):null,S&&j?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(M.Z,{className:"h-4 w-4 text-emerald-400"}),g("包名搜索与启动","Packages")]}),(0,s.jsxs)("div",{className:"mt-3 flex flex-col gap-2 sm:flex-row",children:[(0,s.jsx)("input",{className:"min-w-0 flex-1 rounded-xl border border-white/10 bg-black/40 px-4 py-2 text-sm",value:Y,onChange:e=>J(e.target.value),placeholder:"tiktok / musically / youtube",onKeyDown:e=>{"Enter"===e.key&&ez()}}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void ez(),className:"rounded-xl bg-emerald-500/20 px-4 py-2 text-sm text-emerald-100 ring-1 ring-emerald-500/30",children:g("搜索","Search")})]}),(0,s.jsxs)("ul",{className:"mt-4 max-h-48 space-y-1 overflow-y-auto rounded-lg border border-white/5 bg-black/30 p-2 font-mono text-[11px]",children:[G.map(e=>(0,s.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 py-1 text-zinc-400",children:[(0,s.jsx)("span",{className:"min-w-0 truncate text-zinc-300",children:e.package}),(0,s.jsxs)("span",{className:"flex shrink-0 gap-1",children:[(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("launch_package",{package:e.package}),className:"rounded bg-white/10 px-2 py-0.5 text-[10px] text-zinc-200",children:g("启动","Launch")}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("force_stop",{package:e.package}),className:"rounded bg-rose-500/15 px-2 py-0.5 text-[10px] text-rose-200",children:g("停止","Stop")})]})]},e.package)),G.length?null:(0,s.jsx)("li",{className:"py-2 text-center text-zinc-600",children:g("暂无结果","No results")})]})]}):null,S&&j?(0,s.jsxs)("div",{className:"grid gap-6 xl:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(T.Z,{className:"h-4 w-4 text-amber-400"}),"ADB shell"]}),(0,s.jsx)("div",{className:"mt-2 flex flex-wrap gap-1.5",children:el.map(e=>(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>X(e.cmd),className:"rounded-md border border-white/10 bg-white/[0.04] px-2 py-1 text-[10px] text-zinc-400 hover:text-zinc-200",children:e.label},e.label))}),(0,s.jsx)("textarea",{className:"mt-3 min-h-[100px] w-full resize-y rounded-xl border border-white/10 bg-black/50 p-3 font-mono text-xs text-zinc-200",value:q,onChange:e=>X(e.target.value),spellCheck:!1,onKeyDown:e=>{"Enter"===e.key&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),eS())}}),(0,s.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eS(),className:"rounded-xl bg-amber-500/20 px-4 py-2 text-sm text-amber-100 ring-1 ring-amber-500/30",children:"shell"===ev?(0,s.jsxs)("span",{className:"inline-flex items-center gap-2",children:[(0,s.jsx)(v.Z,{className:"h-3.5 w-3.5 animate-spin"}),"Run"]}):"Run"}),$?(0,s.jsxs)("button",{type:"button",disabled:!$,onClick:()=>I($),className:"inline-flex items-center gap-1 rounded-lg border border-white/10 px-3 py-1.5 text-xs text-zinc-400 hover:text-zinc-200",children:[(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"}),g("复制输出","Copy")]}):null]}),$?(0,s.jsx)("pre",{className:"mt-3 max-h-64 overflow-auto whitespace-pre-wrap rounded-lg border border-white/5 bg-black/40 p-3 font-mono text-[11px] text-zinc-400 xl:max-h-[min(24rem,50vh)]",children:$}):null]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("Logcat","Logcat")}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[(0,s.jsx)("input",{className:"w-24 rounded-lg border border-white/10 bg-black/40 px-3 py-2 font-mono text-xs",value:ee,onChange:e=>et(e.target.value)}),(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 text-[11px] text-zinc-400",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:eg,onChange:e=>ef(e.target.checked)}),g("每 3 秒自动刷新","Auto every 3s")]}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void e_(),className:"rounded-xl bg-cyan-500/20 px-4 py-2 text-sm text-cyan-100 ring-1 ring-cyan-500/30",children:g("拉取日志","Pull logs")}),en?(0,s.jsxs)("button",{type:"button",onClick:()=>I(en),className:"inline-flex items-center gap-1 rounded-lg border border-white/10 px-3 py-1.5 text-xs text-zinc-400 hover:text-zinc-200",children:[(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"}),g("复制","Copy")]}):null]}),ea?(0,s.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:ea}):null,en?(0,s.jsx)("pre",{className:"mt-3 max-h-72 overflow-auto whitespace-pre-wrap rounded-lg border border-white/5 bg-black/50 p-3 font-mono text-[10px] leading-tight text-zinc-500 xl:max-h-[min(24rem,50vh)]",children:en}):null]})]}):null,S&&j?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(E.Z,{className:"h-4 w-4 text-fuchsia-400"}),g("界面节点","UI nodes")]}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void eC(),className:"mt-3 rounded-xl border border-fuchsia-500/30 bg-fuchsia-500/10 px-4 py-2 text-sm text-fuchsia-100",children:g("刷新节点","Refresh nodes")}),ex?(0,s.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:ex}):null,(0,s.jsxs)("ul",{className:"mt-3 max-h-64 space-y-1 overflow-y-auto rounded-lg border border-white/5 bg-black/30 p-2 text-[11px]",children:[ec.map((e,t)=>(0,s.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 border-b border-white/[0.04] py-1.5 text-zinc-400 last:border-0",children:[(0,s.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,s.jsx)("span",{className:"text-zinc-200",children:e.label}),e.resource_id?(0,s.jsx)("span",{className:"ml-2 font-mono text-[10px] text-zinc-600",children:e.resource_id}):null,(0,s.jsxs)("div",{className:"font-mono text-[10px] text-zinc-600",children:["(",e.center_x,", ",e.center_y,")",e.clickable?" click":""]})]}),(0,s.jsx)("button",{type:"button",disabled:ew,onClick:()=>void P("tap",{x:e.center_x,y:e.center_y}),className:"shrink-0 rounded bg-white/10 px-2 py-1 text-[10px] text-zinc-200",children:"Tap"})]},"".concat(e.center_x,"-").concat(e.center_y,"-").concat(t))),ec.length||ex?null:(0,s.jsx)("li",{className:"py-4 text-center text-zinc-600",children:g("尚未加载","Not loaded")})]})]}):null,S&&j?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("安装 APK","Install APK")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:g("先 adb push 到 /sdcard/ 再执行安装。","Push the APK to /sdcard/ first.")}),(0,s.jsx)("input",{className:"mt-4 w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm",value:C,onChange:e=>R(e.target.value)}),(0,s.jsx)("button",{type:"button",disabled:ew||!S||!j,onClick:()=>void P("install_apk",{path:C}),className:"mt-3 rounded-xl bg-emerald-500/20 px-4 py-2 text-sm font-medium text-emerald-100 ring-1 ring-emerald-500/30",children:"pm install"})]}):null]})}var ea=n(9897),eo=n(4554),ec=n(7689),ed=n(8930),ex=n(8401);function eu(e){let{t,title:n,subtitle:l,steps:i,onNavigate:r}=e;return(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/25 bg-gradient-to-br from-violet-500/10 via-zinc-950/40 to-fuchsia-500/5 p-6 shadow-lg shadow-violet-900/10",children:[(0,s.jsx)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:n}),(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-400",children:l}),(0,s.jsx)("div",{className:"mt-6 flex flex-col items-center gap-4 sm:flex-row sm:flex-wrap sm:justify-center",children:i.map((e,t)=>(0,s.jsxs)("div",{className:"flex items-center gap-4",children:[e.openUrl||e.target&&r?(0,s.jsxs)("button",{type:"button",onClick:()=>{if(e.openUrl){window.open((0,ex.p)(e.openUrl),"_blank","noopener,noreferrer");return}e.target&&r&&r(e.target)},className:"flex min-h-[4rem] min-w-[7rem] flex-col items-center justify-center rounded-2xl bg-gradient-to-br px-4 py-2 text-center text-xs font-bold text-white shadow-lg ring-2 ring-white/10 transition hover:ring-violet-400/50 hover:brightness-110 ".concat(e.gradient),children:[(0,s.jsx)("span",{children:e.label}),e.sub?(0,s.jsx)("span",{className:"mt-1 text-[10px] font-normal text-white/80",children:e.sub}):null]}):(0,s.jsxs)("div",{className:"flex min-h-[4rem] min-w-[7rem] flex-col items-center justify-center rounded-2xl bg-gradient-to-br px-4 py-2 text-center text-xs font-bold text-white shadow-lg ".concat(e.gradient),children:[(0,s.jsx)("span",{children:e.label}),e.sub?(0,s.jsx)("span",{className:"mt-1 text-[10px] font-normal text-white/80",children:e.sub}):null]}),t8?e.slice(-8):e;if(e.includes("live2/")){let t=e.split("/"),n=t[t.length-1]||"";return n.length>8?n.slice(-8):n}}}let t=e.trim();return!t||t.includes("\n")||t.toLowerCase().startsWith("rtmp")?"":t.length>8?t.slice(-8):t}function eh(e){let t=[];for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith("#")||!/douyin\.com|v\.douyin\.com/i.test(e))continue;let s=e.match(/(https?:\/\/live\.douyin\.com\/[a-zA-Z0-9_-]+)/i);if(s){t.push(s[1].replace(/^http:\/\//i,"https://"));continue}let l=e.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);if(l){t.push("https://live.douyin.com/".concat(l[1]));continue}let i=e.match(/(\d{8,})/);i&&t.push("https://live.douyin.com/".concat(i[1]))}return Array.from(new Set(t)).slice(0,16)}function ep(e){let t="",n=!0,s="",l=!1,i=e.split(/\r?\n/),r=!1;for(let e of i){let i=e.trim();if(/^\[youtube\]/i.test(i)){r=!0;continue}if(/^\[/.test(i)){r=!1;continue}if(!r||!i||i.startsWith("#")||i.startsWith(";"))continue;let a=i.indexOf("=");if(a<0)continue;let o=i.slice(0,a).trim().toLowerCase(),c=i.slice(a+1).trim().split(/[#;]/)[0].trim();"key"===o||"stream_key"===o?t=c:"rtmps"===o?n=!/^(0|false|否)/i.test(c):"bitrate"===o?s=c:"fast_audio"===o&&(l=/^(1|true|yes|是|开|on)/i.test(c))}return{key:t,rtmps:n,bitrate:s,fastAudio:l}}function eb(e){return"URL_config.".concat(e.replace(/[^a-zA-Z0-9_.-]/g,"_"),".ini")}function eg(e){let t=e.bitrate.trim()?"bitrate = ".concat(e.bitrate.trim()):"# bitrate = 4000";return"[youtube]\n# YouTube 推流 key(工作室 → 直播 → 串流密钥)\nkey = ".concat(e.key.trim(),"\n\n# 使用 RTMPS;填 否 则 RTMP\nrtmps = ").concat(e.rtmps?"是":"否","\n\n# 视频比特率 kbps(可选)\n").concat(t,"\n\n# 轻量音频链,减轻 CPU:1 / 是\nfast_audio = ").concat(e.fastAudio?"1":"0","\n")}function ef(e){if(e<60)return"".concat(e,"s");let t=Math.floor(e/60);return t<60?"".concat(t,"m ").concat(e%60,"s"):"".concat(Math.floor(t/60),"h ").concat(t%60,"m")}function ev(e){var t,n,l;let{t:i,currentProc:r,fetchJson:a,urlListText:o,keySuffixUi:c,showKeyRow:d=!0,pollMs:x=1e3,refreshToken:u=0}=e,[m,h]=(0,_.useState)(""),[p,b]=(0,_.useState)(""),[g,f]=(0,_.useState)(""),[v,w]=(0,_.useState)(""),[N,j]=(0,_.useState)(""),[k,z]=(0,_.useState)([]),[S,C]=(0,_.useState)(null),[R,P]=(0,_.useState)(!1),[L,M]=(0,_.useState)(null),[T,U]=(0,_.useState)(0),[E,I]=(0,_.useState)(!0),D=(0,_.useRef)(null),A=(0,_.useRef)(null),O=(0,_.useRef)(!1),H=(0,_.useRef)(!1),B=(0,_.useRef)(!1),W=(0,_.useRef)(r),Y=(0,_.useRef)(0),J=function(e){let t=[];for(let n of e.split(/\r?\n/)){let e=n.trim();if(!e||e.startsWith("#")||!/douyin\.com|v\.douyin\.com/i.test(e))continue;let s=e.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);if(s){t.push(s[1]);continue}let l=e.match(/(\d{8,})/);t.push(l?l[1]:e.slice(0,96))}return Array.from(new Set(t)).slice(0,12)}(o),G=/^(online|running)$/i.test(m),V=function(e){if(!e)return null;let t=null;for(let n of e.split(/\r?\n/)){let e=n.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);e&&(t=e[1]);let s=n.match(/https?:\/\/[^/\s]*douyin\.com\/(\d{8,})/i);s&&(t=s[1])}return t}(p),q=null!==(n=eh(o)[0])&&void 0!==n?n:"",X=V||(null!==(l=null===(t=q.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i))||void 0===t?void 0:t[1])&&void 0!==l?l:null),$=X?"https://live.douyin.com/".concat(X):q||null,Q=(0,_.useCallback)(async()=>{let e=W.current.trim();if(!e)return;if(H.current){B.current=!0;return}H.current=!0;let t=++Y.current;try{let n=await a("/status?process=".concat(encodeURIComponent(e)));if(t!==Y.current||e!==W.current.trim())return;let s=n.process_status||"unknown";h(s),b(n.recent_log||""),f(n.recent_error||""),w(n.business_status||""),j(n.business_note||""),z(Array.isArray(n.ffmpeg_pids)?n.ffmpeg_pids:[]),C("number"==typeof n.log_age_seconds?n.log_age_seconds:null);let l=/^(online|running)$/i.test(s);l&&!O.current&&M(Date.now()),l||M(null),O.current=l}catch(n){if(t!==Y.current||e!==W.current.trim())return;h("error"),w("error"),j(""),z([]),C(null)}finally{H.current=!1,B.current&&(B.current=!1,window.setTimeout(()=>void Q(),0))}},[a]);(0,_.useEffect)(()=>{if(W.current=r,Y.current+=1,B.current=!1,!r){h(""),b(""),f(""),w(""),j(""),z([]),C(null),M(null),O.current=!1;return}h(""),b(""),f(""),w(""),j(""),z([]),C(null),M(null),O.current=!1,Q()},[r,Q]),(0,_.useEffect)(()=>{let e=()=>I("visible"===document.visibilityState);return e(),document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[]),(0,_.useEffect)(()=>{r&&Q()},[r,Q,u]),(0,_.useEffect)(()=>{if(R||!E||!r)return;let e=window.setInterval(()=>void Q(),x);return()=>clearInterval(e)},[R,E,r,Q,x]),(0,_.useEffect)(()=>{let e=()=>{"visible"===document.visibilityState&&Q()};return document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[Q]),(0,_.useEffect)(()=>{if(!L)return;let e=window.setInterval(()=>U(e=>e+1),1e3);return()=>clearInterval(e)},[L]),(0,_.useEffect)(()=>{if(R||!E)return;let e=D.current;e&&(e.scrollTop=e.scrollHeight)},[p,R,E]),(0,_.useEffect)(()=>{if(R||!E)return;let e=A.current;e&&(e.scrollTop=e.scrollHeight)},[g,R,E]);let ee=null==L?i("—(未检测到在线)","— (not online)"):ef(Math.max(0,Math.floor((Date.now()-L)/1e3))),et=R?i("已暂停刷新","Paused"):E?i("每秒刷新","~1s refresh"):i("后台暂停","Hidden"),en=R?"bg-amber-500/20 text-amber-100 ring-amber-500/35":E?"bg-emerald-500/15 text-emerald-200/90 ring-emerald-500/25":"bg-sky-500/15 text-sky-100 ring-sky-500/25";return(0,s.jsxs)("section",{className:"rounded-2xl border border-emerald-500/20 bg-gradient-to-b from-emerald-500/[0.07] to-zinc-950/80 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsx)("span",{className:"sr-only","aria-hidden":!0,children:T}),(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:i("当前直播日志","Live process log")}),(0,s.jsx)("span",{className:"rounded-full bg-white/10 px-2 py-0.5 font-mono text-[10px] text-zinc-300 ring-1 ring-white/10",children:r||"—"}),(0,s.jsx)("span",{className:"rounded-full px-2 py-0.5 text-[10px] font-medium ring-1 ".concat(en),children:et})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsxs)("button",{type:"button",onClick:()=>void Q(),className:"inline-flex items-center gap-1 rounded-lg border border-white/10 bg-white/[0.05] px-3 py-1.5 text-xs text-zinc-300 hover:bg-white/[0.08]",children:[(0,s.jsx)(y.Z,{className:"h-3.5 w-3.5"}),i("立即拉取","Refresh")]}),(0,s.jsxs)("button",{type:"button",onClick:()=>P(e=>!e),className:"inline-flex items-center gap-1 rounded-lg px-3 py-1.5 text-xs ring-1 ".concat(R?"bg-amber-500/20 text-amber-100 ring-amber-500/35":"border border-white/10 bg-black/30 text-zinc-300"),children:[R?(0,s.jsx)(K.Z,{className:"h-3.5 w-3.5"}):(0,s.jsx)(F.Z,{className:"h-3.5 w-3.5"}),R?i("继续自动刷新","Resume"):i("暂停自动刷新","Pause")]})]})]}),(0,s.jsxs)("div",{className:"mt-4 space-y-3 rounded-xl border border-white/[0.06] bg-black/25 p-4",children:[(0,s.jsxs)("div",{className:"grid gap-2 text-xs sm:grid-cols-2",children:[(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("进程状态","Status")}),(0,s.jsx)("span",{className:"font-medium text-zinc-200",children:function(e,t){let n=(t||"unknown").toLowerCase();return"online"===n||"running"===n?e("运行中(PM2/进程在线)","Running (process online)"):"stopped"===n||"stopping"===n?e("已停止","Stopped"):"not_found"===n||"errored"===n?e("未运行或未找到","Not running / not found"):"invalid"===n?e("无效进程名","Invalid process"):t||"—"}(i,m)})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("Business state","Business state")}),(0,s.jsx)("span",{className:"font-medium text-cyan-200/90",children:function(e,t,n){let s=(t||"").toLowerCase();return"streaming"===s?e("Pushing to YouTube","Pushing to YouTube"):"waiting_source"===s?e("Waiting for the upstream live source","Waiting for the upstream live source"):"source_live"===s?e("Source live detected, but no active FFmpeg relay worker","Source live detected, but no active FFmpeg relay worker"):"monitoring"===s?e("Process online and monitoring the source","Process online and monitoring the source"):"misconfigured"===s?e("YouTube key missing or invalid","YouTube key missing or invalid"):"stale"===s?e("Process online but the log heartbeat is stale","Process online but the log heartbeat is stale"):"error"===s?e("Recent process error detected","Recent process error detected"):(null==n?void 0:n.trim())?n.trim():e("No business-state hint yet","No business-state hint yet")}(i,v,N)})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("本次在线时长(估算)","Online duration (est.)")}),(0,s.jsx)("span",{className:"font-mono text-cyan-200/90",children:ee})]}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("FFmpeg workers","FFmpeg workers")}),(0,s.jsxs)("span",{className:"font-mono text-zinc-300",children:[k.length?k.join(", "):"none",null!=S?" \xb7 log ".concat(ef(Math.max(0,Math.floor(S)))):""]})]})]}),d?(0,s.jsxs)("div",{className:"flex flex-wrap gap-2 text-xs",children:[(0,s.jsx)("span",{className:"text-zinc-500",children:i("YouTube key 尾码(参考)","YT key suffix")}),(0,s.jsx)("span",{className:"font-mono text-zinc-300",children:c||"—"})]}):null,$?(0,s.jsxs)("div",{className:"rounded-lg border border-violet-500/20 bg-violet-500/[0.06] px-3 py-2.5",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsx)("span",{className:"text-[11px] font-medium text-zinc-400",children:V?i("当前直播源站(日志)","Current source (from log)"):G?i("配置中的源站地址","Configured source URL"):i("源站快捷入口","Source quick link")}),(0,s.jsxs)("a",{href:$,target:"_blank",rel:"noreferrer",className:"inline-flex items-center gap-1.5 rounded-lg bg-violet-500/20 px-3 py-1.5 text-xs font-medium text-violet-100 ring-1 ring-violet-500/35 transition hover:bg-violet-500/30",children:[(0,s.jsx)(Z.Z,{className:"h-3.5 w-3.5 shrink-0 opacity-90"}),X||i("打开抖音直播页","Open Douyin live")]})]}),J.length>1&&V?(0,s.jsxs)("p",{className:"mt-2 text-[10px] text-zinc-600",children:[i("配置中还有","Also in config:")," ",J.filter(e=>e!==X).slice(0,3).map(e=>(0,s.jsx)("a",{href:"https://live.douyin.com/".concat(e),target:"_blank",rel:"noreferrer",className:"ml-1 text-violet-400/90 underline-offset-2 hover:underline",children:e},e)),J.length>4?"…":null]}):null]}):(0,s.jsx)("p",{className:"text-[11px] text-zinc-600",children:i("(日志与地址列表中暂无抖音房间)","(No Douyin room in log or URL list)")})]}),"not_found"!==m&&"invalid"!==m?(0,s.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wider text-emerald-400/90",children:i("进程输出(stdout / 合并日志)","Process output")}),(0,s.jsx)("pre",{ref:D,className:"log-live-scroll mt-2 max-h-[min(22rem,42vh)] min-h-[12rem] overflow-auto whitespace-pre-wrap rounded-xl border border-emerald-500/20 bg-black/55 p-3 font-mono text-[10px] leading-relaxed text-emerald-100/95",children:p.trim()||i("(暂无)","(empty)")})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wider text-rose-400/90",children:i("异常信息(stderr)","Stderr")}),(0,s.jsx)("pre",{ref:A,className:"log-live-scroll mt-2 max-h-[min(22rem,42vh)] min-h-[12rem] overflow-auto whitespace-pre-wrap rounded-xl border border-rose-500/20 bg-black/55 p-3 font-mono text-[10px] leading-relaxed text-rose-100/95",children:g.trim()||i("(暂无)","(empty)")})]})]}):(0,s.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:i("进程未在 PM2 / 本地注册表中运行,日志区域已隐藏。","Process not running — log panes hidden.")})]})}function ey(e){return/tiktok/i.test(e.script)||/tiktok/i.test(e.pm2)}let ew=[{id:"720p60",labelZh:"720p @ 60Hz",labelEn:"720p @ 60Hz",spec:"1280x720, 59.94/60Hz, RGB/YUV 有限",hintZh:"板端 HDMI 输出时序与显示端一致;下游画布建议 1280\xd7720。",hintEn:"Match SoC HDMI timing to the display; downstream canvas e.g. 1280\xd7720."},{id:"1080p30",labelZh:"1080p @ 30Hz",labelEn:"1080p @ 30Hz",spec:"1920x1080, 30Hz",hintZh:"带宽紧张时可优先 1080p30;检查线材与接口规格。",hintEn:"Prefer 1080p30 when bandwidth is tight; check cable and port specs."},{id:"1080p60",labelZh:"1080p @ 60Hz",labelEn:"1080p @ 60Hz",spec:"1920x1080, 60Hz, 高刷转播",hintZh:"两端均需稳定支持 1080p60;长时间运行注意散热。",hintEn:"Both ends need stable 1080p60; mind thermals for long runs."}],eN="live-hub-tiktok-hdmi-check-v1",ej="live-hub-tiktok-hdmi-notes-v1",ek="live-hub-tiktok-source-mode-v1";function ez(e){var t;let{t:n,busy:l,entries:i,currentProc:r,setCurrentProc:a,urlConfig:o,setUrlConfig:c,onRunProcess:d,onSaveUrlConfig:x,onReplayGoLive:u,onCopy:m,fetchJson:h,apiPrefix:p,quickLinks:b,hdmiStatus:g,notify:f,onNavigate:v}=e,y=(0,_.useMemo)(()=>i.filter(ey),[i]),w=y.length?y:i,[N,j]=(0,_.useState)("srs"),[k,z]=(0,_.useState)([]),[S,C]=(0,_.useState)(!1),[R,P]=(0,_.useState)(!1),[L,M]=(0,_.useState)("1080p30"),[T,E]=(0,_.useState)("1080p30"),[I,A]=(0,_.useState)(!1),[Z,O]=(0,_.useState)(!0),[H,K]=(0,_.useState)(null),F=(0,_.useRef)(!1),W=(0,_.useRef)(o),[J,G]=(0,_.useState)(""),[V,q]=(0,_.useState)({}),X=(0,_.useCallback)(e=>{W.current=e,c(e)},[c]),$=(0,_.useCallback)(e=>{j(e);try{window.localStorage.setItem(ek,e)}catch(e){}},[]);(0,_.useEffect)(()=>{try{let e=window.localStorage.getItem(ek);("ffmpeg"===e||"replay"===e||"srs"===e)&&("ffmpeg"!==e&&"replay"!==e?j(e):j("srs"))}catch(e){}},[]),(0,_.useEffect)(()=>{F.current=!1},[r]),(0,_.useEffect)(()=>{W.current=o},[o]);let Q=(0,_.useCallback)(async()=>{if(r)try{var e;let t=new URLSearchParams({process:r,_ts:String(Date.now())}),n=await h("/get_url_config?".concat(t));X(null!==(e=n.content)&&void 0!==e?e:"")}catch(e){}},[X,r,h]);(0,_.useEffect)(()=>{if(!r||!Z||"ffmpeg"!==N)return;let e=window.setInterval(()=>{F.current||Q()},8e3);return()=>clearInterval(e)},[r,Z,Q,N]),(0,_.useEffect)(()=>{"ffmpeg"===N&&r&&Q()},[N,r,Q]);let ee=(0,_.useCallback)(async()=>{if(r){C(!0);try{var e;let t=await h("/tiktok_replay/list?process=".concat(encodeURIComponent(r)));z(null!==(e=t.files)&&void 0!==e?e:[])}catch(e){f(e.message),z([])}finally{C(!1)}}},[r,h,f]);(0,_.useEffect)(()=>{"replay"===N&&r&&ee()},[N,r,ee]),(0,_.useEffect)(()=>{try{let e=window.localStorage.getItem(eN);e&&q(JSON.parse(e))}catch(e){}try{G(window.localStorage.getItem(ej)||"")}catch(e){}},[]);let et=(0,_.useCallback)(e=>{q(e);try{window.localStorage.setItem(eN,JSON.stringify(e))}catch(e){}},[]),en=e=>{G(e);try{window.localStorage.setItem(ej,e)}catch(e){}},es=async()=>{if(r){A(!0),K(null),F.current=!1;try{var e;let t=new URLSearchParams({process:r,_ts:String(Date.now())}),s=await h("/get_url_config?".concat(t));X(null!==(e=s.content)&&void 0!==e?e:""),K(n("已从服务器读取 URL_config","Reloaded URL_config from server"))}catch(e){K(e.message)}finally{A(!1)}}},el=async()=>{try{await Promise.resolve(x(W.current)),F.current=!1}catch(e){}},ei=async e=>{if(r){P(!0);try{await h("/tiktok_replay/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({process:r,filename:e})}),f(n("已删除文件","File removed")),await ee()}catch(e){f(e.message)}finally{P(!1)}}},er=async e=>{var t;let s=null===(t=e.target.files)||void 0===t?void 0:t[0];if(e.target.value="",s&&r){P(!0);try{let e=new FormData;e.append("file",s);let t=await (0,Y.N)("".concat(p,"/tiktok_replay/upload?process=").concat(encodeURIComponent(r)),{method:"POST",body:e});f(t.message||n("上传成功","Uploaded")),await ee()}catch(e){f(e.message)}finally{P(!1)}}},ex=l||I||R,em=ew.find(e=>e.id===T),eh=!!(null==g?void 0:g.can_stream_hdmi),ep=(null==g?void 0:g.preferred_device)||(null==g?void 0:null===(t=g.video_devices)||void 0===t?void 0:t[0])||"";return(0,s.jsxs)("div",{className:"mx-auto max-w-4xl space-y-6",children:[v?(0,s.jsx)(eu,{t:n,title:n("TikTok HDMI 硬件链路","TikTok HDMI hardware chain"),subtitle:n("板端编码经 HDMI 到显示/下游设备;与「网络」页顶卡相同的箭头风格。","Encode on SoC → HDMI → display/downstream; same arrow style as Network header."),onNavigate:v,steps:[{label:"FFmpeg",sub:n("采集 / 推流","Capture"),gradient:"from-cyan-400 to-blue-500",target:"live_tiktok"},{label:"HDMI",sub:n("板载输出","SoC out"),gradient:"from-violet-500 to-fuchsia-500"},{label:"Android",sub:n("AOSP / 手机","AOSP"),gradient:"from-amber-400 to-orange-500",target:"android"}]}):null,(0,s.jsx)("div",{className:"rounded-2xl border border-cyan-500/25 bg-gradient-to-br from-cyan-500/[0.14] via-zinc-950/80 to-fuchsia-500/10 p-6 shadow-xl shadow-cyan-900/10",children:(0,s.jsx)("div",{className:"flex flex-wrap items-start gap-4",children:(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[(0,s.jsx)("div",{className:"flex h-11 w-11 items-center justify-center rounded-xl bg-gradient-to-br from-cyan-500/35 to-fuchsia-600/25 ring-1 ring-white/10",children:(0,s.jsx)(D.Z,{className:"h-5 w-5 text-cyan-200"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold tracking-tight text-white",children:n("TikTok 无人直播(单路)","TikTok unmanned (single lane)")}),(0,s.jsx)("p",{className:"mt-0.5 text-xs text-zinc-500",children:n("布局对齐 YouTube 单频道:直播开关 + 源站 + URL_config;无 stream key,输出走 HDMI 硬件链路。","Same layout as YouTube single: controls + URLs; no stream key — HDMI hardware path.")})]})]})})}),(0,s.jsx)("div",{className:"rounded-2xl border border-cyan-500/20 bg-cyan-500/[0.06] p-4 ring-1 ring-white/[0.04]",children:(0,s.jsx)("p",{className:"text-xs leading-relaxed text-cyan-100/90",children:n("HDMI 互斥:后端在「开始 / 重新开始」TikTok 或 obs*.sh(SRS 拉流上屏)时,会自动停止其它正在占用 HDMI 链路的同类进程;与 YouTube 推流互不干扰。","HDMI mutex: starting TikTok or obs*.sh stops other TikTok/OBS HDMI sinks; YouTube RTMP is unaffected.")})}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/10 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-300"}),n("X86 HDMI 采集状态","X86 HDMI capture status")]}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:n("这里直接显示主机是否识别到采集卡和 /dev/video 设备,可用于验证 ARM HDMI 进 X86 的链路。","Shows whether the host sees the capture card and /dev/video nodes for ARM-to-X86 HDMI ingest.")})]}),(0,s.jsx)("span",{className:"rounded-full px-3 py-1 text-[11px] font-semibold ring-1 ".concat(eh?"bg-emerald-500/20 text-emerald-200 ring-emerald-500/30":"bg-rose-500/15 text-rose-200 ring-rose-500/25"),children:eh?n("可推流","Ready"):n("未就绪","Not ready")})]}),(0,s.jsxs)("div",{className:"mt-4 grid gap-3 md:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-4 text-[11px] text-zinc-400",children:[(0,s.jsxs)("p",{children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"device: "}),(0,s.jsx)("span",{className:"font-mono text-zinc-200",children:ep||"—"})]}),(0,s.jsxs)("p",{className:"mt-2",children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"video nodes: "}),(0,s.jsx)("span",{className:"font-mono text-zinc-200",children:((null==g?void 0:g.video_devices)||[]).join(", ")||"—"})]}),(0,s.jsxs)("p",{className:"mt-2",children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"usb matches: "}),(0,s.jsx)("span",{className:"text-zinc-300",children:((null==g?void 0:g.usb_capture_matches)||[]).length||0})]})]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-4 text-[11px] text-zinc-400",children:[(0,s.jsx)("p",{className:"text-zinc-600",children:n("建议 FFmpeg","Suggested FFmpeg")}),(0,s.jsx)("p",{className:"mt-2 break-all font-mono text-zinc-200",children:(null==g?void 0:g.suggested_ffmpeg_cmd)||"—"}),(null==g?void 0:g.suggested_ffmpeg_cmd)?(0,s.jsxs)("button",{type:"button",onClick:()=>m(g.suggested_ffmpeg_cmd||""),className:"mt-3 inline-flex items-center gap-2 rounded-lg bg-cyan-500/15 px-3 py-2 text-xs font-medium text-cyan-100 ring-1 ring-cyan-500/25",children:[(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"}),n("复制命令","Copy command")]}):null]})]}),((null==g?void 0:g.issues)||[]).length?(0,s.jsx)("ul",{className:"mt-4 list-inside list-disc space-y-1 text-[11px] text-amber-200/85",children:((null==g?void 0:g.issues)||[]).map(e=>(0,s.jsx)("li",{children:e},e))}):null]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-amber-500/20 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-amber-200/90",children:[(0,s.jsx)(B.Z,{className:"h-4 w-4"}),(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:n("直播开关","Live control")})]}),(0,s.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:n("TikTok 进程(PM2)","TikTok PM2 process")}),(0,s.jsx)("select",{className:"mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm text-white",value:r,onChange:e=>a(e.target.value),children:w.map(e=>(0,s.jsxs)("option",{value:e.pm2,children:[e.label," (",e.pm2,")"]},e.pm2))}),(0,s.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:n("直播源","Video source")}),(0,s.jsxs)("select",{className:"mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm text-white",value:N,onChange:e=>$(e.target.value),children:[(0,s.jsx)("option",{value:"ffmpeg",hidden:!0,children:"FFmpeg(抖音 / TikTok 等直播间 URL)"}),(0,s.jsx)("option",{value:"replay",hidden:!0,children:n("录播素材(本地上传)","VOD upload")}),(0,s.jsx)("option",{value:"srs",children:n("SRS(OBS 推流)","SRS (OBS)")})]}),"srs"===N?(0,s.jsx)("p",{className:"mt-2 text-[11px] leading-relaxed text-amber-200/85",children:n("此模式不显示 URL_config:请在 OBS 中填写下方 RTMP 推流地址;板端 SRS 拉流上屏仍可能占用 HDMI,与 TikTok 进程互斥规则不变。","URL_config is hidden: set the RTMP URL in OBS. SRS pull-to-HDMI may still mutex with TikTok per server rules.")}):null,(0,s.jsx)("div",{className:"mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3",children:[["start",n("开始直播","Start"),"bg-emerald-500/20 text-emerald-200 ring-emerald-500/30"],["stop",n("停止直播","Stop"),"bg-rose-500/15 text-rose-200 ring-rose-500/25"],["restart",n("重新开始","Restart"),"bg-amber-500/15 text-amber-200 ring-amber-500/25"]].map(e=>{let[t,n,l]=e;return(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>d(t),className:"rounded-xl px-4 py-3 text-sm font-medium ring-1 ".concat(l),children:n},t)})}),(0,s.jsxs)("p",{className:"mt-3 text-center text-[11px] text-zinc-500",children:[n("当前 HDMI 预设(备忘)","HDMI preset (memo)"),":"," ",(0,s.jsx)("span",{className:"font-mono text-cyan-300/90",children:em?n(em.labelZh,em.labelEn):T})]})]}),"replay"===N?(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/25 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(eo.Z,{className:"h-4 w-4 text-violet-300"}),n("录播素材","VOD library")]}),(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,s.jsxs)("label",{className:"inline-flex cursor-pointer items-center gap-2 rounded-xl bg-violet-500/15 px-3 py-2 text-xs font-medium text-violet-100 ring-1 ring-violet-500/30",children:[(0,s.jsx)(ec.Z,{className:"h-3.5 w-3.5"}),(0,s.jsx)("span",{children:n("上传视频","Upload")}),(0,s.jsx)("input",{type:"file",accept:".mp4,.mkv,.ts,.flv,.mov,.m4v,.webm",className:"hidden",onChange:er})]}),(0,s.jsx)("button",{type:"button",disabled:ex||!r,onClick:()=>void ee(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-3 py-2 text-xs text-zinc-300",children:n("刷新列表","Refresh")})]})]}),(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:n("文件保存在服务器 config/tiktok_replay/对应进程目录;点「开始直播」会写入 replayfile 行并启动 PM2 进程。停播请用上方「停止直播」。","Files under config/tiktok_replay/. Go live writes replayfile + starts PM2. Use Stop above to stop.")}),S?(0,s.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:n("加载中…","Loading…")}):0===k.length?(0,s.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:n("暂无文件,请先上传。","No files yet.")}):(0,s.jsx)("ul",{className:"mt-4 space-y-2",children:k.map(e=>(0,s.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 rounded-xl border border-white/10 bg-black/30 px-3 py-2 text-xs text-zinc-300",children:[(0,s.jsx)("span",{className:"min-w-0 flex-1 truncate font-mono",children:e.name}),(0,s.jsxs)("span",{className:"shrink-0 text-zinc-500",children:[(e.size/1048576).toFixed(1)," MB"]}),(0,s.jsxs)("div",{className:"flex shrink-0 flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>void(async()=>{try{await Promise.resolve(u(e.replay_url,e.name))}catch(e){}})(),className:"rounded-lg bg-emerald-500/20 px-2 py-1 text-[11px] text-emerald-100 ring-1 ring-emerald-500/30",children:n("开始直播","Go live")}),(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>d("stop"),className:"rounded-lg bg-rose-500/15 px-2 py-1 text-[11px] text-rose-100 ring-1 ring-rose-500/25",children:n("停播","Stop")}),(0,s.jsxs)("button",{type:"button",disabled:ex,onClick:()=>void ei(e.name),className:"inline-flex items-center gap-1 rounded-lg bg-zinc-700/40 px-2 py-1 text-[11px] text-zinc-200",children:[(0,s.jsx)(ed.Z,{className:"h-3 w-3"}),n("删除","Del")]})]})]},e.name))})]}):null,"srs"===N?(0,s.jsxs)("div",{className:"rounded-2xl border border-emerald-500/25 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:n("SRS / OBS 推流","SRS / OBS ingest")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:n("OBS:设置 → 推流 → 服务选「自定义」,服务器填 RTMP 地址;串流密钥可与 SRS 应用配置一致(默认 live/livestream)。","OBS → Stream → Custom: RTMP URL as server; stream key per SRS app (default live/livestream).")}),(0,s.jsxs)("dl",{className:"mt-4 space-y-3 text-xs",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-500",children:n("RTMP 推流地址(OBS 服务器)","RTMP publish URL")}),(0,s.jsxs)("dd",{className:"mt-1 flex flex-wrap items-center gap-2 font-mono text-emerald-200/90",children:[(0,s.jsx)("span",{className:"break-all",children:b.srs_rtmp_publish||"—"}),b.srs_rtmp_publish?(0,s.jsx)("button",{type:"button",className:"shrink-0 text-cyan-300 hover:text-cyan-200",onClick:()=>m(b.srs_rtmp_publish),children:(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"})}):null]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-500",children:n("HTTP-FLV 预览","HTTP-FLV preview")}),(0,s.jsxs)("dd",{className:"mt-1 flex flex-wrap items-center gap-2 font-mono text-zinc-400",children:[(0,s.jsx)("span",{className:"break-all",children:b.srs_play_flv||b.srs_http||"—"}),b.srs_play_flv||b.srs_http?(0,s.jsx)("button",{type:"button",className:"shrink-0 text-cyan-300 hover:text-cyan-200",onClick:()=>m(b.srs_play_flv||b.srs_http),children:(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"})}):null]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-500",children:n("SRS 控制台","SRS web UI")}),(0,s.jsx)("dd",{className:"mt-1 font-mono text-zinc-400",children:(0,s.jsx)("a",{href:b.srs_http||"#",target:"_blank",rel:"noreferrer",className:"text-cyan-300 hover:underline",children:b.srs_http||"—"})})]})]})]}):null,(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-400"}),n("HDMI 硬件与时序","HDMI timing")]}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:n("点选一路作为现场备忘;与板端 ffmpeg/OBS 采集参数对齐。","Pick a preset as field memo; match capture settings.")}),(0,s.jsx)("div",{className:"mt-4 grid gap-3 md:grid-cols-3",children:ew.map(e=>{let t=L===e.id,l=T===e.id;return(0,s.jsxs)("button",{type:"button",onClick:()=>{M(t?null:e.id),E(e.id)},className:"rounded-2xl border p-4 text-left transition ".concat(l?"border-cyan-500/50 ring-1 ring-cyan-500/20":""," ").concat(t?"border-cyan-500/40 bg-cyan-500/10":"border-white/[0.08] bg-zinc-950/50 hover:border-white/15"),children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-400"}),n(e.labelZh,e.labelEn)]}),(0,s.jsx)("p",{className:"mt-2 font-mono text-[11px] text-zinc-400",children:e.spec}),t?(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:n(e.hintZh,e.hintEn)}):null]},e.id)})}),(0,s.jsxs)("div",{className:"mt-6 rounded-xl border border-white/5 bg-black/25 p-4",children:[(0,s.jsx)("p",{className:"text-xs font-semibold text-zinc-400",children:n("上线前检查清单(本地保存)","Pre-flight checklist (local)")}),(0,s.jsx)("ul",{className:"mt-3 space-y-2",children:[{id:"cable",zh:"HDMI 线材插紧、方向正确(如需转接头确认规格)",en:"HDMI cable seated; adapter specs OK"},{id:"thermal",zh:"长时间推流注意散热,过热会掉帧黑屏",en:"Thermal headroom for long runs"}].map(e=>(0,s.jsxs)("li",{className:"flex items-start gap-2 text-xs text-zinc-400",children:[(0,s.jsx)("input",{type:"checkbox",className:"mt-0.5 rounded border-white/20 bg-black/40",checked:!!V[e.id],onChange:t=>et({...V,[e.id]:t.target.checked})}),(0,s.jsx)("span",{children:n(e.zh,e.en)})]},e.id))}),(0,s.jsx)("label",{className:"mt-4 block text-[11px] text-zinc-500",children:n("HDMI / 走线备忘","HDMI / wiring notes")}),(0,s.jsx)("textarea",{className:"mt-1 min-h-[72px] w-full resize-y rounded-lg border border-white/10 bg-black/40 p-3 text-xs text-zinc-300",value:J,onChange:e=>en(e.target.value),spellCheck:!1,placeholder:n("接口、线长、显示器型号…","Ports, cable length, display model…")})]})]}),"ffmpeg"===N?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:n("直播地址列表 \xb7 URL_config.ini","URL_config.ini")}),(0,s.jsxs)("button",{type:"button",className:"inline-flex items-center gap-1 text-xs text-cyan-300 hover:text-cyan-200",onClick:()=>m(o),children:[(0,s.jsx)(U.Z,{className:"h-3.5 w-3.5"}),n("复制全文","Copy all")]})]}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:n("一行一个地址;可勾选自动从服务器刷新,或点「重新读取」手动同步。","One URL per line; enable auto-refresh or reload from server.")}),(0,s.jsx)("div",{className:"mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400",children:(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:Z,onChange:e=>O(e.target.checked)}),n("每 8 秒自动从服务器刷新","Auto-refresh from server every 8s")]})}),H?(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:H}):null,(0,s.jsx)("textarea",{className:"mt-4 min-h-[200px] w-full resize-y rounded-xl border border-white/10 bg-black/50 p-4 font-mono text-xs text-zinc-300",value:o,onChange:e=>{F.current=!0,X(e.target.value)},spellCheck:!1}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>void es(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-300",children:n("重新读取","Reload from server")}),(0,s.jsx)("button",{type:"button",disabled:ex,onClick:()=>void el(),className:"rounded-xl bg-cyan-500/20 px-4 py-2 text-sm font-medium text-cyan-100 ring-1 ring-cyan-500/30",children:n("保存 URL 配置","Save URL config")})]})]}):null,(0,s.jsx)(ev,{t:n,currentProc:r,fetchJson:h,urlListText:"ffmpeg"===N?o:"",keySuffixUi:"",showKeyRow:!1})]})}var eS=n(5468),e_=n(9397),eC=n(90);let eR="live-hub-youtube-pro-v2",eP="youtube2__",eL=/[^a-zA-Z0-9_.-]+/g,eM=new Set(["youtube","douyin_youtube","tiktok","obs","web"]);function eT(e){return(e||"").trim().replace(eL,"_")}function eU(e,t){let n=eT(e);return!n||eM.has(n)||n===eP?eK(t):n.startsWith(eP)?n:eK(n)}function eE(e){return eU(String(e.pm2Name||""),String(e.id||""))}function eI(e){if(!e||"object"!=typeof e)return null;let t=String(e.id||"").trim();if(!t)return null;let n=String(e.name||"").trim()||t;return{id:t,name:n,streamKeySuffix:"string"==typeof e.streamKeySuffix?e.streamKeySuffix:void 0,streamKey:"string"==typeof e.streamKey?e.streamKey:void 0,urlLines:"string"==typeof e.urlLines?e.urlLines:void 0,pm2Name:eU("string"==typeof e.pm2Name?e.pm2Name:"",t),notes:"string"==typeof e.notes?e.notes:void 0}}function eD(e){if(!e)return[];try{let t=JSON.parse(e);if(!Array.isArray(t))return[];return t.map(e=>eI(e)).filter(e=>null!==e)}catch(e){return[]}}function eA(e){window.localStorage.setItem(eR,JSON.stringify(e))}let eZ=["/hub/youtube_pro_channels","/youtube_pro_channels"];async function eO(e){for(let n of eZ)try{var t;let s=await e(n);return{fetched:!0,channels:(t=s.channels,Array.isArray(t)?t.map(e=>eI(e)).filter(e=>null!==e):[])}}catch(e){}return{fetched:!1,channels:[]}}async function eH(e,t){let n=null;for(let l of eZ)try{var s;let i=await e(l,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channels:t})});if((null===(s=i.neko)||void 0===s?void 0:s.ok)===!1){let e=i.neko.desired?" desired=".concat(i.neko.desired):"",t=i.neko.current?" current=".concat(i.neko.current):"";n=Error("Neko capacity expansion failed:".concat(e).concat(t," ").concat(i.neko.reason||"unknown error").trim());break}return}catch(e){n=e instanceof Error?e:Error(String(e))}throw null!=n?n:Error("youtube_pro_channels sync failed")}function eB(){return"ch_".concat(Date.now().toString(36),"_").concat(Math.random().toString(36).slice(2,7))}function eK(e){return"".concat(eP).concat(eT(e)||"channel")}function eF(e){return/youtube/i.test(e.script)||/youtube/i.test(e.pm2)}function eW(e){return(e.split("/").pop()||e).replace(/\.[^.]+$/,"")}function eY(e){var t;return!!e&&(/youtube/i.test(e.pm2)||/youtube/i.test(null!==(t=e.script)&&void 0!==t?t:""))}function eJ(e,t){let n=((null==t?void 0:t.business_status)||"").trim().toLowerCase();return(null==t?void 0:t.is_pushing)||"streaming"===n?0:eX(null==t?void 0:t.process_status)?1:"youtube"===e.pm2.trim().toLowerCase()?2:"youtube"===eW(e.script).trim().toLowerCase()?3:10}let eG="live-hub-youtube-mode-v1",eV=new Set(["youtube","douyin_youtube","tiktok","obs","web"]);function eq(e){var t,n,s;return{name:e.name,streamKey:null!==(t=e.streamKey)&&void 0!==t?t:"",pm2Name:null!==(n=e.pm2Name)&&void 0!==n?n:eK(e.id),notes:null!==(s=e.notes)&&void 0!==s?s:""}}function eX(e){return/^(online|running)$/i.test((e||"").trim())}function e$(e,t){let n=((null==e?void 0:e.business_status)||"").trim().toLowerCase();return"ready"===n?t("已配置","Ready"):"streaming"===n?t("推流中","Pushing"):"waiting_source"===n?t("等待上游","Waiting source"):"source_live"===n?t("源已开播,转推未起","Source live, relay down"):"monitoring"===n?t("监控中","Monitoring"):"misconfigured"===n?t("密钥异常","Key invalid"):"stale"===n?t("心跳过期","Stale"):"error"===n?t("异常","Error"):eX(null==e?void 0:e.process_status)?t("运行中","Running"):((null==e?void 0:e.process_status)||"").trim()||t("未运行","Idle")}function eQ(e){return e.split(/\r?\n/).map(e=>e.trim()).filter(e=>e&&!e.startsWith("#"))}function e0(e,t){return eQ(e).length>0&&0===eQ(t).length}function e1(e){let{kind:t,busyKind:n,targetPm2:l,busy:i,online:r,label:a,className:o,baseLock:c,onRun:d,notify:x,t:u,compact:m}=e,h=function(e){if(!(null==e?void 0:e.startsWith("proc:")))return null;let t=e.slice(5),n=t.indexOf(":");if(n<=0)return null;let s=t.slice(0,n),l=t.slice(n+1);return l&&["start","stop","restart"].includes(s)?{action:s,pm2:l}:null}(i),p=h&&h.pm2===l,b=null!=n?n:t,g=!!(p&&h.action===b),f=!!(p&&h.action!==b),y="start"===t&&r,w="stop"===t&&!r,N="restart"===t&&!r,j=y||w||N;return(0,s.jsxs)("button",{type:"button",onClick:()=>{if(!g){if(f){x(u("请等待当前操作完成","Wait for the current action to finish"));return}if(y){x(u("已在直播中,无需重复开始","Already live"));return}if(w){x(u("当前未在直播,无法停止","Not live — cannot stop"));return}if(N){x(u("进程未运行时请使用「开始直播」","Use Start when the process is not running"));return}c||d()}},className:"relative overflow-hidden rounded-xl ring-1 transition ".concat(m?"min-h-[2rem] px-3 py-1.5 text-xs font-medium":"min-h-[2.75rem] px-4 py-3 text-sm font-medium"," ").concat(o," ").concat(j||c||g||f?"cursor-not-allowed":""," ").concat(j&&!g?"opacity-45":""," ").concat(f?"opacity-35":""," ").concat(g?"ring-violet-400/40":""),children:[g?(0,s.jsx)("span",{className:"absolute inset-0 flex items-center justify-center bg-black/25 backdrop-blur-[2px]",children:(0,s.jsx)(v.Z,{className:"".concat(m?"h-4 w-4":"h-6 w-6"," animate-spin text-white")})}):null,(0,s.jsxs)("span",{className:"inline-flex items-center justify-center gap-1.5 ".concat(g?"invisible":""),children:[j?(0,s.jsx)(eS.Z,{className:"".concat(m?"h-3 w-3":"h-4 w-4"," shrink-0 opacity-90"),"aria-hidden":!0}):null,a]})]})}function e5(e){var t,n,l,i,r;let{t:a,busy:o,entries:d,currentProc:x,setCurrentProc:u,urlConfig:m,setUrlConfig:h,onRunProcess:p,onSaveUrlConfig:b,fetchJson:g,liveProcesses:f,notify:w,onNavigate:N,quickLinks:j}=e,k=(0,_.useMemo)(()=>d.filter(eF),[d]),z=(0,_.useMemo)(()=>(function(e,t){let n=e.filter(eF),s=n.filter(e=>eF(e)&&e.pm2.trim()===eW(e.script).trim()),l=s.length?[...s]:n.length?[...n]:[...e],i=new Set(l.map(e=>e.pm2.trim()));for(let e of t.filter(eY)){var r,a,o,c;let t=e.pm2.trim();if(!t||i.has(t))continue;let s=(e.business_status||"").trim().toLowerCase();if(!e.is_pushing&&"streaming"!==s&&!eX(e.process_status))continue;let d=n.find(e=>e.pm2.trim()===t);l.push(null!=d?d:{pm2:t,script:null!==(o=null!==(a=e.script)&&void 0!==a?a:null===(r=n[0])||void 0===r?void 0:r.script)&&void 0!==o?o:"youtube.py",label:null!==(c=e.label)&&void 0!==c?c:t}),i.add(t)}return l})(k.length?k:d,f),[d,f,k]),S=(0,_.useMemo)(()=>(function(e,t){if(!e.length)return"";let n=new Map(t.filter(eY).map(e=>[e.pm2.trim(),e])),s=e[0],l=eJ(s,n.get(s.pm2.trim()));for(let t of e.slice(1)){let e=eJ(t,n.get(t.pm2.trim()));e"youtube"===e.pm2.trim().toLowerCase());if(s)return s.pm2;let l=e.find(e=>"youtube"===eW(e.script).trim().toLowerCase());return l?l.pm2:null!==(n=null===(t=e[0])||void 0===t?void 0:t.pm2)&&void 0!==n?n:""}(z),[f,z]),[C,R]=(0,_.useState)("single"),[P,L]=(0,_.useState)([]),[M,T]=(0,_.useState)(""),[U,E]=(0,_.useState)(""),[I,D]=(0,_.useState)({key:"",rtmps:!0,bitrate:"",fastAudio:!1}),[A,O]=(0,_.useState)(null),[H,K]=(0,_.useState)(!1),[F,W]=(0,_.useState)(""),[Y,J]=(0,_.useState)(!0),[G,V]=(0,_.useState)(!1),[q,X]=(0,_.useState)(!1),[$,Q]=(0,_.useState)(null),[ee,et]=(0,_.useState)({}),[en,es]=(0,_.useState)(!1),[el,ei]=(0,_.useState)(null),[er,ea]=(0,_.useState)(0),eo=(0,_.useRef)(!1),ec=(0,_.useRef)(m),ef=(0,_.useRef)(F),ey=(0,_.useRef)([]),ew=(0,_.useRef)(x),eN=(0,_.useRef)(0),ej=(0,_.useRef)(0),ek=(0,_.useCallback)(e=>{ec.current=e,h(e)},[h]),ez=(0,_.useCallback)(e=>{ef.current=e,W(e)},[]);(0,_.useEffect)(()=>{eo.current=!1},[x]),(0,_.useEffect)(()=>{ew.current=x},[x]),(0,_.useEffect)(()=>{ec.current=m},[m]),(0,_.useEffect)(()=>{ef.current=F},[F]),(0,_.useEffect)(()=>{ey.current=P},[P]);let eS=(0,_.useCallback)((e,t)=>{e&&L(n=>{let s=!1,l=n.map(n=>{var l;return n.id!==e||(null!==(l=n.urlLines)&&void 0!==l?l:"")===t?n:(s=!0,{...n,urlLines:t})});return s?(ey.current=l,eA(l),l):n})},[]),eP=(0,_.useCallback)(async()=>{let e=ew.current.trim();if(!e)return;let t=++eN.current;try{var n,s,l;let i=new URLSearchParams({process:e,_ts:String(Date.now())}),r=await g("/get_url_config?".concat(i));if(t!==eN.current||e!==ew.current.trim())return;let a=null!==(n=r.content)&&void 0!==n?n:"";if(eo.current)return;if("single"===C)ek(a);else{let e=null!==(l=null===(s=ey.current.find(e=>e.id===M))||void 0===s?void 0:s.urlLines)&&void 0!==l?l:"";if(e0(e,a)){ez(e);return}ez(a),eS(M,a)}}catch(e){}},[M,ez,ek,g,C,eS]);(0,_.useEffect)(()=>{if(!x||!Y)return;let e=window.setInterval(()=>{eo.current||eP()},8e3);return()=>clearInterval(e)},[x,Y,eP]);let eL=async()=>{let e=ew.current.trim();if(!e)return;V(!0),Q(null),eo.current=!1;let t=++eN.current;try{var n,s,l;let i=new URLSearchParams({process:e,_ts:String(Date.now())}),r=await g("/get_url_config?".concat(i));if(t!==eN.current||e!==ew.current.trim())return;let o=null!==(n=r.content)&&void 0!==n?n:"";if(eo.current){Q(a("检测到本地未保存修改,已保留当前草稿","Kept the local unsaved draft"));return}if("single"===C)ek(o);else{let e=null!==(l=null===(s=ey.current.find(e=>e.id===M))||void 0===s?void 0:s.urlLines)&&void 0!==l?l:"";if(e0(e,o)){ez(e),Q(a("服务器暂无已保存 URL,已保留本地草稿","Server has no saved URLs, kept the local draft"));return}ez(o),eS(M,o)}Q(a("已从服务器读取 URL_config","Reloaded URL_config from server"))}catch(n){if(t!==eN.current||e!==ew.current.trim())return;Q(n.message)}finally{t===eN.current&&V(!1)}};(0,_.useEffect)(()=>{try{let e=window.localStorage.getItem(eG);("pro"===e||"single"===e)&&R(e)}catch(e){}},[]),(0,_.useEffect)(()=>{let e=!1;return(async()=>{try{let t=await eO(g);if(t.fetched&&t.channels.length&&!e){ey.current=t.channels,L(t.channels),eA(t.channels);return}}catch(e){}if(e)return;let t=function(){let e=window.localStorage.getItem(eR);if(!e&&(e=window.localStorage.getItem("live-hub-youtube-pro-v1"))){let t=eD(e);if(t.length)return window.localStorage.setItem(eR,JSON.stringify(t)),t}return eD(e)}(),n=t.length>0?t:(()=>{let e=eB();return[{id:e,name:"线路 1",streamKey:"",urlLines:"",pm2Name:eK(e),notes:""}]})();ey.current=n,L(n),t.length||eA(n)})(),()=>{e=!0}},[g]),(0,_.useEffect)(()=>{if(!P.length){M&&T("");return}M&&P.some(e=>e.id===M)||T(P[0].id)},[P,M]);let eM=(0,_.useCallback)(e=>f.find(t=>t.pm2===e),[f]),eU=(0,_.useCallback)(e=>{var t;return null===(t=eM(e))||void 0===t?void 0:t.process_status},[eM]),eI=eM(x),eZ=(0,_.useMemo)(()=>{var e,t;return!!x&&(/youtube/i.test(x)||/youtube/i.test(null!==(e=null==eI?void 0:eI.script)&&void 0!==e?e:"")||/youtube/i.test(null!==(t=null==eI?void 0:eI.label)&&void 0!==t?t:""))},[x,eI]);(0,_.useEffect)(()=>{"single"!==C||!S||x&&eZ||u(S)},[x,eZ,C,S,u]);let e5=(0,_.useCallback)(e=>{ey.current=e,L(e),eA(e)},[]),e2=(0,_.useCallback)(async e=>{await eH(g,e)},[g]),e3=(0,_.useCallback)(e=>{e5(e),e2(e).catch(e=>{w("".concat(a("多频道列表未同步到服务器","Channel list not saved on server"),": ").concat(e.message))})},[e5,w,e2,a]),e4=P.find(e=>e.id===M)||P[0],e6=(0,_.useMemo)(()=>{var e;return e4?null!==(e=ee[e4.id])&&void 0!==e?e:eq(e4):null},[e4,ee]);(0,_.useEffect)(()=>{e4&&et(e=>e[e4.id]?e:{...e,[e4.id]:eq(e4)})},[e4]),(0,_.useEffect)(()=>{ei(null)},[M]);let e8=(0,_.useCallback)((e,t)=>{e4&&(et(n=>{var s;return{...n,[e4.id]:{...null!==(s=n[e4.id])&&void 0!==s?s:eq(e4),[e]:t}}}),ei(null))},[e4]),e9=e4?eE(e4):"",e7=e4&&e6?eE({id:e4.id,pm2Name:e6.pm2Name}):"",te=!!e4&&!!e6&&e7!==e9,tt=(0,_.useMemo)(()=>{if(!e4||!e6)return{ok:!1,message:a("请选择线路","Pick a lane"),normalizedName:"",normalizedPm2:"",normalizedStreamKey:"",normalizedNotes:""};let e=e6.name.trim()||"".concat(a("线路","Ch")," ").concat(P.findIndex(e=>e.id===e4.id)+1),t=eE({id:e4.id,pm2Name:e6.pm2Name});return t?eV.has(t)?{ok:!1,message:a("该进程名保留给系统模块,请换一个","This PM2 name is reserved"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e6.streamKey.trim(),normalizedNotes:e6.notes.trim()}:P.find(e=>e.id!==e4.id&&eE(e)===t)?{ok:!1,message:a("该进程名已被其它线路占用","Another lane already uses this PM2 name"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e6.streamKey.trim(),normalizedNotes:e6.notes.trim()}:{ok:!0,message:"",normalizedName:e,normalizedPm2:t,normalizedStreamKey:e6.streamKey.trim(),normalizedNotes:e6.notes.trim()}:{ok:!1,message:a("进程名不能为空","PM2 name is required"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e6.streamKey.trim(),normalizedNotes:e6.notes.trim()}},[e4,e6,P,a]),tn=(0,_.useMemo)(()=>{if(!e4||!e6)return!1;let e=eq(e4);return e6.name!==e.name||e6.streamKey!==e.streamKey||eT(e6.pm2Name)!==eT(e.pm2Name)||e6.notes!==e.notes},[e4,e6]),ts=(0,_.useCallback)(e=>{var t,n,s;if("single"===e&&"pro"===C&&e4){let e=ef.current;e!==(null!==(t=e4.urlLines)&&void 0!==t?t:"").trim()&&e3(P.map(t=>t.id===e4.id?{...t,urlLines:e}:t))}if("pro"===e&&P.length){let e=P[0],t=ec.current.trim(),l=eE(e),i=[{...e,streamKey:I.key.trim()||e.streamKey||"",urlLines:t||e.urlLines||"",pm2Name:l},...P.slice(1)];e3(i);let r=null!==(n=i.find(e=>e.id===M))&&void 0!==n?n:i[0];ez((null!==(s=null==r?void 0:r.urlLines)&&void 0!==s?s:"").trim()||t)}R(e);try{window.localStorage.setItem(eG,e)}catch(e){}},[C,e4,P,ez,I.key,M,e3]),tl=(0,_.useCallback)(e=>{var t,n;let s=ef.current;e4&&"pro"===C&&s!==(null!==(t=e4.urlLines)&&void 0!==t?t:"").trim()&&e3(P.map(e=>e.id===e4.id?{...e,urlLines:s}:e)),ez((null!==(n=e.urlLines)&&void 0!==n?n:"").trim()),T(e.id),u(eE(e))},[e4,ez,C,P,u,e3]);(0,_.useEffect)(()=>{if("pro"!==C||!M)return;let e=P.find(e=>e.id===M);e&&u(eE(e))},[C,M,P,u]);let ti=(0,_.useCallback)(async()=>{let e=ew.current.trim();if(!e)return;let t=++ej.current;K(!0),O(null);try{var n;let s=new URLSearchParams({process:e,_ts:String(Date.now())}),l=await g("/get_config?".concat(s));if(t!==ej.current||e!==ew.current.trim())return;let i=null!==(n=l.content)&&void 0!==n?n:"";E(i),D(ep(i))}catch(n){if(t!==ej.current||e!==ew.current.trim())return;O(n.message)}finally{t===ej.current&&K(!1)}},[g]);(0,_.useEffect)(()=>{x&&(eP(),ti(),ea(e=>e+1))},[M,x,ti,C,eP]);let tr=(0,_.useCallback)(async()=>{var e;if(!e4||!e6)throw Error(a("请选择线路","Pick a lane"));if(!tt.ok)throw Error(tt.message);let t=ef.current,n=P.map(e=>e.id===e4.id?{...e,name:tt.normalizedName,streamKey:tt.normalizedStreamKey,pm2Name:tt.normalizedPm2,notes:tt.normalizedNotes,urlLines:t}:e);return e5(n),await e2(n),et(e=>({...e,[e4.id]:{name:tt.normalizedName,streamKey:tt.normalizedStreamKey,pm2Name:tt.normalizedPm2,notes:tt.normalizedNotes}})),{next:n,savedLane:null!==(e=n.find(e=>e.id===e4.id))&&void 0!==e?e:{...e4,name:tt.normalizedName,streamKey:tt.normalizedStreamKey,pm2Name:tt.normalizedPm2,notes:tt.normalizedNotes,urlLines:t},pm2:tt.normalizedPm2}},[e4,e6,tt,e5,P,e2,a]),ta=(0,_.useCallback)(async()=>{if(e4){es(!0),ei(null);try{let e=await tr();u(e.pm2),ei(a("线路设置已保存","Lane settings saved"))}catch(t){let e=t.message;ei(e),w(e)}finally{es(!1)}}},[e4,w,tr,u,a]),to=async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ew.current,n=t.trim();if(!n){O(a("请选择进程","Pick a process"));return}K(!0),O(null);try{let t=new URLSearchParams({process:n});await g("/save_config?".concat(t),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:e})}),E(e),O(a("youtube.ini 已保存","youtube.ini saved"))}catch(e){O(e.message)}finally{K(!1)}},tc=async()=>{let e=eg(I);await to(e)},td=async()=>{K(!0),O(null);try{var e,t;let n=U||eg(I),s=await g("/config_optimize",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:"app-config",path:(t=ew.current,"youtube.".concat(t.replace(/[^a-zA-Z0-9_.-]/g,"_"),".ini")),content:n,action:"youtube_balanced_preset"})}),l=null!==(e=s.content)&&void 0!==e?e:n;E(l),D(ep(l)),O(s.message||a("已应用 YouTube 预设","Applied YouTube preset"))}catch(e){O(e.message)}finally{K(!1)}},tx=(0,_.useMemo)(()=>{var e,t;if("single"===C)return em("key = ".concat(I.key));let n=null!==(t=null!==(e=null==e6?void 0:e6.streamKey)&&void 0!==e?e:null==e4?void 0:e4.streamKey)&&void 0!==t?t:"";return em("key = ".concat(n))},[C,I.key,null==e4?void 0:e4.streamKey,null==e6?void 0:e6.streamKey]),tu=async()=>{if(e4)try{es(!0),ei(null),eN.current+=1;let e=ef.current,t=await tr();u(t.pm2),await Promise.resolve(b(e,t.pm2)),eo.current=!1,ei(a("线路与地址已保存","Lane settings and URLs saved"))}catch(t){let e=t instanceof Error?t.message:String(t);ei(e),w(e)}finally{es(!1)}},tm=async()=>{let e=ew.current.trim();if(!e){w(a("请选择进程","Pick a process"));return}try{eN.current+=1,await Promise.resolve(b(ec.current,e)),eo.current=!1}catch(e){}},th=async()=>{let e="single"===C?ec.current:ef.current;X(!0),Q(null);try{var t;let n=await g("/config_optimize",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:"app-config",path:eb(ew.current),content:e,action:"dedupe_urls"})}),s=null!==(t=n.content)&&void 0!==t?t:e;"single"===C?ek(s):ez(s),eo.current=!0,Q(n.message||a("已去重当前 URL 列表","Deduplicated current URL list"))}catch(e){Q(e.message)}finally{X(!1)}},tp=async()=>{if(!e4||!e6)return;let e=ep(U||eg(I)),t=eg({key:e6.streamKey.trim(),rtmps:e.rtmps,bitrate:e.bitrate,fastAudio:e.fastAudio});es(!0),ei(null);try{let e=await tr();u(e.pm2),await to(t,e.pm2),ei(a("线路设置与 youtube.ini 已保存","Lane settings and youtube.ini saved"))}catch(t){let e=t.message;ei(e),w(e)}finally{es(!1)}},tb="single"===C?m:F,tg=(0,_.useMemo)(()=>eQ(tb).length,[tb]),tf=(0,_.useMemo)(()=>eh(tb).length,[tb]),tv=(0,_.useMemo)(()=>(0,eC.O0)(j),[j]),ty=(0,_.useMemo)(()=>(0,eC.U_)(tv,"pro"===C&&e4?P.findIndex(e=>e.id===e4.id):0),[e4,P,C,tv]),tw=ty.link?(0,ex.p)(ty.link.url):(0,ex.p)("http://live.local:9200/"),tN=(0,_.useMemo)(()=>(0,eC.Tc)(tv),[tv]),tj=(0,_.useMemo)(()=>{var e;return[null===(e=ty.link)||void 0===e?void 0:e.url,null==j?void 0:j.chromium_remote_debug,null==j?void 0:j.srs_api].filter(e=>!!e)},[j,null===(t=ty.link)||void 0===t?void 0:t.url]),tk=(0,_.useCallback)(async e=>{let t=e4?eE(e4):"";return e4&&e===t?await tr():(e5(P),await e2(P),{next:P,savedLane:null!=e4?e4:null,pm2:e})},[e4,e5,P,tr,e2]),tz=(0,_.useCallback)(async(e,t)=>{let n=!!e4&&eE(e4)===t;if("stop"!==e){var s,l;let e=P,n=t;try{let s=await tk(t);e=s.next,n=s.pm2}catch(e){w("".concat(a("当前线路保存失败","Failed to save the active lane"),": ").concat(e.message));return}let i=e.find(e=>eE(e)===n),r=null!==(s=null==i?void 0:i.urlLines)&&void 0!==s?s:"";if(!(null!==(l=null==i?void 0:i.streamKey)&&void 0!==l?l:"").trim()){w(a("请先填写当前线路的推流密钥","Fill the stream key before starting"));return}if(!eQ(r).length){w(a("请先填写当前线路的直播地址","Fill the source URLs before starting"));return}t=n}n&&u(t),p(e,t)},[e4,P,tk,w,p,u,a]),tS=!!o||H||G||q||en,t_=eX(eU(x)),tC=(0,s.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400",children:[(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:Y,onChange:e=>J(e.target.checked)}),a("每 8 秒自动从服务器刷新","Auto-refresh from server every 8s")]}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void eL(),className:"rounded-lg border border-white/10 px-3 py-1.5 text-zinc-200 hover:bg-white/5",children:a("手动重新读取","Reload from server")}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void th(),className:"rounded-lg border border-cyan-500/20 bg-cyan-500/10 px-3 py-1.5 text-cyan-100 hover:bg-cyan-500/15",children:q?a("去重中...","Deduplicating..."):a("智能去重","Deduplicate")})]});return(0,s.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6",children:[N?(0,s.jsx)(eu,{t:a,title:a("YouTube 转播链路","YouTube relay chain"),subtitle:a("与「网络」页相同风格的链路示意:代理 → 编码推流 → 浏览器侧操作工作室。","Same visual language as Network: proxy → encode → browser studio."),onNavigate:N,steps:[{label:"ShellCrash",sub:a("透明代理","Proxy"),gradient:"from-violet-500 to-fuchsia-500",target:"network"},{label:"FFmpeg",sub:a("推流 / 转码","Stream"),gradient:"from-cyan-400 to-blue-500",target:"live_youtube"},{label:"Neko",sub:ty.link?"".concat(a("Chromium 工作室","Chromium studio")," \xb7 ").concat(ty.link.label):a("Chromium 工作室","Chromium studio"),gradient:"from-emerald-400 to-teal-500",openUrl:tw}]}):null,(0,s.jsx)("div",{className:"rounded-2xl border border-violet-500/25 bg-gradient-to-br from-violet-500/[0.12] via-zinc-950/80 to-cyan-500/5 p-6 shadow-xl shadow-violet-900/10",children:(0,s.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[(0,s.jsxs)("div",{className:"flex items-center gap-3",children:[(0,s.jsx)("div",{className:"flex h-11 w-11 items-center justify-center rounded-xl bg-gradient-to-br from-red-500/30 to-violet-600/30 ring-1 ring-white/10",children:(0,s.jsx)(c.Z,{className:"h-5 w-5 text-red-200"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("h2",{className:"text-lg font-semibold tracking-tight text-white",children:a("YouTube 无人直播","YouTube unmanned live")}),(0,s.jsx)("p",{className:"mt-0.5 text-xs text-zinc-500",children:a("单路一条流;多路时每条线路独立保存自己的密钥、URL 列表和 PM2 任务。填好后保存,再点「开始」。Neko 浏览器仅作辅助工作室,不再阻塞推流。","Single lane or multi-lane: every lane keeps its own key, URL list, and PM2 task. Save, then Start. Neko is optional browser tooling and no longer blocks streaming.")})]})]}),(0,s.jsxs)("div",{className:"flex rounded-xl border border-white/10 bg-black/30 p-1 ".concat(""),"aria-hidden":!1,children:[(0,s.jsx)("button",{type:"button",onClick:()=>ts("single"),className:"rounded-lg px-4 py-2 text-xs font-medium transition ".concat("single"===C?"bg-violet-500/25 text-white":"text-zinc-500 hover:text-zinc-300"),children:a("单频道","Single")}),(0,s.jsx)("button",{type:"button",onClick:()=>ts("pro"),className:"rounded-lg px-4 py-2 text-xs font-medium transition ".concat("pro"===C?"bg-violet-500/25 text-white":"text-zinc-500 hover:text-zinc-300"),children:a("多频道 Pro","Multi Pro")})]})]})}),tj.length?(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[ty.link?(0,s.jsx)("a",{href:tw,target:"_blank",rel:"noreferrer",className:"rounded-lg border border-emerald-500/20 bg-emerald-500/10 px-3 py-2 text-xs text-emerald-100 ring-1 ring-emerald-500/20",children:a("打开当前线路 Neko 工作室","Open lane Neko studio")}):null,tv.length>1?(0,s.jsx)("div",{className:"flex flex-wrap gap-2",children:tv.map(e=>{var t;return(0,s.jsxs)("a",{href:(0,ex.p)(e.url),target:"_blank",rel:"noreferrer",className:"rounded-lg border px-3 py-2 text-xs ring-1 ".concat((null===(t=ty.link)||void 0===t?void 0:t.id)===e.id?"border-emerald-400/30 bg-emerald-500/15 text-emerald-50 ring-emerald-400/25":"border-white/10 bg-white/5 text-zinc-200 ring-white/10"),children:[e.label,e.port?" :".concat(e.port):""]},e.key)})}):null,(null==j?void 0:j.chromium_remote_debug)?(0,s.jsx)("a",{href:(0,ex.p)(j.chromium_remote_debug),target:"_blank",rel:"noreferrer",className:"rounded-lg border border-cyan-500/20 bg-cyan-500/10 px-3 py-2 text-xs text-cyan-100 ring-1 ring-cyan-500/20",children:a("打开 Chromium 调试","Open Chromium debug")}):null,(null==j?void 0:j.srs_api)?(0,s.jsx)("a",{href:(0,ex.p)(j.srs_api),target:"_blank",rel:"noreferrer",className:"rounded-lg border border-violet-500/20 bg-violet-500/10 px-3 py-2 text-xs text-violet-100 ring-1 ring-violet-500/20",children:a("打开 SRS API","Open SRS API")}):null]}):null,(0,s.jsxs)("div",{className:"rounded-2xl border border-amber-500/20 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 text-amber-200/90",children:[(0,s.jsx)(B.Z,{className:"h-4 w-4"}),(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播开关","Live control")})]}),"single"===C?(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:a("转播任务","Relay task")}),(0,s.jsxs)("select",{className:"mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm text-white",value:x,onChange:e=>{let t=e.target.value;ew.current=t,u(t)},children:[x&&!z.some(e=>e.pm2===x)?(0,s.jsxs)("option",{value:x,children:[x,eI?" (".concat(e$(eI,a),")"):""]}):null,z.map(e=>(0,s.jsxs)("option",{value:e.pm2,children:[function(e,t){let n=eW(e.script).toLowerCase();return n.startsWith("douyin_youtube")?t("抖音→YouTube","Douyin → YouTube"):n.startsWith("youtube")?t("YouTube","YouTube"):e.label}(e,a)," (",e.pm2,")"]},e.pm2))]}),(0,s.jsxs)("div",{className:"mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3",children:[(0,s.jsx)(e1,{kind:"start",targetPm2:x,busy:o,online:t_,label:a("开始直播","Start"),className:"bg-emerald-500/20 text-emerald-200 ring-emerald-500/30",baseLock:!1,onRun:()=>p("start",x),notify:w,t:a}),(0,s.jsx)(e1,{kind:"stop",targetPm2:x,busy:o,online:t_,label:a("停止直播","Stop"),className:"bg-rose-500/15 text-rose-200 ring-rose-500/25",baseLock:!1,onRun:()=>p("stop",x),notify:w,t:a}),(0,s.jsx)(e1,{kind:"restart",targetPm2:x,busy:o,online:t_,label:a("重新开始","Restart"),className:"bg-amber-500/15 text-amber-200 ring-amber-500/25",baseLock:!1,onRun:()=>p("restart",x),notify:w,t:a})]}),(0,s.jsxs)("p",{className:"mt-3 text-center text-xs text-zinc-400",children:[a("当前状态","Current state"),": ",e$(eI,a)]}),(0,s.jsxs)("p",{className:"mt-3 text-center font-mono text-[11px] text-zinc-600",children:["key ",a("尾码","suffix"),": ",tx||"—"]})]}):(0,s.jsx)(s.Fragment,{children:(0,s.jsxs)("div",{className:"mt-4 rounded-xl border border-cyan-500/25 bg-gradient-to-br from-cyan-500/[0.1] via-zinc-950/50 to-violet-500/[0.06] p-4 ring-1 ring-white/[0.04]",children:[(0,s.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-cyan-200/90",children:a("Pro 转播实况","Pro relay status")}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:a("对齐桌面端:每路独立 URL / youtube 配置文件;点左侧信息切换编辑,右侧控制进程。","Per-lane config files like desktop; click row info to edit, use right-side controls for PM2.")}),tN?(0,s.jsxs)("p",{className:"mt-2 text-[11px] text-zinc-500",children:[a("Neko 实例","Neko instances"),": ",tN]}):null,(0,s.jsx)("div",{className:"mt-3 max-h-[min(24rem,55vh)] space-y-2 overflow-y-auto pr-1",children:P.map(e=>{var t,n,l;let i=eE(e),r=eM(i),c=eU(i),d=eQ((null!==(t=e.urlLines)&&void 0!==t?t:"").trim()),x=eh((null!==(n=e.urlLines)&&void 0!==n?n:"").trim()),u=x[0],m=em("key = ".concat(null!==(l=e.streamKey)&&void 0!==l?l:"")),h=M===e.id,p=eX(c),b=P.findIndex(t=>t.id===e.id),g=(0,eC.U_)(tv,b).link;return(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2 rounded-lg border px-3 py-2.5 text-left text-xs transition sm:flex-nowrap ".concat(h?"border-violet-500/45 bg-violet-500/[0.1]":"border-white/10 bg-black/30 hover:border-white/18"),children:[(0,s.jsxs)("button",{type:"button",className:"min-w-0 flex-1 text-left",onClick:()=>{ew.current=eE(e),tl(e)},children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,s.jsx)("span",{className:"font-medium text-zinc-100",children:e.name}),(0,s.jsx)("span",{className:"shrink-0 rounded-md px-2 py-0.5 text-[10px] font-medium ring-1 ".concat(function(e){let t=((null==e?void 0:e.business_status)||"").trim().toLowerCase();return"ready"===t?"bg-sky-500/15 text-sky-100 ring-sky-500/25":"streaming"===t?"bg-emerald-500/15 text-emerald-200 ring-emerald-500/30":"waiting_source"===t||"monitoring"===t?"bg-amber-500/15 text-amber-100 ring-amber-500/25":"source_live"===t?"bg-sky-500/15 text-sky-100 ring-sky-500/25":"misconfigured"===t||"error"===t||"stale"===t?"bg-rose-500/15 text-rose-100 ring-rose-500/25":eX(null==e?void 0:e.process_status)?"bg-emerald-500/15 text-emerald-200 ring-emerald-500/30":"bg-zinc-600/20 text-zinc-400 ring-zinc-500/25"}(r)),children:e$(r,a)}),g?(0,s.jsx)("span",{className:"shrink-0 rounded-md bg-emerald-500/15 px-2 py-0.5 text-[10px] font-medium text-emerald-100 ring-1 ring-emerald-500/25",children:g.label}):null]}),(0,s.jsxs)("div",{className:"mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 font-mono text-[10px] text-zinc-500",children:[(0,s.jsxs)("span",{children:["key …",m||"—"]}),(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,s.jsx)("span",{className:"truncate",title:i,children:i}),(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,s.jsxs)("span",{children:["URL ",d.length]}),(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,s.jsxs)("span",{children:["DY ",x.length]})]}),u?(0,s.jsx)("a",{href:u,target:"_blank",rel:"noreferrer",className:"mt-1 block max-w-full truncate text-cyan-300/90 underline-offset-2 hover:underline",onClick:e=>e.stopPropagation(),title:u,children:u.replace(/^https?:\/\//,"")}):(0,s.jsx)("span",{className:"mt-1 block text-zinc-600",children:"—"})]}),(0,s.jsxs)("div",{className:"flex w-full shrink-0 flex-wrap items-center justify-end gap-1.5 sm:w-auto",onClick:e=>e.stopPropagation(),onKeyDown:e=>e.stopPropagation(),children:[(0,s.jsx)(e1,{kind:"start",targetPm2:i,busy:o,online:p,label:a("开始","Start"),className:"rounded-lg bg-emerald-500/20 text-emerald-100 ring-emerald-500/30",baseLock:!1,onRun:()=>void tz("start",i),notify:w,t:a,compact:!0}),(0,s.jsx)(e1,{kind:"stop",targetPm2:i,busy:o,online:p,label:a("停止","Stop"),className:"rounded-lg bg-rose-500/15 text-rose-100 ring-rose-500/25",baseLock:!1,onRun:()=>void tz("stop",i),notify:w,t:a,compact:!0}),(0,s.jsx)(e1,{kind:"restart",targetPm2:i,busy:o,online:p,label:a("重新开始","Restart"),className:"rounded-lg bg-amber-500/15 text-amber-100 ring-amber-500/25",baseLock:!1,onRun:()=>void tz("restart",i),notify:w,t:a,compact:!0}),g?(0,s.jsxs)("button",{type:"button",onClick:()=>{window.open((0,ex.p)(g.url),"_blank","noopener,noreferrer")},className:"inline-flex min-h-[2rem] items-center justify-center rounded-lg border border-emerald-500/25 bg-emerald-500/10 px-2.5 py-1.5 text-emerald-100 ring-1 ring-emerald-500/20 transition hover:bg-emerald-500/20",title:"".concat(a("打开该线路 Neko 工作室","Open this lane's Neko studio")," \xb7 ").concat(g.label).concat(g.port?" :".concat(g.port):""),"aria-label":"".concat(a("打开该线路 Neko 工作室","Open this lane's Neko studio")," \xb7 ").concat(g.label),children:[(0,s.jsx)("span",{className:"sr-only",children:a("打开该线路 Neko 工作室","Open this lane's Neko studio")}),(0,s.jsx)("span",{"aria-hidden":!0,className:"text-sm leading-none",children:"\uD83D\uDC31"}),(0,s.jsx)(Z.Z,{className:"ml-1 h-3.5 w-3.5 shrink-0","aria-hidden":!0})]}):null]})]},e.id)})})]})})]}),"single"===C?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("YouTube 相关设置","YouTube settings")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:a("串流参数写进 youtube.ini,无需 Google 登录。","Stream settings go to youtube.ini — no Google login.")}),(0,s.jsxs)("div",{className:"mt-4 space-y-3",children:[(0,s.jsx)("label",{className:"block text-xs text-zinc-400",children:a("串流密钥","Stream key")}),(0,s.jsx)("input",{className:"w-full rounded-xl border border-white/10 bg-black/40 px-4 py-3 text-sm font-mono text-zinc-200",spellCheck:!1,autoComplete:"off",value:I.key,onChange:e=>D(t=>({...t,key:e.target.value})),placeholder:"xxxx-xxxx-xxxx-xxxx-xxxx"}),(0,s.jsxs)("div",{className:"grid gap-3 sm:grid-cols-3",children:[(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-zinc-400",children:["RTMPS",(0,s.jsxs)("select",{className:"rounded-lg border border-white/10 bg-black/40 px-3 py-2 text-sm text-white",value:I.rtmps?"1":"0",onChange:e=>D(t=>({...t,rtmps:"1"===e.target.value})),children:[(0,s.jsx)("option",{value:"1",children:a("是(默认)","Yes")}),(0,s.jsx)("option",{value:"0",children:a("否 → RTMP","No")})]})]}),(0,s.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-zinc-400",children:[a("比特率 kbps","Bitrate kbps"),(0,s.jsx)("input",{className:"rounded-lg border border-white/10 bg-black/40 px-3 py-2 font-mono text-sm",value:I.bitrate,onChange:e=>D(t=>({...t,bitrate:e.target.value})),placeholder:"4000"})]}),(0,s.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 pt-6 text-xs text-zinc-300",children:[(0,s.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:I.fastAudio,onChange:e=>D(t=>({...t,fastAudio:e.target.checked}))}),"fast_audio(",a("轻量音频","lighter audio"),")"]})]})]}),(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,s.jsxs)("button",{type:"button",disabled:tS,onClick:()=>void ti(),className:"inline-flex items-center gap-2 rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-200",children:[(0,s.jsx)(y.Z,{className:"h-3.5 w-3.5 ".concat(H?"animate-spin":"")}),a("重新读取","Reload")]}),(0,s.jsxs)("button",{type:"button",disabled:tS,onClick:()=>void tc(),className:"inline-flex items-center gap-2 rounded-xl bg-violet-500/25 px-4 py-2 text-sm font-medium text-violet-100 ring-1 ring-violet-500/35",children:[H?(0,s.jsx)(v.Z,{className:"h-4 w-4 animate-spin"}):null,a("保存 youtube.ini","Save youtube.ini")]}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void td(),className:"rounded-xl border border-cyan-500/20 bg-cyan-500/10 px-4 py-2 text-sm text-cyan-100",children:a("平衡预设","Balanced preset")}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>{D(ep(U)),O(a("已从下方原文同步到表单","Synced from raw"))},className:"rounded-xl border border-white/10 px-4 py-2 text-sm text-zinc-400",children:a("从原文同步表单","Parse raw")})]}),(0,s.jsxs)("details",{className:"mt-4 rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,s.jsx)("summary",{className:"cursor-pointer text-xs text-zinc-500",children:a("高级:youtube.ini 原文","Raw youtube.ini")}),(0,s.jsx)("textarea",{className:"mt-2 h-36 w-full resize-y rounded-lg border border-white/10 bg-black/50 p-3 font-mono text-[11px] text-zinc-400",value:U,onChange:e=>E(e.target.value),spellCheck:!1}),(0,s.jsx)("button",{type:"button",disabled:tS,className:"mt-2 rounded-lg bg-cyan-500/15 px-3 py-1.5 text-xs text-cyan-200",onClick:()=>void to(U),children:a("保存原文","Save raw")})]}),A?(0,s.jsx)("p",{className:"mt-2 font-mono text-xs text-zinc-500",children:A}):null]}):(0,s.jsxs)("div",{className:"space-y-6",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsxs)("h3",{className:"text-sm font-semibold text-white",children:[a("当前线路","Current lane"),e4?(0,s.jsxs)("span",{className:"ml-2 font-normal text-zinc-400",children:["\xb7 ",e4.name]}):null,tn?(0,s.jsx)("span",{className:"ml-2 rounded-md bg-amber-500/15 px-2 py-0.5 text-[10px] font-medium text-amber-100 ring-1 ring-amber-500/25",children:a("有未保存修改","Unsaved")}):null]}),e4?(0,s.jsxs)("p",{className:"mt-0.5 font-mono text-[11px] text-zinc-500",children:["PM2: ",e9,te?" → ".concat(e7):""," \xb7 ","key ",tx||"—"]}):null]}),(0,s.jsxs)("button",{type:"button",disabled:tS,className:"inline-flex items-center gap-1 rounded-lg bg-violet-500/20 px-3 py-1.5 text-xs text-violet-100 ring-1 ring-violet-500/30",onClick:()=>{let e=eB(),t={id:e,name:"".concat(a("线路","Ch")," ").concat(P.length+1),streamKey:"",urlLines:"",pm2Name:eK(e),notes:""};et(n=>({...n,[e]:eq(t)})),e3([...P,t]),T(e),ew.current=eE(t),u(ew.current),ez("")},children:[(0,s.jsx)(e_.Z,{className:"h-3.5 w-3.5"}),a("新增线路","Add lane")]})]}),e4?(0,s.jsxs)("div",{className:"mt-4 space-y-3 border-t border-white/5 pt-4",children:[(0,s.jsx)("input",{className:"w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-sm",value:null!==(n=null==e6?void 0:e6.name)&&void 0!==n?n:"",onChange:e=>e8("name",e.target.value),placeholder:a("线路名称","Lane name")}),(0,s.jsx)("label",{className:"block text-xs text-zinc-500",children:a("串流密钥","Stream key")}),(0,s.jsx)("input",{className:"w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 font-mono text-sm",spellCheck:!1,value:null!==(l=null==e6?void 0:e6.streamKey)&&void 0!==l?l:"",onChange:e=>e8("streamKey",e.target.value),placeholder:"xxxx-xxxx… / rtmp(s)://…"}),(0,s.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void ta(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-100",children:en?a("保存中...","Saving..."):a("保存线路设置","Save lane")}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void tp(),className:"rounded-xl bg-violet-500/25 px-4 py-2 text-sm font-medium text-violet-100 ring-1 ring-violet-500/35",children:a("写入 youtube.ini","Write youtube.ini")})]}),tt.ok?null:(0,s.jsx)("p",{className:"text-xs text-rose-300",children:tt.message}),(0,s.jsxs)("details",{className:"rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,s.jsx)("summary",{className:"cursor-pointer text-xs text-zinc-500",children:a("高级:进程名","Advanced: process name")}),(0,s.jsx)("input",{className:"mt-2 w-full rounded-lg border border-white/10 bg-black/40 px-3 py-2 font-mono text-xs",value:null!==(i=null==e6?void 0:e6.pm2Name)&&void 0!==i?i:eK(e4.id),onChange:e=>e8("pm2Name",e.target.value),spellCheck:!1,placeholder:"youtube2__…"}),(0,s.jsxs)("p",{className:"mt-2 font-mono text-[11px] text-zinc-500",children:[a("实际生效","Effective"),": ",e7||"—"]}),tt.message&&!tt.ok?(0,s.jsx)("p",{className:"mt-2 text-[11px] text-rose-300",children:tt.message}):null]}),(0,s.jsx)("textarea",{className:"h-16 w-full resize-y rounded-xl border border-white/10 bg-black/40 p-3 text-xs text-zinc-300",value:null!==(r=null==e6?void 0:e6.notes)&&void 0!==r?r:"",onChange:e=>e8("notes",e.target.value),placeholder:a("备注(可选)","Notes (optional)")}),el?(0,s.jsx)("p",{className:"text-xs text-zinc-400",children:el}):null,(0,s.jsxs)("button",{type:"button",disabled:tS||P.length<2,className:"inline-flex items-center gap-1 text-xs text-rose-300 hover:text-rose-200 disabled:opacity-30",onClick:()=>{var e;let t=P.filter(e=>e.id!==e4.id);et(e=>{let t={...e};return delete t[e4.id],t}),e3(t),T((null===(e=t[0])||void 0===e?void 0:e.id)||"")},children:[(0,s.jsx)(ed.Z,{className:"h-3.5 w-3.5"}),a("删除此线路","Delete lane")]})]}):null]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播地址列表","URL list")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:a("每条线路独立写入自己的 URL_config..ini,不再复用或回填所谓“全局地址”。","Each lane writes to its own URL_config..ini with no shared global URL draft.")}),(0,s.jsx)("p",{className:"mt-1 font-mono text-[10px] text-zinc-600",children:x?eb(x):"URL_config.ini"}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2 text-[11px]",children:[(0,s.jsxs)("span",{className:"rounded-full border border-cyan-500/20 bg-cyan-500/10 px-2.5 py-1 text-cyan-100",children:[a("有效地址","Valid URLs"),": ",tg]}),(0,s.jsxs)("span",{className:"rounded-full border border-violet-500/20 bg-violet-500/10 px-2.5 py-1 text-violet-100",children:["Douyin: ",tf]})]}),tC,$?(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:$}):null,(0,s.jsx)("textarea",{className:"mt-4 min-h-[160px] w-full resize-y rounded-xl border border-white/10 bg-black/50 p-4 font-mono text-xs text-zinc-300",value:F,onChange:e=>{eo.current=!0,ez(e.target.value)},spellCheck:!1,placeholder:"https://live.douyin.com/..."}),(0,s.jsx)("div",{className:"mt-3 flex flex-wrap gap-2",children:(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void tu(),className:"rounded-xl bg-cyan-500/20 px-4 py-2 text-sm text-cyan-100 ring-1 ring-cyan-500/30",children:a("保存地址","Save URLs")})})]})]}),"single"===C?(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播地址列表 \xb7 URL_config.ini","URL_config.ini")}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:a("一行一个地址;可自动刷新或手动重新读取。","One URL per line; auto-refresh or reload.")}),(0,s.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2 text-[11px]",children:[(0,s.jsxs)("span",{className:"rounded-full border border-cyan-500/20 bg-cyan-500/10 px-2.5 py-1 text-cyan-100",children:[a("有效地址","Valid URLs"),": ",tg]}),(0,s.jsxs)("span",{className:"rounded-full border border-violet-500/20 bg-violet-500/10 px-2.5 py-1 text-violet-100",children:["Douyin: ",tf]})]}),tC,$?(0,s.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:$}):null,(0,s.jsx)("textarea",{className:"mt-4 min-h-[200px] w-full resize-y rounded-xl border border-white/10 bg-black/50 p-4 font-mono text-xs text-zinc-300",value:m,onChange:e=>{eo.current=!0,ek(e.target.value)},spellCheck:!1}),(0,s.jsx)("button",{type:"button",disabled:tS,onClick:()=>void tm(),className:"mt-3 rounded-xl bg-cyan-500/20 px-4 py-2 text-sm text-cyan-100 ring-1 ring-cyan-500/30",children:a("保存 URL 配置","Save URL config")})]}):null,(0,s.jsx)(ev,{t:a,currentProc:x,fetchJson:g,urlListText:"single"===C?m:F,keySuffixUi:tx,showKeyRow:!0,pollMs:800,refreshToken:er})]})}var e2=n(257);let e3=()=>void 0!==e2&&e2.env.NEXT_PUBLIC_API_URL||"";function e4(e){if(null==e||!Number.isFinite(e))return"—";if(0===e)return"0 B";let t=["B","KB","MB","GB","TB"],n=e,s=0;for(;n>=1024&&s=10||0===s?0:1)," ").concat(t[s])}function e6(e){let t=e4(e);return"—"===t?t:"".concat(t,"/s")}function e8(e){return"online"===e||"running"===e?"bg-emerald-500/15 text-emerald-300 ring-1 ring-emerald-500/30":"configured"===e?"bg-sky-500/15 text-sky-200 ring-1 ring-sky-500/25":"skipped"===e?"bg-slate-500/15 text-slate-300 ring-1 ring-slate-500/30":"stopped"===e||"not_found"===e?"bg-zinc-500/15 text-zinc-400 ring-1 ring-zinc-500/25":"error"===e?"bg-rose-500/15 text-rose-300 ring-1 ring-rose-500/35":"bg-violet-500/15 text-violet-200 ring-1 ring-violet-500/30"}function e9(e,t){let n=(e||"").trim().toLowerCase();return"online"===n||"running"===n?t("运行中","Running"):"configured"===n?t("已配置","Configured"):"not_found"===n?t("未注册","Unregistered"):"stopped"===n?t("已停止","Stopped"):"error"===n?t("异常","Error"):e||"—"}function e7(){var e,t,n,L,M,T,U,E,I,D,A,Z,O,H,B,K,F,W,J,G,V,q,X,$,Q,ee,et,en,es,el,ei,ea,eo,ec,ed,eu,em,eh,ep,eb,eg,ef,ev,ey,ew,eN,ej,ek,eS,e_,eR,eP,eL,eM,eT,eU,eE,eI,eD;let eA=e3(),[eZ,eO]=(0,_.useState)("zh"),[eH,eB]=(0,_.useState)("dark"),[eK,eF]=(0,_.useState)("dashboard"),[eW,eY]=(0,_.useState)(!1),[eJ,eG]=(0,_.useState)(null),[eV,eq]=(0,_.useState)(null),[eX,e$]=(0,_.useState)(!0),[eQ,e0]=(0,_.useState)(null),[e1,e2]=(0,_.useState)(null),[e7,te]=(0,_.useState)(null),[tt,tn]=(0,_.useState)(!0),[ts,tl]=(0,_.useState)([]),[ti,tr]=(0,_.useState)([]),[ta,to]=(0,_.useState)(""),[tc,td]=(0,_.useState)(""),[tx,tu]=(0,_.useState)("/sdcard/app.apk"),[tm,th]=(0,_.useState)(""),[tp,tb]=(0,_.useState)(null),[tg,tf]=(0,_.useState)(null),[tv,ty]=(0,_.useState)(!0),[tw,tN]=(0,_.useState)(!0),tj=(0,_.useRef)(null),tk=(0,_.useRef)(null),tz=(0,_.useRef)(ta),tS=(0,_.useRef)(0),t_=(0,_.useRef)(null),tC=(0,_.useCallback)((e,t)=>"zh"===eZ?e:t,[eZ]),tR=(0,_.useCallback)(e=>{e2(e),null!=t_.current&&window.clearTimeout(t_.current),t_.current=window.setTimeout(()=>{e2(null),t_.current=null},2800)},[]),tP=(0,_.useCallback)(async(e,t)=>(0,Y.N)("".concat(eA).concat(e),t),[eA]),tL=(0,_.useCallback)(async()=>{if(tj.current)return tj.current;let e=(async()=>{try{var e;let[t,n]=await Promise.allSettled([tP("/hub/dashboard"),tP("/deploy/check")]);if("fulfilled"!==t.status)throw t.reason;let s=t.value;eG(s),eq(null),te(Date.now()),"fulfilled"===n.status?tf(n.value):tf(null);let l=(null===(e=s.android)||void 0===e?void 0:e.devices)||[];if(l.length&&!tm){let e=l.find(e=>"device"===(e.state||"").toLowerCase());th((null!=e?e:l[0]).serial)}}catch(e){eq(e.message),tf(null)}finally{e$(!1),tj.current=null}})();return tj.current=e,e},[tm,tP]),tM=(0,_.useMemo)(()=>{let e=new URLSearchParams({light:"1"});return"live_youtube"===eK?e.set("family","youtube"):"live_tiktok"===eK&&e.set("family","tiktok"),"/process_monitor?".concat(e.toString())},[eK]),tT=(0,_.useCallback)(async()=>{if(tk.current)return tk.current;let e=(async()=>{try{let e=(await tP(tM)).entries||[];tr(e),tl(e.map(e=>({pm2:e.pm2,script:e.script,label:e.label}))),te(Date.now()),to(t=>!e.length||t&&e.some(e=>e.pm2===t)?t:e[0].pm2)}catch(e){}finally{tk.current=null}})();return tk.current=e,e},[tP,tM]);(0,_.useEffect)(()=>{let e=window.localStorage.getItem("live-hub-lang");("zh"===e||"en"===e)&&eO(e);let t=window.localStorage.getItem("live-hub-theme");("light"===t||"dark"===t)&&eB(t)},[]),(0,_.useEffect)(()=>{window.localStorage.setItem("live-hub-lang",eZ)},[eZ]),(0,_.useEffect)(()=>{document.documentElement.setAttribute("data-theme",eH);try{window.localStorage.setItem("live-hub-theme",eH)}catch(e){}},[eH]),(0,_.useEffect)(()=>{let e=()=>tn("visible"===document.visibilityState);return e(),document.addEventListener("visibilitychange",e),()=>document.removeEventListener("visibilitychange",e)},[]),(0,_.useEffect)(()=>{if(!eW)return;let e=e=>{"Escape"===e.key&&eY(!1)};window.addEventListener("keydown",e);let t=document.body.style.overflow;return document.body.style.overflow="hidden",()=>{window.removeEventListener("keydown",e),document.body.style.overflow=t}},[eW]),(0,_.useEffect)(()=>()=>{null!=t_.current&&window.clearTimeout(t_.current)},[]),(0,_.useEffect)(()=>{try{"0"===localStorage.getItem("livehub.autorefresh")&&ty(!1),"0"===localStorage.getItem("livehub.showStreamProbes")&&tN(!1)}catch(e){}},[]),(0,_.useEffect)(()=>{tL()},[tL]),(0,_.useEffect)(()=>{tT()},[tT]),(0,_.useEffect)(()=>{if(!tv||!tt||"live_youtube"===eK||"live_tiktok"===eK)return;let e=window.setInterval(()=>{tL()},1e4);return()=>clearInterval(e)},[tv,tt,tL,eK]),(0,_.useEffect)(()=>{if(!tv||!tt)return;let e=window.setInterval(()=>{tT()},"live_youtube"===eK||"live_tiktok"===eK?700:4e3);return()=>clearInterval(e)},[tv,tt,tT,eK]),(0,_.useEffect)(()=>{tz.current=ta},[ta]),(0,_.useEffect)(()=>{ta&&"live_youtube"===eK&&(async()=>{let e=tz.current.trim(),t=++tS.current;try{let n=new URLSearchParams({process:e,_ts:String(Date.now())}),s=await tP("/get_url_config?".concat(n));if(t!==tS.current||e!==tz.current.trim())return;td(s.content||"")}catch(e){}})()},[ta,tP,eK]),(0,_.useEffect)(()=>{"settings"===eK&&(async()=>{try{let e=await tP("/hub/config");tb(e)}catch(e){tb(null)}})()},[tP,eK]);let tU=(0,_.useMemo)(()=>{var e;let t=(null==eJ?void 0:null===(e=eJ.stack)||void 0===e?void 0:e.quick_links)||{},n={};for(let[e,s]of Object.entries(t))/^https?:\/\//i.test(s)?n[e]=(0,ex.p)(s):n[e]=s;return n},[null==eJ?void 0:null===(e=eJ.stack)||void 0===e?void 0:e.quick_links]),tE=(0,_.useMemo)(()=>(0,eC.O0)(tU),[tU]),tI=(0,_.useMemo)(()=>(0,eC.Tc)(tE),[tE]),tD=async(e,t)=>{e0("svc:".concat(e));try{let n=await tP("/service_action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({service:e,action:t})});"error"===n.status?tR(n.detail||n.message||tC("操作失败","Action failed")):tR(n.message||"OK"),await tL()}catch(e){tR(e.message)}finally{e0(null)}},tA=async(e,t)=>{let n=(null!=t?t:ta).trim();if(n){e0("proc:".concat(e,":").concat(n));try{let t=await tP("/".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({process:n})});tR(String(t.output||t.message||"OK")),await tT(),"live_youtube"===eK||"live_tiktok"===eK?tL():await tL()}catch(e){tR(e.message)}finally{e0(null)}}},tZ=async(e,t)=>{let n=(null!=t?t:ta).trim();if(!n)return;let s=null!=e?e:tc,l=++tS.current;e0("save:url");try{let e=new URLSearchParams({process:n});await tP("/save_url_config?".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:s})}),l===tS.current&&n===tz.current.trim()&&td(s),tR(tC("URL 配置已保存","URL config saved"))}catch(e){throw tR(e.message),e}finally{e0(null)}},tO=async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(!tm){tR(tC("请选择设备","Pick a device"));return}e0("adb:".concat(e));try{let n=await tP("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,serial:tm,payload:t})});tR(n.message||"OK")}catch(e){tR(e.message)}finally{e0(null)}},tH=[{id:"dashboard",icon:r.Z,labelZh:"总览",labelEn:"Dashboard"},{id:"services",icon:a.Z,labelZh:"服务",labelEn:"Services"},{id:"live_youtube",icon:o.Z,labelZh:"YouTube 无人直播",labelEn:"YouTube unmanned"},{id:"live_tiktok",icon:c.Z,labelZh:"TikTok 无人直播",labelEn:"TikTok unmanned"},{id:"android",icon:d.Z,labelZh:"安卓",labelEn:"Android"},{id:"network",icon:x.Z,labelZh:"网络",labelEn:"Network"},{id:"settings",icon:u.Z,labelZh:"设置",labelEn:"Settings"}],tB=e=>{(async()=>{var t;if(null===(t=navigator.clipboard)||void 0===t?void 0:t.writeText){await navigator.clipboard.writeText(e);return}let n=document.createElement("textarea");n.value=e,n.readOnly=!0,n.style.position="fixed",n.style.opacity="0",document.body.appendChild(n),n.select(),document.execCommand("copy"),n.remove()})().then(()=>tR(tC("已复制","Copied")),()=>tR(tC("复制失败","Copy failed")))},tK=null!==(ev=null==eJ?void 0:null===(t=eJ.services)||void 0===t?void 0:t.filter(e=>e.running&&e.available).length)&&void 0!==ev?ev:0,tF=null!==(ey=null==eJ?void 0:null===(n=eJ.services)||void 0===n?void 0:n.length)&&void 0!==ey?ey:0,tW=e7?new Date(e7).toLocaleTimeString("zh"===eZ?"zh-CN":"en-US",{hour12:!1}):tC("未同步","Not synced"),tY=tt?tC("前台自动刷新","Auto refresh"):tC("后台已暂停刷新","Refresh paused in background");return(0,s.jsxs)("div",{className:"lp-root min-h-screen transition-colors duration-300 ".concat("light"===eH?"bg-slate-100 text-slate-900 selection:bg-violet-400/25":"bg-[#050508] text-zinc-100 selection:bg-violet-500/30"),children:[(0,s.jsx)("div",{className:"lp-noise pointer-events-none fixed inset-0 z-0 ".concat("light"===eH?"opacity-[0.06]":"opacity-[0.22]"),"aria-hidden":!0}),(0,s.jsx)("div",{className:"lp-aurora pointer-events-none fixed -left-1/4 top-0 h-[42rem] w-[42rem] rounded-full blur-[120px] ".concat("light"===eH?"bg-violet-400/15":"bg-violet-600/20"),"aria-hidden":!0}),(0,s.jsx)("div",{className:"lp-aurora2 pointer-events-none fixed bottom-0 right-0 h-[36rem] w-[36rem] rounded-full blur-[100px] ".concat("light"===eH?"bg-cyan-400/10":"bg-cyan-500/10"),"aria-hidden":!0}),e1?(0,s.jsx)(l.E.div,{initial:{opacity:0,y:16},animate:{opacity:1,y:0},role:"status","aria-live":"polite","aria-atomic":"true",className:"fixed bottom-6 left-1/2 z-[100] max-w-md -translate-x-1/2 rounded-2xl border border-white/10 bg-zinc-950/95 px-5 py-3 text-center text-sm text-zinc-100 shadow-2xl shadow-black/50 backdrop-blur-xl",children:e1}):null,(0,s.jsxs)("div",{className:"relative z-10 flex min-h-screen",children:[(0,s.jsxs)("aside",{className:"hidden w-64 shrink-0 flex-col border-r px-4 py-6 backdrop-blur-2xl lg:flex ".concat("light"===eH?"border-slate-200/90 bg-white/70":"border-white/[0.06] bg-zinc-950/40"),children:[(0,s.jsxs)("div",{className:"flex items-center gap-2 px-2",children:[(0,s.jsx)("div",{className:"flex h-9 w-9 items-center justify-center rounded-xl bg-gradient-to-br from-violet-500 to-cyan-400 shadow-lg shadow-violet-500/25",children:(0,s.jsx)(m.Z,{className:"h-4 w-4 text-white"})}),(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-[0.2em] ".concat("light"===eH?"text-slate-500":"text-zinc-500"),children:"live.local"}),(0,s.jsx)("p",{className:"text-sm font-semibold ".concat("light"===eH?"text-slate-900":"text-white"),children:tC("无人直播系统","Unmanned Live System")})]})]}),(0,s.jsx)("nav",{className:"mt-10 flex flex-1 flex-col gap-1",children:tH.map(e=>{let t=e.icon,n=eK===e.id;return(0,s.jsxs)("button",{type:"button",onClick:()=>eF(e.id),"aria-current":n?"page":void 0,className:"flex items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm font-medium transition ".concat("light"===eH?n?"bg-violet-100/90 text-slate-900 shadow-inner shadow-violet-200/50":"text-slate-600 hover:bg-slate-200/60 hover:text-slate-900":n?"bg-white/[0.08] text-white shadow-inner shadow-white/5":"text-zinc-500 hover:bg-white/[0.04] hover:text-zinc-200"),children:[(0,s.jsx)(t,{className:"h-4 w-4 ".concat("light"===eH?n?"text-violet-600":"text-slate-400":n?"text-violet-300":"text-zinc-600")}),tC(e.labelZh,e.labelEn),n?(0,s.jsx)(h.Z,{className:"ml-auto h-4 w-4 ".concat("light"===eH?"text-slate-400":"text-zinc-600")}):null]},e.id)})})]}),(0,s.jsxs)("div",{className:"flex min-w-0 flex-1 flex-col",children:[(0,s.jsxs)("header",{className:"sticky top-0 z-20 flex items-center justify-between gap-3 border-b px-4 py-3 backdrop-blur-xl lg:px-8 ".concat("light"===eH?"border-slate-200/80 bg-white/75 text-slate-900":"border-white/[0.06] bg-zinc-950/70 text-white"),children:[(0,s.jsxs)("div",{className:"flex min-w-0 items-center gap-3",children:[(0,s.jsx)("button",{type:"button",className:"rounded-xl border p-2 lg:hidden ".concat("light"===eH?"border-slate-200 bg-white/80":"border-white/10 bg-white/5"),onClick:()=>eY(!0),"aria-label":"Menu",children:(0,s.jsx)(p.Z,{className:"h-5 w-5"})}),(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsx)("h1",{className:"truncate text-lg font-semibold tracking-tight lg:text-xl ".concat("light"===eH?"text-slate-900":"text-white"),children:tC((null===(L=tH.find(e=>e.id===eK))||void 0===L?void 0:L.labelZh)||"",(null===(M=tH.find(e=>e.id===eK))||void 0===M?void 0:M.labelEn)||"")}),(0,s.jsxs)("p",{className:"truncate text-xs ".concat("light"===eH?"text-slate-500":"text-zinc-500"),children:[(null==eJ?void 0:null===(T=eJ.stack)||void 0===T?void 0:T.mdns_host)||"live.local"," \xb7"," ","dark"===eH?tC("夜间","Dark mode"):tC("日间","Light mode")," \xb7 ",tY," \xb7"," ",tC("最后同步","Last sync")," ",tW]})]})]}),(0,s.jsxs)("div",{className:"flex shrink-0 items-center gap-1.5 sm:gap-2",children:[(0,s.jsx)("button",{type:"button",onClick:()=>eB(e=>"dark"===e?"light":"dark"),className:"rounded-xl border p-2 transition ".concat("light"===eH?"border-slate-200 bg-white text-amber-500 shadow-sm":"border-white/10 bg-white/[0.06] text-violet-200"),title:"dark"===eH?tC("切换到日间","Switch to light"):tC("切换到夜间","Switch to dark"),"aria-label":"dark"===eH?tC("日间模式","Light mode"):tC("夜间模式","Dark mode"),"aria-pressed":"light"===eH,children:"dark"===eH?(0,s.jsx)(b.Z,{className:"h-5 w-5",strokeWidth:2}):(0,s.jsx)(g.Z,{className:"h-5 w-5",strokeWidth:2})}),(0,s.jsxs)("button",{type:"button",onClick:()=>eO(e=>"zh"===e?"en":"zh"),className:"relative rounded-xl border p-2 transition ".concat("light"===eH?"border-slate-200 bg-white text-cyan-600 shadow-sm":"border-white/10 bg-white/[0.06] text-cyan-200"),title:"zh"===eZ?"English":"中文","aria-label":tC("切换语言","Toggle language"),"aria-pressed":"en"===eZ,children:[(0,s.jsx)(f.Z,{className:"h-5 w-5",strokeWidth:2}),(0,s.jsx)("span",{className:"absolute -bottom-0.5 -right-0.5 flex h-4 min-w-[1rem] items-center justify-center rounded px-0.5 text-[9px] font-bold leading-none ".concat("light"===eH?"bg-cyan-100 text-cyan-800":"bg-cyan-500/30 text-cyan-100"),children:"zh"===eZ?"中":"A"})]}),(0,s.jsxs)("button",{type:"button",disabled:!!eQ,onClick:()=>void Promise.all([tL(),tT()]),className:"flex items-center gap-2 rounded-xl border px-3 py-2 text-xs font-medium transition disabled:opacity-40 ".concat("light"===eH?"border-slate-200 bg-white text-slate-700 hover:bg-slate-50":"border-white/10 bg-white/[0.04] text-zinc-300 hover:bg-white/[0.07]"),children:[eQ?(0,s.jsx)(v.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,s.jsx)(y.Z,{className:"h-3.5 w-3.5"}),(0,s.jsx)("span",{className:"hidden sm:inline",children:tC("刷新","Refresh")})]})]})]}),(0,s.jsx)("main",{className:"flex-1 px-4 py-6 lg:px-8 lg:py-8",children:(0,s.jsx)(i.M,{mode:"wait",children:(0,s.jsxs)(l.E.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},exit:{opacity:0,y:-6},transition:{duration:.28,ease:[.22,1,.36,1]},children:["dashboard"===eK?(0,s.jsxs)("div",{className:"space-y-6",children:[eV?(0,s.jsxs)("div",{className:"rounded-2xl border border-rose-500/25 bg-rose-950/20 p-4 text-sm text-rose-200",children:[tC("无法加载仪表盘:","Dashboard error: "),eV]}):null,(0,s.jsx)(l.E.div,{initial:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{delay:.02},className:"rounded-2xl border p-2 backdrop-blur-xl ".concat("light"===eH?"border-slate-200/90 bg-white/80 shadow-sm shadow-slate-200/30":"border-white/[0.07] bg-zinc-950/30"),children:(0,s.jsx)(R.Z,{snapshot:null!==(ew=null==eJ?void 0:eJ.snapshot)&&void 0!==ew?ew:null,theme:eH,tr:tC})}),(0,s.jsx)(l.E.div,{initial:{opacity:0,y:8},animate:{opacity:1,y:0},transition:{delay:.05},className:"rounded-2xl border p-3 shadow-lg ".concat("light"===eH?"border-fuchsia-200/80 bg-gradient-to-br from-fuchsia-50/90 via-white to-cyan-50/70 shadow-fuchsia-100/40":"border-fuchsia-500/20 bg-gradient-to-br from-fuchsia-500/10 via-zinc-950/60 to-cyan-500/10 shadow-fuchsia-900/10"),children:(0,s.jsx)(C,{tr:tC})}),(0,s.jsx)("div",{className:"grid gap-2 sm:grid-cols-2 xl:grid-cols-5",children:[{icon:w.Z,label:tC("CPU 1m","CPU 1m"),value:null!==(eN=null==eJ?void 0:null===(I=eJ.snapshot)||void 0===I?void 0:null===(E=I.cpu_load)||void 0===E?void 0:null===(U=E["1m"])||void 0===U?void 0:U.toFixed(2))&&void 0!==eN?eN:"—",sub:tC("负载均值","Load avg")},{icon:r.Z,label:tC("内存","Memory"),value:e4(null==eJ?void 0:null===(A=eJ.snapshot)||void 0===A?void 0:null===(D=A.memory)||void 0===D?void 0:D.available),sub:"/ ".concat(e4(null==eJ?void 0:null===(O=eJ.snapshot)||void 0===O?void 0:null===(Z=O.memory)||void 0===Z?void 0:Z.total))},{icon:N.Z,label:tC("磁盘可用","Disk free"),value:e4(null==eJ?void 0:null===(B=eJ.snapshot)||void 0===B?void 0:null===(H=B.disk)||void 0===H?void 0:H.free),sub:"/ ".concat(e4(null==eJ?void 0:null===(F=eJ.snapshot)||void 0===F?void 0:null===(K=F.disk)||void 0===K?void 0:K.total))},{icon:a.Z,label:tC("服务在线","Services up"),value:"".concat(tK,"/").concat(tF||"—"),sub:tC("基础服务层","Infra layer")},{icon:j.Z,label:tC("运行时间","Uptime"),value:function(e){if(null==e||!Number.isFinite(e))return"—";let t=Math.max(0,Math.floor(e)),n=Math.floor(t/86400),s=Math.floor(t%86400/3600),l=Math.floor(t%3600/60);return n>0?"".concat(n,"d ").concat(s,"h"):s>0?"".concat(s,"h ").concat(l,"m"):"".concat(l,"m")}(null==eJ?void 0:null===(W=eJ.snapshot)||void 0===W?void 0:W.uptime_seconds),sub:tC("自开机","Since boot")}].map((e,t)=>(0,s.jsxs)(l.E.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},transition:{delay:.05*t,duration:.35,ease:[.22,1,.36,1]},whileHover:{y:-2},className:"group relative overflow-hidden rounded-xl border border-white/[0.07] bg-gradient-to-br from-white/[0.05] to-transparent p-3 shadow-lg shadow-black/20",children:[(0,s.jsx)("div",{className:"absolute -right-4 -top-4 h-16 w-16 rounded-full bg-violet-500/10 blur-xl transition group-hover:bg-violet-500/18"}),(0,s.jsx)(e.icon,{className:"h-4 w-4 text-violet-300/90"}),(0,s.jsx)("p",{className:"mt-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:e.label}),(0,s.jsx)("p",{className:"mt-0.5 font-mono text-lg font-semibold leading-tight text-white",children:eX?"…":e.value}),(0,s.jsx)("p",{className:"mt-0.5 text-[10px] text-zinc-500",children:e.sub})]},e.label))}),(null==eJ?void 0:eJ.hardware)&&"object"==typeof eJ.hardware?(0,s.jsxs)("div",{className:"rounded-2xl border border-indigo-500/25 bg-gradient-to-br from-indigo-500/[0.1] via-zinc-950/70 to-violet-500/[0.08] p-6 shadow-2xl shadow-indigo-500/5",children:[(0,s.jsx)("h3",{className:"text-base font-semibold text-white",children:tC("系统硬件与软件能力","Hardware & software profile")}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("来自 hardware_probe;用于直播/解码策略参考。","From hardware_probe; guides decode/streaming posture.")}),(0,s.jsxs)("div",{className:"mt-5 grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-indigo-300/90",children:tC("平台","Platform")}),(0,s.jsxs)("dl",{className:"space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"arch"}),(0,s.jsx)("dd",{className:"text-right text-zinc-200",children:String(null!==(ej=eJ.hardware.arch)&&void 0!==ej?ej:"—")})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"kernel"}),(0,s.jsx)("dd",{className:"text-right text-zinc-200",children:String(null!==(eS=null!==(ek=eJ.hardware.kernel)&&void 0!==ek?ek:null===(J=eJ.stack)||void 0===J?void 0:J.kernel)&&void 0!==eS?eS:"—")})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"Python"}),(0,s.jsx)("dd",{className:"text-right text-zinc-200",children:String(null!==(e_=null===(G=eJ.stack)||void 0===G?void 0:G.python)&&void 0!==e_?e_:"—")})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"mDNS"}),(0,s.jsx)("dd",{className:"text-right text-cyan-200/90",children:null!==(eR=null===(V=eJ.stack)||void 0===V?void 0:V.mdns_host)&&void 0!==eR?eR:"—"})]}),(0,s.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"IP"}),(0,s.jsx)("dd",{className:"text-right text-zinc-300",children:((null===(q=eJ.stack)||void 0===q?void 0:q.ips)||[]).join(" \xb7 ")||"—"})]})]})]}),(0,s.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-fuchsia-300/90",children:"GPU / NPU"}),(()=>{let e=eJ.hardware.gpu,t=eJ.hardware.npu;return(0,s.jsxs)("dl",{className:"space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"GPU"}),(0,s.jsxs)("dd",{className:"mt-0.5 text-zinc-200",children:[(null==e?void 0:e.present)?tC("已检测","present"):tC("未检测","absent"),(null==e?void 0:e.driver)?" \xb7 ".concat(e.driver):""]})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"render"}),(0,s.jsx)("dd",{className:"mt-0.5 break-all text-zinc-500",children:((null==e?void 0:e.render_nodes)||[]).join(", ")||"—"})]}),(0,s.jsxs)("div",{children:[(0,s.jsx)("dt",{className:"text-zinc-600",children:"NPU"}),(0,s.jsx)("dd",{className:"mt-0.5 break-all text-zinc-500",children:(null==t?void 0:t.present)?(t.devices||[]).join(", "):tC("—","—")})]})]})})()]}),(0,s.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4 lg:col-span-2",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-emerald-300/90",children:"ffmpeg / 建议策略"}),(()=>{var e,t,n,l;let i=eJ.hardware.ffmpeg_hwaccels||[],r=eJ.hardware.recommendation;return(0,s.jsxs)("div",{className:"space-y-2 text-[11px] text-zinc-400",children:[(0,s.jsxs)("p",{children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"hwaccels: "}),(0,s.jsx)("span",{className:"font-mono text-emerald-200/90",children:i.length?i.join(", "):"—"})]}),(0,s.jsxs)("div",{className:"grid gap-2 sm:grid-cols-2",children:[(0,s.jsxs)("p",{children:[(0,s.jsxs)("span",{className:"text-zinc-600",children:[tC("解码","Decoder"),": "]}),(0,s.jsx)("span",{className:"text-zinc-200",children:null!==(e=null==r?void 0:r.video_decoder)&&void 0!==e?e:"—"})]}),(0,s.jsxs)("p",{children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"HDMI: "}),(0,s.jsx)("span",{className:"text-zinc-200",children:null!==(t=null==r?void 0:r.hdmi_player)&&void 0!==t?t:"—"})]}),(0,s.jsxs)("p",{children:[(0,s.jsx)("span",{className:"text-zinc-600",children:"Browser: "}),(0,s.jsx)("span",{className:"text-zinc-200",children:null!==(n=null==r?void 0:r.browser_hwaccel)&&void 0!==n?n:"—"})]}),(0,s.jsxs)("p",{children:[(0,s.jsxs)("span",{className:"text-zinc-600",children:[tC("稳定模式","Stability"),": "]}),(0,s.jsx)("span",{className:"text-amber-200/90",children:null!==(l=null==r?void 0:r.stability_mode)&&void 0!==l?l:"—"})]})]}),((null==r?void 0:r.degradation_reasons)||[]).length?(0,s.jsx)("ul",{className:"mt-2 list-inside list-disc space-y-1 text-[10px] text-amber-200/80",children:((null==r?void 0:r.degradation_reasons)||[]).map(e=>(0,s.jsx)("li",{children:e},e))}):null]})})()]})]})]}):null,tg?(0,s.jsxs)("div",{className:"rounded-2xl border p-5 ".concat(tg.ready?"border-emerald-500/25 bg-gradient-to-br from-emerald-500/[0.08] via-zinc-950/50 to-cyan-500/[0.05]":"border-amber-500/30 bg-gradient-to-br from-amber-500/[0.1] via-zinc-950/55 to-rose-500/[0.05]"),children:[(0,s.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("安装验收","Deployment health")}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("一键脚本完成后,本机 API、局域网入口、反向代理与 mDNS 的可用性检查。","Post-install checks for loopback API, LAN access, reverse proxy, and mDNS.")})]}),(0,s.jsx)("span",{className:"rounded-full px-3 py-1 text-[10px] font-semibold ".concat(tg.ready?"bg-emerald-500/20 text-emerald-100 ring-1 ring-emerald-500/30":"bg-amber-500/20 text-amber-100 ring-1 ring-amber-500/30"),children:tg.ready?tC("可交付","Ready"):tC("需处理","Needs attention")})]}),(0,s.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:tC("验收摘要","Acceptance summary")}),(0,s.jsxs)("p",{className:"mt-2 font-mono text-sm text-white",children:[null!==(eP=tg.pass_count)&&void 0!==eP?eP:0,"/",null!==(eL=tg.total_count)&&void 0!==eL?eL:0,(0,s.jsx)("span",{className:"ml-2 text-[11px] text-zinc-500",children:tC("已通过","checks passed")})]}),(0,s.jsxs)("p",{className:"mt-1 text-[11px] text-zinc-500",children:[tC("必需项","Required"),": ",null!==(eM=tg.required_total)&&void 0!==eM?eM:0," \xb7 mDNS"," ",tg.mdns_enabled?tC("已启用","enabled"):tC("已关闭","disabled")," \xb7 edge"," ",tg.live_edge_enabled?tC("已启用","enabled"):tC("已关闭","disabled")]}),(0,s.jsx)("div",{className:"mt-3 flex flex-wrap gap-2",children:Object.entries(tg.urls||{}).filter(e=>{let[,t]=e;return!!t}).slice(0,4).map(e=>{let[t,n]=e;return(0,s.jsx)("a",{href:(0,ex.p)(n),target:"_blank",rel:"noreferrer",className:"rounded-lg border border-white/10 bg-white/5 px-3 py-2 text-[11px] text-zinc-200 ring-1 ring-white/10",children:t},t)})})]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,s.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:(null===(X=tg.failing_checks)||void 0===X?void 0:X.length)?tC("失败项","Failing checks"):tC("当前状态","Current state")}),(null===($=tg.failing_checks)||void 0===$?void 0:$.length)?(0,s.jsx)("ul",{className:"mt-2 space-y-2 text-[11px] text-zinc-300",children:tg.failing_checks.slice(0,4).map(e=>(0,s.jsxs)("li",{className:"rounded-lg border border-amber-500/20 bg-amber-500/10 px-3 py-2",children:[(0,s.jsx)("span",{className:"font-semibold text-amber-100",children:e.label}),(0,s.jsx)("span",{className:"ml-2 text-zinc-400",children:e.detail||"—"})]},e.id))}):(0,s.jsx)("p",{className:"mt-2 text-[11px] text-emerald-200/90",children:tC("必需检查已全部通过,可直接用浏览器面板交付。","All required checks pass; browser control plane is ready.")}),(tg.hints||[]).length?(0,s.jsx)("ul",{className:"mt-3 list-inside list-disc space-y-1 text-[10px] text-zinc-400",children:(tg.hints||[]).slice(0,3).map(e=>(0,s.jsx)("li",{children:e},e))}):null]})]})]}):null,(null==eJ?void 0:null===(Q=eJ.stack)||void 0===Q?void 0:Q.neko_login)?(0,s.jsxs)("div",{className:"rounded-2xl border border-fuchsia-500/25 bg-gradient-to-r from-fuchsia-500/[0.08] to-violet-500/[0.06] p-5",children:[(0,s.jsxs)("h3",{className:"text-sm font-semibold text-white",children:["Neko ",tC("登录","sign-in")]}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:eJ.stack.neko_login.note_zh||tC(tI?"Neko Chromium ".concat(tI," 使用下列账号策略。"):"Neko Chromium 多实例使用下列账号策略。",tI?"Neko Chromium ".concat(tI," uses the policy below."):"Neko Chromium instances use the policy below.")}),(0,s.jsx)("p",{className:"mt-2 text-[11px] text-amber-200/85",children:tC("重要:两栏分开填——昵称随意,密码必须是环境变量里的口令(默认 12345678)。用错密码会像一直加载;勿把「用户名/密码」写在一行。","Use two fields: display name is free-form; password must match NEKO_* (default 12345678). Wrong password looks like infinite loading.")}),tE.length?(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:tE.map(e=>(0,s.jsxs)("a",{href:e.url,target:"_blank",rel:"noreferrer",className:"rounded-lg border border-fuchsia-400/20 bg-black/25 px-3 py-2 text-[11px] text-fuchsia-100 ring-1 ring-fuchsia-400/20",children:[e.label,e.port?" :".concat(e.port):""]},e.key))}):null,(0,s.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2 font-mono text-sm",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/40 px-4 py-3",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase text-zinc-500",children:tC("昵称示例","Display Name Example")}),(0,s.jsx)("p",{className:"mt-1 text-fuchsia-200",children:null!==(eT=eJ.stack.neko_login.user_login)&&void 0!==eT?eT:"live"}),(0,s.jsx)("p",{className:"mt-2 text-[10px] uppercase text-zinc-500",children:tC("连接口令","Access Password")}),(0,s.jsx)("p",{className:"mt-0.5 text-fuchsia-100",children:null!==(eU=eJ.stack.neko_login.user_password)&&void 0!==eU?eU:"—"})]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/40 px-4 py-3",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase text-zinc-500",children:tC("管理昵称示例","Admin Display Name Example")}),(0,s.jsx)("p",{className:"mt-1 text-violet-200",children:null!==(eE=eJ.stack.neko_login.admin_login)&&void 0!==eE?eE:"admin"}),(0,s.jsx)("p",{className:"mt-2 text-[10px] uppercase text-zinc-500",children:tC("管理口令","Admin Password")}),(0,s.jsx)("p",{className:"mt-0.5 text-violet-100",children:null!==(eI=eJ.stack.neko_login.admin_password)&&void 0!==eI?eI:"—"})]})]}),(0,s.jsx)("p",{className:"mt-3 text-[10px] text-zinc-600",children:tC("x86 默认使用 Neko 的 Chrome 镜像,ARM 默认使用 Chromium 镜像;默认保留管理员会话、开发者工具和 Tampermonkey 持久化。本栈未启用 Firefox 版 Neko。","x86 defaults to Neko’s Chrome image, ARM defaults to Chromium, and admin access, DevTools, plus persistent Tampermonkey stay enabled. This stack does not use Firefox Neko.")})]}):null,(null==eJ?void 0:null===(et=eJ.network)||void 0===et?void 0:null===(ee=et.interfaces)||void 0===ee?void 0:ee.length)?(0,s.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-gradient-to-br from-cyan-500/[0.07] to-transparent p-5",children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,s.jsx)(k.Z,{className:"h-4 w-4 text-cyan-300"}),tC("网络带宽 / 流量","Network bandwidth / traffic")]}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("实时速率由总览自动刷新间隔计算;累计值来自系统网卡计数器。","Live rates are calculated from dashboard refresh deltas; totals come from kernel counters.")}),(0,s.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase tracking-[0.08em] text-cyan-300/70",children:tC("实时下行","Live down")}),(0,s.jsx)("p",{className:"mt-1 text-lg font-semibold text-cyan-100",children:e6(eJ.network.total_rx_bps)}),(0,s.jsxs)("p",{className:"mt-1 text-zinc-500",children:[tC("累计","Total"),": ",e4(eJ.network.total_rx_bytes)]})]}),(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,s.jsx)("p",{className:"text-[10px] uppercase tracking-[0.08em] text-cyan-300/70",children:tC("实时上行","Live up")}),(0,s.jsx)("p",{className:"mt-1 text-lg font-semibold text-cyan-100",children:e6(eJ.network.total_tx_bps)}),(0,s.jsxs)("p",{className:"mt-1 text-zinc-500",children:[tC("累计","Total"),": ",e4(eJ.network.total_tx_bytes)]})]})]}),(0,s.jsx)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:(eJ.network.interfaces||[]).slice(0,6).map(e=>{var t,n,l,i;return(0,s.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,s.jsx)("p",{className:"text-xs font-semibold text-cyan-200/90",children:e.name}),(0,s.jsxs)("p",{className:"mt-2 text-zinc-500",children:[tC("链路","Link"),": ",e.operstate||"unknown"," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e.speed_mbps?"".concat(e.speed_mbps," Mbps"):tC("未知速率","unknown speed")]}),(0,s.jsxs)("p",{className:"mt-2 text-zinc-500",children:["↓ ",e6(e.rx_bps)," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e4(e.rx_bytes)," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",null!==(l=null===(t=e.rx_packets)||void 0===t?void 0:t.toLocaleString())&&void 0!==l?l:"—"," pkt"]}),(0,s.jsxs)("p",{className:"mt-0.5 text-zinc-500",children:["↑ ",e6(e.tx_bps)," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e4(e.tx_bytes)," ",(0,s.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",null!==(i=null===(n=e.tx_packets)||void 0===n?void 0:n.toLocaleString())&&void 0!==i?i:"—"," pkt"]})]},e.name)})})]}):null,(null==eJ?void 0:null===(es=eJ.live_events)||void 0===es?void 0:null===(en=es.pm2_tail)||void 0===en?void 0:en.length)||(null==eJ?void 0:null===(ei=eJ.live_events)||void 0===ei?void 0:null===(el=ei.process_digest)||void 0===el?void 0:el.length)?(0,s.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,s.jsxs)("div",{className:"rounded-2xl border border-amber-500/15 bg-zinc-950/40 p-5",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("直播 / PM2 事件","Live / PM2 feed")}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("PM2 合并日志尾部","PM2 merged log tail")}),(0,s.jsx)("pre",{className:"mt-3 max-h-48 overflow-auto whitespace-pre-wrap rounded-lg border border-white/[0.05] bg-black/40 p-3 font-mono text-[10px] leading-relaxed text-zinc-400",children:((null==eJ?void 0:null===(ea=eJ.live_events)||void 0===ea?void 0:ea.pm2_tail)||[]).join("\n")||tC("暂无 PM2 输出","No PM2 output")})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/15 bg-zinc-950/40 p-5",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("进程快照","Process digest")}),(0,s.jsx)("ul",{className:"mt-3 space-y-2",children:((null==eJ?void 0:null===(eo=eJ.live_events)||void 0===eo?void 0:eo.process_digest)||[]).map(e=>(0,s.jsxs)("li",{className:"flex items-center justify-between gap-2 rounded-lg border border-white/[0.05] bg-black/30 px-3 py-2 text-xs",children:[(0,s.jsx)("span",{className:"truncate text-zinc-300",children:e.label||e.pm2}),(0,s.jsx)("span",{className:"shrink-0 rounded-md px-2 py-0.5 text-[10px] font-medium ".concat(e8(e.status||"")),children:e9(e.status||"",tC)})]},e.pm2))})]})]}):null,(0,s.jsxs)("div",{className:"rounded-2xl border border-violet-500/20 bg-gradient-to-br from-violet-500/[0.12] via-zinc-950/50 to-fuchsia-500/[0.06] p-5 shadow-lg shadow-violet-500/5",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,s.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("直播进程","Live processes")}),(0,s.jsx)("span",{className:"rounded-full bg-white/10 px-2 py-0.5 text-[10px] font-medium text-zinc-300",children:(null==eJ?void 0:null===(ec=eJ.live)||void 0===ec?void 0:ec.backend_mode)||"—"})]}),(0,s.jsxs)("ul",{className:"mt-4 space-y-2.5",children:[((null==eJ?void 0:null===(ed=eJ.live)||void 0===ed?void 0:ed.processes)||[]).slice(0,10).map(e=>(0,s.jsxs)("li",{className:"group flex items-center gap-3 rounded-xl border border-white/[0.08] bg-black/35 px-3 py-2.5 transition hover:border-violet-400/25 hover:bg-black/45",children:[(0,s.jsx)("div",{className:"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-gradient-to-br from-violet-500/30 to-fuchsia-500/20 text-[10px] font-bold text-violet-100 ring-1 ring-white/10",children:"LIVE"}),(0,s.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,s.jsx)("p",{className:"truncate text-sm font-medium text-zinc-100",children:e.label||e.pm2}),(0,s.jsx)("p",{className:"truncate font-mono text-[10px] text-zinc-600",children:e.script||e.pm2})]}),(0,s.jsx)("span",{className:"shrink-0 rounded-lg px-2.5 py-1 text-[10px] font-semibold ".concat(e8(e.process_status||"")),children:e9(e.process_status||"",tC)})]},e.pm2)),(null==eJ?void 0:null===(em=eJ.live)||void 0===em?void 0:null===(eu=em.processes)||void 0===eu?void 0:eu.length)?null:(0,s.jsx)("li",{className:"rounded-xl border border-dashed border-white/10 py-8 text-center text-xs text-zinc-600",children:tC("暂无直播进程","No live processes")})]}),(0,s.jsxs)("div",{className:"mt-5 grid grid-cols-2 gap-2",children:[(0,s.jsx)("button",{type:"button",onClick:()=>eF("live_youtube"),className:"rounded-xl border border-violet-400/35 bg-violet-500/15 py-2.5 text-[11px] font-semibold text-violet-100 shadow-inner shadow-black/20 transition hover:bg-violet-500/25",children:"YouTube"}),(0,s.jsx)("button",{type:"button",onClick:()=>eF("live_tiktok"),className:"rounded-xl border border-cyan-400/35 bg-cyan-500/15 py-2.5 text-[11px] font-semibold text-cyan-100 shadow-inner shadow-black/20 transition hover:bg-cyan-500/25",children:"TikTok"})]})]}),(null==eJ?void 0:eJ.probes)&&tw?(0,s.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:[eJ.probes.srs?(()=>{var e,t,n,l,i,r,a;let o=null===(e=eJ.probes)||void 0===e?void 0:e.srs,c=null==o?void 0:null===(t=o.tcp)||void 0===t?void 0:t.reachable,d=null==o?void 0:null===(n=o.tcp_api)||void 0===n?void 0:n.reachable,x=null==o?void 0:o.http_ui,u=null==o?void 0:o.http,m=null==o?void 0:o.api_port,h=null!==(i=null==o?void 0:o.api_ok)&&void 0!==i?i:(null==u?void 0:u.http_code)===200,p=null==x?void 0:x.http_code;return(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-zinc-950/40 p-4 backdrop-blur-sm",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,s.jsx)("p",{className:"text-xs font-semibold text-white",children:"SRS"}),(0,s.jsx)("span",{className:"rounded-full px-2 py-0.5 text-[10px] font-semibold ".concat(h?"bg-emerald-500/20 text-emerald-200 ring-1 ring-emerald-500/30":"bg-rose-500/15 text-rose-200 ring-1 ring-rose-500/25"),children:h?tC("API 正常","API OK"):tC("API 异常","API down")})]}),(0,s.jsxs)("p",{className:"mt-1 font-mono text-[11px] text-zinc-500",children:[":",null!==(r=null==o?void 0:o.port)&&void 0!==r?r:"—"," / API :",null!=m?m:"—"," \xb7 TCP ",c?"OK":"—"," \xb7 API TCP"," ",d?"OK":"—"]}),(0,s.jsxs)("p",{className:"mt-1 font-mono text-[11px] text-zinc-500",children:["API HTTP ",null!==(a=null==u?void 0:u.http_code)&&void 0!==a?a:"—"," \xb7 ",tC("根路径","root")," ",null!=p?p:"—",404===p?tC("(无首页不影响推流)"," (no index is OK for streaming)"):null]}),(0,s.jsxs)("p",{className:"mt-1 text-[11px] text-zinc-500",children:[tC("延迟","RTT")," ",(null==u?void 0:u.latency_ms)!=null?"".concat(u.latency_ms," ms"):(null==o?void 0:null===(l=o.tcp)||void 0===l?void 0:l.latency_ms)!=null?"".concat(o.tcp.latency_ms," ms"):"—"]}),!h&&(null==u?void 0:u.error)?(0,s.jsx)("p",{className:"mt-1 line-clamp-2 text-[10px] text-amber-200/80",children:u.error}):null]})})():null,eJ.probes.neko?(()=>{var e,t,n,l,i,r,a;let o=null===(e=eJ.probes)||void 0===e?void 0:e.neko,c=null==o?void 0:null===(t=o.tcp)||void 0===t?void 0:t.reachable,d=null==o?void 0:o.http,x=(null==o?void 0:o.instances)||[],u=null!==(l=null==o?void 0:o.running_count)&&void 0!==l?l:x.filter(e=>{var t;return null===(t=e.tcp)||void 0===t?void 0:t.reachable}).length,m=null!==(i=null==o?void 0:o.required_count)&&void 0!==i?i:x.length;return(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-zinc-950/40 p-4 backdrop-blur-sm",children:[(0,s.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,s.jsx)("p",{className:"text-xs font-semibold text-white",children:"Neko Chromium"}),(0,s.jsxs)("span",{className:"rounded-full px-2 py-0.5 text-[10px] font-semibold ".concat(u>0?"bg-emerald-500/20 text-emerald-200 ring-1 ring-emerald-500/30":"bg-rose-500/15 text-rose-200 ring-1 ring-rose-500/25"),children:[u,"/",m||"—"," ",tC("在线","online")]})]}),(0,s.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("Docker 内 Chromium(非 Chrome 品牌);arm64/x86 同一镜像。","Chromium in Docker (not Chrome branding); multi-arch.")}),(0,s.jsxs)("p",{className:"mt-2 font-mono text-[11px] text-zinc-500",children:[":",null!==(r=null==o?void 0:o.port)&&void 0!==r?r:"—"," \xb7 TCP ",c?"OK":"—"," \xb7 HTTP ",null!==(a=null==d?void 0:d.http_code)&&void 0!==a?a:"—"]}),(0,s.jsxs)("p",{className:"mt-1 text-[11px] text-zinc-500",children:[tC("延迟","RTT")," ",(null==d?void 0:d.latency_ms)!=null?"".concat(d.latency_ms," ms"):(null==o?void 0:null===(n=o.tcp)||void 0===n?void 0:n.latency_ms)!=null?"".concat(o.tcp.latency_ms," ms"):"—"]}),x.length?(0,s.jsx)("div",{className:"mt-3 space-y-2",children:x.map(e=>{var t,n,l,i,r,a,o;return(0,s.jsxs)("div",{className:"flex items-center justify-between gap-3 rounded-lg border border-white/[0.05] bg-black/25 px-3 py-2",children:[(0,s.jsxs)("div",{className:"min-w-0",children:[(0,s.jsxs)("p",{className:"text-[11px] font-semibold text-zinc-200",children:["Neko ",null!==(r=e.id)&&void 0!==r?r:"?"]}),(0,s.jsxs)("p",{className:"font-mono text-[10px] text-zinc-500",children:[":",null!==(a=e.port)&&void 0!==a?a:"—"," \xb7 TCP ",(null===(t=e.tcp)||void 0===t?void 0:t.reachable)?"OK":"—"," \xb7 HTTP"," ",null!==(o=null===(n=e.http)||void 0===n?void 0:n.http_code)&&void 0!==o?o:"—"]})]}),(0,s.jsx)("span",{className:"shrink-0 rounded-full px-2 py-0.5 text-[10px] font-semibold ".concat((null===(l=e.tcp)||void 0===l?void 0:l.reachable)?"bg-emerald-500/15 text-emerald-200 ring-1 ring-emerald-500/25":"bg-zinc-500/15 text-zinc-400 ring-1 ring-zinc-500/25"),children:(null===(i=e.tcp)||void 0===i?void 0:i.reachable)?tC("运行中","Running"):tC("未连通","Offline")})]},"".concat(e.id,"-").concat(e.port))})}):null,!(null==d?void 0:d.reachable)&&(null==d?void 0:d.error)?(0,s.jsx)("p",{className:"mt-1 line-clamp-2 text-[10px] text-amber-200/80",children:d.error}):null]})})():null]}):null]}):null,"services"===eK?(0,s.jsxs)("div",{className:"grid gap-4 md:grid-cols-2 xl:grid-cols-3",children:[((null==eJ?void 0:eJ.services)||[]).map((e,t)=>(0,s.jsxs)(l.E.div,{initial:{opacity:0,y:10},animate:{opacity:1,y:0},transition:{delay:.04*t},whileHover:{y:-2},className:"rounded-2xl border border-white/[0.07] bg-gradient-to-b from-white/[0.05] to-transparent p-5",children:[(0,s.jsxs)("div",{className:"flex items-start justify-between gap-2",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("h3",{className:"font-semibold text-white",children:e.label}),(0,s.jsx)("p",{className:"mt-1 text-xs text-zinc-500 line-clamp-2",children:e.description})]}),(0,s.jsx)("span",{className:"shrink-0 rounded-full px-2.5 py-1 text-[10px] font-semibold ".concat(e8(e.running?"online":e.status)),children:e.running?tC("运行中","Running"):e.status})]}),e.detail?(0,s.jsx)("p",{className:"mt-2 text-[11px] leading-snug line-clamp-6 ".concat("skipped"===e.status?"text-slate-300/90":"text-amber-200/85"),children:e.detail}):null,"shellcrash"===e.service_id&&e.available&&!e.running?(0,s.jsx)("p",{className:"mt-2 text-[11px] text-zinc-500",children:tC("stopped 为常态:仅当需要透明代理 / 规则分流时再点 Start(或 systemctl enable --now shellcrash)。","Stopped is normal; Start only when you need the proxy (or enable shellcrash.service).")}):null,(0,s.jsxs)("div",{className:"mt-4 flex flex-wrap items-center gap-2",children:[e.url?(0,s.jsx)("a",{href:(0,ex.p)(e.url),target:"_blank",rel:"noreferrer",className:"rounded-lg bg-violet-500/15 px-3 py-1.5 text-xs font-medium text-violet-200 ring-1 ring-violet-500/25",children:tC("打开面板","Open panel")}):null,(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"start"),className:"rounded-lg bg-emerald-500/20 px-3 py-1.5 text-xs font-medium text-emerald-200 ring-1 ring-emerald-500/30 disabled:opacity-30",children:"Start"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"install"),className:"rounded-lg bg-sky-500/15 px-3 py-1.5 text-xs font-medium text-sky-200 ring-1 ring-sky-500/25 disabled:opacity-30",children:"Install"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"restart"),className:"rounded-lg bg-amber-500/15 px-3 py-1.5 text-xs font-medium text-amber-200 ring-1 ring-amber-500/25 disabled:opacity-30",children:"Restart"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"upgrade"),className:"rounded-lg bg-indigo-500/15 px-3 py-1.5 text-xs font-medium text-indigo-200 ring-1 ring-indigo-500/25 disabled:opacity-30",children:"Upgrade"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"stop"),className:"rounded-lg bg-rose-500/15 px-3 py-1.5 text-xs font-medium text-rose-200 ring-1 ring-rose-500/25 disabled:opacity-30",children:"Stop"}),(0,s.jsx)("button",{type:"button",disabled:!!eQ||!e.available||"android_gateway"===e.service_id&&"skipped"===e.status,title:"android_gateway"===e.service_id&&"skipped"===e.status?tC("单网口无需网关","Not needed on single NIC"):e.available?void 0:e.detail||tC("当前不可操作","Unavailable"),onClick:()=>void tD(e.service_id,"uninstall"),className:"rounded-lg bg-zinc-500/15 px-3 py-1.5 text-xs font-medium text-zinc-200 ring-1 ring-zinc-500/25 disabled:opacity-30",children:"Uninstall"})]})]},e.service_id)),(null==eJ?void 0:null===(eh=eJ.services)||void 0===eh?void 0:eh.length)?null:(0,s.jsx)("p",{className:"text-sm text-zinc-500",children:tC("暂无服务数据","No services")})]}):null,"live_youtube"===eK?(0,s.jsx)(e5,{t:tC,busy:eQ,entries:ts,currentProc:ta,setCurrentProc:to,urlConfig:tc,setUrlConfig:td,onRunProcess:(e,t)=>void tA(e,t),onSaveUrlConfig:(e,t)=>tZ(e,t),fetchJson:tP,liveProcesses:ti.length?ti:null!==(eD=null==eJ?void 0:null===(ep=eJ.live)||void 0===ep?void 0:ep.processes)&&void 0!==eD?eD:[],notify:tR,quickLinks:tU,onNavigate:e=>eF(e)}):null,"live_tiktok"===eK?(0,s.jsx)(ez,{t:tC,busy:!!eQ,entries:ts,currentProc:ta,setCurrentProc:to,urlConfig:tc,setUrlConfig:td,onRunProcess:e=>void tA(e),onSaveUrlConfig:e=>tZ(e),onReplayGoLive:async(e,t)=>{let n=t.replace(/[,,|]/g,"_");await tZ("原画,".concat(e,",主播: ").concat(n)),await tA("start")},onCopy:tB,fetchJson:tP,apiPrefix:eA,quickLinks:tU,hdmiStatus:null==eJ?void 0:eJ.hdmi,notify:tR,onNavigate:e=>eF(e)}):null,"android"===eK?(0,s.jsx)(er,{t:tC,notify:tR,fetchJson:tP,apiBase:eA,busy:eQ,androidSerial:tm,setAndroidSerial:th,devices:(null==eJ?void 0:null===(eb=eJ.android)||void 0===eb?void 0:eb.devices)||[],adbAvailable:!!(null==eJ?void 0:null===(eg=eJ.android)||void 0===eg?void 0:eg.adb_available),apkPath:tx,setApkPath:tu,onAndroidAction:(e,t)=>tO(e,null!=t?t:{}),onCopy:tB,onRefreshDevices:()=>void tL()}):null,"network"===eK?(0,s.jsxs)("div",{className:"mx-auto max-w-7xl space-y-6",children:[(0,s.jsxs)("div",{className:"rounded-2xl border p-6 ".concat("light"===eH?"border-violet-200/90 bg-gradient-to-br from-violet-50 via-white to-fuchsia-50/80":"border-violet-500/25 bg-gradient-to-br from-violet-500/10 via-zinc-950/40 to-fuchsia-500/5"),children:[(0,s.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold ".concat("light"===eH?"text-slate-900":"text-white"),children:[(0,s.jsx)(k.Z,{className:"h-4 w-4 ".concat("light"===eH?"text-violet-600":"text-violet-300")}),tC("ShellCrash 网络面板","ShellCrash panel")]}),(0,s.jsx)("p",{className:"mt-2 text-xs ".concat("light"===eH?"text-slate-600":"text-zinc-400"),children:tC("透明代理与规则分流直接在本页完成,无需跳转;流媒体与其它系统服务请在「服务」页管理。","Proxy rules and YAML editing are embedded here. Use Services for SRS/Neko/Chromium, etc.")}),(0,s.jsx)("div",{className:"mt-6 flex flex-col items-center gap-4 sm:flex-row sm:justify-center",children:[{tx:tC("互联网","Internet"),c:"from-cyan-400 to-blue-500"},{tx:"ShellCrash",c:"from-violet-500 to-fuchsia-500"},{tx:tC("本机 / 安卓","Host / Android"),c:"from-emerald-400 to-teal-500"}].map((e,t)=>(0,s.jsxs)("div",{className:"flex items-center gap-4",children:[(0,s.jsx)("div",{className:"flex h-16 w-28 items-center justify-center rounded-2xl bg-gradient-to-br ".concat(e.c," text-xs font-bold text-white shadow-lg"),children:e.tx}),t<2?(0,s.jsx)(h.Z,{className:"hidden h-5 w-5 sm:block ".concat("light"===eH?"text-slate-400":"text-zinc-600")}):null]},e.tx))})]}),(0,s.jsx)("div",{className:"overflow-hidden rounded-2xl border shadow-xl ".concat("light"===eH?"border-slate-200/90 bg-white shadow-slate-200/40":"border-white/[0.08] bg-zinc-950/50 shadow-black/30"),children:(0,s.jsx)("div",{className:"max-h-[min(78vh,56rem)] min-h-[22rem] overflow-y-auto overflow-x-hidden",children:(0,s.jsx)(P.d,{embeddedShellCrash:!0,portalLang:eZ})})})]}):null,"settings"===eK?(0,s.jsxs)("div",{className:"mx-auto max-w-lg space-y-6",children:[(0,s.jsx)("p",{className:"text-sm ".concat("light"===eH?"text-slate-600":"text-zinc-400"),children:tC("常用选项(本机偏好);完整文件与 JSON 编辑见下方链接。","Local preferences; full file/JSON editor via the link below.")}),(0,s.jsxs)("div",{className:"space-y-4 rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,s.jsxs)("label",{className:"flex cursor-pointer items-center justify-between gap-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-sm font-medium text-white",children:tC("总览自动刷新","Auto-refresh dashboard")}),(0,s.jsx)("p",{className:"text-[11px] text-zinc-500",children:"10s"})]}),(0,s.jsx)("input",{type:"checkbox",className:"h-5 w-5 accent-violet-500",checked:tv,onChange:e=>{let t=e.target.checked;ty(t);try{localStorage.setItem("livehub.autorefresh",t?"1":"0")}catch(e){}tR(t?tC("已开启刷新","Auto refresh on"):tC("已暂停刷新","Paused"))}})]}),(0,s.jsxs)("label",{className:"flex cursor-pointer items-center justify-between gap-4 border-t border-white/[0.06] pt-4",children:[(0,s.jsxs)("div",{children:[(0,s.jsx)("p",{className:"text-sm font-medium text-white",children:tC("总览显示 SRS / Neko 探针","Show SRS/Neko probes")}),(0,s.jsx)("p",{className:"text-[11px] text-zinc-500",children:tC("关闭可精简首页","Hide stream probe cards")})]}),(0,s.jsx)("input",{type:"checkbox",className:"h-5 w-5 accent-violet-500",checked:tw,onChange:e=>{let t=e.target.checked;tN(t);try{localStorage.setItem("livehub.showStreamProbes",t?"1":"0")}catch(e){}}})]})]}),(0,s.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/40 p-5",children:[(0,s.jsx)("p",{className:"text-xs font-semibold uppercase tracking-wider text-zinc-500",children:tC("配置快照","Config snapshot")}),(0,s.jsx)("p",{className:"mt-2 font-mono text-[11px] text-zinc-400",children:String((null==tp?void 0:tp.config_root)||"—")}),(0,s.jsxs)("p",{className:"mt-3 text-sm text-zinc-300",children:[tC("主机名","Hostname"),":"," ",(0,s.jsx)("span",{className:"font-mono text-violet-200",children:(()=>{var e,t,n;let s=null==tp?void 0:tp.system;return(null==s?void 0:null===(t=s.identity)||void 0===t?void 0:null===(e=t.hostname_alias)||void 0===e?void 0:e.trim())||((null==eJ?void 0:null===(n=eJ.stack)||void 0===n?void 0:n.mdns_host)||"").replace(/\.local$/i,"")||"—"})()})]}),(0,s.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:null==tp?void 0:null===(ef=tp.services)||void 0===ef?void 0:ef.slice(0,8).map(e=>(0,s.jsxs)("span",{className:"rounded-full px-2.5 py-1 text-[10px] font-medium ".concat(e.enabled?"bg-emerald-500/15 text-emerald-200 ring-1 ring-emerald-500/25":"bg-zinc-500/15 text-zinc-400"),children:[e.id," ",e.enabled?"ON":"off"]},e.id))})]}),(0,s.jsxs)("a",{href:"/console?tab=config",className:"inline-flex w-full items-center justify-center gap-2 rounded-xl border py-3 text-sm transition ".concat("light"===eH?"border-slate-200 bg-slate-50 text-violet-700 hover:bg-slate-100":"border-white/10 bg-white/[0.05] text-violet-200 hover:bg-white/[0.08]"),children:[tC("完整配置中心(文件 / JSON)","Full config center (files / JSON)"),(0,s.jsx)(z.Z,{className:"h-4 w-4"})]})]}):null]},eK)})})]})]}),(0,s.jsx)(i.M,{children:eW?(0,s.jsx)(l.E.div,{initial:{opacity:0},animate:{opacity:1},exit:{opacity:0},className:"fixed inset-0 z-50 bg-black/60 backdrop-blur-sm lg:hidden",onClick:()=>eY(!1),children:(0,s.jsxs)(l.E.aside,{initial:{x:-280},animate:{x:0},exit:{x:-280},transition:{type:"spring",damping:28,stiffness:320},className:"absolute left-0 top-0 h-full w-[min(88vw,280px)] border-r border-white/10 bg-zinc-950 p-4 shadow-2xl",onClick:e=>e.stopPropagation(),children:[(0,s.jsx)("div",{className:"flex justify-end",children:(0,s.jsx)("button",{type:"button",onClick:()=>eY(!1),className:"rounded-lg p-2",children:(0,s.jsx)(S.Z,{className:"h-5 w-5"})})}),(0,s.jsx)("nav",{className:"mt-4 flex flex-col gap-1",children:tH.map(e=>{let t=e.icon,n=eK===e.id;return(0,s.jsxs)("button",{type:"button",onClick:()=>{eF(e.id),eY(!1)},"aria-current":n?"page":void 0,className:"flex items-center gap-3 rounded-xl px-3 py-3 text-left text-sm transition ".concat(n?"bg-white/[0.08] text-white shadow-inner shadow-white/5":"text-zinc-300 hover:bg-white/[0.04]"),children:[(0,s.jsx)(t,{className:"h-4 w-4 ".concat(n?"text-violet-300":"text-violet-400")}),tC(e.labelZh,e.labelEn)]},e.id)})})]})}):null})]})}}},function(e){e.O(0,[500,719,246,971,117,744],function(){return e(e.s=5052)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/app/shellcrash/page-3d8615ae919b9119.js b/d2ypp2/web-console/out/_next/static/chunks/app/shellcrash/page-3d8615ae919b9119.js deleted file mode 100644 index 724f721..0000000 --- a/d2ypp2/web-console/out/_next/static/chunks/app/shellcrash/page-3d8615ae919b9119.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6],{632:function(n,u,e){Promise.resolve().then(e.bind(e,3398))},3398:function(n,u,e){"use strict";e.r(u),e.d(u,{default:function(){return c}});var t=e(7437),r=e(2246);function c(){return(0,t.jsx)(r.d,{})}}},function(n){n.O(0,[500,246,971,117,744],function(){return n(n.s=632)}),_N_E=n.O()}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/app/shellcrash/page-766863ba520c08ee.js b/d2ypp2/web-console/out/_next/static/chunks/app/shellcrash/page-766863ba520c08ee.js new file mode 100644 index 0000000..1f2faa2 --- /dev/null +++ b/d2ypp2/web-console/out/_next/static/chunks/app/shellcrash/page-766863ba520c08ee.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[6],{7564:function(n,u,e){Promise.resolve().then(e.bind(e,3398))},3398:function(n,u,e){"use strict";e.r(u),e.d(u,{default:function(){return c}});var t=e(7437),r=e(2246);function c(){return(0,t.jsx)(r.d,{})}}},function(n){n.O(0,[500,246,971,117,744],function(){return n(n.s=7564)}),_N_E=n.O()}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/main-app-862a0795add9a1f2.js b/d2ypp2/web-console/out/_next/static/chunks/main-app-5ec094bd229d9247.js similarity index 58% rename from d2ypp2/web-console/out/_next/static/chunks/main-app-862a0795add9a1f2.js rename to d2ypp2/web-console/out/_next/static/chunks/main-app-5ec094bd229d9247.js index 4bdb3f8..9c0c2d2 100644 --- a/d2ypp2/web-console/out/_next/static/chunks/main-app-862a0795add9a1f2.js +++ b/d2ypp2/web-console/out/_next/static/chunks/main-app-5ec094bd229d9247.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{2086:function(e,n,t){Promise.resolve().then(t.t.bind(t,2846,23)),Promise.resolve().then(t.t.bind(t,9107,23)),Promise.resolve().then(t.t.bind(t,1060,23)),Promise.resolve().then(t.t.bind(t,4707,23)),Promise.resolve().then(t.t.bind(t,80,23)),Promise.resolve().then(t.t.bind(t,6423,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,117],function(){return n(4278),n(2086)}),_N_E=e.O()}]); \ No newline at end of file +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[744],{5629:function(e,n,t){Promise.resolve().then(t.t.bind(t,2846,23)),Promise.resolve().then(t.t.bind(t,9107,23)),Promise.resolve().then(t.t.bind(t,1060,23)),Promise.resolve().then(t.t.bind(t,4707,23)),Promise.resolve().then(t.t.bind(t,80,23)),Promise.resolve().then(t.t.bind(t,6423,23))}},function(e){var n=function(n){return e(e.s=n)};e.O(0,[971,117],function(){return n(4278),n(5629)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/chunks/webpack-7691246368419d30.js b/d2ypp2/web-console/out/_next/static/chunks/webpack-8b48d63693aaff80.js similarity index 76% rename from d2ypp2/web-console/out/_next/static/chunks/webpack-7691246368419d30.js rename to d2ypp2/web-console/out/_next/static/chunks/webpack-8b48d63693aaff80.js index 4291edf..9e5a274 100644 --- a/d2ypp2/web-console/out/_next/static/chunks/webpack-7691246368419d30.js +++ b/d2ypp2/web-console/out/_next/static/chunks/webpack-8b48d63693aaff80.js @@ -1 +1 @@ -!function(){"use strict";var e,t,n,r,o,u,i,c,f,a={},l={};function s(e){var t=l[e];if(void 0!==t)return t.exports;var n=l[e]={exports:{}},r=!0;try{a[e](n,n.exports,s),r=!1}finally{r&&delete l[e]}return n.exports}s.m=a,e=[],s.O=function(t,n,r,o){if(n){o=o||0;for(var u=e.length;u>0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[n,r,o];return}for(var i=1/0,u=0;u=o&&Object.keys(s.O).every(function(e){return s.O[e](n[f])})?n.splice(f--,1):(c=!1,o0&&e[u-1][2]>o;u--)e[u]=e[u-1];e[u]=[n,r,o];return}for(var i=1/0,u=0;u=o&&Object.keys(s.O).every(function(e){return s.O[e](n[f])})?n.splice(f--,1):(c=!1,o:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.625rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-3xl{border-radius:1.5rem}.rounded-\[1\.35rem\]{border-radius:1.35rem}.rounded-\[2rem\]{border-radius:2rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.border{border-width:1px}.border-\[10px\]{border-width:10px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-400\/50{border-color:rgba(251,191,36,.5)}.border-amber-500\/15{border-color:rgba(245,158,11,.15)}.border-amber-500\/20{border-color:rgba(245,158,11,.2)}.border-amber-500\/25{border-color:rgba(245,158,11,.25)}.border-amber-500\/30{border-color:rgba(245,158,11,.3)}.border-cyan-400\/35{border-color:rgba(34,211,238,.35)}.border-cyan-400\/50{border-color:rgba(34,211,238,.5)}.border-cyan-500\/15{border-color:rgba(6,182,212,.15)}.border-cyan-500\/20{border-color:rgba(6,182,212,.2)}.border-cyan-500\/25{border-color:rgba(6,182,212,.25)}.border-cyan-500\/30{border-color:rgba(6,182,212,.3)}.border-cyan-500\/40{border-color:rgba(6,182,212,.4)}.border-cyan-500\/50{border-color:rgba(6,182,212,.5)}.border-emerald-400\/30{border-color:rgba(52,211,153,.3)}.border-emerald-500\/15{border-color:rgba(16,185,129,.15)}.border-emerald-500\/20{border-color:rgba(16,185,129,.2)}.border-emerald-500\/25{border-color:rgba(16,185,129,.25)}.border-emerald-500\/30{border-color:rgba(16,185,129,.3)}.border-emerald-500\/50{border-color:rgba(16,185,129,.5)}.border-fuchsia-200\/80{border-color:rgba(245,208,254,.8)}.border-fuchsia-400\/20{border-color:rgba(232,121,249,.2)}.border-fuchsia-500\/20{border-color:rgba(217,70,239,.2)}.border-fuchsia-500\/25{border-color:rgba(217,70,239,.25)}.border-fuchsia-500\/30{border-color:rgba(217,70,239,.3)}.border-indigo-400\/50{border-color:rgba(129,140,248,.5)}.border-indigo-500\/25{border-color:rgba(99,102,241,.25)}.border-rose-500\/15{border-color:rgba(244,63,94,.15)}.border-rose-500\/20{border-color:rgba(244,63,94,.2)}.border-rose-500\/25{border-color:rgba(244,63,94,.25)}.border-rose-500\/30{border-color:rgba(244,63,94,.3)}.border-sky-500\/20{border-color:rgba(14,165,233,.2)}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-slate-200\/80{border-color:rgba(226,232,240,.8)}.border-slate-200\/90{border-color:rgba(226,232,240,.9)}.border-slate-500\/30{border-color:rgba(100,116,139,.3)}.border-slate-700\/30{border-color:rgba(51,65,85,.3)}.border-violet-200\/90{border-color:rgba(221,214,254,.9)}.border-violet-400\/35{border-color:rgba(167,139,250,.35)}.border-violet-500\/15{border-color:rgba(139,92,246,.15)}.border-violet-500\/20{border-color:rgba(139,92,246,.2)}.border-violet-500\/25{border-color:rgba(139,92,246,.25)}.border-violet-500\/30{border-color:rgba(139,92,246,.3)}.border-violet-500\/35{border-color:rgba(139,92,246,.35)}.border-violet-500\/45{border-color:rgba(139,92,246,.45)}.border-violet-500\/50{border-color:rgba(139,92,246,.5)}.border-white\/10{border-color:hsla(0,0%,100%,.1)}.border-white\/15{border-color:hsla(0,0%,100%,.15)}.border-white\/20{border-color:hsla(0,0%,100%,.2)}.border-white\/5{border-color:hsla(0,0%,100%,.05)}.border-white\/\[0\.04\]{border-color:hsla(0,0%,100%,.04)}.border-white\/\[0\.05\]{border-color:hsla(0,0%,100%,.05)}.border-white\/\[0\.06\]{border-color:hsla(0,0%,100%,.06)}.border-white\/\[0\.07\]{border-color:hsla(0,0%,100%,.07)}.border-white\/\[0\.08\]{border-color:hsla(0,0%,100%,.08)}.border-zinc-800{--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.bg-\[\#050508\]{--tw-bg-opacity:1;background-color:rgb(5 5 8/var(--tw-bg-opacity,1))}.bg-amber-500\/10{background-color:rgba(245,158,11,.1)}.bg-amber-500\/15{background-color:rgba(245,158,11,.15)}.bg-amber-500\/20{background-color:rgba(245,158,11,.2)}.bg-amber-500\/5{background-color:rgba(245,158,11,.05)}.bg-amber-500\/\[0\.06\]{background-color:rgba(245,158,11,.06)}.bg-amber-600{--tw-bg-opacity:1;background-color:rgb(217 119 6/var(--tw-bg-opacity,1))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-black\/15{background-color:rgba(0,0,0,.15)}.bg-black\/20{background-color:rgba(0,0,0,.2)}.bg-black\/25{background-color:rgba(0,0,0,.25)}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/35{background-color:rgba(0,0,0,.35)}.bg-black\/40{background-color:rgba(0,0,0,.4)}.bg-black\/45{background-color:rgba(0,0,0,.45)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/55{background-color:rgba(0,0,0,.55)}.bg-black\/60{background-color:rgba(0,0,0,.6)}.bg-black\/75{background-color:rgba(0,0,0,.75)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-cyan-100{--tw-bg-opacity:1;background-color:rgb(207 250 254/var(--tw-bg-opacity,1))}.bg-cyan-400\/10{background-color:rgba(34,211,238,.1)}.bg-cyan-500\/10{background-color:rgba(6,182,212,.1)}.bg-cyan-500\/15{background-color:rgba(6,182,212,.15)}.bg-cyan-500\/20{background-color:rgba(6,182,212,.2)}.bg-cyan-500\/30{background-color:rgba(6,182,212,.3)}.bg-cyan-500\/90{background-color:rgba(6,182,212,.9)}.bg-cyan-500\/\[0\.05\]{background-color:rgba(6,182,212,.05)}.bg-cyan-500\/\[0\.06\]{background-color:rgba(6,182,212,.06)}.bg-cyan-600{--tw-bg-opacity:1;background-color:rgb(8 145 178/var(--tw-bg-opacity,1))}.bg-cyan-600\/80{background-color:rgba(8,145,178,.8)}.bg-emerald-500\/10{background-color:rgba(16,185,129,.1)}.bg-emerald-500\/15{background-color:rgba(16,185,129,.15)}.bg-emerald-500\/20{background-color:rgba(16,185,129,.2)}.bg-emerald-500\/90{background-color:rgba(16,185,129,.9)}.bg-emerald-600{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.bg-fuchsia-500\/10{background-color:rgba(217,70,239,.1)}.bg-fuchsia-500\/20{background-color:rgba(217,70,239,.2)}.bg-indigo-500\/15{background-color:rgba(99,102,241,.15)}.bg-rose-500\/10{background-color:rgba(244,63,94,.1)}.bg-rose-500\/15{background-color:rgba(244,63,94,.15)}.bg-rose-600{--tw-bg-opacity:1;background-color:rgb(225 29 72/var(--tw-bg-opacity,1))}.bg-rose-950\/20{background-color:rgba(76,5,25,.2)}.bg-rose-950\/25{background-color:rgba(76,5,25,.25)}.bg-sky-500\/15{background-color:rgba(14,165,233,.15)}.bg-sky-500\/25{background-color:rgba(14,165,233,.25)}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.bg-slate-500\/10{background-color:rgba(100,116,139,.1)}.bg-slate-500\/15{background-color:rgba(100,116,139,.15)}.bg-slate-800\/50{background-color:rgba(30,41,59,.5)}.bg-slate-950\/30{background-color:rgba(2,6,23,.3)}.bg-slate-950\/50{background-color:rgba(2,6,23,.5)}.bg-slate-950\/60{background-color:rgba(2,6,23,.6)}.bg-slate-950\/80{background-color:rgba(2,6,23,.8)}.bg-slate-950\/95{background-color:rgba(2,6,23,.95)}.bg-violet-100{--tw-bg-opacity:1;background-color:rgb(237 233 254/var(--tw-bg-opacity,1))}.bg-violet-100\/90{background-color:rgba(237,233,254,.9)}.bg-violet-400\/15{background-color:rgba(167,139,250,.15)}.bg-violet-500\/10{background-color:rgba(139,92,246,.1)}.bg-violet-500\/15{background-color:rgba(139,92,246,.15)}.bg-violet-500\/20{background-color:rgba(139,92,246,.2)}.bg-violet-500\/25{background-color:rgba(139,92,246,.25)}.bg-violet-500\/\[0\.06\]{background-color:rgba(139,92,246,.06)}.bg-violet-500\/\[0\.1\]{background-color:rgba(139,92,246,.1)}.bg-violet-600{--tw-bg-opacity:1;background-color:rgb(124 58 237/var(--tw-bg-opacity,1))}.bg-violet-600\/20{background-color:rgba(124,58,237,.2)}.bg-violet-600\/70{background-color:rgba(124,58,237,.7)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/10{background-color:hsla(0,0%,100%,.1)}.bg-white\/5{background-color:hsla(0,0%,100%,.05)}.bg-white\/70{background-color:hsla(0,0%,100%,.7)}.bg-white\/75{background-color:hsla(0,0%,100%,.75)}.bg-white\/80{background-color:hsla(0,0%,100%,.8)}.bg-white\/90{background-color:hsla(0,0%,100%,.9)}.bg-white\/\[0\.04\]{background-color:hsla(0,0%,100%,.04)}.bg-white\/\[0\.05\]{background-color:hsla(0,0%,100%,.05)}.bg-white\/\[0\.06\]{background-color:hsla(0,0%,100%,.06)}.bg-white\/\[0\.08\]{background-color:hsla(0,0%,100%,.08)}.bg-zinc-500\/15{background-color:hsla(240,4%,46%,.15)}.bg-zinc-600\/20{background-color:rgba(82,82,91,.2)}.bg-zinc-600\/30{background-color:rgba(82,82,91,.3)}.bg-zinc-700\/40{background-color:rgba(63,63,70,.4)}.bg-zinc-700\/90{background-color:rgba(63,63,70,.9)}.bg-zinc-950{--tw-bg-opacity:1;background-color:rgb(9 9 11/var(--tw-bg-opacity,1))}.bg-zinc-950\/30{background-color:rgba(9,9,11,.3)}.bg-zinc-950\/40{background-color:rgba(9,9,11,.4)}.bg-zinc-950\/50{background-color:rgba(9,9,11,.5)}.bg-zinc-950\/60{background-color:rgba(9,9,11,.6)}.bg-zinc-950\/70{background-color:rgba(9,9,11,.7)}.bg-zinc-950\/80{background-color:rgba(9,9,11,.8)}.bg-zinc-950\/95{background-color:rgba(9,9,11,.95)}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-amber-400{--tw-gradient-from:#fbbf24 var(--tw-gradient-from-position);--tw-gradient-to:rgba(251,191,36,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-50\/90{--tw-gradient-from:rgba(255,251,235,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(255,251,235,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-500\/35{--tw-gradient-from:rgba(245,158,11,.35) var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,158,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-500\/\[0\.07\]{--tw-gradient-from:rgba(245,158,11,.07) var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,158,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-500\/\[0\.12\]{--tw-gradient-from:rgba(245,158,11,.12) var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,158,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-500\/\[0\.1\]{--tw-gradient-from:rgba(245,158,11,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,158,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-400{--tw-gradient-from:#22d3ee var(--tw-gradient-from-position);--tw-gradient-to:rgba(34,211,238,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/35{--tw-gradient-from:rgba(6,182,212,.35) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/\[0\.07\]{--tw-gradient-from:rgba(6,182,212,.07) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/\[0\.08\]{--tw-gradient-from:rgba(6,182,212,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/\[0\.14\]{--tw-gradient-from:rgba(6,182,212,.14) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/\[0\.1\]{--tw-gradient-from:rgba(6,182,212,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-400{--tw-gradient-from:#34d399 var(--tw-gradient-from-position);--tw-gradient-to:rgba(52,211,153,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-400\/30{--tw-gradient-from:rgba(52,211,153,.3) var(--tw-gradient-from-position);--tw-gradient-to:rgba(52,211,153,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-500\/\[0\.07\]{--tw-gradient-from:rgba(16,185,129,.07) var(--tw-gradient-from-position);--tw-gradient-to:rgba(16,185,129,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-500\/\[0\.08\]{--tw-gradient-from:rgba(16,185,129,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(16,185,129,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-500\/\[0\.12\]{--tw-gradient-from:rgba(16,185,129,.12) var(--tw-gradient-from-position);--tw-gradient-to:rgba(16,185,129,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-fuchsia-50\/90{--tw-gradient-from:rgba(253,244,255,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(253,244,255,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-fuchsia-500\/10{--tw-gradient-from:rgba(217,70,239,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(217,70,239,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-fuchsia-500\/\[0\.08\]{--tw-gradient-from:rgba(217,70,239,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(217,70,239,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-fuchsia-950\/40{--tw-gradient-from:rgba(74,4,78,.4) var(--tw-gradient-from-position);--tw-gradient-to:rgba(74,4,78,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-indigo-500\/\[0\.1\]{--tw-gradient-from:rgba(99,102,241,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(99,102,241,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-pink-500\/25{--tw-gradient-from:rgba(236,72,153,.25) var(--tw-gradient-from-position);--tw-gradient-to:rgba(236,72,153,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-red-500\/30{--tw-gradient-from:rgba(239,68,68,.3) var(--tw-gradient-from-position);--tw-gradient-to:rgba(239,68,68,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-sky-500\/\[0\.08\]{--tw-gradient-from:rgba(14,165,233,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(14,165,233,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-50{--tw-gradient-from:#f5f3ff var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,243,255,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500{--tw-gradient-from:#8b5cf6 var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500\/10{--tw-gradient-from:rgba(139,92,246,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500\/30{--tw-gradient-from:rgba(139,92,246,.3) var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500\/\[0\.08\]{--tw-gradient-from:rgba(139,92,246,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500\/\[0\.12\]{--tw-gradient-from:rgba(139,92,246,.12) var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-white\/\[0\.05\]{--tw-gradient-from:hsla(0,0%,100%,.05) var(--tw-gradient-from-position);--tw-gradient-to:hsla(0,0%,100%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-black\/25{--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(0,0,0,.25) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-white{--tw-gradient-to:hsla(0,0%,100%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#fff var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/40{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.4) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/50{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.5) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/55{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.55) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/60{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.6) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/70{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.7) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/80{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.8) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/90{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.9) var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-black\/40{--tw-gradient-to:rgba(0,0,0,.4) var(--tw-gradient-to-position)}.to-blue-500{--tw-gradient-to:#3b82f6 var(--tw-gradient-to-position)}.to-cyan-400{--tw-gradient-to:#22d3ee var(--tw-gradient-to-position)}.to-cyan-50\/70{--tw-gradient-to:rgba(236,254,255,.7) var(--tw-gradient-to-position)}.to-cyan-500\/10{--tw-gradient-to:rgba(6,182,212,.1) var(--tw-gradient-to-position)}.to-cyan-500\/5,.to-cyan-500\/\[0\.05\]{--tw-gradient-to:rgba(6,182,212,.05) var(--tw-gradient-to-position)}.to-cyan-950\/20{--tw-gradient-to:rgba(8,51,68,.2) var(--tw-gradient-to-position)}.to-fuchsia-50\/80{--tw-gradient-to:rgba(253,244,255,.8) var(--tw-gradient-to-position)}.to-fuchsia-500{--tw-gradient-to:#d946ef var(--tw-gradient-to-position)}.to-fuchsia-500\/10{--tw-gradient-to:rgba(217,70,239,.1) var(--tw-gradient-to-position)}.to-fuchsia-500\/20{--tw-gradient-to:rgba(217,70,239,.2) var(--tw-gradient-to-position)}.to-fuchsia-500\/5{--tw-gradient-to:rgba(217,70,239,.05) var(--tw-gradient-to-position)}.to-fuchsia-500\/\[0\.06\]{--tw-gradient-to:rgba(217,70,239,.06) var(--tw-gradient-to-position)}.to-fuchsia-600\/25{--tw-gradient-to:rgba(192,38,211,.25) var(--tw-gradient-to-position)}.to-orange-500{--tw-gradient-to:#f97316 var(--tw-gradient-to-position)}.to-rose-500\/\[0\.05\]{--tw-gradient-to:rgba(244,63,94,.05) var(--tw-gradient-to-position)}.to-slate-50{--tw-gradient-to:#f8fafc var(--tw-gradient-to-position)}.to-teal-500{--tw-gradient-to:#14b8a6 var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.to-violet-500\/10{--tw-gradient-to:rgba(139,92,246,.1) var(--tw-gradient-to-position)}.to-violet-500\/25{--tw-gradient-to:rgba(139,92,246,.25) var(--tw-gradient-to-position)}.to-violet-500\/\[0\.06\]{--tw-gradient-to:rgba(139,92,246,.06) var(--tw-gradient-to-position)}.to-violet-500\/\[0\.08\]{--tw-gradient-to:rgba(139,92,246,.08) var(--tw-gradient-to-position)}.to-violet-600\/25{--tw-gradient-to:rgba(124,58,237,.25) var(--tw-gradient-to-position)}.to-violet-600\/30{--tw-gradient-to:rgba(124,58,237,.3) var(--tw-gradient-to-position)}.to-zinc-900\/90{--tw-gradient-to:rgba(24,24,27,.9) var(--tw-gradient-to-position)}.to-zinc-950\/80{--tw-gradient-to:rgba(9,9,11,.8) var(--tw-gradient-to-position)}.object-contain{object-fit:contain}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-24{padding-top:6rem;padding-bottom:6rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-1{padding-bottom:.25rem}.pb-16{padding-bottom:4rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-5{padding-left:1.25rem}.pr-1{padding-right:.25rem}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-\[0\.08em\]{letter-spacing:.08em}.tracking-\[0\.22em\]{letter-spacing:.22em}.tracking-\[0\.2em\]{letter-spacing:.2em}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-\[color\:var\(--text\)\]{color:var(--text)}.text-amber-100{--tw-text-opacity:1;color:rgb(254 243 199/var(--tw-text-opacity,1))}.text-amber-200{--tw-text-opacity:1;color:rgb(253 230 138/var(--tw-text-opacity,1))}.text-amber-200\/80{color:hsla(48,97%,77%,.8)}.text-amber-200\/85{color:hsla(48,97%,77%,.85)}.text-amber-200\/90{color:hsla(48,97%,77%,.9)}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-amber-400\/95{color:rgba(251,191,36,.95)}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-amber-800{--tw-text-opacity:1;color:rgb(146 64 14/var(--tw-text-opacity,1))}.text-cyan-100{--tw-text-opacity:1;color:rgb(207 250 254/var(--tw-text-opacity,1))}.text-cyan-100\/90{color:rgba(207,250,254,.9)}.text-cyan-200{--tw-text-opacity:1;color:rgb(165 243 252/var(--tw-text-opacity,1))}.text-cyan-200\/90{color:rgba(165,243,252,.9)}.text-cyan-300{--tw-text-opacity:1;color:rgb(103 232 249/var(--tw-text-opacity,1))}.text-cyan-300\/70{color:rgba(103,232,249,.7)}.text-cyan-300\/80{color:rgba(103,232,249,.8)}.text-cyan-300\/90{color:rgba(103,232,249,.9)}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-cyan-400\/90{color:rgba(34,211,238,.9)}.text-cyan-50{--tw-text-opacity:1;color:rgb(236 254 255/var(--tw-text-opacity,1))}.text-cyan-600{--tw-text-opacity:1;color:rgb(8 145 178/var(--tw-text-opacity,1))}.text-cyan-800{--tw-text-opacity:1;color:rgb(21 94 117/var(--tw-text-opacity,1))}.text-cyan-950{--tw-text-opacity:1;color:rgb(8 51 68/var(--tw-text-opacity,1))}.text-emerald-100{--tw-text-opacity:1;color:rgb(209 250 229/var(--tw-text-opacity,1))}.text-emerald-100\/95{color:rgba(209,250,229,.95)}.text-emerald-200{--tw-text-opacity:1;color:rgb(167 243 208/var(--tw-text-opacity,1))}.text-emerald-200\/90{color:rgba(167,243,208,.9)}.text-emerald-300{--tw-text-opacity:1;color:rgb(110 231 183/var(--tw-text-opacity,1))}.text-emerald-300\/90{color:rgba(110,231,183,.9)}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-emerald-400\/80{color:rgba(52,211,153,.8)}.text-emerald-400\/90{color:rgba(52,211,153,.9)}.text-emerald-50{--tw-text-opacity:1;color:rgb(236 253 245/var(--tw-text-opacity,1))}.text-emerald-950{--tw-text-opacity:1;color:rgb(2 44 34/var(--tw-text-opacity,1))}.text-fuchsia-100{--tw-text-opacity:1;color:rgb(250 232 255/var(--tw-text-opacity,1))}.text-fuchsia-200{--tw-text-opacity:1;color:rgb(245 208 254/var(--tw-text-opacity,1))}.text-fuchsia-200\/80{color:rgba(245,208,254,.8)}.text-fuchsia-300\/90{color:rgba(240,171,252,.9)}.text-fuchsia-400{--tw-text-opacity:1;color:rgb(232 121 249/var(--tw-text-opacity,1))}.text-indigo-200{--tw-text-opacity:1;color:rgb(199 210 254/var(--tw-text-opacity,1))}.text-indigo-300\/90{color:rgba(165,180,252,.9)}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity,1))}.text-rose-100{--tw-text-opacity:1;color:rgb(255 228 230/var(--tw-text-opacity,1))}.text-rose-100\/95{color:rgba(255,228,230,.95)}.text-rose-200{--tw-text-opacity:1;color:rgb(254 205 211/var(--tw-text-opacity,1))}.text-rose-300{--tw-text-opacity:1;color:rgb(253 164 175/var(--tw-text-opacity,1))}.text-rose-400\/90{color:rgba(251,113,133,.9)}.text-sky-100{--tw-text-opacity:1;color:rgb(224 242 254/var(--tw-text-opacity,1))}.text-sky-200{--tw-text-opacity:1;color:rgb(186 230 253/var(--tw-text-opacity,1))}.text-sky-400{--tw-text-opacity:1;color:rgb(56 189 248/var(--tw-text-opacity,1))}.text-slate-100{--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity,1))}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-300\/90{color:rgba(203,213,225,.9)}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity,1))}.text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.text-violet-100{--tw-text-opacity:1;color:rgb(237 233 254/var(--tw-text-opacity,1))}.text-violet-200{--tw-text-opacity:1;color:rgb(221 214 254/var(--tw-text-opacity,1))}.text-violet-300{--tw-text-opacity:1;color:rgb(196 181 253/var(--tw-text-opacity,1))}.text-violet-300\/80{color:rgba(196,181,253,.8)}.text-violet-300\/90{color:rgba(196,181,253,.9)}.text-violet-400{--tw-text-opacity:1;color:rgb(167 139 250/var(--tw-text-opacity,1))}.text-violet-400\/90{color:rgba(167,139,250,.9)}.text-violet-600{--tw-text-opacity:1;color:rgb(124 58 237/var(--tw-text-opacity,1))}.text-violet-700{--tw-text-opacity:1;color:rgb(109 40 217/var(--tw-text-opacity,1))}.text-violet-800{--tw-text-opacity:1;color:rgb(91 33 182/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/80{color:hsla(0,0%,100%,.8)}.text-zinc-100{--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.text-zinc-200{--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.text-zinc-300{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.text-zinc-500{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.accent-violet-500{accent-color:#8b5cf6}.opacity-35{opacity:.35}.opacity-40{opacity:.4}.opacity-45{opacity:.45}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.opacity-\[0\.06\]{opacity:.06}.opacity-\[0\.22\]{opacity:.22}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-black\/20{--tw-shadow-color:rgba(0,0,0,.2);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/30{--tw-shadow-color:rgba(0,0,0,.3);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/50{--tw-shadow-color:rgba(0,0,0,.5);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/80{--tw-shadow-color:rgba(0,0,0,.8);--tw-shadow:var(--tw-shadow-colored)}.shadow-cyan-900\/10{--tw-shadow-color:rgba(22,78,99,.1);--tw-shadow:var(--tw-shadow-colored)}.shadow-emerald-900\/20{--tw-shadow-color:rgba(6,78,59,.2);--tw-shadow:var(--tw-shadow-colored)}.shadow-fuchsia-100\/40{--tw-shadow-color:rgba(250,232,255,.4);--tw-shadow:var(--tw-shadow-colored)}.shadow-fuchsia-900\/10{--tw-shadow-color:rgba(112,26,117,.1);--tw-shadow:var(--tw-shadow-colored)}.shadow-indigo-500\/5{--tw-shadow-color:rgba(99,102,241,.05);--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-200\/30{--tw-shadow-color:rgba(226,232,240,.3);--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-200\/40{--tw-shadow-color:rgba(226,232,240,.4);--tw-shadow:var(--tw-shadow-colored)}.shadow-violet-200\/50{--tw-shadow-color:rgba(221,214,254,.5);--tw-shadow:var(--tw-shadow-colored)}.shadow-violet-500\/25{--tw-shadow-color:rgba(139,92,246,.25);--tw-shadow:var(--tw-shadow-colored)}.shadow-violet-500\/5{--tw-shadow-color:rgba(139,92,246,.05);--tw-shadow:var(--tw-shadow-colored)}.shadow-violet-900\/10{--tw-shadow-color:rgba(76,29,149,.1);--tw-shadow:var(--tw-shadow-colored)}.shadow-white\/5{--tw-shadow-color:hsla(0,0%,100%,.05);--tw-shadow:var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-amber-500\/25{--tw-ring-color:rgba(245,158,11,.25)}.ring-amber-500\/30{--tw-ring-color:rgba(245,158,11,.3)}.ring-amber-500\/35{--tw-ring-color:rgba(245,158,11,.35)}.ring-cyan-400\/35{--tw-ring-color:rgba(34,211,238,.35)}.ring-cyan-500\/20{--tw-ring-color:rgba(6,182,212,.2)}.ring-cyan-500\/25{--tw-ring-color:rgba(6,182,212,.25)}.ring-cyan-500\/30{--tw-ring-color:rgba(6,182,212,.3)}.ring-cyan-500\/35{--tw-ring-color:rgba(6,182,212,.35)}.ring-emerald-400\/25{--tw-ring-color:rgba(52,211,153,.25)}.ring-emerald-400\/30{--tw-ring-color:rgba(52,211,153,.3)}.ring-emerald-500\/20{--tw-ring-color:rgba(16,185,129,.2)}.ring-emerald-500\/25{--tw-ring-color:rgba(16,185,129,.25)}.ring-emerald-500\/30{--tw-ring-color:rgba(16,185,129,.3)}.ring-fuchsia-400\/20{--tw-ring-color:rgba(232,121,249,.2)}.ring-fuchsia-500\/35{--tw-ring-color:rgba(217,70,239,.35)}.ring-indigo-500\/25{--tw-ring-color:rgba(99,102,241,.25)}.ring-rose-500\/25{--tw-ring-color:rgba(244,63,94,.25)}.ring-rose-500\/35{--tw-ring-color:rgba(244,63,94,.35)}.ring-sky-400\/40{--tw-ring-color:rgba(56,189,248,.4)}.ring-sky-500\/25{--tw-ring-color:rgba(14,165,233,.25)}.ring-slate-500\/30{--tw-ring-color:rgba(100,116,139,.3)}.ring-violet-400\/35{--tw-ring-color:rgba(167,139,250,.35)}.ring-violet-400\/40{--tw-ring-color:rgba(167,139,250,.4)}.ring-violet-500\/20{--tw-ring-color:rgba(139,92,246,.2)}.ring-violet-500\/25{--tw-ring-color:rgba(139,92,246,.25)}.ring-violet-500\/30{--tw-ring-color:rgba(139,92,246,.3)}.ring-violet-500\/35{--tw-ring-color:rgba(139,92,246,.35)}.ring-white\/10{--tw-ring-color:hsla(0,0%,100%,.1)}.ring-white\/\[0\.04\]{--tw-ring-color:hsla(0,0%,100%,.04)}.ring-white\/\[0\.05\]{--tw-ring-color:hsla(0,0%,100%,.05)}.ring-white\/\[0\.06\]{--tw-ring-color:hsla(0,0%,100%,.06)}.ring-zinc-500\/25{--tw-ring-color:hsla(240,4%,46%,.25)}.blur-3xl{--tw-blur:blur(64px)}.blur-3xl,.blur-\[100px\]{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-\[100px\]{--tw-blur:blur(100px)}.blur-\[120px\]{--tw-blur:blur(120px)}.blur-\[120px\],.blur-xl{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-xl{--tw-blur:blur(24px)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-2xl{--tw-backdrop-blur:blur(40px)}.backdrop-blur-2xl,.backdrop-blur-\[2px\]{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-\[2px\]{--tw-backdrop-blur:blur(2px)}.backdrop-blur-lg{--tw-backdrop-blur:blur(16px)}.backdrop-blur-lg,.backdrop-blur-md{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-blur-sm,.backdrop-blur-xl{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-xl{--tw-backdrop-blur:blur(24px)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.glass{border-width:1px;border-color:hsla(0,0%,100%,.08);--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-shadow-color:rgba(0,0,0,.4);--tw-shadow:var(--tw-shadow-colored);background:var(--bg-card);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);transition:border-color .25s ease,box-shadow .25s ease,background .25s ease}html[data-theme=light] .glass{border-color:rgba(226,232,240,.9);--tw-shadow-color:rgba(148,163,184,.15);--tw-shadow:var(--tw-shadow-colored)}.section-title{font-size:1.125rem;line-height:1.75rem;font-weight:600;letter-spacing:-.025em;color:var(--text)}.section-lead{margin-top:.5rem}.meta-chip,.section-lead{font-size:.75rem;line-height:1rem;line-height:1.625;color:var(--muted)}.meta-chip{border-radius:1rem;border-width:1px;padding:.75rem 1rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;border-color:hsla(0,0%,100%,.1);background:rgba(0,0,0,.22)}html[data-theme=light] .meta-chip{border-color:rgba(226,232,240,.95);background:hsla(0,0%,100%,.72);color:var(--muted)}.tab-strip{margin-left:-.25rem;margin-right:-.25rem;display:flex;gap:.5rem;overflow-x:auto;padding-bottom:.375rem;padding-top:.125rem}@media (min-width:768px){.tab-strip{flex-wrap:wrap;overflow:visible}}.tab-strip{scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch}.tab-btn{flex-shrink:0;scroll-snap-align:start;border-radius:1rem;border-width:1px;padding:.625rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.tab-btn:focus-visible{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(34,211,238,.5);--tw-ring-offset-width:2px}.tab-btn{--tw-ring-offset-color:var(--ring-offset);border-color:hsla(0,0%,100%,.12);background:rgba(0,0,0,.22);color:#cbd5e1}.tab-btn:hover{border-color:rgba(34,211,238,.25);color:#e2e8f0}.tab-btn-active{border-color:rgba(34,211,238,.45)!important;background:rgba(34,211,238,.12)!important;color:#cffafe!important}html[data-theme=light] .tab-btn{border-color:#e2e8f0;background:hsla(0,0%,100%,.75);color:#475569}html[data-theme=light] .tab-btn:hover{border-color:rgba(6,182,212,.45);color:#0f766e}html[data-theme=light] .tab-btn-active{border-color:rgba(6,182,212,.55)!important;background:rgba(207,250,254,.55)!important;color:#0e7490!important}.link-tile{display:block;border-radius:1rem;border-width:1px;padding:.625rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.link-tile:focus-visible{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(34,211,238,.5);--tw-ring-offset-width:2px}.link-tile{--tw-ring-offset-color:var(--ring-offset);border-color:hsla(0,0%,100%,.1);background:rgba(0,0,0,.2);color:#f1f5f9}.link-tile:hover{border-color:rgba(34,211,238,.35)}html[data-theme=light] .link-tile{border-color:#e2e8f0;background:hsla(0,0%,100%,.65);color:#1e293b}.link-tile-accent{border-color:rgba(34,211,238,.28);background:rgba(34,211,238,.1);color:#ecfeff}.link-tile-accent:hover{border-color:rgba(34,211,238,.55)}html[data-theme=light] .link-tile-accent{border-color:rgba(6,182,212,.35);background:rgba(207,250,254,.65);color:#0e7490}.link-tile-warn{border-color:rgba(251,191,36,.25);background:rgba(251,191,36,.1);color:#fefce8}html[data-theme=light] .link-tile-warn{border-color:rgba(251,191,36,.45);background:hsla(55,92%,95%,.9);color:#78350f}.service-card{border-radius:1.5rem;border-width:1px;padding:1.25rem;transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;border-color:hsla(0,0%,100%,.08);background:rgba(0,0,0,.2)}.service-card:hover{box-shadow:0 12px 40px -24px rgba(34,211,238,.35)}html[data-theme=light] .service-card{border-color:rgba(226,232,240,.95);background:hsla(0,0%,100%,.55)}.panel-inset{border-radius:1rem;border-width:1px;padding:1rem;font-size:.875rem;line-height:1.25rem;border-color:hsla(0,0%,100%,.08);background:rgba(0,0,0,.2);color:#cbd5e1}html[data-theme=light] .panel-inset{border-color:rgba(226,232,240,.85);background:hsla(0,0%,100%,.5);color:#334155}.field-select{width:100%;border-radius:1rem;border-width:1px;padding:.75rem 1rem;font-size:.875rem;line-height:1.25rem;outline:2px solid transparent;outline-offset:2px;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;border-color:hsla(0,0%,100%,.12);background:rgba(2,6,23,.55);color:#f8fafc}html[data-theme=light] .field-select{border-color:#e2e8f0;background:hsla(0,0%,100%,.9);color:#0f172a}.btn-focus:focus-visible{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(34,211,238,.5);--tw-ring-offset-width:2px}.btn-focus{--tw-ring-offset-color:var(--ring-offset)}.\[-ms-overflow-style\:none\]{-ms-overflow-style:none}.\[scrollbar-width\:none\]{scrollbar-width:none}:root{--bg-deep:#060912;--bg-card:rgba(16,22,36,.78);--accent:#22d3ee;--accent2:#a78bfa;--danger:#f43f5e;--ok:#34d399;--text:#e8edf7;--muted:#94a3b8;--ring-offset:#060912;color-scheme:dark}html[data-theme=light]{--bg-deep:#f1f5f9;--bg-card:hsla(0,0%,100%,.88);--text:#0f172a;--muted:#64748b;--ring-offset:#f1f5f9;color-scheme:light}html{scroll-behavior:smooth}body{color:var(--text);background:var(--bg-deep);min-height:100vh;font-family:var(--font-geist-sans),system-ui,sans-serif;overflow-x:hidden;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;transition:background-color .35s ease,color .25s ease}*{scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.35) transparent}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:rgba(148,163,184,.35);border-radius:999px}::-webkit-scrollbar-track{background:transparent}.app-bg-layer{position:fixed;inset:0;z-index:-1;opacity:.92;pointer-events:none;background:radial-gradient(ellipse 80% 50% at 50% -20%,rgba(34,211,238,.22),transparent),radial-gradient(ellipse 60% 40% at 100% 0,rgba(167,139,250,.18),transparent),radial-gradient(ellipse 50% 30% at 0 100%,rgba(59,130,246,.12),transparent);transition:opacity .35s ease}html[data-theme=light] .app-bg-layer{opacity:.75;background:radial-gradient(ellipse 80% 50% at 50% -20%,rgba(14,165,233,.12),transparent),radial-gradient(ellipse 60% 40% at 100% 0,rgba(139,92,246,.1),transparent),radial-gradient(ellipse 50% 30% at 0 100%,rgba(59,130,246,.08),transparent)}html[data-theme=light] .chart-surface{border-color:rgba(15,23,42,.12)!important;background:hsla(0,0%,100%,.65)!important}::selection{background:rgba(34,211,238,.25)}.safe-pb-nav{padding-bottom:calc(5.5rem + env(safe-area-inset-bottom, 0px))}@media (min-width:768px){.safe-pb-nav{padding-bottom:4rem}}@keyframes toast-in{0%{opacity:0;transform:translate(-50%,12px)}to{opacity:1;transform:translate(-50%)}}.animate-toast-in{animation:toast-in .35s ease-out both}@keyframes pulse-soft{0%,to{opacity:1}50%{opacity:.65}}.animate-pulse-soft{animation:pulse-soft 2s ease-in-out infinite}.log-scroll{scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.35) transparent}.log-scroll::-webkit-scrollbar{width:6px;height:6px}.log-scroll::-webkit-scrollbar-thumb{background:rgba(148,163,184,.35);border-radius:6px}.portal-grid-bg{background-image:linear-gradient(hsla(0,0%,100%,.05) 1px,transparent 0),linear-gradient(90deg,hsla(0,0%,100%,.05) 1px,transparent 0);background-size:28px 28px}.lp-noise{background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E")}@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,:after,:before{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}.selection\:bg-violet-400\/25 ::selection{background-color:rgba(167,139,250,.25)}.selection\:bg-violet-500\/30 ::selection{background-color:rgba(139,92,246,.3)}.selection\:bg-violet-400\/25::selection{background-color:rgba(167,139,250,.25)}.selection\:bg-violet-500\/30::selection{background-color:rgba(139,92,246,.3)}.last\:border-0:last-child{border-width:0}.hover\:border-violet-400\/25:hover{border-color:rgba(167,139,250,.25)}.hover\:border-white\/15:hover{border-color:hsla(0,0%,100%,.15)}.hover\:border-white\/20:hover{border-color:hsla(0,0%,100%,.2)}.hover\:bg-black\/45:hover{background-color:rgba(0,0,0,.45)}.hover\:bg-cyan-500\/15:hover{background-color:rgba(6,182,212,.15)}.hover\:bg-cyan-500\/25:hover{background-color:rgba(6,182,212,.25)}.hover\:bg-emerald-500\/20:hover{background-color:rgba(16,185,129,.2)}.hover\:bg-slate-100:hover{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.hover\:bg-slate-200\/60:hover{background-color:rgba(226,232,240,.6)}.hover\:bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.hover\:bg-violet-500\/25:hover{background-color:rgba(139,92,246,.25)}.hover\:bg-violet-500\/30:hover{background-color:rgba(139,92,246,.3)}.hover\:bg-white\/10:hover{background-color:hsla(0,0%,100%,.1)}.hover\:bg-white\/5:hover{background-color:hsla(0,0%,100%,.05)}.hover\:bg-white\/\[0\.04\]:hover{background-color:hsla(0,0%,100%,.04)}.hover\:bg-white\/\[0\.07\]:hover{background-color:hsla(0,0%,100%,.07)}.hover\:bg-white\/\[0\.08\]:hover{background-color:hsla(0,0%,100%,.08)}.hover\:bg-white\/\[0\.1\]:hover{background-color:hsla(0,0%,100%,.1)}.hover\:text-amber-300:hover{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.hover\:text-cyan-200:hover{--tw-text-opacity:1;color:rgb(165 243 252/var(--tw-text-opacity,1))}.hover\:text-rose-200:hover{--tw-text-opacity:1;color:rgb(254 205 211/var(--tw-text-opacity,1))}.hover\:text-slate-900:hover{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.hover\:text-zinc-200:hover{--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.hover\:text-zinc-300:hover{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:ring-violet-400\/50:hover{--tw-ring-color:rgba(167,139,250,.5)}.hover\:brightness-110:hover{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-emerald-500\/50:focus-visible{--tw-ring-color:rgba(16,185,129,.5)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}@media (min-width:640px){.sm\:block{display:block}.sm\:inline{display:inline}.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:flex-wrap{flex-wrap:wrap}.sm\:flex-nowrap{flex-wrap:nowrap}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-center{justify-content:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-2{gap:.5rem}.sm\:px-3{padding-left:.75rem;padding-right:.75rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-4xl{font-size:2.25rem;line-height:2.5rem}}@media (min-width:768px){.md\:bottom-6{bottom:1.5rem}.md\:hidden{display:none}.md\:h-72{height:18rem}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:1024px){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:items-start{align-items:flex-start}.lg\:items-end{align-items:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:px-10{padding-left:2.5rem;padding-right:2.5rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:py-8{padding-top:2rem;padding-bottom:2rem}.lg\:text-xl{font-size:1.25rem;line-height:1.75rem}}@media (min-width:1280px){.xl\:col-span-12{grid-column:span 12/span 12}.xl\:col-span-4{grid-column:span 4/span 4}.xl\:col-span-8{grid-column:span 8/span 8}.xl\:max-h-\[min\(24rem\2c 50vh\)\]{max-height:min(24rem,50vh)}.xl\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:grid-cols-\[0\.95fr\2c 1\.05fr\]{grid-template-columns:.95fr 1.05fr}.xl\:grid-cols-\[1\.1fr_0\.9fr\]{grid-template-columns:1.1fr .9fr}.xl\:grid-cols-\[18rem\2c 1fr\]{grid-template-columns:18rem 1fr}}.\[\&\:\:-webkit-scrollbar\]\:hidden::-webkit-scrollbar{display:none}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:border-cyan-600\/25{border-color:rgba(8,145,178,.25)}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:border-slate-200\/60{border-color:rgba(226,232,240,.6)}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:bg-white\/90{background-color:hsla(0,0%,100%,.9)}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:bg-white\/95{background-color:hsla(0,0%,100%,.95)}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:text-cyan-700{--tw-text-opacity:1;color:rgb(14 116 144/var(--tw-text-opacity,1))}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:text-cyan-950{--tw-text-opacity:1;color:rgb(8 51 68/var(--tw-text-opacity,1))}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))} \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/css/f7eb93299e7a4c6e.css b/d2ypp2/web-console/out/_next/static/css/f7eb93299e7a4c6e.css new file mode 100644 index 0000000..5e09f9a --- /dev/null +++ b/d2ypp2/web-console/out/_next/static/css/f7eb93299e7a4c6e.css @@ -0,0 +1,3 @@ +@font-face{font-family:__geistSans_1e4310;src:url(/_next/static/media/4473ecc91f70f139-s.p.woff) format("woff");font-display:swap;font-weight:100 900}@font-face{font-family:__geistSans_Fallback_1e4310;src:local("Arial");ascent-override:85.83%;descent-override:20.52%;line-gap-override:9.33%;size-adjust:107.19%}.__className_1e4310{font-family:__geistSans_1e4310,__geistSans_Fallback_1e4310}.__variable_1e4310{--font-geist-sans:"__geistSans_1e4310","__geistSans_Fallback_1e4310"}@font-face{font-family:__geistMono_c3aa02;src:url(/_next/static/media/463dafcda517f24f-s.p.woff) format("woff");font-display:swap;font-weight:100 900}@font-face{font-family:__geistMono_Fallback_c3aa02;src:local("Arial");ascent-override:69.97%;descent-override:16.73%;line-gap-override:7.61%;size-adjust:131.49%}.__className_c3aa02{font-family:__geistMono_c3aa02,__geistMono_Fallback_c3aa02}.__variable_c3aa02{--font-geist-mono:"__geistMono_c3aa02","__geistMono_Fallback_c3aa02"}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/* +! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com +*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.invisible{visibility:hidden}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.-bottom-0\.5{bottom:-.125rem}.-left-1\/4{left:-25%}.-right-0\.5{right:-.125rem}.-right-20{right:-5rem}.-right-4{right:-1rem}.-top-20{top:-5rem}.-top-4{top:-1rem}.bottom-0{bottom:0}.bottom-24{bottom:6rem}.bottom-3{bottom:.75rem}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\/2{left:50%}.right-0{right:0}.right-3{right:.75rem}.top-0{top:0}.z-0{z-index:0}.z-10{z-index:10}.z-20{z-index:20}.z-40{z-index:40}.z-50{z-index:50}.z-\[100\]{z-index:100}.col-span-2{grid-column:span 2/span 2}.mx-auto{margin-left:auto;margin-right:auto}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-8{margin-bottom:2rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-10{margin-top:2.5rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-5{margin-top:1.25rem}.mt-6{margin-top:1.5rem}.line-clamp-2{-webkit-line-clamp:2}.line-clamp-2,.line-clamp-3{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical}.line-clamp-3{-webkit-line-clamp:3}.line-clamp-6{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:6}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-11{height:2.75rem}.h-12{height:3rem}.h-16{height:4rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-36{height:9rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-56{height:14rem}.h-6{height:1.5rem}.h-64{height:16rem}.h-9{height:2.25rem}.h-\[30rem\]{height:30rem}.h-\[36rem\]{height:36rem}.h-\[42rem\]{height:42rem}.h-\[min\(72vh\2c 40rem\)\]{height:min(72vh,40rem)}.h-full{height:100%}.max-h-48{max-height:12rem}.max-h-64{max-height:16rem}.max-h-72{max-height:18rem}.max-h-\[28rem\]{max-height:28rem}.max-h-\[min\(22rem\2c 42vh\)\]{max-height:min(22rem,42vh)}.max-h-\[min\(24rem\2c 55vh\)\]{max-height:min(24rem,55vh)}.max-h-\[min\(70vh\2c 48rem\)\]{max-height:min(70vh,48rem)}.max-h-\[min\(72vh\2c 680px\)\]{max-height:min(72vh,680px)}.max-h-\[min\(78vh\2c 56rem\)\]{max-height:min(78vh,56rem)}.max-h-\[min\(78vh\2c 720px\)\]{max-height:min(78vh,720px)}.min-h-0{min-height:0}.min-h-\[100px\]{min-height:100px}.min-h-\[12rem\]{min-height:12rem}.min-h-\[14rem\]{min-height:14rem}.min-h-\[160px\]{min-height:160px}.min-h-\[18rem\]{min-height:18rem}.min-h-\[2\.75rem\]{min-height:2.75rem}.min-h-\[200px\]{min-height:200px}.min-h-\[22rem\]{min-height:22rem}.min-h-\[280px\]{min-height:280px}.min-h-\[2rem\]{min-height:2rem}.min-h-\[32rem\]{min-height:32rem}.min-h-\[3rem\]{min-height:3rem}.min-h-\[4rem\]{min-height:4rem}.min-h-\[6rem\]{min-height:6rem}.min-h-\[72px\]{min-height:72px}.min-h-screen{min-height:100vh}.w-11{width:2.75rem}.w-12{width:3rem}.w-16{width:4rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-24{width:6rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-56{width:14rem}.w-6{width:1.5rem}.w-64{width:16rem}.w-9{width:2.25rem}.w-\[36rem\]{width:36rem}.w-\[42rem\]{width:42rem}.w-\[min\(88vw\2c 280px\)\]{width:min(88vw,280px)}.w-auto{width:auto}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[12rem\]{min-width:12rem}.min-w-\[1rem\]{min-width:1rem}.min-w-\[6rem\]{min-width:6rem}.min-w-\[7rem\]{min-width:7rem}.min-w-\[9rem\]{min-width:9rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-5xl{max-width:64rem}.max-w-6xl{max-width:72rem}.max-w-7xl{max-width:80rem}.max-w-\[min\(92vw\2c 28rem\)\]{max-width:min(92vw,28rem)}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.max-w-md{max-width:28rem}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-crosshair{cursor:crosshair}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.resize{resize:both}.list-inside{list-style-position:inside}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.justify-around{justify-content:space-around}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-x-2{column-gap:.5rem}.gap-y-0\.5{row-gap:.125rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.625rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-3xl{border-radius:1.5rem}.rounded-\[1\.35rem\]{border-radius:1.35rem}.rounded-\[2rem\]{border-radius:2rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-b-xl{border-bottom-right-radius:.75rem;border-bottom-left-radius:.75rem}.border{border-width:1px}.border-\[10px\]{border-width:10px}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-400\/50{border-color:rgba(251,191,36,.5)}.border-amber-500\/15{border-color:rgba(245,158,11,.15)}.border-amber-500\/20{border-color:rgba(245,158,11,.2)}.border-amber-500\/25{border-color:rgba(245,158,11,.25)}.border-amber-500\/30{border-color:rgba(245,158,11,.3)}.border-cyan-400\/35{border-color:rgba(34,211,238,.35)}.border-cyan-400\/50{border-color:rgba(34,211,238,.5)}.border-cyan-500\/15{border-color:rgba(6,182,212,.15)}.border-cyan-500\/20{border-color:rgba(6,182,212,.2)}.border-cyan-500\/25{border-color:rgba(6,182,212,.25)}.border-cyan-500\/30{border-color:rgba(6,182,212,.3)}.border-cyan-500\/40{border-color:rgba(6,182,212,.4)}.border-cyan-500\/50{border-color:rgba(6,182,212,.5)}.border-emerald-400\/30{border-color:rgba(52,211,153,.3)}.border-emerald-500\/15{border-color:rgba(16,185,129,.15)}.border-emerald-500\/20{border-color:rgba(16,185,129,.2)}.border-emerald-500\/25{border-color:rgba(16,185,129,.25)}.border-emerald-500\/30{border-color:rgba(16,185,129,.3)}.border-emerald-500\/50{border-color:rgba(16,185,129,.5)}.border-fuchsia-200\/80{border-color:rgba(245,208,254,.8)}.border-fuchsia-400\/20{border-color:rgba(232,121,249,.2)}.border-fuchsia-500\/20{border-color:rgba(217,70,239,.2)}.border-fuchsia-500\/25{border-color:rgba(217,70,239,.25)}.border-fuchsia-500\/30{border-color:rgba(217,70,239,.3)}.border-indigo-400\/50{border-color:rgba(129,140,248,.5)}.border-indigo-500\/25{border-color:rgba(99,102,241,.25)}.border-rose-500\/15{border-color:rgba(244,63,94,.15)}.border-rose-500\/20{border-color:rgba(244,63,94,.2)}.border-rose-500\/25{border-color:rgba(244,63,94,.25)}.border-rose-500\/30{border-color:rgba(244,63,94,.3)}.border-sky-400\/20{border-color:rgba(56,189,248,.2)}.border-sky-500\/20{border-color:rgba(14,165,233,.2)}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-slate-200\/80{border-color:rgba(226,232,240,.8)}.border-slate-200\/90{border-color:rgba(226,232,240,.9)}.border-slate-500\/30{border-color:rgba(100,116,139,.3)}.border-slate-700\/30{border-color:rgba(51,65,85,.3)}.border-violet-200\/90{border-color:rgba(221,214,254,.9)}.border-violet-400\/35{border-color:rgba(167,139,250,.35)}.border-violet-500\/15{border-color:rgba(139,92,246,.15)}.border-violet-500\/20{border-color:rgba(139,92,246,.2)}.border-violet-500\/25{border-color:rgba(139,92,246,.25)}.border-violet-500\/30{border-color:rgba(139,92,246,.3)}.border-violet-500\/35{border-color:rgba(139,92,246,.35)}.border-violet-500\/45{border-color:rgba(139,92,246,.45)}.border-violet-500\/50{border-color:rgba(139,92,246,.5)}.border-white\/10{border-color:hsla(0,0%,100%,.1)}.border-white\/15{border-color:hsla(0,0%,100%,.15)}.border-white\/20{border-color:hsla(0,0%,100%,.2)}.border-white\/5{border-color:hsla(0,0%,100%,.05)}.border-white\/\[0\.04\]{border-color:hsla(0,0%,100%,.04)}.border-white\/\[0\.05\]{border-color:hsla(0,0%,100%,.05)}.border-white\/\[0\.06\]{border-color:hsla(0,0%,100%,.06)}.border-white\/\[0\.07\]{border-color:hsla(0,0%,100%,.07)}.border-white\/\[0\.08\]{border-color:hsla(0,0%,100%,.08)}.border-zinc-800{--tw-border-opacity:1;border-color:rgb(39 39 42/var(--tw-border-opacity,1))}.bg-\[\#050508\]{--tw-bg-opacity:1;background-color:rgb(5 5 8/var(--tw-bg-opacity,1))}.bg-amber-500\/10{background-color:rgba(245,158,11,.1)}.bg-amber-500\/15{background-color:rgba(245,158,11,.15)}.bg-amber-500\/20{background-color:rgba(245,158,11,.2)}.bg-amber-500\/5{background-color:rgba(245,158,11,.05)}.bg-amber-500\/\[0\.06\]{background-color:rgba(245,158,11,.06)}.bg-amber-600{--tw-bg-opacity:1;background-color:rgb(217 119 6/var(--tw-bg-opacity,1))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity,1))}.bg-black\/15{background-color:rgba(0,0,0,.15)}.bg-black\/20{background-color:rgba(0,0,0,.2)}.bg-black\/25{background-color:rgba(0,0,0,.25)}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/35{background-color:rgba(0,0,0,.35)}.bg-black\/40{background-color:rgba(0,0,0,.4)}.bg-black\/45{background-color:rgba(0,0,0,.45)}.bg-black\/50{background-color:rgba(0,0,0,.5)}.bg-black\/55{background-color:rgba(0,0,0,.55)}.bg-black\/60{background-color:rgba(0,0,0,.6)}.bg-black\/75{background-color:rgba(0,0,0,.75)}.bg-black\/80{background-color:rgba(0,0,0,.8)}.bg-cyan-100{--tw-bg-opacity:1;background-color:rgb(207 250 254/var(--tw-bg-opacity,1))}.bg-cyan-400\/10{background-color:rgba(34,211,238,.1)}.bg-cyan-500\/10{background-color:rgba(6,182,212,.1)}.bg-cyan-500\/15{background-color:rgba(6,182,212,.15)}.bg-cyan-500\/20{background-color:rgba(6,182,212,.2)}.bg-cyan-500\/30{background-color:rgba(6,182,212,.3)}.bg-cyan-500\/90{background-color:rgba(6,182,212,.9)}.bg-cyan-500\/\[0\.05\]{background-color:rgba(6,182,212,.05)}.bg-cyan-500\/\[0\.06\]{background-color:rgba(6,182,212,.06)}.bg-cyan-600{--tw-bg-opacity:1;background-color:rgb(8 145 178/var(--tw-bg-opacity,1))}.bg-cyan-600\/80{background-color:rgba(8,145,178,.8)}.bg-emerald-500\/10{background-color:rgba(16,185,129,.1)}.bg-emerald-500\/15{background-color:rgba(16,185,129,.15)}.bg-emerald-500\/20{background-color:rgba(16,185,129,.2)}.bg-emerald-500\/90{background-color:rgba(16,185,129,.9)}.bg-emerald-600{--tw-bg-opacity:1;background-color:rgb(5 150 105/var(--tw-bg-opacity,1))}.bg-fuchsia-500\/10{background-color:rgba(217,70,239,.1)}.bg-fuchsia-500\/20{background-color:rgba(217,70,239,.2)}.bg-indigo-500\/15{background-color:rgba(99,102,241,.15)}.bg-rose-500\/10{background-color:rgba(244,63,94,.1)}.bg-rose-500\/15{background-color:rgba(244,63,94,.15)}.bg-rose-600{--tw-bg-opacity:1;background-color:rgb(225 29 72/var(--tw-bg-opacity,1))}.bg-rose-950\/20{background-color:rgba(76,5,25,.2)}.bg-rose-950\/25{background-color:rgba(76,5,25,.25)}.bg-sky-500\/10{background-color:rgba(14,165,233,.1)}.bg-sky-500\/15{background-color:rgba(14,165,233,.15)}.bg-sky-500\/25{background-color:rgba(14,165,233,.25)}.bg-sky-600{--tw-bg-opacity:1;background-color:rgb(2 132 199/var(--tw-bg-opacity,1))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.bg-slate-50{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.bg-slate-500\/10{background-color:rgba(100,116,139,.1)}.bg-slate-500\/15{background-color:rgba(100,116,139,.15)}.bg-slate-800\/50{background-color:rgba(30,41,59,.5)}.bg-slate-950\/30{background-color:rgba(2,6,23,.3)}.bg-slate-950\/50{background-color:rgba(2,6,23,.5)}.bg-slate-950\/60{background-color:rgba(2,6,23,.6)}.bg-slate-950\/80{background-color:rgba(2,6,23,.8)}.bg-slate-950\/95{background-color:rgba(2,6,23,.95)}.bg-violet-100{--tw-bg-opacity:1;background-color:rgb(237 233 254/var(--tw-bg-opacity,1))}.bg-violet-100\/90{background-color:rgba(237,233,254,.9)}.bg-violet-400\/15{background-color:rgba(167,139,250,.15)}.bg-violet-500\/10{background-color:rgba(139,92,246,.1)}.bg-violet-500\/15{background-color:rgba(139,92,246,.15)}.bg-violet-500\/20{background-color:rgba(139,92,246,.2)}.bg-violet-500\/25{background-color:rgba(139,92,246,.25)}.bg-violet-500\/\[0\.06\]{background-color:rgba(139,92,246,.06)}.bg-violet-500\/\[0\.1\]{background-color:rgba(139,92,246,.1)}.bg-violet-600{--tw-bg-opacity:1;background-color:rgb(124 58 237/var(--tw-bg-opacity,1))}.bg-violet-600\/20{background-color:rgba(124,58,237,.2)}.bg-violet-600\/70{background-color:rgba(124,58,237,.7)}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/10{background-color:hsla(0,0%,100%,.1)}.bg-white\/5{background-color:hsla(0,0%,100%,.05)}.bg-white\/70{background-color:hsla(0,0%,100%,.7)}.bg-white\/75{background-color:hsla(0,0%,100%,.75)}.bg-white\/80{background-color:hsla(0,0%,100%,.8)}.bg-white\/90{background-color:hsla(0,0%,100%,.9)}.bg-white\/\[0\.04\]{background-color:hsla(0,0%,100%,.04)}.bg-white\/\[0\.05\]{background-color:hsla(0,0%,100%,.05)}.bg-white\/\[0\.06\]{background-color:hsla(0,0%,100%,.06)}.bg-white\/\[0\.08\]{background-color:hsla(0,0%,100%,.08)}.bg-zinc-500\/15{background-color:hsla(240,4%,46%,.15)}.bg-zinc-600\/20{background-color:rgba(82,82,91,.2)}.bg-zinc-600\/30{background-color:rgba(82,82,91,.3)}.bg-zinc-700\/40{background-color:rgba(63,63,70,.4)}.bg-zinc-700\/90{background-color:rgba(63,63,70,.9)}.bg-zinc-950{--tw-bg-opacity:1;background-color:rgb(9 9 11/var(--tw-bg-opacity,1))}.bg-zinc-950\/30{background-color:rgba(9,9,11,.3)}.bg-zinc-950\/40{background-color:rgba(9,9,11,.4)}.bg-zinc-950\/50{background-color:rgba(9,9,11,.5)}.bg-zinc-950\/60{background-color:rgba(9,9,11,.6)}.bg-zinc-950\/70{background-color:rgba(9,9,11,.7)}.bg-zinc-950\/80{background-color:rgba(9,9,11,.8)}.bg-zinc-950\/95{background-color:rgba(9,9,11,.95)}.bg-gradient-to-b{background-image:linear-gradient(to bottom,var(--tw-gradient-stops))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-amber-400{--tw-gradient-from:#fbbf24 var(--tw-gradient-from-position);--tw-gradient-to:rgba(251,191,36,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-50\/90{--tw-gradient-from:rgba(255,251,235,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(255,251,235,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-500\/35{--tw-gradient-from:rgba(245,158,11,.35) var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,158,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-500\/\[0\.07\]{--tw-gradient-from:rgba(245,158,11,.07) var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,158,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-500\/\[0\.12\]{--tw-gradient-from:rgba(245,158,11,.12) var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,158,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-amber-500\/\[0\.1\]{--tw-gradient-from:rgba(245,158,11,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,158,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-400{--tw-gradient-from:#22d3ee var(--tw-gradient-from-position);--tw-gradient-to:rgba(34,211,238,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/35{--tw-gradient-from:rgba(6,182,212,.35) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/\[0\.07\]{--tw-gradient-from:rgba(6,182,212,.07) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/\[0\.08\]{--tw-gradient-from:rgba(6,182,212,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/\[0\.14\]{--tw-gradient-from:rgba(6,182,212,.14) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-cyan-500\/\[0\.1\]{--tw-gradient-from:rgba(6,182,212,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(6,182,212,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-400{--tw-gradient-from:#34d399 var(--tw-gradient-from-position);--tw-gradient-to:rgba(52,211,153,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-400\/30{--tw-gradient-from:rgba(52,211,153,.3) var(--tw-gradient-from-position);--tw-gradient-to:rgba(52,211,153,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-500\/\[0\.07\]{--tw-gradient-from:rgba(16,185,129,.07) var(--tw-gradient-from-position);--tw-gradient-to:rgba(16,185,129,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-500\/\[0\.08\]{--tw-gradient-from:rgba(16,185,129,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(16,185,129,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-emerald-500\/\[0\.12\]{--tw-gradient-from:rgba(16,185,129,.12) var(--tw-gradient-from-position);--tw-gradient-to:rgba(16,185,129,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-fuchsia-50\/90{--tw-gradient-from:rgba(253,244,255,.9) var(--tw-gradient-from-position);--tw-gradient-to:rgba(253,244,255,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-fuchsia-500\/10{--tw-gradient-from:rgba(217,70,239,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(217,70,239,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-fuchsia-500\/\[0\.08\]{--tw-gradient-from:rgba(217,70,239,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(217,70,239,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-fuchsia-950\/40{--tw-gradient-from:rgba(74,4,78,.4) var(--tw-gradient-from-position);--tw-gradient-to:rgba(74,4,78,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-indigo-500\/\[0\.1\]{--tw-gradient-from:rgba(99,102,241,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(99,102,241,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-pink-500\/25{--tw-gradient-from:rgba(236,72,153,.25) var(--tw-gradient-from-position);--tw-gradient-to:rgba(236,72,153,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-red-500\/30{--tw-gradient-from:rgba(239,68,68,.3) var(--tw-gradient-from-position);--tw-gradient-to:rgba(239,68,68,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-sky-500\/\[0\.08\]{--tw-gradient-from:rgba(14,165,233,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(14,165,233,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-50{--tw-gradient-from:#f5f3ff var(--tw-gradient-from-position);--tw-gradient-to:rgba(245,243,255,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500{--tw-gradient-from:#8b5cf6 var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500\/10{--tw-gradient-from:rgba(139,92,246,.1) var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500\/30{--tw-gradient-from:rgba(139,92,246,.3) var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500\/\[0\.08\]{--tw-gradient-from:rgba(139,92,246,.08) var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-violet-500\/\[0\.12\]{--tw-gradient-from:rgba(139,92,246,.12) var(--tw-gradient-from-position);--tw-gradient-to:rgba(139,92,246,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.from-white\/\[0\.05\]{--tw-gradient-from:hsla(0,0%,100%,.05) var(--tw-gradient-from-position);--tw-gradient-to:hsla(0,0%,100%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),var(--tw-gradient-to)}.via-black\/25{--tw-gradient-to:transparent var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(0,0,0,.25) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-white{--tw-gradient-to:hsla(0,0%,100%,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),#fff var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/40{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.4) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/50{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.5) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/55{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.55) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/60{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.6) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/70{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.7) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/80{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.8) var(--tw-gradient-via-position),var(--tw-gradient-to)}.via-zinc-950\/90{--tw-gradient-to:rgba(9,9,11,0) var(--tw-gradient-to-position);--tw-gradient-stops:var(--tw-gradient-from),rgba(9,9,11,.9) var(--tw-gradient-via-position),var(--tw-gradient-to)}.to-black\/40{--tw-gradient-to:rgba(0,0,0,.4) var(--tw-gradient-to-position)}.to-blue-500{--tw-gradient-to:#3b82f6 var(--tw-gradient-to-position)}.to-cyan-400{--tw-gradient-to:#22d3ee var(--tw-gradient-to-position)}.to-cyan-50\/70{--tw-gradient-to:rgba(236,254,255,.7) var(--tw-gradient-to-position)}.to-cyan-500\/10{--tw-gradient-to:rgba(6,182,212,.1) var(--tw-gradient-to-position)}.to-cyan-500\/5,.to-cyan-500\/\[0\.05\]{--tw-gradient-to:rgba(6,182,212,.05) var(--tw-gradient-to-position)}.to-cyan-950\/20{--tw-gradient-to:rgba(8,51,68,.2) var(--tw-gradient-to-position)}.to-fuchsia-50\/80{--tw-gradient-to:rgba(253,244,255,.8) var(--tw-gradient-to-position)}.to-fuchsia-500{--tw-gradient-to:#d946ef var(--tw-gradient-to-position)}.to-fuchsia-500\/10{--tw-gradient-to:rgba(217,70,239,.1) var(--tw-gradient-to-position)}.to-fuchsia-500\/20{--tw-gradient-to:rgba(217,70,239,.2) var(--tw-gradient-to-position)}.to-fuchsia-500\/5{--tw-gradient-to:rgba(217,70,239,.05) var(--tw-gradient-to-position)}.to-fuchsia-500\/\[0\.06\]{--tw-gradient-to:rgba(217,70,239,.06) var(--tw-gradient-to-position)}.to-fuchsia-600\/25{--tw-gradient-to:rgba(192,38,211,.25) var(--tw-gradient-to-position)}.to-orange-500{--tw-gradient-to:#f97316 var(--tw-gradient-to-position)}.to-rose-500\/\[0\.05\]{--tw-gradient-to:rgba(244,63,94,.05) var(--tw-gradient-to-position)}.to-slate-50{--tw-gradient-to:#f8fafc var(--tw-gradient-to-position)}.to-teal-500{--tw-gradient-to:#14b8a6 var(--tw-gradient-to-position)}.to-transparent{--tw-gradient-to:transparent var(--tw-gradient-to-position)}.to-violet-500\/10{--tw-gradient-to:rgba(139,92,246,.1) var(--tw-gradient-to-position)}.to-violet-500\/25{--tw-gradient-to:rgba(139,92,246,.25) var(--tw-gradient-to-position)}.to-violet-500\/\[0\.06\]{--tw-gradient-to:rgba(139,92,246,.06) var(--tw-gradient-to-position)}.to-violet-500\/\[0\.08\]{--tw-gradient-to:rgba(139,92,246,.08) var(--tw-gradient-to-position)}.to-violet-600\/25{--tw-gradient-to:rgba(124,58,237,.25) var(--tw-gradient-to-position)}.to-violet-600\/30{--tw-gradient-to:rgba(124,58,237,.3) var(--tw-gradient-to-position)}.to-zinc-900\/90{--tw-gradient-to:rgba(24,24,27,.9) var(--tw-gradient-to-position)}.to-zinc-950\/80{--tw-gradient-to:rgba(9,9,11,.8) var(--tw-gradient-to-position)}.object-contain{object-fit:contain}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-24{padding-top:6rem;padding-bottom:6rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-1{padding-bottom:.25rem}.pb-16{padding-bottom:4rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-5{padding-left:1.25rem}.pr-1{padding-right:.25rem}.pt-1{padding-top:.25rem}.pt-2{padding-top:.5rem}.pt-4{padding-top:1rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-snug{line-height:1.375}.leading-tight{line-height:1.25}.tracking-\[0\.08em\]{letter-spacing:.08em}.tracking-\[0\.22em\]{letter-spacing:.22em}.tracking-\[0\.2em\]{letter-spacing:.2em}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-\[color\:var\(--text\)\]{color:var(--text)}.text-amber-100{--tw-text-opacity:1;color:rgb(254 243 199/var(--tw-text-opacity,1))}.text-amber-200{--tw-text-opacity:1;color:rgb(253 230 138/var(--tw-text-opacity,1))}.text-amber-200\/80{color:hsla(48,97%,77%,.8)}.text-amber-200\/85{color:hsla(48,97%,77%,.85)}.text-amber-200\/90{color:hsla(48,97%,77%,.9)}.text-amber-300{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.text-amber-400{--tw-text-opacity:1;color:rgb(251 191 36/var(--tw-text-opacity,1))}.text-amber-400\/95{color:rgba(251,191,36,.95)}.text-amber-500{--tw-text-opacity:1;color:rgb(245 158 11/var(--tw-text-opacity,1))}.text-amber-800{--tw-text-opacity:1;color:rgb(146 64 14/var(--tw-text-opacity,1))}.text-cyan-100{--tw-text-opacity:1;color:rgb(207 250 254/var(--tw-text-opacity,1))}.text-cyan-100\/90{color:rgba(207,250,254,.9)}.text-cyan-200{--tw-text-opacity:1;color:rgb(165 243 252/var(--tw-text-opacity,1))}.text-cyan-200\/90{color:rgba(165,243,252,.9)}.text-cyan-300{--tw-text-opacity:1;color:rgb(103 232 249/var(--tw-text-opacity,1))}.text-cyan-300\/70{color:rgba(103,232,249,.7)}.text-cyan-300\/80{color:rgba(103,232,249,.8)}.text-cyan-300\/90{color:rgba(103,232,249,.9)}.text-cyan-400{--tw-text-opacity:1;color:rgb(34 211 238/var(--tw-text-opacity,1))}.text-cyan-400\/90{color:rgba(34,211,238,.9)}.text-cyan-50{--tw-text-opacity:1;color:rgb(236 254 255/var(--tw-text-opacity,1))}.text-cyan-600{--tw-text-opacity:1;color:rgb(8 145 178/var(--tw-text-opacity,1))}.text-cyan-800{--tw-text-opacity:1;color:rgb(21 94 117/var(--tw-text-opacity,1))}.text-cyan-950{--tw-text-opacity:1;color:rgb(8 51 68/var(--tw-text-opacity,1))}.text-emerald-100{--tw-text-opacity:1;color:rgb(209 250 229/var(--tw-text-opacity,1))}.text-emerald-100\/95{color:rgba(209,250,229,.95)}.text-emerald-200{--tw-text-opacity:1;color:rgb(167 243 208/var(--tw-text-opacity,1))}.text-emerald-200\/90{color:rgba(167,243,208,.9)}.text-emerald-300{--tw-text-opacity:1;color:rgb(110 231 183/var(--tw-text-opacity,1))}.text-emerald-300\/90{color:rgba(110,231,183,.9)}.text-emerald-400{--tw-text-opacity:1;color:rgb(52 211 153/var(--tw-text-opacity,1))}.text-emerald-400\/80{color:rgba(52,211,153,.8)}.text-emerald-400\/90{color:rgba(52,211,153,.9)}.text-emerald-50{--tw-text-opacity:1;color:rgb(236 253 245/var(--tw-text-opacity,1))}.text-emerald-950{--tw-text-opacity:1;color:rgb(2 44 34/var(--tw-text-opacity,1))}.text-fuchsia-100{--tw-text-opacity:1;color:rgb(250 232 255/var(--tw-text-opacity,1))}.text-fuchsia-200{--tw-text-opacity:1;color:rgb(245 208 254/var(--tw-text-opacity,1))}.text-fuchsia-200\/80{color:rgba(245,208,254,.8)}.text-fuchsia-300\/90{color:rgba(240,171,252,.9)}.text-fuchsia-400{--tw-text-opacity:1;color:rgb(232 121 249/var(--tw-text-opacity,1))}.text-indigo-200{--tw-text-opacity:1;color:rgb(199 210 254/var(--tw-text-opacity,1))}.text-indigo-300\/90{color:rgba(165,180,252,.9)}.text-red-200{--tw-text-opacity:1;color:rgb(254 202 202/var(--tw-text-opacity,1))}.text-rose-100{--tw-text-opacity:1;color:rgb(255 228 230/var(--tw-text-opacity,1))}.text-rose-100\/95{color:rgba(255,228,230,.95)}.text-rose-200{--tw-text-opacity:1;color:rgb(254 205 211/var(--tw-text-opacity,1))}.text-rose-300{--tw-text-opacity:1;color:rgb(253 164 175/var(--tw-text-opacity,1))}.text-rose-400\/90{color:rgba(251,113,133,.9)}.text-sky-100{--tw-text-opacity:1;color:rgb(224 242 254/var(--tw-text-opacity,1))}.text-sky-100\/80{color:rgba(224,242,254,.8)}.text-sky-200{--tw-text-opacity:1;color:rgb(186 230 253/var(--tw-text-opacity,1))}.text-sky-400{--tw-text-opacity:1;color:rgb(56 189 248/var(--tw-text-opacity,1))}.text-slate-100{--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity,1))}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-300\/90{color:rgba(203,213,225,.9)}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity,1))}.text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.text-violet-100{--tw-text-opacity:1;color:rgb(237 233 254/var(--tw-text-opacity,1))}.text-violet-200{--tw-text-opacity:1;color:rgb(221 214 254/var(--tw-text-opacity,1))}.text-violet-300{--tw-text-opacity:1;color:rgb(196 181 253/var(--tw-text-opacity,1))}.text-violet-300\/80{color:rgba(196,181,253,.8)}.text-violet-300\/90{color:rgba(196,181,253,.9)}.text-violet-400{--tw-text-opacity:1;color:rgb(167 139 250/var(--tw-text-opacity,1))}.text-violet-400\/90{color:rgba(167,139,250,.9)}.text-violet-600{--tw-text-opacity:1;color:rgb(124 58 237/var(--tw-text-opacity,1))}.text-violet-700{--tw-text-opacity:1;color:rgb(109 40 217/var(--tw-text-opacity,1))}.text-violet-800{--tw-text-opacity:1;color:rgb(91 33 182/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/80{color:hsla(0,0%,100%,.8)}.text-zinc-100{--tw-text-opacity:1;color:rgb(244 244 245/var(--tw-text-opacity,1))}.text-zinc-200{--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.text-zinc-300{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.text-zinc-500{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.text-zinc-600{--tw-text-opacity:1;color:rgb(82 82 91/var(--tw-text-opacity,1))}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.accent-violet-500{accent-color:#8b5cf6}.opacity-35{opacity:.35}.opacity-40{opacity:.4}.opacity-45{opacity:.45}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.opacity-\[0\.06\]{opacity:.06}.opacity-\[0\.22\]{opacity:.22}.shadow-2xl{--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color)}.shadow-2xl,.shadow-inner{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 rgba(0,0,0,.05);--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-xl{--tw-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 8px 10px -6px rgba(0,0,0,.1);--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color),0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-black\/20{--tw-shadow-color:rgba(0,0,0,.2);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/30{--tw-shadow-color:rgba(0,0,0,.3);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/50{--tw-shadow-color:rgba(0,0,0,.5);--tw-shadow:var(--tw-shadow-colored)}.shadow-black\/80{--tw-shadow-color:rgba(0,0,0,.8);--tw-shadow:var(--tw-shadow-colored)}.shadow-cyan-900\/10{--tw-shadow-color:rgba(22,78,99,.1);--tw-shadow:var(--tw-shadow-colored)}.shadow-emerald-900\/20{--tw-shadow-color:rgba(6,78,59,.2);--tw-shadow:var(--tw-shadow-colored)}.shadow-fuchsia-100\/40{--tw-shadow-color:rgba(250,232,255,.4);--tw-shadow:var(--tw-shadow-colored)}.shadow-fuchsia-900\/10{--tw-shadow-color:rgba(112,26,117,.1);--tw-shadow:var(--tw-shadow-colored)}.shadow-indigo-500\/5{--tw-shadow-color:rgba(99,102,241,.05);--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-200\/30{--tw-shadow-color:rgba(226,232,240,.3);--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-200\/40{--tw-shadow-color:rgba(226,232,240,.4);--tw-shadow:var(--tw-shadow-colored)}.shadow-violet-200\/50{--tw-shadow-color:rgba(221,214,254,.5);--tw-shadow:var(--tw-shadow-colored)}.shadow-violet-500\/25{--tw-shadow-color:rgba(139,92,246,.25);--tw-shadow:var(--tw-shadow-colored)}.shadow-violet-500\/5{--tw-shadow-color:rgba(139,92,246,.05);--tw-shadow:var(--tw-shadow-colored)}.shadow-violet-900\/10{--tw-shadow-color:rgba(76,29,149,.1);--tw-shadow:var(--tw-shadow-colored)}.shadow-white\/5{--tw-shadow-color:hsla(0,0%,100%,.05);--tw-shadow:var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring,.ring-1{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-amber-500\/25{--tw-ring-color:rgba(245,158,11,.25)}.ring-amber-500\/30{--tw-ring-color:rgba(245,158,11,.3)}.ring-amber-500\/35{--tw-ring-color:rgba(245,158,11,.35)}.ring-cyan-400\/35{--tw-ring-color:rgba(34,211,238,.35)}.ring-cyan-500\/20{--tw-ring-color:rgba(6,182,212,.2)}.ring-cyan-500\/25{--tw-ring-color:rgba(6,182,212,.25)}.ring-cyan-500\/30{--tw-ring-color:rgba(6,182,212,.3)}.ring-cyan-500\/35{--tw-ring-color:rgba(6,182,212,.35)}.ring-emerald-400\/25{--tw-ring-color:rgba(52,211,153,.25)}.ring-emerald-400\/30{--tw-ring-color:rgba(52,211,153,.3)}.ring-emerald-500\/20{--tw-ring-color:rgba(16,185,129,.2)}.ring-emerald-500\/25{--tw-ring-color:rgba(16,185,129,.25)}.ring-emerald-500\/30{--tw-ring-color:rgba(16,185,129,.3)}.ring-fuchsia-400\/20{--tw-ring-color:rgba(232,121,249,.2)}.ring-fuchsia-500\/35{--tw-ring-color:rgba(217,70,239,.35)}.ring-indigo-500\/25{--tw-ring-color:rgba(99,102,241,.25)}.ring-rose-500\/25{--tw-ring-color:rgba(244,63,94,.25)}.ring-rose-500\/35{--tw-ring-color:rgba(244,63,94,.35)}.ring-sky-400\/40{--tw-ring-color:rgba(56,189,248,.4)}.ring-sky-500\/25{--tw-ring-color:rgba(14,165,233,.25)}.ring-slate-500\/30{--tw-ring-color:rgba(100,116,139,.3)}.ring-violet-400\/35{--tw-ring-color:rgba(167,139,250,.35)}.ring-violet-400\/40{--tw-ring-color:rgba(167,139,250,.4)}.ring-violet-500\/20{--tw-ring-color:rgba(139,92,246,.2)}.ring-violet-500\/25{--tw-ring-color:rgba(139,92,246,.25)}.ring-violet-500\/30{--tw-ring-color:rgba(139,92,246,.3)}.ring-violet-500\/35{--tw-ring-color:rgba(139,92,246,.35)}.ring-white\/10{--tw-ring-color:hsla(0,0%,100%,.1)}.ring-white\/\[0\.04\]{--tw-ring-color:hsla(0,0%,100%,.04)}.ring-white\/\[0\.05\]{--tw-ring-color:hsla(0,0%,100%,.05)}.ring-white\/\[0\.06\]{--tw-ring-color:hsla(0,0%,100%,.06)}.ring-zinc-500\/25{--tw-ring-color:hsla(240,4%,46%,.25)}.blur-3xl{--tw-blur:blur(64px)}.blur-3xl,.blur-\[100px\]{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-\[100px\]{--tw-blur:blur(100px)}.blur-\[120px\]{--tw-blur:blur(120px)}.blur-\[120px\],.blur-xl{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.blur-xl{--tw-blur:blur(24px)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-2xl{--tw-backdrop-blur:blur(40px)}.backdrop-blur-2xl,.backdrop-blur-\[2px\]{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-\[2px\]{--tw-backdrop-blur:blur(2px)}.backdrop-blur-lg{--tw-backdrop-blur:blur(16px)}.backdrop-blur-lg,.backdrop-blur-md{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px)}.backdrop-blur-sm,.backdrop-blur-xl{-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-xl{--tw-backdrop-blur:blur(24px)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.glass{border-width:1px;border-color:hsla(0,0%,100%,.08);--tw-shadow:0 25px 50px -12px rgba(0,0,0,.25);--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);--tw-shadow-color:rgba(0,0,0,.4);--tw-shadow:var(--tw-shadow-colored);background:var(--bg-card);backdrop-filter:blur(20px);-webkit-backdrop-filter:blur(20px);transition:border-color .25s ease,box-shadow .25s ease,background .25s ease}html[data-theme=light] .glass{border-color:rgba(226,232,240,.9);--tw-shadow-color:rgba(148,163,184,.15);--tw-shadow:var(--tw-shadow-colored)}.section-title{font-size:1.125rem;line-height:1.75rem;font-weight:600;letter-spacing:-.025em;color:var(--text)}.section-lead{margin-top:.5rem}.meta-chip,.section-lead{font-size:.75rem;line-height:1rem;line-height:1.625;color:var(--muted)}.meta-chip{border-radius:1rem;border-width:1px;padding:.75rem 1rem;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;border-color:hsla(0,0%,100%,.1);background:rgba(0,0,0,.22)}html[data-theme=light] .meta-chip{border-color:rgba(226,232,240,.95);background:hsla(0,0%,100%,.72);color:var(--muted)}.tab-strip{margin-left:-.25rem;margin-right:-.25rem;display:flex;gap:.5rem;overflow-x:auto;padding-bottom:.375rem;padding-top:.125rem}@media (min-width:768px){.tab-strip{flex-wrap:wrap;overflow:visible}}.tab-strip{scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch}.tab-btn{flex-shrink:0;scroll-snap-align:start;border-radius:1rem;border-width:1px;padding:.625rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.tab-btn:focus-visible{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(34,211,238,.5);--tw-ring-offset-width:2px}.tab-btn{--tw-ring-offset-color:var(--ring-offset);border-color:hsla(0,0%,100%,.12);background:rgba(0,0,0,.22);color:#cbd5e1}.tab-btn:hover{border-color:rgba(34,211,238,.25);color:#e2e8f0}.tab-btn-active{border-color:rgba(34,211,238,.45)!important;background:rgba(34,211,238,.12)!important;color:#cffafe!important}html[data-theme=light] .tab-btn{border-color:#e2e8f0;background:hsla(0,0%,100%,.75);color:#475569}html[data-theme=light] .tab-btn:hover{border-color:rgba(6,182,212,.45);color:#0f766e}html[data-theme=light] .tab-btn-active{border-color:rgba(6,182,212,.55)!important;background:rgba(207,250,254,.55)!important;color:#0e7490!important}.link-tile{display:block;border-radius:1rem;border-width:1px;padding:.625rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:500;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.link-tile:focus-visible{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(34,211,238,.5);--tw-ring-offset-width:2px}.link-tile{--tw-ring-offset-color:var(--ring-offset);border-color:hsla(0,0%,100%,.1);background:rgba(0,0,0,.2);color:#f1f5f9}.link-tile:hover{border-color:rgba(34,211,238,.35)}html[data-theme=light] .link-tile{border-color:#e2e8f0;background:hsla(0,0%,100%,.65);color:#1e293b}.link-tile-accent{border-color:rgba(34,211,238,.28);background:rgba(34,211,238,.1);color:#ecfeff}.link-tile-accent:hover{border-color:rgba(34,211,238,.55)}html[data-theme=light] .link-tile-accent{border-color:rgba(6,182,212,.35);background:rgba(207,250,254,.65);color:#0e7490}.link-tile-warn{border-color:rgba(251,191,36,.25);background:rgba(251,191,36,.1);color:#fefce8}html[data-theme=light] .link-tile-warn{border-color:rgba(251,191,36,.45);background:hsla(55,92%,95%,.9);color:#78350f}.service-card{border-radius:1.5rem;border-width:1px;padding:1.25rem;transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s;border-color:hsla(0,0%,100%,.08);background:rgba(0,0,0,.2)}.service-card:hover{box-shadow:0 12px 40px -24px rgba(34,211,238,.35)}html[data-theme=light] .service-card{border-color:rgba(226,232,240,.95);background:hsla(0,0%,100%,.55)}.panel-inset{border-radius:1rem;border-width:1px;padding:1rem;font-size:.875rem;line-height:1.25rem;border-color:hsla(0,0%,100%,.08);background:rgba(0,0,0,.2);color:#cbd5e1}html[data-theme=light] .panel-inset{border-color:rgba(226,232,240,.85);background:hsla(0,0%,100%,.5);color:#334155}.field-select{width:100%;border-radius:1rem;border-width:1px;padding:.75rem 1rem;font-size:.875rem;line-height:1.25rem;outline:2px solid transparent;outline-offset:2px;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s;border-color:hsla(0,0%,100%,.12);background:rgba(2,6,23,.55);color:#f8fafc}html[data-theme=light] .field-select{border-color:#e2e8f0;background:hsla(0,0%,100%,.9);color:#0f172a}.btn-focus:focus-visible{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);--tw-ring-color:rgba(34,211,238,.5);--tw-ring-offset-width:2px}.btn-focus{--tw-ring-offset-color:var(--ring-offset)}.\[-ms-overflow-style\:none\]{-ms-overflow-style:none}.\[scrollbar-width\:none\]{scrollbar-width:none}:root{--bg-deep:#060912;--bg-card:rgba(16,22,36,.78);--accent:#22d3ee;--accent2:#a78bfa;--danger:#f43f5e;--ok:#34d399;--text:#e8edf7;--muted:#94a3b8;--ring-offset:#060912;color-scheme:dark}html[data-theme=light]{--bg-deep:#f1f5f9;--bg-card:hsla(0,0%,100%,.88);--text:#0f172a;--muted:#64748b;--ring-offset:#f1f5f9;color-scheme:light}html{scroll-behavior:smooth}body{color:var(--text);background:var(--bg-deep);min-height:100vh;font-family:var(--font-geist-sans),system-ui,sans-serif;overflow-x:hidden;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;transition:background-color .35s ease,color .25s ease}*{scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.35) transparent}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-thumb{background:rgba(148,163,184,.35);border-radius:999px}::-webkit-scrollbar-track{background:transparent}.app-bg-layer{position:fixed;inset:0;z-index:-1;opacity:.92;pointer-events:none;background:radial-gradient(ellipse 80% 50% at 50% -20%,rgba(34,211,238,.22),transparent),radial-gradient(ellipse 60% 40% at 100% 0,rgba(167,139,250,.18),transparent),radial-gradient(ellipse 50% 30% at 0 100%,rgba(59,130,246,.12),transparent);transition:opacity .35s ease}html[data-theme=light] .app-bg-layer{opacity:.75;background:radial-gradient(ellipse 80% 50% at 50% -20%,rgba(14,165,233,.12),transparent),radial-gradient(ellipse 60% 40% at 100% 0,rgba(139,92,246,.1),transparent),radial-gradient(ellipse 50% 30% at 0 100%,rgba(59,130,246,.08),transparent)}html[data-theme=light] .chart-surface{border-color:rgba(15,23,42,.12)!important;background:hsla(0,0%,100%,.65)!important}::selection{background:rgba(34,211,238,.25)}.safe-pb-nav{padding-bottom:calc(5.5rem + env(safe-area-inset-bottom, 0px))}@media (min-width:768px){.safe-pb-nav{padding-bottom:4rem}}@keyframes toast-in{0%{opacity:0;transform:translate(-50%,12px)}to{opacity:1;transform:translate(-50%)}}.animate-toast-in{animation:toast-in .35s ease-out both}@keyframes pulse-soft{0%,to{opacity:1}50%{opacity:.65}}.animate-pulse-soft{animation:pulse-soft 2s ease-in-out infinite}.log-scroll{scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.35) transparent}.log-scroll::-webkit-scrollbar{width:6px;height:6px}.log-scroll::-webkit-scrollbar-thumb{background:rgba(148,163,184,.35);border-radius:6px}.portal-grid-bg{background-image:linear-gradient(hsla(0,0%,100%,.05) 1px,transparent 0),linear-gradient(90deg,hsla(0,0%,100%,.05) 1px,transparent 0);background-size:28px 28px}.lp-noise{background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.04'/%3E%3C/svg%3E")}@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}*,:after,:before{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}}.selection\:bg-violet-400\/25 ::selection{background-color:rgba(167,139,250,.25)}.selection\:bg-violet-500\/30 ::selection{background-color:rgba(139,92,246,.3)}.selection\:bg-violet-400\/25::selection{background-color:rgba(167,139,250,.25)}.selection\:bg-violet-500\/30::selection{background-color:rgba(139,92,246,.3)}.last\:border-0:last-child{border-width:0}.hover\:border-violet-400\/25:hover{border-color:rgba(167,139,250,.25)}.hover\:border-white\/15:hover{border-color:hsla(0,0%,100%,.15)}.hover\:border-white\/20:hover{border-color:hsla(0,0%,100%,.2)}.hover\:bg-black\/45:hover{background-color:rgba(0,0,0,.45)}.hover\:bg-cyan-500\/15:hover{background-color:rgba(6,182,212,.15)}.hover\:bg-cyan-500\/25:hover{background-color:rgba(6,182,212,.25)}.hover\:bg-emerald-500\/20:hover{background-color:rgba(16,185,129,.2)}.hover\:bg-slate-100:hover{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.hover\:bg-slate-200\/60:hover{background-color:rgba(226,232,240,.6)}.hover\:bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.hover\:bg-violet-500\/25:hover{background-color:rgba(139,92,246,.25)}.hover\:bg-violet-500\/30:hover{background-color:rgba(139,92,246,.3)}.hover\:bg-white\/10:hover{background-color:hsla(0,0%,100%,.1)}.hover\:bg-white\/5:hover{background-color:hsla(0,0%,100%,.05)}.hover\:bg-white\/\[0\.04\]:hover{background-color:hsla(0,0%,100%,.04)}.hover\:bg-white\/\[0\.07\]:hover{background-color:hsla(0,0%,100%,.07)}.hover\:bg-white\/\[0\.08\]:hover{background-color:hsla(0,0%,100%,.08)}.hover\:bg-white\/\[0\.1\]:hover{background-color:hsla(0,0%,100%,.1)}.hover\:text-amber-300:hover{--tw-text-opacity:1;color:rgb(252 211 77/var(--tw-text-opacity,1))}.hover\:text-cyan-200:hover{--tw-text-opacity:1;color:rgb(165 243 252/var(--tw-text-opacity,1))}.hover\:text-rose-200:hover{--tw-text-opacity:1;color:rgb(254 205 211/var(--tw-text-opacity,1))}.hover\:text-slate-900:hover{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.hover\:text-zinc-200:hover{--tw-text-opacity:1;color:rgb(228 228 231/var(--tw-text-opacity,1))}.hover\:text-zinc-300:hover{--tw-text-opacity:1;color:rgb(212 212 216/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:ring-violet-400\/50:hover{--tw-ring-color:rgba(167,139,250,.5)}.hover\:brightness-110:hover{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-emerald-500\/50:focus-visible{--tw-ring-color:rgba(16,185,129,.5)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}@media (min-width:640px){.sm\:block{display:block}.sm\:inline{display:inline}.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:flex-wrap{flex-wrap:wrap}.sm\:flex-nowrap{flex-wrap:nowrap}.sm\:items-start{align-items:flex-start}.sm\:items-center{align-items:center}.sm\:justify-center{justify-content:center}.sm\:justify-between{justify-content:space-between}.sm\:gap-2{gap:.5rem}.sm\:px-3{padding-left:.75rem;padding-right:.75rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-4xl{font-size:2.25rem;line-height:2.5rem}}@media (min-width:768px){.md\:bottom-6{bottom:1.5rem}.md\:hidden{display:none}.md\:h-72{height:18rem}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:1024px){.lg\:col-span-2{grid-column:span 2/span 2}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:flex-row{flex-direction:row}.lg\:items-start{align-items:flex-start}.lg\:items-end{align-items:flex-end}.lg\:justify-between{justify-content:space-between}.lg\:px-10{padding-left:2.5rem;padding-right:2.5rem}.lg\:px-8{padding-left:2rem;padding-right:2rem}.lg\:py-8{padding-top:2rem;padding-bottom:2rem}.lg\:text-xl{font-size:1.25rem;line-height:1.75rem}}@media (min-width:1280px){.xl\:col-span-12{grid-column:span 12/span 12}.xl\:col-span-4{grid-column:span 4/span 4}.xl\:col-span-8{grid-column:span 8/span 8}.xl\:max-h-\[min\(24rem\2c 50vh\)\]{max-height:min(24rem,50vh)}.xl\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:grid-cols-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:grid-cols-\[0\.95fr\2c 1\.05fr\]{grid-template-columns:.95fr 1.05fr}.xl\:grid-cols-\[1\.1fr_0\.9fr\]{grid-template-columns:1.1fr .9fr}.xl\:grid-cols-\[18rem\2c 1fr\]{grid-template-columns:18rem 1fr}}.\[\&\:\:-webkit-scrollbar\]\:hidden::-webkit-scrollbar{display:none}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:border-cyan-600\/25{border-color:rgba(8,145,178,.25)}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:border-slate-200\/60{border-color:rgba(226,232,240,.6)}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:bg-white\/90{background-color:hsla(0,0%,100%,.9)}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:bg-white\/95{background-color:hsla(0,0%,100%,.95)}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:text-cyan-700{--tw-text-opacity:1;color:rgb(14 116 144/var(--tw-text-opacity,1))}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:text-cyan-950{--tw-text-opacity:1;color:rgb(8 51 68/var(--tw-text-opacity,1))}html[data-theme=light] .\[html\[data-theme\=light\]_\&\]\:text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))} \ No newline at end of file diff --git a/d2ypp2/web-console/out/_next/static/DBO2lufGEkC0vKztt3KO1/_buildManifest.js b/d2ypp2/web-console/out/_next/static/gGPi9R7eKZcpHz_wmmWrF/_buildManifest.js similarity index 100% rename from d2ypp2/web-console/out/_next/static/DBO2lufGEkC0vKztt3KO1/_buildManifest.js rename to d2ypp2/web-console/out/_next/static/gGPi9R7eKZcpHz_wmmWrF/_buildManifest.js diff --git a/d2ypp2/web-console/out/_next/static/DBO2lufGEkC0vKztt3KO1/_ssgManifest.js b/d2ypp2/web-console/out/_next/static/gGPi9R7eKZcpHz_wmmWrF/_ssgManifest.js similarity index 100% rename from d2ypp2/web-console/out/_next/static/DBO2lufGEkC0vKztt3KO1/_ssgManifest.js rename to d2ypp2/web-console/out/_next/static/gGPi9R7eKZcpHz_wmmWrF/_ssgManifest.js diff --git a/d2ypp2/web-console/out/android.html b/d2ypp2/web-console/out/android.html index 456197e..12ef3c1 100644 --- a/d2ypp2/web-console/out/android.html +++ b/d2ypp2/web-console/out/android.html @@ -1 +1 @@ -无人直播系统 · live.local
返回门户首页无人直播 · 本页需与 API 同域(推荐 live.local:8001)

控制平面 · ARM Linux 开发板

无人直播控制中心

ShellCrash 负责代理上网;本机 FFmpeg 处理推流或 HDMI;Neko(Docker Chromium)或本机 Chromium 负责浏览器侧;开发板通过 USB 双头线 ADB 控制 AOSP。各模块独立,可分别启停。

live.local · unknown · unknown
正在连接控制台...
\ No newline at end of file +无人直播系统 · live.local
返回门户首页无人直播 · 本页需与 API 同域(推荐 live.local:8001)

控制平面 · ARM Linux 开发板

无人直播控制中心

ShellCrash 负责代理上网;本机 FFmpeg 处理推流或 HDMI;Neko(Docker Chromium)或本机 Chromium 负责浏览器侧;开发板通过 USB 双头线 ADB 控制 AOSP。各模块独立,可分别启停。

live.local · unknown · unknown
正在连接控制台...
\ No newline at end of file diff --git a/d2ypp2/web-console/out/android.txt b/d2ypp2/web-console/out/android.txt index a338d8a..3374043 100644 --- a/d2ypp2/web-console/out/android.txt +++ b/d2ypp2/web-console/out/android.txt @@ -1,7 +1,7 @@ 2:I[9107,[],"ClientPageRoot"] -3:I[3946,["500","static/chunks/500-ea37cc8de90441f7.js","246","static/chunks/246-b5d14933cf331e85.js","357","static/chunks/app/android/page-84550dabda18d658.js"],"default",1] +3:I[3946,["500","static/chunks/500-ea37cc8de90441f7.js","246","static/chunks/246-316dc23346e75be8.js","357","static/chunks/app/android/page-69ff6e74a15b80d9.js"],"default",1] 4:I[4707,[],""] 5:I[6423,[],""] -0:["DBO2lufGEkC0vKztt3KO1",[[["",{"children":["android",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],["",{"children":["android",{"children":["__PAGE__",{},[["$L1",["$","$L2",null,{"props":{"params":{},"searchParams":{}},"Component":"$3"}],null],null],null]},[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","android","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/693f7950f3222bce.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"zh-CN","data-theme":"dark","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_1e4310 __variable_c3aa02 font-sans antialiased","children":[["$","div",null,{"className":"app-bg-layer","aria-hidden":true}],["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]]}]}]],null],null],["$L6",null]]]] -6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"无人直播系统 · live.local"}],["$","meta","3",{"name":"description","content":"Linux ARM/x86 一键部署的无人直播控制台:YouTube 转播、TikTok HDMI、SRS、Neko 与系统服务"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]] +0:["gGPi9R7eKZcpHz_wmmWrF",[[["",{"children":["android",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],["",{"children":["android",{"children":["__PAGE__",{},[["$L1",["$","$L2",null,{"props":{"params":{},"searchParams":{}},"Component":"$3"}],null],null],null]},[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","android","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/f7eb93299e7a4c6e.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"zh-CN","data-theme":"dark","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_1e4310 __variable_c3aa02 font-sans antialiased","children":[["$","div",null,{"className":"app-bg-layer","aria-hidden":true}],["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]]}]}]],null],null],["$L6",null]]]] +6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"无人直播系统 · live.local"}],["$","meta","3",{"name":"description","content":"Linux ARM/x86 一键部署的无人直播控制台:YouTube 转播、TikTok HDMI、SRS、Neko 与系统服务"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}]] 1:null diff --git a/d2ypp2/web-console/out/console.html b/d2ypp2/web-console/out/console.html index a0c55a0..3d150f6 100644 --- a/d2ypp2/web-console/out/console.html +++ b/d2ypp2/web-console/out/console.html @@ -1 +1 @@ -无人直播系统 · live.local
返回门户首页无人直播 · 本页需与 API 同域(推荐 live.local:8001)

控制平面 · ARM Linux 开发板

无人直播控制中心

ShellCrash 负责代理上网;本机 FFmpeg 处理推流或 HDMI;Neko(Docker Chromium)或本机 Chromium 负责浏览器侧;开发板通过 USB 双头线 ADB 控制 AOSP。各模块独立,可分别启停。

live.local · unknown · unknown
正在连接控制台...
\ No newline at end of file +无人直播系统 · live.local
返回门户首页无人直播 · 本页需与 API 同域(推荐 live.local:8001)

控制平面 · ARM Linux 开发板

无人直播控制中心

ShellCrash 负责代理上网;本机 FFmpeg 处理推流或 HDMI;Neko(Docker Chromium)或本机 Chromium 负责浏览器侧;开发板通过 USB 双头线 ADB 控制 AOSP。各模块独立,可分别启停。

live.local · unknown · unknown
正在连接控制台...
\ No newline at end of file diff --git a/d2ypp2/web-console/out/console.txt b/d2ypp2/web-console/out/console.txt index db49f0c..a3e665c 100644 --- a/d2ypp2/web-console/out/console.txt +++ b/d2ypp2/web-console/out/console.txt @@ -1,7 +1,7 @@ 2:I[9107,[],"ClientPageRoot"] -3:I[6367,["500","static/chunks/500-ea37cc8de90441f7.js","246","static/chunks/246-b5d14933cf331e85.js","443","static/chunks/app/console/page-75d851a154677dbc.js"],"default",1] +3:I[6367,["500","static/chunks/500-ea37cc8de90441f7.js","246","static/chunks/246-316dc23346e75be8.js","443","static/chunks/app/console/page-db00fd3a990c6a05.js"],"default",1] 4:I[4707,[],""] 5:I[6423,[],""] -0:["DBO2lufGEkC0vKztt3KO1",[[["",{"children":["console",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],["",{"children":["console",{"children":["__PAGE__",{},[["$L1",["$","$L2",null,{"props":{"params":{},"searchParams":{}},"Component":"$3"}],null],null],null]},[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","console","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/693f7950f3222bce.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"zh-CN","data-theme":"dark","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_1e4310 __variable_c3aa02 font-sans antialiased","children":[["$","div",null,{"className":"app-bg-layer","aria-hidden":true}],["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]]}]}]],null],null],["$L6",null]]]] -6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"无人直播系统 · live.local"}],["$","meta","3",{"name":"description","content":"Linux ARM/x86 一键部署的无人直播控制台:YouTube 转播、TikTok HDMI、SRS、Neko 与系统服务"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]] +0:["gGPi9R7eKZcpHz_wmmWrF",[[["",{"children":["console",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],["",{"children":["console",{"children":["__PAGE__",{},[["$L1",["$","$L2",null,{"props":{"params":{},"searchParams":{}},"Component":"$3"}],null],null],null]},[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","console","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/f7eb93299e7a4c6e.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"zh-CN","data-theme":"dark","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_1e4310 __variable_c3aa02 font-sans antialiased","children":[["$","div",null,{"className":"app-bg-layer","aria-hidden":true}],["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]]}]}]],null],null],["$L6",null]]]] +6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"无人直播系统 · live.local"}],["$","meta","3",{"name":"description","content":"Linux ARM/x86 一键部署的无人直播控制台:YouTube 转播、TikTok HDMI、SRS、Neko 与系统服务"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}]] 1:null diff --git a/d2ypp2/web-console/out/index.html b/d2ypp2/web-console/out/index.html index e99fb94..cf5d8a1 100644 --- a/d2ypp2/web-console/out/index.html +++ b/d2ypp2/web-console/out/index.html @@ -1 +1 @@ -无人直播系统 · live.local

总览

live.local · 夜间 · 前台自动刷新 · 最后同步 未同步

直播工作室 · 3D

CPU 1m

负载均值

内存

/ —

磁盘可用

/ —

服务在线

基础服务层

运行时间

自开机

直播进程

  • 暂无直播进程
\ No newline at end of file +无人直播系统 · live.local

总览

live.local · 夜间 · 前台自动刷新 · 最后同步 未同步

直播工作室 · 3D

CPU 1m

负载均值

内存

/ —

磁盘可用

/ —

服务在线

基础服务层

运行时间

自开机

直播进程

  • 暂无直播进程
\ No newline at end of file diff --git a/d2ypp2/web-console/out/index.txt b/d2ypp2/web-console/out/index.txt index 46f0843..bb0a6df 100644 --- a/d2ypp2/web-console/out/index.txt +++ b/d2ypp2/web-console/out/index.txt @@ -1,7 +1,7 @@ 2:I[9107,[],"ClientPageRoot"] -3:I[1499,["500","static/chunks/500-ea37cc8de90441f7.js","719","static/chunks/719-4dbe9dca4cff8afd.js","246","static/chunks/246-b5d14933cf331e85.js","931","static/chunks/app/page-4d705a6f49d462b3.js"],"default",1] +3:I[1499,["500","static/chunks/500-ea37cc8de90441f7.js","719","static/chunks/719-4dbe9dca4cff8afd.js","246","static/chunks/246-316dc23346e75be8.js","931","static/chunks/app/page-abd70046db11ff5c.js"],"default",1] 4:I[4707,[],""] 5:I[6423,[],""] -0:["DBO2lufGEkC0vKztt3KO1",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},[["$L1",["$","$L2",null,{"props":{"params":{},"searchParams":{}},"Component":"$3"}],null],null],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/693f7950f3222bce.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"zh-CN","data-theme":"dark","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_1e4310 __variable_c3aa02 font-sans antialiased","children":[["$","div",null,{"className":"app-bg-layer","aria-hidden":true}],["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]]}]}]],null],null],["$L6",null]]]] -6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"无人直播系统 · live.local"}],["$","meta","3",{"name":"description","content":"Linux ARM/x86 一键部署的无人直播控制台:YouTube 转播、TikTok HDMI、SRS、Neko 与系统服务"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]] +0:["gGPi9R7eKZcpHz_wmmWrF",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},[["$L1",["$","$L2",null,{"props":{"params":{},"searchParams":{}},"Component":"$3"}],null],null],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/f7eb93299e7a4c6e.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"zh-CN","data-theme":"dark","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_1e4310 __variable_c3aa02 font-sans antialiased","children":[["$","div",null,{"className":"app-bg-layer","aria-hidden":true}],["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]]}]}]],null],null],["$L6",null]]]] +6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"无人直播系统 · live.local"}],["$","meta","3",{"name":"description","content":"Linux ARM/x86 一键部署的无人直播控制台:YouTube 转播、TikTok HDMI、SRS、Neko 与系统服务"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}]] 1:null diff --git a/d2ypp2/web-console/out/shellcrash.html b/d2ypp2/web-console/out/shellcrash.html index b60f739..f4cf9a8 100644 --- a/d2ypp2/web-console/out/shellcrash.html +++ b/d2ypp2/web-console/out/shellcrash.html @@ -1 +1 @@ -无人直播系统 · live.local
返回门户首页无人直播 · 本页需与 API 同域(推荐 live.local:8001)

控制平面 · ARM Linux 开发板

无人直播控制中心

ShellCrash 负责代理上网;本机 FFmpeg 处理推流或 HDMI;Neko(Docker Chromium)或本机 Chromium 负责浏览器侧;开发板通过 USB 双头线 ADB 控制 AOSP。各模块独立,可分别启停。

live.local · unknown · unknown
正在连接控制台...
\ No newline at end of file +无人直播系统 · live.local
返回门户首页无人直播 · 本页需与 API 同域(推荐 live.local:8001)

控制平面 · ARM Linux 开发板

无人直播控制中心

ShellCrash 负责代理上网;本机 FFmpeg 处理推流或 HDMI;Neko(Docker Chromium)或本机 Chromium 负责浏览器侧;开发板通过 USB 双头线 ADB 控制 AOSP。各模块独立,可分别启停。

live.local · unknown · unknown
正在连接控制台...
\ No newline at end of file diff --git a/d2ypp2/web-console/out/shellcrash.txt b/d2ypp2/web-console/out/shellcrash.txt index c0e4ac1..8115834 100644 --- a/d2ypp2/web-console/out/shellcrash.txt +++ b/d2ypp2/web-console/out/shellcrash.txt @@ -1,7 +1,7 @@ 2:I[9107,[],"ClientPageRoot"] -3:I[3398,["500","static/chunks/500-ea37cc8de90441f7.js","246","static/chunks/246-b5d14933cf331e85.js","6","static/chunks/app/shellcrash/page-3d8615ae919b9119.js"],"default",1] +3:I[3398,["500","static/chunks/500-ea37cc8de90441f7.js","246","static/chunks/246-316dc23346e75be8.js","6","static/chunks/app/shellcrash/page-766863ba520c08ee.js"],"default",1] 4:I[4707,[],""] 5:I[6423,[],""] -0:["DBO2lufGEkC0vKztt3KO1",[[["",{"children":["shellcrash",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],["",{"children":["shellcrash",{"children":["__PAGE__",{},[["$L1",["$","$L2",null,{"props":{"params":{},"searchParams":{}},"Component":"$3"}],null],null],null]},[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","shellcrash","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/693f7950f3222bce.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"zh-CN","data-theme":"dark","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_1e4310 __variable_c3aa02 font-sans antialiased","children":[["$","div",null,{"className":"app-bg-layer","aria-hidden":true}],["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]]}]}]],null],null],["$L6",null]]]] -6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"无人直播系统 · live.local"}],["$","meta","3",{"name":"description","content":"Linux ARM/x86 一键部署的无人直播控制台:YouTube 转播、TikTok HDMI、SRS、Neko 与系统服务"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]] +0:["gGPi9R7eKZcpHz_wmmWrF",[[["",{"children":["shellcrash",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],["",{"children":["shellcrash",{"children":["__PAGE__",{},[["$L1",["$","$L2",null,{"props":{"params":{},"searchParams":{}},"Component":"$3"}],null],null],null]},[null,["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children","shellcrash","children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined"}]],null]},[[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/f7eb93299e7a4c6e.css","precedence":"next","crossOrigin":"$undefined"}]],["$","html",null,{"lang":"zh-CN","data-theme":"dark","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_1e4310 __variable_c3aa02 font-sans antialiased","children":[["$","div",null,{"className":"app-bg-layer","aria-hidden":true}],["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[]}]]}]}]],null],null],["$L6",null]]]] +6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"无人直播系统 · live.local"}],["$","meta","3",{"name":"description","content":"Linux ARM/x86 一键部署的无人直播控制台:YouTube 转播、TikTok HDMI、SRS、Neko 与系统服务"}],["$","link","4",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}]] 1:null diff --git a/d2ypp2/web.py b/d2ypp2/web.py index 9389002..2913298 100644 --- a/d2ypp2/web.py +++ b/d2ypp2/web.py @@ -38,6 +38,9 @@ from src.android_control import ( from src.scrcpy_stream import cleanup_scrcpy_session, open_scrcpy_h264_stream, scrcpy_stream_info from src.scrcpy_vendor import ensure_scrcpy_jar from src.control_plane import ( + SHELLCRASH_DEFAULT_NODE, + SHELLCRASH_DEFAULT_PROFILE, + apply_shellcrash_profile, deployment_report, delete_root_file, list_root_files, @@ -617,6 +620,11 @@ class ServiceActionPostBody(BaseModel): action: str = Field(..., pattern="^(install|start|stop|restart|status|uninstall|upgrade)$") +class ShellCrashApplyProfileBody(BaseModel): + path: str = Field(default=SHELLCRASH_DEFAULT_PROFILE, min_length=1, max_length=240) + target_node: str = Field(default=SHELLCRASH_DEFAULT_NODE, min_length=1, max_length=200) + + class ManagedFileBody(BaseModel): root: str = Field(..., min_length=1, max_length=64) path: str = Field(..., min_length=1, max_length=240) @@ -1024,6 +1032,18 @@ async def run_service_action_post(body: ServiceActionPostBody): return JSONResponse({"error": str(exc)}, status_code=400) +@app.post("/shellcrash/apply_profile") +async def post_shellcrash_apply_profile(body: ShellCrashApplyProfileBody): + try: + return await apply_shellcrash_profile(body.path.strip(), body.target_node.strip()) + except FileNotFoundError: + return JSONResponse({"error": f"ShellCrash YAML not found: {body.path}"}, status_code=404) + except (PermissionError, ValueError) as exc: + return JSONResponse({"error": str(exc)}, status_code=400) + except RuntimeError as exc: + return JSONResponse({"error": str(exc)}, status_code=500) + + @app.get("/managed_roots") async def get_managed_roots(): return {"roots": list_root_summaries()}