This commit is contained in:
2026-03-06 04:00:48 +05:00
parent 7444e7ddd7
commit ed1f3b3a75
5 changed files with 225 additions and 122 deletions

88
ui.ts
View File

@@ -97,6 +97,20 @@ export const html = `<!DOCTYPE html>
.proxy-tag.blue{color:#60a5fa;background:rgba(96,165,250,.1)}
.proxy-refresh{background:none;border:none;color:var(--dim);cursor:pointer;padding:4px;font-size:.9rem;transition:color .2s;flex-shrink:0}
.proxy-refresh:hover{color:var(--text)}
.proxy-settings{display:none;margin-top:10px;padding-top:10px;border-top:1px solid var(--border);width:100%}
.proxy-settings.open{display:block}
.proxy-form{display:flex;gap:8px;flex-wrap:wrap}
.proxy-input{flex:1;min-width:200px;background:var(--surface2);border:1px solid var(--border);padding:8px 12px;border-radius:8px;color:var(--text);font-size:.8rem;font-family:monospace}
.proxy-input:focus{outline:none;border-color:var(--accent)}
.proxy-input::placeholder{color:var(--dim)}
.proxy-save{background:var(--accent);color:#000;border:none;padding:8px 16px;border-radius:8px;font-size:.8rem;font-weight:600;cursor:pointer;font-family:inherit;transition:opacity .15s}
.proxy-save:hover{opacity:.85}
.proxy-save:disabled{opacity:.4}
.proxy-clear-btn{background:rgba(239,68,68,.15);color:#ef4444;border:1px solid rgba(239,68,68,.3);padding:8px 14px;border-radius:8px;font-size:.8rem;cursor:pointer;font-family:inherit;transition:all .15s}
.proxy-clear-btn:hover{background:rgba(239,68,68,.25)}
.proxy-msg{font-size:.75rem;margin-top:6px;padding:4px 8px;border-radius:4px;display:none}
.proxy-msg.ok{display:block;color:#10b981;background:rgba(16,185,129,.1)}
.proxy-msg.err{display:block;color:#ef4444;background:rgba(239,68,68,.1)}
@media(max-width:600px){.container{padding:40px 16px 180px}.logo{width:80px;height:80px}.title{font-size:2rem}.desc{display:none}.search-row{flex-direction:column}.proxy-widget{flex-wrap:wrap}}
</style>
</head>
@@ -109,14 +123,26 @@ export const html = `<!DOCTYPE html>
<p class="subtitle">Music API for YouTube Music, Lyrics & Streaming</p>
<!-- Proxy Status Widget -->
<div class="proxy-widget loading" id="proxyWidget">
<div class="proxy-widget loading" id="proxyWidget" style="flex-wrap:wrap">
<div class="proxy-dot"></div>
<div class="proxy-main">
<div class="proxy-label" id="proxyLabel">Checking proxy...</div>
<div class="proxy-sub" id="proxySub"></div>
<div class="proxy-meta" id="proxyMeta"></div>
</div>
<button class="proxy-refresh" onclick="toggleProxySettings()" title="Settings" style="font-size:1rem">⚙</button>
<button class="proxy-refresh" id="proxyRefreshBtn" onclick="loadProxyStatus()" title="Refresh">↻</button>
<!-- Settings form (hidden by default) -->
<div class="proxy-settings" id="proxySettings">
<div style="font-size:.7rem;color:var(--muted);margin-bottom:6px">Proxy URL <span style="color:var(--dim)">(http://user:pass@host:port)</span></div>
<div class="proxy-form">
<input class="proxy-input" id="proxyUrlInput" type="text" placeholder="http://music:music@193.124.94.179:35467" spellcheck="false" autocomplete="off">
<button class="proxy-save" id="proxySaveBtn" onclick="saveProxy()">Test & Save</button>
<button class="proxy-clear-btn" onclick="clearProxy()">Clear</button>
</div>
<div class="proxy-msg" id="proxyMsg"></div>
</div>
</div>
</div>
@@ -494,6 +520,66 @@ async function testApi(){
}
updateInputs();
// ── Proxy Settings Form ────────────────────────────────────────────────────
function toggleProxySettings(){
var s=document.getElementById('proxySettings');
s.classList.toggle('open');
}
function showProxyMsg(text,isOk){
var m=document.getElementById('proxyMsg');
m.textContent=text;
m.className='proxy-msg '+(isOk?'ok':'err');
clearTimeout(m._t);
m._t=setTimeout(()=>m.className='proxy-msg',4000);
}
async function saveProxy(){
var input=document.getElementById('proxyUrlInput');
var btn=document.getElementById('proxySaveBtn');
var url=input.value.trim();
if(!url){showProxyMsg('Enter proxy URL first','');return;}
btn.disabled=true;
btn.textContent='Testing...';
try{
var res=await fetch('/api/proxy/set',{
method:'POST',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({url:url})
});
var d=await res.json();
if(d.success){
showProxyMsg('✓ Saved. Checking status...',true);
// Collapse form and refresh status
setTimeout(()=>{
document.getElementById('proxySettings').classList.remove('open');
loadProxyStatus();
},600);
}else{
showProxyMsg('Error: '+(d.error||'Unknown'),false);
}
}catch(e){
showProxyMsg('Request failed: '+String(e),false);
}finally{
btn.disabled=false;
btn.textContent='Test & Save';
}
}
async function clearProxy(){
try{
await fetch('/api/proxy/clear',{method:'POST'});
document.getElementById('proxyUrlInput').value='';
document.getElementById('proxySettings').classList.remove('open');
showProxyMsg('Proxy cleared',true);
setTimeout(loadProxyStatus,400);
}catch(e){
showProxyMsg('Failed: '+String(e),false);
}
}
// ── Proxy Status Widget ────────────────────────────────────────────────────
async function loadProxyStatus(){
var w=document.getElementById('proxyWidget');