this repo has no description

Accounts component

ari.express fe96164f 8bf166f1

verified
+21 -5
src/App.svelte
··· 1 1 <script lang="ts"> 2 2 import PostComponent from "./lib/PostComponent.svelte"; 3 - import { fetchAllPosts, Post } from "./lib/pdsfetch"; 3 + import AccountComponent from "./lib/AccountComponent.svelte"; 4 + import { fetchAllPosts, Post, getAllMetadataFromPds } from "./lib/pdsfetch"; 4 5 const postsPromise = fetchAllPosts(); 6 + const accountsPromise = getAllMetadataFromPds(); 5 7 </script> 6 8 7 9 <main> 10 + <h1>Welcome to the Feed</h1> 11 + {#await accountsPromise} 12 + <p>Loading...</p> 13 + {:then accountsData} 14 + <div id="Account"> 15 + {#each accountsData as accountObject} 16 + <AccountComponent account={accountObject} /> 17 + {/each} 18 + </div> 19 + {:catch error} 20 + <p>Error: {error.message}</p> 21 + {/await} 22 + 8 23 {#await postsPromise} 9 24 <p>Loading...</p> 10 25 {:then postsData} 11 - {#each postsData as postObject} 12 - <PostComponent post={postObject as Post} /> 13 - {/each} 26 + <div id="Feed"> 27 + {#each postsData as postObject} 28 + <PostComponent post={postObject as Post} /> 29 + {/each} 30 + </div> 14 31 {/await} 15 32 </main> 16 33 17 34 <style> 18 - 19 35 </style>
+27
src/lib/AccountComponent.svelte
··· 1 + <script lang="ts"> 2 + import type { AccountMetadata } from "./pdsfetch"; 3 + const { account }: { account: AccountMetadata } = $props(); 4 + </script> 5 + <div id="accountContainer"> 6 + {#if account.avatarCid} 7 + <img 8 + id="avatar" 9 + alt="avatar of {account.displayName}" 10 + src="https://pds.witchcraft.systems/xrpc/com.atproto.sync.getBlob?did={account.did}&cid={account.avatarCid}" 11 + /> 12 + {/if} 13 + <p>{account.displayName}</p> 14 + </div> 15 + <style> 16 + #accountContainer { 17 + display: column; 18 + text-align: start; 19 + border: 2px solid black; 20 + padding: 4%; 21 + } 22 + #avatar { 23 + width: 50px; 24 + height: 50px; 25 + border-radius: 50%; 26 + } 27 + </style>
+11 -7
src/lib/PostComponent.svelte
··· 8 8 {#if post.authorAvatarCid} 9 9 <img 10 10 id="avatar" 11 + alt="avatar of {post.displayName}" 11 12 src="https://pds.witchcraft.systems/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.authorAvatarCid}" 12 13 /> 13 14 {/if} ··· 18 19 {#if post.replyingDid} 19 20 <p>Replying to: {post.replyingDid}</p> 20 21 {/if} 21 - {#if post.imagesLinksCid} 22 - {#each post.imagesLinksCid as imageLink} 23 - <img 24 - id="embedImages" 25 - src="https://pds.witchcraft.systems/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={imageLink}" 26 - /> 27 - {/each} 22 + {#if post.imagesCid} 23 + <div id="imagesContainer"> 24 + {#each post.imagesCid as imageLink} 25 + <img 26 + id="embedImages" 27 + alt="Post Image" 28 + src="https://pds.witchcraft.systems/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={imageLink}" 29 + /> 30 + {/each} 31 + </div> 28 32 {/if} 29 33 {#if post.videosLinkCid} 30 34 <video
+26 -9
src/lib/pdsfetch.ts
··· 1 1 import { simpleFetchHandler, XRPC } from "@atcute/client"; 2 2 import "@atcute/bluesky/lexicons"; 3 + import type { 4 + AppBskyActorDefs, 5 + AppBskyFeedPost, 6 + ComAtprotoRepoListRecords, 7 + } from "@atcute/client/lexicons"; 3 8 // import { ComAtprotoRepoListRecords.Record } from "@atcute/client/lexicons"; 4 9 // import { AppBskyFeedPost } from "@atcute/client/lexicons"; 5 10 // import { AppBskyActorDefs } from "@atcute/client/lexicons"; ··· 12 17 class Post { 13 18 authorDid: string; 14 19 authorAvatarCid: string | null; 15 - displayName : string; 20 + displayName: string; 16 21 text: string; 17 22 timestamp: number; 18 23 timenotstamp: string; 19 24 quotingDid: string | null; 20 25 replyingDid: string | null; 21 - imagesLinksCid: string[] | null; 26 + imagesCid: string[] | null; 22 27 videosLinkCid: string | null; 23 28 24 - constructor(record: ComAtprotoRepoListRecords.Record, account : AccountMetadata) { 29 + constructor( 30 + record: ComAtprotoRepoListRecords.Record, 31 + account: AccountMetadata, 32 + ) { 25 33 this.authorDid = account.did; 26 34 this.authorAvatarCid = account.avatarCid; 27 35 this.displayName = account.displayName; ··· 35 43 this.replyingDid = null; 36 44 } 37 45 this.quotingDid = null; 38 - this.imagesLinksCid = null; 46 + this.imagesCid = null; 39 47 this.videosLinkCid = null; 40 48 switch (post.embed?.$type) { 41 49 case "app.bsky.embed.images": 42 - this.imagesLinksCid = post.embed.images.map((imageRecord) => 50 + this.imagesCid = post.embed.images.map((imageRecord: any) => 43 51 imageRecord.image.ref.$link 44 52 ); 45 53 break; ··· 53 61 this.quotingDid = didFromATuri(post.embed.record.record.uri).repo; 54 62 switch (post.embed.media.$type) { 55 63 case "app.bsky.embed.images": 56 - this.imagesLinksCid = post.embed.media.images.map((imageRecord) => 64 + this.imagesCid = post.embed.media.images.map((imageRecord) => 57 65 imageRecord.image.ref.$link 58 66 ); 59 67 ··· 141 149 await fetchPosts(metadata.did) 142 150 ), 143 151 ); 144 - const posts : Post[] = postRecords.flatMap((userFetch) => 145 - userFetch.records.map((record) => new Post(record, users.find((user : AccountMetadata) => user.did == userFetch.did))) 152 + const posts: Post[] = postRecords.flatMap((userFetch) => 153 + userFetch.records.map((record) => { 154 + const user = users.find((user: AccountMetadata) => 155 + user.did == userFetch.did 156 + ); 157 + if (!user) { 158 + throw new Error(`User with DID ${userFetch.did} not found`); 159 + } 160 + return new Post(record, user); 161 + }) 146 162 ); 147 163 posts.sort((a, b) => b.timestamp - a.timestamp); 148 164 return posts; 149 165 }; 150 166 151 - export { fetchAllPosts, Post }; 167 + export { fetchAllPosts, getAllMetadataFromPds, Post }; 168 + export type { AccountMetadata };