this repo has no description

Cleanup and Maintenance part 1 (#1)

Co-authored-by: ari <ariadna@omg.lol>
Reviewed-on: https://git.witchcraft.systems/scientific-witchery/pds-dash/pulls/1

+3 -3
config.ts
··· 15 15 static readonly FRONTEND_URL: string = "https://deer.social"; 16 16 17 17 /** 18 - * Maximum number of posts to fetch from the PDS per user 19 - * @default 10 18 + * Maximum number of posts to show in the feed (across all users) 19 + * @default 100 20 20 */ 21 - static readonly MAX_POSTS_PER_USER: number = 22; 21 + static readonly MAX_POSTS: number = 100; 22 22 23 23 /** 24 24 * Footer text for the dashboard
+5
deno.lock
··· 6 6 "npm:@atcute/identity-resolver@~0.1.2": "0.1.2_@atcute+identity@0.1.3", 7 7 "npm:@sveltejs/vite-plugin-svelte@^5.0.3": "5.0.3_svelte@5.28.1__acorn@8.14.1_vite@6.3.2__picomatch@4.0.2", 8 8 "npm:@tsconfig/svelte@^5.0.4": "5.0.4", 9 + "npm:moment@^2.30.1": "2.30.1", 9 10 "npm:svelte-check@^4.1.5": "4.1.6_svelte@5.28.1__acorn@8.14.1_typescript@5.7.3", 10 11 "npm:svelte@^5.23.1": "5.28.1_acorn@8.14.1", 11 12 "npm:typescript@~5.7.2": "5.7.3", ··· 337 338 "@jridgewell/sourcemap-codec" 338 339 ] 339 340 }, 341 + "moment@2.30.1": { 342 + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==" 343 + }, 340 344 "mri@1.2.0": { 341 345 "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==" 342 346 }, ··· 470 474 "npm:@atcute/identity-resolver@~0.1.2", 471 475 "npm:@sveltejs/vite-plugin-svelte@^5.0.3", 472 476 "npm:@tsconfig/svelte@^5.0.4", 477 + "npm:moment@^2.30.1", 473 478 "npm:svelte-check@^4.1.5", 474 479 "npm:svelte@^5.23.1", 475 480 "npm:typescript@~5.7.2",
+2 -1
package.json
··· 12 12 "dependencies": { 13 13 "@atcute/bluesky": "^2.0.2", 14 14 "@atcute/client": "^3.0.1", 15 - "@atcute/identity-resolver": "^0.1.2" 15 + "@atcute/identity-resolver": "^0.1.2", 16 + "moment": "^2.30.1" 16 17 }, 17 18 "devDependencies": { 18 19 "@sveltejs/vite-plugin-svelte": "^5.0.3",
+8 -7
src/App.svelte
··· 41 41 </main> 42 42 43 43 <style> 44 + 44 45 /* desktop style */ 45 - 46 + 46 47 #Content { 47 48 display: flex; 48 49 /* split the screen in half, left for accounts, right for posts */ ··· 51 52 flex-direction: row; 52 53 justify-content: space-between; 53 54 align-items: center; 54 - background-color: #12082b; 55 - color: #ffffff; 55 + background-color: var(--background-color); 56 + color: var(--text-color); 56 57 } 57 58 #Feed { 58 59 width: 65%; ··· 74 75 width: 35%; 75 76 display: flex; 76 77 flex-direction: column; 77 - border: 1px solid #8054f0; 78 - background-color: #0d0620; 78 + border: 1px solid var(--border-color); 79 + background-color: var(--content-background-color); 79 80 height: 80vh; 80 81 padding: 20px; 81 82 margin-left: 20px; ··· 96 97 margin-bottom: 20px; 97 98 } 98 99 99 - /* mobile style */ 100 - @media screen and (max-width: 600px) { 100 + /* mobile style */ 101 + @media screen and (max-width: 600px) { 101 102 #Content { 102 103 flex-direction: column; 103 104 width: auto;
+18 -8
src/app.css
··· 3 3 src: url(https://witchcraft.systems/ProggyCleanNerdFont-Regular.ttf); 4 4 } 5 5 6 + :root { 7 + --link-color: #646cff; 8 + --link-hover-color: #535bf2; 9 + --background-color: #12082b; 10 + --header-background-color: #1f1145; 11 + --content-background-color: #0d0620; 12 + --text-color: white; 13 + --border-color: #8054f0; 14 + --indicator-inactive-color: #4a4a4a; 15 + --indicator-active-color: #8054f0; 16 + } 17 + 6 18 ::-webkit-scrollbar { 7 19 width: 0px; 8 20 background: transparent; ··· 35 47 36 48 a { 37 49 font-weight: 500; 38 - color: #646cff; 50 + color: var(--link-color); 39 51 text-decoration: inherit; 40 52 } 41 53 a:hover { 42 - color: #535bf2; 54 + color: var(--link-hover-color); 43 55 text-decoration: underline; 44 56 } 45 57 ··· 49 61 place-items: center; 50 62 min-width: 320px; 51 63 min-height: 100vh; 52 - background-color: #12082b; 64 + background-color: var(--background-color); 53 65 font-family: 'ProggyClean', monospace; 54 66 font-size: 24px; 55 - color: white; 56 - border-color: #8054f0; 67 + color: var(--text-color); 68 + border-color: var(--border-color); 57 69 } 58 70 59 71 h1 { ··· 68 80 margin-left: auto; 69 81 margin-right: auto; 70 82 text-align: center; 71 - } 72 - 73 - 83 + }
+3 -3
src/lib/AccountComponent.svelte
··· 24 24 display: flex; 25 25 text-align: start; 26 26 align-items: center; 27 - background-color: #12082b; 27 + background-color: var(--background-color); 28 28 padding: 0px; 29 29 margin-bottom: 15px; 30 - border: 1px solid #8054f0; 30 + border: 1px solid var(--border-color); 31 31 } 32 32 #accountName { 33 33 margin-left: 10px; ··· 43 43 width: 50px; 44 44 height: 50px; 45 45 margin: 0px; 46 - border-right: #8054f0 1px solid; 46 + border-right: var(--border-color) 1px solid; 47 47 } 48 48 </style>
+20 -15
src/lib/PostComponent.svelte
··· 2 2 import { Post } from "./pdsfetch"; 3 3 import { Config } from "../../config"; 4 4 import { onMount } from "svelte"; 5 + import moment from "moment"; 5 6 6 7 let { post }: { post: Post } = $props(); 7 8 ··· 76 77 <a 77 78 id="postLink" 78 79 href="{Config.FRONTEND_URL}/profile/{post.authorDid}/post/{post.recordName}" 79 - >{post.timenotstamp}</a 80 + >{moment(post.timenotstamp).isBefore(moment().subtract(1, "month")) 81 + ? moment(post.timenotstamp).format("MMM D, YYYY") 82 + : moment(post.timenotstamp).fromNow()}</a 80 83 > 81 84 </p> 82 85 </div> ··· 131 134 </div> 132 135 {/if} 133 136 {#if post.videosLinkCid} 137 + <!-- svelte-ignore a11y_media_has_caption --> 134 138 <video 135 139 id="embedVideo" 136 140 src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.videosLinkCid}" ··· 141 145 </div> 142 146 143 147 <style> 148 + 144 149 a:hover { 145 150 text-decoration: underline; 146 151 } 147 152 #postContainer { 148 153 display: flex; 149 154 flex-direction: column; 150 - border: 1px solid #8054f0; 151 - background-color: black; 155 + border: 1px solid var(--border-color); 156 + background-color: var(--background-color); 152 157 margin-bottom: 15px; 153 158 overflow-wrap: break-word; 154 159 } ··· 157 162 flex-direction: row; 158 163 align-items: center; 159 164 justify-content: start; 160 - background-color: #1f1145; 165 + background-color: var(--header-background-color); 161 166 padding: 0px 0px; 162 167 height: fit-content; 163 - border-bottom: 1px solid #8054f0; 168 + border-bottom: 1px solid var(--border-color); 164 169 font-weight: bold; 165 170 overflow-wrap: break-word; 166 171 height: 60px; 167 172 } 168 173 #displayName { 169 - color: white; 174 + color: var(--text-color); 170 175 font-size: 1.2em; 171 176 padding: 0; 172 177 margin: 0; 173 178 } 174 179 #handle { 175 - color: #8054f0; 180 + color: var(--border-color); 176 181 font-size: 0.8em; 177 182 padding: 0; 178 183 margin: 0; 179 184 } 180 185 181 186 #postLink { 182 - color: #8054f0; 187 + color: var(--border-color); 183 188 font-size: 0.8em; 184 189 padding: 0; 185 190 margin: 0; ··· 189 194 text-align: start; 190 195 flex-direction: column; 191 196 padding: 10px; 192 - background-color: #0d0620; 193 - color: white; 197 + background-color: var(--content-background-color); 198 + color: var(--text-color); 194 199 overflow-wrap: break-word; 195 200 } 196 201 #replyingText { ··· 220 225 height: 100%; 221 226 margin: 0px; 222 227 margin-left: 0px; 223 - border-right: #8054f0 1px solid; 228 + border-right: var(--border-color) 1px solid; 224 229 } 225 230 #carouselContainer { 226 231 position: relative; ··· 245 250 .indicator { 246 251 width: 8px; 247 252 height: 8px; 248 - background-color: #4a4a4a; 253 + background-color: var(--indicator-inactive-color); 249 254 } 250 255 .indicator.active { 251 - background-color: #8054f0; 256 + background-color: var(--indicator-active-color); 252 257 } 253 258 #prevBtn, 254 259 #nextBtn { 255 260 background-color: rgba(31, 17, 69, 0.7); 256 - color: white; 257 - border: 1px solid #8054f0; 261 + color: var(--text-color); 262 + border: 1px solid var(--border-color); 258 263 width: 30px; 259 264 height: 30px; 260 265 cursor: pointer;
+8 -14
src/lib/pdsfetch.ts
··· 48 48 account: AccountMetadata, 49 49 ) { 50 50 this.postCid = record.cid; 51 - this.recordName = record.uri.split("/").slice(-1)[0]; 51 + this.recordName = processAtUri(record.uri).rkey; 52 52 this.authorDid = account.did; 53 53 this.authorAvatarCid = account.avatarCid; 54 54 this.authorHandle = account.handle; ··· 111 111 }), 112 112 }); 113 113 114 - const getDidsFromPDS = async () => { 114 + const getDidsFromPDS = async () : Promise<At.Did[]> => { 115 115 const { data } = await rpc.get("com.atproto.sync.listRepos", { 116 116 params: {}, 117 117 }); 118 - return data.repos.map((repo: any) => (repo.did)); 118 + return data.repos.map((repo: any) => (repo.did)) as At.Did[]; 119 119 }; 120 - const getAccountMetadata = async (did: `did:${string}:${string}`) => { 120 + const getAccountMetadata = async (did: `did:${string}:${string}`) : Promise<AccountMetadata> => { 121 121 // gonna assume self exists in the app.bsky.actor.profile 122 122 try { 123 123 const { data } = await rpc.get("com.atproto.repo.getRecord", { ··· 146 146 did: "error", 147 147 displayName: "", 148 148 avatarCid: null, 149 + handle: "error", 149 150 }; 150 151 } 151 152 }; 152 153 153 - const getAllMetadataFromPds = async () => { 154 + const getAllMetadataFromPds = async () : Promise<AccountMetadata[]> => { 154 155 const dids = await getDidsFromPDS(); 155 156 const metadata = await Promise.all( 156 157 dids.map(async (repo: `did:${string}:${string}`) => { ··· 166 167 params: { 167 168 repo: did as At.Identifier, 168 169 collection: "app.bsky.feed.post", 169 - limit: Config.MAX_POSTS_PER_USER, 170 + limit: Config.MAX_POSTS, 170 171 }, 171 172 }); 172 173 return { ··· 237 238 }) 238 239 ); 239 240 posts.sort((a, b) => b.timestamp - a.timestamp); 240 - return posts; 241 - }; 242 - 243 - const testApiCall = async () => { 244 - const { data } = await rpc.get("com.atproto.sync.listRepos", { 245 - params: {}, 246 - }); 247 - console.log(data); 241 + return posts.slice(0, Config.MAX_POSTS); 248 242 }; 249 243 export { fetchAllPosts, getAllMetadataFromPds, Post }; 250 244 export type { AccountMetadata };