Update index.html

This commit is contained in:
2025-08-20 21:46:53 -07:00
committed by GitHub
parent 0c11718db8
commit f6333b0f4f

View File

@@ -65,6 +65,7 @@
<button data-action="pin" class="menu-item"><i data-lucide="pin" class="h-4 w-4"></i><span>Pin to top</span></button>
<button data-action="rename" class="menu-item"><i data-lucide="edit-3" class="h-4 w-4"></i><span>Rename</span></button>
<button data-action="delete" class="menu-item text-red-600"><i data-lucide="trash-2" class="h-4 w-4"></i><span>Delete</span></button>
<button data-action="count_tokens" class="menu-item"><i data-lucide="hash" class="h-4 w-4"></i><span>Count tokens (approx.)</span></button>
</div>
<div id="suneMenu" class="menu-card hidden">
<button data-action="pin" class="menu-item"><i data-lucide="pin" class="h-4 w-4"></i><span>Pin to top</span></button>
@@ -149,7 +150,7 @@ function showHistoryMenu(btn,id){menuThreadId=id;const r=btn.getBoundingClientRe
let menuSuneId=null;const hideSuneMenu=()=>{el.suneMenu.classList.add('hidden');menuSuneId=null}
function showSuneMenu(btn,id){menuSuneId=id;const r=btn.getBoundingClientRect();el.suneMenu.style.top=(r.bottom+4)+'px';el.suneMenu.style.left=Math.min(window.innerWidth-220,r.right-200)+'px';el.suneMenu.classList.remove('hidden');icons()}
el.historyList.addEventListener('click',async e=>{const openBtn=e.target.closest('[data-open-thread]'),menuBtn=e.target.closest('[data-thread-menu]');if(openBtn){const id=openBtn.getAttribute('data-open-thread'),th=threads.find(t=>t.id===id)||await idb.get(id);if(!th)return;state.currentThreadId=id;clearChat();state.messages=Array.isArray(th.messages)?[...th.messages]:[];for(const m of state.messages){const b=msgRow(m);renderMarkdown(b,m.content)}queueMicrotask(()=>el.chat.scrollTo({top:el.chat.scrollHeight,behavior:'smooth'}));el.historyPanel.classList.add('translate-x-full');el.historyOverlay.classList.add('hidden');hideHistoryMenu();return}if(menuBtn){e.stopPropagation();showHistoryMenu(menuBtn,menuBtn.getAttribute('data-thread-menu'))}})
el.historyMenu.addEventListener('click',async e=>{const act=e.target.closest('[data-action]')?.getAttribute('data-action');if(!act||!menuThreadId)return;const th=threads.find(t=>t.id===menuThreadId)||await idb.get(menuThreadId);if(!th)return;if(act==='pin'){th.pinned=!th.pinned;await idb.put(th)}else if(act==='rename'){const nv=prompt('Rename to:',th.title);if(nv!=null){th.title=titleFrom(nv);th.updatedAt=Date.now();await idb.put(th)}}else if(act==='delete'){if(confirm('Delete this chat?')){await idb.del(th.id);if(state.currentThreadId===th.id){state.currentThreadId=null;clearChat()}}}hideHistoryMenu();renderHistory()})
el.historyMenu.addEventListener('click',async e=>{const act=e.target.closest('[data-action]')?.getAttribute('data-action');if(!act||!menuThreadId)return;const th=threads.find(t=>t.id===menuThreadId)||await idb.get(menuThreadId);if(!th)return;if(act==='pin'){th.pinned=!th.pinned;await idb.put(th)}else if(act==='rename'){const nv=prompt('Rename to:',th.title);if(nv!=null){th.title=titleFrom(nv);th.updatedAt=Date.now();await idb.put(th)}}else if(act==='delete'){if(confirm('Delete this chat?')){await idb.del(th.id);if(state.currentThreadId===th.id){state.currentThreadId=null;clearChat()}}}else if(act==='count_tokens'){const msgs=Array.isArray(th.messages)?th.messages:[];let totalChars=0;for(const m of msgs){if(!m||!m.role||m.role==='system')continue;totalChars+=String(m.content||'').length}const tokens=Math.max(0,Math.ceil(totalChars/4));const k=tokens>=1000?Math.round(tokens/1000)+'k':String(tokens);alert(tokens+' tokens ('+k+')')}hideHistoryMenu();renderHistory()})
el.suneList.addEventListener('click',e=>{const menuBtn=e.target.closest('[data-sune-menu]');if(menuBtn){e.stopPropagation();showSuneMenu(menuBtn,menuBtn.getAttribute('data-sune-menu'));return}const btn=e.target.closest('[data-sune-id]');if(!btn)return;const id=btn.getAttribute('data-sune-id');if(id){su.setActiveId(id);renderSidebar();reflectActiveSune();state.currentThreadId=null;clearChat();document.getElementById('sidebar').classList.add('-translate-x-full');document.getElementById('sidebarOverlay').classList.add('hidden')}})
el.suneMenu.addEventListener('click',e=>{const act=e.target.closest('[data-action]')?.getAttribute('data-action');if(!act||!menuSuneId)return;const s=sunes.find(x=>x.id===menuSuneId);if(!s)return;if(act==='pin')s.pinned=!s.pinned;else if(act==='rename'){const nv=prompt('Rename sune to:',s.name);if(nv!=null)s.name=nv.trim()||s.name}else if(act==='pfp'){const url=prompt('Image URL:',s.avatar||'');if(url!==null)s.avatar=url.trim()}s.updatedAt=Date.now();su.save(sunes);hideSuneMenu();renderSidebar();reflectActiveSune()})
const raf=(fn=>{let id=null;return()=>{if(id)cancelAnimationFrame(id);id=requestAnimationFrame(()=>{id=null;fn()})}})