46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import type { MediaItem } from '../../../../../packages/api-contracts/src/index.js';
|
|
import { mediaConversation, mediaType } from './filters.js';
|
|
|
|
interface MediaCardProps {
|
|
item: MediaItem;
|
|
isRevealed: boolean;
|
|
onToggleReveal(): void;
|
|
}
|
|
|
|
function formatMediaDate(timestamp: number): string {
|
|
return new Intl.DateTimeFormat(undefined, { dateStyle: 'medium', timeStyle: 'short' }).format(timestamp);
|
|
}
|
|
|
|
export function MediaCard({ item, isRevealed, onToggleReveal }: MediaCardProps) {
|
|
return (
|
|
<article className="media-card">
|
|
<div className="media-preview">
|
|
<img
|
|
alt={`Media from ${item.sender}`}
|
|
className={isRevealed ? 'media-image' : 'media-image is-blurred'}
|
|
loading="lazy"
|
|
src={item.urlPath}
|
|
/>
|
|
{!isRevealed ? <span className="privacy-label">Private media hidden</span> : null}
|
|
</div>
|
|
<div className="media-card-body">
|
|
<div>
|
|
<strong>{item.sender}</strong>
|
|
<span>{mediaConversation(item)}</span>
|
|
</div>
|
|
<dl>
|
|
<div><dt>Type</dt><dd>{mediaType(item) === 'gif' ? 'GIF' : 'Image'}</dd></div>
|
|
<div><dt>Received</dt><dd>{formatMediaDate(item.timestamp)}</dd></div>
|
|
</dl>
|
|
<button
|
|
className="button secondary media-reveal"
|
|
onClick={onToggleReveal}
|
|
type="button"
|
|
>
|
|
{isRevealed ? `Hide media from ${item.sender}` : `Reveal media from ${item.sender}`}
|
|
</button>
|
|
</div>
|
|
</article>
|
|
);
|
|
}
|