Compare commits

...
Sign in to create a new pull request.

10 commits

8 changed files with 67 additions and 51 deletions

View file

@ -15,10 +15,10 @@ export class Config {
static readonly FRONTEND_URL: string = "https://deer.social";
/**
* Maximum number of posts to fetch from the PDS per user
* @default 10
* Maximum number of posts to show in the feed (across all users)
* @default 100
*/
static readonly MAX_POSTS_PER_USER: number = 22;
static readonly MAX_POSTS: number = 100;
/**
* Footer text for the dashboard

5
deno.lock generated
View file

@ -6,6 +6,7 @@
"npm:@atcute/identity-resolver@~0.1.2": "0.1.2_@atcute+identity@0.1.3",
"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",
"npm:@tsconfig/svelte@^5.0.4": "5.0.4",
"npm:moment@^2.30.1": "2.30.1",
"npm:svelte-check@^4.1.5": "4.1.6_svelte@5.28.1__acorn@8.14.1_typescript@5.7.3",
"npm:svelte@^5.23.1": "5.28.1_acorn@8.14.1",
"npm:typescript@~5.7.2": "5.7.3",
@ -337,6 +338,9 @@
"@jridgewell/sourcemap-codec"
]
},
"moment@2.30.1": {
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="
},
"mri@1.2.0": {
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="
},
@ -470,6 +474,7 @@
"npm:@atcute/identity-resolver@~0.1.2",
"npm:@sveltejs/vite-plugin-svelte@^5.0.3",
"npm:@tsconfig/svelte@^5.0.4",
"npm:moment@^2.30.1",
"npm:svelte-check@^4.1.5",
"npm:svelte@^5.23.1",
"npm:typescript@~5.7.2",

View file

@ -12,7 +12,8 @@
"dependencies": {
"@atcute/bluesky": "^2.0.2",
"@atcute/client": "^3.0.1",
"@atcute/identity-resolver": "^0.1.2"
"@atcute/identity-resolver": "^0.1.2",
"moment": "^2.30.1"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^5.0.3",

View file

@ -41,6 +41,7 @@
</main>
<style>
/* desktop style */
#Content {
@ -51,8 +52,8 @@
flex-direction: row;
justify-content: space-between;
align-items: center;
background-color: #12082b;
color: #ffffff;
background-color: var(--background-color);
color: var(--text-color);
}
#Feed {
width: 65%;
@ -74,8 +75,8 @@
width: 35%;
display: flex;
flex-direction: column;
border: 1px solid #8054f0;
background-color: #0d0620;
border: 1px solid var(--border-color);
background-color: var(--content-background-color);
height: 80vh;
padding: 20px;
margin-left: 20px;

View file

@ -3,6 +3,18 @@
src: url(https://witchcraft.systems/ProggyCleanNerdFont-Regular.ttf);
}
:root {
--link-color: #646cff;
--link-hover-color: #535bf2;
--background-color: #12082b;
--header-background-color: #1f1145;
--content-background-color: #0d0620;
--text-color: white;
--border-color: #8054f0;
--indicator-inactive-color: #4a4a4a;
--indicator-active-color: #8054f0;
}
::-webkit-scrollbar {
width: 0px;
background: transparent;
@ -35,11 +47,11 @@
a {
font-weight: 500;
color: #646cff;
color: var(--link-color);
text-decoration: inherit;
}
a:hover {
color: #535bf2;
color: var(--link-hover-color);
text-decoration: underline;
}
@ -49,11 +61,11 @@ body {
place-items: center;
min-width: 320px;
min-height: 100vh;
background-color: #12082b;
background-color: var(--background-color);
font-family: 'ProggyClean', monospace;
font-size: 24px;
color: white;
border-color: #8054f0;
color: var(--text-color);
border-color: var(--border-color);
}
h1 {
@ -69,5 +81,3 @@ h1 {
margin-right: auto;
text-align: center;
}

View file

@ -24,10 +24,10 @@
display: flex;
text-align: start;
align-items: center;
background-color: #12082b;
background-color: var(--background-color);
padding: 0px;
margin-bottom: 15px;
border: 1px solid #8054f0;
border: 1px solid var(--border-color);
}
#accountName {
margin-left: 10px;
@ -43,6 +43,6 @@
width: 50px;
height: 50px;
margin: 0px;
border-right: #8054f0 1px solid;
border-right: var(--border-color) 1px solid;
}
</style>

View file

@ -2,6 +2,7 @@
import { Post } from "./pdsfetch";
import { Config } from "../../config";
import { onMount } from "svelte";
import moment from "moment";
let { post }: { post: Post } = $props();
@ -76,7 +77,9 @@
<a
id="postLink"
href="{Config.FRONTEND_URL}/profile/{post.authorDid}/post/{post.recordName}"
>{post.timenotstamp}</a
>{moment(post.timenotstamp).isBefore(moment().subtract(1, "month"))
? moment(post.timenotstamp).format("MMM D, YYYY")
: moment(post.timenotstamp).fromNow()}</a
>
</p>
</div>
@ -131,6 +134,7 @@
</div>
{/if}
{#if post.videosLinkCid}
<!-- svelte-ignore a11y_media_has_caption -->
<video
id="embedVideo"
src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.videosLinkCid}"
@ -141,14 +145,15 @@
</div>
<style>
a:hover {
text-decoration: underline;
}
#postContainer {
display: flex;
flex-direction: column;
border: 1px solid #8054f0;
background-color: black;
border: 1px solid var(--border-color);
background-color: var(--background-color);
margin-bottom: 15px;
overflow-wrap: break-word;
}
@ -157,29 +162,29 @@
flex-direction: row;
align-items: center;
justify-content: start;
background-color: #1f1145;
background-color: var(--header-background-color);
padding: 0px 0px;
height: fit-content;
border-bottom: 1px solid #8054f0;
border-bottom: 1px solid var(--border-color);
font-weight: bold;
overflow-wrap: break-word;
height: 60px;
}
#displayName {
color: white;
color: var(--text-color);
font-size: 1.2em;
padding: 0;
margin: 0;
}
#handle {
color: #8054f0;
color: var(--border-color);
font-size: 0.8em;
padding: 0;
margin: 0;
}
#postLink {
color: #8054f0;
color: var(--border-color);
font-size: 0.8em;
padding: 0;
margin: 0;
@ -189,8 +194,8 @@
text-align: start;
flex-direction: column;
padding: 10px;
background-color: #0d0620;
color: white;
background-color: var(--content-background-color);
color: var(--text-color);
overflow-wrap: break-word;
}
#replyingText {
@ -220,7 +225,7 @@
height: 100%;
margin: 0px;
margin-left: 0px;
border-right: #8054f0 1px solid;
border-right: var(--border-color) 1px solid;
}
#carouselContainer {
position: relative;
@ -245,16 +250,16 @@
.indicator {
width: 8px;
height: 8px;
background-color: #4a4a4a;
background-color: var(--indicator-inactive-color);
}
.indicator.active {
background-color: #8054f0;
background-color: var(--indicator-active-color);
}
#prevBtn,
#nextBtn {
background-color: rgba(31, 17, 69, 0.7);
color: white;
border: 1px solid #8054f0;
color: var(--text-color);
border: 1px solid var(--border-color);
width: 30px;
height: 30px;
cursor: pointer;

View file

@ -48,7 +48,7 @@ class Post {
account: AccountMetadata,
) {
this.postCid = record.cid;
this.recordName = record.uri.split("/").slice(-1)[0];
this.recordName = processAtUri(record.uri).rkey;
this.authorDid = account.did;
this.authorAvatarCid = account.avatarCid;
this.authorHandle = account.handle;
@ -111,13 +111,13 @@ const rpc = new XRPC({
}),
});
const getDidsFromPDS = async () => {
const getDidsFromPDS = async () : Promise<At.Did[]> => {
const { data } = await rpc.get("com.atproto.sync.listRepos", {
params: {},
});
return data.repos.map((repo: any) => (repo.did));
return data.repos.map((repo: any) => (repo.did)) as At.Did[];
};
const getAccountMetadata = async (did: `did:${string}:${string}`) => {
const getAccountMetadata = async (did: `did:${string}:${string}`) : Promise<AccountMetadata> => {
// gonna assume self exists in the app.bsky.actor.profile
try {
const { data } = await rpc.get("com.atproto.repo.getRecord", {
@ -146,11 +146,12 @@ const getAccountMetadata = async (did: `did:${string}:${string}`) => {
did: "error",
displayName: "",
avatarCid: null,
handle: "error",
};
}
};
const getAllMetadataFromPds = async () => {
const getAllMetadataFromPds = async () : Promise<AccountMetadata[]> => {
const dids = await getDidsFromPDS();
const metadata = await Promise.all(
dids.map(async (repo: `did:${string}:${string}`) => {
@ -166,7 +167,7 @@ const fetchPosts = async (did: string) => {
params: {
repo: did as At.Identifier,
collection: "app.bsky.feed.post",
limit: Config.MAX_POSTS_PER_USER,
limit: Config.MAX_POSTS,
},
});
return {
@ -237,14 +238,7 @@ const fetchAllPosts = async () => {
})
);
posts.sort((a, b) => b.timestamp - a.timestamp);
return posts;
};
const testApiCall = async () => {
const { data } = await rpc.get("com.atproto.sync.listRepos", {
params: {},
});
console.log(data);
return posts.slice(0, Config.MAX_POSTS);
};
export { fetchAllPosts, getAllMetadataFromPds, Post };
export type { AccountMetadata };