diff --git a/d2ypp2/scripts/linux/lib/common.sh b/d2ypp2/scripts/linux/lib/common.sh index 40857df..4d22ed1 100755 --- a/d2ypp2/scripts/linux/lib/common.sh +++ b/d2ypp2/scripts/linux/lib/common.sh @@ -776,6 +776,7 @@ ensure_runtime_dirs_owned_by_live() { backup_config \ .pm2 \ .process_runner \ + web-console \ web-console/out \ web-console/.next \ web-console/node_modules \ @@ -784,6 +785,7 @@ ensure_runtime_dirs_owned_by_live() { path="$ROOT_DIR/$rel" mkdir -p "$path" chown -R live:live "$path" 2>/dev/null || true + chmod -R u+rwX,g+rwX "$path" 2>/dev/null || true done } @@ -952,11 +954,14 @@ StartLimitIntervalSec=0 [Service] User=live +PermissionsStartOnly=true WorkingDirectory=$ROOT_DIR Environment=HOST=0.0.0.0 Environment=PORT=$PORT Environment=LIVE_NOFILE_SOFT=$LIVE_NOFILE_SOFT LimitNOFILE=$LIVE_NOFILE_SOFT +ExecStartPre=/usr/bin/install -d -o live -g live $ROOT_DIR/config $ROOT_DIR/logs $ROOT_DIR/downloads $ROOT_DIR/backup $ROOT_DIR/backup_config $ROOT_DIR/.pm2 $ROOT_DIR/.process_runner $ROOT_DIR/web-console $ROOT_DIR/services/neko/data +ExecStartPre=/bin/chown -R live:live $ROOT_DIR/config $ROOT_DIR/logs $ROOT_DIR/downloads $ROOT_DIR/backup $ROOT_DIR/backup_config $ROOT_DIR/.pm2 $ROOT_DIR/.process_runner $ROOT_DIR/web-console $ROOT_DIR/services/neko/data ExecStart=$ROOT_DIR/start.sh Restart=always RestartSec=5 diff --git a/d2ypp2/src/hub_routes.py b/d2ypp2/src/hub_routes.py index 5fa36f6..bc568d4 100644 --- a/d2ypp2/src/hub_routes.py +++ b/d2ypp2/src/hub_routes.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio import json +import sqlite3 import time from pathlib import Path from typing import Any, Callable, Optional @@ -276,6 +277,11 @@ async def hub_youtube_pro_channels_write(body: YoutubeProChannelsBody) -> dict[s set_youtube_pro_channels(body.channels) except ValueError as exc: raise HTTPException(status_code=400, detail=str(exc)) from exc + except sqlite3.Error as exc: + raise HTTPException( + status_code=500, + detail=f"多频道状态数据库写入失败: {exc}; 请确认 config 目录归 live 用户可写", + ) from exc capacity = await asyncio.to_thread(ensure_neko_capacity_for_youtube_channels, _repo_root, body.channels) return {"message": "ok", "neko": capacity} diff --git a/d2ypp2/tests/test_web_dynamic_processes.py b/d2ypp2/tests/test_web_dynamic_processes.py index b381eb9..6404ac8 100644 --- a/d2ypp2/tests/test_web_dynamic_processes.py +++ b/d2ypp2/tests/test_web_dynamic_processes.py @@ -3,6 +3,7 @@ from __future__ import annotations import ast import asyncio import json +import sqlite3 import tempfile import unittest from pathlib import Path @@ -19,6 +20,15 @@ class _JsonRequest: return self._payload +class _ReadRequest: + headers: dict[str, str] = {} + + class _Client: + host = "127.0.0.1" + + client = _Client() + + def _json_body(resp) -> dict[str, object]: # noqa: ANN001 return json.loads(resp.body) @@ -180,7 +190,7 @@ class WebDynamicProcessesTests(unittest.TestCase): with patch("web.allows_url_config", return_value=True): with patch("web.managed_url_config_relpath", return_value=rel): with patch("web._sync_youtube_pro_runtime_files", side_effect=AssertionError("unexpected resync")): - payload = asyncio.run(web.get_url_config("youtube")) + payload = asyncio.run(web.get_url_config(_ReadRequest(), process="youtube")) self.assertEqual(_json_body(payload)["content"], "https://live.douyin.com/new\n") self.assertEqual(payload.headers.get("cache-control"), "no-store, max-age=0, must-revalidate") @@ -204,6 +214,26 @@ class WebDynamicProcessesTests(unittest.TestCase): self.assertEqual(_json_body(payload)["message"], "配置保存成功") self.assertEqual(captured[-1][0]["urlLines"], "https://live.douyin.com/fresh\n") + def test_save_url_config_returns_json_when_channel_store_readonly(self) -> None: + channels = [{"id": "lane1", "name": "Lane 1", "pm2Name": "youtube2__lane1", "urlLines": "old\n"}] + + with patch("web.allows_url_config", return_value=True): + with patch("web.managed_url_config_relpath", return_value="URL_config.youtube2__lane1.ini"): + with patch("web.governed_save_managed_file"): + with patch("web.get_youtube_pro_channels", return_value=channels): + with patch("web.set_youtube_pro_channels", side_effect=sqlite3.OperationalError("attempt to write a readonly database")): + payload = asyncio.run( + web.save_url_config( + _JsonRequest({"content": "https://live.douyin.com/fresh\n"}), + process="youtube2__lane1", + ) + ) + + body = _json_body(payload) + self.assertEqual(payload.status_code, 500) + self.assertIn("多频道状态数据库写入失败", body["error"]) + self.assertIn("config", body["error"]) + def test_save_config_updates_matching_youtube_pro_channel_stream_key(self) -> None: captured: list[list[dict[str, object]]] = [] channels = [{"id": "lane1", "name": "Lane 1", "pm2Name": "youtube2__lane1", "streamKey": "old-key"}] diff --git a/d2ypp2/web-console/components/live-product/LiveYoutubeUnmannedView.tsx b/d2ypp2/web-console/components/live-product/LiveYoutubeUnmannedView.tsx index 284c64c..6aa5ec2 100644 --- a/d2ypp2/web-console/components/live-product/LiveYoutubeUnmannedView.tsx +++ b/d2ypp2/web-console/components/live-product/LiveYoutubeUnmannedView.tsx @@ -370,6 +370,7 @@ export function LiveYoutubeUnmannedView({ const urlListDirtyRef = useRef(false); const singleUrlDraftRef = useRef(urlConfig); const proUrlDraftRef = useRef(proUrlDraft); + const channelsRef = useRef([]); const currentProcRef = useRef(currentProc); const urlRequestSeqRef = useRef(0); const ytIniRequestSeqRef = useRef(0); @@ -403,6 +404,27 @@ export function LiveYoutubeUnmannedView({ proUrlDraftRef.current = proUrlDraft; }, [proUrlDraft]); + useEffect(() => { + channelsRef.current = channels; + }, [channels]); + + const updateActiveChannelUrlLines = useCallback((channelId: string, nextUrlLines: string) => { + if (!channelId) return; + setChannels((prev) => { + let changed = false; + const next = prev.map((row) => { + if (row.id !== channelId) return row; + if ((row.urlLines ?? "") === nextUrlLines) return row; + changed = true; + return { ...row, urlLines: nextUrlLines }; + }); + if (!changed) return prev; + channelsRef.current = next; + saveYoutubeProChannels(next); + return next; + }); + }, []); + const pullUrlConfigFromServer = useCallback(async () => { const targetProc = currentProcRef.current.trim(); if (!targetProc) return; @@ -418,24 +440,18 @@ export function LiveYoutubeUnmannedView({ if (urlListDirtyRef.current) return; if (mode === "single") applySingleUrlDraft(c); else { - const localDraft = channels.find((row) => row.id === activeCh)?.urlLines ?? ""; + const localDraft = channelsRef.current.find((row) => row.id === activeCh)?.urlLines ?? ""; if (shouldPreserveLocalUrlDraft(localDraft, c)) { applyProUrlDraft(localDraft); return; } applyProUrlDraft(c); - if (activeCh) { - setChannels((prev) => { - const next = prev.map((x) => (x.id === activeCh ? { ...x, urlLines: c } : x)); - saveYoutubeProChannels(next); - return next; - }); - } + updateActiveChannelUrlLines(activeCh, c); } } catch { /* ignore */ } - }, [activeCh, applyProUrlDraft, applySingleUrlDraft, channels, fetchJson, mode]); + }, [activeCh, applyProUrlDraft, applySingleUrlDraft, fetchJson, mode, updateActiveChannelUrlLines]); useEffect(() => { if (!currentProc || !urlAutoRefresh) return; @@ -467,27 +483,21 @@ export function LiveYoutubeUnmannedView({ } if (mode === "single") applySingleUrlDraft(c); else { - const localDraft = channels.find((row) => row.id === activeCh)?.urlLines ?? ""; + const localDraft = channelsRef.current.find((row) => row.id === activeCh)?.urlLines ?? ""; if (shouldPreserveLocalUrlDraft(localDraft, c)) { applyProUrlDraft(localDraft); setUrlFetchNote(t("服务器暂无已保存 URL,已保留本地草稿", "Server has no saved URLs, kept the local draft")); return; } applyProUrlDraft(c); - if (activeCh) { - setChannels((prev) => { - const next = prev.map((x) => (x.id === activeCh ? { ...x, urlLines: c } : x)); - saveYoutubeProChannels(next); - return next; - }); - } + updateActiveChannelUrlLines(activeCh, c); } setUrlFetchNote(t("已从服务器读取 URL_config", "Reloaded URL_config from server")); } catch (e) { if (requestId !== urlRequestSeqRef.current || targetProc !== currentProcRef.current.trim()) return; setUrlFetchNote((e as Error).message); } finally { - if (requestId === urlRequestSeqRef.current && targetProc === currentProcRef.current.trim()) { + if (requestId === urlRequestSeqRef.current) { setUrlReloading(false); } } @@ -512,6 +522,7 @@ export function LiveYoutubeUnmannedView({ try { const remote = await fetchYoutubeProChannelsRemote(fetchJson); if (remote.fetched && remote.channels.length && !cancelled) { + channelsRef.current = remote.channels; setChannels(remote.channels); saveYoutubeProChannels(remote.channels); return; @@ -537,6 +548,7 @@ export function LiveYoutubeUnmannedView({ }, ]; })(); + channelsRef.current = initial; setChannels(initial); if (!list.length) saveYoutubeProChannels(initial); })(); @@ -574,6 +586,7 @@ export function LiveYoutubeUnmannedView({ }, [currentProc, currentProcLooksYoutube, mode, preferredSingleProc, setCurrentProc]); const applyChannelsLocal = useCallback((next: YoutubeProChannel[]) => { + channelsRef.current = next; setChannels(next); saveYoutubeProChannels(next); }, []); @@ -786,7 +799,7 @@ export function LiveYoutubeUnmannedView({ if (requestId !== ytIniRequestSeqRef.current || targetProc !== currentProcRef.current.trim()) return; setYtIniStatus((e as Error).message); } finally { - if (requestId === ytIniRequestSeqRef.current && targetProc === currentProcRef.current.trim()) { + if (requestId === ytIniRequestSeqRef.current) { setYtIniLoading(false); } } diff --git a/d2ypp2/web-console/out/.build-stamp.json b/d2ypp2/web-console/out/.build-stamp.json index f885f59..8636e6c 100644 --- a/d2ypp2/web-console/out/.build-stamp.json +++ b/d2ypp2/web-console/out/.build-stamp.json @@ -1,6 +1,6 @@ { - "built_at": 1779182151.9524395, - "source_mtime": 1779180451.7832174, + "built_at": 1779184553.6568675, + "source_mtime": 1779183169.5914183, "toolchain": "local", "node_major": 20 } \ No newline at end of file diff --git a/d2ypp2/web-console/out/404.html b/d2ypp2/web-console/out/404.html index fcdca3c..0b0ddfe 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/UmN0Ou_Iv2TWI4xcHvY2X/_buildManifest.js b/d2ypp2/web-console/out/_next/static/Bqx_FrY3OzE8SRa_XO6pv/_buildManifest.js similarity index 100% rename from d2ypp2/web-console/out/_next/static/UmN0Ou_Iv2TWI4xcHvY2X/_buildManifest.js rename to d2ypp2/web-console/out/_next/static/Bqx_FrY3OzE8SRa_XO6pv/_buildManifest.js diff --git a/d2ypp2/web-console/out/_next/static/UmN0Ou_Iv2TWI4xcHvY2X/_ssgManifest.js b/d2ypp2/web-console/out/_next/static/Bqx_FrY3OzE8SRa_XO6pv/_ssgManifest.js similarity index 100% rename from d2ypp2/web-console/out/_next/static/UmN0Ou_Iv2TWI4xcHvY2X/_ssgManifest.js rename to d2ypp2/web-console/out/_next/static/Bqx_FrY3OzE8SRa_XO6pv/_ssgManifest.js diff --git a/d2ypp2/web-console/out/_next/static/chunks/app/page-3c5cf076d3a5e7c5.js b/d2ypp2/web-console/out/_next/static/chunks/app/page-a84b3c1d3686233c.js similarity index 53% rename from d2ypp2/web-console/out/_next/static/chunks/app/page-3c5cf076d3a5e7c5.js rename to d2ypp2/web-console/out/_next/static/chunks/app/page-a84b3c1d3686233c.js index 5fccce4..5c8d6ea 100644 --- a/d2ypp2/web-console/out/_next/static/chunks/app/page-3c5cf076d3a5e7c5.js +++ b/d2ypp2/web-console/out/_next/static/chunks/app/page-a84b3c1d3686233c.js @@ -1 +1 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{4578:function(e,t,s){Promise.resolve().then(s.bind(s,1499))},1499:function(e,t,s){"use strict";s.r(t),s.d(t,{default:function(){return e7}});var n=s(7437),l=s(6247),i=s(7586),r=s(4401),a=s(6137),o=s(4372),c=s(5901),d=s(3388),x=s(3420),u=s(8728),m=s(2023),h=s(407),p=s(6840),b=s(7226),g=s(5929),f=s(7945),v=s(1817),y=s(7168),w=s(4822),N=s(4428),j=s(1723),k=s(2926),z=s(7580),S=s(2489),_=s(2265);function C(e){let{tr:t}=e,l=(0,_.useRef)(null);return(0,_.useEffect)(()=>{let e;if(!l.current)return;let t=!1,n=0;return s.e(689).then(s.bind(s,1448)).then(s=>{if(t||!l.current)return;let i=l.current,r=Math.max(i.clientWidth,280),a=Math.max(i.clientHeight,200),o=new s.Scene,c=new s.PerspectiveCamera(48,r/a,.1,80);c.position.set(0,1.1,7.2);let d=new s.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 s.HemisphereLight(16762092,4482815,.85);o.add(x);let u=new s.DirectionalLight(16777215,.9);u.position.set(4,8,6),o.add(u);let m=new s.PointLight(8189439,.6,20);m.position.set(-3,2,-2),o.add(m);let h=new s.Group,p=new s.Mesh(new s.BoxGeometry(3.2,.35,2.2),new s.MeshStandardMaterial({color:2762048,metalness:.15,roughness:.55}));p.position.y=-.85,h.add(p);let b=new s.Mesh(new s.TorusGeometry(.72,.09,12,48),new s.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 s.Mesh(new s.ConeGeometry(.35,.5,3),new s.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 s.Mesh(new s.CylinderGeometry(.22,.28,.95,20),new s.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 s.Mesh(new s.SphereGeometry(.26,16,16),new s.MeshStandardMaterial({color:16657493,emissive:2229520,metalness:.2,roughness:.4}));v.position.set(1.05,.92,-.15),h.add(v);let y=new s.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 s.BufferAttribute(w,3));let N=new s.Points(y,new s.PointsMaterial({color:16777215,size:.06,transparent:!0,opacity:.7}));o.add(N),o.add(h);let j=performance.now(),k=()=>{if(t)return;n=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),s=Math.max(l.current.clientHeight,200);c.aspect=e/s,c.updateProjectionMatrix(),d.setSize(e,s)});z.observe(i),e=()=>{cancelAnimationFrame(n),z.disconnect(),d.dispose(),y.dispose(),d.domElement.parentNode===i&&i.removeChild(d.domElement)}}),()=>{t=!0,cancelAnimationFrame(n),null==e||e()}},[]),(0,n.jsxs)("div",{className:"flex h-full min-h-[14rem] flex-col",children:[(0,n.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,n.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=s(9170),P=s(2246),L=s(4286),M=s(4794),T=s(221),U=s(8867),E=s(8124),I=s(2101),D=s(3651),A=s(9985),Z=s(6362),O=s(3468),H=s(6443),B=s(5287),K=s(3276),F=s(9227),W=s(257),Y=s(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 s=new Uint8Array(e.length+t.length);return s.set(e,0),s.set(t,e.length),s}(this.buf,t),this.drainAvcc()}drainAvcc(){let e=this.buf,t=0;for(;t+4<=e.length;){var s;let n=e[s=t]<<24|e[s+1]<<16|e[s+2]<<8|e[s+3];if(n<=0||n>6291456){this.buf=new Uint8Array(e.subarray(t+1)),t=0;continue}if(t+4+n>e.length)break;let l=e.subarray(t+4,t+4+n);t+=4+n,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 s=new Uint8Array(4+e.length);new DataView(s.buffer).setUint32(0,e.length,!1),s.set(e,4);try{let e=new EncodedVideoChunk({type:5===t?"key":"delta",timestamp:this.ts,data:s});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 s=e.subarray(1),n=t.subarray(1),l=new Uint8Array(11+s.length+3+n.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++]=s.length>>8&255,l[i++]=255&s.length,l.set(s,i),i+=s.length,l[i++]=1,l[i++]=n.length>>8&255,l[i++]=255&n.length,l.set(n,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),s=new VideoDecoder({output:e=>{var t;let s=this.canvas.getContext("2d");if(!s){e.close();return}(this.canvas.width!==e.displayWidth||this.canvas.height!==e.displayHeight)&&(this.canvas.width=e.displayWidth,this.canvas.height=e.displayHeight),s.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 s.configure({codec:t,description:e,optimizeForLatency:!0}),this.decoder=s,this.configured=!0}catch(e){this.onDecodeError(e.message||String(e))}finally{this.configuring=!1}}}constructor(e,t,s){this.canvas=e,this.onDecodeError=t,this.onFrame=s,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,s){let n,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?(n=a.width,l=a.width/x,i=0,r=(a.height-l)/2):(l=a.height,n=a.height*x,i=(a.width-n)/2,r=0);let u=t-a.left-i,m=s-a.top-r;return u<0||m<0||u>n||m>l?null:{x:Math.max(0,Math.min(o-1,Math.round(u/n*o))),y:Math.max(0,Math.min(c-1,Math.round(m/l*c)))}}function X(e,t,s){let n,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?(n=a.width,l=a.width/x,i=0,r=(a.height-l)/2):(l=a.height,n=a.height*x,i=(a.width-n)/2,r=0);let u=t-a.left-i,m=s-a.top-r;return u<0||m<0||u>n||m>l?null:{x:Math.max(0,Math.min(o-1,Math.round(u/n*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 es(e,t){let s=t.startsWith("/")?t:"/".concat(t),n=(e||"").trim().replace(/\/$/,"");return n?"".concat(n).concat(s):s}function en(e){var t;let{t:s,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,en]=(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(es(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 n=[t,...er.filter(e=>e!==t)].slice(0,16);ea(n);try{window.localStorage.setItem(V,JSON.stringify(n))}catch(e){}p(s("已保存快捷地址","Saved quick address"))};(0,_.useEffect)(()=>{if(!r||!c){C(null);return}let e=!1;return(async()=>{try{let t=await (0,Y.N)("".concat(es(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)(es(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(s("当前浏览器不支持 WebCodecs H.264","WebCodecs H.264 not supported in this browser")),ec(!1);return}let n=eN.current;if(!n)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(n,e=>i("".concat(s("实时画面解码失败,已切回截图模式","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 s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1920,n=(function(e){let t=(e||"").trim();if(t)try{let e=new URL(t,window.location.href),s="https:"===e.protocol?"wss:":"ws:";return"".concat(s,"//").concat(e.host)}catch(e){}let s=void 0!==W&&W.env.NEXT_PUBLIC_API_URL?String(W.env.NEXT_PUBLIC_API_URL).trim():"";if(s)try{let e=new URL(s,window.location.href),t="https:"===e.protocol?"wss:":"ws:";return"".concat(t,"//").concat(e.host)}catch(e){}let n=window.location.port;if("3000"===n||"3001"===n){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(s)});return"".concat(n,"/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(s("实时画面无首帧,已切回截图模式","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(s("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(s("实时画面连接失败,已切回截图模式","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,s]),(0,_.useEffect)(()=>{r&&c&&(eS.current=0,f(e=>e+1))},[r,c]);let eI=async()=>{let e=L.trim();if(!e){p(s("填写 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":s("连接结果见日志","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,n=D.trim();if(!e||!n){p(s("填写配对 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:n})});p(l.message||(l.ok?s("配对成功后再点连接","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 n=X(t,e.clientX,e.clientY);if(!n)return;let l=Date.now(),i=ey.current;i&&l-i.t<320&&28>Math.abs(i.x-n.x)&&28>Math.abs(i.y-n.y)?(ey.current=null,await h("double_tap",{x:n.x,y:n.y}),p(s("双击","Double tap"))):(ey.current={t:l,x:n.x,y:n.y},await h("tap",{x:n.x,y:n.y})),eT()},eO=async e=>{if(e.preventDefault(),x||!c||!r)return;let t=ew.current;if(!t)return;let n=X(t,e.clientX,e.clientY);n&&(await h("long_press",{x:n.x,y:n.y,duration:720}),p(s("长按","Long press")),eT())},eH=async e=>{if(!R||x||!c||!r)return;let t=eN.current;if(!t)return;let n=q(t,e.clientX,e.clientY);if(!n)return;let l=Date.now(),i=ey.current;i&&l-i.t<320&&28>Math.abs(i.x-n.x)&&28>Math.abs(i.y-n.y)?(ey.current=null,await h("double_tap",{x:n.x,y:n.y}),p(s("双击","Double tap"))):(ey.current={t:l,x:n.x,y:n.y},await h("tap",{x:n.x,y:n.y})),eo||eT()},eB=async e=>{if(e.preventDefault(),x||!c||!r)return;let t=eN.current;if(!t)return;let n=q(t,e.clientX,e.clientY);n&&(await h("long_press",{x:n.x,y:n.y,duration:720}),p(s("长按","Long press")),eo||eT())};if(!c)return(0,n.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:s("宿主机未安装 adb,无法使用 Live 控制台。","adb is required for the Live console.")});let eK=Q(eP),eF=eK.Icon;return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.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,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-white/[0.06] pb-3",children:[(0,n.jsx)(A.Z,{className:"h-4 w-4 text-sky-400"}),(0,n.jsx)("h4",{className:"text-sm font-semibold text-white",children:s("链路管理","Link manager")}),(0,n.jsx)("span",{className:"text-[10px] text-zinc-500",children:s("USB / Redroid :5555 / 无线调试(先配对再连接)","USB \xb7 Redroid :5555 \xb7 wireless (pair then connect)")})]}),(0,n.jsxs)("div",{className:"mt-3 grid gap-3 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"space-y-2 rounded-xl border border-white/[0.06] bg-black/35 p-3",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"adb connect"}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.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,n.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,n.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:s("存书签","Pin")})]}),er.length?(0,n.jsx)("div",{className:"flex flex-wrap gap-1.5 pt-1",children:er.map(e=>(0,n.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,n.jsxs)("div",{className:"flex flex-wrap gap-2 pt-2",children:[(0,n.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:s("断开当前 TCP","Disconnect current")}),(0,n.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:s("断开全部 TCP","Disconnect all TCP")}),(0,n.jsxs)("button",{type:"button",disabled:el||x,onClick:()=>{b(),eT(),p(s("已刷新设备列表","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,n.jsx)(y.Z,{className:"h-3 w-3"}),"ADB list"]})]})]}),(0,n.jsxs)("div",{className:"space-y-2 rounded-xl border border-white/[0.06] bg-black/35 p-3",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"adb pair(无线调试)"}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.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,n.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,n.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=>en(e.target.value)}),(0,n.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,n.jsx)("p",{className:"text-[10px] leading-relaxed text-zinc-600",children:s("手机上「无线调试」会显示配对端口与 6 位码;配对成功后用上方 connect 连接 adb 显示的 IP:5555。","Use the pairing port + 6-digit code from Wireless debugging; then connect to the listed adb IP:5555.")})]})]})]}),(0,n.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,n.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,n.jsxs)("div",{className:"relative rounded-[1.35rem] border border-white/[0.06] bg-zinc-950/80 p-4 backdrop-blur-sm",children:[(0,n.jsxs)("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between",children:[(0,n.jsxs)("div",{className:"flex items-start gap-3",children:[(0,n.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,n.jsx)(m.Z,{className:"h-6 w-6 text-emerald-200"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"text-base font-semibold tracking-tight text-white",children:s("无人直播系统 \xb7 ADB 云控台","Unmanned Live System \xb7 ADB farm console")}),(0,n.jsxs)("p",{className:"mt-1 max-w-xl text-[11px] leading-relaxed text-zinc-500",children:[s("统一适配 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,n.jsx)("a",{href:et,target:"_blank",rel:"noreferrer",className:"text-emerald-300/90 underline-offset-2 hover:underline",children:"escrcpy"}),s(" / "," / "),(0,n.jsx)("a",{href:ee,target:"_blank",rel:"noreferrer",className:"text-emerald-300/90 underline-offset-2 hover:underline",children:"scrcpy"}),s(");无 jar 或关闭真流时用截图。","); PNG screenshot when jar missing or stream off.")]})]})]}),(0,n.jsxs)("div",{className:"flex shrink-0 flex-col gap-1.5 self-start sm:flex-row",children:[(0,n.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,n.jsx)(Z.Z,{className:"h-3.5 w-3.5 opacity-70"})]}),(0,n.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,n.jsx)(Z.Z,{className:"h-3.5 w-3.5 opacity-70"})]})]})]}),a.length>0?(0,n.jsxs)("div",{className:"mt-5",children:[(0,n.jsxs)("p",{className:"mb-2 flex items-center gap-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:[(0,n.jsx)(O.Z,{className:"h-3.5 w-3.5"}),s("设备矩阵","Device matrix")]}),(0,n.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,n.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,n.jsxs)("span",{className:"flex items-center gap-1.5 text-xs font-medium text-zinc-200",children:[(0,n.jsx)(d.Z,{className:"h-3.5 w-3.5 text-emerald-400/80"}),(0,n.jsx)("span",{className:"truncate",children:e.model||e.serial.slice(0,10)})]}),(0,n.jsx)("span",{className:"mt-0.5 truncate font-mono text-[9px] text-zinc-600",children:e.serial}),(0,n.jsxs)("div",{className:"mt-1 flex flex-wrap gap-1",children:[(0,n.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,n.jsx)(a,{className:"h-2.5 w-2.5"}),s(i.zh,i.en)]}),(0,n.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,n.jsxs)("div",{className:"mt-6 grid gap-6 xl:grid-cols-12",children:[(0,n.jsxs)("div",{className:"xl:col-span-8",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-white/[0.06] pb-3",children:[(0,n.jsx)("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:s("刷新间隔","Interval")}),$.map(e=>(0,n.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?s("手动","Manual"):"".concat(e,"ms")},e)),(0,n.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,n.jsx)(eF,{className:"h-3 w-3"}),"tcp"===eP?s("建议 ≥450ms","Suggest ≥450ms"):s("可试 280ms","Try 280ms")]}),(0,n.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,n.jsx)(y.Z,{className:"h-3 w-3 ".concat(N?"animate-spin":"")}),s("下一帧","Next frame")]}),(0,n.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,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-1.5 text-[10px] text-zinc-400",children:[(0,n.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/50",checked:R,onChange:e=>P(e.target.checked)}),(0,n.jsx)(H.Z,{className:"h-3 w-3"}),s("点按穿透","Tap-through")]}),(0,n.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:s("官方 scrcpy-server + WebSocket H.264","Official scrcpy-server + WebSocket H.264"),onClick:()=>{ec(e=>{let t=!e;return t?(ex(null),p(s("已开启实时画面(H.264 WebSocket)","Live H.264 WebSocket stream on"))):(r&&ex(r),p(s("已关闭实时画面(将使用截图)","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,n.jsx)(B.Z,{className:"h-3 w-3"}),eo?s("关闭真流","Stop WS"):s("实时画面","Live H.264")]})]}),eb&&!eb.server_jar?(0,n.jsxs)("p",{className:"mt-2 text-[10px] text-amber-200/80",children:[s("未检测到 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(s("期望版本","version")," ").concat(eb.server_version,")"):null]}):null,(0,n.jsx)("p",{className:"mt-2 text-[10px] text-zinc-600",children:s("快捷键(镜像区聚焦时):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,n.jsxs)("div",{className:"relative mx-auto mt-4 max-h-[min(78vh,720px)] min-h-[280px]",children:[r?(0,n.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 s={h:["key",{keycode:"3"}],b:["key",{keycode:"4"}],r:["key",{keycode:"187"}],w:["wake",void 0],m:["key",{keycode:"82"}]}[e.key.toLowerCase()];s&&(e.preventDefault(),(async()=>{await h(s[0],s[1]),eo||eT()})())},className:"relative flex justify-center outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/50",children:[(0,n.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,n.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,n.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,n.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(s("截图连续失败:检查 USB 授权 / 无线是否断开 / Redroid 端口","Screenshot failed repeatedly"))},onClick:eZ,onContextMenu:eO})]}),eu?(0,n.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,n.jsx)(B.Z,{className:"h-3 w-3"}),"SCRCPY\xb7WS"]}):v>0&&!eo?(0,n.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,n.jsx)(K.Z,{className:"h-3 w-3"}),"LIVE"]}):eo?null:(0,n.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,n.jsx)(F.Z,{className:"h-3 w-3"}),s("单帧","Still")]})]}):(0,n.jsx)("p",{className:"py-16 text-center text-sm text-zinc-600",children:s("请选择或连接设备","Pick or connect a device")}),eh?(0,n.jsx)("p",{className:"mt-3 text-center text-xs text-rose-300",children:eh}):null,k&&!eo?(0,n.jsx)("p",{className:"mt-3 text-center text-xs text-rose-300",children:k}):null,(0,n.jsx)("p",{className:"mt-3 text-center text-[10px] text-zinc-600",children:s("左键单击 / 双击 \xb7 右键长按 \xb7 坐标对齐 PNG 像素","Left tap/double \xb7 right long-press \xb7 PNG pixel coords")})]})]}),(0,n.jsxs)("div",{className:"space-y-4 xl:col-span-4",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-black/40 p-4",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:s("遥测","Telemetry")}),u?(0,n.jsxs)("dl",{className:"mt-3 space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"device"}),(0,n.jsxs)("dd",{className:"text-right text-zinc-200",children:[u.brand," ",u.model]})]}),(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"Android"}),(0,n.jsxs)("dd",{className:"text-zinc-300",children:[u.android_version," (API ",u.sdk,")"]})]}),(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"wm size"}),(0,n.jsx)("dd",{className:"text-cyan-300/90",children:S?"".concat(S.width,"\xd7").concat(S.height):u.resolution||"—"})]}),(0,n.jsx)("div",{className:"whitespace-pre-wrap text-[10px] leading-snug text-zinc-500",children:u.battery})]}):(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-600",children:s("在上方点「刷新设备信息」","Use Refresh device info above")})]}),(0,n.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,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-violet-300/80",children:s("导航坞","Nav dock")}),(0,n.jsx)("div",{className:"mt-3 grid grid-cols-3 gap-2",children:[["3","Home"],["4","Back"],["187","Recents"]].map(e=>{let[t,s]=e;return(0,n.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:s},t)})}),(0,n.jsxs)("div",{className:"mt-2 grid grid-cols-2 gap-2",children:[(0,n.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,n.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,n.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-cyan-500/[0.05] p-4",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-cyan-300/80",children:s("手势","Gestures")}),(0,n.jsx)("div",{className:"mt-2 grid grid-cols-2 gap-2",children:["up","down","left","right"].map(e=>(0,n.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,s){return e?(0,n.jsx)("span",{className:"rounded bg-emerald-500/15 px-2 py-0.5 text-[10px] text-emerald-200",children:t}):(0,n.jsx)("span",{className:"rounded bg-zinc-500/15 px-2 py-0.5 text-[10px] text-zinc-400",children:s})}function er(e){var t,s,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"),[es,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,s;let n=await y("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"shell",serial:j,payload:{command:e}})});Q(null!==(s=null!==(t=n.output)&&void 0!==t?t:n.message)&&void 0!==s?s:"")}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)),s=!!(null==e?void 0:e.silent);s||ey("logcat"),eo(null);try{var n;let e=await y("/android/logcat?serial=".concat(encodeURIComponent(j),"&lines=").concat(t));er(null!==(n=e.text)&&void 0!==n?n:"")}catch(e){er(""),eo(e.message)}finally{s||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 s=await y("/redroid/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,name:t||""})});s.summary&&K(s.summary),f(s.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,n.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("安卓设备工作台","Android workstation")}),(0,n.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,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.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,n.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,n.jsx)("span",{className:"text-xs text-amber-200/90",children:g("宿主机未检测到 adb","adb not found on host")})]}),(0,n.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:z.map(e=>(0,n.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,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)("span",{className:"font-medium text-zinc-200",children:e.model||e.serial}),e.transport?(0,n.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,n.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,n.jsx)("div",{className:"text-[10px] text-zinc-600",children:e.serial}),"device"!==(e.state||"").toLowerCase()?(0,n.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,n.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,n.jsxs)("div",{className:"grid gap-4 xl:grid-cols-[1.1fr_0.9fr]",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-violet-500/15 bg-zinc-950/50 p-5",children:[(0,n.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-violet-300/90",children:g("真机诊断","Phone diagnostics")}),O?(0,n.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:O}):null,A?(0,n.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,n.jsxs)("dl",{className:"space-y-1.5 font-mono text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"model"})," ",(0,n.jsxs)("dd",{className:"inline text-zinc-300",children:[A.brand," ",A.model]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"android"})," ",(0,n.jsxs)("dd",{className:"inline text-zinc-300",children:[A.android_version," (sdk ",A.sdk,")"]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"kind"})," ",(0,n.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,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"display"})," ",(0,n.jsx)("dd",{className:"inline text-zinc-300",children:A.resolution})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"rotation"})," ",(0,n.jsx)("dd",{className:"inline text-zinc-300",children:A.rotation})]}),(0,n.jsx)("div",{className:"whitespace-pre-wrap text-[10px] leading-snug text-zinc-500",children:A.battery}),(0,n.jsx)("div",{className:"line-clamp-3 text-[10px] text-zinc-500",children:A.focus})]}),(0,n.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===(s=A.diagnostics)||void 0===s?void 0:s.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,n.jsxs)("div",{className:"rounded-xl border border-white/5 bg-black/20 p-3 text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{children:["boot_completed: ",(null===(a=A.diagnostics)||void 0===a?void 0:a.boot_completed)||"-"]}),(0,n.jsxs)("div",{children:["provisioned: ",(null===(o=A.diagnostics)||void 0===o?void 0:o.device_provisioned)||"-"]}),(0,n.jsxs)("div",{children:["setup_complete: ",(null===(c=A.diagnostics)||void 0===c?void 0:c.user_setup_complete)||"-"]}),(0,n.jsxs)("div",{children:["abi: ",(null===(d=A.diagnostics)||void 0===d?void 0:d.abi)||"-"]}),(0,n.jsxs)("div",{className:"truncate",children:["hardware: ",(null===(x=A.diagnostics)||void 0===x?void 0:x.hardware)||"-"]})]})]}):O?null:(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:g("加载中","Loading")})]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-zinc-950/50 p-5",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,n.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-cyan-300/90",children:g("Redroid 板块","Redroid panel")}),(0,n.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,n.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:F}):null,B?(0,n.jsxs)("div",{className:"mt-3 space-y-3 text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,n.jsxs)("div",{children:["arch: ",B.arch||"-"]}),(0,n.jsxs)("div",{className:"truncate",children:["image: ",B.image||"-"]}),(0,n.jsxs)("div",{children:["profile: ",B.device_profile||"-"]}),(0,n.jsxs)("div",{children:["gpu: ",B.gpu_mode||"-"]}),(0,n.jsxs)("div",{children:["adb: 127.0.0.1:",B.default_port||5555]})]}),(0,n.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,n.jsxs)("div",{className:"space-y-2",children:[(B.instances||[]).map(e=>{var t,s,l,i;return(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-3",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-medium text-zinc-100",children:e.name}),(0,n.jsxs)("div",{className:"font-mono text-[10px] text-zinc-500",children:[e.port?"127.0.0.1:".concat(e.port):"-"," / ",e.status_text||"-"]})]}),(0,n.jsxs)("div",{className:"flex gap-1",children:[(0,n.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,n.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,n.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,n.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,n.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===(s=e.diagnostics)||void 0===s?void 0:s.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,n.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,n.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,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:g("读取 Redroid 状态中","Loading Redroid status")})]})]}),(0,n.jsx)(en,{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,n.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,n.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-emerald-300/90",children:g("快捷控制","Quick controls")}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,n.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,n.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,n.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,n.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,n.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,n.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,n.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,n.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,n.jsx)("p",{className:"mt-3 text-[10px] text-zinc-600",children:g("滑动手势","Swipe gestures")}),(0,n.jsx)("div",{className:"mt-1 flex flex-wrap gap-2",children:["up","down","left","right"].map(e=>(0,n.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,n.jsxs)("div",{className:"mt-4 rounded-lg border border-white/5 bg-black/20 p-3",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:g("ADB 文本输入","ADB text input")}),(0,n.jsxs)("div",{className:"mt-2 flex flex-col gap-2 sm:flex-row",children:[(0,n.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,n.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,n.jsxs)("div",{className:"mt-4 flex flex-col gap-2 sm:flex-row sm:items-center",children:[(0,n.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,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,n.jsxs)("h4",{className:"flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-cyan-300/90",children:[(0,n.jsx)(L.Z,{className:"h-4 w-4"}),g("USB 真机优化建议","USB optimization")]}),(0,n.jsxs)("ul",{className:"mt-3 space-y-2 text-xs leading-relaxed text-zinc-400",children:[(0,n.jsx)("li",{children:g("优先使用主板直连 USB,不要经过不稳的 HUB。","Prefer direct motherboard USB, not unstable hubs.")}),(0,n.jsx)("li",{children:g("开发板端固定 adb server,避免频繁 kill-server。","Keep adb server stable and avoid frequent kill-server.")}),(0,n.jsx)("li",{children:g("镜像页默认支持 scrcpy H.264 真流,截图模式作为回退。","Use scrcpy H.264 live stream first, screenshot mode as fallback.")}),(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(M.Z,{className:"h-4 w-4 text-emerald-400"}),g("包名搜索与启动","Packages")]}),(0,n.jsxs)("div",{className:"mt-3 flex flex-col gap-2 sm:flex-row",children:[(0,n.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,n.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,n.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,n.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 py-1 text-zinc-400",children:[(0,n.jsx)("span",{className:"min-w-0 truncate text-zinc-300",children:e.package}),(0,n.jsxs)("span",{className:"flex shrink-0 gap-1",children:[(0,n.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,n.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,n.jsx)("li",{className:"py-2 text-center text-zinc-600",children:g("暂无结果","No results")})]})]}):null,S&&j?(0,n.jsxs)("div",{className:"grid gap-6 xl:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(T.Z,{className:"h-4 w-4 text-amber-400"}),"ADB shell"]}),(0,n.jsx)("div",{className:"mt-2 flex flex-wrap gap-1.5",children:el.map(e=>(0,n.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,n.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,n.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[(0,n.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,n.jsxs)("span",{className:"inline-flex items-center gap-2",children:[(0,n.jsx)(v.Z,{className:"h-3.5 w-3.5 animate-spin"}),"Run"]}):"Run"}),$?(0,n.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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"}),g("复制输出","Copy")]}):null]}),$?(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("Logcat","Logcat")}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[(0,n.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,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 text-[11px] text-zinc-400",children:[(0,n.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,n.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")}),es?(0,n.jsxs)("button",{type:"button",onClick:()=>I(es),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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"}),g("复制","Copy")]}):null]}),ea?(0,n.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:ea}):null,es?(0,n.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:es}):null]})]}):null,S&&j?(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(E.Z,{className:"h-4 w-4 text-fuchsia-400"}),g("界面节点","UI nodes")]}),(0,n.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,n.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:ex}):null,(0,n.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,n.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,n.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,n.jsx)("span",{className:"text-zinc-200",children:e.label}),e.resource_id?(0,n.jsx)("span",{className:"ml-2 font-mono text-[10px] text-zinc-600",children:e.resource_id}):null,(0,n.jsxs)("div",{className:"font-mono text-[10px] text-zinc-600",children:["(",e.center_x,", ",e.center_y,")",e.clickable?" click":""]})]}),(0,n.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,n.jsx)("li",{className:"py-4 text-center text-zinc-600",children:g("尚未加载","Not loaded")})]})]}):null,S&&j?(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("安装 APK","Install APK")}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:g("先 adb push 到 /sdcard/ 再执行安装。","Push the APK to /sdcard/ first.")}),(0,n.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,n.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=s(9897),eo=s(4554),ec=s(7689),ed=s(8930),ex=s(8401);function eu(e){let{t,title:s,subtitle:l,steps:i,onNavigate:r}=e;return(0,n.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,n.jsx)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:s}),(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-400",children:l}),(0,n.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,n.jsxs)("div",{className:"flex items-center gap-4",children:[e.openUrl||e.target&&r?(0,n.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,n.jsx)("span",{children:e.label}),e.sub?(0,n.jsx)("span",{className:"mt-1 text-[10px] font-normal text-white/80",children:e.sub}):null]}):(0,n.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,n.jsx)("span",{children:e.label}),e.sub?(0,n.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("/"),s=t[t.length-1]||"";return s.length>8?s.slice(-8):s}}}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 s of e.split(/\r?\n/)){let e=s.trim();if(!e||e.startsWith("#")||!/douyin\.com|v\.douyin\.com/i.test(e))continue;let n=e.match(/(https?:\/\/live\.douyin\.com\/[a-zA-Z0-9_-]+)/i);if(n){t.push(n[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="",s=!0,n="",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?s=!/^(0|false|否)/i.test(c):"bitrate"===o?n=c:"fast_audio"===o&&(l=/^(1|true|yes|是|开|on)/i.test(c))}return{key:t,rtmps:s,bitrate:n,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,s,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 s of e.split(/\r?\n/)){let e=s.trim();if(!e||e.startsWith("#")||!/douyin\.com|v\.douyin\.com/i.test(e))continue;let n=e.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);if(n){t.push(n[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 s of e.split(/\r?\n/)){let e=s.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);e&&(t=e[1]);let n=s.match(/https?:\/\/[^/\s]*douyin\.com\/(\d{8,})/i);n&&(t=n[1])}return t}(p),q=null!==(s=eh(o)[0])&&void 0!==s?s:"",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 s=await a("/status?process=".concat(encodeURIComponent(e)));if(t!==Y.current||e!==W.current.trim())return;let n=s.process_status||"unknown";h(n),b(s.recent_log||""),f(s.recent_error||""),w(s.business_status||""),j(s.business_note||""),z(Array.isArray(s.ffmpeg_pids)?s.ffmpeg_pids:[]),C("number"==typeof s.log_age_seconds?s.log_age_seconds:null);let l=/^(online|running)$/i.test(n);l&&!O.current&&M(Date.now()),l||M(null),O.current=l}catch(s){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"),es=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,n.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,n.jsx)("span",{className:"sr-only","aria-hidden":!0,children:T}),(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:i("当前直播日志","Live process log")}),(0,n.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,n.jsx)("span",{className:"rounded-full px-2 py-0.5 text-[10px] font-medium ring-1 ".concat(es),children:et})]}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.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,n.jsx)(y.Z,{className:"h-3.5 w-3.5"}),i("立即拉取","Refresh")]}),(0,n.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,n.jsx)(K.Z,{className:"h-3.5 w-3.5"}):(0,n.jsx)(F.Z,{className:"h-3.5 w-3.5"}),R?i("继续自动刷新","Resume"):i("暂停自动刷新","Pause")]})]})]}),(0,n.jsxs)("div",{className:"mt-4 space-y-3 rounded-xl border border-white/[0.06] bg-black/25 p-4",children:[(0,n.jsxs)("div",{className:"grid gap-2 text-xs sm:grid-cols-2",children:[(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("进程状态","Status")}),(0,n.jsx)("span",{className:"font-medium text-zinc-200",children:function(e,t){let s=(t||"unknown").toLowerCase();return"online"===s||"running"===s?e("运行中(PM2/进程在线)","Running (process online)"):"stopped"===s||"stopping"===s?e("已停止","Stopped"):"not_found"===s||"errored"===s?e("未运行或未找到","Not running / not found"):"invalid"===s?e("无效进程名","Invalid process"):t||"—"}(i,m)})]}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("Business state","Business state")}),(0,n.jsx)("span",{className:"font-medium text-cyan-200/90",children:function(e,t,s){let n=(t||"").toLowerCase();return"streaming"===n?e("Pushing to YouTube","Pushing to YouTube"):"waiting_source"===n?e("Waiting for the upstream live source","Waiting for the upstream live source"):"source_live"===n?e("Source live detected, but no active FFmpeg relay worker","Source live detected, but no active FFmpeg relay worker"):"monitoring"===n?e("Process online and monitoring the source","Process online and monitoring the source"):"misconfigured"===n?e("YouTube key missing or invalid","YouTube key missing or invalid"):"stale"===n?e("Process online but the log heartbeat is stale","Process online but the log heartbeat is stale"):"error"===n?e("Recent process error detected","Recent process error detected"):(null==s?void 0:s.trim())?s.trim():e("No business-state hint yet","No business-state hint yet")}(i,v,N)})]}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("本次在线时长(估算)","Online duration (est.)")}),(0,n.jsx)("span",{className:"font-mono text-cyan-200/90",children:ee})]}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("FFmpeg workers","FFmpeg workers")}),(0,n.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,n.jsxs)("div",{className:"flex flex-wrap gap-2 text-xs",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("YouTube key 尾码(参考)","YT key suffix")}),(0,n.jsx)("span",{className:"font-mono text-zinc-300",children:c||"—"})]}):null,$?(0,n.jsxs)("div",{className:"rounded-lg border border-violet-500/20 bg-violet-500/[0.06] px-3 py-2.5",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.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,n.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,n.jsx)(Z.Z,{className:"h-3.5 w-3.5 shrink-0 opacity-90"}),X||i("打开抖音直播页","Open Douyin live")]})]}),J.length>1&&V?(0,n.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,n.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,n.jsx)("p",{className:"text-[11px] text-zinc-600",children:i("(日志与地址列表中暂无抖音房间)","(No Douyin room in log or URL list)")})]}),"not_found"!==m&&"invalid"!==m?(0,n.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wider text-emerald-400/90",children:i("进程输出(stdout / 合并日志)","Process output")}),(0,n.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,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wider text-rose-400/90",children:i("异常信息(stderr)","Stderr")}),(0,n.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,n.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:s,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())}),s=await h("/get_url_config?".concat(t));X(null!==(e=s.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){}},[]),es=e=>{G(e);try{window.localStorage.setItem(ej,e)}catch(e){}},en=async()=>{if(r){A(!0),K(null),F.current=!1;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:""),K(s("已从服务器读取 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(s("已删除文件","File removed")),await ee()}catch(e){f(e.message)}finally{P(!1)}}},er=async e=>{var t;let n=null===(t=e.target.files)||void 0===t?void 0:t[0];if(e.target.value="",n&&r){P(!0);try{let e=new FormData;e.append("file",n);let t=await (0,Y.N)("".concat(p,"/tiktok_replay/upload?process=").concat(encodeURIComponent(r)),{method:"POST",body:e});f(t.message||s("上传成功","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,n.jsxs)("div",{className:"mx-auto max-w-4xl space-y-6",children:[v?(0,n.jsx)(eu,{t:s,title:s("TikTok HDMI 硬件链路","TikTok HDMI hardware chain"),subtitle:s("板端编码经 HDMI 到显示/下游设备;与「网络」页顶卡相同的箭头风格。","Encode on SoC → HDMI → display/downstream; same arrow style as Network header."),onNavigate:v,steps:[{label:"FFmpeg",sub:s("采集 / 推流","Capture"),gradient:"from-cyan-400 to-blue-500",target:"live_tiktok"},{label:"HDMI",sub:s("板载输出","SoC out"),gradient:"from-violet-500 to-fuchsia-500"},{label:"Android",sub:s("AOSP / 手机","AOSP"),gradient:"from-amber-400 to-orange-500",target:"android"}]}):null,(0,n.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,n.jsx)("div",{className:"flex flex-wrap items-start gap-4",children:(0,n.jsxs)("div",{className:"flex items-center gap-3",children:[(0,n.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,n.jsx)(D.Z,{className:"h-5 w-5 text-cyan-200"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold tracking-tight text-white",children:s("TikTok 无人直播(单路)","TikTok unmanned (single lane)")}),(0,n.jsx)("p",{className:"mt-0.5 text-xs text-zinc-500",children:s("布局对齐 YouTube 单频道:直播开关 + 源站 + URL_config;无 stream key,输出走 HDMI 硬件链路。","Same layout as YouTube single: controls + URLs; no stream key — HDMI hardware path.")})]})]})})}),(0,n.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,n.jsx)("p",{className:"text-xs leading-relaxed text-cyan-100/90",children:s("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,n.jsxs)("div",{className:"rounded-2xl border border-white/10 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-300"}),s("X86 HDMI 采集状态","X86 HDMI capture status")]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:s("这里直接显示主机是否识别到采集卡和 /dev/video 设备,可用于验证 ARM HDMI 进 X86 的链路。","Shows whether the host sees the capture card and /dev/video nodes for ARM-to-X86 HDMI ingest.")})]}),(0,n.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?s("可推流","Ready"):s("未就绪","Not ready")})]}),(0,n.jsxs)("div",{className:"mt-4 grid gap-3 md:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-4 text-[11px] text-zinc-400",children:[(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"device: "}),(0,n.jsx)("span",{className:"font-mono text-zinc-200",children:ep||"—"})]}),(0,n.jsxs)("p",{className:"mt-2",children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"video nodes: "}),(0,n.jsx)("span",{className:"font-mono text-zinc-200",children:((null==g?void 0:g.video_devices)||[]).join(", ")||"—"})]}),(0,n.jsxs)("p",{className:"mt-2",children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"usb matches: "}),(0,n.jsx)("span",{className:"text-zinc-300",children:((null==g?void 0:g.usb_capture_matches)||[]).length||0})]})]}),(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-4 text-[11px] text-zinc-400",children:[(0,n.jsx)("p",{className:"text-zinc-600",children:s("建议 FFmpeg","Suggested FFmpeg")}),(0,n.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,n.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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"}),s("复制命令","Copy command")]}):null]})]}),((null==g?void 0:g.issues)||[]).length?(0,n.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,n.jsx)("li",{children:e},e))}):null]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-amber-500/20 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2 text-amber-200/90",children:[(0,n.jsx)(B.Z,{className:"h-4 w-4"}),(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:s("直播开关","Live control")})]}),(0,n.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:s("TikTok 进程(PM2)","TikTok PM2 process")}),(0,n.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,n.jsxs)("option",{value:e.pm2,children:[e.label," (",e.pm2,")"]},e.pm2))}),(0,n.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:s("直播源","Video source")}),(0,n.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,n.jsx)("option",{value:"ffmpeg",hidden:!0,children:"FFmpeg(抖音 / TikTok 等直播间 URL)"}),(0,n.jsx)("option",{value:"replay",hidden:!0,children:s("录播素材(本地上传)","VOD upload")}),(0,n.jsx)("option",{value:"srs",children:s("SRS(OBS 推流)","SRS (OBS)")})]}),"srs"===N?(0,n.jsx)("p",{className:"mt-2 text-[11px] leading-relaxed text-amber-200/85",children:s("此模式不显示 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,n.jsx)("div",{className:"mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3",children:[["start",s("开始直播","Start"),"bg-emerald-500/20 text-emerald-200 ring-emerald-500/30"],["stop",s("停止直播","Stop"),"bg-rose-500/15 text-rose-200 ring-rose-500/25"],["restart",s("重新开始","Restart"),"bg-amber-500/15 text-amber-200 ring-amber-500/25"]].map(e=>{let[t,s,l]=e;return(0,n.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:s},t)})}),(0,n.jsxs)("p",{className:"mt-3 text-center text-[11px] text-zinc-500",children:[s("当前 HDMI 预设(备忘)","HDMI preset (memo)"),":"," ",(0,n.jsx)("span",{className:"font-mono text-cyan-300/90",children:em?s(em.labelZh,em.labelEn):T})]})]}),"replay"===N?(0,n.jsxs)("div",{className:"rounded-2xl border border-violet-500/25 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(eo.Z,{className:"h-4 w-4 text-violet-300"}),s("录播素材","VOD library")]}),(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.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,n.jsx)(ec.Z,{className:"h-3.5 w-3.5"}),(0,n.jsx)("span",{children:s("上传视频","Upload")}),(0,n.jsx)("input",{type:"file",accept:".mp4,.mkv,.ts,.flv,.mov,.m4v,.webm",className:"hidden",onChange:er})]}),(0,n.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:s("刷新列表","Refresh")})]})]}),(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:s("文件保存在服务器 config/tiktok_replay/对应进程目录;点「开始直播」会写入 replayfile 行并启动 PM2 进程。停播请用上方「停止直播」。","Files under config/tiktok_replay/. Go live writes replayfile + starts PM2. Use Stop above to stop.")}),S?(0,n.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:s("加载中…","Loading…")}):0===k.length?(0,n.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:s("暂无文件,请先上传。","No files yet.")}):(0,n.jsx)("ul",{className:"mt-4 space-y-2",children:k.map(e=>(0,n.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,n.jsx)("span",{className:"min-w-0 flex-1 truncate font-mono",children:e.name}),(0,n.jsxs)("span",{className:"shrink-0 text-zinc-500",children:[(e.size/1048576).toFixed(1)," MB"]}),(0,n.jsxs)("div",{className:"flex shrink-0 flex-wrap gap-2",children:[(0,n.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:s("开始直播","Go live")}),(0,n.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:s("停播","Stop")}),(0,n.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,n.jsx)(ed.Z,{className:"h-3 w-3"}),s("删除","Del")]})]})]},e.name))})]}):null,"srs"===N?(0,n.jsxs)("div",{className:"rounded-2xl border border-emerald-500/25 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:s("SRS / OBS 推流","SRS / OBS ingest")}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:s("OBS:设置 → 推流 → 服务选「自定义」,服务器填 RTMP 地址;串流密钥可与 SRS 应用配置一致(默认 live/livestream)。","OBS → Stream → Custom: RTMP URL as server; stream key per SRS app (default live/livestream).")}),(0,n.jsxs)("dl",{className:"mt-4 space-y-3 text-xs",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-500",children:s("RTMP 推流地址(OBS 服务器)","RTMP publish URL")}),(0,n.jsxs)("dd",{className:"mt-1 flex flex-wrap items-center gap-2 font-mono text-emerald-200/90",children:[(0,n.jsx)("span",{className:"break-all",children:b.srs_rtmp_publish||"—"}),b.srs_rtmp_publish?(0,n.jsx)("button",{type:"button",className:"shrink-0 text-cyan-300 hover:text-cyan-200",onClick:()=>m(b.srs_rtmp_publish),children:(0,n.jsx)(U.Z,{className:"h-3.5 w-3.5"})}):null]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-500",children:s("HTTP-FLV 预览","HTTP-FLV preview")}),(0,n.jsxs)("dd",{className:"mt-1 flex flex-wrap items-center gap-2 font-mono text-zinc-400",children:[(0,n.jsx)("span",{className:"break-all",children:b.srs_play_flv||b.srs_http||"—"}),b.srs_play_flv||b.srs_http?(0,n.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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"})}):null]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-500",children:s("SRS 控制台","SRS web UI")}),(0,n.jsx)("dd",{className:"mt-1 font-mono text-zinc-400",children:(0,n.jsx)("a",{href:b.srs_http||"#",target:"_blank",rel:"noreferrer",className:"text-cyan-300 hover:underline",children:b.srs_http||"—"})})]})]})]}):null,(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-400"}),s("HDMI 硬件与时序","HDMI timing")]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:s("点选一路作为现场备忘;与板端 ffmpeg/OBS 采集参数对齐。","Pick a preset as field memo; match capture settings.")}),(0,n.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,n.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,n.jsxs)("div",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-400"}),s(e.labelZh,e.labelEn)]}),(0,n.jsx)("p",{className:"mt-2 font-mono text-[11px] text-zinc-400",children:e.spec}),t?(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:s(e.hintZh,e.hintEn)}):null]},e.id)})}),(0,n.jsxs)("div",{className:"mt-6 rounded-xl border border-white/5 bg-black/25 p-4",children:[(0,n.jsx)("p",{className:"text-xs font-semibold text-zinc-400",children:s("上线前检查清单(本地保存)","Pre-flight checklist (local)")}),(0,n.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,n.jsxs)("li",{className:"flex items-start gap-2 text-xs text-zinc-400",children:[(0,n.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,n.jsx)("span",{children:s(e.zh,e.en)})]},e.id))}),(0,n.jsx)("label",{className:"mt-4 block text-[11px] text-zinc-500",children:s("HDMI / 走线备忘","HDMI / wiring notes")}),(0,n.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=>es(e.target.value),spellCheck:!1,placeholder:s("接口、线长、显示器型号…","Ports, cable length, display model…")})]})]}),"ffmpeg"===N?(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:s("直播地址列表 \xb7 URL_config.ini","URL_config.ini")}),(0,n.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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"}),s("复制全文","Copy all")]})]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:s("一行一个地址;可勾选自动从服务器刷新,或点「重新读取」手动同步。","One URL per line; enable auto-refresh or reload from server.")}),(0,n.jsx)("div",{className:"mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400",children:(0,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-2",children:[(0,n.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:Z,onChange:e=>O(e.target.checked)}),s("每 8 秒自动从服务器刷新","Auto-refresh from server every 8s")]})}),H?(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:H}):null,(0,n.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,n.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,n.jsx)("button",{type:"button",disabled:ex,onClick:()=>void en(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-300",children:s("重新读取","Reload from server")}),(0,n.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:s("保存 URL 配置","Save URL config")})]})]}):null,(0,n.jsx)(ev,{t:s,currentProc:r,fetchJson:h,urlListText:"ffmpeg"===N?o:"",keySuffixUi:"",showKeyRow:!1})]})}var eS=s(5468),e_=s(9397),eC=s(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 s=eT(e);return!s||eM.has(s)||s===eP?eK(t):s.startsWith(eP)?s:eK(s)}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 s=String(e.name||"").trim()||t;return{id:t,name:s,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 s of eZ)try{var t;let n=await e(s);return{fetched:!0,channels:(t=n.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 s=null;for(let n of eZ)try{await e(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channels:t})});return}catch(e){s=e instanceof Error?e:Error(String(e))}throw null!=s?s: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 s=((null==t?void 0:t.business_status)||"").trim().toLowerCase();return(null==t?void 0:t.is_pushing)||"streaming"===s?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,s,n;return{name:e.name,streamKey:null!==(t=e.streamKey)&&void 0!==t?t:"",pm2Name:null!==(s=e.pm2Name)&&void 0!==s?s:eK(e.id),notes:null!==(n=e.notes)&&void 0!==n?n:""}}function eX(e){return/^(online|running)$/i.test((e||"").trim())}function e$(e,t){let s=((null==e?void 0:e.business_status)||"").trim().toLowerCase();return"ready"===s?t("已配置","Ready"):"streaming"===s?t("推流中","Pushing"):"waiting_source"===s?t("等待上游","Waiting source"):"source_live"===s?t("源已开播,转推未起","Source live, relay down"):"monitoring"===s?t("监控中","Monitoring"):"misconfigured"===s?t("密钥异常","Key invalid"):"stale"===s?t("心跳过期","Stale"):"error"===s?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:s,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),s=t.indexOf(":");if(s<=0)return null;let n=t.slice(0,s),l=t.slice(s+1);return l&&["start","stop","restart"].includes(n)?{action:n,pm2:l}:null}(i),p=h&&h.pm2===l,b=null!=s?s: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,n.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,n.jsx)("span",{className:"absolute inset-0 flex items-center justify-center bg-black/25 backdrop-blur-[2px]",children:(0,n.jsx)(v.Z,{className:"".concat(m?"h-4 w-4":"h-6 w-6"," animate-spin text-white")})}):null,(0,n.jsxs)("span",{className:"inline-flex items-center justify-center gap-1.5 ".concat(g?"invisible":""),children:[j?(0,n.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,s,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 s=e.filter(eF),n=s.filter(e=>eF(e)&&e.pm2.trim()===eW(e.script).trim()),l=n.length?[...n]:s.length?[...s]:[...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 n=(e.business_status||"").trim().toLowerCase();if(!e.is_pushing&&"streaming"!==n&&!eX(e.process_status))continue;let d=s.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=s[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 s=new Map(t.filter(eY).map(e=>[e.pm2.trim(),e])),n=e[0],l=eJ(n,s.get(n.pm2.trim()));for(let t of e.slice(1)){let e=eJ(t,s.get(t.pm2.trim()));e"youtube"===e.pm2.trim().toLowerCase());if(n)return n.pm2;let l=e.find(e=>"youtube"===eW(e.script).trim().toLowerCase());return l?l.pm2:null!==(s=null===(t=e[0])||void 0===t?void 0:t.pm2)&&void 0!==s?s:""}(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)({}),[es,en]=(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)(x),ew=(0,_.useRef)(0),eN=(0,_.useRef)(0),ej=(0,_.useCallback)(e=>{ec.current=e,h(e)},[h]),ek=(0,_.useCallback)(e=>{ef.current=e,W(e)},[]);(0,_.useEffect)(()=>{eo.current=!1},[x]),(0,_.useEffect)(()=>{ey.current=x},[x]),(0,_.useEffect)(()=>{ec.current=m},[m]),(0,_.useEffect)(()=>{ef.current=F},[F]);let ez=(0,_.useCallback)(async()=>{let e=ey.current.trim();if(!e)return;let t=++ew.current;try{var s,n,l;let i=new URLSearchParams({process:e,_ts:String(Date.now())}),r=await g("/get_url_config?".concat(i));if(t!==ew.current||e!==ey.current.trim())return;let a=null!==(s=r.content)&&void 0!==s?s:"";if(eo.current)return;if("single"===C)ej(a);else{let e=null!==(l=null===(n=P.find(e=>e.id===M))||void 0===n?void 0:n.urlLines)&&void 0!==l?l:"";if(e0(e,a)){ek(e);return}ek(a),M&&L(e=>{let t=e.map(e=>e.id===M?{...e,urlLines:a}:e);return eA(t),t})}}catch(e){}},[M,ek,ej,P,g,C]);(0,_.useEffect)(()=>{if(!x||!Y)return;let e=window.setInterval(()=>{eo.current||ez()},8e3);return()=>clearInterval(e)},[x,Y,ez]);let eS=async()=>{let e=ey.current.trim();if(!e)return;V(!0),Q(null),eo.current=!1;let t=++ew.current;try{var s,n,l;let i=new URLSearchParams({process:e,_ts:String(Date.now())}),r=await g("/get_url_config?".concat(i));if(t!==ew.current||e!==ey.current.trim())return;let o=null!==(s=r.content)&&void 0!==s?s:"";if(eo.current){Q(a("检测到本地未保存修改,已保留当前草稿","Kept the local unsaved draft"));return}if("single"===C)ej(o);else{let e=null!==(l=null===(n=P.find(e=>e.id===M))||void 0===n?void 0:n.urlLines)&&void 0!==l?l:"";if(e0(e,o)){ek(e),Q(a("服务器暂无已保存 URL,已保留本地草稿","Server has no saved URLs, kept the local draft"));return}ek(o),M&&L(e=>{let t=e.map(e=>e.id===M?{...e,urlLines:o}:e);return eA(t),t})}Q(a("已从服务器读取 URL_config","Reloaded URL_config from server"))}catch(s){if(t!==ew.current||e!==ey.current.trim())return;Q(s.message)}finally{t===ew.current&&e===ey.current.trim()&&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){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)}(),s=t.length>0?t:(()=>{let e=eB();return[{id:e,name:"线路 1",streamKey:"",urlLines:"",pm2Name:eK(e),notes:""}]})();L(s),t.length||eA(s)})(),()=>{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 eP=(0,_.useCallback)(e=>f.find(t=>t.pm2===e),[f]),eL=(0,_.useCallback)(e=>{var t;return null===(t=eP(e))||void 0===t?void 0:t.process_status},[eP]),eM=eP(x),eU=(0,_.useMemo)(()=>{var e,t;return!!x&&(/youtube/i.test(x)||/youtube/i.test(null!==(e=null==eM?void 0:eM.script)&&void 0!==e?e:"")||/youtube/i.test(null!==(t=null==eM?void 0:eM.label)&&void 0!==t?t:""))},[x,eM]);(0,_.useEffect)(()=>{"single"!==C||!S||x&&eU||u(S)},[x,eU,C,S,u]);let eI=(0,_.useCallback)(e=>{L(e),eA(e)},[]),eZ=(0,_.useCallback)(async e=>{await eH(g,e)},[g]),e5=(0,_.useCallback)(e=>{eI(e),eZ(e).catch(e=>{w("".concat(a("多频道列表未同步到服务器","Channel list not saved on server"),": ").concat(e.message))})},[eI,w,eZ,a]),e2=P.find(e=>e.id===M)||P[0],e3=(0,_.useMemo)(()=>{var e;return e2?null!==(e=ee[e2.id])&&void 0!==e?e:eq(e2):null},[e2,ee]);(0,_.useEffect)(()=>{e2&&et(e=>e[e2.id]?e:{...e,[e2.id]:eq(e2)})},[e2]),(0,_.useEffect)(()=>{ei(null)},[M]);let e4=(0,_.useCallback)((e,t)=>{e2&&(et(s=>{var n;return{...s,[e2.id]:{...null!==(n=s[e2.id])&&void 0!==n?n:eq(e2),[e]:t}}}),ei(null))},[e2]),e6=e2?eE(e2):"",e8=e2&&e3?eE({id:e2.id,pm2Name:e3.pm2Name}):"",e9=!!e2&&!!e3&&e8!==e6,e7=(0,_.useMemo)(()=>{if(!e2||!e3)return{ok:!1,message:a("请选择线路","Pick a lane"),normalizedName:"",normalizedPm2:"",normalizedStreamKey:"",normalizedNotes:""};let e=e3.name.trim()||"".concat(a("线路","Ch")," ").concat(P.findIndex(e=>e.id===e2.id)+1),t=eE({id:e2.id,pm2Name:e3.pm2Name});return t?eV.has(t)?{ok:!1,message:a("该进程名保留给系统模块,请换一个","This PM2 name is reserved"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e3.streamKey.trim(),normalizedNotes:e3.notes.trim()}:P.find(e=>e.id!==e2.id&&eE(e)===t)?{ok:!1,message:a("该进程名已被其它线路占用","Another lane already uses this PM2 name"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e3.streamKey.trim(),normalizedNotes:e3.notes.trim()}:{ok:!0,message:"",normalizedName:e,normalizedPm2:t,normalizedStreamKey:e3.streamKey.trim(),normalizedNotes:e3.notes.trim()}:{ok:!1,message:a("进程名不能为空","PM2 name is required"),normalizedName:e,normalizedPm2:t,normalizedStreamKey:e3.streamKey.trim(),normalizedNotes:e3.notes.trim()}},[e2,e3,P,a]),te=(0,_.useMemo)(()=>{if(!e2||!e3)return!1;let e=eq(e2);return e3.name!==e.name||e3.streamKey!==e.streamKey||eT(e3.pm2Name)!==eT(e.pm2Name)||e3.notes!==e.notes},[e2,e3]),tt=(0,_.useCallback)(e=>{var t,s,n;if("single"===e&&"pro"===C&&e2){let e=ef.current;e!==(null!==(t=e2.urlLines)&&void 0!==t?t:"").trim()&&e5(P.map(t=>t.id===e2.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)];e5(i);let r=null!==(s=i.find(e=>e.id===M))&&void 0!==s?s:i[0];ek((null!==(n=null==r?void 0:r.urlLines)&&void 0!==n?n:"").trim()||t)}R(e);try{window.localStorage.setItem(eG,e)}catch(e){}},[C,e2,P,ek,I.key,M,e5]),ts=(0,_.useCallback)(e=>{var t,s;let n=ef.current;e2&&"pro"===C&&n!==(null!==(t=e2.urlLines)&&void 0!==t?t:"").trim()&&e5(P.map(e=>e.id===e2.id?{...e,urlLines:n}:e)),ek((null!==(s=e.urlLines)&&void 0!==s?s:"").trim()),T(e.id),u(eE(e))},[e2,ek,C,P,u,e5]);(0,_.useEffect)(()=>{if("pro"!==C||!M)return;let e=P.find(e=>e.id===M);e&&u(eE(e))},[C,M,P,u]);let tn=(0,_.useCallback)(async()=>{let e=ey.current.trim();if(!e)return;let t=++eN.current;K(!0),O(null);try{var s;let n=new URLSearchParams({process:e,_ts:String(Date.now())}),l=await g("/get_config?".concat(n));if(t!==eN.current||e!==ey.current.trim())return;let i=null!==(s=l.content)&&void 0!==s?s:"";E(i),D(ep(i))}catch(s){if(t!==eN.current||e!==ey.current.trim())return;O(s.message)}finally{t===eN.current&&e===ey.current.trim()&&K(!1)}},[g]);(0,_.useEffect)(()=>{x&&(ez(),tn(),ea(e=>e+1))},[M,x,tn,C,ez]);let tl=(0,_.useCallback)(async()=>{var e;if(!e2||!e3)throw Error(a("请选择线路","Pick a lane"));if(!e7.ok)throw Error(e7.message);let t=ef.current,s=P.map(e=>e.id===e2.id?{...e,name:e7.normalizedName,streamKey:e7.normalizedStreamKey,pm2Name:e7.normalizedPm2,notes:e7.normalizedNotes,urlLines:t}:e);return eI(s),await eZ(s),et(e=>({...e,[e2.id]:{name:e7.normalizedName,streamKey:e7.normalizedStreamKey,pm2Name:e7.normalizedPm2,notes:e7.normalizedNotes}})),{next:s,savedLane:null!==(e=s.find(e=>e.id===e2.id))&&void 0!==e?e:{...e2,name:e7.normalizedName,streamKey:e7.normalizedStreamKey,pm2Name:e7.normalizedPm2,notes:e7.normalizedNotes,urlLines:t},pm2:e7.normalizedPm2}},[e2,e3,e7,eI,P,eZ,a]),ti=(0,_.useCallback)(async()=>{if(e2){en(!0),ei(null);try{let e=await tl();u(e.pm2),ei(a("线路设置已保存","Lane settings saved"))}catch(t){let e=t.message;ei(e),w(e)}finally{en(!1)}}},[e2,w,tl,u,a]),tr=async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ey.current,s=t.trim();if(!s){O(a("请选择进程","Pick a process"));return}K(!0),O(null);try{let t=new URLSearchParams({process:s});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)}},ta=async()=>{let e=eg(I);await tr(e)},to=async()=>{K(!0),O(null);try{var e,t;let s=U||eg(I),n=await g("/config_optimize",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:"app-config",path:(t=ey.current,"youtube.".concat(t.replace(/[^a-zA-Z0-9_.-]/g,"_"),".ini")),content:s,action:"youtube_balanced_preset"})}),l=null!==(e=n.content)&&void 0!==e?e:s;E(l),D(ep(l)),O(n.message||a("已应用 YouTube 预设","Applied YouTube preset"))}catch(e){O(e.message)}finally{K(!1)}},tc=(0,_.useMemo)(()=>{var e,t;if("single"===C)return em("key = ".concat(I.key));let s=null!==(t=null!==(e=null==e3?void 0:e3.streamKey)&&void 0!==e?e:null==e2?void 0:e2.streamKey)&&void 0!==t?t:"";return em("key = ".concat(s))},[C,I.key,null==e2?void 0:e2.streamKey,null==e3?void 0:e3.streamKey]),td=async()=>{if(e2)try{en(!0),ei(null),ew.current+=1;let e=ef.current,t=await tl();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{en(!1)}},tx=async()=>{let e=ey.current.trim();if(!e){w(a("请选择进程","Pick a process"));return}try{ew.current+=1,await Promise.resolve(b(ec.current,e)),eo.current=!1}catch(e){}},tu=async()=>{let e="single"===C?ec.current:ef.current;X(!0),Q(null);try{var t;let s=await g("/config_optimize",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({root:"app-config",path:eb(ey.current),content:e,action:"dedupe_urls"})}),n=null!==(t=s.content)&&void 0!==t?t:e;"single"===C?ej(n):ek(n),eo.current=!0,Q(s.message||a("已去重当前 URL 列表","Deduplicated current URL list"))}catch(e){Q(e.message)}finally{X(!1)}},tm=async()=>{if(!e2||!e3)return;let e=ep(U||eg(I)),t=eg({key:e3.streamKey.trim(),rtmps:e.rtmps,bitrate:e.bitrate,fastAudio:e.fastAudio});en(!0),ei(null);try{let e=await tl();u(e.pm2),await tr(t,e.pm2),ei(a("线路设置与 youtube.ini 已保存","Lane settings and youtube.ini saved"))}catch(t){let e=t.message;ei(e),w(e)}finally{en(!1)}},th="single"===C?m:F,tp=(0,_.useMemo)(()=>eQ(th).length,[th]),tb=(0,_.useMemo)(()=>eh(th).length,[th]),tg=(0,_.useMemo)(()=>(0,eC.O0)(j),[j]),tf=(0,_.useMemo)(()=>(0,eC.U_)(tg,"pro"===C&&e2?P.findIndex(e=>e.id===e2.id):0),[e2,P,C,tg]),tv=tf.link?(0,ex.p)(tf.link.url):(0,ex.p)("http://live.local:9200/"),ty=(0,_.useMemo)(()=>(0,eC.Tc)(tg),[tg]),tw=(0,_.useMemo)(()=>{var e;return[null===(e=tf.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=tf.link)||void 0===t?void 0:t.url]),tN=(0,_.useCallback)(async e=>{let t=e2?eE(e2):"";return e2&&e===t?await tl():(eI(P),await eZ(P),{next:P,savedLane:null!=e2?e2:null,pm2:e})},[e2,eI,P,tl,eZ]),tj=(0,_.useCallback)(async(e,t)=>{let s=!!e2&&eE(e2)===t;if("stop"!==e){var n,l;let e=P,s=t;try{let n=await tN(t);e=n.next,s=n.pm2}catch(e){w("".concat(a("当前线路保存失败","Failed to save the active lane"),": ").concat(e.message));return}let i=e.find(e=>eE(e)===s),r=null!==(n=null==i?void 0:i.urlLines)&&void 0!==n?n:"";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=s}s&&u(t),p(e,t)},[e2,P,tN,w,p,u,a]),tk=!!o||H||G||q||es,tz=eX(eL(x)),tS=(0,n.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400",children:[(0,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-2",children:[(0,n.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,n.jsx)("button",{type:"button",disabled:tk,onClick:()=>void eS(),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,n.jsx)("button",{type:"button",disabled:tk,onClick:()=>void tu(),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,n.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6",children:[N?(0,n.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:tf.link?"".concat(a("Chromium 工作室","Chromium studio")," \xb7 ").concat(tf.link.label):a("Chromium 工作室","Chromium studio"),gradient:"from-emerald-400 to-teal-500",openUrl:tv}]}):null,(0,n.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,n.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[(0,n.jsxs)("div",{className:"flex items-center gap-3",children:[(0,n.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,n.jsx)(c.Z,{className:"h-5 w-5 text-red-200"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold tracking-tight text-white",children:a("YouTube 无人直播","YouTube unmanned live")}),(0,n.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,n.jsxs)("div",{className:"flex rounded-xl border border-white/10 bg-black/30 p-1 ".concat(""),"aria-hidden":!1,children:[(0,n.jsx)("button",{type:"button",onClick:()=>tt("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,n.jsx)("button",{type:"button",onClick:()=>tt("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")})]})]})}),tw.length?(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[tf.link?(0,n.jsx)("a",{href:tv,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,tg.length>1?(0,n.jsx)("div",{className:"flex flex-wrap gap-2",children:tg.map(e=>{var t;return(0,n.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=tf.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,n.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,n.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,n.jsxs)("div",{className:"rounded-2xl border border-amber-500/20 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2 text-amber-200/90",children:[(0,n.jsx)(B.Z,{className:"h-4 w-4"}),(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播开关","Live control")})]}),"single"===C?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:a("转播任务","Relay task")}),(0,n.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;ey.current=t,u(t)},children:[x&&!z.some(e=>e.pm2===x)?(0,n.jsxs)("option",{value:x,children:[x,eM?" (".concat(e$(eM,a),")"):""]}):null,z.map(e=>(0,n.jsxs)("option",{value:e.pm2,children:[function(e,t){let s=eW(e.script).toLowerCase();return s.startsWith("douyin_youtube")?t("抖音→YouTube","Douyin → YouTube"):s.startsWith("youtube")?t("YouTube","YouTube"):e.label}(e,a)," (",e.pm2,")"]},e.pm2))]}),(0,n.jsxs)("div",{className:"mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3",children:[(0,n.jsx)(e1,{kind:"start",targetPm2:x,busy:o,online:tz,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,n.jsx)(e1,{kind:"stop",targetPm2:x,busy:o,online:tz,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,n.jsx)(e1,{kind:"restart",targetPm2:x,busy:o,online:tz,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,n.jsxs)("p",{className:"mt-3 text-center text-xs text-zinc-400",children:[a("当前状态","Current state"),": ",e$(eM,a)]}),(0,n.jsxs)("p",{className:"mt-3 text-center font-mono text-[11px] text-zinc-600",children:["key ",a("尾码","suffix"),": ",tc||"—"]})]}):(0,n.jsx)(n.Fragment,{children:(0,n.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,n.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-cyan-200/90",children:a("Pro 转播实况","Pro relay status")}),(0,n.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.")}),ty?(0,n.jsxs)("p",{className:"mt-2 text-[11px] text-zinc-500",children:[a("Neko 实例","Neko instances"),": ",ty]}):null,(0,n.jsx)("div",{className:"mt-3 max-h-[min(24rem,55vh)] space-y-2 overflow-y-auto pr-1",children:P.map(e=>{var t,s,l;let i=eE(e),r=eP(i),c=eL(i),d=eQ((null!==(t=e.urlLines)&&void 0!==t?t:"").trim()),x=eh((null!==(s=e.urlLines)&&void 0!==s?s:"").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_)(tg,b).link;return(0,n.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,n.jsxs)("button",{type:"button",className:"min-w-0 flex-1 text-left",onClick:()=>{ey.current=eE(e),ts(e)},children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("span",{className:"font-medium text-zinc-100",children:e.name}),(0,n.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,n.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,n.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,n.jsxs)("span",{children:["key …",m||"—"]}),(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,n.jsx)("span",{className:"truncate",title:i,children:i}),(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,n.jsxs)("span",{children:["URL ",d.length]}),(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,n.jsxs)("span",{children:["DY ",x.length]})]}),u?(0,n.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,n.jsx)("span",{className:"mt-1 block text-zinc-600",children:"—"})]}),(0,n.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,n.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 tj("start",i),notify:w,t:a,compact:!0}),(0,n.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 tj("stop",i),notify:w,t:a,compact:!0}),(0,n.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 tj("restart",i),notify:w,t:a,compact:!0}),g?(0,n.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,n.jsx)("span",{className:"sr-only",children:a("打开该线路 Neko 工作室","Open this lane's Neko studio")}),(0,n.jsx)("span",{"aria-hidden":!0,className:"text-sm leading-none",children:"\uD83D\uDC31"}),(0,n.jsx)(Z.Z,{className:"ml-1 h-3.5 w-3.5 shrink-0","aria-hidden":!0})]}):null]})]},e.id)})})]})})]}),"single"===C?(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("YouTube 相关设置","YouTube settings")}),(0,n.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,n.jsxs)("div",{className:"mt-4 space-y-3",children:[(0,n.jsx)("label",{className:"block text-xs text-zinc-400",children:a("串流密钥","Stream key")}),(0,n.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,n.jsxs)("div",{className:"grid gap-3 sm:grid-cols-3",children:[(0,n.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-zinc-400",children:["RTMPS",(0,n.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,n.jsx)("option",{value:"1",children:a("是(默认)","Yes")}),(0,n.jsx)("option",{value:"0",children:a("否 → RTMP","No")})]})]}),(0,n.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-zinc-400",children:[a("比特率 kbps","Bitrate kbps"),(0,n.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,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 pt-6 text-xs text-zinc-300",children:[(0,n.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,n.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,n.jsxs)("button",{type:"button",disabled:tk,onClick:()=>void tn(),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,n.jsx)(y.Z,{className:"h-3.5 w-3.5 ".concat(H?"animate-spin":"")}),a("重新读取","Reload")]}),(0,n.jsxs)("button",{type:"button",disabled:tk,onClick:()=>void ta(),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,n.jsx)(v.Z,{className:"h-4 w-4 animate-spin"}):null,a("保存 youtube.ini","Save youtube.ini")]}),(0,n.jsx)("button",{type:"button",disabled:tk,onClick:()=>void to(),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,n.jsx)("button",{type:"button",disabled:tk,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,n.jsxs)("details",{className:"mt-4 rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,n.jsx)("summary",{className:"cursor-pointer text-xs text-zinc-500",children:a("高级:youtube.ini 原文","Raw youtube.ini")}),(0,n.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,n.jsx)("button",{type:"button",disabled:tk,className:"mt-2 rounded-lg bg-cyan-500/15 px-3 py-1.5 text-xs text-cyan-200",onClick:()=>void tr(U),children:a("保存原文","Save raw")})]}),A?(0,n.jsx)("p",{className:"mt-2 font-mono text-xs text-zinc-500",children:A}):null]}):(0,n.jsxs)("div",{className:"space-y-6",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsxs)("h3",{className:"text-sm font-semibold text-white",children:[a("当前线路","Current lane"),e2?(0,n.jsxs)("span",{className:"ml-2 font-normal text-zinc-400",children:["\xb7 ",e2.name]}):null,te?(0,n.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]}),e2?(0,n.jsxs)("p",{className:"mt-0.5 font-mono text-[11px] text-zinc-500",children:["PM2: ",e6,e9?" → ".concat(e8):""," \xb7 ","key ",tc||"—"]}):null]}),(0,n.jsxs)("button",{type:"button",disabled:tk,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(s=>({...s,[e]:eq(t)})),e5([...P,t]),T(e),ey.current=eE(t),u(ey.current),ek("")},children:[(0,n.jsx)(e_.Z,{className:"h-3.5 w-3.5"}),a("新增线路","Add lane")]})]}),e2?(0,n.jsxs)("div",{className:"mt-4 space-y-3 border-t border-white/5 pt-4",children:[(0,n.jsx)("input",{className:"w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-sm",value:null!==(s=null==e3?void 0:e3.name)&&void 0!==s?s:"",onChange:e=>e4("name",e.target.value),placeholder:a("线路名称","Lane name")}),(0,n.jsx)("label",{className:"block text-xs text-zinc-500",children:a("串流密钥","Stream key")}),(0,n.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==e3?void 0:e3.streamKey)&&void 0!==l?l:"",onChange:e=>e4("streamKey",e.target.value),placeholder:"xxxx-xxxx… / rtmp(s)://…"}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("button",{type:"button",disabled:tk,onClick:()=>void ti(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-100",children:es?a("保存中...","Saving..."):a("保存线路设置","Save lane")}),(0,n.jsx)("button",{type:"button",disabled:tk,onClick:()=>void tm(),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")})]}),e7.ok?null:(0,n.jsx)("p",{className:"text-xs text-rose-300",children:e7.message}),(0,n.jsxs)("details",{className:"rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,n.jsx)("summary",{className:"cursor-pointer text-xs text-zinc-500",children:a("高级:进程名","Advanced: process name")}),(0,n.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==e3?void 0:e3.pm2Name)&&void 0!==i?i:eK(e2.id),onChange:e=>e4("pm2Name",e.target.value),spellCheck:!1,placeholder:"youtube2__…"}),(0,n.jsxs)("p",{className:"mt-2 font-mono text-[11px] text-zinc-500",children:[a("实际生效","Effective"),": ",e8||"—"]}),e7.message&&!e7.ok?(0,n.jsx)("p",{className:"mt-2 text-[11px] text-rose-300",children:e7.message}):null]}),(0,n.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==e3?void 0:e3.notes)&&void 0!==r?r:"",onChange:e=>e4("notes",e.target.value),placeholder:a("备注(可选)","Notes (optional)")}),el?(0,n.jsx)("p",{className:"text-xs text-zinc-400",children:el}):null,(0,n.jsxs)("button",{type:"button",disabled:tk||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!==e2.id);et(e=>{let t={...e};return delete t[e2.id],t}),e5(t),T((null===(e=t[0])||void 0===e?void 0:e.id)||"")},children:[(0,n.jsx)(ed.Z,{className:"h-3.5 w-3.5"}),a("删除此线路","Delete lane")]})]}):null]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播地址列表","URL list")}),(0,n.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,n.jsx)("p",{className:"mt-1 font-mono text-[10px] text-zinc-600",children:x?eb(x):"URL_config.ini"}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2 text-[11px]",children:[(0,n.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"),": ",tp]}),(0,n.jsxs)("span",{className:"rounded-full border border-violet-500/20 bg-violet-500/10 px-2.5 py-1 text-violet-100",children:["Douyin: ",tb]})]}),tS,$?(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:$}):null,(0,n.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,ek(e.target.value)},spellCheck:!1,placeholder:"https://live.douyin.com/..."}),(0,n.jsx)("div",{className:"mt-3 flex flex-wrap gap-2",children:(0,n.jsx)("button",{type:"button",disabled:tk,onClick:()=>void td(),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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播地址列表 \xb7 URL_config.ini","URL_config.ini")}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:a("一行一个地址;可自动刷新或手动重新读取。","One URL per line; auto-refresh or reload.")}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2 text-[11px]",children:[(0,n.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"),": ",tp]}),(0,n.jsxs)("span",{className:"rounded-full border border-violet-500/20 bg-violet-500/10 px-2.5 py-1 text-violet-100",children:["Douyin: ",tb]})]}),tS,$?(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:$}):null,(0,n.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,ej(e.target.value)},spellCheck:!1}),(0,n.jsx)("button",{type:"button",disabled:tk,onClick:()=>void tx(),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,n.jsx)(ev,{t:a,currentProc:x,fetchJson:g,urlListText:"single"===C?m:F,keySuffixUi:tc,showKeyRow:!0,pollMs:800,refreshToken:er})]})}var e2=s(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"],s=e,n=0;for(;s>=1024&&n=10||0===n?0:1)," ").concat(t[n])}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 s=(e||"").trim().toLowerCase();return"online"===s||"running"===s?t("运行中","Running"):"configured"===s?t("已配置","Configured"):"not_found"===s?t("未注册","Unregistered"):"stopped"===s?t("已停止","Stopped"):"error"===s?t("异常","Error"):e||"—"}function e7(){var e,t,s,L,M,T,U,E,I,D,A,Z,O,H,B,K,F,W,J,G,V,q,X,$,Q,ee,et,es,en,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,ts]=(0,_.useState)(!0),[tn,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,s]=await Promise.allSettled([tP("/hub/dashboard"),tP("/deploy/check")]);if("fulfilled"!==t.status)throw t.reason;let n=t.value;eG(n),eq(null),te(Date.now()),"fulfilled"===s.status?tf(s.value):tf(null);let l=(null===(e=n.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=()=>ts("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 s=new URLSearchParams({process:e,_ts:String(Date.now())}),n=await tP("/get_url_config?".concat(s));if(t!==tS.current||e!==tz.current.trim())return;td(n.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)||{},s={};for(let[e,n]of Object.entries(t))/^https?:\/\//i.test(n)?s[e]=(0,ex.p)(n):s[e]=n;return s},[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 s=await tP("/service_action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({service:e,action:t})});"error"===s.status?tR(s.detail||s.message||tC("操作失败","Action failed")):tR(s.message||"OK"),await tL()}catch(e){tR(e.message)}finally{e0(null)}},tA=async(e,t)=>{let s=(null!=t?t:ta).trim();if(s){e0("proc:".concat(e,":").concat(s));try{let t=await tP("/".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({process:s})});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 s=(null!=t?t:ta).trim();if(!s)return;let n=null!=e?e:tc,l=++tS.current;e0("save:url");try{let e=new URLSearchParams({process:s});await tP("/save_url_config?".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:n})}),l===tS.current&&s===tz.current.trim()&&td(n),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 s=await tP("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,serial:tm,payload:t})});tR(s.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 s=document.createElement("textarea");s.value=e,s.readOnly=!0,s.style.position="fixed",s.style.opacity="0",document.body.appendChild(s),s.select(),document.execCommand("copy"),s.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===(s=eJ.services)||void 0===s?void 0:s.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,n.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,n.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,n.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,n.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,n.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,n.jsxs)("div",{className:"relative z-10 flex min-h-screen",children:[(0,n.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,n.jsxs)("div",{className:"flex items-center gap-2 px-2",children:[(0,n.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,n.jsx)(m.Z,{className:"h-4 w-4 text-white"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-[0.2em] ".concat("light"===eH?"text-slate-500":"text-zinc-500"),children:"live.local"}),(0,n.jsx)("p",{className:"text-sm font-semibold ".concat("light"===eH?"text-slate-900":"text-white"),children:tC("无人直播系统","Unmanned Live System")})]})]}),(0,n.jsx)("nav",{className:"mt-10 flex flex-1 flex-col gap-1",children:tH.map(e=>{let t=e.icon,s=eK===e.id;return(0,n.jsxs)("button",{type:"button",onClick:()=>eF(e.id),"aria-current":s?"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?s?"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":s?"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,n.jsx)(t,{className:"h-4 w-4 ".concat("light"===eH?s?"text-violet-600":"text-slate-400":s?"text-violet-300":"text-zinc-600")}),tC(e.labelZh,e.labelEn),s?(0,n.jsx)(h.Z,{className:"ml-auto h-4 w-4 ".concat("light"===eH?"text-slate-400":"text-zinc-600")}):null]},e.id)})})]}),(0,n.jsxs)("div",{className:"flex min-w-0 flex-1 flex-col",children:[(0,n.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,n.jsxs)("div",{className:"flex min-w-0 items-center gap-3",children:[(0,n.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,n.jsx)(p.Z,{className:"h-5 w-5"})}),(0,n.jsxs)("div",{className:"min-w-0",children:[(0,n.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,n.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,n.jsxs)("div",{className:"flex shrink-0 items-center gap-1.5 sm:gap-2",children:[(0,n.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,n.jsx)(b.Z,{className:"h-5 w-5",strokeWidth:2}):(0,n.jsx)(g.Z,{className:"h-5 w-5",strokeWidth:2})}),(0,n.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,n.jsx)(f.Z,{className:"h-5 w-5",strokeWidth:2}),(0,n.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,n.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,n.jsx)(v.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,n.jsx)(y.Z,{className:"h-3.5 w-3.5"}),(0,n.jsx)("span",{className:"hidden sm:inline",children:tC("刷新","Refresh")})]})]})]}),(0,n.jsx)("main",{className:"flex-1 px-4 py-6 lg:px-8 lg:py-8",children:(0,n.jsx)(i.M,{mode:"wait",children:(0,n.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,n.jsxs)("div",{className:"space-y-6",children:[eV?(0,n.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,n.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,n.jsx)(R.Z,{snapshot:null!==(ew=null==eJ?void 0:eJ.snapshot)&&void 0!==ew?ew:null,theme:eH,tr:tC})}),(0,n.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,n.jsx)(C,{tr:tC})}),(0,n.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)),s=Math.floor(t/86400),n=Math.floor(t%86400/3600),l=Math.floor(t%3600/60);return s>0?"".concat(s,"d ").concat(n,"h"):n>0?"".concat(n,"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,n.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,n.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,n.jsx)(e.icon,{className:"h-4 w-4 text-violet-300/90"}),(0,n.jsx)("p",{className:"mt-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:e.label}),(0,n.jsx)("p",{className:"mt-0.5 font-mono text-lg font-semibold leading-tight text-white",children:eX?"…":e.value}),(0,n.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,n.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,n.jsx)("h3",{className:"text-base font-semibold text-white",children:tC("系统硬件与软件能力","Hardware & software profile")}),(0,n.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("来自 hardware_probe;用于直播/解码策略参考。","From hardware_probe; guides decode/streaming posture.")}),(0,n.jsxs)("div",{className:"mt-5 grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-indigo-300/90",children:tC("平台","Platform")}),(0,n.jsxs)("dl",{className:"space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"arch"}),(0,n.jsx)("dd",{className:"text-right text-zinc-200",children:String(null!==(ej=eJ.hardware.arch)&&void 0!==ej?ej:"—")})]}),(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"kernel"}),(0,n.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,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"Python"}),(0,n.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,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"mDNS"}),(0,n.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,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"IP"}),(0,n.jsx)("dd",{className:"text-right text-zinc-300",children:((null===(q=eJ.stack)||void 0===q?void 0:q.ips)||[]).join(" \xb7 ")||"—"})]})]})]}),(0,n.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,n.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,n.jsxs)("dl",{className:"space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"GPU"}),(0,n.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,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"render"}),(0,n.jsx)("dd",{className:"mt-0.5 break-all text-zinc-500",children:((null==e?void 0:e.render_nodes)||[]).join(", ")||"—"})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"NPU"}),(0,n.jsx)("dd",{className:"mt-0.5 break-all text-zinc-500",children:(null==t?void 0:t.present)?(t.devices||[]).join(", "):tC("—","—")})]})]})})()]}),(0,n.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4 lg:col-span-2",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-emerald-300/90",children:"ffmpeg / 建议策略"}),(()=>{var e,t,s,l;let i=eJ.hardware.ffmpeg_hwaccels||[],r=eJ.hardware.recommendation;return(0,n.jsxs)("div",{className:"space-y-2 text-[11px] text-zinc-400",children:[(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"hwaccels: "}),(0,n.jsx)("span",{className:"font-mono text-emerald-200/90",children:i.length?i.join(", "):"—"})]}),(0,n.jsxs)("div",{className:"grid gap-2 sm:grid-cols-2",children:[(0,n.jsxs)("p",{children:[(0,n.jsxs)("span",{className:"text-zinc-600",children:[tC("解码","Decoder"),": "]}),(0,n.jsx)("span",{className:"text-zinc-200",children:null!==(e=null==r?void 0:r.video_decoder)&&void 0!==e?e:"—"})]}),(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"HDMI: "}),(0,n.jsx)("span",{className:"text-zinc-200",children:null!==(t=null==r?void 0:r.hdmi_player)&&void 0!==t?t:"—"})]}),(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"Browser: "}),(0,n.jsx)("span",{className:"text-zinc-200",children:null!==(s=null==r?void 0:r.browser_hwaccel)&&void 0!==s?s:"—"})]}),(0,n.jsxs)("p",{children:[(0,n.jsxs)("span",{className:"text-zinc-600",children:[tC("稳定模式","Stability"),": "]}),(0,n.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,n.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,n.jsx)("li",{children:e},e))}):null]})})()]})]})]}):null,tg?(0,n.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,n.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("安装验收","Deployment health")}),(0,n.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,n.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,n.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:tC("验收摘要","Acceptance summary")}),(0,n.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,n.jsx)("span",{className:"ml-2 text-[11px] text-zinc-500",children:tC("已通过","checks passed")})]}),(0,n.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,n.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,s]=e;return(0,n.jsx)("a",{href:(0,ex.p)(s),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,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,n.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,n.jsx)("ul",{className:"mt-2 space-y-2 text-[11px] text-zinc-300",children:tg.failing_checks.slice(0,4).map(e=>(0,n.jsxs)("li",{className:"rounded-lg border border-amber-500/20 bg-amber-500/10 px-3 py-2",children:[(0,n.jsx)("span",{className:"font-semibold text-amber-100",children:e.label}),(0,n.jsx)("span",{className:"ml-2 text-zinc-400",children:e.detail||"—"})]},e.id))}):(0,n.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,n.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,n.jsx)("li",{children:e},e))}):null]})]})]}):null,(null==eJ?void 0:null===(Q=eJ.stack)||void 0===Q?void 0:Q.neko_login)?(0,n.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,n.jsxs)("h3",{className:"text-sm font-semibold text-white",children:["Neko ",tC("登录","sign-in")]}),(0,n.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,n.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,n.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:tE.map(e=>(0,n.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,n.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2 font-mono text-sm",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/40 px-4 py-3",children:[(0,n.jsx)("p",{className:"text-[10px] uppercase text-zinc-500",children:tC("昵称示例","Display Name Example")}),(0,n.jsx)("p",{className:"mt-1 text-fuchsia-200",children:null!==(eT=eJ.stack.neko_login.user_login)&&void 0!==eT?eT:"live"}),(0,n.jsx)("p",{className:"mt-2 text-[10px] uppercase text-zinc-500",children:tC("连接口令","Access Password")}),(0,n.jsx)("p",{className:"mt-0.5 text-fuchsia-100",children:null!==(eU=eJ.stack.neko_login.user_password)&&void 0!==eU?eU:"—"})]}),(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/40 px-4 py-3",children:[(0,n.jsx)("p",{className:"text-[10px] uppercase text-zinc-500",children:tC("管理昵称示例","Admin Display Name Example")}),(0,n.jsx)("p",{className:"mt-1 text-violet-200",children:null!==(eE=eJ.stack.neko_login.admin_login)&&void 0!==eE?eE:"admin"}),(0,n.jsx)("p",{className:"mt-2 text-[10px] uppercase text-zinc-500",children:tC("管理口令","Admin Password")}),(0,n.jsx)("p",{className:"mt-0.5 text-violet-100",children:null!==(eI=eJ.stack.neko_login.admin_password)&&void 0!==eI?eI:"—"})]})]}),(0,n.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,n.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,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(k.Z,{className:"h-4 w-4 text-cyan-300"}),tC("网络带宽 / 流量","Network bandwidth / traffic")]}),(0,n.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,n.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,n.jsx)("p",{className:"text-[10px] uppercase tracking-[0.08em] text-cyan-300/70",children:tC("实时下行","Live down")}),(0,n.jsx)("p",{className:"mt-1 text-lg font-semibold text-cyan-100",children:e6(eJ.network.total_rx_bps)}),(0,n.jsxs)("p",{className:"mt-1 text-zinc-500",children:[tC("累计","Total"),": ",e4(eJ.network.total_rx_bytes)]})]}),(0,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,n.jsx)("p",{className:"text-[10px] uppercase tracking-[0.08em] text-cyan-300/70",children:tC("实时上行","Live up")}),(0,n.jsx)("p",{className:"mt-1 text-lg font-semibold text-cyan-100",children:e6(eJ.network.total_tx_bps)}),(0,n.jsxs)("p",{className:"mt-1 text-zinc-500",children:[tC("累计","Total"),": ",e4(eJ.network.total_tx_bytes)]})]})]}),(0,n.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,s,l,i;return(0,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,n.jsx)("p",{className:"text-xs font-semibold text-cyan-200/90",children:e.name}),(0,n.jsxs)("p",{className:"mt-2 text-zinc-500",children:[tC("链路","Link"),": ",e.operstate||"unknown"," ",(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e.speed_mbps?"".concat(e.speed_mbps," Mbps"):tC("未知速率","unknown speed")]}),(0,n.jsxs)("p",{className:"mt-2 text-zinc-500",children:["↓ ",e6(e.rx_bps)," ",(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e4(e.rx_bytes)," ",(0,n.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,n.jsxs)("p",{className:"mt-0.5 text-zinc-500",children:["↑ ",e6(e.tx_bps)," ",(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e4(e.tx_bytes)," ",(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",null!==(i=null===(s=e.tx_packets)||void 0===s?void 0:s.toLocaleString())&&void 0!==i?i:"—"," pkt"]})]},e.name)})})]}):null,(null==eJ?void 0:null===(en=eJ.live_events)||void 0===en?void 0:null===(es=en.pm2_tail)||void 0===es?void 0:es.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,n.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-amber-500/15 bg-zinc-950/40 p-5",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("直播 / PM2 事件","Live / PM2 feed")}),(0,n.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("PM2 合并日志尾部","PM2 merged log tail")}),(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-violet-500/15 bg-zinc-950/40 p-5",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("进程快照","Process digest")}),(0,n.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,n.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,n.jsx)("span",{className:"truncate text-zinc-300",children:e.label||e.pm2}),(0,n.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,n.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,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("直播进程","Live processes")}),(0,n.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,n.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,n.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,n.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,n.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,n.jsx)("p",{className:"truncate text-sm font-medium text-zinc-100",children:e.label||e.pm2}),(0,n.jsx)("p",{className:"truncate font-mono text-[10px] text-zinc-600",children:e.script||e.pm2})]}),(0,n.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,n.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,n.jsxs)("div",{className:"mt-5 grid grid-cols-2 gap-2",children:[(0,n.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,n.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,n.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:[eJ.probes.srs?(()=>{var e,t,s,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===(s=o.tcp_api)||void 0===s?void 0:s.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-zinc-950/40 p-4 backdrop-blur-sm",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsx)("p",{className:"text-xs font-semibold text-white",children:"SRS"}),(0,n.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,n.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,n.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,n.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,n.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,s,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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-zinc-950/40 p-4 backdrop-blur-sm",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsx)("p",{className:"text-xs font-semibold text-white",children:"Neko Chromium"}),(0,n.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,n.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,n.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,n.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===(s=o.tcp)||void 0===s?void 0:s.latency_ms)!=null?"".concat(o.tcp.latency_ms," ms"):"—"]}),x.length?(0,n.jsx)("div",{className:"mt-3 space-y-2",children:x.map(e=>{var t,s,l,i,r,a,o;return(0,n.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,n.jsxs)("div",{className:"min-w-0",children:[(0,n.jsxs)("p",{className:"text-[11px] font-semibold text-zinc-200",children:["Neko ",null!==(r=e.id)&&void 0!==r?r:"?"]}),(0,n.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===(s=e.http)||void 0===s?void 0:s.http_code)&&void 0!==o?o:"—"]})]}),(0,n.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,n.jsx)("p",{className:"mt-1 line-clamp-2 text-[10px] text-amber-200/80",children:d.error}):null]})})():null]}):null]}):null,"services"===eK?(0,n.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,n.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,n.jsxs)("div",{className:"flex items-start justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"font-semibold text-white",children:e.label}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500 line-clamp-2",children:e.description})]}),(0,n.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,n.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,n.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,n.jsxs)("div",{className:"mt-4 flex flex-wrap items-center gap-2",children:[e.url?(0,n.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,n.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,n.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,n.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,n.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,n.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,n.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,n.jsx)("p",{className:"text-sm text-zinc-500",children:tC("暂无服务数据","No services")})]}):null,"live_youtube"===eK?(0,n.jsx)(e5,{t:tC,busy:eQ,entries:tn,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,n.jsx)(ez,{t:tC,busy:!!eQ,entries:tn,currentProc:ta,setCurrentProc:to,urlConfig:tc,setUrlConfig:td,onRunProcess:e=>void tA(e),onSaveUrlConfig:e=>tZ(e),onReplayGoLive:async(e,t)=>{let s=t.replace(/[,,|]/g,"_");await tZ("原画,".concat(e,",主播: ").concat(s)),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,n.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,n.jsxs)("div",{className:"mx-auto max-w-7xl space-y-6",children:[(0,n.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,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold ".concat("light"===eH?"text-slate-900":"text-white"),children:[(0,n.jsx)(k.Z,{className:"h-4 w-4 ".concat("light"===eH?"text-violet-600":"text-violet-300")}),tC("ShellCrash 网络面板","ShellCrash panel")]}),(0,n.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,n.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,n.jsxs)("div",{className:"flex items-center gap-4",children:[(0,n.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,n.jsx)(h.Z,{className:"hidden h-5 w-5 sm:block ".concat("light"===eH?"text-slate-400":"text-zinc-600")}):null]},e.tx))})]}),(0,n.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,n.jsx)("div",{className:"max-h-[min(78vh,56rem)] min-h-[22rem] overflow-y-auto overflow-x-hidden",children:(0,n.jsx)(P.d,{embeddedShellCrash:!0,portalLang:eZ})})})]}):null,"settings"===eK?(0,n.jsxs)("div",{className:"mx-auto max-w-lg space-y-6",children:[(0,n.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,n.jsxs)("div",{className:"space-y-4 rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,n.jsxs)("label",{className:"flex cursor-pointer items-center justify-between gap-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("p",{className:"text-sm font-medium text-white",children:tC("总览自动刷新","Auto-refresh dashboard")}),(0,n.jsx)("p",{className:"text-[11px] text-zinc-500",children:"10s"})]}),(0,n.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,n.jsxs)("label",{className:"flex cursor-pointer items-center justify-between gap-4 border-t border-white/[0.06] pt-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("p",{className:"text-sm font-medium text-white",children:tC("总览显示 SRS / Neko 探针","Show SRS/Neko probes")}),(0,n.jsx)("p",{className:"text-[11px] text-zinc-500",children:tC("关闭可精简首页","Hide stream probe cards")})]}),(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/40 p-5",children:[(0,n.jsx)("p",{className:"text-xs font-semibold uppercase tracking-wider text-zinc-500",children:tC("配置快照","Config snapshot")}),(0,n.jsx)("p",{className:"mt-2 font-mono text-[11px] text-zinc-400",children:String((null==tp?void 0:tp.config_root)||"—")}),(0,n.jsxs)("p",{className:"mt-3 text-sm text-zinc-300",children:[tC("主机名","Hostname"),":"," ",(0,n.jsx)("span",{className:"font-mono text-violet-200",children:(()=>{var e,t,s;let n=null==tp?void 0:tp.system;return(null==n?void 0:null===(t=n.identity)||void 0===t?void 0:null===(e=t.hostname_alias)||void 0===e?void 0:e.trim())||((null==eJ?void 0:null===(s=eJ.stack)||void 0===s?void 0:s.mdns_host)||"").replace(/\.local$/i,"")||"—"})()})]}),(0,n.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,n.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,n.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,n.jsx)(z.Z,{className:"h-4 w-4"})]})]}):null]},eK)})})]})]}),(0,n.jsx)(i.M,{children:eW?(0,n.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,n.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,n.jsx)("div",{className:"flex justify-end",children:(0,n.jsx)("button",{type:"button",onClick:()=>eY(!1),className:"rounded-lg p-2",children:(0,n.jsx)(S.Z,{className:"h-5 w-5"})})}),(0,n.jsx)("nav",{className:"mt-4 flex flex-col gap-1",children:tH.map(e=>{let t=e.icon,s=eK===e.id;return(0,n.jsxs)("button",{type:"button",onClick:()=>{eF(e.id),eY(!1)},"aria-current":s?"page":void 0,className:"flex items-center gap-3 rounded-xl px-3 py-3 text-left text-sm transition ".concat(s?"bg-white/[0.08] text-white shadow-inner shadow-white/5":"text-zinc-300 hover:bg-white/[0.04]"),children:[(0,n.jsx)(t,{className:"h-4 w-4 ".concat(s?"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],{4578:function(e,t,s){Promise.resolve().then(s.bind(s,1499))},1499:function(e,t,s){"use strict";s.r(t),s.d(t,{default:function(){return e7}});var n=s(7437),l=s(6247),i=s(7586),r=s(4401),a=s(6137),o=s(4372),c=s(5901),d=s(3388),x=s(3420),u=s(8728),m=s(2023),h=s(407),p=s(6840),b=s(7226),g=s(5929),f=s(7945),v=s(1817),y=s(7168),w=s(4822),N=s(4428),j=s(1723),k=s(2926),z=s(7580),S=s(2489),_=s(2265);function C(e){let{tr:t}=e,l=(0,_.useRef)(null);return(0,_.useEffect)(()=>{let e;if(!l.current)return;let t=!1,n=0;return s.e(689).then(s.bind(s,1448)).then(s=>{if(t||!l.current)return;let i=l.current,r=Math.max(i.clientWidth,280),a=Math.max(i.clientHeight,200),o=new s.Scene,c=new s.PerspectiveCamera(48,r/a,.1,80);c.position.set(0,1.1,7.2);let d=new s.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 s.HemisphereLight(16762092,4482815,.85);o.add(x);let u=new s.DirectionalLight(16777215,.9);u.position.set(4,8,6),o.add(u);let m=new s.PointLight(8189439,.6,20);m.position.set(-3,2,-2),o.add(m);let h=new s.Group,p=new s.Mesh(new s.BoxGeometry(3.2,.35,2.2),new s.MeshStandardMaterial({color:2762048,metalness:.15,roughness:.55}));p.position.y=-.85,h.add(p);let b=new s.Mesh(new s.TorusGeometry(.72,.09,12,48),new s.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 s.Mesh(new s.ConeGeometry(.35,.5,3),new s.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 s.Mesh(new s.CylinderGeometry(.22,.28,.95,20),new s.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 s.Mesh(new s.SphereGeometry(.26,16,16),new s.MeshStandardMaterial({color:16657493,emissive:2229520,metalness:.2,roughness:.4}));v.position.set(1.05,.92,-.15),h.add(v);let y=new s.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 s.BufferAttribute(w,3));let N=new s.Points(y,new s.PointsMaterial({color:16777215,size:.06,transparent:!0,opacity:.7}));o.add(N),o.add(h);let j=performance.now(),k=()=>{if(t)return;n=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),s=Math.max(l.current.clientHeight,200);c.aspect=e/s,c.updateProjectionMatrix(),d.setSize(e,s)});z.observe(i),e=()=>{cancelAnimationFrame(n),z.disconnect(),d.dispose(),y.dispose(),d.domElement.parentNode===i&&i.removeChild(d.domElement)}}),()=>{t=!0,cancelAnimationFrame(n),null==e||e()}},[]),(0,n.jsxs)("div",{className:"flex h-full min-h-[14rem] flex-col",children:[(0,n.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,n.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=s(9170),P=s(2246),L=s(4286),M=s(4794),T=s(221),U=s(8867),E=s(8124),I=s(2101),D=s(3651),A=s(9985),Z=s(6362),O=s(3468),H=s(6443),B=s(5287),K=s(3276),F=s(9227),W=s(257),Y=s(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 s=new Uint8Array(e.length+t.length);return s.set(e,0),s.set(t,e.length),s}(this.buf,t),this.drainAvcc()}drainAvcc(){let e=this.buf,t=0;for(;t+4<=e.length;){var s;let n=e[s=t]<<24|e[s+1]<<16|e[s+2]<<8|e[s+3];if(n<=0||n>6291456){this.buf=new Uint8Array(e.subarray(t+1)),t=0;continue}if(t+4+n>e.length)break;let l=e.subarray(t+4,t+4+n);t+=4+n,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 s=new Uint8Array(4+e.length);new DataView(s.buffer).setUint32(0,e.length,!1),s.set(e,4);try{let e=new EncodedVideoChunk({type:5===t?"key":"delta",timestamp:this.ts,data:s});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 s=e.subarray(1),n=t.subarray(1),l=new Uint8Array(11+s.length+3+n.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++]=s.length>>8&255,l[i++]=255&s.length,l.set(s,i),i+=s.length,l[i++]=1,l[i++]=n.length>>8&255,l[i++]=255&n.length,l.set(n,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),s=new VideoDecoder({output:e=>{var t;let s=this.canvas.getContext("2d");if(!s){e.close();return}(this.canvas.width!==e.displayWidth||this.canvas.height!==e.displayHeight)&&(this.canvas.width=e.displayWidth,this.canvas.height=e.displayHeight),s.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 s.configure({codec:t,description:e,optimizeForLatency:!0}),this.decoder=s,this.configured=!0}catch(e){this.onDecodeError(e.message||String(e))}finally{this.configuring=!1}}}constructor(e,t,s){this.canvas=e,this.onDecodeError=t,this.onFrame=s,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,s){let n,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?(n=a.width,l=a.width/x,i=0,r=(a.height-l)/2):(l=a.height,n=a.height*x,i=(a.width-n)/2,r=0);let u=t-a.left-i,m=s-a.top-r;return u<0||m<0||u>n||m>l?null:{x:Math.max(0,Math.min(o-1,Math.round(u/n*o))),y:Math.max(0,Math.min(c-1,Math.round(m/l*c)))}}function X(e,t,s){let n,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?(n=a.width,l=a.width/x,i=0,r=(a.height-l)/2):(l=a.height,n=a.height*x,i=(a.width-n)/2,r=0);let u=t-a.left-i,m=s-a.top-r;return u<0||m<0||u>n||m>l?null:{x:Math.max(0,Math.min(o-1,Math.round(u/n*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 es(e,t){let s=t.startsWith("/")?t:"/".concat(t),n=(e||"").trim().replace(/\/$/,"");return n?"".concat(n).concat(s):s}function en(e){var t;let{t:s,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,en]=(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(es(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 n=[t,...er.filter(e=>e!==t)].slice(0,16);ea(n);try{window.localStorage.setItem(V,JSON.stringify(n))}catch(e){}p(s("已保存快捷地址","Saved quick address"))};(0,_.useEffect)(()=>{if(!r||!c){C(null);return}let e=!1;return(async()=>{try{let t=await (0,Y.N)("".concat(es(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)(es(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(s("当前浏览器不支持 WebCodecs H.264","WebCodecs H.264 not supported in this browser")),ec(!1);return}let n=eN.current;if(!n)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(n,e=>i("".concat(s("实时画面解码失败,已切回截图模式","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 s=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1920,n=(function(e){let t=(e||"").trim();if(t)try{let e=new URL(t,window.location.href),s="https:"===e.protocol?"wss:":"ws:";return"".concat(s,"//").concat(e.host)}catch(e){}let s=void 0!==W&&W.env.NEXT_PUBLIC_API_URL?String(W.env.NEXT_PUBLIC_API_URL).trim():"";if(s)try{let e=new URL(s,window.location.href),t="https:"===e.protocol?"wss:":"ws:";return"".concat(t,"//").concat(e.host)}catch(e){}let n=window.location.port;if("3000"===n||"3001"===n){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(s)});return"".concat(n,"/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(s("实时画面无首帧,已切回截图模式","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(s("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(s("实时画面连接失败,已切回截图模式","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,s]),(0,_.useEffect)(()=>{r&&c&&(eS.current=0,f(e=>e+1))},[r,c]);let eI=async()=>{let e=L.trim();if(!e){p(s("填写 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":s("连接结果见日志","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,n=D.trim();if(!e||!n){p(s("填写配对 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:n})});p(l.message||(l.ok?s("配对成功后再点连接","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 n=X(t,e.clientX,e.clientY);if(!n)return;let l=Date.now(),i=ey.current;i&&l-i.t<320&&28>Math.abs(i.x-n.x)&&28>Math.abs(i.y-n.y)?(ey.current=null,await h("double_tap",{x:n.x,y:n.y}),p(s("双击","Double tap"))):(ey.current={t:l,x:n.x,y:n.y},await h("tap",{x:n.x,y:n.y})),eT()},eO=async e=>{if(e.preventDefault(),x||!c||!r)return;let t=ew.current;if(!t)return;let n=X(t,e.clientX,e.clientY);n&&(await h("long_press",{x:n.x,y:n.y,duration:720}),p(s("长按","Long press")),eT())},eH=async e=>{if(!R||x||!c||!r)return;let t=eN.current;if(!t)return;let n=q(t,e.clientX,e.clientY);if(!n)return;let l=Date.now(),i=ey.current;i&&l-i.t<320&&28>Math.abs(i.x-n.x)&&28>Math.abs(i.y-n.y)?(ey.current=null,await h("double_tap",{x:n.x,y:n.y}),p(s("双击","Double tap"))):(ey.current={t:l,x:n.x,y:n.y},await h("tap",{x:n.x,y:n.y})),eo||eT()},eB=async e=>{if(e.preventDefault(),x||!c||!r)return;let t=eN.current;if(!t)return;let n=q(t,e.clientX,e.clientY);n&&(await h("long_press",{x:n.x,y:n.y,duration:720}),p(s("长按","Long press")),eo||eT())};if(!c)return(0,n.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:s("宿主机未安装 adb,无法使用 Live 控制台。","adb is required for the Live console.")});let eK=Q(eP),eF=eK.Icon;return(0,n.jsxs)("div",{className:"space-y-5",children:[(0,n.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,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-white/[0.06] pb-3",children:[(0,n.jsx)(A.Z,{className:"h-4 w-4 text-sky-400"}),(0,n.jsx)("h4",{className:"text-sm font-semibold text-white",children:s("链路管理","Link manager")}),(0,n.jsx)("span",{className:"text-[10px] text-zinc-500",children:s("USB / Redroid :5555 / 无线调试(先配对再连接)","USB \xb7 Redroid :5555 \xb7 wireless (pair then connect)")})]}),(0,n.jsxs)("div",{className:"mt-3 grid gap-3 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"space-y-2 rounded-xl border border-white/[0.06] bg-black/35 p-3",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"adb connect"}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.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,n.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,n.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:s("存书签","Pin")})]}),er.length?(0,n.jsx)("div",{className:"flex flex-wrap gap-1.5 pt-1",children:er.map(e=>(0,n.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,n.jsxs)("div",{className:"flex flex-wrap gap-2 pt-2",children:[(0,n.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:s("断开当前 TCP","Disconnect current")}),(0,n.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:s("断开全部 TCP","Disconnect all TCP")}),(0,n.jsxs)("button",{type:"button",disabled:el||x,onClick:()=>{b(),eT(),p(s("已刷新设备列表","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,n.jsx)(y.Z,{className:"h-3 w-3"}),"ADB list"]})]})]}),(0,n.jsxs)("div",{className:"space-y-2 rounded-xl border border-white/[0.06] bg-black/35 p-3",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:"adb pair(无线调试)"}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.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,n.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,n.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=>en(e.target.value)}),(0,n.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,n.jsx)("p",{className:"text-[10px] leading-relaxed text-zinc-600",children:s("手机上「无线调试」会显示配对端口与 6 位码;配对成功后用上方 connect 连接 adb 显示的 IP:5555。","Use the pairing port + 6-digit code from Wireless debugging; then connect to the listed adb IP:5555.")})]})]})]}),(0,n.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,n.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,n.jsxs)("div",{className:"relative rounded-[1.35rem] border border-white/[0.06] bg-zinc-950/80 p-4 backdrop-blur-sm",children:[(0,n.jsxs)("div",{className:"flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between",children:[(0,n.jsxs)("div",{className:"flex items-start gap-3",children:[(0,n.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,n.jsx)(m.Z,{className:"h-6 w-6 text-emerald-200"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"text-base font-semibold tracking-tight text-white",children:s("无人直播系统 \xb7 ADB 云控台","Unmanned Live System \xb7 ADB farm console")}),(0,n.jsxs)("p",{className:"mt-1 max-w-xl text-[11px] leading-relaxed text-zinc-500",children:[s("统一适配 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,n.jsx)("a",{href:et,target:"_blank",rel:"noreferrer",className:"text-emerald-300/90 underline-offset-2 hover:underline",children:"escrcpy"}),s(" / "," / "),(0,n.jsx)("a",{href:ee,target:"_blank",rel:"noreferrer",className:"text-emerald-300/90 underline-offset-2 hover:underline",children:"scrcpy"}),s(");无 jar 或关闭真流时用截图。","); PNG screenshot when jar missing or stream off.")]})]})]}),(0,n.jsxs)("div",{className:"flex shrink-0 flex-col gap-1.5 self-start sm:flex-row",children:[(0,n.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,n.jsx)(Z.Z,{className:"h-3.5 w-3.5 opacity-70"})]}),(0,n.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,n.jsx)(Z.Z,{className:"h-3.5 w-3.5 opacity-70"})]})]})]}),a.length>0?(0,n.jsxs)("div",{className:"mt-5",children:[(0,n.jsxs)("p",{className:"mb-2 flex items-center gap-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:[(0,n.jsx)(O.Z,{className:"h-3.5 w-3.5"}),s("设备矩阵","Device matrix")]}),(0,n.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,n.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,n.jsxs)("span",{className:"flex items-center gap-1.5 text-xs font-medium text-zinc-200",children:[(0,n.jsx)(d.Z,{className:"h-3.5 w-3.5 text-emerald-400/80"}),(0,n.jsx)("span",{className:"truncate",children:e.model||e.serial.slice(0,10)})]}),(0,n.jsx)("span",{className:"mt-0.5 truncate font-mono text-[9px] text-zinc-600",children:e.serial}),(0,n.jsxs)("div",{className:"mt-1 flex flex-wrap gap-1",children:[(0,n.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,n.jsx)(a,{className:"h-2.5 w-2.5"}),s(i.zh,i.en)]}),(0,n.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,n.jsxs)("div",{className:"mt-6 grid gap-6 xl:grid-cols-12",children:[(0,n.jsxs)("div",{className:"xl:col-span-8",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2 border-b border-white/[0.06] pb-3",children:[(0,n.jsx)("span",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:s("刷新间隔","Interval")}),$.map(e=>(0,n.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?s("手动","Manual"):"".concat(e,"ms")},e)),(0,n.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,n.jsx)(eF,{className:"h-3 w-3"}),"tcp"===eP?s("建议 ≥450ms","Suggest ≥450ms"):s("可试 280ms","Try 280ms")]}),(0,n.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,n.jsx)(y.Z,{className:"h-3 w-3 ".concat(N?"animate-spin":"")}),s("下一帧","Next frame")]}),(0,n.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,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-1.5 text-[10px] text-zinc-400",children:[(0,n.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/50",checked:R,onChange:e=>P(e.target.checked)}),(0,n.jsx)(H.Z,{className:"h-3 w-3"}),s("点按穿透","Tap-through")]}),(0,n.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:s("官方 scrcpy-server + WebSocket H.264","Official scrcpy-server + WebSocket H.264"),onClick:()=>{ec(e=>{let t=!e;return t?(ex(null),p(s("已开启实时画面(H.264 WebSocket)","Live H.264 WebSocket stream on"))):(r&&ex(r),p(s("已关闭实时画面(将使用截图)","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,n.jsx)(B.Z,{className:"h-3 w-3"}),eo?s("关闭真流","Stop WS"):s("实时画面","Live H.264")]})]}),eb&&!eb.server_jar?(0,n.jsxs)("p",{className:"mt-2 text-[10px] text-amber-200/80",children:[s("未检测到 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(s("期望版本","version")," ").concat(eb.server_version,")"):null]}):null,(0,n.jsx)("p",{className:"mt-2 text-[10px] text-zinc-600",children:s("快捷键(镜像区聚焦时):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,n.jsxs)("div",{className:"relative mx-auto mt-4 max-h-[min(78vh,720px)] min-h-[280px]",children:[r?(0,n.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 s={h:["key",{keycode:"3"}],b:["key",{keycode:"4"}],r:["key",{keycode:"187"}],w:["wake",void 0],m:["key",{keycode:"82"}]}[e.key.toLowerCase()];s&&(e.preventDefault(),(async()=>{await h(s[0],s[1]),eo||eT()})())},className:"relative flex justify-center outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/50",children:[(0,n.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,n.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,n.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,n.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(s("截图连续失败:检查 USB 授权 / 无线是否断开 / Redroid 端口","Screenshot failed repeatedly"))},onClick:eZ,onContextMenu:eO})]}),eu?(0,n.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,n.jsx)(B.Z,{className:"h-3 w-3"}),"SCRCPY\xb7WS"]}):v>0&&!eo?(0,n.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,n.jsx)(K.Z,{className:"h-3 w-3"}),"LIVE"]}):eo?null:(0,n.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,n.jsx)(F.Z,{className:"h-3 w-3"}),s("单帧","Still")]})]}):(0,n.jsx)("p",{className:"py-16 text-center text-sm text-zinc-600",children:s("请选择或连接设备","Pick or connect a device")}),eh?(0,n.jsx)("p",{className:"mt-3 text-center text-xs text-rose-300",children:eh}):null,k&&!eo?(0,n.jsx)("p",{className:"mt-3 text-center text-xs text-rose-300",children:k}):null,(0,n.jsx)("p",{className:"mt-3 text-center text-[10px] text-zinc-600",children:s("左键单击 / 双击 \xb7 右键长按 \xb7 坐标对齐 PNG 像素","Left tap/double \xb7 right long-press \xb7 PNG pixel coords")})]})]}),(0,n.jsxs)("div",{className:"space-y-4 xl:col-span-4",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-black/40 p-4",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:s("遥测","Telemetry")}),u?(0,n.jsxs)("dl",{className:"mt-3 space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"device"}),(0,n.jsxs)("dd",{className:"text-right text-zinc-200",children:[u.brand," ",u.model]})]}),(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"Android"}),(0,n.jsxs)("dd",{className:"text-zinc-300",children:[u.android_version," (API ",u.sdk,")"]})]}),(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"wm size"}),(0,n.jsx)("dd",{className:"text-cyan-300/90",children:S?"".concat(S.width,"\xd7").concat(S.height):u.resolution||"—"})]}),(0,n.jsx)("div",{className:"whitespace-pre-wrap text-[10px] leading-snug text-zinc-500",children:u.battery})]}):(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-600",children:s("在上方点「刷新设备信息」","Use Refresh device info above")})]}),(0,n.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,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-violet-300/80",children:s("导航坞","Nav dock")}),(0,n.jsx)("div",{className:"mt-3 grid grid-cols-3 gap-2",children:[["3","Home"],["4","Back"],["187","Recents"]].map(e=>{let[t,s]=e;return(0,n.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:s},t)})}),(0,n.jsxs)("div",{className:"mt-2 grid grid-cols-2 gap-2",children:[(0,n.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,n.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,n.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-cyan-500/[0.05] p-4",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-cyan-300/80",children:s("手势","Gestures")}),(0,n.jsx)("div",{className:"mt-2 grid grid-cols-2 gap-2",children:["up","down","left","right"].map(e=>(0,n.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,s){return e?(0,n.jsx)("span",{className:"rounded bg-emerald-500/15 px-2 py-0.5 text-[10px] text-emerald-200",children:t}):(0,n.jsx)("span",{className:"rounded bg-zinc-500/15 px-2 py-0.5 text-[10px] text-zinc-400",children:s})}function er(e){var t,s,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"),[es,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,s;let n=await y("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:"shell",serial:j,payload:{command:e}})});Q(null!==(s=null!==(t=n.output)&&void 0!==t?t:n.message)&&void 0!==s?s:"")}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)),s=!!(null==e?void 0:e.silent);s||ey("logcat"),eo(null);try{var n;let e=await y("/android/logcat?serial=".concat(encodeURIComponent(j),"&lines=").concat(t));er(null!==(n=e.text)&&void 0!==n?n:"")}catch(e){er(""),eo(e.message)}finally{s||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 s=await y("/redroid/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,name:t||""})});s.summary&&K(s.summary),f(s.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,n.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("安卓设备工作台","Android workstation")}),(0,n.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,n.jsxs)("div",{className:"flex gap-2",children:[(0,n.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,n.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,n.jsx)("span",{className:"text-xs text-amber-200/90",children:g("宿主机未检测到 adb","adb not found on host")})]}),(0,n.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:z.map(e=>(0,n.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,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)("span",{className:"font-medium text-zinc-200",children:e.model||e.serial}),e.transport?(0,n.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,n.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,n.jsx)("div",{className:"text-[10px] text-zinc-600",children:e.serial}),"device"!==(e.state||"").toLowerCase()?(0,n.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,n.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,n.jsxs)("div",{className:"grid gap-4 xl:grid-cols-[1.1fr_0.9fr]",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-violet-500/15 bg-zinc-950/50 p-5",children:[(0,n.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-violet-300/90",children:g("真机诊断","Phone diagnostics")}),O?(0,n.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:O}):null,A?(0,n.jsxs)("div",{className:"mt-3 space-y-3",children:[(0,n.jsxs)("dl",{className:"space-y-1.5 font-mono text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"model"})," ",(0,n.jsxs)("dd",{className:"inline text-zinc-300",children:[A.brand," ",A.model]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"android"})," ",(0,n.jsxs)("dd",{className:"inline text-zinc-300",children:[A.android_version," (sdk ",A.sdk,")"]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"kind"})," ",(0,n.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,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"display"})," ",(0,n.jsx)("dd",{className:"inline text-zinc-300",children:A.resolution})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"inline text-zinc-600",children:"rotation"})," ",(0,n.jsx)("dd",{className:"inline text-zinc-300",children:A.rotation})]}),(0,n.jsx)("div",{className:"whitespace-pre-wrap text-[10px] leading-snug text-zinc-500",children:A.battery}),(0,n.jsx)("div",{className:"line-clamp-3 text-[10px] text-zinc-500",children:A.focus})]}),(0,n.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===(s=A.diagnostics)||void 0===s?void 0:s.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,n.jsxs)("div",{className:"rounded-xl border border-white/5 bg-black/20 p-3 text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{children:["boot_completed: ",(null===(a=A.diagnostics)||void 0===a?void 0:a.boot_completed)||"-"]}),(0,n.jsxs)("div",{children:["provisioned: ",(null===(o=A.diagnostics)||void 0===o?void 0:o.device_provisioned)||"-"]}),(0,n.jsxs)("div",{children:["setup_complete: ",(null===(c=A.diagnostics)||void 0===c?void 0:c.user_setup_complete)||"-"]}),(0,n.jsxs)("div",{children:["abi: ",(null===(d=A.diagnostics)||void 0===d?void 0:d.abi)||"-"]}),(0,n.jsxs)("div",{className:"truncate",children:["hardware: ",(null===(x=A.diagnostics)||void 0===x?void 0:x.hardware)||"-"]})]})]}):O?null:(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:g("加载中","Loading")})]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-cyan-500/15 bg-zinc-950/50 p-5",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-3",children:[(0,n.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-cyan-300/90",children:g("Redroid 板块","Redroid panel")}),(0,n.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,n.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:F}):null,B?(0,n.jsxs)("div",{className:"mt-3 space-y-3 text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,n.jsxs)("div",{children:["arch: ",B.arch||"-"]}),(0,n.jsxs)("div",{className:"truncate",children:["image: ",B.image||"-"]}),(0,n.jsxs)("div",{children:["profile: ",B.device_profile||"-"]}),(0,n.jsxs)("div",{children:["gpu: ",B.gpu_mode||"-"]}),(0,n.jsxs)("div",{children:["adb: 127.0.0.1:",B.default_port||5555]})]}),(0,n.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,n.jsxs)("div",{className:"space-y-2",children:[(B.instances||[]).map(e=>{var t,s,l,i;return(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-3",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"font-medium text-zinc-100",children:e.name}),(0,n.jsxs)("div",{className:"font-mono text-[10px] text-zinc-500",children:[e.port?"127.0.0.1:".concat(e.port):"-"," / ",e.status_text||"-"]})]}),(0,n.jsxs)("div",{className:"flex gap-1",children:[(0,n.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,n.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,n.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,n.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,n.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===(s=e.diagnostics)||void 0===s?void 0:s.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,n.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,n.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,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:g("读取 Redroid 状态中","Loading Redroid status")})]})]}),(0,n.jsx)(en,{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,n.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,n.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-emerald-300/90",children:g("快捷控制","Quick controls")}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,n.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,n.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,n.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,n.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,n.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,n.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,n.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,n.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,n.jsx)("p",{className:"mt-3 text-[10px] text-zinc-600",children:g("滑动手势","Swipe gestures")}),(0,n.jsx)("div",{className:"mt-1 flex flex-wrap gap-2",children:["up","down","left","right"].map(e=>(0,n.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,n.jsxs)("div",{className:"mt-4 rounded-lg border border-white/5 bg-black/20 p-3",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:g("ADB 文本输入","ADB text input")}),(0,n.jsxs)("div",{className:"mt-2 flex flex-col gap-2 sm:flex-row",children:[(0,n.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,n.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,n.jsxs)("div",{className:"mt-4 flex flex-col gap-2 sm:flex-row sm:items-center",children:[(0,n.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,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,n.jsxs)("h4",{className:"flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-cyan-300/90",children:[(0,n.jsx)(L.Z,{className:"h-4 w-4"}),g("USB 真机优化建议","USB optimization")]}),(0,n.jsxs)("ul",{className:"mt-3 space-y-2 text-xs leading-relaxed text-zinc-400",children:[(0,n.jsx)("li",{children:g("优先使用主板直连 USB,不要经过不稳的 HUB。","Prefer direct motherboard USB, not unstable hubs.")}),(0,n.jsx)("li",{children:g("开发板端固定 adb server,避免频繁 kill-server。","Keep adb server stable and avoid frequent kill-server.")}),(0,n.jsx)("li",{children:g("镜像页默认支持 scrcpy H.264 真流,截图模式作为回退。","Use scrcpy H.264 live stream first, screenshot mode as fallback.")}),(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(M.Z,{className:"h-4 w-4 text-emerald-400"}),g("包名搜索与启动","Packages")]}),(0,n.jsxs)("div",{className:"mt-3 flex flex-col gap-2 sm:flex-row",children:[(0,n.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,n.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,n.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,n.jsxs)("li",{className:"flex flex-wrap items-center justify-between gap-2 py-1 text-zinc-400",children:[(0,n.jsx)("span",{className:"min-w-0 truncate text-zinc-300",children:e.package}),(0,n.jsxs)("span",{className:"flex shrink-0 gap-1",children:[(0,n.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,n.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,n.jsx)("li",{className:"py-2 text-center text-zinc-600",children:g("暂无结果","No results")})]})]}):null,S&&j?(0,n.jsxs)("div",{className:"grid gap-6 xl:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(T.Z,{className:"h-4 w-4 text-amber-400"}),"ADB shell"]}),(0,n.jsx)("div",{className:"mt-2 flex flex-wrap gap-1.5",children:el.map(e=>(0,n.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,n.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,n.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[(0,n.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,n.jsxs)("span",{className:"inline-flex items-center gap-2",children:[(0,n.jsx)(v.Z,{className:"h-3.5 w-3.5 animate-spin"}),"Run"]}):"Run"}),$?(0,n.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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"}),g("复制输出","Copy")]}):null]}),$?(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("Logcat","Logcat")}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap items-center gap-2",children:[(0,n.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,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 text-[11px] text-zinc-400",children:[(0,n.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,n.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")}),es?(0,n.jsxs)("button",{type:"button",onClick:()=>I(es),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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"}),g("复制","Copy")]}):null]}),ea?(0,n.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:ea}):null,es?(0,n.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:es}):null]})]}):null,S&&j?(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(E.Z,{className:"h-4 w-4 text-fuchsia-400"}),g("界面节点","UI nodes")]}),(0,n.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,n.jsx)("p",{className:"mt-2 text-xs text-rose-300",children:ex}):null,(0,n.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,n.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,n.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,n.jsx)("span",{className:"text-zinc-200",children:e.label}),e.resource_id?(0,n.jsx)("span",{className:"ml-2 font-mono text-[10px] text-zinc-600",children:e.resource_id}):null,(0,n.jsxs)("div",{className:"font-mono text-[10px] text-zinc-600",children:["(",e.center_x,", ",e.center_y,")",e.clickable?" click":""]})]}),(0,n.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,n.jsx)("li",{className:"py-4 text-center text-zinc-600",children:g("尚未加载","Not loaded")})]})]}):null,S&&j?(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:g("安装 APK","Install APK")}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:g("先 adb push 到 /sdcard/ 再执行安装。","Push the APK to /sdcard/ first.")}),(0,n.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,n.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=s(9897),eo=s(4554),ec=s(7689),ed=s(8930),ex=s(8401);function eu(e){let{t,title:s,subtitle:l,steps:i,onNavigate:r}=e;return(0,n.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,n.jsx)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:s}),(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-400",children:l}),(0,n.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,n.jsxs)("div",{className:"flex items-center gap-4",children:[e.openUrl||e.target&&r?(0,n.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,n.jsx)("span",{children:e.label}),e.sub?(0,n.jsx)("span",{className:"mt-1 text-[10px] font-normal text-white/80",children:e.sub}):null]}):(0,n.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,n.jsx)("span",{children:e.label}),e.sub?(0,n.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("/"),s=t[t.length-1]||"";return s.length>8?s.slice(-8):s}}}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 s of e.split(/\r?\n/)){let e=s.trim();if(!e||e.startsWith("#")||!/douyin\.com|v\.douyin\.com/i.test(e))continue;let n=e.match(/(https?:\/\/live\.douyin\.com\/[a-zA-Z0-9_-]+)/i);if(n){t.push(n[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="",s=!0,n="",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?s=!/^(0|false|否)/i.test(c):"bitrate"===o?n=c:"fast_audio"===o&&(l=/^(1|true|yes|是|开|on)/i.test(c))}return{key:t,rtmps:s,bitrate:n,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,s,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 s of e.split(/\r?\n/)){let e=s.trim();if(!e||e.startsWith("#")||!/douyin\.com|v\.douyin\.com/i.test(e))continue;let n=e.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);if(n){t.push(n[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 s of e.split(/\r?\n/)){let e=s.match(/live\.douyin\.com\/([a-zA-Z0-9_-]+)/i);e&&(t=e[1]);let n=s.match(/https?:\/\/[^/\s]*douyin\.com\/(\d{8,})/i);n&&(t=n[1])}return t}(p),q=null!==(s=eh(o)[0])&&void 0!==s?s:"",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 s=await a("/status?process=".concat(encodeURIComponent(e)));if(t!==Y.current||e!==W.current.trim())return;let n=s.process_status||"unknown";h(n),b(s.recent_log||""),f(s.recent_error||""),w(s.business_status||""),j(s.business_note||""),z(Array.isArray(s.ffmpeg_pids)?s.ffmpeg_pids:[]),C("number"==typeof s.log_age_seconds?s.log_age_seconds:null);let l=/^(online|running)$/i.test(n);l&&!O.current&&M(Date.now()),l||M(null),O.current=l}catch(s){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"),es=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,n.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,n.jsx)("span",{className:"sr-only","aria-hidden":!0,children:T}),(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:i("当前直播日志","Live process log")}),(0,n.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,n.jsx)("span",{className:"rounded-full px-2 py-0.5 text-[10px] font-medium ring-1 ".concat(es),children:et})]}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.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,n.jsx)(y.Z,{className:"h-3.5 w-3.5"}),i("立即拉取","Refresh")]}),(0,n.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,n.jsx)(K.Z,{className:"h-3.5 w-3.5"}):(0,n.jsx)(F.Z,{className:"h-3.5 w-3.5"}),R?i("继续自动刷新","Resume"):i("暂停自动刷新","Pause")]})]})]}),(0,n.jsxs)("div",{className:"mt-4 space-y-3 rounded-xl border border-white/[0.06] bg-black/25 p-4",children:[(0,n.jsxs)("div",{className:"grid gap-2 text-xs sm:grid-cols-2",children:[(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("进程状态","Status")}),(0,n.jsx)("span",{className:"font-medium text-zinc-200",children:function(e,t){let s=(t||"unknown").toLowerCase();return"online"===s||"running"===s?e("运行中(PM2/进程在线)","Running (process online)"):"stopped"===s||"stopping"===s?e("已停止","Stopped"):"not_found"===s||"errored"===s?e("未运行或未找到","Not running / not found"):"invalid"===s?e("无效进程名","Invalid process"):t||"—"}(i,m)})]}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("Business state","Business state")}),(0,n.jsx)("span",{className:"font-medium text-cyan-200/90",children:function(e,t,s){let n=(t||"").toLowerCase();return"streaming"===n?e("Pushing to YouTube","Pushing to YouTube"):"waiting_source"===n?e("Waiting for the upstream live source","Waiting for the upstream live source"):"source_live"===n?e("Source live detected, but no active FFmpeg relay worker","Source live detected, but no active FFmpeg relay worker"):"monitoring"===n?e("Process online and monitoring the source","Process online and monitoring the source"):"misconfigured"===n?e("YouTube key missing or invalid","YouTube key missing or invalid"):"stale"===n?e("Process online but the log heartbeat is stale","Process online but the log heartbeat is stale"):"error"===n?e("Recent process error detected","Recent process error detected"):(null==s?void 0:s.trim())?s.trim():e("No business-state hint yet","No business-state hint yet")}(i,v,N)})]}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("本次在线时长(估算)","Online duration (est.)")}),(0,n.jsx)("span",{className:"font-mono text-cyan-200/90",children:ee})]}),(0,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("FFmpeg workers","FFmpeg workers")}),(0,n.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,n.jsxs)("div",{className:"flex flex-wrap gap-2 text-xs",children:[(0,n.jsx)("span",{className:"text-zinc-500",children:i("YouTube key 尾码(参考)","YT key suffix")}),(0,n.jsx)("span",{className:"font-mono text-zinc-300",children:c||"—"})]}):null,$?(0,n.jsxs)("div",{className:"rounded-lg border border-violet-500/20 bg-violet-500/[0.06] px-3 py-2.5",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.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,n.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,n.jsx)(Z.Z,{className:"h-3.5 w-3.5 shrink-0 opacity-90"}),X||i("打开抖音直播页","Open Douyin live")]})]}),J.length>1&&V?(0,n.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,n.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,n.jsx)("p",{className:"text-[11px] text-zinc-600",children:i("(日志与地址列表中暂无抖音房间)","(No Douyin room in log or URL list)")})]}),"not_found"!==m&&"invalid"!==m?(0,n.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wider text-emerald-400/90",children:i("进程输出(stdout / 合并日志)","Process output")}),(0,n.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,n.jsxs)("div",{children:[(0,n.jsx)("div",{className:"text-[11px] font-semibold uppercase tracking-wider text-rose-400/90",children:i("异常信息(stderr)","Stderr")}),(0,n.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,n.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:s,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())}),s=await h("/get_url_config?".concat(t));X(null!==(e=s.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){}},[]),es=e=>{G(e);try{window.localStorage.setItem(ej,e)}catch(e){}},en=async()=>{if(r){A(!0),K(null),F.current=!1;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:""),K(s("已从服务器读取 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(s("已删除文件","File removed")),await ee()}catch(e){f(e.message)}finally{P(!1)}}},er=async e=>{var t;let n=null===(t=e.target.files)||void 0===t?void 0:t[0];if(e.target.value="",n&&r){P(!0);try{let e=new FormData;e.append("file",n);let t=await (0,Y.N)("".concat(p,"/tiktok_replay/upload?process=").concat(encodeURIComponent(r)),{method:"POST",body:e});f(t.message||s("上传成功","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,n.jsxs)("div",{className:"mx-auto max-w-4xl space-y-6",children:[v?(0,n.jsx)(eu,{t:s,title:s("TikTok HDMI 硬件链路","TikTok HDMI hardware chain"),subtitle:s("板端编码经 HDMI 到显示/下游设备;与「网络」页顶卡相同的箭头风格。","Encode on SoC → HDMI → display/downstream; same arrow style as Network header."),onNavigate:v,steps:[{label:"FFmpeg",sub:s("采集 / 推流","Capture"),gradient:"from-cyan-400 to-blue-500",target:"live_tiktok"},{label:"HDMI",sub:s("板载输出","SoC out"),gradient:"from-violet-500 to-fuchsia-500"},{label:"Android",sub:s("AOSP / 手机","AOSP"),gradient:"from-amber-400 to-orange-500",target:"android"}]}):null,(0,n.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,n.jsx)("div",{className:"flex flex-wrap items-start gap-4",children:(0,n.jsxs)("div",{className:"flex items-center gap-3",children:[(0,n.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,n.jsx)(D.Z,{className:"h-5 w-5 text-cyan-200"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold tracking-tight text-white",children:s("TikTok 无人直播(单路)","TikTok unmanned (single lane)")}),(0,n.jsx)("p",{className:"mt-0.5 text-xs text-zinc-500",children:s("布局对齐 YouTube 单频道:直播开关 + 源站 + URL_config;无 stream key,输出走 HDMI 硬件链路。","Same layout as YouTube single: controls + URLs; no stream key — HDMI hardware path.")})]})]})})}),(0,n.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,n.jsx)("p",{className:"text-xs leading-relaxed text-cyan-100/90",children:s("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,n.jsxs)("div",{className:"rounded-2xl border border-white/10 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-300"}),s("X86 HDMI 采集状态","X86 HDMI capture status")]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:s("这里直接显示主机是否识别到采集卡和 /dev/video 设备,可用于验证 ARM HDMI 进 X86 的链路。","Shows whether the host sees the capture card and /dev/video nodes for ARM-to-X86 HDMI ingest.")})]}),(0,n.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?s("可推流","Ready"):s("未就绪","Not ready")})]}),(0,n.jsxs)("div",{className:"mt-4 grid gap-3 md:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-4 text-[11px] text-zinc-400",children:[(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"device: "}),(0,n.jsx)("span",{className:"font-mono text-zinc-200",children:ep||"—"})]}),(0,n.jsxs)("p",{className:"mt-2",children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"video nodes: "}),(0,n.jsx)("span",{className:"font-mono text-zinc-200",children:((null==g?void 0:g.video_devices)||[]).join(", ")||"—"})]}),(0,n.jsxs)("p",{className:"mt-2",children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"usb matches: "}),(0,n.jsx)("span",{className:"text-zinc-300",children:((null==g?void 0:g.usb_capture_matches)||[]).length||0})]})]}),(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/25 p-4 text-[11px] text-zinc-400",children:[(0,n.jsx)("p",{className:"text-zinc-600",children:s("建议 FFmpeg","Suggested FFmpeg")}),(0,n.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,n.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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"}),s("复制命令","Copy command")]}):null]})]}),((null==g?void 0:g.issues)||[]).length?(0,n.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,n.jsx)("li",{children:e},e))}):null]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-amber-500/20 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2 text-amber-200/90",children:[(0,n.jsx)(B.Z,{className:"h-4 w-4"}),(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:s("直播开关","Live control")})]}),(0,n.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:s("TikTok 进程(PM2)","TikTok PM2 process")}),(0,n.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,n.jsxs)("option",{value:e.pm2,children:[e.label," (",e.pm2,")"]},e.pm2))}),(0,n.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:s("直播源","Video source")}),(0,n.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,n.jsx)("option",{value:"ffmpeg",hidden:!0,children:"FFmpeg(抖音 / TikTok 等直播间 URL)"}),(0,n.jsx)("option",{value:"replay",hidden:!0,children:s("录播素材(本地上传)","VOD upload")}),(0,n.jsx)("option",{value:"srs",children:s("SRS(OBS 推流)","SRS (OBS)")})]}),"srs"===N?(0,n.jsx)("p",{className:"mt-2 text-[11px] leading-relaxed text-amber-200/85",children:s("此模式不显示 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,n.jsx)("div",{className:"mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3",children:[["start",s("开始直播","Start"),"bg-emerald-500/20 text-emerald-200 ring-emerald-500/30"],["stop",s("停止直播","Stop"),"bg-rose-500/15 text-rose-200 ring-rose-500/25"],["restart",s("重新开始","Restart"),"bg-amber-500/15 text-amber-200 ring-amber-500/25"]].map(e=>{let[t,s,l]=e;return(0,n.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:s},t)})}),(0,n.jsxs)("p",{className:"mt-3 text-center text-[11px] text-zinc-500",children:[s("当前 HDMI 预设(备忘)","HDMI preset (memo)"),":"," ",(0,n.jsx)("span",{className:"font-mono text-cyan-300/90",children:em?s(em.labelZh,em.labelEn):T})]})]}),"replay"===N?(0,n.jsxs)("div",{className:"rounded-2xl border border-violet-500/25 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(eo.Z,{className:"h-4 w-4 text-violet-300"}),s("录播素材","VOD library")]}),(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.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,n.jsx)(ec.Z,{className:"h-3.5 w-3.5"}),(0,n.jsx)("span",{children:s("上传视频","Upload")}),(0,n.jsx)("input",{type:"file",accept:".mp4,.mkv,.ts,.flv,.mov,.m4v,.webm",className:"hidden",onChange:er})]}),(0,n.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:s("刷新列表","Refresh")})]})]}),(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:s("文件保存在服务器 config/tiktok_replay/对应进程目录;点「开始直播」会写入 replayfile 行并启动 PM2 进程。停播请用上方「停止直播」。","Files under config/tiktok_replay/. Go live writes replayfile + starts PM2. Use Stop above to stop.")}),S?(0,n.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:s("加载中…","Loading…")}):0===k.length?(0,n.jsx)("p",{className:"mt-4 text-xs text-zinc-500",children:s("暂无文件,请先上传。","No files yet.")}):(0,n.jsx)("ul",{className:"mt-4 space-y-2",children:k.map(e=>(0,n.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,n.jsx)("span",{className:"min-w-0 flex-1 truncate font-mono",children:e.name}),(0,n.jsxs)("span",{className:"shrink-0 text-zinc-500",children:[(e.size/1048576).toFixed(1)," MB"]}),(0,n.jsxs)("div",{className:"flex shrink-0 flex-wrap gap-2",children:[(0,n.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:s("开始直播","Go live")}),(0,n.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:s("停播","Stop")}),(0,n.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,n.jsx)(ed.Z,{className:"h-3 w-3"}),s("删除","Del")]})]})]},e.name))})]}):null,"srs"===N?(0,n.jsxs)("div",{className:"rounded-2xl border border-emerald-500/25 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:s("SRS / OBS 推流","SRS / OBS ingest")}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:s("OBS:设置 → 推流 → 服务选「自定义」,服务器填 RTMP 地址;串流密钥可与 SRS 应用配置一致(默认 live/livestream)。","OBS → Stream → Custom: RTMP URL as server; stream key per SRS app (default live/livestream).")}),(0,n.jsxs)("dl",{className:"mt-4 space-y-3 text-xs",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-500",children:s("RTMP 推流地址(OBS 服务器)","RTMP publish URL")}),(0,n.jsxs)("dd",{className:"mt-1 flex flex-wrap items-center gap-2 font-mono text-emerald-200/90",children:[(0,n.jsx)("span",{className:"break-all",children:b.srs_rtmp_publish||"—"}),b.srs_rtmp_publish?(0,n.jsx)("button",{type:"button",className:"shrink-0 text-cyan-300 hover:text-cyan-200",onClick:()=>m(b.srs_rtmp_publish),children:(0,n.jsx)(U.Z,{className:"h-3.5 w-3.5"})}):null]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-500",children:s("HTTP-FLV 预览","HTTP-FLV preview")}),(0,n.jsxs)("dd",{className:"mt-1 flex flex-wrap items-center gap-2 font-mono text-zinc-400",children:[(0,n.jsx)("span",{className:"break-all",children:b.srs_play_flv||b.srs_http||"—"}),b.srs_play_flv||b.srs_http?(0,n.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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"})}):null]})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-500",children:s("SRS 控制台","SRS web UI")}),(0,n.jsx)("dd",{className:"mt-1 font-mono text-zinc-400",children:(0,n.jsx)("a",{href:b.srs_http||"#",target:"_blank",rel:"noreferrer",className:"text-cyan-300 hover:underline",children:b.srs_http||"—"})})]})]})]}):null,(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-400"}),s("HDMI 硬件与时序","HDMI timing")]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:s("点选一路作为现场备忘;与板端 ffmpeg/OBS 采集参数对齐。","Pick a preset as field memo; match capture settings.")}),(0,n.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,n.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,n.jsxs)("div",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(ea.Z,{className:"h-4 w-4 text-cyan-400"}),s(e.labelZh,e.labelEn)]}),(0,n.jsx)("p",{className:"mt-2 font-mono text-[11px] text-zinc-400",children:e.spec}),t?(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:s(e.hintZh,e.hintEn)}):null]},e.id)})}),(0,n.jsxs)("div",{className:"mt-6 rounded-xl border border-white/5 bg-black/25 p-4",children:[(0,n.jsx)("p",{className:"text-xs font-semibold text-zinc-400",children:s("上线前检查清单(本地保存)","Pre-flight checklist (local)")}),(0,n.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,n.jsxs)("li",{className:"flex items-start gap-2 text-xs text-zinc-400",children:[(0,n.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,n.jsx)("span",{children:s(e.zh,e.en)})]},e.id))}),(0,n.jsx)("label",{className:"mt-4 block text-[11px] text-zinc-500",children:s("HDMI / 走线备忘","HDMI / wiring notes")}),(0,n.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=>es(e.target.value),spellCheck:!1,placeholder:s("接口、线长、显示器型号…","Ports, cable length, display model…")})]})]}),"ffmpeg"===N?(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:s("直播地址列表 \xb7 URL_config.ini","URL_config.ini")}),(0,n.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,n.jsx)(U.Z,{className:"h-3.5 w-3.5"}),s("复制全文","Copy all")]})]}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:s("一行一个地址;可勾选自动从服务器刷新,或点「重新读取」手动同步。","One URL per line; enable auto-refresh or reload from server.")}),(0,n.jsx)("div",{className:"mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400",children:(0,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-2",children:[(0,n.jsx)("input",{type:"checkbox",className:"rounded border-white/20 bg-black/40",checked:Z,onChange:e=>O(e.target.checked)}),s("每 8 秒自动从服务器刷新","Auto-refresh from server every 8s")]})}),H?(0,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:H}):null,(0,n.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,n.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2",children:[(0,n.jsx)("button",{type:"button",disabled:ex,onClick:()=>void en(),className:"rounded-xl border border-white/10 bg-white/[0.05] px-4 py-2 text-sm text-zinc-300",children:s("重新读取","Reload from server")}),(0,n.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:s("保存 URL 配置","Save URL config")})]})]}):null,(0,n.jsx)(ev,{t:s,currentProc:r,fetchJson:h,urlListText:"ffmpeg"===N?o:"",keySuffixUi:"",showKeyRow:!1})]})}var eS=s(5468),e_=s(9397),eC=s(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 s=eT(e);return!s||eM.has(s)||s===eP?eK(t):s.startsWith(eP)?s:eK(s)}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 s=String(e.name||"").trim()||t;return{id:t,name:s,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 s of eZ)try{var t;let n=await e(s);return{fetched:!0,channels:(t=n.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 s=null;for(let n of eZ)try{await e(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channels:t})});return}catch(e){s=e instanceof Error?e:Error(String(e))}throw null!=s?s: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 s=((null==t?void 0:t.business_status)||"").trim().toLowerCase();return(null==t?void 0:t.is_pushing)||"streaming"===s?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,s,n;return{name:e.name,streamKey:null!==(t=e.streamKey)&&void 0!==t?t:"",pm2Name:null!==(s=e.pm2Name)&&void 0!==s?s:eK(e.id),notes:null!==(n=e.notes)&&void 0!==n?n:""}}function eX(e){return/^(online|running)$/i.test((e||"").trim())}function e$(e,t){let s=((null==e?void 0:e.business_status)||"").trim().toLowerCase();return"ready"===s?t("已配置","Ready"):"streaming"===s?t("推流中","Pushing"):"waiting_source"===s?t("等待上游","Waiting source"):"source_live"===s?t("源已开播,转推未起","Source live, relay down"):"monitoring"===s?t("监控中","Monitoring"):"misconfigured"===s?t("密钥异常","Key invalid"):"stale"===s?t("心跳过期","Stale"):"error"===s?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:s,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),s=t.indexOf(":");if(s<=0)return null;let n=t.slice(0,s),l=t.slice(s+1);return l&&["start","stop","restart"].includes(n)?{action:n,pm2:l}:null}(i),p=h&&h.pm2===l,b=null!=s?s: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,n.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,n.jsx)("span",{className:"absolute inset-0 flex items-center justify-center bg-black/25 backdrop-blur-[2px]",children:(0,n.jsx)(v.Z,{className:"".concat(m?"h-4 w-4":"h-6 w-6"," animate-spin text-white")})}):null,(0,n.jsxs)("span",{className:"inline-flex items-center justify-center gap-1.5 ".concat(g?"invisible":""),children:[j?(0,n.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,s,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 s=e.filter(eF),n=s.filter(e=>eF(e)&&e.pm2.trim()===eW(e.script).trim()),l=n.length?[...n]:s.length?[...s]:[...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 n=(e.business_status||"").trim().toLowerCase();if(!e.is_pushing&&"streaming"!==n&&!eX(e.process_status))continue;let d=s.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=s[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 s=new Map(t.filter(eY).map(e=>[e.pm2.trim(),e])),n=e[0],l=eJ(n,s.get(n.pm2.trim()));for(let t of e.slice(1)){let e=eJ(t,s.get(t.pm2.trim()));e"youtube"===e.pm2.trim().toLowerCase());if(n)return n.pm2;let l=e.find(e=>"youtube"===eW(e.script).trim().toLowerCase());return l?l.pm2:null!==(s=null===(t=e[0])||void 0===t?void 0:t.pm2)&&void 0!==s?s:""}(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)({}),[es,en]=(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(s=>{let n=!1,l=s.map(s=>{var l;return s.id!==e||(null!==(l=s.urlLines)&&void 0!==l?l:"")===t?s:(n=!0,{...s,urlLines:t})});return n?(ey.current=l,eA(l),l):s})},[]),eP=(0,_.useCallback)(async()=>{let e=ew.current.trim();if(!e)return;let t=++eN.current;try{var s,n,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!==(s=r.content)&&void 0!==s?s:"";if(eo.current)return;if("single"===C)ek(a);else{let e=null!==(l=null===(n=ey.current.find(e=>e.id===M))||void 0===n?void 0:n.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 s,n,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!==(s=r.content)&&void 0!==s?s:"";if(eo.current){Q(a("检测到本地未保存修改,已保留当前草稿","Kept the local unsaved draft"));return}if("single"===C)ek(o);else{let e=null!==(l=null===(n=ey.current.find(e=>e.id===M))||void 0===n?void 0:n.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(s){if(t!==eN.current||e!==ew.current.trim())return;Q(s.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)}(),s=t.length>0?t:(()=>{let e=eB();return[{id:e,name:"线路 1",streamKey:"",urlLines:"",pm2Name:eK(e),notes:""}]})();ey.current=s,L(s),t.length||eA(s)})(),()=>{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(s=>{var n;return{...s,[e4.id]:{...null!==(n=s[e4.id])&&void 0!==n?n: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]),ts=(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]),tn=(0,_.useCallback)(e=>{var t,s,n;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!==(s=i.find(e=>e.id===M))&&void 0!==s?s:i[0];ez((null!==(n=null==r?void 0:r.urlLines)&&void 0!==n?n:"").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,s;let n=ef.current;e4&&"pro"===C&&n!==(null!==(t=e4.urlLines)&&void 0!==t?t:"").trim()&&e3(P.map(e=>e.id===e4.id?{...e,urlLines:n}:e)),ez((null!==(s=e.urlLines)&&void 0!==s?s:"").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 s;let n=new URLSearchParams({process:e,_ts:String(Date.now())}),l=await g("/get_config?".concat(n));if(t!==ej.current||e!==ew.current.trim())return;let i=null!==(s=l.content)&&void 0!==s?s:"";E(i),D(ep(i))}catch(s){if(t!==ej.current||e!==ew.current.trim())return;O(s.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,s=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(s),await e2(s),et(e=>({...e,[e4.id]:{name:tt.normalizedName,streamKey:tt.normalizedStreamKey,pm2Name:tt.normalizedPm2,notes:tt.normalizedNotes}})),{next:s,savedLane:null!==(e=s.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){en(!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{en(!1)}}},[e4,w,tr,u,a]),to=async function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ew.current,s=t.trim();if(!s){O(a("请选择进程","Pick a process"));return}K(!0),O(null);try{let t=new URLSearchParams({process:s});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 s=U||eg(I),n=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:s,action:"youtube_balanced_preset"})}),l=null!==(e=n.content)&&void 0!==e?e:s;E(l),D(ep(l)),O(n.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 s=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(s))},[C,I.key,null==e4?void 0:e4.streamKey,null==e6?void 0:e6.streamKey]),tu=async()=>{if(e4)try{en(!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{en(!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 s=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"})}),n=null!==(t=s.content)&&void 0!==t?t:e;"single"===C?ek(n):ez(n),eo.current=!0,Q(s.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});en(!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{en(!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 s=!!e4&&eE(e4)===t;if("stop"!==e){var n,l;let e=P,s=t;try{let n=await tk(t);e=n.next,s=n.pm2}catch(e){w("".concat(a("当前线路保存失败","Failed to save the active lane"),": ").concat(e.message));return}let i=e.find(e=>eE(e)===s),r=null!==(n=null==i?void 0:i.urlLines)&&void 0!==n?n:"";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=s}s&&u(t),p(e,t)},[e4,P,tk,w,p,u,a]),tS=!!o||H||G||q||es,t_=eX(eU(x)),tC=(0,n.jsxs)("div",{className:"mt-2 flex flex-wrap items-center gap-4 text-xs text-zinc-400",children:[(0,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-2",children:[(0,n.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,n.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,n.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,n.jsxs)("div",{className:"mx-auto max-w-6xl space-y-6",children:[N?(0,n.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,n.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,n.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[(0,n.jsxs)("div",{className:"flex items-center gap-3",children:[(0,n.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,n.jsx)(c.Z,{className:"h-5 w-5 text-red-200"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("h2",{className:"text-lg font-semibold tracking-tight text-white",children:a("YouTube 无人直播","YouTube unmanned live")}),(0,n.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,n.jsxs)("div",{className:"flex rounded-xl border border-white/10 bg-black/30 p-1 ".concat(""),"aria-hidden":!1,children:[(0,n.jsx)("button",{type:"button",onClick:()=>tn("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,n.jsx)("button",{type:"button",onClick:()=>tn("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,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[ty.link?(0,n.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,n.jsx)("div",{className:"flex flex-wrap gap-2",children:tv.map(e=>{var t;return(0,n.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,n.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,n.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,n.jsxs)("div",{className:"rounded-2xl border border-amber-500/20 bg-zinc-950/60 p-6 ring-1 ring-white/[0.04]",children:[(0,n.jsxs)("div",{className:"flex items-center gap-2 text-amber-200/90",children:[(0,n.jsx)(B.Z,{className:"h-4 w-4"}),(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播开关","Live control")})]}),"single"===C?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)("label",{className:"mt-4 block text-xs font-semibold uppercase tracking-wider text-zinc-500",children:a("转播任务","Relay task")}),(0,n.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,n.jsxs)("option",{value:x,children:[x,eI?" (".concat(e$(eI,a),")"):""]}):null,z.map(e=>(0,n.jsxs)("option",{value:e.pm2,children:[function(e,t){let s=eW(e.script).toLowerCase();return s.startsWith("douyin_youtube")?t("抖音→YouTube","Douyin → YouTube"):s.startsWith("youtube")?t("YouTube","YouTube"):e.label}(e,a)," (",e.pm2,")"]},e.pm2))]}),(0,n.jsxs)("div",{className:"mt-4 grid grid-cols-2 gap-2 sm:grid-cols-3",children:[(0,n.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,n.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,n.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,n.jsxs)("p",{className:"mt-3 text-center text-xs text-zinc-400",children:[a("当前状态","Current state"),": ",e$(eI,a)]}),(0,n.jsxs)("p",{className:"mt-3 text-center font-mono text-[11px] text-zinc-600",children:["key ",a("尾码","suffix"),": ",tx||"—"]})]}):(0,n.jsx)(n.Fragment,{children:(0,n.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,n.jsx)("h4",{className:"text-xs font-semibold uppercase tracking-wider text-cyan-200/90",children:a("Pro 转播实况","Pro relay status")}),(0,n.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,n.jsxs)("p",{className:"mt-2 text-[11px] text-zinc-500",children:[a("Neko 实例","Neko instances"),": ",tN]}):null,(0,n.jsx)("div",{className:"mt-3 max-h-[min(24rem,55vh)] space-y-2 overflow-y-auto pr-1",children:P.map(e=>{var t,s,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!==(s=e.urlLines)&&void 0!==s?s:"").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,n.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,n.jsxs)("button",{type:"button",className:"min-w-0 flex-1 text-left",onClick:()=>{ew.current=eE(e),tl(e)},children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center gap-2",children:[(0,n.jsx)("span",{className:"font-medium text-zinc-100",children:e.name}),(0,n.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,n.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,n.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,n.jsxs)("span",{children:["key …",m||"—"]}),(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,n.jsx)("span",{className:"truncate",title:i,children:i}),(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,n.jsxs)("span",{children:["URL ",d.length]}),(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"}),(0,n.jsxs)("span",{children:["DY ",x.length]})]}),u?(0,n.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,n.jsx)("span",{className:"mt-1 block text-zinc-600",children:"—"})]}),(0,n.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,n.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,n.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,n.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,n.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,n.jsx)("span",{className:"sr-only",children:a("打开该线路 Neko 工作室","Open this lane's Neko studio")}),(0,n.jsx)("span",{"aria-hidden":!0,className:"text-sm leading-none",children:"\uD83D\uDC31"}),(0,n.jsx)(Z.Z,{className:"ml-1 h-3.5 w-3.5 shrink-0","aria-hidden":!0})]}):null]})]},e.id)})})]})})]}),"single"===C?(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("YouTube 相关设置","YouTube settings")}),(0,n.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,n.jsxs)("div",{className:"mt-4 space-y-3",children:[(0,n.jsx)("label",{className:"block text-xs text-zinc-400",children:a("串流密钥","Stream key")}),(0,n.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,n.jsxs)("div",{className:"grid gap-3 sm:grid-cols-3",children:[(0,n.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-zinc-400",children:["RTMPS",(0,n.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,n.jsx)("option",{value:"1",children:a("是(默认)","Yes")}),(0,n.jsx)("option",{value:"0",children:a("否 → RTMP","No")})]})]}),(0,n.jsxs)("label",{className:"flex flex-col gap-1 text-xs text-zinc-400",children:[a("比特率 kbps","Bitrate kbps"),(0,n.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,n.jsxs)("label",{className:"flex cursor-pointer items-center gap-2 pt-6 text-xs text-zinc-300",children:[(0,n.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,n.jsxs)("div",{className:"mt-4 flex flex-wrap gap-2",children:[(0,n.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,n.jsx)(y.Z,{className:"h-3.5 w-3.5 ".concat(H?"animate-spin":"")}),a("重新读取","Reload")]}),(0,n.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,n.jsx)(v.Z,{className:"h-4 w-4 animate-spin"}):null,a("保存 youtube.ini","Save youtube.ini")]}),(0,n.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,n.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,n.jsxs)("details",{className:"mt-4 rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,n.jsx)("summary",{className:"cursor-pointer text-xs text-zinc-500",children:a("高级:youtube.ini 原文","Raw youtube.ini")}),(0,n.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,n.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,n.jsx)("p",{className:"mt-2 font-mono text-xs text-zinc-500",children:A}):null]}):(0,n.jsxs)("div",{className:"space-y-6",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsxs)("h3",{className:"text-sm font-semibold text-white",children:[a("当前线路","Current lane"),e4?(0,n.jsxs)("span",{className:"ml-2 font-normal text-zinc-400",children:["\xb7 ",e4.name]}):null,ts?(0,n.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,n.jsxs)("p",{className:"mt-0.5 font-mono text-[11px] text-zinc-500",children:["PM2: ",e9,te?" → ".concat(e7):""," \xb7 ","key ",tx||"—"]}):null]}),(0,n.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(s=>({...s,[e]:eq(t)})),e3([...P,t]),T(e),ew.current=eE(t),u(ew.current),ez("")},children:[(0,n.jsx)(e_.Z,{className:"h-3.5 w-3.5"}),a("新增线路","Add lane")]})]}),e4?(0,n.jsxs)("div",{className:"mt-4 space-y-3 border-t border-white/5 pt-4",children:[(0,n.jsx)("input",{className:"w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-sm",value:null!==(s=null==e6?void 0:e6.name)&&void 0!==s?s:"",onChange:e=>e8("name",e.target.value),placeholder:a("线路名称","Lane name")}),(0,n.jsx)("label",{className:"block text-xs text-zinc-500",children:a("串流密钥","Stream key")}),(0,n.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,n.jsxs)("div",{className:"flex flex-wrap gap-2",children:[(0,n.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:es?a("保存中...","Saving..."):a("保存线路设置","Save lane")}),(0,n.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,n.jsx)("p",{className:"text-xs text-rose-300",children:tt.message}),(0,n.jsxs)("details",{className:"rounded-xl border border-white/5 bg-black/20 p-3",children:[(0,n.jsx)("summary",{className:"cursor-pointer text-xs text-zinc-500",children:a("高级:进程名","Advanced: process name")}),(0,n.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,n.jsxs)("p",{className:"mt-2 font-mono text-[11px] text-zinc-500",children:[a("实际生效","Effective"),": ",e7||"—"]}),tt.message&&!tt.ok?(0,n.jsx)("p",{className:"mt-2 text-[11px] text-rose-300",children:tt.message}):null]}),(0,n.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,n.jsx)("p",{className:"text-xs text-zinc-400",children:el}):null,(0,n.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,n.jsx)(ed.Z,{className:"h-3.5 w-3.5"}),a("删除此线路","Delete lane")]})]}):null]}),(0,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播地址列表","URL list")}),(0,n.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,n.jsx)("p",{className:"mt-1 font-mono text-[10px] text-zinc-600",children:x?eb(x):"URL_config.ini"}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2 text-[11px]",children:[(0,n.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,n.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,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:$}):null,(0,n.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,n.jsx)("div",{className:"mt-3 flex flex-wrap gap-2",children:(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-6",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:a("直播地址列表 \xb7 URL_config.ini","URL_config.ini")}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500",children:a("一行一个地址;可自动刷新或手动重新读取。","One URL per line; auto-refresh or reload.")}),(0,n.jsxs)("div",{className:"mt-3 flex flex-wrap gap-2 text-[11px]",children:[(0,n.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,n.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,n.jsx)("p",{className:"mt-2 text-xs text-zinc-500",children:$}):null,(0,n.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,n.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,n.jsx)(ev,{t:a,currentProc:x,fetchJson:g,urlListText:"single"===C?m:F,keySuffixUi:tx,showKeyRow:!0,pollMs:800,refreshToken:er})]})}var e2=s(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"],s=e,n=0;for(;s>=1024&&n=10||0===n?0:1)," ").concat(t[n])}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 s=(e||"").trim().toLowerCase();return"online"===s||"running"===s?t("运行中","Running"):"configured"===s?t("已配置","Configured"):"not_found"===s?t("未注册","Unregistered"):"stopped"===s?t("已停止","Stopped"):"error"===s?t("异常","Error"):e||"—"}function e7(){var e,t,s,L,M,T,U,E,I,D,A,Z,O,H,B,K,F,W,J,G,V,q,X,$,Q,ee,et,es,en,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,ts]=(0,_.useState)(!0),[tn,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,s]=await Promise.allSettled([tP("/hub/dashboard"),tP("/deploy/check")]);if("fulfilled"!==t.status)throw t.reason;let n=t.value;eG(n),eq(null),te(Date.now()),"fulfilled"===s.status?tf(s.value):tf(null);let l=(null===(e=n.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=()=>ts("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 s=new URLSearchParams({process:e,_ts:String(Date.now())}),n=await tP("/get_url_config?".concat(s));if(t!==tS.current||e!==tz.current.trim())return;td(n.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)||{},s={};for(let[e,n]of Object.entries(t))/^https?:\/\//i.test(n)?s[e]=(0,ex.p)(n):s[e]=n;return s},[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 s=await tP("/service_action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({service:e,action:t})});"error"===s.status?tR(s.detail||s.message||tC("操作失败","Action failed")):tR(s.message||"OK"),await tL()}catch(e){tR(e.message)}finally{e0(null)}},tA=async(e,t)=>{let s=(null!=t?t:ta).trim();if(s){e0("proc:".concat(e,":").concat(s));try{let t=await tP("/".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({process:s})});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 s=(null!=t?t:ta).trim();if(!s)return;let n=null!=e?e:tc,l=++tS.current;e0("save:url");try{let e=new URLSearchParams({process:s});await tP("/save_url_config?".concat(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:n})}),l===tS.current&&s===tz.current.trim()&&td(n),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 s=await tP("/android/action",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,serial:tm,payload:t})});tR(s.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 s=document.createElement("textarea");s.value=e,s.readOnly=!0,s.style.position="fixed",s.style.opacity="0",document.body.appendChild(s),s.select(),document.execCommand("copy"),s.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===(s=eJ.services)||void 0===s?void 0:s.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,n.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,n.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,n.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,n.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,n.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,n.jsxs)("div",{className:"relative z-10 flex min-h-screen",children:[(0,n.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,n.jsxs)("div",{className:"flex items-center gap-2 px-2",children:[(0,n.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,n.jsx)(m.Z,{className:"h-4 w-4 text-white"})}),(0,n.jsxs)("div",{children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-[0.2em] ".concat("light"===eH?"text-slate-500":"text-zinc-500"),children:"live.local"}),(0,n.jsx)("p",{className:"text-sm font-semibold ".concat("light"===eH?"text-slate-900":"text-white"),children:tC("无人直播系统","Unmanned Live System")})]})]}),(0,n.jsx)("nav",{className:"mt-10 flex flex-1 flex-col gap-1",children:tH.map(e=>{let t=e.icon,s=eK===e.id;return(0,n.jsxs)("button",{type:"button",onClick:()=>eF(e.id),"aria-current":s?"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?s?"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":s?"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,n.jsx)(t,{className:"h-4 w-4 ".concat("light"===eH?s?"text-violet-600":"text-slate-400":s?"text-violet-300":"text-zinc-600")}),tC(e.labelZh,e.labelEn),s?(0,n.jsx)(h.Z,{className:"ml-auto h-4 w-4 ".concat("light"===eH?"text-slate-400":"text-zinc-600")}):null]},e.id)})})]}),(0,n.jsxs)("div",{className:"flex min-w-0 flex-1 flex-col",children:[(0,n.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,n.jsxs)("div",{className:"flex min-w-0 items-center gap-3",children:[(0,n.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,n.jsx)(p.Z,{className:"h-5 w-5"})}),(0,n.jsxs)("div",{className:"min-w-0",children:[(0,n.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,n.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,n.jsxs)("div",{className:"flex shrink-0 items-center gap-1.5 sm:gap-2",children:[(0,n.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,n.jsx)(b.Z,{className:"h-5 w-5",strokeWidth:2}):(0,n.jsx)(g.Z,{className:"h-5 w-5",strokeWidth:2})}),(0,n.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,n.jsx)(f.Z,{className:"h-5 w-5",strokeWidth:2}),(0,n.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,n.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,n.jsx)(v.Z,{className:"h-3.5 w-3.5 animate-spin"}):(0,n.jsx)(y.Z,{className:"h-3.5 w-3.5"}),(0,n.jsx)("span",{className:"hidden sm:inline",children:tC("刷新","Refresh")})]})]})]}),(0,n.jsx)("main",{className:"flex-1 px-4 py-6 lg:px-8 lg:py-8",children:(0,n.jsx)(i.M,{mode:"wait",children:(0,n.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,n.jsxs)("div",{className:"space-y-6",children:[eV?(0,n.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,n.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,n.jsx)(R.Z,{snapshot:null!==(ew=null==eJ?void 0:eJ.snapshot)&&void 0!==ew?ew:null,theme:eH,tr:tC})}),(0,n.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,n.jsx)(C,{tr:tC})}),(0,n.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)),s=Math.floor(t/86400),n=Math.floor(t%86400/3600),l=Math.floor(t%3600/60);return s>0?"".concat(s,"d ").concat(n,"h"):n>0?"".concat(n,"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,n.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,n.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,n.jsx)(e.icon,{className:"h-4 w-4 text-violet-300/90"}),(0,n.jsx)("p",{className:"mt-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:e.label}),(0,n.jsx)("p",{className:"mt-0.5 font-mono text-lg font-semibold leading-tight text-white",children:eX?"…":e.value}),(0,n.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,n.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,n.jsx)("h3",{className:"text-base font-semibold text-white",children:tC("系统硬件与软件能力","Hardware & software profile")}),(0,n.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("来自 hardware_probe;用于直播/解码策略参考。","From hardware_probe; guides decode/streaming posture.")}),(0,n.jsxs)("div",{className:"mt-5 grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-indigo-300/90",children:tC("平台","Platform")}),(0,n.jsxs)("dl",{className:"space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"arch"}),(0,n.jsx)("dd",{className:"text-right text-zinc-200",children:String(null!==(ej=eJ.hardware.arch)&&void 0!==ej?ej:"—")})]}),(0,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"kernel"}),(0,n.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,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"Python"}),(0,n.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,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"mDNS"}),(0,n.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,n.jsxs)("div",{className:"flex justify-between gap-2",children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"IP"}),(0,n.jsx)("dd",{className:"text-right text-zinc-300",children:((null===(q=eJ.stack)||void 0===q?void 0:q.ips)||[]).join(" \xb7 ")||"—"})]})]})]}),(0,n.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,n.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,n.jsxs)("dl",{className:"space-y-2 font-mono text-[11px] text-zinc-400",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"GPU"}),(0,n.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,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"render"}),(0,n.jsx)("dd",{className:"mt-0.5 break-all text-zinc-500",children:((null==e?void 0:e.render_nodes)||[]).join(", ")||"—"})]}),(0,n.jsxs)("div",{children:[(0,n.jsx)("dt",{className:"text-zinc-600",children:"NPU"}),(0,n.jsx)("dd",{className:"mt-0.5 break-all text-zinc-500",children:(null==t?void 0:t.present)?(t.devices||[]).join(", "):tC("—","—")})]})]})})()]}),(0,n.jsxs)("div",{className:"space-y-3 rounded-xl border border-white/[0.06] bg-black/30 p-4 lg:col-span-2",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-emerald-300/90",children:"ffmpeg / 建议策略"}),(()=>{var e,t,s,l;let i=eJ.hardware.ffmpeg_hwaccels||[],r=eJ.hardware.recommendation;return(0,n.jsxs)("div",{className:"space-y-2 text-[11px] text-zinc-400",children:[(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"hwaccels: "}),(0,n.jsx)("span",{className:"font-mono text-emerald-200/90",children:i.length?i.join(", "):"—"})]}),(0,n.jsxs)("div",{className:"grid gap-2 sm:grid-cols-2",children:[(0,n.jsxs)("p",{children:[(0,n.jsxs)("span",{className:"text-zinc-600",children:[tC("解码","Decoder"),": "]}),(0,n.jsx)("span",{className:"text-zinc-200",children:null!==(e=null==r?void 0:r.video_decoder)&&void 0!==e?e:"—"})]}),(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"HDMI: "}),(0,n.jsx)("span",{className:"text-zinc-200",children:null!==(t=null==r?void 0:r.hdmi_player)&&void 0!==t?t:"—"})]}),(0,n.jsxs)("p",{children:[(0,n.jsx)("span",{className:"text-zinc-600",children:"Browser: "}),(0,n.jsx)("span",{className:"text-zinc-200",children:null!==(s=null==r?void 0:r.browser_hwaccel)&&void 0!==s?s:"—"})]}),(0,n.jsxs)("p",{children:[(0,n.jsxs)("span",{className:"text-zinc-600",children:[tC("稳定模式","Stability"),": "]}),(0,n.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,n.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,n.jsx)("li",{children:e},e))}):null]})})()]})]})]}):null,tg?(0,n.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,n.jsxs)("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("安装验收","Deployment health")}),(0,n.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,n.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,n.jsxs)("div",{className:"mt-4 grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,n.jsx)("p",{className:"text-[10px] font-semibold uppercase tracking-wider text-zinc-500",children:tC("验收摘要","Acceptance summary")}),(0,n.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,n.jsx)("span",{className:"ml-2 text-[11px] text-zinc-500",children:tC("已通过","checks passed")})]}),(0,n.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,n.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,s]=e;return(0,n.jsx)("a",{href:(0,ex.p)(s),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,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/30 p-4",children:[(0,n.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,n.jsx)("ul",{className:"mt-2 space-y-2 text-[11px] text-zinc-300",children:tg.failing_checks.slice(0,4).map(e=>(0,n.jsxs)("li",{className:"rounded-lg border border-amber-500/20 bg-amber-500/10 px-3 py-2",children:[(0,n.jsx)("span",{className:"font-semibold text-amber-100",children:e.label}),(0,n.jsx)("span",{className:"ml-2 text-zinc-400",children:e.detail||"—"})]},e.id))}):(0,n.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,n.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,n.jsx)("li",{children:e},e))}):null]})]})]}):null,(null==eJ?void 0:null===(Q=eJ.stack)||void 0===Q?void 0:Q.neko_login)?(0,n.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,n.jsxs)("h3",{className:"text-sm font-semibold text-white",children:["Neko ",tC("登录","sign-in")]}),(0,n.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,n.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,n.jsx)("div",{className:"mt-4 flex flex-wrap gap-2",children:tE.map(e=>(0,n.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,n.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2 font-mono text-sm",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/40 px-4 py-3",children:[(0,n.jsx)("p",{className:"text-[10px] uppercase text-zinc-500",children:tC("昵称示例","Display Name Example")}),(0,n.jsx)("p",{className:"mt-1 text-fuchsia-200",children:null!==(eT=eJ.stack.neko_login.user_login)&&void 0!==eT?eT:"live"}),(0,n.jsx)("p",{className:"mt-2 text-[10px] uppercase text-zinc-500",children:tC("连接口令","Access Password")}),(0,n.jsx)("p",{className:"mt-0.5 text-fuchsia-100",children:null!==(eU=eJ.stack.neko_login.user_password)&&void 0!==eU?eU:"—"})]}),(0,n.jsxs)("div",{className:"rounded-xl border border-white/10 bg-black/40 px-4 py-3",children:[(0,n.jsx)("p",{className:"text-[10px] uppercase text-zinc-500",children:tC("管理昵称示例","Admin Display Name Example")}),(0,n.jsx)("p",{className:"mt-1 text-violet-200",children:null!==(eE=eJ.stack.neko_login.admin_login)&&void 0!==eE?eE:"admin"}),(0,n.jsx)("p",{className:"mt-2 text-[10px] uppercase text-zinc-500",children:tC("管理口令","Admin Password")}),(0,n.jsx)("p",{className:"mt-0.5 text-violet-100",children:null!==(eI=eJ.stack.neko_login.admin_password)&&void 0!==eI?eI:"—"})]})]}),(0,n.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,n.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,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold text-white",children:[(0,n.jsx)(k.Z,{className:"h-4 w-4 text-cyan-300"}),tC("网络带宽 / 流量","Network bandwidth / traffic")]}),(0,n.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,n.jsxs)("div",{className:"mt-4 grid gap-3 sm:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,n.jsx)("p",{className:"text-[10px] uppercase tracking-[0.08em] text-cyan-300/70",children:tC("实时下行","Live down")}),(0,n.jsx)("p",{className:"mt-1 text-lg font-semibold text-cyan-100",children:e6(eJ.network.total_rx_bps)}),(0,n.jsxs)("p",{className:"mt-1 text-zinc-500",children:[tC("累计","Total"),": ",e4(eJ.network.total_rx_bytes)]})]}),(0,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,n.jsx)("p",{className:"text-[10px] uppercase tracking-[0.08em] text-cyan-300/70",children:tC("实时上行","Live up")}),(0,n.jsx)("p",{className:"mt-1 text-lg font-semibold text-cyan-100",children:e6(eJ.network.total_tx_bps)}),(0,n.jsxs)("p",{className:"mt-1 text-zinc-500",children:[tC("累计","Total"),": ",e4(eJ.network.total_tx_bytes)]})]})]}),(0,n.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,s,l,i;return(0,n.jsxs)("div",{className:"rounded-xl border border-white/[0.06] bg-black/25 px-4 py-3 font-mono text-[11px]",children:[(0,n.jsx)("p",{className:"text-xs font-semibold text-cyan-200/90",children:e.name}),(0,n.jsxs)("p",{className:"mt-2 text-zinc-500",children:[tC("链路","Link"),": ",e.operstate||"unknown"," ",(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e.speed_mbps?"".concat(e.speed_mbps," Mbps"):tC("未知速率","unknown speed")]}),(0,n.jsxs)("p",{className:"mt-2 text-zinc-500",children:["↓ ",e6(e.rx_bps)," ",(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e4(e.rx_bytes)," ",(0,n.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,n.jsxs)("p",{className:"mt-0.5 text-zinc-500",children:["↑ ",e6(e.tx_bps)," ",(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",e4(e.tx_bytes)," ",(0,n.jsx)("span",{className:"text-zinc-600",children:"\xb7"})," ",null!==(i=null===(s=e.tx_packets)||void 0===s?void 0:s.toLocaleString())&&void 0!==i?i:"—"," pkt"]})]},e.name)})})]}):null,(null==eJ?void 0:null===(en=eJ.live_events)||void 0===en?void 0:null===(es=en.pm2_tail)||void 0===es?void 0:es.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,n.jsxs)("div",{className:"grid gap-4 lg:grid-cols-2",children:[(0,n.jsxs)("div",{className:"rounded-2xl border border-amber-500/15 bg-zinc-950/40 p-5",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("直播 / PM2 事件","Live / PM2 feed")}),(0,n.jsx)("p",{className:"mt-1 text-[11px] text-zinc-500",children:tC("PM2 合并日志尾部","PM2 merged log tail")}),(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-violet-500/15 bg-zinc-950/40 p-5",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("进程快照","Process digest")}),(0,n.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,n.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,n.jsx)("span",{className:"truncate text-zinc-300",children:e.label||e.pm2}),(0,n.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,n.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,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsx)("h3",{className:"text-sm font-semibold text-white",children:tC("直播进程","Live processes")}),(0,n.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,n.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,n.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,n.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,n.jsxs)("div",{className:"min-w-0 flex-1",children:[(0,n.jsx)("p",{className:"truncate text-sm font-medium text-zinc-100",children:e.label||e.pm2}),(0,n.jsx)("p",{className:"truncate font-mono text-[10px] text-zinc-600",children:e.script||e.pm2})]}),(0,n.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,n.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,n.jsxs)("div",{className:"mt-5 grid grid-cols-2 gap-2",children:[(0,n.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,n.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,n.jsxs)("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:[eJ.probes.srs?(()=>{var e,t,s,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===(s=o.tcp_api)||void 0===s?void 0:s.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-zinc-950/40 p-4 backdrop-blur-sm",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsx)("p",{className:"text-xs font-semibold text-white",children:"SRS"}),(0,n.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,n.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,n.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,n.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,n.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,s,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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.07] bg-zinc-950/40 p-4 backdrop-blur-sm",children:[(0,n.jsxs)("div",{className:"flex items-center justify-between gap-2",children:[(0,n.jsx)("p",{className:"text-xs font-semibold text-white",children:"Neko Chromium"}),(0,n.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,n.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,n.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,n.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===(s=o.tcp)||void 0===s?void 0:s.latency_ms)!=null?"".concat(o.tcp.latency_ms," ms"):"—"]}),x.length?(0,n.jsx)("div",{className:"mt-3 space-y-2",children:x.map(e=>{var t,s,l,i,r,a,o;return(0,n.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,n.jsxs)("div",{className:"min-w-0",children:[(0,n.jsxs)("p",{className:"text-[11px] font-semibold text-zinc-200",children:["Neko ",null!==(r=e.id)&&void 0!==r?r:"?"]}),(0,n.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===(s=e.http)||void 0===s?void 0:s.http_code)&&void 0!==o?o:"—"]})]}),(0,n.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,n.jsx)("p",{className:"mt-1 line-clamp-2 text-[10px] text-amber-200/80",children:d.error}):null]})})():null]}):null]}):null,"services"===eK?(0,n.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,n.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,n.jsxs)("div",{className:"flex items-start justify-between gap-2",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("h3",{className:"font-semibold text-white",children:e.label}),(0,n.jsx)("p",{className:"mt-1 text-xs text-zinc-500 line-clamp-2",children:e.description})]}),(0,n.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,n.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,n.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,n.jsxs)("div",{className:"mt-4 flex flex-wrap items-center gap-2",children:[e.url?(0,n.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,n.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,n.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,n.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,n.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,n.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,n.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,n.jsx)("p",{className:"text-sm text-zinc-500",children:tC("暂无服务数据","No services")})]}):null,"live_youtube"===eK?(0,n.jsx)(e5,{t:tC,busy:eQ,entries:tn,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,n.jsx)(ez,{t:tC,busy:!!eQ,entries:tn,currentProc:ta,setCurrentProc:to,urlConfig:tc,setUrlConfig:td,onRunProcess:e=>void tA(e),onSaveUrlConfig:e=>tZ(e),onReplayGoLive:async(e,t)=>{let s=t.replace(/[,,|]/g,"_");await tZ("原画,".concat(e,",主播: ").concat(s)),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,n.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,n.jsxs)("div",{className:"mx-auto max-w-7xl space-y-6",children:[(0,n.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,n.jsxs)("h3",{className:"flex items-center gap-2 text-sm font-semibold ".concat("light"===eH?"text-slate-900":"text-white"),children:[(0,n.jsx)(k.Z,{className:"h-4 w-4 ".concat("light"===eH?"text-violet-600":"text-violet-300")}),tC("ShellCrash 网络面板","ShellCrash panel")]}),(0,n.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,n.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,n.jsxs)("div",{className:"flex items-center gap-4",children:[(0,n.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,n.jsx)(h.Z,{className:"hidden h-5 w-5 sm:block ".concat("light"===eH?"text-slate-400":"text-zinc-600")}):null]},e.tx))})]}),(0,n.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,n.jsx)("div",{className:"max-h-[min(78vh,56rem)] min-h-[22rem] overflow-y-auto overflow-x-hidden",children:(0,n.jsx)(P.d,{embeddedShellCrash:!0,portalLang:eZ})})})]}):null,"settings"===eK?(0,n.jsxs)("div",{className:"mx-auto max-w-lg space-y-6",children:[(0,n.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,n.jsxs)("div",{className:"space-y-4 rounded-2xl border border-white/[0.08] bg-zinc-950/50 p-5",children:[(0,n.jsxs)("label",{className:"flex cursor-pointer items-center justify-between gap-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("p",{className:"text-sm font-medium text-white",children:tC("总览自动刷新","Auto-refresh dashboard")}),(0,n.jsx)("p",{className:"text-[11px] text-zinc-500",children:"10s"})]}),(0,n.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,n.jsxs)("label",{className:"flex cursor-pointer items-center justify-between gap-4 border-t border-white/[0.06] pt-4",children:[(0,n.jsxs)("div",{children:[(0,n.jsx)("p",{className:"text-sm font-medium text-white",children:tC("总览显示 SRS / Neko 探针","Show SRS/Neko probes")}),(0,n.jsx)("p",{className:"text-[11px] text-zinc-500",children:tC("关闭可精简首页","Hide stream probe cards")})]}),(0,n.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,n.jsxs)("div",{className:"rounded-2xl border border-white/[0.08] bg-zinc-950/40 p-5",children:[(0,n.jsx)("p",{className:"text-xs font-semibold uppercase tracking-wider text-zinc-500",children:tC("配置快照","Config snapshot")}),(0,n.jsx)("p",{className:"mt-2 font-mono text-[11px] text-zinc-400",children:String((null==tp?void 0:tp.config_root)||"—")}),(0,n.jsxs)("p",{className:"mt-3 text-sm text-zinc-300",children:[tC("主机名","Hostname"),":"," ",(0,n.jsx)("span",{className:"font-mono text-violet-200",children:(()=>{var e,t,s;let n=null==tp?void 0:tp.system;return(null==n?void 0:null===(t=n.identity)||void 0===t?void 0:null===(e=t.hostname_alias)||void 0===e?void 0:e.trim())||((null==eJ?void 0:null===(s=eJ.stack)||void 0===s?void 0:s.mdns_host)||"").replace(/\.local$/i,"")||"—"})()})]}),(0,n.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,n.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,n.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,n.jsx)(z.Z,{className:"h-4 w-4"})]})]}):null]},eK)})})]})]}),(0,n.jsx)(i.M,{children:eW?(0,n.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,n.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,n.jsx)("div",{className:"flex justify-end",children:(0,n.jsx)("button",{type:"button",onClick:()=>eY(!1),className:"rounded-lg p-2",children:(0,n.jsx)(S.Z,{className:"h-5 w-5"})})}),(0,n.jsx)("nav",{className:"mt-4 flex flex-col gap-1",children:tH.map(e=>{let t=e.icon,s=eK===e.id;return(0,n.jsxs)("button",{type:"button",onClick:()=>{eF(e.id),eY(!1)},"aria-current":s?"page":void 0,className:"flex items-center gap-3 rounded-xl px-3 py-3 text-left text-sm transition ".concat(s?"bg-white/[0.08] text-white shadow-inner shadow-white/5":"text-zinc-300 hover:bg-white/[0.04]"),children:[(0,n.jsx)(t,{className:"h-4 w-4 ".concat(s?"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 diff --git a/d2ypp2/web-console/out/android.html b/d2ypp2/web-console/out/android.html index 82b61a8..d4fa8b0 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 4ed5230..a380952 100644 --- a/d2ypp2/web-console/out/android.txt +++ b/d2ypp2/web-console/out/android.txt @@ -2,6 +2,6 @@ 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] 4:I[4707,[],""] 5:I[6423,[],""] -0:["UmN0Ou_Iv2TWI4xcHvY2X",[[["",{"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]]]] +0:["Bqx_FrY3OzE8SRa_XO6pv",[[["",{"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"}]] 1:null diff --git a/d2ypp2/web-console/out/console.html b/d2ypp2/web-console/out/console.html index 86c7754..4f9bc79 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 81ac4a4..0088891 100644 --- a/d2ypp2/web-console/out/console.txt +++ b/d2ypp2/web-console/out/console.txt @@ -2,6 +2,6 @@ 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] 4:I[4707,[],""] 5:I[6423,[],""] -0:["UmN0Ou_Iv2TWI4xcHvY2X",[[["",{"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]]]] +0:["Bqx_FrY3OzE8SRa_XO6pv",[[["",{"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"}]] 1:null diff --git a/d2ypp2/web-console/out/index.html b/d2ypp2/web-console/out/index.html index 25d631b..a4cd46a 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 6cc9b72..d55d12c 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-3c5cf076d3a5e7c5.js"],"default",1] +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-a84b3c1d3686233c.js"],"default",1] 4:I[4707,[],""] 5:I[6423,[],""] -0:["UmN0Ou_Iv2TWI4xcHvY2X",[[["",{"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]]]] +0:["Bqx_FrY3OzE8SRa_XO6pv",[[["",{"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"}]] 1:null diff --git a/d2ypp2/web-console/out/shellcrash.html b/d2ypp2/web-console/out/shellcrash.html index 65192da..d4de63a 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 87e111a..1f1500e 100644 --- a/d2ypp2/web-console/out/shellcrash.txt +++ b/d2ypp2/web-console/out/shellcrash.txt @@ -2,6 +2,6 @@ 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] 4:I[4707,[],""] 5:I[6423,[],""] -0:["UmN0Ou_Iv2TWI4xcHvY2X",[[["",{"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]]]] +0:["Bqx_FrY3OzE8SRa_XO6pv",[[["",{"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"}]] 1:null diff --git a/d2ypp2/web.py b/d2ypp2/web.py index 807147b..9389002 100644 --- a/d2ypp2/web.py +++ b/d2ypp2/web.py @@ -6,7 +6,9 @@ import json import os import re import signal +import sqlite3 import sys +import time from contextlib import asynccontextmanager, suppress from pathlib import Path from typing import Any, Optional @@ -362,6 +364,10 @@ def _persist_youtube_pro_channel_edits( return updated +def _youtube_pro_store_error(exc: sqlite3.Error) -> str: + return f"多频道状态数据库写入失败: {exc}; 请确认 config 目录归 live 用户可写" + + def _validate_youtube_runtime_files(process: str) -> list[str]: return validate_youtube_runtime_files(BASE_DIR, CONFIG_DIR, process, get_youtube_pro_channels()) @@ -553,6 +559,8 @@ async def alias_youtube_pro_channels_post(body: YoutubeProChannelsBody): set_youtube_pro_channels(body.channels) except ValueError as exc: return JSONResponse({"error": str(exc)}, status_code=400) + except sqlite3.Error as exc: + return JSONResponse({"error": _youtube_pro_store_error(exc)}, status_code=500) capacity = await asyncio.to_thread(ensure_neko_capacity_for_youtube_channels, BASE_DIR, body.channels) return {"message": "ok", "neko": capacity} @@ -570,6 +578,35 @@ _NO_STORE_HEADERS = { "Expires": "0", } +_READ_CONFIG_MIN_INTERVAL_SECONDS = 0.45 +_READ_CONFIG_LAST_SEEN: dict[tuple[str, str, str], float] = {} + + +def _client_host(request: Request) -> str: + forwarded = (request.headers.get("x-forwarded-for") or "").split(",", 1)[0].strip() + if forwarded: + return forwarded + return request.client.host if request.client else "unknown" + + +def _reject_config_read_storm(request: Request, endpoint: str, process: str) -> JSONResponse | None: + now = time.monotonic() + if len(_READ_CONFIG_LAST_SEEN) > 2048: + cutoff = now - 30.0 + for key, seen_at in list(_READ_CONFIG_LAST_SEEN.items()): + if seen_at < cutoff: + _READ_CONFIG_LAST_SEEN.pop(key, None) + key = (_client_host(request), endpoint, (process or "").strip()) + last = _READ_CONFIG_LAST_SEEN.get(key, 0.0) + _READ_CONFIG_LAST_SEEN[key] = now + if now - last >= _READ_CONFIG_MIN_INTERVAL_SECONDS: + return None + return JSONResponse( + {"error": "刷新过快,请稍后重试"}, + status_code=429, + headers={**_NO_STORE_HEADERS, "Retry-After": "1"}, + ) + class ProcessNameBody(BaseModel): process: str = Field(..., min_length=1, max_length=160) @@ -1112,7 +1149,10 @@ async def get_system_snapshot(): # ---------------- 配置路由(youtube.ini,仅 youtube) ---------------- @app.get("/get_config") -async def get_config(process: str = Query(..., description="进程名")): +async def get_config(request: Request, process: str = Query(..., description="进程名")): + storm = _reject_config_read_storm(request, "get_config", process) + if storm is not None: + return storm rel = managed_youtube_ini_relpath(process) if not rel: return JSONResponse( @@ -1156,13 +1196,18 @@ async def save_config(request: Request, process: str = Query(..., description=" governed_save_managed_file("app-config", rel, content) _persist_youtube_pro_channel_edits(process, youtube_ini_content=content) return JSONResponse({"message": "配置保存成功"}, headers=_NO_STORE_HEADERS) + except sqlite3.Error as e: + return JSONResponse({"error": _youtube_pro_store_error(e)}, status_code=500) except OSError as e: return JSONResponse({"error": f"保存失败: {str(e)}"}, status_code=500) # ---------------- 配置路由(URL_config.ini) ---------------- @app.get("/get_url_config") -async def get_url_config(process: str = Query(..., description="进程名")): +async def get_url_config(request: Request, process: str = Query(..., description="进程名")): + storm = _reject_config_read_storm(request, "get_url_config", process) + if storm is not None: + return storm if not allows_url_config(process): return JSONResponse( {"error": "仅 tiktok*.py / youtube*.py / douyin_youtube*.py 对应进程支持 URL 配置编辑"}, @@ -1210,6 +1255,8 @@ async def save_url_config(request: Request, process: str = Query(..., descriptio governed_save_managed_file("app-config", rel, content) _persist_youtube_pro_channel_edits(process, url_content=content) return JSONResponse({"message": "配置保存成功"}, headers=_NO_STORE_HEADERS) + except sqlite3.Error as e: + return JSONResponse({"error": _youtube_pro_store_error(e)}, status_code=500) except OSError as e: return JSONResponse({"error": f"保存失败: {str(e)}"}, status_code=500)