Compare commits
10 commits
main
...
ari/CleanA
Author | SHA1 | Date | |
---|---|---|---|
d92f6f6514 | |||
04de4c1841 | |||
824fcf2575 | |||
5da1494081 | |||
1e04628fdf | |||
cb4189ee51 | |||
cef9060948 | |||
e1665b6c55 | |||
9fe004f4a4 | |||
412e18f628 |
8 changed files with 67 additions and 51 deletions
|
@ -15,10 +15,10 @@ export class Config {
|
||||||
static readonly FRONTEND_URL: string = "https://deer.social";
|
static readonly FRONTEND_URL: string = "https://deer.social";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of posts to fetch from the PDS per user
|
* Maximum number of posts to show in the feed (across all users)
|
||||||
* @default 10
|
* @default 100
|
||||||
*/
|
*/
|
||||||
static readonly MAX_POSTS_PER_USER: number = 22;
|
static readonly MAX_POSTS: number = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Footer text for the dashboard
|
* Footer text for the dashboard
|
||||||
|
|
5
deno.lock
generated
5
deno.lock
generated
|
@ -6,6 +6,7 @@
|
||||||
"npm:@atcute/identity-resolver@~0.1.2": "0.1.2_@atcute+identity@0.1.3",
|
"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:@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:@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-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:svelte@^5.23.1": "5.28.1_acorn@8.14.1",
|
||||||
"npm:typescript@~5.7.2": "5.7.3",
|
"npm:typescript@~5.7.2": "5.7.3",
|
||||||
|
@ -337,6 +338,9 @@
|
||||||
"@jridgewell/sourcemap-codec"
|
"@jridgewell/sourcemap-codec"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"moment@2.30.1": {
|
||||||
|
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="
|
||||||
|
},
|
||||||
"mri@1.2.0": {
|
"mri@1.2.0": {
|
||||||
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="
|
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="
|
||||||
},
|
},
|
||||||
|
@ -470,6 +474,7 @@
|
||||||
"npm:@atcute/identity-resolver@~0.1.2",
|
"npm:@atcute/identity-resolver@~0.1.2",
|
||||||
"npm:@sveltejs/vite-plugin-svelte@^5.0.3",
|
"npm:@sveltejs/vite-plugin-svelte@^5.0.3",
|
||||||
"npm:@tsconfig/svelte@^5.0.4",
|
"npm:@tsconfig/svelte@^5.0.4",
|
||||||
|
"npm:moment@^2.30.1",
|
||||||
"npm:svelte-check@^4.1.5",
|
"npm:svelte-check@^4.1.5",
|
||||||
"npm:svelte@^5.23.1",
|
"npm:svelte@^5.23.1",
|
||||||
"npm:typescript@~5.7.2",
|
"npm:typescript@~5.7.2",
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@atcute/bluesky": "^2.0.2",
|
"@atcute/bluesky": "^2.0.2",
|
||||||
"@atcute/client": "^3.0.1",
|
"@atcute/client": "^3.0.1",
|
||||||
"@atcute/identity-resolver": "^0.1.2"
|
"@atcute/identity-resolver": "^0.1.2",
|
||||||
|
"moment": "^2.30.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
/* desktop style */
|
/* desktop style */
|
||||||
|
|
||||||
#Content {
|
#Content {
|
||||||
|
@ -51,8 +52,8 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #12082b;
|
background-color: var(--background-color);
|
||||||
color: #ffffff;
|
color: var(--text-color);
|
||||||
}
|
}
|
||||||
#Feed {
|
#Feed {
|
||||||
width: 65%;
|
width: 65%;
|
||||||
|
@ -74,8 +75,8 @@
|
||||||
width: 35%;
|
width: 35%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: 1px solid #8054f0;
|
border: 1px solid var(--border-color);
|
||||||
background-color: #0d0620;
|
background-color: var(--content-background-color);
|
||||||
height: 80vh;
|
height: 80vh;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
|
@ -96,8 +97,8 @@
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mobile style */
|
/* mobile style */
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
#Content {
|
#Content {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
24
src/app.css
24
src/app.css
|
@ -3,6 +3,18 @@
|
||||||
src: url(https://witchcraft.systems/ProggyCleanNerdFont-Regular.ttf);
|
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 {
|
::-webkit-scrollbar {
|
||||||
width: 0px;
|
width: 0px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
@ -35,11 +47,11 @@
|
||||||
|
|
||||||
a {
|
a {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #646cff;
|
color: var(--link-color);
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
}
|
}
|
||||||
a:hover {
|
a:hover {
|
||||||
color: #535bf2;
|
color: var(--link-hover-color);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,11 +61,11 @@ body {
|
||||||
place-items: center;
|
place-items: center;
|
||||||
min-width: 320px;
|
min-width: 320px;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #12082b;
|
background-color: var(--background-color);
|
||||||
font-family: 'ProggyClean', monospace;
|
font-family: 'ProggyClean', monospace;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
color: white;
|
color: var(--text-color);
|
||||||
border-color: #8054f0;
|
border-color: var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
|
@ -69,5 +81,3 @@ h1 {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,10 +24,10 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
text-align: start;
|
text-align: start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #12082b;
|
background-color: var(--background-color);
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
border: 1px solid #8054f0;
|
border: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
#accountName {
|
#accountName {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
@ -43,6 +43,6 @@
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
border-right: #8054f0 1px solid;
|
border-right: var(--border-color) 1px solid;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { Post } from "./pdsfetch";
|
import { Post } from "./pdsfetch";
|
||||||
import { Config } from "../../config";
|
import { Config } from "../../config";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
let { post }: { post: Post } = $props();
|
let { post }: { post: Post } = $props();
|
||||||
|
|
||||||
|
@ -76,7 +77,9 @@
|
||||||
<a
|
<a
|
||||||
id="postLink"
|
id="postLink"
|
||||||
href="{Config.FRONTEND_URL}/profile/{post.authorDid}/post/{post.recordName}"
|
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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -131,6 +134,7 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if post.videosLinkCid}
|
{#if post.videosLinkCid}
|
||||||
|
<!-- svelte-ignore a11y_media_has_caption -->
|
||||||
<video
|
<video
|
||||||
id="embedVideo"
|
id="embedVideo"
|
||||||
src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.videosLinkCid}"
|
src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.videosLinkCid}"
|
||||||
|
@ -141,14 +145,15 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
a:hover {
|
a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
#postContainer {
|
#postContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: 1px solid #8054f0;
|
border: 1px solid var(--border-color);
|
||||||
background-color: black;
|
background-color: var(--background-color);
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
@ -157,29 +162,29 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: start;
|
justify-content: start;
|
||||||
background-color: #1f1145;
|
background-color: var(--header-background-color);
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
border-bottom: 1px solid #8054f0;
|
border-bottom: 1px solid var(--border-color);
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
#displayName {
|
#displayName {
|
||||||
color: white;
|
color: var(--text-color);
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
#handle {
|
#handle {
|
||||||
color: #8054f0;
|
color: var(--border-color);
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#postLink {
|
#postLink {
|
||||||
color: #8054f0;
|
color: var(--border-color);
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -189,8 +194,8 @@
|
||||||
text-align: start;
|
text-align: start;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: #0d0620;
|
background-color: var(--content-background-color);
|
||||||
color: white;
|
color: var(--text-color);
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
}
|
}
|
||||||
#replyingText {
|
#replyingText {
|
||||||
|
@ -220,7 +225,7 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
border-right: #8054f0 1px solid;
|
border-right: var(--border-color) 1px solid;
|
||||||
}
|
}
|
||||||
#carouselContainer {
|
#carouselContainer {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -245,16 +250,16 @@
|
||||||
.indicator {
|
.indicator {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
background-color: #4a4a4a;
|
background-color: var(--indicator-inactive-color);
|
||||||
}
|
}
|
||||||
.indicator.active {
|
.indicator.active {
|
||||||
background-color: #8054f0;
|
background-color: var(--indicator-active-color);
|
||||||
}
|
}
|
||||||
#prevBtn,
|
#prevBtn,
|
||||||
#nextBtn {
|
#nextBtn {
|
||||||
background-color: rgba(31, 17, 69, 0.7);
|
background-color: rgba(31, 17, 69, 0.7);
|
||||||
color: white;
|
color: var(--text-color);
|
||||||
border: 1px solid #8054f0;
|
border: 1px solid var(--border-color);
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Post {
|
||||||
account: AccountMetadata,
|
account: AccountMetadata,
|
||||||
) {
|
) {
|
||||||
this.postCid = record.cid;
|
this.postCid = record.cid;
|
||||||
this.recordName = record.uri.split("/").slice(-1)[0];
|
this.recordName = processAtUri(record.uri).rkey;
|
||||||
this.authorDid = account.did;
|
this.authorDid = account.did;
|
||||||
this.authorAvatarCid = account.avatarCid;
|
this.authorAvatarCid = account.avatarCid;
|
||||||
this.authorHandle = account.handle;
|
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", {
|
const { data } = await rpc.get("com.atproto.sync.listRepos", {
|
||||||
params: {},
|
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
|
// gonna assume self exists in the app.bsky.actor.profile
|
||||||
try {
|
try {
|
||||||
const { data } = await rpc.get("com.atproto.repo.getRecord", {
|
const { data } = await rpc.get("com.atproto.repo.getRecord", {
|
||||||
|
@ -146,11 +146,12 @@ const getAccountMetadata = async (did: `did:${string}:${string}`) => {
|
||||||
did: "error",
|
did: "error",
|
||||||
displayName: "",
|
displayName: "",
|
||||||
avatarCid: null,
|
avatarCid: null,
|
||||||
|
handle: "error",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAllMetadataFromPds = async () => {
|
const getAllMetadataFromPds = async () : Promise<AccountMetadata[]> => {
|
||||||
const dids = await getDidsFromPDS();
|
const dids = await getDidsFromPDS();
|
||||||
const metadata = await Promise.all(
|
const metadata = await Promise.all(
|
||||||
dids.map(async (repo: `did:${string}:${string}`) => {
|
dids.map(async (repo: `did:${string}:${string}`) => {
|
||||||
|
@ -166,7 +167,7 @@ const fetchPosts = async (did: string) => {
|
||||||
params: {
|
params: {
|
||||||
repo: did as At.Identifier,
|
repo: did as At.Identifier,
|
||||||
collection: "app.bsky.feed.post",
|
collection: "app.bsky.feed.post",
|
||||||
limit: Config.MAX_POSTS_PER_USER,
|
limit: Config.MAX_POSTS,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
|
@ -237,14 +238,7 @@ const fetchAllPosts = async () => {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
posts.sort((a, b) => b.timestamp - a.timestamp);
|
posts.sort((a, b) => b.timestamp - a.timestamp);
|
||||||
return posts;
|
return posts.slice(0, Config.MAX_POSTS);
|
||||||
};
|
|
||||||
|
|
||||||
const testApiCall = async () => {
|
|
||||||
const { data } = await rpc.get("com.atproto.sync.listRepos", {
|
|
||||||
params: {},
|
|
||||||
});
|
|
||||||
console.log(data);
|
|
||||||
};
|
};
|
||||||
export { fetchAllPosts, getAllMetadataFromPds, Post };
|
export { fetchAllPosts, getAllMetadataFromPds, Post };
|
||||||
export type { AccountMetadata };
|
export type { AccountMetadata };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue