perf(video): cache attachment auth so Range playback stops stuttering; strict on-demand
Root cause of a downloaded/streaming video buffering repeatedly: every /files Range request (a playing video fires dozens) re-ran the full attachment authorization, which scans the messages table by attachment_id (un-indexed) — a per-chunk table scan = stutter. Now the auth decision is cached per user+attachment for 60s (module-level, bounded), so range requests after the first are ~free. Also: preload='none' (nothing about a video downloads until the user taps play — only the small poster loads), per 'no auto-download'. And the buffering spinner no longer hides on canplay/loadeddata (they fire mid-buffer), so it reliably spins whenever it's buffering. build batch159. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1165,7 +1165,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<script src="/icons.js?v=6"></script>
|
||||
<script>window.__BUILD='2026-07-22-batch158';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
<script>window.__BUILD='2026-07-22-batch159';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
// Emoji are rendered with the OS's own (colour) emoji font — instant, zero network.
|
||||
//
|
||||
// We used to run Twemoji over every emoji, which swapped each one for an <img> pulled INDIVIDUALLY from
|
||||
@@ -2013,7 +2013,7 @@ function bubbleHTML(m){
|
||||
const A = m.attachment;
|
||||
const att = A ? (
|
||||
A.isImage ? '<img class="att-img" src="/files/'+pEsc(A.id)+'" data-img="/files/'+pEsc(A.id)+'" alt="'+pEsc(A.name)+'" title="Click to view">'
|
||||
: A.isVideo ? '<div class="att-vid"><video class="att-vid-v" src="/files/'+pEsc(A.id)+'#t=0.1" poster="/thumbs/'+pEsc(A.id)+'" controls playsinline preload="metadata" title="'+pEsc(A.name)+'"></video><span class="att-vid-spin" aria-hidden="true"></span></div>'
|
||||
: A.isVideo ? '<div class="att-vid"><video class="att-vid-v" src="/files/'+pEsc(A.id)+'#t=0.1" poster="/thumbs/'+pEsc(A.id)+'" controls playsinline preload="none" title="'+pEsc(A.name)+'"></video><span class="att-vid-spin" aria-hidden="true"></span></div>'
|
||||
: '<a class="att-file" href="/files/'+pEsc(A.id)+'" download="'+pEsc(A.name)+'">'+ic('file',15)+' <span>'+pEsc(A.name)+'</span> <span class="att-sz">'+fmtSize(A.size)+'</span></a>') : '';
|
||||
const mentionsMe=convoIsGroup && !mine && Array.isArray(m.mentions) && (m.mentions.includes(ME.id)||m.mentions.includes('everyone'));
|
||||
// DM ticks: sent (1 grey) → delivered (2 grey) → read (2 yellow).
|
||||
@@ -5047,7 +5047,7 @@ window.addEventListener('popstate', ()=>{ if(bzcBack()){ try{ history.pushState(
|
||||
(function(){
|
||||
const set=(on)=>(e)=>{ const v=e.target; if(v && v.classList && v.classList.contains('att-vid-v')){ const w=v.parentElement; if(w && w.classList.contains('att-vid')) w.classList.toggle('buffering', on); } };
|
||||
['waiting','seeking','stalled'].forEach(ev=>document.addEventListener(ev, set(true), true));
|
||||
['playing','canplay','seeked','pause','ended','error','loadeddata'].forEach(ev=>document.addEventListener(ev, set(false), true));
|
||||
['playing','seeked','pause','ended','error'].forEach(ev=>document.addEventListener(ev, set(false), true)); // NOT canplay/loadeddata — they fire mid-buffer and would hide the spinner too early
|
||||
})();
|
||||
// #9: swipe a message bubble to the right to reply to it (mobile), like WhatsApp/Teams. The bubble
|
||||
// follows the finger a little; releasing past the threshold opens the reply composer for that message.
|
||||
|
||||
Reference in New Issue
Block a user