feat(web): fullscreen media preview/viewer and fix media context menu
Some checks failed
CI / test (push) Failing after 26s

This commit is contained in:
2026-03-08 10:38:46 +03:00
parent a77516cfea
commit 72c3b10ba5
2 changed files with 172 additions and 53 deletions

View File

@@ -567,55 +567,62 @@ export function MessageComposer() {
</div>
{selectedFile ? (
<div className="mb-2 rounded-2xl border border-slate-700/80 bg-slate-900/95 p-3 text-sm shadow-xl">
<div className="mb-2 flex items-center justify-between">
<div>
<p className="font-semibold">Send {selectedType === "image" || selectedType === "video" ? "Photo" : "File"}</p>
<p className="text-xs text-slate-400">{selectedFile.name} {formatBytes(selectedFile.size)}</p>
<div className="fixed inset-0 z-[160] flex items-center justify-center bg-slate-950/80 p-3" onClick={cancelSelectedFile}>
<div className="flex h-full w-full max-w-2xl flex-col rounded-2xl border border-slate-700/80 bg-slate-900/95 shadow-2xl" onClick={(event) => event.stopPropagation()}>
<div className="flex items-center justify-between border-b border-slate-700/70 px-3 py-2">
<div className="min-w-0">
<p className="truncate text-sm font-semibold">Send {selectedType === "image" || selectedType === "video" ? "Photo" : "File"}</p>
<p className="truncate text-xs text-slate-400">{selectedFile.name} {formatBytes(selectedFile.size)}</p>
</div>
<button className="rounded bg-slate-700 px-2 py-1 text-xs" onClick={cancelSelectedFile} type="button">
Close
</button>
</div>
<button className="rounded bg-slate-700 px-2 py-1 text-xs" onClick={cancelSelectedFile} type="button">
</button>
</div>
{previewUrl && selectedType === "image" ? (
<img className="mb-2 max-h-72 w-full rounded-xl object-contain" src={previewUrl} alt={selectedFile.name} />
) : null}
{previewUrl && selectedType === "video" ? (
<video className="mb-2 max-h-72 w-full rounded-xl" src={previewUrl} controls muted />
) : null}
{!previewUrl ? (
<div className="mb-2 rounded-lg border border-slate-700/80 bg-slate-800/60 px-3 py-2 text-xs text-slate-300">
No preview available
<div className="tg-scrollbar min-h-0 flex-1 overflow-auto p-3">
{previewUrl && selectedType === "image" ? (
<img className="mx-auto max-h-[70vh] w-full rounded-xl object-contain" src={previewUrl} alt={selectedFile.name} />
) : null}
{previewUrl && selectedType === "video" ? (
<video className="mx-auto max-h-[70vh] w-full rounded-xl" src={previewUrl} controls muted />
) : null}
{!previewUrl ? (
<div className="rounded-lg border border-slate-700/80 bg-slate-800/60 px-3 py-2 text-xs text-slate-300">
No preview available
</div>
) : null}
</div>
) : null}
<input
className="mb-2 w-full rounded-xl border border-slate-700/80 bg-slate-800/80 px-3 py-2 text-sm outline-none placeholder:text-slate-400 focus:border-sky-500"
maxLength={1000}
placeholder="Add a caption..."
value={captionDraft}
onChange={(event) => setCaptionDraft(event.target.value)}
/>
<div className="border-t border-slate-700/70 p-3">
<input
className="mb-2 w-full rounded-xl border border-slate-700/80 bg-slate-800/80 px-3 py-2 text-sm outline-none placeholder:text-slate-400 focus:border-sky-500"
maxLength={1000}
placeholder="Add a caption..."
value={captionDraft}
onChange={(event) => setCaptionDraft(event.target.value)}
/>
{isUploading ? (
<div className="mb-2">
<div className="mb-1 text-xs text-slate-300">Uploading: {uploadProgress}%</div>
<div className="h-2 rounded bg-slate-700">
<div className="h-2 rounded bg-sky-500 transition-all" style={{ width: `${uploadProgress}%` }} />
{isUploading ? (
<div className="mb-2">
<div className="mb-1 text-xs text-slate-300">Uploading: {uploadProgress}%</div>
<div className="h-2 rounded bg-slate-700">
<div className="h-2 rounded bg-sky-500 transition-all" style={{ width: `${uploadProgress}%` }} />
</div>
</div>
) : null}
<div className="flex gap-2">
<button
className="w-full rounded-xl bg-sky-500 px-3 py-2 font-semibold text-slate-950 disabled:opacity-50"
onClick={() => void sendSelectedFile()}
disabled={isUploading}
>
Send
</button>
<button className="w-full rounded-xl bg-slate-700 px-3 py-2 disabled:opacity-50" onClick={cancelSelectedFile} disabled={isUploading}>
Cancel
</button>
</div>
</div>
) : null}
<div className="flex gap-2">
<button
className="w-full rounded-xl bg-sky-500 px-3 py-2 font-semibold text-slate-950 disabled:opacity-50"
onClick={() => void sendSelectedFile()}
disabled={isUploading}
>
Send
</button>
<button className="w-full rounded-xl bg-slate-700 px-3 py-2 disabled:opacity-50" onClick={cancelSelectedFile} disabled={isUploading}>
Cancel
</button>
</div>
</div>
) : null}