feat(video): server-generated poster thumbnails + HTTP Range streaming
- Dockerfile: add ffmpeg (Alpine). - static.js: new /thumbs/<id> — ffmpeg extracts the first frame (0.5s), caches it next to the file, serves as the video poster (cosmetic; 404s gracefully if ffmpeg unavailable). - static.js: /files now supports HTTP Range (206 Partial Content) + Accept-Ranges, which iOS requires to stream/seek video reliably (fixes the buffer-before-play / multi-tap); media (image/video/audio) now served inline, other files still download. Shared attachment auth refactored into one helper used by /files and /thumbs. - home.html: video poster points at /thumbs/<id>. build batch157. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1162,7 +1162,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<script src="/icons.js?v=6"></script>
|
||||
<script>window.__BUILD='2026-07-22-batch156';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
<script>window.__BUILD='2026-07-22-batch157';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
|
||||
@@ -2010,7 +2010,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 ? '<video class="att-vid" src="/files/'+pEsc(A.id)+'#t=0.1" controls playsinline preload="metadata" title="'+pEsc(A.name)+'"></video>'
|
||||
: A.isVideo ? '<video class="att-vid" src="/files/'+pEsc(A.id)+'#t=0.1" poster="/thumbs/'+pEsc(A.id)+'" controls playsinline preload="metadata" title="'+pEsc(A.name)+'"></video>'
|
||||
: '<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).
|
||||
|
||||
Reference in New Issue
Block a user