grain.social is a photo sharing platform built on atproto.
1import { GalleryView } from "$lexicon/types/social/grain/gallery/defs.ts";
2import { PhotoView } from "$lexicon/types/social/grain/photo/defs.ts";
3import { Un$Typed } from "$lexicon/util.ts";
4import { AtUri } from "@atproto/syntax";
5import { AltTextButton } from "./AltTextButton.tsx";
6import { PhotoExifButton } from "./PhotoExifButton.tsx";
7import { RemovePhotoDialogButton } from "./RemovePhotoDialog.tsx";
8
9export function PhotoPreview({
10 photo,
11 selectedGallery,
12}: Readonly<{
13 photo: Un$Typed<PhotoView>;
14 selectedGallery?: GalleryView;
15}>) {
16 const atUri = new AtUri(photo.uri);
17 const did = atUri.hostname;
18 const rkey = atUri.rkey;
19 return (
20 <div
21 class="relative aspect-square bg-zinc-200 dark:bg-zinc-900"
22 id={`photo-${rkey}`}
23 >
24 {photo.uri ? <AltTextButton photoUri={photo.uri} /> : null}
25 {photo.exif ? <PhotoExifButton photoUri={photo.uri} /> : null}
26 {photo.uri
27 ? (
28 <RemovePhotoDialogButton
29 selectedGallery={selectedGallery}
30 photoUri={photo.uri}
31 />
32 )
33 : null}
34 {photo.uri
35 ? (
36 <button
37 type="button"
38 hx-get={`/dialogs/gallery/${did}/select?photoUri=${photo.uri}`}
39 hx-trigger="click"
40 hx-target="#layout"
41 hx-swap="afterbegin"
42 class="bg-zinc-950/50 z-10 absolute bottom-2 right-2 cursor-pointer size-4 flex items-center justify-center"
43 >
44 <i class="fas fa-plus text-white"></i>
45 </button>
46 )
47 : null}
48 <img
49 src={photo.thumb}
50 alt=""
51 data-state={photo.uri ? "complete" : "pending"}
52 class="absolute inset-0 w-full h-full object-contain data-[state=pending]:opacity-50"
53 />
54 </div>
55 );
56}