your personal website on atproto - mirror blento.app
25
fork

Configure Feed

Select the types of activity you want to include in your feed.

at update-docs 126 lines 3.2 kB view raw
1<script lang="ts"> 2 import { Button, Input, Label, Modal, Subheading } from '@foxui/core'; 3 import type { CreationModalComponentProps } from '../../types'; 4 import { onMount } from 'svelte'; 5 import { getDidContext } from '$lib/website/context'; 6 import { getAuthorFeed } from '$lib/atproto/methods'; 7 8 let { item = $bindable(), oncreate, oncancel }: CreationModalComponentProps = $props(); 9 10 let did = getDidContext(); 11 12 let mediaList: { fullsize: string; isVideo?: boolean; playlist?: string; thumbnail?: string }[] = 13 $state([]); 14 15 let isLoading = $state(true); 16 17 onMount(async () => { 18 const authorFeed = await getAuthorFeed({ did }); 19 20 for (let post of authorFeed?.feed ?? []) { 21 let images = 22 post.post.embed?.$type === 'app.bsky.embed.images#view' ? post.post.embed : undefined; 23 24 for (let image of images?.images ?? []) { 25 mediaList.push(image); 26 } 27 28 if ( 29 post.post.embed?.$type === 'app.bsky.embed.video#view' && 30 post.post.embed.thumbnail && 31 post.post.embed.playlist 32 ) { 33 mediaList.push({ 34 ...post.post.embed, 35 isVideo: true, 36 fullsize: '' 37 }); 38 } 39 } 40 41 isLoading = false; 42 }); 43 44 let selected = $state(); 45</script> 46 47<Modal 48 bind:open={ 49 () => true, 50 (change) => { 51 if (!change) oncancel(); 52 } 53 } 54 closeButton={false} 55 class="flex max-h-screen flex-col" 56> 57 <Subheading>Select an image or video</Subheading> 58 59 <div 60 class="bg-base-100 dark:bg-base-950 grid h-[50dvh] grid-cols-2 gap-4 overflow-y-scroll rounded-2xl p-4 lg:grid-cols-3" 61 > 62 {#each mediaList as media (media.thumbnail || media.playlist)} 63 <button 64 onclick={() => { 65 selected = media; 66 if (media.isVideo) { 67 item.cardData = { 68 video: media 69 }; 70 } else item.cardData.image = media; 71 }} 72 class="relative cursor-pointer" 73 > 74 <img 75 src={media.fullsize || media.thumbnail} 76 alt="" 77 class={[ 78 'h-32 w-full rounded-xl object-cover', 79 selected === media 80 ? 'outline-accent-500 opacity-100 outline-2 -outline-offset-2' 81 : 'opacity-80' 82 ]} 83 /> 84 {#if media.isVideo} 85 <div class="absolute inset-0 inline-flex items-center justify-center"> 86 <svg 87 xmlns="http://www.w3.org/2000/svg" 88 viewBox="0 0 24 24" 89 fill="currentColor" 90 class="text-accent-500 size-6" 91 > 92 <path 93 d="M4.5 4.5a3 3 0 0 0-3 3v9a3 3 0 0 0 3 3h8.25a3 3 0 0 0 3-3v-9a3 3 0 0 0-3-3H4.5ZM19.94 18.75l-2.69-2.69V7.94l2.69-2.69c.944-.945 2.56-.276 2.56 1.06v11.38c0 1.336-1.616 2.005-2.56 1.06Z" 94 /> 95 </svg> 96 </div> 97 {/if} 98 </button> 99 {/each} 100 {#if isLoading} 101 <span class="col-span-full p-4 text-lg italic">Loading your media...</span> 102 {:else if mediaList.length === 0} 103 <span class="col-span-full p-4 text-lg italic" 104 >No media found, upload an image or video to bluesky to see it here.</span 105 > 106 {/if} 107 </div> 108 109 <Label class="mt-4">Link (optional):</Label> 110 <Input bind:value={item.cardData.href} /> 111 112 <div class="mt-4 flex justify-end gap-2"> 113 <Button 114 onclick={() => { 115 oncancel(); 116 }} 117 variant="ghost">Cancel</Button 118 > 119 <Button 120 disabled={!selected} 121 onclick={async () => { 122 oncreate(); 123 }}>Create</Button 124 > 125 </div> 126</Modal>