grain.social is a photo sharing platform built on atproto.
at main 3.2 kB view raw
1import { GalleryView } from "$lexicon/types/social/grain/gallery/defs.ts"; 2import { isPhotoView } from "$lexicon/types/social/grain/photo/defs.ts"; 3import { AtUri } from "@atproto/syntax"; 4import { ModerationDecsion } from "../lib/moderation.ts"; 5import { CommentsButton } from "../modules/comments.tsx"; 6import { EditGalleryButton } from "./EditGalleryDialog.tsx"; 7import { FavoriteButton } from "./FavoriteButton.tsx"; 8import { GalleryInfo } from "./GalleryInfo.tsx"; 9import { GalleryLayout } from "./GalleryLayout.tsx"; 10import { ModerationWrapper } from "./ModerationWrapper.tsx"; 11import { ShareGalleryDialogButton } from "./ShareGalleryDialog.tsx"; 12 13export function GalleryPage({ 14 gallery, 15 currentUserDid, 16 modDecision, 17}: Readonly<{ 18 gallery: GalleryView; 19 currentUserDid?: string; 20 modDecision?: ModerationDecsion; 21}>) { 22 const isCreator = currentUserDid === gallery.creator.did; 23 const isLoggedIn = !!currentUserDid; 24 const galleryItems = gallery.items?.filter(isPhotoView) ?? []; 25 return ( 26 <div class="px-4" id="gallery-page"> 27 <div id="dialog-target" /> 28 <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between mt-4 mb-2"> 29 <GalleryInfo gallery={gallery} /> 30 {isLoggedIn && isCreator 31 ? ( 32 <div class="flex self-start gap-2 w-full flex-col sm:flex-row sm:justify-end"> 33 <EditGalleryButton gallery={gallery} /> 34 <div class="flex flex-row gap-2 w-full sm:w-fit"> 35 <FavoriteButton class="flex-1" gallery={gallery} /> 36 <CommentsButton class="flex-1" gallery={gallery} /> 37 <ShareGalleryDialogButton class="flex-1" gallery={gallery} /> 38 </div> 39 </div> 40 ) 41 : null} 42 {!isCreator 43 ? ( 44 <div class="flex self-start gap-2 flex-row w-full sm:w-fit"> 45 <FavoriteButton gallery={gallery} /> 46 <CommentsButton class="flex-1" gallery={gallery} /> 47 <ShareGalleryDialogButton class="flex-1" gallery={gallery} /> 48 </div> 49 ) 50 : null} 51 </div> 52 {isLoggedIn && isCreator && gallery.items?.length === 0 53 ? ( 54 <div 55 hx-get={`/dialogs/gallery/${new AtUri(gallery.uri).rkey}/photos`} 56 hx-trigger="load" 57 hx-target="#dialog-target" 58 hx-swap="innerHTML" 59 /> 60 ) 61 : null} 62 { 63 <ModerationWrapper moderationDecision={modDecision} class="mb-2"> 64 <GalleryLayout 65 layoutButtons={ 66 <> 67 <GalleryLayout.ModeButton mode="justified" /> 68 <GalleryLayout.ModeButton mode="masonry" /> 69 </> 70 } 71 > 72 <GalleryLayout.Container> 73 {galleryItems?.length 74 ? galleryItems.map((photo) => ( 75 <GalleryLayout.Item 76 key={photo.cid} 77 photo={photo} 78 gallery={gallery} 79 /> 80 )) 81 : null} 82 </GalleryLayout.Container> 83 </GalleryLayout> 84 </ModerationWrapper> 85 } 86 </div> 87 ); 88}