@linktr.ee/messaging-react 4.4.3 → 4.4.4-rc-1788190776
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AttachmentCard-BbsjzdLJ.cjs +2 -0
- package/dist/AttachmentCard-BbsjzdLJ.cjs.map +1 -0
- package/dist/{AttachmentCard-BqwWgqvi.js → AttachmentCard-DSekwIOA.js} +35 -20
- package/dist/AttachmentCard-DSekwIOA.js.map +1 -0
- package/dist/{Card-BIbqWagz.cjs → Card-BS6Fza2a.cjs} +2 -2
- package/dist/{Card-BIbqWagz.cjs.map → Card-BS6Fza2a.cjs.map} +1 -1
- package/dist/{Card-f51K6V7Y.js → Card-BhwBkgxI.js} +2 -2
- package/dist/{Card-f51K6V7Y.js.map → Card-BhwBkgxI.js.map} +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +67 -42
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/AttachmentCard/MediaPlayer.test.tsx +62 -85
- package/src/components/AttachmentCard/MediaPlayer.tsx +14 -2
- package/src/components/AttachmentCard/Thumbnail.test.tsx +37 -46
- package/src/components/AttachmentCard/index.test.tsx +18 -46
- package/src/components/AttachmentCard/index.tsx +8 -2
- package/src/components/AttachmentCard/utils/icons.ts +11 -1
- package/src/components/Avatar/Avatar.test.tsx +37 -64
- package/src/components/Avatar/index.tsx +8 -1
- package/src/components/ChannelList/CustomChannelPreview.test.tsx +19 -19
- package/src/components/ChannelList/CustomChannelPreview.tsx +8 -2
- package/src/components/ChannelView.outbound-resolution.integration.test.tsx +25 -30
- package/src/components/ChannelView.test.tsx +17 -31
- package/src/components/ChannelView.tsx +1 -0
- package/src/components/CustomLinkPreviewList/CustomLinkPreviewList.test.tsx +8 -5
- package/src/components/CustomLinkPreviewList/index.tsx +4 -1
- package/src/components/CustomMessage/StreamAttachmentMessage.test.tsx +26 -21
- package/src/components/CustomMessage/StreamAttachmentMessage.tsx +2 -0
- package/src/components/CustomMessageInput/CustomMessageInput.test.tsx +43 -56
- package/src/components/CustomMessageInput/index.tsx +25 -5
- package/src/components/CustomSystemMessage/CustomSystemMessage.test.tsx +17 -23
- package/src/components/FaqList/FaqList.test.tsx +5 -4
- package/src/components/FaqList/index.tsx +6 -1
- package/src/components/LinkAttachment/LinkAttachment.test.tsx +70 -81
- package/src/components/LinkAttachment/components/_shared/BubbleTail.test.tsx +1 -0
- package/src/components/LinkAttachment/components/_shared/CardBody.test.tsx +20 -61
- package/src/components/LinkAttachment/components/_shared/CardBody.tsx +10 -2
- package/src/components/LinkAttachment/components/_shared/CardCta.test.tsx +1 -21
- package/src/components/LinkAttachment/components/_shared/CardShell.test.tsx +11 -37
- package/src/components/LinkAttachment/components/_shared/CardShell.tsx +5 -2
- package/src/components/LinkAttachment/components/_shared/CardThumbnail.test.tsx +65 -72
- package/src/components/LinkAttachment/components/_shared/CardThumbnail.tsx +13 -2
- package/src/components/MessageAttachment/MessageAttachment.test.tsx +25 -8
- package/src/components/MessageAttachment/_shared/CompactDocumentRow.test.tsx +5 -19
- package/src/components/MessageAttachment/_shared/MediaStackGrid.test.tsx +7 -9
- package/src/components/MessageAttachment/_shared/VideoViewer.test.tsx +9 -2
- package/src/components/MessageAttachment/_shared/VideoViewer.tsx +1 -0
- package/src/components/MessageAttachment/_shared/ViewerShell.test.tsx +2 -2
- package/src/components/MessageBubble/MessageBubble.test.tsx +0 -1
- package/src/components/RichCard/RichCard.test.tsx +24 -54
- package/src/components/RichCard/RichCardBody.tsx +4 -1
- package/src/hooks/useChannelModerationActions.ts +15 -30
- package/src/logging/index.test.tsx +1 -0
- package/src/providers/MessagingProvider.test.tsx +37 -41
- package/dist/AttachmentCard-BqwWgqvi.js.map +0 -1
- package/dist/AttachmentCard-DUrgGRsq.cjs +0 -2
- package/dist/AttachmentCard-DUrgGRsq.cjs.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("./rolldown-runtime-BocRIvOZ.cjs");let t=require("react");t=e.t(t,1);let n=require("react/jsx-runtime"),r=require("classnames");r=e.t(r,1);let i=require("@phosphor-icons/react");var a=[`linktr.ee`],o=`messaging-attachment-v1_0`;function s(e){try{return new URL(e).hostname.toLowerCase()}catch{return null}}function c(e){return a.some(t=>e===t||e.endsWith(`.${t}`))}function l(e){let t=e?.trim();if(!t)return;let n=s(t);if(!n||!c(n))return t;let r=new URL(t);return r.searchParams.get(`io`)===`true`&&r.searchParams.get(`size`)===o?t:(r.searchParams.set(`io`,`true`),r.searchParams.set(`size`,o),r.toString())}var u=`data-mes-native-player`,d={[u]:``},f=e=>{typeof document>`u`||document.querySelectorAll(`[${u}]`).forEach(t=>{t!==e&&t.pause()})},p=[[/pdf/,`pdf`],[/wordprocessingml|msword|\.doc/,`doc`],[/spreadsheetml|ms-excel|\.xls/,`xls`],[/csv/,`csv`],[/presentationml|ms-powerpoint|\.ppt/,`ppt`],[/zip|x-rar|x-7z|x-tar|x-gzip/,`zip`],[/plain|rtf/,`text`],[/markdown/,`markdown`]];function m(e){return e.startsWith(`video/`)?`video`:e.startsWith(`audio/`)?`audio`:e.startsWith(`image/`)?`image`:`document`}function h(e){let t=p.find(([t])=>t.test(e));return t?t[1]:`generic`}var g={video:i.VideoCameraIcon,audio:i.SpeakerHighIcon,image:i.ImageIcon,document:i.FileIcon},_={pdf:i.FilePdfIcon,doc:i.FileDocIcon,xls:i.FileXlsIcon,csv:i.FileCsvIcon,ppt:i.FilePptIcon,zip:i.FileZipIcon,text:i.FileTextIcon,markdown:i.FileMdIcon,generic:i.FileIcon};function v(e){let t=m(e);return t===`document`?_[h(e)]:g[t]}function y(e){let t=m(e);return t===`document`?h(e):t}function b(e,n){return t.default.createElement(v(e),{"data-testid":`type-icon-${y(e)}`,...n})}function x(){return!1}var S=e=>`touches`in e?e.touches[0]?.clientX??e.changedTouches[0]?.clientX??0:e.clientX,C=({source:e,mimeType:r,poster:a,autoPlay:o=!1,playing:s,loop:c=!1,controls:l=!0,showProgress:u=!1,muted:f=!1,onContainerClick:p})=>{let h=m(r),g=(0,t.useRef)(null),_=(0,t.useRef)(null),v=(0,t.useRef)(null),y=(0,t.useRef)(s),[C,w]=(0,t.useState)(o),[T,E]=(0,t.useState)(0),[D,O]=(0,t.useState)(!1),[k,A]=(0,t.useState)(!1),[j,M]=(0,t.useState)(!1),[N,P]=(0,t.useState)(!1),[F,I]=(0,t.useState)(!0),[L,R]=(0,t.useState)(null),z=(0,t.useCallback)(()=>{M(!1),w(!0)},[]),B=(0,t.useCallback)(e=>{let t=_.current;if(!t)return 0;let n=t.getBoundingClientRect();return Math.max(0,Math.min(1,(S(e)-n.left)/n.width))},[]),V=(0,t.useCallback)(e=>{let t=g.current;t&&t.duration&&(t.currentTime=e*t.duration)},[]),H=e=>{e.stopPropagation(),O(!0);let t=B(e);E(t),V(t)},U=(0,t.useCallback)(e=>{e.key===`ArrowRight`&&V(Math.min(1,T+.05)),e.key===`ArrowLeft`&&V(Math.max(0,T-.05))},[V,T]);(0,t.useEffect)(()=>{s!==void 0&&s!==y.current&&(y.current=s,w(s))},[s]),(0,t.useEffect)(()=>{if(!C){v.current!==null&&(cancelAnimationFrame(v.current),v.current=null);return}let e=()=>{let t=g.current;t&&t.duration&&!D&&E(t.currentTime/t.duration),v.current=requestAnimationFrame(e)};return v.current=requestAnimationFrame(e),()=>{v.current!==null&&cancelAnimationFrame(v.current)}},[C,D]),(0,t.useEffect)(()=>{let e=g.current;e&&(C?e.play().catch(e=>{w(!1),M(!0),x()&&console.debug(`[MediaPlayer] play() failed`,e)}):e.pause())},[C]),(0,t.useEffect)(()=>{if(!D)return;let e=e=>E(B(e)),t=e=>{O(!1),V(B(e))};return window.addEventListener(`mousemove`,e),window.addEventListener(`mouseup`,t),window.addEventListener(`touchmove`,e,{passive:!0}),window.addEventListener(`touchend`,t),()=>{window.removeEventListener(`mousemove`,e),window.removeEventListener(`mouseup`,t),window.removeEventListener(`touchmove`,e),window.removeEventListener(`touchend`,t)}},[D,B,V]);let W=L?{aspectRatio:String(L)}:void 0,G=L?``:` aspect-video`,K=Math.round(T*100);return(0,n.jsxs)(`div`,{role:`button`,tabIndex:0,"data-testid":`media-player`,className:`relative cursor-pointer overflow-hidden bg-black ${G}`,style:W,onClick:e=>{if(p){p(e);return}j||l&&w(e=>!e)},onKeyDown:e=>{if(e.key===`Enter`||e.key===` `){if(e.preventDefault(),p){p(e);return}j||l&&w(e=>!e)}},children:[a&&(h===`audio`||F)&&(0,n.jsx)(`img`,{src:a,alt:``,"data-testid":`media-player-poster`,className:`absolute inset-0 h-full w-full object-cover`}),!a&&(h===`audio`||F)&&(0,n.jsx)(`div`,{"data-testid":`media-player-placeholder`,className:`absolute inset-0 flex items-center justify-center`,children:b(r,{className:`size-12 text-black/20`,weight:`regular`})}),(0,n.jsx)(`div`,{className:`absolute inset-0`,children:h===`audio`?(0,n.jsx)(`audio`,{...d,ref:g,"data-testid":`media-player-audio`,src:e,loop:c,muted:f,style:{width:`100%`,height:`100%`},onLoadStart:()=>P(!0),onCanPlay:()=>{P(!1),I(!1)},onWaiting:()=>P(!0),onPlay:()=>M(!1),onEnded:()=>{c||(w(!1),E(0))},children:(0,n.jsx)(`track`,{kind:`captions`})}):(0,n.jsx)(`video`,{ref:g,"data-testid":`media-player-video`,src:e,loop:c,muted:f,playsInline:!0,style:{width:`100%`,height:`100%`},onLoadStart:()=>P(!0),onCanPlay:()=>{P(!1),I(!1)},onWaiting:()=>P(!0),onPlay:()=>M(!1),onLoadedMetadata:()=>{let e=g.current;e instanceof HTMLVideoElement&&e.videoWidth&&e.videoHeight&&R(e.videoWidth/e.videoHeight)},onEnded:()=>{c||(w(!1),E(0))},children:(0,n.jsx)(`track`,{kind:`captions`})})}),N&&!j&&(0,n.jsx)(`div`,{role:`status`,"aria-label":`Loading media`,className:`absolute inset-0 z-10 flex items-center justify-center`,children:(0,n.jsx)(i.CircleNotchIcon,{className:`size-8 animate-spin text-white/80`,weight:`bold`})}),j&&!l&&(0,n.jsx)(`div`,{className:`absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35`,role:`button`,tabIndex:0,"aria-label":`Play preview`,onClick:e=>{e.stopPropagation(),z()},onKeyDown:e=>{(e.key===`Enter`||e.key===` `)&&(e.preventDefault(),e.stopPropagation(),z())},children:(0,n.jsx)(`span`,{className:`flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm`,children:(0,n.jsx)(i.PlayIcon,{className:`size-9 translate-x-0.5`,weight:`fill`})})}),u&&!l&&(0,n.jsx)(`div`,{className:`absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent`,children:(0,n.jsx)(`div`,{role:`slider`,"aria-label":`Playback position`,"aria-valuenow":K,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0,ref:_,className:`relative flex h-4 w-full cursor-pointer items-center`,onMouseDown:H,onTouchStart:H,onClick:e=>e.stopPropagation(),onKeyDown:U,children:(0,n.jsx)(`div`,{className:`w-full overflow-hidden rounded-full bg-white/30 h-1`,children:(0,n.jsx)(`div`,{className:`h-full rounded-full bg-white`,style:{width:`${K}%`}})})})}),l&&(0,n.jsxs)(`div`,{className:`absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200`,children:[(0,n.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),w(e=>!e)},className:`shrink-0 text-white`,"aria-label":C?`Pause`:`Play`,children:C?(0,n.jsx)(i.PauseIcon,{className:`size-5`,weight:`fill`}):(0,n.jsx)(i.PlayIcon,{className:`size-5 translate-x-px`,weight:`fill`})}),(0,n.jsxs)(`div`,{role:`slider`,"aria-label":`Playback position`,"aria-valuenow":K,"aria-valuemin":0,"aria-valuemax":100,tabIndex:0,ref:_,className:`relative flex h-4 w-full cursor-pointer items-center`,onMouseDown:H,onTouchStart:H,onClick:e=>e.stopPropagation(),onMouseEnter:()=>A(!0),onMouseLeave:()=>A(!1),onKeyDown:U,children:[(0,n.jsx)(`div`,{className:`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${k||D?`h-1.5`:`h-1`}`,children:(0,n.jsx)(`div`,{className:`h-full rounded-full bg-white`,style:{width:`${K}%`}})}),(0,n.jsx)(`div`,{"data-testid":`media-player-scrubber-thumb`,className:`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${k||D?`scale-100 opacity-100`:`scale-0 opacity-0`}`,style:{left:`${K}%`}})]})]})]})},w=e=>e===`dark`?`size-12 text-white/20`:`size-12 text-black/20`,T=e=>e===`dark`?`aspect-video overflow-hidden bg-white/10`:`aspect-video overflow-hidden bg-black/5`,E=({mimeType:e,sourceUrl:r,thumbnailUrl:i,title:a,variant:o,mediaPlayerProps:s,containedImage:c=!1})=>{let u=m(e),[d,f]=(0,t.useState)(!1),p=l(r),h=l(i);return r&&(u===`video`||u===`audio`)?(0,n.jsx)(C,{source:r,mimeType:e,poster:h,controls:!0,...s}):r&&u===`image`?c?(0,n.jsx)(`div`,{className:`relative ${T(o)}`,children:(0,n.jsx)(`img`,{src:p??r,alt:a??``,className:`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${d?`opacity-100`:`opacity-0`}`,draggable:!1,onLoad:()=>f(!0)})}):(0,n.jsx)(`img`,{src:p??r,alt:a??``,className:`block w-full`,draggable:!1}):r&&u===`document`?i?c?(0,n.jsx)(`div`,{className:`relative ${T(o)}`,children:(0,n.jsx)(`img`,{src:h??i,alt:a??``,className:`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${d?`opacity-100`:`opacity-0`}`,draggable:!1,onLoad:()=>f(!0)})}):(0,n.jsx)(`img`,{src:h??i,alt:``,className:`block w-full`,draggable:!1}):(0,n.jsx)(`div`,{className:`flex aspect-video w-full items-center justify-center ${o===`dark`?`bg-white/10`:`bg-black/5`}`,children:b(e,{className:w(o),weight:`regular`})}):i?(0,n.jsx)(`div`,{className:`relative ${T(o)}`,children:(0,n.jsx)(`img`,{src:h??i,alt:a??``,draggable:!1,className:`absolute inset-0 h-full w-full object-cover`})}):(0,n.jsx)(`div`,{className:`flex aspect-video w-full items-center justify-center ${o===`dark`?`bg-white/10`:`bg-black/5`}`,children:b(e,{className:w(o),weight:`regular`})})};Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return m}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return h}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return E}});
|
|
2
|
+
//# sourceMappingURL=AttachmentCard-BbsjzdLJ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AttachmentCard-BbsjzdLJ.cjs","names":[],"sources":["../src/utils/cdnImageUrl.ts","../src/utils/nativeMediaPlayers.ts","../src/components/AttachmentCard/utils/mimeType.ts","../src/components/AttachmentCard/utils/icons.ts","../src/utils/isDevBuild.ts","../src/components/AttachmentCard/MediaPlayer.tsx","../src/components/AttachmentCard/Thumbnail.tsx"],"sourcesContent":["const LINKTREE_CDN_HOSTS = ['linktr.ee']\n\nconst ATTACHMENT_IMAGE_SIZE_PRESET = 'messaging-attachment-v1_0'\n\nfunction hostnameFromUrl(url: string): string | null {\n try {\n return new URL(url).hostname.toLowerCase()\n } catch {\n return null\n }\n}\n\nfunction isLinktreeCdnHost(hostname: string): boolean {\n return LINKTREE_CDN_HOSTS.some(\n (host) => hostname === host || hostname.endsWith(`.${host}`)\n )\n}\n\nexport function optimizeMessagingAttachmentUrl(\n url: string | undefined | null\n): string | undefined {\n const trimmed = url?.trim()\n if (!trimmed) return undefined\n\n const hostname = hostnameFromUrl(trimmed)\n if (!hostname || !isLinktreeCdnHost(hostname)) return trimmed\n\n const parsedUrl = new URL(trimmed)\n const isAlreadyMessagingOptimized =\n parsedUrl.searchParams.get('io') === 'true' &&\n parsedUrl.searchParams.get('size') === ATTACHMENT_IMAGE_SIZE_PRESET\n\n if (isAlreadyMessagingOptimized) {\n return trimmed\n }\n\n parsedUrl.searchParams.set('io', 'true')\n parsedUrl.searchParams.set('size', ATTACHMENT_IMAGE_SIZE_PRESET)\n\n return parsedUrl.toString()\n}\n","/**\n * Attribute marking every native `<audio>` / `<video>` the toolkit\n * renders on a message surface, so opening one player can silence the\n * others.\n *\n * stream-chat-react's `AudioPlayerPool` — what `useActiveAudioPlayer()`\n * reads — only knows the players *it* mounts, i.e. voice recordings.\n * Everything the toolkit draws itself is a plain native element that\n * never registers there: `MessageAttachment.Audio`, a playable\n * `LinkAttachment` card, and `AttachmentCard`'s `MediaPlayer`. Pausing\n * the pool alone therefore left thread audio sounding underneath an\n * opened video viewer on the production `StreamAttachmentMessage` path,\n * which is exactly the surface the mutual exclusion exists for\n * (MES-1353).\n */\nexport const NATIVE_PLAYER_ATTRIBUTE = 'data-mes-native-player'\n\n/**\n * Spread onto a native player element to enrol it. Keyed off the\n * constant so the marker and the query below can't drift apart.\n */\nexport const nativePlayerProps = { [NATIVE_PLAYER_ATTRIBUTE]: '' } as const\n\n/**\n * Pauses every enrolled player except `except`.\n *\n * No `paused` check: pausing an already-paused element is a no-op per\n * spec, and reading `paused` first would only add a branch that jsdom\n * answers differently from a browser.\n */\nexport const pauseNativeMediaPlayers = (\n except?: HTMLMediaElement | null\n): void => {\n if (typeof document === 'undefined') return\n\n document\n .querySelectorAll<HTMLMediaElement>(`[${NATIVE_PLAYER_ATTRIBUTE}]`)\n .forEach((player) => {\n if (player !== except) player.pause()\n })\n}\n","export type AttachmentSourceType = 'image' | 'audio' | 'video' | 'document'\n\nexport type DocumentIconType =\n | 'pdf'\n | 'doc'\n | 'xls'\n | 'csv'\n | 'ppt'\n | 'zip'\n | 'text'\n | 'markdown'\n | 'generic'\n\nconst DOCUMENT_ICON_PATTERNS: Array<[RegExp, DocumentIconType]> = [\n [/pdf/, 'pdf'],\n [/wordprocessingml|msword|\\.doc/, 'doc'],\n [/spreadsheetml|ms-excel|\\.xls/, 'xls'],\n [/csv/, 'csv'],\n [/presentationml|ms-powerpoint|\\.ppt/, 'ppt'],\n [/zip|x-rar|x-7z|x-tar|x-gzip/, 'zip'],\n [/plain|rtf/, 'text'],\n [/markdown/, 'markdown'],\n]\n\nexport function getSourceType(mimeType: string): AttachmentSourceType {\n if (mimeType.startsWith('video/')) return 'video'\n if (mimeType.startsWith('audio/')) return 'audio'\n if (mimeType.startsWith('image/')) return 'image'\n return 'document'\n}\n\nexport function getDocumentIconType(mimeType: string): DocumentIconType {\n const match = DOCUMENT_ICON_PATTERNS.find(([pattern]) =>\n pattern.test(mimeType)\n )\n return match ? match[1] : 'generic'\n}\n","import {\n FileIcon,\n FileCsvIcon,\n FileDocIcon,\n FileMdIcon,\n FilePdfIcon,\n FilePptIcon,\n FileTextIcon,\n FileXlsIcon,\n FileZipIcon,\n ImageIcon,\n SpeakerHighIcon,\n VideoCameraIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getDocumentIconType, getSourceType } from './mimeType'\nimport type { AttachmentSourceType } from './mimeType'\n\nconst MEDIA_TYPE_ICON: Record<AttachmentSourceType, React.ElementType> = {\n video: VideoCameraIcon,\n audio: SpeakerHighIcon,\n image: ImageIcon,\n document: FileIcon,\n}\n\nconst DOCUMENT_ICON_COMPONENT = {\n pdf: FilePdfIcon,\n doc: FileDocIcon,\n xls: FileXlsIcon,\n csv: FileCsvIcon,\n ppt: FilePptIcon,\n zip: FileZipIcon,\n text: FileTextIcon,\n markdown: FileMdIcon,\n generic: FileIcon,\n} as const\n\nfunction getTypeIcon(mimeType: string): React.ElementType {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return MEDIA_TYPE_ICON[sourceType]\n return DOCUMENT_ICON_COMPONENT[getDocumentIconType(mimeType)]\n}\n\nfunction getTypeIconName(mimeType: string): string {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return sourceType\n return getDocumentIconType(mimeType)\n}\n\n/** Use instead of `<TypeIcon />` where TypeIcon = getTypeIcon(mime) to satisfy react-hooks/static-components. */\nexport function renderTypeIcon(\n mimeType: string,\n props: IconProps\n): React.ReactElement {\n // Decorative icons: which one was picked is otherwise only visible in a pixel diff.\n return React.createElement(getTypeIcon(mimeType), {\n 'data-testid': `type-icon-${getTypeIconName(mimeType)}`,\n ...props,\n })\n}\n","/**\n * True in Vite dev builds (`import.meta.env.DEV`). Uses a type assertion so\n * `tsc` does not rely on ambient `ImportMeta` merging (vite/client).\n */\nexport function isDevBuild(): boolean {\n return (\n typeof import.meta !== 'undefined' &&\n (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV === true\n )\n}\n","import { CircleNotchIcon, PauseIcon, PlayIcon } from '@phosphor-icons/react'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { isDevBuild } from '../../utils/isDevBuild'\nimport { nativePlayerProps } from '../../utils/nativeMediaPlayers'\n\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\ntype TouchEventUnion =\n MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent\n\nconst getClientXFromEvent = (e: TouchEventUnion): number => {\n if ('touches' in e) {\n return e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0\n }\n return e.clientX\n}\n\nexport interface MediaPlayerProps {\n source: string\n mimeType: string\n poster?: string\n autoPlay?: boolean\n /** Controlled playing state. When provided, syncs to internal play/pause. */\n playing?: boolean\n loop?: boolean\n controls?: boolean\n showProgress?: boolean\n /** When true, requests muted playback (helps autoplay policies on video). */\n muted?: boolean\n /**\n * When provided, overrides the default click-to-play-toggle behaviour on the\n * player container. The play/pause button (which calls stopPropagation) is\n * unaffected, so inline playback still works.\n */\n onContainerClick?: (e: React.MouseEvent) => void\n}\n\nconst MediaPlayer: React.FC<MediaPlayerProps> = ({\n source,\n mimeType,\n poster,\n autoPlay = false,\n playing: playingProp,\n loop = false,\n controls = true,\n showProgress = false,\n muted = false,\n onContainerClick,\n}) => {\n // --- Derived ---\n const sourceType = getSourceType(mimeType)\n\n // --- Refs ---\n const playerRef = useRef<HTMLMediaElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n const rafRef = useRef<number | null>(null)\n const prevPlayingPropRef = useRef(playingProp)\n\n // --- State: playback ---\n const [playing, setPlaying] = useState(autoPlay)\n const [played, setPlayed] = useState(0)\n const [seeking, setSeeking] = useState(false)\n\n // --- State: UI ---\n const [scrubberHovered, setScrubberHovered] = useState(false)\n /** Set when autoplay/play() was rejected so user can start via gesture (no controls UI). */\n const [manualPlayRequired, setManualPlayRequired] = useState(false)\n\n // --- State: loading ---\n const [buffering, setBuffering] = useState(false)\n /** True until the first canPlay fires for the current source — hides controls/spinner behind poster. */\n const [initialLoad, setInitialLoad] = useState(true)\n const [videoAspect, setVideoAspect] = useState<number | null>(null)\n\n // --- Callbacks ---\n const startPlaybackFromGesture = useCallback(() => {\n setManualPlayRequired(false)\n setPlaying(true)\n }, [])\n\n const getFraction = useCallback((e: TouchEventUnion) => {\n const track = trackRef.current\n if (!track) return 0\n const rect = track.getBoundingClientRect()\n return Math.max(\n 0,\n Math.min(1, (getClientXFromEvent(e) - rect.left) / rect.width)\n )\n }, [])\n\n const seekTo = useCallback((fraction: number) => {\n const el = playerRef.current\n if (el && el.duration) el.currentTime = fraction * el.duration\n }, [])\n\n const handleTrackPointerDown = (\n e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>\n ) => {\n e.stopPropagation()\n setSeeking(true)\n const fraction = getFraction(e)\n setPlayed(fraction)\n seekTo(fraction)\n }\n\n const handleScrubberKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n },\n [seekTo, played]\n )\n\n // --- Effects ---\n\n // Sync controlled playing prop to internal state\n useEffect(() => {\n if (\n playingProp !== undefined &&\n playingProp !== prevPlayingPropRef.current\n ) {\n prevPlayingPropRef.current = playingProp\n setPlaying(playingProp)\n }\n }, [playingProp])\n\n // RAF-driven progress updates\n useEffect(() => {\n if (!playing) {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n return\n }\n const tick = () => {\n const el = playerRef.current\n if (el && el.duration && !seeking) setPlayed(el.currentTime / el.duration)\n rafRef.current = requestAnimationFrame(tick)\n }\n rafRef.current = requestAnimationFrame(tick)\n return () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current)\n }\n }, [playing, seeking])\n\n // ReactPlayer v3 uses native HTML media elements and does not support a\n // declarative `playing` prop — playback must be driven imperatively.\n useEffect(() => {\n const el = playerRef.current\n if (!el) return\n if (playing) {\n void el.play().catch((err) => {\n setPlaying(false)\n setManualPlayRequired(true)\n if (isDevBuild()) {\n console.debug('[MediaPlayer] play() failed', err)\n }\n })\n } else {\n el.pause()\n }\n }, [playing])\n\n // Global seeking listeners\n useEffect(() => {\n if (!seeking) return\n const onMove = (e: MouseEvent | TouchEvent) => setPlayed(getFraction(e))\n const onUp = (e: MouseEvent | TouchEvent) => {\n setSeeking(false)\n seekTo(getFraction(e))\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n window.addEventListener('touchmove', onMove, { passive: true })\n window.addEventListener('touchend', onUp)\n return () => {\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n window.removeEventListener('touchmove', onMove)\n window.removeEventListener('touchend', onUp)\n }\n }, [seeking, getFraction, seekTo])\n\n // --- Derived render values ---\n // Use natural aspect ratio once metadata loads, fall back to 16:9 before then.\n const aspectStyle = videoAspect\n ? { aspectRatio: String(videoAspect) }\n : undefined\n const aspectClass = !videoAspect ? ' aspect-video' : ''\n const scrubberPercent = Math.round(played * 100)\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n data-testid=\"media-player\"\n className={`relative cursor-pointer overflow-hidden bg-black ${aspectClass}`}\n style={aspectStyle}\n onClick={(e) => {\n if (onContainerClick) {\n onContainerClick(e)\n return\n }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n if (onContainerClick) {\n onContainerClick(e as unknown as React.MouseEvent)\n return\n }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n >\n {/* For audio, poster persists as a visual background. For video, hide once loaded. */}\n {poster && (sourceType === 'audio' || initialLoad) && (\n <img\n src={poster}\n alt=\"\"\n data-testid=\"media-player-poster\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {!poster && (sourceType === 'audio' || initialLoad) && (\n <div\n data-testid=\"media-player-placeholder\"\n className=\"absolute inset-0 flex items-center justify-center\"\n >\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <div className=\"absolute inset-0\">\n {sourceType === 'audio' ? (\n <audio\n {...nativePlayerProps}\n ref={playerRef as React.RefObject<HTMLAudioElement>}\n data-testid=\"media-player-audio\"\n src={source}\n loop={loop}\n muted={muted}\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </audio>\n ) : (\n <video\n ref={playerRef as React.RefObject<HTMLVideoElement>}\n data-testid=\"media-player-video\"\n src={source}\n loop={loop}\n muted={muted}\n playsInline\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onLoadedMetadata={() => {\n const el = playerRef.current\n if (\n el instanceof HTMLVideoElement &&\n el.videoWidth &&\n el.videoHeight\n ) {\n setVideoAspect(el.videoWidth / el.videoHeight)\n }\n }}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </video>\n )}\n </div>\n\n {buffering && !manualPlayRequired && (\n <div\n role=\"status\"\n aria-label=\"Loading media\"\n className=\"absolute inset-0 z-10 flex items-center justify-center\"\n >\n <CircleNotchIcon\n className=\"size-8 animate-spin text-white/80\"\n weight=\"bold\"\n />\n </div>\n )}\n\n {manualPlayRequired && !controls && (\n <div\n className=\"absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35\"\n role=\"button\"\n tabIndex={0}\n aria-label=\"Play preview\"\n onClick={(e) => {\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n >\n <span className=\"flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm\">\n <PlayIcon className=\"size-9 translate-x-0.5\" weight=\"fill\" />\n </span>\n </div>\n )}\n\n {showProgress && !controls && (\n <div className=\"absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent\">\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={handleScrubberKeyDown}\n >\n <div className=\"w-full overflow-hidden rounded-full bg-white/30 h-1\">\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n </div>\n )}\n\n {controls && (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n setPlaying((p) => !p)\n }}\n className=\"shrink-0 text-white\"\n aria-label={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <PauseIcon className=\"size-5\" weight=\"fill\" />\n ) : (\n <PlayIcon className=\"size-5 translate-x-px\" weight=\"fill\" />\n )}\n </button>\n\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={() => setScrubberHovered(true)}\n onMouseLeave={() => setScrubberHovered(false)}\n onKeyDown={handleScrubberKeyDown}\n >\n <div\n className={`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${scrubberHovered || seeking ? 'h-1.5' : 'h-1'}`}\n >\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n <div\n data-testid=\"media-player-scrubber-thumb\"\n className={`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${scrubberHovered || seeking ? 'scale-100 opacity-100' : 'scale-0 opacity-0'}`}\n style={{ left: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default MediaPlayer\n","import React, { useState } from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\n\nimport MediaPlayer, { type MediaPlayerProps } from './MediaPlayer'\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\nexport type AttachmentThumbnailVariant = 'light' | 'dark'\n\nexport interface AttachmentThumbnailProps {\n mimeType: string\n sourceUrl?: string\n thumbnailUrl?: string\n title?: string\n variant: AttachmentThumbnailVariant\n /** Extra props passed to MediaPlayer when source is video or audio. */\n mediaPlayerProps?: Partial<\n Pick<\n MediaPlayerProps,\n 'autoPlay' | 'loop' | 'muted' | 'controls' | 'onContainerClick'\n >\n >\n /**\n * When true (Visitor unlocked image/document), use aspect-video + object-contain fade-in.\n */\n containedImage?: boolean\n}\n\nconst placeholderIconClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark' ? 'size-12 text-white/20' : 'size-12 text-black/20'\n\nconst posterShellClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark'\n ? 'aspect-video overflow-hidden bg-white/10'\n : 'aspect-video overflow-hidden bg-black/5'\n\n/**\n * Renders the media preview area for attachment cards (LockedAttachment, MediaMessage).\n * Overlays (dim, lock, eye toggle) are composed by the parent.\n */\nconst AttachmentThumbnail: React.FC<AttachmentThumbnailProps> = ({\n mimeType,\n sourceUrl,\n thumbnailUrl,\n title,\n variant,\n mediaPlayerProps,\n containedImage = false,\n}) => {\n const sourceType = getSourceType(mimeType)\n const [sourceReady, setSourceReady] = useState(false)\n const optimizedSourceUrl = optimizeMessagingAttachmentUrl(sourceUrl)\n const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl)\n\n if (sourceUrl && (sourceType === 'video' || sourceType === 'audio')) {\n return (\n <MediaPlayer\n source={sourceUrl}\n mimeType={mimeType}\n poster={optimizedThumbnailUrl}\n controls\n {...mediaPlayerProps}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'image') {\n if (containedImage) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'document') {\n if (thumbnailUrl) {\n if (containedImage) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt=\"\"\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n }\n\n // Poster-only or empty (no sourceUrl)\n if (thumbnailUrl) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n draggable={false}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n </div>\n )\n }\n\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n}\n\nexport default AttachmentThumbnail\n"],"mappings":"kMAAA,IAAM,EAAqB,CAAC,WAAW,EAEjC,EAA+B,4BAErC,SAAS,EAAgB,EAA4B,CACnD,GAAI,CACF,OAAO,IAAI,IAAI,CAAG,CAAC,CAAC,SAAS,YAAY,CAC3C,MAAQ,CACN,OAAO,IACT,CACF,CAEA,SAAS,EAAkB,EAA2B,CACpD,OAAO,EAAmB,KACvB,GAAS,IAAa,GAAQ,EAAS,SAAS,IAAI,GAAM,CAC7D,CACF,CAEA,SAAgB,EACd,EACoB,CACpB,IAAM,EAAU,GAAK,KAAK,EAC1B,GAAI,CAAC,EAAS,OAEd,IAAM,EAAW,EAAgB,CAAO,EACxC,GAAI,CAAC,GAAY,CAAC,EAAkB,CAAQ,EAAG,OAAO,EAEtD,IAAM,EAAY,IAAI,IAAI,CAAO,EAYjC,OAVE,EAAU,aAAa,IAAI,IAAI,IAAM,QACrC,EAAU,aAAa,IAAI,MAAM,IAAM,EAGhC,GAGT,EAAU,aAAa,IAAI,KAAM,MAAM,EACvC,EAAU,aAAa,IAAI,OAAQ,CAA4B,EAExD,EAAU,SAAS,EAC5B,CCzBA,IAAa,EAA0B,yBAM1B,EAAoB,EAAG,GAA0B,EAAG,EASpD,EACX,GACS,CACL,OAAO,SAAa,KAExB,SACG,iBAAmC,IAAI,EAAwB,EAAE,CAAC,CAClE,QAAS,GAAW,CACf,IAAW,GAAQ,EAAO,MAAM,CACtC,CAAC,CACL,EC3BM,EAA4D,CAChE,CAAC,MAAO,KAAK,EACb,CAAC,gCAAiC,KAAK,EACvC,CAAC,+BAAgC,KAAK,EACtC,CAAC,MAAO,KAAK,EACb,CAAC,qCAAsC,KAAK,EAC5C,CAAC,8BAA+B,KAAK,EACrC,CAAC,YAAa,MAAM,EACpB,CAAC,WAAY,UAAU,CACzB,EAEA,SAAgB,EAAc,EAAwC,CAIpE,OAHI,EAAS,WAAW,QAAQ,EAAU,QACtC,EAAS,WAAW,QAAQ,EAAU,QACtC,EAAS,WAAW,QAAQ,EAAU,QACnC,UACT,CAEA,SAAgB,EAAoB,EAAoC,CACtE,IAAM,EAAQ,EAAuB,MAAM,CAAC,KAC1C,EAAQ,KAAK,CAAQ,CACvB,EACA,OAAO,EAAQ,EAAM,GAAK,SAC5B,CChBA,IAAM,EAAmE,CACvE,MAAO,EAAA,gBACP,MAAO,EAAA,gBACP,MAAO,EAAA,UACP,SAAU,EAAA,QACZ,EAEM,EAA0B,CAC9B,IAAK,EAAA,YACL,IAAK,EAAA,YACL,IAAK,EAAA,YACL,IAAK,EAAA,YACL,IAAK,EAAA,YACL,IAAK,EAAA,YACL,KAAM,EAAA,aACN,SAAU,EAAA,WACV,QAAS,EAAA,QACX,EAEA,SAAS,EAAY,EAAqC,CACxD,IAAM,EAAa,EAAc,CAAQ,EAEzC,OADI,IAAe,WACZ,EAAwB,EAAoB,CAAQ,GADrB,EAAgB,EAExD,CAEA,SAAS,EAAgB,EAA0B,CACjD,IAAM,EAAa,EAAc,CAAQ,EAEzC,OADI,IAAe,WACZ,EAAoB,CAAQ,EADG,CAExC,CAGA,SAAgB,EACd,EACA,EACoB,CAEpB,OAAO,EAAA,QAAM,cAAc,EAAY,CAAQ,EAAG,CAChD,cAAe,aAAa,EAAgB,CAAQ,IACpD,GAAG,CACL,CAAC,CACH,CCzDA,SAAgB,GAAsB,CACpC,MAEG,EAEL,CCGA,IAAM,EAAuB,GACvB,YAAa,EACR,EAAE,QAAQ,EAAE,EAAE,SAAW,EAAE,eAAe,EAAE,EAAE,SAAW,EAE3D,EAAE,QAuBL,GAA2C,CAC/C,SACA,WACA,SACA,WAAW,GACX,QAAS,EACT,OAAO,GACP,WAAW,GACX,eAAe,GACf,QAAQ,GACR,sBACI,CAEJ,IAAM,EAAa,EAAc,CAAQ,EAGnC,GAAA,EAAY,EAAA,OAAA,CAAyB,IAAI,EACzC,GAAA,EAAW,EAAA,OAAA,CAAuB,IAAI,EACtC,GAAA,EAAS,EAAA,OAAA,CAAsB,IAAI,EACnC,GAAA,EAAqB,EAAA,OAAA,CAAO,CAAW,EAGvC,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAS,CAAQ,EACzC,CAAC,EAAQ,IAAA,EAAa,EAAA,SAAA,CAAS,CAAC,EAChC,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAS,EAAK,EAGtC,CAAC,EAAiB,IAAA,EAAsB,EAAA,SAAA,CAAS,EAAK,EAEtD,CAAC,EAAoB,IAAA,EAAyB,EAAA,SAAA,CAAS,EAAK,EAG5D,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAS,EAAK,EAE1C,CAAC,EAAa,IAAA,EAAkB,EAAA,SAAA,CAAS,EAAI,EAC7C,CAAC,EAAa,IAAA,EAAkB,EAAA,SAAA,CAAwB,IAAI,EAG5D,GAAA,EAA2B,EAAA,YAAA,KAAkB,CACjD,EAAsB,EAAK,EAC3B,EAAW,EAAI,CACjB,EAAG,CAAC,CAAC,EAEC,GAAA,EAAc,EAAA,YAAA,CAAa,GAAuB,CACtD,IAAM,EAAQ,EAAS,QACvB,GAAI,CAAC,EAAO,MAAO,GACnB,IAAM,EAAO,EAAM,sBAAsB,EACzC,OAAO,KAAK,IACV,EACA,KAAK,IAAI,GAAI,EAAoB,CAAC,EAAI,EAAK,MAAQ,EAAK,KAAK,CAC/D,CACF,EAAG,CAAC,CAAC,EAEC,GAAA,EAAS,EAAA,YAAA,CAAa,GAAqB,CAC/C,IAAM,EAAK,EAAU,QACjB,GAAM,EAAG,WAAU,EAAG,YAAc,EAAW,EAAG,SACxD,EAAG,CAAC,CAAC,EAEC,EACJ,GACG,CACH,EAAE,gBAAgB,EAClB,EAAW,EAAI,EACf,IAAM,EAAW,EAAY,CAAC,EAC9B,EAAU,CAAQ,EAClB,EAAO,CAAQ,CACjB,EAEM,GAAA,EAAwB,EAAA,YAAA,CAC3B,GAA2C,CACtC,EAAE,MAAQ,cAAc,EAAO,KAAK,IAAI,EAAG,EAAS,GAAI,CAAC,EACzD,EAAE,MAAQ,aAAa,EAAO,KAAK,IAAI,EAAG,EAAS,GAAI,CAAC,CAC9D,EACA,CAAC,EAAQ,CAAM,CACjB,GAKA,EAAA,EAAA,UAAA,KAAgB,CAEZ,IAAgB,IAAA,IAChB,IAAgB,EAAmB,UAEnC,EAAmB,QAAU,EAC7B,EAAW,CAAW,EAE1B,EAAG,CAAC,CAAW,CAAC,GAGhB,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAS,CACR,EAAO,UAAY,OACrB,qBAAqB,EAAO,OAAO,EACnC,EAAO,QAAU,MAEnB,MACF,CACA,IAAM,MAAa,CACjB,IAAM,EAAK,EAAU,QACjB,GAAM,EAAG,UAAY,CAAC,GAAS,EAAU,EAAG,YAAc,EAAG,QAAQ,EACzE,EAAO,QAAU,sBAAsB,CAAI,CAC7C,EAEA,MADA,GAAO,QAAU,sBAAsB,CAAI,MAC9B,CACP,EAAO,UAAY,MAAM,qBAAqB,EAAO,OAAO,CAClE,CACF,EAAG,CAAC,EAAS,CAAO,CAAC,GAIrB,EAAA,EAAA,UAAA,KAAgB,CACd,IAAM,EAAK,EAAU,QAChB,IACD,EACF,EAAQ,KAAK,CAAC,CAAC,MAAO,GAAQ,CAC5B,EAAW,EAAK,EAChB,EAAsB,EAAI,EACtB,EAAW,GACb,QAAQ,MAAM,8BAA+B,CAAG,CAEpD,CAAC,EAED,EAAG,MAAM,EAEb,EAAG,CAAC,CAAO,CAAC,GAGZ,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAS,OACd,IAAM,EAAU,GAA+B,EAAU,EAAY,CAAC,CAAC,EACjE,EAAQ,GAA+B,CAC3C,EAAW,EAAK,EAChB,EAAO,EAAY,CAAC,CAAC,CACvB,EAKA,OAJA,OAAO,iBAAiB,YAAa,CAAM,EAC3C,OAAO,iBAAiB,UAAW,CAAI,EACvC,OAAO,iBAAiB,YAAa,EAAQ,CAAE,QAAS,EAAK,CAAC,EAC9D,OAAO,iBAAiB,WAAY,CAAI,MAC3B,CACX,OAAO,oBAAoB,YAAa,CAAM,EAC9C,OAAO,oBAAoB,UAAW,CAAI,EAC1C,OAAO,oBAAoB,YAAa,CAAM,EAC9C,OAAO,oBAAoB,WAAY,CAAI,CAC7C,CACF,EAAG,CAAC,EAAS,EAAa,CAAM,CAAC,EAIjC,IAAM,EAAc,EAChB,CAAE,YAAa,OAAO,CAAW,CAAE,EACnC,IAAA,GACE,EAAe,EAAgC,GAAlB,gBAC7B,EAAkB,KAAK,MAAM,EAAS,GAAG,EAE/C,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,KAAK,SACL,SAAU,EACV,cAAY,eACZ,UAAW,oDAAoD,IAC/D,MAAO,EACP,QAAU,GAAM,CACd,GAAI,EAAkB,CACpB,EAAiB,CAAC,EAClB,MACF,CACI,GACA,GAAU,EAAY,GAAM,CAAC,CAAC,CACpC,EACA,UAAY,GAAM,CACZ,KAAE,MAAQ,SAAW,EAAE,MAAQ,IAEnC,IADA,EAAE,eAAe,EACb,EAAkB,CACpB,EAAiB,CAAgC,EACjD,MACF,CACI,GACA,GAAU,EAAY,GAAM,CAAC,CAAC,CAFlC,CAGF,EAvBF,SAAA,CA0BG,IAAW,IAAe,SAAW,KACpC,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,EACL,IAAI,GACJ,cAAY,sBACZ,UAAU,6CACX,CAAA,EAEF,CAAC,IAAW,IAAe,SAAW,KACrC,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,cAAY,2BACZ,UAAU,oDAET,SAAA,EAAe,EAAU,CACxB,UAAW,wBACX,OAAQ,SACV,CAAC,CACE,CAAA,GAEP,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,mBACZ,SAAA,IAAe,SACd,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,GAAI,EACJ,IAAK,EACL,cAAY,qBACZ,IAAK,EACC,OACC,QACP,MAAO,CAAE,MAAO,OAAQ,OAAQ,MAAO,EACvC,gBAAmB,EAAa,EAAI,EACpC,cAAiB,CACf,EAAa,EAAK,EAClB,EAAe,EAAK,CACtB,EACA,cAAiB,EAAa,EAAI,EAClC,WAAc,EAAsB,EAAK,EACzC,YAAe,CACR,IACH,EAAW,EAAK,EAChB,EAAU,CAAC,EAEf,EAEA,UAAA,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,KAAK,UAAY,CAAA,CACnB,CAAA,GAEP,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,IAAK,EACL,cAAY,qBACZ,IAAK,EACC,OACC,QACP,YAAA,GACA,MAAO,CAAE,MAAO,OAAQ,OAAQ,MAAO,EACvC,gBAAmB,EAAa,EAAI,EACpC,cAAiB,CACf,EAAa,EAAK,EAClB,EAAe,EAAK,CACtB,EACA,cAAiB,EAAa,EAAI,EAClC,WAAc,EAAsB,EAAK,EACzC,qBAAwB,CACtB,IAAM,EAAK,EAAU,QAEnB,aAAc,kBACd,EAAG,YACH,EAAG,aAEH,EAAe,EAAG,WAAa,EAAG,WAAW,CAEjD,EACA,YAAe,CACR,IACH,EAAW,EAAK,EAChB,EAAU,CAAC,EAEf,EAEA,UAAA,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,KAAK,UAAY,CAAA,CACnB,CAAA,CAEN,CAAA,EAEJ,GAAa,CAAC,IACb,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,KAAK,SACL,aAAW,gBACX,UAAU,yDAEV,UAAA,EAAA,EAAA,IAAA,CAAC,EAAA,gBAAD,CACE,UAAU,oCACV,OAAO,MACR,CAAA,CACE,CAAA,EAGN,GAAsB,CAAC,IACtB,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAU,oFACV,KAAK,SACL,SAAU,EACV,aAAW,eACX,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAyB,CAC3B,EACA,UAAY,GAAM,EACZ,EAAE,MAAQ,SAAW,EAAE,MAAQ,OACnC,EAAE,eAAe,EACjB,EAAE,gBAAgB,EAClB,EAAyB,EAC3B,EAEA,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,gGACd,UAAA,EAAA,EAAA,IAAA,CAAC,EAAA,SAAD,CAAU,UAAU,yBAAyB,OAAO,MAAQ,CAAA,CACxD,CAAA,CACH,CAAA,EAGN,GAAgB,CAAC,IAChB,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,6FACb,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,KAAK,SACL,aAAW,oBACX,gBAAe,EACf,gBAAe,EACf,gBAAe,IACf,SAAU,EACV,IAAK,EACL,UAAU,uDACV,YAAa,EACb,aAAc,EACd,QAAU,GAAM,EAAE,gBAAgB,EAClC,UAAW,EAEX,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,sDACb,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAU,+BACV,MAAO,CAAE,MAAO,GAAG,EAAgB,EAAG,CACvC,CAAA,CACE,CAAA,CACF,CAAA,CACF,CAAA,EAGN,IACC,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,iJAAf,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,QAAU,GAAM,CACd,EAAE,gBAAgB,EAClB,EAAY,GAAM,CAAC,CAAC,CACtB,EACA,UAAU,sBACV,aAAY,EAAU,QAAU,OAE/B,SAAA,GACC,EAAA,EAAA,IAAA,CAAC,EAAA,UAAD,CAAW,UAAU,SAAS,OAAO,MAAQ,CAAA,GAE7C,EAAA,EAAA,IAAA,CAAC,EAAA,SAAD,CAAU,UAAU,wBAAwB,OAAO,MAAQ,CAAA,CAEvD,CAAA,GAER,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,KAAK,SACL,aAAW,oBACX,gBAAe,EACf,gBAAe,EACf,gBAAe,IACf,SAAU,EACV,IAAK,EACL,UAAU,uDACV,YAAa,EACb,aAAc,EACd,QAAU,GAAM,EAAE,gBAAgB,EAClC,iBAAoB,EAAmB,EAAI,EAC3C,iBAAoB,EAAmB,EAAK,EAC5C,UAAW,EAdb,SAAA,EAgBE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAW,+EAA+E,GAAmB,EAAU,QAAU,QAEjI,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAU,+BACV,MAAO,CAAE,MAAO,GAAG,EAAgB,EAAG,CACvC,CAAA,CACE,CAAA,GACL,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,cAAY,8BACZ,UAAW,6GAA6G,GAAmB,EAAU,wBAA0B,sBAC/K,MAAO,CAAE,KAAM,GAAG,EAAgB,EAAG,CACtC,CAAA,CACE,CACF,CAAA,CAAA,GAEJ,GAET,ECrYM,EAAwB,GAC5B,IAAY,OAAS,wBAA0B,wBAE3C,EAAoB,GACxB,IAAY,OACR,2CACA,0CAMA,GAA2D,CAC/D,WACA,YACA,eACA,QACA,UACA,mBACA,iBAAiB,MACb,CACJ,IAAM,EAAa,EAAc,CAAQ,EACnC,CAAC,EAAa,IAAA,EAAkB,EAAA,SAAA,CAAS,EAAK,EAC9C,EAAqB,EAA+B,CAAS,EAC7D,EAAwB,EAA+B,CAAY,EAwFzE,OAtFI,IAAc,IAAe,SAAW,IAAe,UAEvD,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,OAAQ,EACE,WACV,OAAQ,EACR,SAAA,GACA,GAAI,CACL,CAAA,EAID,GAAa,IAAe,QAC1B,GAEA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,YAAY,EAAiB,CAAO,IAClD,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,GAAsB,EAC3B,IAAK,GAAS,GACd,UAAW,iFAAiF,EAAc,cAAgB,cAC1H,UAAW,GACX,WAAc,EAAe,EAAI,CAClC,CAAA,CACE,CAAA,GAIP,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,GAAsB,EAC3B,IAAK,GAAS,GACd,UAAU,eACV,UAAW,EACZ,CAAA,EAID,GAAa,IAAe,WAC1B,EACE,GAEA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,YAAY,EAAiB,CAAO,IAClD,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,GAAyB,EAC9B,IAAK,GAAS,GACd,UAAW,iFAAiF,EAAc,cAAgB,cAC1H,UAAW,GACX,WAAc,EAAe,EAAI,CAClC,CAAA,CACE,CAAA,GAIP,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,GAAyB,EAC9B,IAAI,GACJ,UAAU,eACV,UAAW,EACZ,CAAA,GAIH,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAW,wDAAwD,IAAY,OAAS,cAAgB,eAEvG,SAAA,EAAe,EAAU,CACxB,UAAW,EAAqB,CAAO,EACvC,OAAQ,SACV,CAAC,CACE,CAAA,EAKL,GAEA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,YAAY,EAAiB,CAAO,IAClD,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,GAAyB,EAC9B,IAAK,GAAS,GACd,UAAW,GACX,UAAU,6CACX,CAAA,CACE,CAAA,GAKP,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,UAAW,wDAAwD,IAAY,OAAS,cAAgB,eAEvG,SAAA,EAAe,EAAU,CACxB,UAAW,EAAqB,CAAO,EACvC,OAAQ,SACV,CAAC,CACE,CAAA,CAET"}
|
|
@@ -67,24 +67,31 @@ function F(e) {
|
|
|
67
67
|
let t = j(e);
|
|
68
68
|
return t === "document" ? P[M(e)] : N[t];
|
|
69
69
|
}
|
|
70
|
-
function I(
|
|
71
|
-
|
|
70
|
+
function I(e) {
|
|
71
|
+
let t = j(e);
|
|
72
|
+
return t === "document" ? M(e) : t;
|
|
73
|
+
}
|
|
74
|
+
function L(t, n) {
|
|
75
|
+
return e.createElement(F(t), {
|
|
76
|
+
"data-testid": `type-icon-${I(t)}`,
|
|
77
|
+
...n
|
|
78
|
+
});
|
|
72
79
|
}
|
|
73
80
|
//#endregion
|
|
74
81
|
//#region src/utils/isDevBuild.ts
|
|
75
|
-
function
|
|
82
|
+
function R() {
|
|
76
83
|
return !1;
|
|
77
84
|
}
|
|
78
85
|
//#endregion
|
|
79
86
|
//#region src/components/AttachmentCard/MediaPlayer.tsx
|
|
80
|
-
var
|
|
81
|
-
let _ = j(c), b = r(null), x = r(null), S = r(null), C = r(d), [w, T] = i(u), [E, D] = i(0), [k, A] = i(!1), [M, N] = i(!1), [P, F] = i(!1), [
|
|
87
|
+
var z = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0 : e.clientX, B = ({ source: e, mimeType: c, poster: l, autoPlay: u = !1, playing: d, loop: f = !1, controls: p = !0, showProgress: m = !1, muted: h = !1, onContainerClick: g }) => {
|
|
88
|
+
let _ = j(c), b = r(null), x = r(null), S = r(null), C = r(d), [w, T] = i(u), [E, D] = i(0), [k, A] = i(!1), [M, N] = i(!1), [P, F] = i(!1), [I, B] = i(!1), [V, H] = i(!0), [U, W] = i(null), G = t(() => {
|
|
82
89
|
F(!1), T(!0);
|
|
83
90
|
}, []), K = t((e) => {
|
|
84
91
|
let t = x.current;
|
|
85
92
|
if (!t) return 0;
|
|
86
93
|
let n = t.getBoundingClientRect();
|
|
87
|
-
return Math.max(0, Math.min(1, (
|
|
94
|
+
return Math.max(0, Math.min(1, (z(e) - n.left) / n.width));
|
|
88
95
|
}, []), q = t((e) => {
|
|
89
96
|
let t = b.current;
|
|
90
97
|
t && t.duration && (t.currentTime = e * t.duration);
|
|
@@ -112,7 +119,7 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
112
119
|
}, [w, k]), n(() => {
|
|
113
120
|
let e = b.current;
|
|
114
121
|
e && (w ? e.play().catch((e) => {
|
|
115
|
-
T(!1), F(!0),
|
|
122
|
+
T(!1), F(!0), R() && console.debug("[MediaPlayer] play() failed", e);
|
|
116
123
|
}) : e.pause());
|
|
117
124
|
}, [w]), n(() => {
|
|
118
125
|
if (!k) return;
|
|
@@ -131,6 +138,7 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
131
138
|
return /* @__PURE__ */ o("div", {
|
|
132
139
|
role: "button",
|
|
133
140
|
tabIndex: 0,
|
|
141
|
+
"data-testid": "media-player",
|
|
134
142
|
className: `relative cursor-pointer overflow-hidden bg-black ${Z}`,
|
|
135
143
|
style: X,
|
|
136
144
|
onClick: (e) => {
|
|
@@ -153,11 +161,13 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
153
161
|
l && (_ === "audio" || V) && /* @__PURE__ */ a("img", {
|
|
154
162
|
src: l,
|
|
155
163
|
alt: "",
|
|
164
|
+
"data-testid": "media-player-poster",
|
|
156
165
|
className: "absolute inset-0 h-full w-full object-cover"
|
|
157
166
|
}),
|
|
158
167
|
!l && (_ === "audio" || V) && /* @__PURE__ */ a("div", {
|
|
168
|
+
"data-testid": "media-player-placeholder",
|
|
159
169
|
className: "absolute inset-0 flex items-center justify-center",
|
|
160
|
-
children:
|
|
170
|
+
children: L(c, {
|
|
161
171
|
className: "size-12 text-black/20",
|
|
162
172
|
weight: "regular"
|
|
163
173
|
})
|
|
@@ -167,6 +177,7 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
167
177
|
children: _ === "audio" ? /* @__PURE__ */ a("audio", {
|
|
168
178
|
...O,
|
|
169
179
|
ref: b,
|
|
180
|
+
"data-testid": "media-player-audio",
|
|
170
181
|
src: e,
|
|
171
182
|
loop: f,
|
|
172
183
|
muted: h,
|
|
@@ -186,6 +197,7 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
186
197
|
children: /* @__PURE__ */ a("track", { kind: "captions" })
|
|
187
198
|
}) : /* @__PURE__ */ a("video", {
|
|
188
199
|
ref: b,
|
|
200
|
+
"data-testid": "media-player-video",
|
|
189
201
|
src: e,
|
|
190
202
|
loop: f,
|
|
191
203
|
muted: h,
|
|
@@ -210,7 +222,9 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
210
222
|
children: /* @__PURE__ */ a("track", { kind: "captions" })
|
|
211
223
|
})
|
|
212
224
|
}),
|
|
213
|
-
|
|
225
|
+
I && !P && /* @__PURE__ */ a("div", {
|
|
226
|
+
role: "status",
|
|
227
|
+
"aria-label": "Loading media",
|
|
214
228
|
className: "absolute inset-0 z-10 flex items-center justify-center",
|
|
215
229
|
children: /* @__PURE__ */ a(s, {
|
|
216
230
|
className: "size-8 animate-spin text-white/80",
|
|
@@ -298,6 +312,7 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
298
312
|
style: { width: `${Q}%` }
|
|
299
313
|
})
|
|
300
314
|
}), /* @__PURE__ */ a("div", {
|
|
315
|
+
"data-testid": "media-player-scrubber-thumb",
|
|
301
316
|
className: `absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${M || k ? "scale-100 opacity-100" : "scale-0 opacity-0"}`,
|
|
302
317
|
style: { left: `${Q}%` }
|
|
303
318
|
})]
|
|
@@ -305,16 +320,16 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
305
320
|
})
|
|
306
321
|
]
|
|
307
322
|
});
|
|
308
|
-
},
|
|
323
|
+
}, V = (e) => e === "dark" ? "size-12 text-white/20" : "size-12 text-black/20", H = (e) => e === "dark" ? "aspect-video overflow-hidden bg-white/10" : "aspect-video overflow-hidden bg-black/5", U = ({ mimeType: e, sourceUrl: t, thumbnailUrl: n, title: r, variant: o, mediaPlayerProps: s, containedImage: c = !1 }) => {
|
|
309
324
|
let l = j(e), [u, d] = i(!1), f = E(t), p = E(n);
|
|
310
|
-
return t && (l === "video" || l === "audio") ? /* @__PURE__ */ a(
|
|
325
|
+
return t && (l === "video" || l === "audio") ? /* @__PURE__ */ a(B, {
|
|
311
326
|
source: t,
|
|
312
327
|
mimeType: e,
|
|
313
328
|
poster: p,
|
|
314
329
|
controls: !0,
|
|
315
330
|
...s
|
|
316
331
|
}) : t && l === "image" ? c ? /* @__PURE__ */ a("div", {
|
|
317
|
-
className: `relative ${
|
|
332
|
+
className: `relative ${H(o)}`,
|
|
318
333
|
children: /* @__PURE__ */ a("img", {
|
|
319
334
|
src: f ?? t,
|
|
320
335
|
alt: r ?? "",
|
|
@@ -328,7 +343,7 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
328
343
|
className: "block w-full",
|
|
329
344
|
draggable: !1
|
|
330
345
|
}) : t && l === "document" ? n ? c ? /* @__PURE__ */ a("div", {
|
|
331
|
-
className: `relative ${
|
|
346
|
+
className: `relative ${H(o)}`,
|
|
332
347
|
children: /* @__PURE__ */ a("img", {
|
|
333
348
|
src: p ?? n,
|
|
334
349
|
alt: r ?? "",
|
|
@@ -343,12 +358,12 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
343
358
|
draggable: !1
|
|
344
359
|
}) : /* @__PURE__ */ a("div", {
|
|
345
360
|
className: `flex aspect-video w-full items-center justify-center ${o === "dark" ? "bg-white/10" : "bg-black/5"}`,
|
|
346
|
-
children:
|
|
347
|
-
className:
|
|
361
|
+
children: L(e, {
|
|
362
|
+
className: V(o),
|
|
348
363
|
weight: "regular"
|
|
349
364
|
})
|
|
350
365
|
}) : n ? /* @__PURE__ */ a("div", {
|
|
351
|
-
className: `relative ${
|
|
366
|
+
className: `relative ${H(o)}`,
|
|
352
367
|
children: /* @__PURE__ */ a("img", {
|
|
353
368
|
src: p ?? n,
|
|
354
369
|
alt: r ?? "",
|
|
@@ -357,13 +372,13 @@ var R = (e) => "touches" in e ? e.touches[0]?.clientX ?? e.changedTouches[0]?.cl
|
|
|
357
372
|
})
|
|
358
373
|
}) : /* @__PURE__ */ a("div", {
|
|
359
374
|
className: `flex aspect-video w-full items-center justify-center ${o === "dark" ? "bg-white/10" : "bg-black/5"}`,
|
|
360
|
-
children:
|
|
361
|
-
className:
|
|
375
|
+
children: L(e, {
|
|
376
|
+
className: V(o),
|
|
362
377
|
weight: "regular"
|
|
363
378
|
})
|
|
364
379
|
});
|
|
365
380
|
};
|
|
366
381
|
//#endregion
|
|
367
|
-
export { O as a, j as i,
|
|
382
|
+
export { O as a, j as i, L as n, k as o, M as r, E as s, U as t };
|
|
368
383
|
|
|
369
|
-
//# sourceMappingURL=AttachmentCard-
|
|
384
|
+
//# sourceMappingURL=AttachmentCard-DSekwIOA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AttachmentCard-DSekwIOA.js","names":[],"sources":["../src/utils/cdnImageUrl.ts","../src/utils/nativeMediaPlayers.ts","../src/components/AttachmentCard/utils/mimeType.ts","../src/components/AttachmentCard/utils/icons.ts","../src/utils/isDevBuild.ts","../src/components/AttachmentCard/MediaPlayer.tsx","../src/components/AttachmentCard/Thumbnail.tsx"],"sourcesContent":["const LINKTREE_CDN_HOSTS = ['linktr.ee']\n\nconst ATTACHMENT_IMAGE_SIZE_PRESET = 'messaging-attachment-v1_0'\n\nfunction hostnameFromUrl(url: string): string | null {\n try {\n return new URL(url).hostname.toLowerCase()\n } catch {\n return null\n }\n}\n\nfunction isLinktreeCdnHost(hostname: string): boolean {\n return LINKTREE_CDN_HOSTS.some(\n (host) => hostname === host || hostname.endsWith(`.${host}`)\n )\n}\n\nexport function optimizeMessagingAttachmentUrl(\n url: string | undefined | null\n): string | undefined {\n const trimmed = url?.trim()\n if (!trimmed) return undefined\n\n const hostname = hostnameFromUrl(trimmed)\n if (!hostname || !isLinktreeCdnHost(hostname)) return trimmed\n\n const parsedUrl = new URL(trimmed)\n const isAlreadyMessagingOptimized =\n parsedUrl.searchParams.get('io') === 'true' &&\n parsedUrl.searchParams.get('size') === ATTACHMENT_IMAGE_SIZE_PRESET\n\n if (isAlreadyMessagingOptimized) {\n return trimmed\n }\n\n parsedUrl.searchParams.set('io', 'true')\n parsedUrl.searchParams.set('size', ATTACHMENT_IMAGE_SIZE_PRESET)\n\n return parsedUrl.toString()\n}\n","/**\n * Attribute marking every native `<audio>` / `<video>` the toolkit\n * renders on a message surface, so opening one player can silence the\n * others.\n *\n * stream-chat-react's `AudioPlayerPool` — what `useActiveAudioPlayer()`\n * reads — only knows the players *it* mounts, i.e. voice recordings.\n * Everything the toolkit draws itself is a plain native element that\n * never registers there: `MessageAttachment.Audio`, a playable\n * `LinkAttachment` card, and `AttachmentCard`'s `MediaPlayer`. Pausing\n * the pool alone therefore left thread audio sounding underneath an\n * opened video viewer on the production `StreamAttachmentMessage` path,\n * which is exactly the surface the mutual exclusion exists for\n * (MES-1353).\n */\nexport const NATIVE_PLAYER_ATTRIBUTE = 'data-mes-native-player'\n\n/**\n * Spread onto a native player element to enrol it. Keyed off the\n * constant so the marker and the query below can't drift apart.\n */\nexport const nativePlayerProps = { [NATIVE_PLAYER_ATTRIBUTE]: '' } as const\n\n/**\n * Pauses every enrolled player except `except`.\n *\n * No `paused` check: pausing an already-paused element is a no-op per\n * spec, and reading `paused` first would only add a branch that jsdom\n * answers differently from a browser.\n */\nexport const pauseNativeMediaPlayers = (\n except?: HTMLMediaElement | null\n): void => {\n if (typeof document === 'undefined') return\n\n document\n .querySelectorAll<HTMLMediaElement>(`[${NATIVE_PLAYER_ATTRIBUTE}]`)\n .forEach((player) => {\n if (player !== except) player.pause()\n })\n}\n","export type AttachmentSourceType = 'image' | 'audio' | 'video' | 'document'\n\nexport type DocumentIconType =\n | 'pdf'\n | 'doc'\n | 'xls'\n | 'csv'\n | 'ppt'\n | 'zip'\n | 'text'\n | 'markdown'\n | 'generic'\n\nconst DOCUMENT_ICON_PATTERNS: Array<[RegExp, DocumentIconType]> = [\n [/pdf/, 'pdf'],\n [/wordprocessingml|msword|\\.doc/, 'doc'],\n [/spreadsheetml|ms-excel|\\.xls/, 'xls'],\n [/csv/, 'csv'],\n [/presentationml|ms-powerpoint|\\.ppt/, 'ppt'],\n [/zip|x-rar|x-7z|x-tar|x-gzip/, 'zip'],\n [/plain|rtf/, 'text'],\n [/markdown/, 'markdown'],\n]\n\nexport function getSourceType(mimeType: string): AttachmentSourceType {\n if (mimeType.startsWith('video/')) return 'video'\n if (mimeType.startsWith('audio/')) return 'audio'\n if (mimeType.startsWith('image/')) return 'image'\n return 'document'\n}\n\nexport function getDocumentIconType(mimeType: string): DocumentIconType {\n const match = DOCUMENT_ICON_PATTERNS.find(([pattern]) =>\n pattern.test(mimeType)\n )\n return match ? match[1] : 'generic'\n}\n","import {\n FileIcon,\n FileCsvIcon,\n FileDocIcon,\n FileMdIcon,\n FilePdfIcon,\n FilePptIcon,\n FileTextIcon,\n FileXlsIcon,\n FileZipIcon,\n ImageIcon,\n SpeakerHighIcon,\n VideoCameraIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getDocumentIconType, getSourceType } from './mimeType'\nimport type { AttachmentSourceType } from './mimeType'\n\nconst MEDIA_TYPE_ICON: Record<AttachmentSourceType, React.ElementType> = {\n video: VideoCameraIcon,\n audio: SpeakerHighIcon,\n image: ImageIcon,\n document: FileIcon,\n}\n\nconst DOCUMENT_ICON_COMPONENT = {\n pdf: FilePdfIcon,\n doc: FileDocIcon,\n xls: FileXlsIcon,\n csv: FileCsvIcon,\n ppt: FilePptIcon,\n zip: FileZipIcon,\n text: FileTextIcon,\n markdown: FileMdIcon,\n generic: FileIcon,\n} as const\n\nfunction getTypeIcon(mimeType: string): React.ElementType {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return MEDIA_TYPE_ICON[sourceType]\n return DOCUMENT_ICON_COMPONENT[getDocumentIconType(mimeType)]\n}\n\nfunction getTypeIconName(mimeType: string): string {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return sourceType\n return getDocumentIconType(mimeType)\n}\n\n/** Use instead of `<TypeIcon />` where TypeIcon = getTypeIcon(mime) to satisfy react-hooks/static-components. */\nexport function renderTypeIcon(\n mimeType: string,\n props: IconProps\n): React.ReactElement {\n // Decorative icons: which one was picked is otherwise only visible in a pixel diff.\n return React.createElement(getTypeIcon(mimeType), {\n 'data-testid': `type-icon-${getTypeIconName(mimeType)}`,\n ...props,\n })\n}\n","/**\n * True in Vite dev builds (`import.meta.env.DEV`). Uses a type assertion so\n * `tsc` does not rely on ambient `ImportMeta` merging (vite/client).\n */\nexport function isDevBuild(): boolean {\n return (\n typeof import.meta !== 'undefined' &&\n (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV === true\n )\n}\n","import { CircleNotchIcon, PauseIcon, PlayIcon } from '@phosphor-icons/react'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { isDevBuild } from '../../utils/isDevBuild'\nimport { nativePlayerProps } from '../../utils/nativeMediaPlayers'\n\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\ntype TouchEventUnion =\n MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent\n\nconst getClientXFromEvent = (e: TouchEventUnion): number => {\n if ('touches' in e) {\n return e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0\n }\n return e.clientX\n}\n\nexport interface MediaPlayerProps {\n source: string\n mimeType: string\n poster?: string\n autoPlay?: boolean\n /** Controlled playing state. When provided, syncs to internal play/pause. */\n playing?: boolean\n loop?: boolean\n controls?: boolean\n showProgress?: boolean\n /** When true, requests muted playback (helps autoplay policies on video). */\n muted?: boolean\n /**\n * When provided, overrides the default click-to-play-toggle behaviour on the\n * player container. The play/pause button (which calls stopPropagation) is\n * unaffected, so inline playback still works.\n */\n onContainerClick?: (e: React.MouseEvent) => void\n}\n\nconst MediaPlayer: React.FC<MediaPlayerProps> = ({\n source,\n mimeType,\n poster,\n autoPlay = false,\n playing: playingProp,\n loop = false,\n controls = true,\n showProgress = false,\n muted = false,\n onContainerClick,\n}) => {\n // --- Derived ---\n const sourceType = getSourceType(mimeType)\n\n // --- Refs ---\n const playerRef = useRef<HTMLMediaElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n const rafRef = useRef<number | null>(null)\n const prevPlayingPropRef = useRef(playingProp)\n\n // --- State: playback ---\n const [playing, setPlaying] = useState(autoPlay)\n const [played, setPlayed] = useState(0)\n const [seeking, setSeeking] = useState(false)\n\n // --- State: UI ---\n const [scrubberHovered, setScrubberHovered] = useState(false)\n /** Set when autoplay/play() was rejected so user can start via gesture (no controls UI). */\n const [manualPlayRequired, setManualPlayRequired] = useState(false)\n\n // --- State: loading ---\n const [buffering, setBuffering] = useState(false)\n /** True until the first canPlay fires for the current source — hides controls/spinner behind poster. */\n const [initialLoad, setInitialLoad] = useState(true)\n const [videoAspect, setVideoAspect] = useState<number | null>(null)\n\n // --- Callbacks ---\n const startPlaybackFromGesture = useCallback(() => {\n setManualPlayRequired(false)\n setPlaying(true)\n }, [])\n\n const getFraction = useCallback((e: TouchEventUnion) => {\n const track = trackRef.current\n if (!track) return 0\n const rect = track.getBoundingClientRect()\n return Math.max(\n 0,\n Math.min(1, (getClientXFromEvent(e) - rect.left) / rect.width)\n )\n }, [])\n\n const seekTo = useCallback((fraction: number) => {\n const el = playerRef.current\n if (el && el.duration) el.currentTime = fraction * el.duration\n }, [])\n\n const handleTrackPointerDown = (\n e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>\n ) => {\n e.stopPropagation()\n setSeeking(true)\n const fraction = getFraction(e)\n setPlayed(fraction)\n seekTo(fraction)\n }\n\n const handleScrubberKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n },\n [seekTo, played]\n )\n\n // --- Effects ---\n\n // Sync controlled playing prop to internal state\n useEffect(() => {\n if (\n playingProp !== undefined &&\n playingProp !== prevPlayingPropRef.current\n ) {\n prevPlayingPropRef.current = playingProp\n setPlaying(playingProp)\n }\n }, [playingProp])\n\n // RAF-driven progress updates\n useEffect(() => {\n if (!playing) {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n return\n }\n const tick = () => {\n const el = playerRef.current\n if (el && el.duration && !seeking) setPlayed(el.currentTime / el.duration)\n rafRef.current = requestAnimationFrame(tick)\n }\n rafRef.current = requestAnimationFrame(tick)\n return () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current)\n }\n }, [playing, seeking])\n\n // ReactPlayer v3 uses native HTML media elements and does not support a\n // declarative `playing` prop — playback must be driven imperatively.\n useEffect(() => {\n const el = playerRef.current\n if (!el) return\n if (playing) {\n void el.play().catch((err) => {\n setPlaying(false)\n setManualPlayRequired(true)\n if (isDevBuild()) {\n console.debug('[MediaPlayer] play() failed', err)\n }\n })\n } else {\n el.pause()\n }\n }, [playing])\n\n // Global seeking listeners\n useEffect(() => {\n if (!seeking) return\n const onMove = (e: MouseEvent | TouchEvent) => setPlayed(getFraction(e))\n const onUp = (e: MouseEvent | TouchEvent) => {\n setSeeking(false)\n seekTo(getFraction(e))\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n window.addEventListener('touchmove', onMove, { passive: true })\n window.addEventListener('touchend', onUp)\n return () => {\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n window.removeEventListener('touchmove', onMove)\n window.removeEventListener('touchend', onUp)\n }\n }, [seeking, getFraction, seekTo])\n\n // --- Derived render values ---\n // Use natural aspect ratio once metadata loads, fall back to 16:9 before then.\n const aspectStyle = videoAspect\n ? { aspectRatio: String(videoAspect) }\n : undefined\n const aspectClass = !videoAspect ? ' aspect-video' : ''\n const scrubberPercent = Math.round(played * 100)\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n data-testid=\"media-player\"\n className={`relative cursor-pointer overflow-hidden bg-black ${aspectClass}`}\n style={aspectStyle}\n onClick={(e) => {\n if (onContainerClick) {\n onContainerClick(e)\n return\n }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n if (onContainerClick) {\n onContainerClick(e as unknown as React.MouseEvent)\n return\n }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n >\n {/* For audio, poster persists as a visual background. For video, hide once loaded. */}\n {poster && (sourceType === 'audio' || initialLoad) && (\n <img\n src={poster}\n alt=\"\"\n data-testid=\"media-player-poster\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {!poster && (sourceType === 'audio' || initialLoad) && (\n <div\n data-testid=\"media-player-placeholder\"\n className=\"absolute inset-0 flex items-center justify-center\"\n >\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <div className=\"absolute inset-0\">\n {sourceType === 'audio' ? (\n <audio\n {...nativePlayerProps}\n ref={playerRef as React.RefObject<HTMLAudioElement>}\n data-testid=\"media-player-audio\"\n src={source}\n loop={loop}\n muted={muted}\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </audio>\n ) : (\n <video\n ref={playerRef as React.RefObject<HTMLVideoElement>}\n data-testid=\"media-player-video\"\n src={source}\n loop={loop}\n muted={muted}\n playsInline\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onLoadedMetadata={() => {\n const el = playerRef.current\n if (\n el instanceof HTMLVideoElement &&\n el.videoWidth &&\n el.videoHeight\n ) {\n setVideoAspect(el.videoWidth / el.videoHeight)\n }\n }}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </video>\n )}\n </div>\n\n {buffering && !manualPlayRequired && (\n <div\n role=\"status\"\n aria-label=\"Loading media\"\n className=\"absolute inset-0 z-10 flex items-center justify-center\"\n >\n <CircleNotchIcon\n className=\"size-8 animate-spin text-white/80\"\n weight=\"bold\"\n />\n </div>\n )}\n\n {manualPlayRequired && !controls && (\n <div\n className=\"absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35\"\n role=\"button\"\n tabIndex={0}\n aria-label=\"Play preview\"\n onClick={(e) => {\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n >\n <span className=\"flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm\">\n <PlayIcon className=\"size-9 translate-x-0.5\" weight=\"fill\" />\n </span>\n </div>\n )}\n\n {showProgress && !controls && (\n <div className=\"absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent\">\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={handleScrubberKeyDown}\n >\n <div className=\"w-full overflow-hidden rounded-full bg-white/30 h-1\">\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n </div>\n )}\n\n {controls && (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n setPlaying((p) => !p)\n }}\n className=\"shrink-0 text-white\"\n aria-label={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <PauseIcon className=\"size-5\" weight=\"fill\" />\n ) : (\n <PlayIcon className=\"size-5 translate-x-px\" weight=\"fill\" />\n )}\n </button>\n\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={() => setScrubberHovered(true)}\n onMouseLeave={() => setScrubberHovered(false)}\n onKeyDown={handleScrubberKeyDown}\n >\n <div\n className={`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${scrubberHovered || seeking ? 'h-1.5' : 'h-1'}`}\n >\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n <div\n data-testid=\"media-player-scrubber-thumb\"\n className={`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${scrubberHovered || seeking ? 'scale-100 opacity-100' : 'scale-0 opacity-0'}`}\n style={{ left: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default MediaPlayer\n","import React, { useState } from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\n\nimport MediaPlayer, { type MediaPlayerProps } from './MediaPlayer'\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\nexport type AttachmentThumbnailVariant = 'light' | 'dark'\n\nexport interface AttachmentThumbnailProps {\n mimeType: string\n sourceUrl?: string\n thumbnailUrl?: string\n title?: string\n variant: AttachmentThumbnailVariant\n /** Extra props passed to MediaPlayer when source is video or audio. */\n mediaPlayerProps?: Partial<\n Pick<\n MediaPlayerProps,\n 'autoPlay' | 'loop' | 'muted' | 'controls' | 'onContainerClick'\n >\n >\n /**\n * When true (Visitor unlocked image/document), use aspect-video + object-contain fade-in.\n */\n containedImage?: boolean\n}\n\nconst placeholderIconClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark' ? 'size-12 text-white/20' : 'size-12 text-black/20'\n\nconst posterShellClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark'\n ? 'aspect-video overflow-hidden bg-white/10'\n : 'aspect-video overflow-hidden bg-black/5'\n\n/**\n * Renders the media preview area for attachment cards (LockedAttachment, MediaMessage).\n * Overlays (dim, lock, eye toggle) are composed by the parent.\n */\nconst AttachmentThumbnail: React.FC<AttachmentThumbnailProps> = ({\n mimeType,\n sourceUrl,\n thumbnailUrl,\n title,\n variant,\n mediaPlayerProps,\n containedImage = false,\n}) => {\n const sourceType = getSourceType(mimeType)\n const [sourceReady, setSourceReady] = useState(false)\n const optimizedSourceUrl = optimizeMessagingAttachmentUrl(sourceUrl)\n const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl)\n\n if (sourceUrl && (sourceType === 'video' || sourceType === 'audio')) {\n return (\n <MediaPlayer\n source={sourceUrl}\n mimeType={mimeType}\n poster={optimizedThumbnailUrl}\n controls\n {...mediaPlayerProps}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'image') {\n if (containedImage) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'document') {\n if (thumbnailUrl) {\n if (containedImage) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt=\"\"\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n }\n\n // Poster-only or empty (no sourceUrl)\n if (thumbnailUrl) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n draggable={false}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n </div>\n )\n }\n\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n}\n\nexport default AttachmentThumbnail\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./AttachmentCard-DUrgGRsq.cjs"),n=require("./LoadingDots-BSk_UeS0.cjs");let r=require("react");r=e.t(r,1);let i=require("react/jsx-runtime"),a=require("classnames");a=e.t(a,1);let o=require("@phosphor-icons/react");var s=({variant:e,title:n,placeholderTitle:r=`Attachment title`,mimeType:o,detail:s,statusBadge:c,action:l,icon:u,trailingAction:d})=>{let f=e===`dark`,p=n||r,m=!n,h=u??t.n(o,{className:(0,a.default)(`size-5 shrink-0`,f?`text-white/55`:`text-black/55`),weight:`regular`});return(0,i.jsxs)(`div`,{className:`px-4 py-3`,children:[(0,i.jsxs)(`div`,{className:`flex items-end gap-3`,children:[(0,i.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-1`,children:[p.trim()!==``&&(0,i.jsx)(`p`,{className:(0,a.default)(`truncate text-base font-medium leading-6`,{"text-black/90":!f&&!m,"text-black/30":!f&&m,"text-white/30":f&&m,"text-white":f&&!m}),children:p}),(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1`,children:[h,s!=null&&s!==``&&(0,i.jsx)(`span`,{className:(0,a.default)(`text-xs font-medium`,f?`text-white/55`:`text-black/55`),children:s}),c]})]}),d&&(0,i.jsx)(`div`,{className:`shrink-0`,children:d})]}),l]})},c=({paymentStatus:e,mimeType:n,isPlayable:r,isLocked:s})=>{let c=n?t.i(n):void 0,l=(r??(c===`video`||c===`audio`))&&!s?o.PlayIcon:e===`paid`?o.LockOpenIcon:o.LockSimpleIcon;return(0,i.jsx)(`div`,{className:`pointer-events-none absolute inset-0 flex items-center justify-center`,children:(0,i.jsx)(`div`,{className:(0,a.default)(`flex size-12 items-center justify-center rounded-full bg-black/30 text-white`,l===o.PlayIcon&&`group-hover:bg-black/40`),children:(0,i.jsx)(l,{className:`size-6`,weight:`fill`})})})};function l(e){let n=t.i(e.mimeType);return n===`video`||n===`audio`}var u=({variant:e,gallery:n,title:s,showLocked:u,paymentStatus:d,topRight:f})=>{let[p,m]=(0,r.useState)(0),h=n.length,g=Math.min(p,h-1),_=n[g],v=l(_),y=t.s(_.thumbnailUrl),b=e=>{e.stopPropagation(),m(e=>Math.max(0,e-1))},x=e=>{e.stopPropagation(),m(e=>Math.min(h-1,e+1))},S=g===0,C=g===h-1,w=e===`dark`;return(0,i.jsxs)(`div`,{className:(0,a.default)(`group relative overflow-hidden rounded-t-md`,u?`aspect-[337/386]`:void 0),children:[u?(0,i.jsx)(`div`,{className:(0,a.default)(`absolute inset-0`,w?`bg-white/10`:`bg-black/5`),children:_.thumbnailUrl&&(0,i.jsx)(`img`,{src:y??_.thumbnailUrl,alt:``,"aria-hidden":!0,draggable:!1,className:`absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]`})}):(0,i.jsx)(t.t,{mimeType:_.mimeType,sourceUrl:_.sourceUrl,thumbnailUrl:_.thumbnailUrl,title:s,variant:e,mediaPlayerProps:{autoPlay:!0}},g),u&&(0,i.jsx)(c,{paymentStatus:d,isPlayable:v,isLocked:u}),h>1&&(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`button`,{type:`button`,onClick:b,disabled:S,"aria-label":`Previous item`,className:(0,a.default)(`absolute left-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity`,S?`opacity-40`:`hover:bg-black/40`),children:(0,i.jsx)(o.CaretLeftIcon,{className:`size-5`,weight:`bold`})}),(0,i.jsx)(`button`,{type:`button`,onClick:x,disabled:C,"aria-label":`Next item`,className:(0,a.default)(`absolute right-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity`,C?`opacity-40`:`hover:bg-black/40`),children:(0,i.jsx)(o.CaretRightIcon,{className:`size-5`,weight:`bold`})}),(0,i.jsx)(`div`,{className:`pointer-events-none absolute bottom-10 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full bg-black/30`,children:(0,i.jsxs)(`span`,{className:`text-xs font-medium leading-none text-white`,children:[g+1,`/`,h]})})]}),f&&(0,i.jsx)(`div`,{className:`pointer-events-auto absolute right-3 top-3 z-10`,children:f})]})},d=({variant:e,mimeType:n,thumbnailUrl:r,title:o,source:s,showLocked:l,paymentStatus:u,topRight:d,containedImage:f=!1})=>{let p=l?void 0:s?.sourceUrl,m=l?r:s?.thumbnailUrl??r,h=t.s(m),g=e===`dark`;return(0,i.jsxs)(`div`,{className:`relative overflow-hidden rounded-t-md`,children:[l?(0,i.jsxs)(`div`,{className:(0,a.default)(`relative aspect-video overflow-hidden`,g?`bg-white/10`:`bg-black/5`),children:[m?(0,i.jsx)(`img`,{src:h??m,alt:``,"aria-hidden":!0,draggable:!1,className:`absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]`}):(0,i.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center`,children:t.n(n,{className:g?`size-12 text-white/20`:`size-12 text-black/20`,weight:`regular`})}),(0,i.jsx)(c,{paymentStatus:u,mimeType:n,isLocked:l})]}):(0,i.jsx)(t.t,{mimeType:n,sourceUrl:p,thumbnailUrl:m,title:o,variant:e,containedImage:f,mediaPlayerProps:p?{autoPlay:!0,loop:!0,controls:!0,muted:!1}:void 0}),d&&(0,i.jsx)(`div`,{className:`pointer-events-auto absolute right-3 top-3 z-10`,children:d})]})},f=e=>e.length>=2,p=e=>(0,i.jsx)(o.ImagesIcon,{className:e===`dark`?`size-5 shrink-0 text-white/55`:`size-5 shrink-0 text-black/55`}),m=({variant:e,gallery:t,title:n,showLocked:r,paymentStatus:a,mimeType:o,thumbnailUrl:s,source:c,containedImage:l,topRight:p})=>f(t)?(0,i.jsx)(u,{variant:e,gallery:t,title:n,showLocked:r,paymentStatus:a,topRight:p}):(0,i.jsx)(d,{variant:e,mimeType:o,thumbnailUrl:s,title:n,source:c,showLocked:r,paymentStatus:a,topRight:p,containedImage:l}),h=({variant:e,children:t,rootRef:n,"data-testid":r})=>(0,i.jsx)(`div`,{ref:n,"data-testid":r,className:(0,a.default)(`relative w-[280px] select-none overflow-hidden rounded-md`,e===`dark`?`bg-[#1e2330]`:`bg-white`,`shadow-[0_1px_2px_rgba(0,0,0,0.08)]`),children:t}),g=({onToggle:e,isBusy:t,isPreviewVisible:n,children:a})=>e?(0,i.jsx)(`div`,{role:`button`,tabIndex:t?-1:0,"aria-label":`Toggle preview`,"aria-busy":t,"aria-pressed":n,"aria-disabled":t||void 0,onClick:t?void 0:e,onKeyDown:n=>{t||n.target===n.currentTarget&&(n.key===`Enter`||n.key===` `)&&(n.preventDefault(),e())},className:t?`block w-full text-left`:`block w-full cursor-pointer text-left`,children:a}):(0,i.jsx)(r.default.Fragment,{children:a});function _({isGallery:e,onFetchSource:t,onPreviewClick:n}){let[i,a]=(0,r.useState)(),[o,s]=(0,r.useState)(!1),[c,l]=(0,r.useState)(!1),u=(0,r.useRef)(!1),d=(0,r.useCallback)(async()=>{if(n?.(),o){s(!1);return}if(e){s(!0);return}if(i){s(!0);return}if(t&&!u.current){u.current=!0,l(!0);try{let e=await t();e&&(a(e),s(!0))}finally{u.current=!1,l(!1)}}},[o,e,i,n,t]);return{source:i,isPreviewVisible:o,isLoadingPreview:c,handleToggle:d,togglePreview:e||t!=null||n!=null?d:void 0}}function v({paymentStatus:e,onFetchSource:t,onUnlockClick:n}){let[i,a]=(0,r.useState)(),o=(0,r.useRef)(null),s=(0,r.useRef)(!1),c=(0,r.useRef)(t);c.current=t;let l=(0,r.useCallback)(async()=>{if(!s.current){s.current=!0;try{let e=await c.current?.();e&&a(e)}finally{s.current=!1}}},[]),u=(0,r.useCallback)(()=>{e===`paid`?l():n?.()},[e,l,n]);return(0,r.useEffect)(()=>{if(!o.current||e!==`paid`||i!==void 0)return;let t=new IntersectionObserver(([e])=>{e.isIntersecting&&(l(),t.disconnect())},{threshold:1});return t.observe(o.current),()=>t.disconnect()},[e,i,l]),{source:i,cardRef:o,handleUnlockClick:u}}var y=`mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full bg-[#121110] px-4 text-sm font-medium leading-none text-white hover:bg-[#2a2928]`,b=({isLocked:e,sourceUrl:t,redeemUrl:a,onUnlockClicked:s,onDownloadClicked:c,isUnlocking:l=!1})=>{if(e&&s!=null)return(0,i.jsx)(`button`,{type:`button`,onClick:s,disabled:l,"aria-label":l?`Unlocking`:`Unlock`,"aria-busy":l,title:l?`Unlocking`:`Unlock`,className:y,children:l?(0,i.jsx)(n.t,{}):(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(o.LockSimpleIcon,{className:`size-4`,weight:`fill`}),`Unlock`]})});if(!e&&c!=null){let e=a??t;return e==null?(0,i.jsxs)(`button`,{type:`button`,onClick:c,"aria-label":`Download`,className:y,children:[(0,i.jsx)(o.DownloadSimpleIcon,{className:`size-4`,weight:`bold`}),`Download`]}):(0,i.jsxs)(`a`,{href:e,"aria-label":`Download`,target:`_blank`,rel:`noopener noreferrer`,onClick:c,className:`${y} !text-white`,children:[(0,i.jsx)(o.DownloadSimpleIcon,{className:`size-4`,weight:`bold`}),`Download`]})}return null},x=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:n,detail:a,amountText:c,placeholderTitle:l,placeholderAmountText:u,gallery:d=[],onDismiss:v,onPreviewClick:y,onFetchSource:b,onEditClick:x})=>{let S=f(d),{source:C,isPreviewVisible:w,isLoadingPreview:T,togglePreview:E}=_({isGallery:S,onFetchSource:b,onPreviewClick:y}),D=!w,O=T,k=(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`span`,{className:`text-xs font-medium text-white/55`,children:`•`}),(0,i.jsx)(`span`,{className:c?`text-xs font-medium text-white/55`:`text-xs font-medium text-white/30`,children:c||u})]}),A=v?(0,i.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),v()},className:`flex size-6 items-center justify-center rounded-full bg-[#121110] text-white`,"aria-label":`Dismiss attachment`,children:(0,i.jsx)(o.XIcon,{className:`size-3`,weight:`bold`})}):void 0,j=x?(0,i.jsx)(`button`,{type:`button`,onClick:x,"aria-label":`Edit attachment`,className:`flex size-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15`,children:(0,i.jsx)(o.PencilSimpleIcon,{className:`size-5`,weight:`regular`})}):void 0;return(0,i.jsxs)(h,{variant:`dark`,children:[(0,i.jsx)(g,{onToggle:E,isBusy:O,isPreviewVisible:!D,children:(0,i.jsx)(m,{variant:`dark`,gallery:d,title:e,showLocked:D,mimeType:t,thumbnailUrl:n,source:C,topRight:A})}),(0,i.jsx)(s,{variant:`dark`,title:e,placeholderTitle:l,mimeType:t,detail:a,statusBadge:k,icon:S?p(`dark`):void 0,trailingAction:j})]})},S=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:n,detail:a,amountText:o,placeholderTitle:c,placeholderAmountText:l,gallery:u=[]})=>{let d=f(u),g=(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`span`,{className:`text-xs font-medium text-black/55`,children:`•`}),(0,i.jsx)(`span`,{className:o?`text-xs font-medium text-black/55`:`text-xs font-medium text-black/30`,children:o||l})]});return(0,i.jsxs)(h,{variant:`light`,children:[(0,i.jsx)(m,{variant:`light`,gallery:u,title:e,showLocked:!0,mimeType:t,thumbnailUrl:n}),(0,i.jsx)(s,{variant:`light`,title:e,placeholderTitle:c,mimeType:t,detail:a,statusBadge:g,icon:d?p(`light`):void 0})]})},C=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:r,detail:a,amountText:o,placeholderTitle:c,paymentStatus:l=`pending`,gallery:u=[],onPreviewClick:d,onFetchSource:v})=>{let y=f(u),{source:b,isPreviewVisible:x,isLoadingPreview:S,togglePreview:C}=_({isGallery:y,onFetchSource:v,onPreviewClick:d}),w=!x;return(0,i.jsxs)(h,{variant:`dark`,children:[(0,i.jsx)(g,{onToggle:C,isBusy:S,isPreviewVisible:!w,children:(0,i.jsx)(m,{variant:`dark`,gallery:u,title:e,showLocked:w,paymentStatus:l,mimeType:t,thumbnailUrl:r,source:b})}),(0,i.jsx)(s,{variant:`dark`,title:e,placeholderTitle:c,mimeType:t,detail:a,statusBadge:(0,i.jsx)(n.n,{isMine:!0,paymentStatus:l,amountText:o}),icon:y?p(`dark`):void 0})]})},w=({title:e,amountText:r,thumbnailUrl:a,mimeType:o=`application/octet-stream`,detail:c,gallery:l=[],onUnlockClick:u,onFetchSource:d,onDownloadClick:g,paymentStatus:_,isUnlocking:y=!1})=>{let x=f(l),{source:S,cardRef:C,handleUnlockClick:w}=v({paymentStatus:_,onFetchSource:d,onUnlockClick:u}),T=S?.sourceUrl,E=S?.redeemUrl,D=x?_!==`paid`:T===void 0,O=t.i(o),k=x?void 0:T;return(0,i.jsxs)(h,{variant:`light`,rootRef:C,"data-testid":`locked-attachment`,children:[(0,i.jsx)(m,{variant:`light`,gallery:l,title:e,showLocked:D,paymentStatus:_,mimeType:o,thumbnailUrl:a,source:S,containedImage:!D&&O===`document`}),(0,i.jsx)(s,{variant:`light`,title:e,mimeType:o,detail:c,statusBadge:(0,i.jsx)(n.n,{isMine:!1,paymentStatus:_,amountText:r}),icon:x?p(`light`):void 0,action:(0,i.jsx)(b,{isLocked:D,isUnlocking:y,sourceUrl:k,redeemUrl:E,onUnlockClicked:w,onDownloadClicked:g})})]})},T=e=>e.isDraft?(0,i.jsx)(x,{...e}):e.isPreview?(0,i.jsx)(S,{...e}):e.isMine?(0,i.jsx)(C,{...e}):(0,i.jsx)(w,{...e});exports.default=T;
|
|
2
|
-
//# sourceMappingURL=Card-
|
|
1
|
+
const e=require("./rolldown-runtime-BocRIvOZ.cjs"),t=require("./AttachmentCard-BbsjzdLJ.cjs"),n=require("./LoadingDots-BSk_UeS0.cjs");let r=require("react");r=e.t(r,1);let i=require("react/jsx-runtime"),a=require("classnames");a=e.t(a,1);let o=require("@phosphor-icons/react");var s=({variant:e,title:n,placeholderTitle:r=`Attachment title`,mimeType:o,detail:s,statusBadge:c,action:l,icon:u,trailingAction:d})=>{let f=e===`dark`,p=n||r,m=!n,h=u??t.n(o,{className:(0,a.default)(`size-5 shrink-0`,f?`text-white/55`:`text-black/55`),weight:`regular`});return(0,i.jsxs)(`div`,{className:`px-4 py-3`,children:[(0,i.jsxs)(`div`,{className:`flex items-end gap-3`,children:[(0,i.jsxs)(`div`,{className:`flex min-w-0 flex-1 flex-col gap-1`,children:[p.trim()!==``&&(0,i.jsx)(`p`,{className:(0,a.default)(`truncate text-base font-medium leading-6`,{"text-black/90":!f&&!m,"text-black/30":!f&&m,"text-white/30":f&&m,"text-white":f&&!m}),children:p}),(0,i.jsxs)(`div`,{className:`flex flex-wrap items-center gap-1`,children:[h,s!=null&&s!==``&&(0,i.jsx)(`span`,{className:(0,a.default)(`text-xs font-medium`,f?`text-white/55`:`text-black/55`),children:s}),c]})]}),d&&(0,i.jsx)(`div`,{className:`shrink-0`,children:d})]}),l]})},c=({paymentStatus:e,mimeType:n,isPlayable:r,isLocked:s})=>{let c=n?t.i(n):void 0,l=(r??(c===`video`||c===`audio`))&&!s?o.PlayIcon:e===`paid`?o.LockOpenIcon:o.LockSimpleIcon;return(0,i.jsx)(`div`,{className:`pointer-events-none absolute inset-0 flex items-center justify-center`,children:(0,i.jsx)(`div`,{className:(0,a.default)(`flex size-12 items-center justify-center rounded-full bg-black/30 text-white`,l===o.PlayIcon&&`group-hover:bg-black/40`),children:(0,i.jsx)(l,{className:`size-6`,weight:`fill`})})})};function l(e){let n=t.i(e.mimeType);return n===`video`||n===`audio`}var u=({variant:e,gallery:n,title:s,showLocked:u,paymentStatus:d,topRight:f})=>{let[p,m]=(0,r.useState)(0),h=n.length,g=Math.min(p,h-1),_=n[g],v=l(_),y=t.s(_.thumbnailUrl),b=e=>{e.stopPropagation(),m(e=>Math.max(0,e-1))},x=e=>{e.stopPropagation(),m(e=>Math.min(h-1,e+1))},S=g===0,C=g===h-1,w=e===`dark`;return(0,i.jsxs)(`div`,{className:(0,a.default)(`group relative overflow-hidden rounded-t-md`,u?`aspect-[337/386]`:void 0),children:[u?(0,i.jsx)(`div`,{className:(0,a.default)(`absolute inset-0`,w?`bg-white/10`:`bg-black/5`),children:_.thumbnailUrl&&(0,i.jsx)(`img`,{src:y??_.thumbnailUrl,alt:``,"aria-hidden":!0,draggable:!1,className:`absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]`})}):(0,i.jsx)(t.t,{mimeType:_.mimeType,sourceUrl:_.sourceUrl,thumbnailUrl:_.thumbnailUrl,title:s,variant:e,mediaPlayerProps:{autoPlay:!0}},g),u&&(0,i.jsx)(c,{paymentStatus:d,isPlayable:v,isLocked:u}),h>1&&(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`button`,{type:`button`,onClick:b,disabled:S,"aria-label":`Previous item`,className:(0,a.default)(`absolute left-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity`,S?`opacity-40`:`hover:bg-black/40`),children:(0,i.jsx)(o.CaretLeftIcon,{className:`size-5`,weight:`bold`})}),(0,i.jsx)(`button`,{type:`button`,onClick:x,disabled:C,"aria-label":`Next item`,className:(0,a.default)(`absolute right-3 top-1/2 -translate-y-1/2 flex size-7 items-center justify-center rounded-full bg-black/30 text-white transition-opacity`,C?`opacity-40`:`hover:bg-black/40`),children:(0,i.jsx)(o.CaretRightIcon,{className:`size-5`,weight:`bold`})}),(0,i.jsx)(`div`,{className:`pointer-events-none absolute bottom-10 left-1/2 flex size-8 -translate-x-1/2 items-center justify-center rounded-full bg-black/30`,children:(0,i.jsxs)(`span`,{className:`text-xs font-medium leading-none text-white`,children:[g+1,`/`,h]})})]}),f&&(0,i.jsx)(`div`,{className:`pointer-events-auto absolute right-3 top-3 z-10`,children:f})]})},d=({variant:e,mimeType:n,thumbnailUrl:r,title:o,source:s,showLocked:l,paymentStatus:u,topRight:d,containedImage:f=!1})=>{let p=l?void 0:s?.sourceUrl,m=l?r:s?.thumbnailUrl??r,h=t.s(m),g=e===`dark`;return(0,i.jsxs)(`div`,{className:`relative overflow-hidden rounded-t-md`,children:[l?(0,i.jsxs)(`div`,{className:(0,a.default)(`relative aspect-video overflow-hidden`,g?`bg-white/10`:`bg-black/5`),children:[m?(0,i.jsx)(`img`,{src:h??m,alt:``,"aria-hidden":!0,draggable:!1,className:`absolute inset-0 h-full w-full scale-110 object-cover blur-[40px]`}):(0,i.jsx)(`div`,{className:`absolute inset-0 flex items-center justify-center`,children:t.n(n,{className:g?`size-12 text-white/20`:`size-12 text-black/20`,weight:`regular`})}),(0,i.jsx)(c,{paymentStatus:u,mimeType:n,isLocked:l})]}):(0,i.jsx)(t.t,{mimeType:n,sourceUrl:p,thumbnailUrl:m,title:o,variant:e,containedImage:f,mediaPlayerProps:p?{autoPlay:!0,loop:!0,controls:!0,muted:!1}:void 0}),d&&(0,i.jsx)(`div`,{className:`pointer-events-auto absolute right-3 top-3 z-10`,children:d})]})},f=e=>e.length>=2,p=e=>(0,i.jsx)(o.ImagesIcon,{className:e===`dark`?`size-5 shrink-0 text-white/55`:`size-5 shrink-0 text-black/55`}),m=({variant:e,gallery:t,title:n,showLocked:r,paymentStatus:a,mimeType:o,thumbnailUrl:s,source:c,containedImage:l,topRight:p})=>f(t)?(0,i.jsx)(u,{variant:e,gallery:t,title:n,showLocked:r,paymentStatus:a,topRight:p}):(0,i.jsx)(d,{variant:e,mimeType:o,thumbnailUrl:s,title:n,source:c,showLocked:r,paymentStatus:a,topRight:p,containedImage:l}),h=({variant:e,children:t,rootRef:n,"data-testid":r})=>(0,i.jsx)(`div`,{ref:n,"data-testid":r,className:(0,a.default)(`relative w-[280px] select-none overflow-hidden rounded-md`,e===`dark`?`bg-[#1e2330]`:`bg-white`,`shadow-[0_1px_2px_rgba(0,0,0,0.08)]`),children:t}),g=({onToggle:e,isBusy:t,isPreviewVisible:n,children:a})=>e?(0,i.jsx)(`div`,{role:`button`,tabIndex:t?-1:0,"aria-label":`Toggle preview`,"aria-busy":t,"aria-pressed":n,"aria-disabled":t||void 0,onClick:t?void 0:e,onKeyDown:n=>{t||n.target===n.currentTarget&&(n.key===`Enter`||n.key===` `)&&(n.preventDefault(),e())},className:t?`block w-full text-left`:`block w-full cursor-pointer text-left`,children:a}):(0,i.jsx)(r.default.Fragment,{children:a});function _({isGallery:e,onFetchSource:t,onPreviewClick:n}){let[i,a]=(0,r.useState)(),[o,s]=(0,r.useState)(!1),[c,l]=(0,r.useState)(!1),u=(0,r.useRef)(!1),d=(0,r.useCallback)(async()=>{if(n?.(),o){s(!1);return}if(e){s(!0);return}if(i){s(!0);return}if(t&&!u.current){u.current=!0,l(!0);try{let e=await t();e&&(a(e),s(!0))}finally{u.current=!1,l(!1)}}},[o,e,i,n,t]);return{source:i,isPreviewVisible:o,isLoadingPreview:c,handleToggle:d,togglePreview:e||t!=null||n!=null?d:void 0}}function v({paymentStatus:e,onFetchSource:t,onUnlockClick:n}){let[i,a]=(0,r.useState)(),o=(0,r.useRef)(null),s=(0,r.useRef)(!1),c=(0,r.useRef)(t);c.current=t;let l=(0,r.useCallback)(async()=>{if(!s.current){s.current=!0;try{let e=await c.current?.();e&&a(e)}finally{s.current=!1}}},[]),u=(0,r.useCallback)(()=>{e===`paid`?l():n?.()},[e,l,n]);return(0,r.useEffect)(()=>{if(!o.current||e!==`paid`||i!==void 0)return;let t=new IntersectionObserver(([e])=>{e.isIntersecting&&(l(),t.disconnect())},{threshold:1});return t.observe(o.current),()=>t.disconnect()},[e,i,l]),{source:i,cardRef:o,handleUnlockClick:u}}var y=`mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full bg-[#121110] px-4 text-sm font-medium leading-none text-white hover:bg-[#2a2928]`,b=({isLocked:e,sourceUrl:t,redeemUrl:a,onUnlockClicked:s,onDownloadClicked:c,isUnlocking:l=!1})=>{if(e&&s!=null)return(0,i.jsx)(`button`,{type:`button`,onClick:s,disabled:l,"aria-label":l?`Unlocking`:`Unlock`,"aria-busy":l,title:l?`Unlocking`:`Unlock`,className:y,children:l?(0,i.jsx)(n.t,{}):(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(o.LockSimpleIcon,{className:`size-4`,weight:`fill`}),`Unlock`]})});if(!e&&c!=null){let e=a??t;return e==null?(0,i.jsxs)(`button`,{type:`button`,onClick:c,"aria-label":`Download`,className:y,children:[(0,i.jsx)(o.DownloadSimpleIcon,{className:`size-4`,weight:`bold`}),`Download`]}):(0,i.jsxs)(`a`,{href:e,"aria-label":`Download`,target:`_blank`,rel:`noopener noreferrer`,onClick:c,className:`${y} !text-white`,children:[(0,i.jsx)(o.DownloadSimpleIcon,{className:`size-4`,weight:`bold`}),`Download`]})}return null},x=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:n,detail:a,amountText:c,placeholderTitle:l,placeholderAmountText:u,gallery:d=[],onDismiss:v,onPreviewClick:y,onFetchSource:b,onEditClick:x})=>{let S=f(d),{source:C,isPreviewVisible:w,isLoadingPreview:T,togglePreview:E}=_({isGallery:S,onFetchSource:b,onPreviewClick:y}),D=!w,O=T,k=(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`span`,{className:`text-xs font-medium text-white/55`,children:`•`}),(0,i.jsx)(`span`,{className:c?`text-xs font-medium text-white/55`:`text-xs font-medium text-white/30`,children:c||u})]}),A=v?(0,i.jsx)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),v()},className:`flex size-6 items-center justify-center rounded-full bg-[#121110] text-white`,"aria-label":`Dismiss attachment`,children:(0,i.jsx)(o.XIcon,{className:`size-3`,weight:`bold`})}):void 0,j=x?(0,i.jsx)(`button`,{type:`button`,onClick:x,"aria-label":`Edit attachment`,className:`flex size-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15`,children:(0,i.jsx)(o.PencilSimpleIcon,{className:`size-5`,weight:`regular`})}):void 0;return(0,i.jsxs)(h,{variant:`dark`,children:[(0,i.jsx)(g,{onToggle:E,isBusy:O,isPreviewVisible:!D,children:(0,i.jsx)(m,{variant:`dark`,gallery:d,title:e,showLocked:D,mimeType:t,thumbnailUrl:n,source:C,topRight:A})}),(0,i.jsx)(s,{variant:`dark`,title:e,placeholderTitle:l,mimeType:t,detail:a,statusBadge:k,icon:S?p(`dark`):void 0,trailingAction:j})]})},S=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:n,detail:a,amountText:o,placeholderTitle:c,placeholderAmountText:l,gallery:u=[]})=>{let d=f(u),g=(0,i.jsxs)(r.default.Fragment,{children:[(0,i.jsx)(`span`,{className:`text-xs font-medium text-black/55`,children:`•`}),(0,i.jsx)(`span`,{className:o?`text-xs font-medium text-black/55`:`text-xs font-medium text-black/30`,children:o||l})]});return(0,i.jsxs)(h,{variant:`light`,children:[(0,i.jsx)(m,{variant:`light`,gallery:u,title:e,showLocked:!0,mimeType:t,thumbnailUrl:n}),(0,i.jsx)(s,{variant:`light`,title:e,placeholderTitle:c,mimeType:t,detail:a,statusBadge:g,icon:d?p(`light`):void 0})]})},C=({title:e,mimeType:t=`application/octet-stream`,thumbnailUrl:r,detail:a,amountText:o,placeholderTitle:c,paymentStatus:l=`pending`,gallery:u=[],onPreviewClick:d,onFetchSource:v})=>{let y=f(u),{source:b,isPreviewVisible:x,isLoadingPreview:S,togglePreview:C}=_({isGallery:y,onFetchSource:v,onPreviewClick:d}),w=!x;return(0,i.jsxs)(h,{variant:`dark`,children:[(0,i.jsx)(g,{onToggle:C,isBusy:S,isPreviewVisible:!w,children:(0,i.jsx)(m,{variant:`dark`,gallery:u,title:e,showLocked:w,paymentStatus:l,mimeType:t,thumbnailUrl:r,source:b})}),(0,i.jsx)(s,{variant:`dark`,title:e,placeholderTitle:c,mimeType:t,detail:a,statusBadge:(0,i.jsx)(n.n,{isMine:!0,paymentStatus:l,amountText:o}),icon:y?p(`dark`):void 0})]})},w=({title:e,amountText:r,thumbnailUrl:a,mimeType:o=`application/octet-stream`,detail:c,gallery:l=[],onUnlockClick:u,onFetchSource:d,onDownloadClick:g,paymentStatus:_,isUnlocking:y=!1})=>{let x=f(l),{source:S,cardRef:C,handleUnlockClick:w}=v({paymentStatus:_,onFetchSource:d,onUnlockClick:u}),T=S?.sourceUrl,E=S?.redeemUrl,D=x?_!==`paid`:T===void 0,O=t.i(o),k=x?void 0:T;return(0,i.jsxs)(h,{variant:`light`,rootRef:C,"data-testid":`locked-attachment`,children:[(0,i.jsx)(m,{variant:`light`,gallery:l,title:e,showLocked:D,paymentStatus:_,mimeType:o,thumbnailUrl:a,source:S,containedImage:!D&&O===`document`}),(0,i.jsx)(s,{variant:`light`,title:e,mimeType:o,detail:c,statusBadge:(0,i.jsx)(n.n,{isMine:!1,paymentStatus:_,amountText:r}),icon:x?p(`light`):void 0,action:(0,i.jsx)(b,{isLocked:D,isUnlocking:y,sourceUrl:k,redeemUrl:E,onUnlockClicked:w,onDownloadClicked:g})})]})},T=e=>e.isDraft?(0,i.jsx)(x,{...e}):e.isPreview?(0,i.jsx)(S,{...e}):e.isMine?(0,i.jsx)(C,{...e}):(0,i.jsx)(w,{...e});exports.default=T;
|
|
2
|
+
//# sourceMappingURL=Card-BS6Fza2a.cjs.map
|