fix(media): keep sticker and gif clicks out of photo viewer
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
This commit is contained in:
@@ -22,7 +22,7 @@ Legend:
|
|||||||
13. Reactions - `DONE`
|
13. Reactions - `DONE`
|
||||||
14. Delivery Status - `DONE` (sent/delivered/read + reconnect reconciliation after backend restarts)
|
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)
|
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)
|
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)
|
18. Circle Video Messages - `PARTIAL` (send/play present, recording UX basic)
|
||||||
19. Stickers - `PARTIAL` (web sticker picker with preset pack + favorites)
|
19. Stickers - `PARTIAL` (web sticker picker with preset pack + favorites)
|
||||||
|
|||||||
@@ -1066,11 +1066,17 @@ function renderMessageContent(
|
|||||||
}
|
}
|
||||||
if (mediaItems.length === 1) {
|
if (mediaItems.length === 1) {
|
||||||
const item = mediaItems[0];
|
const item = mediaItems[0];
|
||||||
|
const blockViewerOpen = isStickerOrGifMedia(item.url);
|
||||||
return (
|
return (
|
||||||
<div className="space-y-1.5">
|
<div className="space-y-1.5">
|
||||||
<button
|
<button
|
||||||
className="relative block overflow-hidden rounded-xl bg-slate-950/30"
|
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) => {
|
onContextMenu={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
opts.onAttachmentContextMenu(event, item.url);
|
opts.onAttachmentContextMenu(event, item.url);
|
||||||
@@ -1098,11 +1104,17 @@ function renderMessageContent(
|
|||||||
<div className={`grid gap-1.5 rounded-xl ${gridClass}`}>
|
<div className={`grid gap-1.5 rounded-xl ${gridClass}`}>
|
||||||
{mediaItems.slice(0, 6).map((item, index) => {
|
{mediaItems.slice(0, 6).map((item, index) => {
|
||||||
const tileClass = getMediaTileClass(mediaItems.length, index);
|
const tileClass = getMediaTileClass(mediaItems.length, index);
|
||||||
|
const blockViewerOpen = isStickerOrGifMedia(item.url);
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={`relative overflow-hidden rounded-lg bg-slate-950/30 ${tileClass}`}
|
className={`relative overflow-hidden rounded-lg bg-slate-950/30 ${tileClass}`}
|
||||||
key={`${item.url}-${index}`}
|
key={`${item.url}-${index}`}
|
||||||
onClick={() => opts.onOpenMedia(item.url, item.type)}
|
onClick={() => {
|
||||||
|
if (blockViewerOpen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
opts.onOpenMedia(item.url, item.type);
|
||||||
|
}}
|
||||||
onContextMenu={(event) => {
|
onContextMenu={(event) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
opts.onAttachmentContextMenu(event, item.url);
|
opts.onAttachmentContextMenu(event, item.url);
|
||||||
@@ -1243,6 +1255,17 @@ function getSafeContextPosition(x: number, y: number, menuWidth: number, menuHei
|
|||||||
return { x: safeX, y: safeY };
|
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 {
|
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.display_title?.trim()) return chat.display_title;
|
||||||
if (chat.title?.trim()) return chat.title;
|
if (chat.title?.trim()) return chat.title;
|
||||||
|
|||||||
Reference in New Issue
Block a user