fix(media): keep sticker and gif clicks out of photo viewer
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-03-08 20:44:33 +03:00
parent f0582bf4ab
commit 11d108f0a6
2 changed files with 26 additions and 3 deletions

View File

@@ -22,7 +22,7 @@ Legend:
13. Reactions - `DONE`
14. Delivery Status - `DONE` (sent/delivered/read + reconnect reconciliation after backend restarts)
15. Typing Realtime - `DONE` (typing start/stop + recording voice start/stop + recording video start/stop in circle-video send flow)
16. Media & Attachments - `DONE` (upload/preview/download/gallery)
16. Media & Attachments - `DONE` (upload/preview/download/gallery; sticker/GIF inline media no longer opens photo viewer on click)
17. Voice Messages - `PARTIAL` (record/send/play/seek + global speed 1x/1.5x/2x; recorder uses mime fallback + chunked capture; websocket send/recorder stop race on fast chat switch is guarded; UX still being polished)
18. Circle Video Messages - `PARTIAL` (send/play present, recording UX basic)
19. Stickers - `PARTIAL` (web sticker picker with preset pack + favorites)

View File

@@ -1066,11 +1066,17 @@ function renderMessageContent(
}
if (mediaItems.length === 1) {
const item = mediaItems[0];
const blockViewerOpen = isStickerOrGifMedia(item.url);
return (
<div className="space-y-1.5">
<button
className="relative block overflow-hidden rounded-xl bg-slate-950/30"
onClick={() => opts.onOpenMedia(item.url, item.type)}
onClick={() => {
if (blockViewerOpen) {
return;
}
opts.onOpenMedia(item.url, item.type);
}}
onContextMenu={(event) => {
event.stopPropagation();
opts.onAttachmentContextMenu(event, item.url);
@@ -1098,11 +1104,17 @@ function renderMessageContent(
<div className={`grid gap-1.5 rounded-xl ${gridClass}`}>
{mediaItems.slice(0, 6).map((item, index) => {
const tileClass = getMediaTileClass(mediaItems.length, index);
const blockViewerOpen = isStickerOrGifMedia(item.url);
return (
<button
className={`relative overflow-hidden rounded-lg bg-slate-950/30 ${tileClass}`}
key={`${item.url}-${index}`}
onClick={() => opts.onOpenMedia(item.url, item.type)}
onClick={() => {
if (blockViewerOpen) {
return;
}
opts.onOpenMedia(item.url, item.type);
}}
onContextMenu={(event) => {
event.stopPropagation();
opts.onAttachmentContextMenu(event, item.url);
@@ -1243,6 +1255,17 @@ function getSafeContextPosition(x: number, y: number, menuWidth: number, menuHei
return { x: safeX, y: safeY };
}
function isStickerOrGifMedia(url: string): boolean {
const value = url.toLowerCase();
if (value.includes("twemoji")) {
return true;
}
if (value.includes("giphy.com") || value.includes("tenor.com") || value.includes("tenor.googleapis.com")) {
return true;
}
return /\.gif($|\?)/.test(value);
}
function chatLabel(chat: { display_title?: string | null; title: string | null; type: "private" | "group" | "channel"; is_saved?: boolean }): string {
if (chat.display_title?.trim()) return chat.display_title;
if (chat.title?.trim()) return chat.title;