fix(gif): send a GIF as the active reply; show GIF (not URL) in reply bar/quote (batch89)
sendGif ignored replyTarget, so picking a GIF while replying sent a plain message instead of a reply. It now carries replyTo and clears the reply, like sendMessage. Reply bar + quote show 'GIF' instead of the raw media URL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1078,7 +1078,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<script src="/icons.js?v=6"></script>
|
||||
<script>window.__BUILD='2026-07-15-batch88';console.log('%cBiz Connect','color:#1F3B73;font-weight:bold','build '+window.__BUILD);
|
||||
<script>window.__BUILD='2026-07-15-batch89';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
|
||||
@@ -1851,7 +1851,7 @@ function bubbleHTML(m){
|
||||
// #1: the sender chip is clickable → mini profile card (with a Message button that opens their DM).
|
||||
const sender=(convoIsGroup && !mine && m.fromName)?'<div class="sender profile-open" data-uid="'+pEsc(m.from)+'" title="View profile">'+senderAvatar(m.from, m.fromName)+'<span>'+pEsc(m.fromName)+'</span></div>':'';
|
||||
let quote='';
|
||||
if(m.reply){ const t=replyTint(m.reply.from||m.reply.fromName); quote='<div class="quote" data-jid="'+pEsc(m.reply.id||'')+'" data-jat="'+(m.reply.at||0)+'" title="Go to message" style="background:'+t[0]+';border-left-color:'+t[1]+'"><b style="color:'+t[1]+'">'+pEsc(m.reply.fromName||'')+'</b>: '+pEsc(m.reply.body)+'</div>'; }
|
||||
if(m.reply){ const t=replyTint(m.reply.from||m.reply.fromName); const rb=isGifUrl(m.reply.body)?'🎞️ GIF':m.reply.body; quote='<div class="quote" data-jid="'+pEsc(m.reply.id||'')+'" data-jat="'+(m.reply.at||0)+'" title="Go to message" style="background:'+t[0]+';border-left-color:'+t[1]+'"><b style="color:'+t[1]+'">'+pEsc(m.reply.fromName||'')+'</b>: '+pEsc(rb)+'</div>'; }
|
||||
const reacts=(m.reactions&&m.reactions.length)?'<div class="reacts">'+m.reactions.map(r=>'<button class="react-chip'+(r.mine?' mine':'')+'" data-id="'+pEsc(m.id)+'" data-emoji="'+pEsc(r.emoji)+'" title="'+pEsc((r.who||[]).join(', '))+'">'+pEsc(r.emoji)+' '+r.count+'</button>').join('')+'</div>':'';
|
||||
const att = m.attachment ? (m.attachment.isImage
|
||||
? '<img class="att-img" src="/files/'+pEsc(m.attachment.id)+'" data-img="/files/'+pEsc(m.attachment.id)+'" alt="'+pEsc(m.attachment.name)+'" title="Click to view">'
|
||||
@@ -1963,7 +1963,8 @@ function setReply(m){
|
||||
replyTarget=m;
|
||||
const bar=document.getElementById('replyBar'); if(!bar) return;
|
||||
const who=m.from===ME.id?'yourself':(m.fromName||currentName()||'them');
|
||||
bar.innerHTML='<span>'+ic('reply',13)+' Replying to <b>'+pEsc(who)+'</b>: '+pEsc(m.body.length>80?m.body.slice(0,80)+'…':m.body)+'</span><span class="rx" id="replyCancel">'+ic('x',15)+'</span>';
|
||||
const rprev=isGifUrl(m.body)?'🎞️ GIF':(m.body.length>80?m.body.slice(0,80)+'…':m.body);
|
||||
bar.innerHTML='<span>'+ic('reply',13)+' Replying to <b>'+pEsc(who)+'</b>: '+pEsc(rprev)+'</span><span class="rx" id="replyCancel">'+ic('x',15)+'</span>';
|
||||
bar.style.display='flex';
|
||||
document.getElementById('replyCancel').onclick=clearReply;
|
||||
const inp=document.getElementById('msgInput'); if(inp) inp.focus();
|
||||
@@ -2137,12 +2138,15 @@ async function loadGifs(q){
|
||||
grid.innerHTML=gifs.map(g=>'<button type="button" class="gif-cell" data-url="'+pEsc(g.url)+'" title="'+pEsc(g.title||'GIF')+'"><img src="'+pEsc(g.preview||g.url)+'" loading="lazy" alt=""></button>').join('');
|
||||
grid.querySelectorAll('.gif-cell').forEach(b=>b.onclick=(ev)=>{ ev.stopPropagation(); sendGif(b.dataset.url); });
|
||||
}
|
||||
// GIFs send immediately (like a sticker), hotlinked to GIPHY's CDN per their terms.
|
||||
// GIFs send immediately (like a sticker), hotlinked to GIPHY's CDN per their terms. If a reply is armed,
|
||||
// the GIF is sent AS that reply (it was going out as a plain message before).
|
||||
async function sendGif(url){
|
||||
if(!url || !selected) return;
|
||||
closeEmoji();
|
||||
const kind=selected.kind, id=selected.id;
|
||||
try{ const m=await postJSON('/api/messages', kind==='group'?{group:id, body:url}:{to:id, body:url}); if(m){ /* echo arrives via WS */ } }
|
||||
const replyTo=replyTarget?replyTarget.id:null;
|
||||
clearReply();
|
||||
try{ await postJSON('/api/messages', kind==='group'?{group:id, body:url, replyTo}:{to:id, body:url, replyTo}); }
|
||||
catch(e){ toast(e.message||'Could not send GIF'); }
|
||||
}
|
||||
function onEmojiPick(e){ if(emojiMode && emojiMode.react){ reactToMessage(emojiMode.react, e); closeEmoji(); } else { insertEmoji(e); } }
|
||||
|
||||
Reference in New Issue
Block a user