Update app/static/index.html
Browse files- app/static/index.html +31 -0
app/static/index.html
CHANGED
|
@@ -454,6 +454,37 @@ function renderMD(txt){if(!txt)return'';marked.setOptions({breaks:true,gfm:true}
|
|
| 454 |
function addCodeCopyBtns(c){c.querySelectorAll('pre code').forEach(b=>{if(!b.closest('.cbw')){const w=document.createElement('div');w.className='cbw';const h=document.createElement('div');h.className='chead';h.innerHTML='<span>code</span><button class="cpbtn" onclick="copyCode(this)">Copy</button>';const pre=b.parentElement;pre.parentNode.insertBefore(w,pre);w.appendChild(h);w.appendChild(pre)}})}
|
| 455 |
function copyCode(btn){navigator.clipboard.writeText(btn.closest('.cbw').querySelector('code').innerText).then(()=>{btn.textContent='Copied!';setTimeout(()=>btn.textContent='Copy',2000)})}
|
| 456 |
function copyTxt(txt,btn){navigator.clipboard.writeText(txt).then(()=>{btn.textContent='β
';setTimeout(()=>btn.textContent='π Copy',2000)})}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 457 |
init();
|
| 458 |
</script>
|
| 459 |
</body>
|
|
|
|
| 454 |
function addCodeCopyBtns(c){c.querySelectorAll('pre code').forEach(b=>{if(!b.closest('.cbw')){const w=document.createElement('div');w.className='cbw';const h=document.createElement('div');h.className='chead';h.innerHTML='<span>code</span><button class="cpbtn" onclick="copyCode(this)">Copy</button>';const pre=b.parentElement;pre.parentNode.insertBefore(w,pre);w.appendChild(h);w.appendChild(pre)}})}
|
| 455 |
function copyCode(btn){navigator.clipboard.writeText(btn.closest('.cbw').querySelector('code').innerText).then(()=>{btn.textContent='Copied!';setTimeout(()=>btn.textContent='Copy',2000)})}
|
| 456 |
function copyTxt(txt,btn){navigator.clipboard.writeText(txt).then(()=>{btn.textContent='β
';setTimeout(()=>btn.textContent='π Copy',2000)})}
|
| 457 |
+
// ββ CROSS-PLATFORM SYNC ββββββββββββββββββββββββββββββββββββββββ
|
| 458 |
+
let _sseSource = null;
|
| 459 |
+
const _sessionId = 'web_' + (localStorage.getItem('pc_session') || (()=>{const id=uid();localStorage.setItem('pc_session',id);return id})());
|
| 460 |
+
|
| 461 |
+
function startSSESync(){
|
| 462 |
+
if(_sseSource) return;
|
| 463 |
+
_sseSource = new EventSource(`/api/sse/${_sessionId}`);
|
| 464 |
+
_sseSource.onmessage = (e) => {
|
| 465 |
+
try{
|
| 466 |
+
const ev = JSON.parse(e.data);
|
| 467 |
+
if(ev.type === 'tg_message'){
|
| 468 |
+
// Telegram message arrived β add to current chat
|
| 469 |
+
if(!S.curId) newChat();
|
| 470 |
+
const msg = {id:uid(), role:ev.role, content:ev.content, ts:Date.now(), source:'telegram'};
|
| 471 |
+
S.msgs.push(msg);
|
| 472 |
+
const row = appendMsg(msg);
|
| 473 |
+
if(row && ev.role==='assistant') markDone(row);
|
| 474 |
+
syncConv();
|
| 475 |
+
showToast('π± Message from Telegram');
|
| 476 |
+
}
|
| 477 |
+
}catch(e){}
|
| 478 |
+
};
|
| 479 |
+
_sseSource.onerror = () => {
|
| 480 |
+
_sseSource = null;
|
| 481 |
+
setTimeout(startSSESync, 5000); // reconnect after 5s
|
| 482 |
+
};
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
// Start SSE sync
|
| 486 |
+
setTimeout(startSSESync, 1000);
|
| 487 |
+
|
| 488 |
init();
|
| 489 |
</script>
|
| 490 |
</body>
|