diff --git a/.forgejo/workflows/deploy.yaml b/.forgejo/workflows/deploy.yaml
index c6a05d0..7f20d99 100644
--- a/.forgejo/workflows/deploy.yaml
+++ b/.forgejo/workflows/deploy.yaml
@@ -6,15 +6,26 @@ on:
- main
- astra/ci
+
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
steps:
- - name: Checkout repo
+ - name: Checkout main repo
uses: actions/checkout@v4
+ - name: Checkout overrides repo
+ uses: actions/checkout@v4
+ with:
+ repository: scientific-witchery/pds-dash-overrides
+ token: ${{ secrets.OVERRIDES_TOKEN}}
+ path: overrides
+
+ - name: Copy config file to root
+ run: cp overrides/config.ts ./config.ts
+
- name: Setup Node.js
uses: actions/setup-node@v3
with:
diff --git a/.gitignore b/.gitignore
index 42a517f..991a625 100644
--- a/.gitignore
+++ b/.gitignore
@@ -149,4 +149,7 @@ dist
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
-.pnp.*
\ No newline at end of file
+.pnp.*
+
+# Config files
+config.ts
\ No newline at end of file
diff --git a/README.md b/README.md
index 25b3cfb..5fd9458 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,9 @@ a frontend dashboard with stats for your ATProto PDS.
### installing
-clone the repo, install dependencies using deno:
+clone the repo, copy `config.ts.example` to `config.ts` and edit it to your liking.
+
+then, install dependencies using deno:
```sh
deno install
@@ -44,14 +46,11 @@ we use our own CI/CD workflow at [`.forgejo/workflows/deploy.yaml`](.forgejo/wor
## theming
-currently the only way to theme the app is to edit css in the components directly, glhf
+themes are located in the `themes/` directory, you can create your own theme by copying one of the existing themes and modifying it to your liking.
-relevant files:
+currently, the name of the theme is determined by the directory name, and the theme itself is defined in `theme.css` inside that directory.
-- [`src/App.svelte`](src/App.svelte)
-- [`src/app.css`](src/app.css)
-- [`src/lib/AccountComponent.svelte`](src/lib/AccountComponent.svelte)
-- [`src/lib/PostComponent.svelte`](src/lib/PostComponent.svelte)
+you can switch themes by changing the `theme` property in `config.ts`.
the favicon is located at [`public/favicon.ico`](public/favicon.ico)
diff --git a/config.ts b/config.ts
deleted file mode 100644
index 0dc01b0..0000000
--- a/config.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Configuration module for the PDS Dashboard
- */
-export class Config {
- /**
- * The base URL of the PDS (Personal Data Server)
- * @default "https://pds.witchcraft.systems"
- */
- static readonly PDS_URL: string = "https://pds.witchcraft.systems";
-
- /**
- * The base URL of the frontend service for linking to replies/quotes/accounts etc.
- * @default "https://deer.social"
- */
- static readonly FRONTEND_URL: string = "https://deer.social";
-
- /**
- * Maximum number of posts to fetch from the PDS per request
- * Should be around 20 for about 10 users on the pds
- * The more users you have, the lower the number should be
- * since sorting is slow and is done on the frontend
- * @default 20
- */
- static readonly MAX_POSTS: number = 20;
-
- /**
- * Footer text for the dashboard
- * @default "Astrally projected from witchcraft.systems"
- */
- static readonly FOOTER_TEXT: string =
- "Astrally projected from witchcraft.systems";
-
- /**
- * Whether to show the posts that are in the future
- * @default false
- */
- static readonly SHOW_FUTURE_POSTS: boolean = false;
-}
diff --git a/config.ts.example b/config.ts.example
new file mode 100644
index 0000000..87894d3
--- /dev/null
+++ b/config.ts.example
@@ -0,0 +1,44 @@
+/**
+ * Configuration module for the PDS Dashboard
+ */
+export class Config {
+ /**
+ * The base URL of the PDS (Personal Data Server).
+ * @default none
+ */
+ static readonly PDS_URL: string = "";
+
+ /**
+ * Theme to be used
+ * @default "default"
+ */
+ static readonly THEME: string = "default";
+
+ /**
+ * The base URL of the frontend service for linking to replies/quotes/accounts etc.
+ * @default "https://deer.social" // or https://bsky.app if you're boring
+ */
+ static readonly FRONTEND_URL: string = "https://deer.social";
+
+ /**
+ * Maximum number of posts to fetch from the PDS per request
+ * Should be around 20 for about 10 users on the pds
+ * The more users you have, the lower the number should be
+ * since sorting is slow and is done on the frontend
+ * @default 20
+ */
+ static readonly MAX_POSTS: number = 20;
+
+ /**
+ * Footer text for the dashboard, you probably want to change this. Supports HTML.
+ * @default "Source (github mirror)"
+ */
+ static readonly FOOTER_TEXT: string =
+ "Source (github mirror)";
+
+ /**
+ * Whether to show the posts with timestamps that are in the future.
+ * @default false
+ */
+ static readonly SHOW_FUTURE_POSTS: boolean = false;
+}
diff --git a/deno.lock b/deno.lock
index 724a5c0..90a8393 100644
--- a/deno.lock
+++ b/deno.lock
@@ -1,5 +1,5 @@
{
- "version": "4",
+ "version": "5",
"specifiers": {
"npm:@atcute/bluesky@^2.0.2": "2.0.2_@atcute+client@3.0.1",
"npm:@atcute/client@^3.0.1": "3.0.1",
@@ -7,6 +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",
"npm:@tsconfig/svelte@^5.0.4": "5.0.4",
"npm:moment@^2.30.1": "2.30.1",
+ "npm:mutex-ts@^1.2.1": "1.2.1",
"npm:svelte-check@^4.1.5": "4.1.6_svelte@5.28.1__acorn@8.14.1_typescript@5.7.3",
"npm:svelte-infinite-loading@^1.4.0": "1.4.0",
"npm:svelte@^5.23.1": "5.28.1_acorn@8.14.1",
@@ -54,79 +55,129 @@
"integrity": "sha512-GEhUCk9c4XbNxi+0YZHZsV4fYNd6HejfWuN4Ti4c02DauX+LyX5WY1Y3WfyZ8Pxxl0zqhs+MLtW98cMh86vv6g=="
},
"@esbuild/aix-ppc64@0.25.2": {
- "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag=="
+ "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==",
+ "os": ["aix"],
+ "cpu": ["ppc64"]
},
"@esbuild/android-arm64@0.25.2": {
- "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w=="
+ "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==",
+ "os": ["android"],
+ "cpu": ["arm64"]
},
"@esbuild/android-arm@0.25.2": {
- "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA=="
+ "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==",
+ "os": ["android"],
+ "cpu": ["arm"]
},
"@esbuild/android-x64@0.25.2": {
- "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg=="
+ "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==",
+ "os": ["android"],
+ "cpu": ["x64"]
},
"@esbuild/darwin-arm64@0.25.2": {
- "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA=="
+ "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==",
+ "os": ["darwin"],
+ "cpu": ["arm64"]
},
"@esbuild/darwin-x64@0.25.2": {
- "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA=="
+ "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==",
+ "os": ["darwin"],
+ "cpu": ["x64"]
},
"@esbuild/freebsd-arm64@0.25.2": {
- "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w=="
+ "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==",
+ "os": ["freebsd"],
+ "cpu": ["arm64"]
},
"@esbuild/freebsd-x64@0.25.2": {
- "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ=="
+ "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==",
+ "os": ["freebsd"],
+ "cpu": ["x64"]
},
"@esbuild/linux-arm64@0.25.2": {
- "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g=="
+ "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==",
+ "os": ["linux"],
+ "cpu": ["arm64"]
},
"@esbuild/linux-arm@0.25.2": {
- "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g=="
+ "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==",
+ "os": ["linux"],
+ "cpu": ["arm"]
},
"@esbuild/linux-ia32@0.25.2": {
- "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ=="
+ "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==",
+ "os": ["linux"],
+ "cpu": ["ia32"]
},
"@esbuild/linux-loong64@0.25.2": {
- "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w=="
+ "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==",
+ "os": ["linux"],
+ "cpu": ["loong64"]
},
"@esbuild/linux-mips64el@0.25.2": {
- "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q=="
+ "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==",
+ "os": ["linux"],
+ "cpu": ["mips64el"]
},
"@esbuild/linux-ppc64@0.25.2": {
- "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g=="
+ "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==",
+ "os": ["linux"],
+ "cpu": ["ppc64"]
},
"@esbuild/linux-riscv64@0.25.2": {
- "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw=="
+ "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==",
+ "os": ["linux"],
+ "cpu": ["riscv64"]
},
"@esbuild/linux-s390x@0.25.2": {
- "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q=="
+ "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==",
+ "os": ["linux"],
+ "cpu": ["s390x"]
},
"@esbuild/linux-x64@0.25.2": {
- "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg=="
+ "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==",
+ "os": ["linux"],
+ "cpu": ["x64"]
},
"@esbuild/netbsd-arm64@0.25.2": {
- "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw=="
+ "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==",
+ "os": ["netbsd"],
+ "cpu": ["arm64"]
},
"@esbuild/netbsd-x64@0.25.2": {
- "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg=="
+ "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==",
+ "os": ["netbsd"],
+ "cpu": ["x64"]
},
"@esbuild/openbsd-arm64@0.25.2": {
- "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg=="
+ "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==",
+ "os": ["openbsd"],
+ "cpu": ["arm64"]
},
"@esbuild/openbsd-x64@0.25.2": {
- "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw=="
+ "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==",
+ "os": ["openbsd"],
+ "cpu": ["x64"]
},
"@esbuild/sunos-x64@0.25.2": {
- "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA=="
+ "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==",
+ "os": ["sunos"],
+ "cpu": ["x64"]
},
"@esbuild/win32-arm64@0.25.2": {
- "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q=="
+ "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==",
+ "os": ["win32"],
+ "cpu": ["arm64"]
},
"@esbuild/win32-ia32@0.25.2": {
- "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg=="
+ "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==",
+ "os": ["win32"],
+ "cpu": ["ia32"]
},
"@esbuild/win32-x64@0.25.2": {
- "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA=="
+ "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==",
+ "os": ["win32"],
+ "cpu": ["x64"]
},
"@jridgewell/gen-mapping@0.3.8": {
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
@@ -153,64 +204,104 @@
]
},
"@rollup/rollup-android-arm-eabi@4.40.0": {
- "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg=="
+ "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==",
+ "os": ["android"],
+ "cpu": ["arm"]
},
"@rollup/rollup-android-arm64@4.40.0": {
- "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w=="
+ "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==",
+ "os": ["android"],
+ "cpu": ["arm64"]
},
"@rollup/rollup-darwin-arm64@4.40.0": {
- "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ=="
+ "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==",
+ "os": ["darwin"],
+ "cpu": ["arm64"]
},
"@rollup/rollup-darwin-x64@4.40.0": {
- "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA=="
+ "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==",
+ "os": ["darwin"],
+ "cpu": ["x64"]
},
"@rollup/rollup-freebsd-arm64@4.40.0": {
- "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg=="
+ "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==",
+ "os": ["freebsd"],
+ "cpu": ["arm64"]
},
"@rollup/rollup-freebsd-x64@4.40.0": {
- "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw=="
+ "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==",
+ "os": ["freebsd"],
+ "cpu": ["x64"]
},
"@rollup/rollup-linux-arm-gnueabihf@4.40.0": {
- "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA=="
+ "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==",
+ "os": ["linux"],
+ "cpu": ["arm"]
},
"@rollup/rollup-linux-arm-musleabihf@4.40.0": {
- "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg=="
+ "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==",
+ "os": ["linux"],
+ "cpu": ["arm"]
},
"@rollup/rollup-linux-arm64-gnu@4.40.0": {
- "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg=="
+ "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==",
+ "os": ["linux"],
+ "cpu": ["arm64"]
},
"@rollup/rollup-linux-arm64-musl@4.40.0": {
- "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ=="
+ "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==",
+ "os": ["linux"],
+ "cpu": ["arm64"]
},
"@rollup/rollup-linux-loongarch64-gnu@4.40.0": {
- "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg=="
+ "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==",
+ "os": ["linux"],
+ "cpu": ["loong64"]
},
"@rollup/rollup-linux-powerpc64le-gnu@4.40.0": {
- "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw=="
+ "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==",
+ "os": ["linux"],
+ "cpu": ["ppc64"]
},
"@rollup/rollup-linux-riscv64-gnu@4.40.0": {
- "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA=="
+ "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==",
+ "os": ["linux"],
+ "cpu": ["riscv64"]
},
"@rollup/rollup-linux-riscv64-musl@4.40.0": {
- "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ=="
+ "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==",
+ "os": ["linux"],
+ "cpu": ["riscv64"]
},
"@rollup/rollup-linux-s390x-gnu@4.40.0": {
- "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw=="
+ "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==",
+ "os": ["linux"],
+ "cpu": ["s390x"]
},
"@rollup/rollup-linux-x64-gnu@4.40.0": {
- "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ=="
+ "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==",
+ "os": ["linux"],
+ "cpu": ["x64"]
},
"@rollup/rollup-linux-x64-musl@4.40.0": {
- "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw=="
+ "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==",
+ "os": ["linux"],
+ "cpu": ["x64"]
},
"@rollup/rollup-win32-arm64-msvc@4.40.0": {
- "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ=="
+ "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==",
+ "os": ["win32"],
+ "cpu": ["arm64"]
},
"@rollup/rollup-win32-ia32-msvc@4.40.0": {
- "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA=="
+ "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==",
+ "os": ["win32"],
+ "cpu": ["ia32"]
},
"@rollup/rollup-win32-x64-msvc@4.40.0": {
- "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ=="
+ "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==",
+ "os": ["win32"],
+ "cpu": ["x64"]
},
"@sveltejs/acorn-typescript@1.0.5_acorn@8.14.1": {
"integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==",
@@ -247,7 +338,8 @@
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ=="
},
"acorn@8.14.1": {
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="
+ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "bin": true
},
"aria-query@5.3.2": {
"integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="
@@ -275,7 +367,7 @@
},
"esbuild@0.25.2": {
"integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==",
- "dependencies": [
+ "optionalDependencies": [
"@esbuild/aix-ppc64",
"@esbuild/android-arm",
"@esbuild/android-arm64",
@@ -301,7 +393,9 @@
"@esbuild/win32-arm64",
"@esbuild/win32-ia32",
"@esbuild/win32-x64"
- ]
+ ],
+ "scripts": true,
+ "bin": true
},
"esm-env@1.2.2": {
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="
@@ -316,10 +410,15 @@
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
"dependencies": [
"picomatch"
+ ],
+ "optionalPeers": [
+ "picomatch"
]
},
"fsevents@2.3.3": {
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "os": ["darwin"],
+ "scripts": true
},
"is-reference@3.0.3": {
"integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==",
@@ -348,8 +447,12 @@
"ms@2.1.3": {
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
+ "mutex-ts@1.2.1": {
+ "integrity": "sha512-OkcXgf0viuCgYdnm48kiNQ9PzC5OzISQ261svHr/Ybc2vBYC/5xfLXn44hQ+dYRX74v7MCSqV/LKPEbpYdDybw=="
+ },
"nanoid@3.3.11": {
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "bin": true
},
"picocolors@1.1.1": {
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
@@ -371,6 +474,9 @@
"rollup@4.40.0": {
"integrity": "sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w==",
"dependencies": [
+ "@types/estree"
+ ],
+ "optionalDependencies": [
"@rollup/rollup-android-arm-eabi",
"@rollup/rollup-android-arm64",
"@rollup/rollup-darwin-arm64",
@@ -391,9 +497,9 @@
"@rollup/rollup-win32-arm64-msvc",
"@rollup/rollup-win32-ia32-msvc",
"@rollup/rollup-win32-x64-msvc",
- "@types/estree",
"fsevents"
- ]
+ ],
+ "bin": true
},
"sade@1.8.1": {
"integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==",
@@ -414,7 +520,8 @@
"sade",
"svelte",
"typescript"
- ]
+ ],
+ "bin": true
},
"svelte-infinite-loading@1.4.0": {
"integrity": "sha512-Jo+f/yr/HmZQuIiiKKzAHVFXdAUWHW2RBbrcQTil8JVk1sCm/riy7KTJVzjBgQvHasrFQYKF84zvtc9/Y4lFYg=="
@@ -446,24 +553,31 @@
]
},
"typescript@5.7.3": {
- "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="
+ "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
+ "bin": true
},
"vite@6.3.2_picomatch@4.0.2": {
"integrity": "sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==",
"dependencies": [
"esbuild",
"fdir",
- "fsevents",
"picomatch",
"postcss",
"rollup",
"tinyglobby"
- ]
+ ],
+ "optionalDependencies": [
+ "fsevents"
+ ],
+ "bin": true
},
"vitefu@1.0.6_vite@6.3.2__picomatch@4.0.2": {
"integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==",
"dependencies": [
"vite"
+ ],
+ "optionalPeers": [
+ "vite"
]
},
"zimmerframe@1.1.2": {
@@ -479,6 +593,7 @@
"npm:@sveltejs/vite-plugin-svelte@^5.0.3",
"npm:@tsconfig/svelte@^5.0.4",
"npm:moment@^2.30.1",
+ "npm:mutex-ts@^1.2.1",
"npm:svelte-check@^4.1.5",
"npm:svelte-infinite-loading@^1.4.0",
"npm:svelte@^5.23.1",
diff --git a/package.json b/package.json
index 1db6461..3b293c0 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
"@atcute/client": "^3.0.1",
"@atcute/identity-resolver": "^0.1.2",
"moment": "^2.30.1",
+ "mutex-ts": "^1.2.1",
"svelte-infinite-loading": "^1.4.0"
},
"devDependencies": {
diff --git a/src/App.svelte b/src/App.svelte
index 9e36d30..798b8a7 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -9,6 +9,26 @@
let posts: Post[] = [];
+ let hue: number = 1;
+ const cycleColors = async () => {
+ while (true) {
+ hue += 1;
+ if (hue > 360) {
+ hue = 0;
+ }
+ document.documentElement.style.setProperty("--primary-h", hue.toString());
+ await new Promise((resolve) => setTimeout(resolve, 10));
+ }
+ }
+ let clickCounter = 0;
+ const carameldansenfusion = async () => {
+ clickCounter++;
+ if (clickCounter >= 10) {
+ clickCounter = 0;
+ cycleColors();
+ }
+ };
+
onMount(() => {
// Fetch initial posts
getNextPosts().then((initialPosts) => {
@@ -16,7 +36,11 @@
});
});
// Infinite loading function
- const onInfinite = ({ detail: { loaded, complete } } : { detail : { loaded : () => void, complete : () => void}}) => {
+ const onInfinite = ({
+ detail: { loaded, complete },
+ }: {
+ detail: { loaded: () => void; complete: () => void };
+ }) => {
getNextPosts().then((newPosts) => {
console.log("Loading next posts...");
if (newPosts.length > 0) {
@@ -35,7 +59,7 @@
Loading...
{:then accountsData}
-
+
Home to {accountsData.length} accounts
{#each accountsData as accountObject}
@@ -53,99 +77,12 @@
{#each posts as postObject}
{/each}
-
+
diff --git a/src/app.css b/src/app.css
index 4c343e2..cb315e4 100644
--- a/src/app.css
+++ b/src/app.css
@@ -1,83 +1,4 @@
-@font-face {
- font-family: "ProggyClean";
- 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;
- padding: 0;
- margin: 0;
-}
-::-webkit-scrollbar-thumb {
- background: transparent;
- border-radius: 0;
-}
-::-webkit-scrollbar-track {
- background: transparent;
- border-radius: 0;
-}
-::-webkit-scrollbar-corner {
- background: transparent;
- border-radius: 0;
-}
-::-webkit-scrollbar-button {
- background: transparent;
- border-radius: 0;
-}
-* {
- scrollbar-width: none;
- scrollbar-color: transparent transparent;
- -ms-overflow-style: none; /* IE and Edge */
- -webkit-overflow-scrolling: touch;
- -webkit-scrollbar: none; /* Safari */
-}
-
-a {
- font-weight: 500;
- color: var(--link-color);
- text-decoration: inherit;
-}
-a:hover {
- color: var(--link-hover-color);
- text-decoration: underline;
-}
-
+@import url('./themes/colors.css');
body {
- margin: 0;
- display: flex;
- place-items: center;
- min-width: 320px;
- min-height: 100vh;
- background-color: var(--background-color);
- font-family: "ProggyClean", monospace;
- font-size: 24px;
- color: var(--text-color);
- border-color: var(--border-color);
-}
-
-h1 {
- font-size: 3.2em;
- line-height: 1.1;
-}
-
-#app {
- max-width: 1400px;
- margin: 0;
- padding: 0;
- margin-left: auto;
- margin-right: auto;
- text-align: center;
-}
+ background-color: red;
+}
\ No newline at end of file
diff --git a/src/lib/AccountComponent.svelte b/src/lib/AccountComponent.svelte
index e324393..faf6251 100644
--- a/src/lib/AccountComponent.svelte
+++ b/src/lib/AccountComponent.svelte
@@ -12,37 +12,17 @@
alt="avatar of {account.displayName}"
src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={account.did}&cid={account.avatarCid}"
/>
+
+ {account.displayName || account.handle || account.did}
+
+ {:else}
+
+ {account.displayName || account.handle || account.did}
+
{/if}
-
- {account.displayName || account.handle || account.did}
-
diff --git a/src/lib/PostComponent.svelte b/src/lib/PostComponent.svelte
index 3c4178c..1cacc28 100644
--- a/src/lib/PostComponent.svelte
+++ b/src/lib/PostComponent.svelte
@@ -71,7 +71,7 @@
>
{post.authorHandle}@{post.authorHandle}
{/if}
+ {#if post.gifLink}
+
+ {/if}
diff --git a/src/lib/pdsfetch.ts b/src/lib/pdsfetch.ts
index 79edab0..d57aff4 100644
--- a/src/lib/pdsfetch.ts
+++ b/src/lib/pdsfetch.ts
@@ -13,6 +13,7 @@ import {
WebDidDocumentResolver,
} from "@atcute/identity-resolver";
import { Config } from "../../config";
+import { Mutex } from "mutex-ts"
// import { ComAtprotoRepoListRecords.Record } from "@atcute/client/lexicons";
// import { AppBskyFeedPost } from "@atcute/client/lexicons";
// import { AppBskyActorDefs } from "@atcute/client/lexicons";
@@ -46,6 +47,7 @@ class Post {
replyingUri: atUriObject | null;
imagesCid: string[] | null;
videosLinkCid: string | null;
+ gifLink: string | null;
constructor(
record: ComAtprotoRepoListRecords.Record,
@@ -69,6 +71,7 @@ class Post {
this.quotingUri = null;
this.imagesCid = null;
this.videosLinkCid = null;
+ this.gifLink = null;
switch (post.embed?.$type) {
case "app.bsky.embed.images":
this.imagesCid = post.embed.images.map(
@@ -96,6 +99,11 @@ class Post {
break;
}
break;
+ case "app.bsky.embed.external": // assuming that external embeds are gifs for now
+ if (post.embed.external.uri.includes(".gif")) {
+ this.gifLink = post.embed.external.uri;
+ }
+ break;
}
}
}
@@ -124,7 +132,13 @@ const getDidsFromPDS = async (): Promise => {
const getAccountMetadata = async (
did: `did:${string}:${string}`,
) => {
- // gonna assume self exists in the app.bsky.actor.profile
+ const account: AccountMetadata = {
+ did: did,
+ handle: "", // Guaranteed to be filled out later
+ displayName: "",
+ avatarCid: null,
+ };
+
try {
const { data } = await rpc.get("com.atproto.repo.getRecord", {
params: {
@@ -134,21 +148,22 @@ const getAccountMetadata = async (
},
});
const value = data.value as AppBskyActorProfile.Record;
- const handle = await blueskyHandleFromDid(did);
- const account: AccountMetadata = {
- did: did,
- handle: handle,
- displayName: value.displayName || "",
- avatarCid: null,
- };
+ account.displayName = value.displayName || "";
if (value.avatar) {
account.avatarCid = value.avatar.ref["$link"];
}
- return account;
} catch (e) {
- console.error(`Error fetching metadata for ${did}:`, e);
+ console.warn(`Error fetching profile for ${did}:`, e);
+ }
+
+ try {
+ account.handle = await blueskyHandleFromDid(did);
+ } catch (e) {
+ console.error(`Error fetching handle for ${did}:`, e);
return null;
}
+
+ return account;
};
const getAllMetadataFromPds = async (): Promise => {
@@ -240,8 +255,11 @@ const filterPostsByDate = (posts: PostsAcc[], cutoffDate: Date) => {
});
return filteredPosts;
};
+
+const postsMutex = new Mutex();
// nightmare function. However it works so I am not touching it
const getNextPosts = async () => {
+ const release = await postsMutex.obtain();
if (!accountsMetadata.length) {
accountsMetadata = await getAllMetadataFromPds();
}
@@ -315,6 +333,8 @@ const getNextPosts = async () => {
}
return new Post(record, account);
});
+ // release the mutex
+ release();
return newPosts;
};
diff --git a/themes/default/theme.css b/themes/default/theme.css
new file mode 100644
index 0000000..e4061ec
--- /dev/null
+++ b/themes/default/theme.css
@@ -0,0 +1,423 @@
+/* Modern Theme for pds-dash */
+
+:root {
+ /* Modern color palette */
+ --primary-h: 243;
+ --link-color: hsl(var(--primary-h), 73%, 59%);
+ --link-hover-color: #4338ca;
+ --time-color: #8b5cf6;
+ --background-color: #f8fafc;
+ --header-background-color: #ffffff;
+ --content-background-color: #ffffff;
+ --text-color: #111827;
+ --text-secondary-color: #4b5563;
+ --border-color: #e2e8f0;
+ --indicator-inactive-color: #cbd5e1;
+ --indicator-active-color: #6366f1;
+
+ /* Modern shadows */
+ --button-hover: #f3f4f6;
+}
+
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+ background-color: var(--background-color);
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;
+ font-size: 18px;
+ line-height: 1.5;
+ color: var(--text-color);
+ border-color: var(--border-color);
+ overflow-wrap: break-word;
+ word-break: break-word;
+ hyphens: none;
+}
+
+a {
+ font-weight: 500;
+ color: var(--link-color);
+ text-decoration: none;
+ transition: color 0.15s ease;
+}
+a:hover {
+ color: var(--link-hover-color);
+}
+
+h1 {
+ font-size: 2.5em;
+ line-height: 1.2;
+ font-weight: 700;
+}
+
+#app {
+ max-width: 1400px;
+ width: 100%;
+ margin: 0 auto;
+ padding: 0;
+ text-align: center;
+}
+
+/* Post Component */
+#postContainer {
+ display: flex;
+ flex-direction: column;
+ border-radius: 12px;
+ border: 1px solid var(--border-color);
+ background-color: var(--content-background-color);
+ margin-bottom: 20px;
+ overflow-wrap: break-word;
+ overflow: hidden;
+ box-shadow: var(--card-shadow);
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
+}
+
+#postContainer:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
+}
+
+#postHeader {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: start;
+ background-color: var(--header-background-color);
+ padding: 12px 16px;
+ height: 60px;
+ border-bottom: 1px solid var(--border-color);
+ font-weight: 600;
+ overflow-wrap: break-word;
+}
+
+#displayName {
+ display: block;
+ color: var(--text-color);
+ font-size: 1.1em;
+ padding: 0;
+ margin: 0 0 2px 0;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ width: 100%;
+ letter-spacing: -0.01em;
+}
+
+#handle {
+ display: flex;
+ align-items: center;
+ color: #6b7280;
+ font-size: 0.85em;
+ font-weight: 400;
+ padding: 0;
+ margin: 0;
+ gap: 8px;
+}
+
+#postLink {
+ color: var(--time-color);
+ font-size: 0.85em;
+ padding: 0;
+ margin: 0;
+ opacity: 0.9;
+}
+
+#postContent {
+ display: flex;
+ text-align: start;
+ flex-direction: column;
+ padding: 16px;
+ background-color: var(--content-background-color);
+ color: var(--text-color);
+ overflow-wrap: break-word;
+ white-space: pre-line;
+ line-height: 1.6;
+}
+
+#replyingText, #quotingText {
+ font-size: 0.8em;
+ margin: 0;
+ padding: 0 0 10px 0;
+ color: #6b7280;
+}
+
+#postText {
+ margin: 0 0 8px 0;
+ padding: 0;
+ overflow-wrap: break-word;
+ word-break: break-word;
+ hyphens: none;
+ font-size: 1.05em;
+}
+
+#headerText {
+ margin-left: 12px;
+ font-size: 0.9em;
+ text-align: start;
+ word-break: break-word;
+ max-width: 80%;
+ max-height: 95%;
+ overflow: hidden;
+ align-self: flex-start;
+ margin-top: auto;
+ margin-bottom: auto;
+}
+
+#carouselContainer {
+ position: relative;
+ width: 100%;
+ margin-top: 12px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+#carouselControls {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+ max-width: 500px;
+ margin-top: 10px;
+}
+
+#carouselIndicators {
+ display: flex;
+ gap: 6px;
+}
+
+.indicator {
+ width: 6px;
+ height: 6px;
+ background-color: var(--indicator-inactive-color);
+ border-radius: 50%;
+ transition: background-color 0.2s ease, transform 0.2s ease;
+}
+
+.indicator.active {
+ background-color: var(--indicator-active-color);
+ transform: scale(1.3);
+}
+
+#prevBtn,
+#nextBtn {
+ background-color: var(--button-bg);
+ color: var(--text-color);
+ border: 1px solid var(--border-color);
+ width: 32px;
+ height: 32px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ transition: background-color 0.15s ease, transform 0.15s ease;
+ font-size: 16px;
+}
+
+#prevBtn:hover:not(:disabled),
+#nextBtn:hover:not(:disabled) {
+ background-color: var(--button-hover);
+ transform: scale(1.05);
+}
+
+#prevBtn:disabled,
+#nextBtn:disabled {
+ opacity: 0.4;
+ cursor: not-allowed;
+}
+
+#embedVideo {
+ width: 100%;
+ max-width: 500px;
+ margin-top: 12px;
+ align-self: center;
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+#embedImages {
+ min-width: min(100%, 500px);
+ max-width: min(100%, 500px);
+ max-height: 500px;
+ object-fit: contain;
+ margin: 0;
+ border-radius: 8px;
+}
+
+/* Account Component */
+#accountContainer {
+ display: flex;
+ text-align: start;
+ align-items: center;
+ background-color: var(--content-background-color);
+ padding: 12px;
+ margin-bottom: 15px;
+ border: 1px solid var(--border-color);
+ border-radius: 12px;
+ transition: background-color 0.15s ease;
+}
+
+#accountContainer:hover {
+ background-color: var(--hover-bg);
+}
+
+#accountName {
+ margin-left: 12px;
+ font-size: 0.95em;
+ max-width: 80%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-weight: 500;
+}
+
+#avatar {
+ width: 48px;
+ height: 48px;
+ margin: 0;
+ object-fit: cover;
+ border-radius: 50%;
+ border: 2px solid white;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+}
+
+/* App.Svelte Layout */
+#Content {
+ display: flex;
+ width: 100%;
+ height: 100%;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ background-color: var(--background-color);
+ color: var(--text-color);
+ gap: 24px;
+}
+
+#Feed {
+ overflow-y: auto;
+ width: 65%;
+ height: 100vh;
+ padding-right: 16px;
+ align-self: flex-start;
+}
+
+#spacer {
+ padding: 0;
+ margin: 0;
+ height: 10vh;
+ width: 100%;
+}
+
+#Account {
+ width: 35%;
+ display: flex;
+ flex-direction: column;
+ border: 1px solid var(--border-color);
+ background-color: var(--content-background-color);
+ max-height: 80vh;
+ padding: 24px;
+ margin-left: 16px;
+ border-radius: 12px;
+ box-shadow: var(--card-shadow);
+}
+
+#accountsList {
+ display: flex;
+ flex-direction: column;
+ overflow-y: auto;
+ height: 100%;
+ width: 100%;
+ padding: 8px 0;
+ margin: 0;
+}
+
+#Header {
+ text-align: center;
+ font-size: 1.8em;
+ margin-bottom: 16px;
+ font-weight: 700;
+ background: linear-gradient(to right, var(--link-color), #8b5cf6);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ background-clip: text;
+}
+
+/* Mobile Styles */
+@media screen and (max-width: 768px) {
+ #Content {
+ flex-direction: column;
+ width: auto;
+ padding: 12px;
+ margin-top: 0;
+ }
+
+ #Account {
+ width: calc(100% - 32px);
+ padding: 16px;
+ margin-bottom: 20px;
+ margin-left: 0;
+ margin-right: 0;
+ height: auto;
+ order: -1;
+ }
+
+ #Feed {
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ overflow-y: visible;
+ }
+
+ #spacer {
+ height: 5vh;
+ }
+
+ body {
+ font-size: 16px;
+ }
+
+ #postHeader {
+ padding: 10px;
+ height: auto;
+ min-height: 50px;
+ }
+}
+
+/* Scrollbar Styles */
+::-webkit-scrollbar {
+ width: 0px;
+ background: transparent;
+ padding: 0;
+ margin: 0;
+}
+::-webkit-scrollbar-thumb {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-track {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-corner {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-button {
+ background: transparent;
+ border-radius: 0;
+}
+
+* {
+ scrollbar-width: none;
+ scrollbar-color: transparent transparent;
+ -ms-overflow-style: none; /* IE and Edge */
+ -webkit-overflow-scrolling: touch;
+ -webkit-scrollbar: none; /* Safari */
+}
\ No newline at end of file
diff --git a/themes/express/theme.css b/themes/express/theme.css
new file mode 100644
index 0000000..58c399e
--- /dev/null
+++ b/themes/express/theme.css
@@ -0,0 +1,375 @@
+@import url("https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap");
+
+:root {
+ /* Color overrides, edit to whatever you want */
+ --primary-h: 341; /* Hue */
+ --background-color: hsl(var(--primary-h), 62%, 30%);
+ --text-color: hsl(var(--primary-h), 69%, 18%);
+ --link-color: hsl(var(--primary-h), 100%, 20%);
+ --link-hover-color: hsl(var(--primary-h), 20%, 20%);
+ --border-color: hsl(var(--primary-h), 59%, 52%);
+ --content-background-color: hsl(var(--primary-h), 97%, 73%);
+
+ --header-background-color: hsl(var(--primary-h), 97%, 73%);
+ --indicator-inactive-color: #4a4a4a;
+ --indicator-active-color: var(--border-color);
+}
+
+a {
+ font-weight: 500;
+ color: var(--link-color);
+ text-decoration: inherit;
+}
+a:hover {
+ color: var(--link-hover-color);
+ text-decoration: underline;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+ background-color: var(--background-color);
+ font-family: "Share Tech Mono", monospace;
+ font-size: 24px;
+ color: var(--text-color);
+ border-color: var(--border-color);
+ overflow-wrap: break-word;
+ word-wrap: normal;
+ word-break: break-word;
+ hyphens: none;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+#app {
+ max-width: 1400px;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: center;
+}
+
+/* Post Component */
+a:hover {
+ text-decoration: underline;
+}
+#postContainer {
+ display: flex;
+ flex-direction: column;
+ border: 4px solid var(--border-color);
+ background-color: var(--background-color);
+ margin-bottom: 15px;
+ overflow-wrap: break-word;
+ box-shadow: var(--border-color) 10px 10px;
+}
+#postHeader {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: start;
+ background-color: var(--header-background-color);
+ padding: 0px 0px;
+ height: fit-content;
+
+ font-weight: bold;
+ overflow-wrap: break-word;
+ height: 64px;
+}
+#displayName {
+ display: block;
+ color: var(--text-color);
+ font-size: 1.2em;
+ padding: 0;
+ margin: 0;
+ overflow-wrap: normal;
+ word-wrap: break-word;
+ word-break: break-word;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ width: 100%;
+}
+#handle {
+ display: block;
+ color: var(--border-color);
+ font-size: 0.8em;
+ padding: 0;
+ margin: 0;
+}
+
+#postLink {
+ color: var(--link-hover-color);
+ font-size: 0.8em;
+ padding: 0;
+ margin: 0;
+}
+#postContent {
+ display: flex;
+ text-align: start;
+ flex-direction: column;
+ padding: 10px;
+ background-color: var(--content-background-color);
+ color: var(--text-color);
+ overflow-wrap: break-word;
+ white-space: pre-line;
+}
+#replyingText {
+ font-size: 0.7em;
+ margin: 0;
+ padding: 0;
+ padding-bottom: 5px;
+}
+#quotingText {
+ font-size: 0.7em;
+ margin: 0;
+ padding: 0;
+ padding-bottom: 5px;
+}
+#postText {
+ margin: 0;
+ padding: 0;
+ overflow-wrap: break-word;
+ word-wrap: normal;
+ word-break: break-word;
+ hyphens: none;
+}
+#headerText {
+ margin-left: 10px;
+ font-size: 0.9em;
+ text-align: start;
+ word-break: break-word;
+ max-width: 80%;
+ max-height: 95%;
+ overflow: hidden;
+ align-self: flex-start;
+ margin-top: auto;
+ margin-bottom: auto;
+}
+#avatar {
+ height: 30px;
+ width: 30px;
+ overflow: hidden;
+ object-fit: cover;
+}
+#postContainer #avatar {
+ height: 60px;
+ width: 60px;
+ border-right: var(--border-color) 4px solid;
+ border-bottom: var(--border-color) 4px solid;
+}
+#carouselContainer {
+ position: relative;
+ width: 100%;
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+#carouselControls {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+ max-width: 500px;
+ margin-top: 5px;
+}
+#carouselIndicators {
+ display: flex;
+ gap: 5px;
+}
+.indicator {
+ width: 8px;
+ height: 8px;
+ background-color: var(--indicator-inactive-color);
+}
+.indicator.active {
+ background-color: var(--indicator-active-color);
+}
+#prevBtn,
+#nextBtn {
+ background-color: rgba(31, 17, 69, 0.7);
+ color: var(--text-color);
+ border: 4px solid var(--border-color);
+ width: 30px;
+ height: 30px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+#prevBtn:disabled,
+#nextBtn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+#embedVideo {
+ width: 100%;
+ max-width: 500px;
+ margin-top: 10px;
+ align-self: center;
+}
+
+#embedImages {
+ min-width: min(100%, 500px);
+ max-width: min(100%, 500px);
+ max-height: 500px;
+ object-fit: contain;
+
+ margin: 0;
+}
+
+/* Account Component */
+#accountContainer {
+ display: flex;
+ text-align: start;
+ align-items: center;
+ background-color: var(--header-background-color);
+ padding: 0px;
+ margin-bottom: 15px;
+ margin-right: 4px;
+ border: 4px solid var(--border-color);
+ box-shadow: var(--border-color) 10px 10px;
+ min-height: 30px;
+}
+#accountName {
+ margin-left: 10px;
+ font-size: 1em;
+ max-width: 80%;
+
+ /* replace overflow with ellipsis */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.no-avatar {
+ margin-left: 40px !important;
+}
+
+/* App.Svelte */
+/* desktop style */
+
+#Content {
+ display: flex;
+ /* split the screen in half, left for accounts, right for posts */
+ width: 100%;
+ height: 100%;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ background-color: var(--background-color);
+ color: var(--text-color);
+}
+#Feed {
+ overflow-y: scroll;
+ width: 65%;
+ height: 100vh;
+ padding: 20px;
+ padding-bottom: 0;
+ padding-top: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+#spacer {
+ padding: 0;
+ margin: 0;
+ height: 10vh;
+ width: 100%;
+}
+#Account {
+ width: 35%;
+ display: flex;
+ flex-direction: column;
+ border: 4px solid var(--border-color);
+ background-color: var(--content-background-color);
+ box-shadow: var(--border-color) 10px 10px;
+ height: 80vh;
+ padding: 20px;
+ margin-left: 20px;
+}
+#accountsList {
+ display: flex;
+ flex-direction: column;
+ overflow-y: scroll;
+ height: 100%;
+ width: 100%;
+ padding: 0px;
+ margin: 0px;
+}
+
+#Header {
+ text-align: center;
+ font-size: 2em;
+ margin-bottom: 20px;
+}
+
+/* mobile style */
+@media screen and (max-width: 600px) {
+ #Content {
+ flex-direction: column;
+ width: auto;
+ padding-left: 0px;
+ padding-right: 0px;
+ margin-top: 5%;
+ }
+ #Account {
+ width: 85%;
+ padding-left: 5%;
+ padding-right: 5%;
+ margin-bottom: 20px;
+ margin-left: 5%;
+ margin-right: 5%;
+ height: auto;
+ }
+ #Feed {
+ width: 95%;
+ margin: 0px;
+ margin-left: 10%;
+ margin-right: 10%;
+ padding: 0px;
+ overflow-y: visible;
+ }
+
+ #spacer {
+ height: 0;
+ }
+}
+
+::-webkit-scrollbar {
+ width: 0px;
+ background: transparent;
+ padding: 0;
+ margin: 0;
+}
+::-webkit-scrollbar-thumb {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-track {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-corner {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-button {
+ background: transparent;
+ border-radius: 0;
+}
+
+* {
+ scrollbar-width: none;
+ scrollbar-color: transparent transparent;
+ -ms-overflow-style: none; /* IE and Edge */
+ -webkit-overflow-scrolling: touch;
+ -webkit-scrollbar: none; /* Safari */
+}
diff --git a/themes/witchcraft/theme.css b/themes/witchcraft/theme.css
new file mode 100644
index 0000000..8ad63d4
--- /dev/null
+++ b/themes/witchcraft/theme.css
@@ -0,0 +1,373 @@
+@font-face {
+ font-family: "ProggyClean";
+ src: url(https://witchcraft.systems/ProggyCleanNerdFont-Regular.ttf);
+}
+
+:root {
+ /* Color overrides, edit to whatever you want */
+ --primary-h: 260; /* Hue */
+
+ --link-color: hsl(calc(var(--primary-h) - 30), 75%, 60%);
+ --link-hover-color: hsl(calc(var(--primary-h) - 30), 75%, 50%);
+ --background-color: hsl(var(--primary-h), 75%, 10%);
+ --header-background-color: hsl(var(--primary-h), 75%, 18%);
+ --content-background-color: hsl(var(--primary-h), 75%, 8%);
+ --text-color: #fff;
+ --border-color: hsl(var(--primary-h), 75%, 60%);
+ --indicator-inactive-color: #4a4a4a;
+ --indicator-active-color: var(--border-color);
+}
+
+
+a {
+ font-weight: 500;
+ color: var(--link-color);
+ text-decoration: inherit;
+}
+a:hover {
+ color: var(--link-hover-color);
+ text-decoration: underline;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+ background-color: var(--background-color);
+ font-family: "ProggyClean", monospace;
+ font-size: 24px;
+ color: var(--text-color);
+ border-color: var(--border-color);
+ overflow-wrap: break-word;
+ word-wrap: normal;
+ word-break: break-word;
+ hyphens: none;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+#app {
+ max-width: 1400px;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: center;
+}
+
+/* Post Component */
+a:hover {
+ text-decoration: underline;
+}
+#postContainer {
+ display: flex;
+ flex-direction: column;
+ border: 1px solid var(--border-color);
+ background-color: var(--background-color);
+ margin-bottom: 15px;
+ overflow-wrap: break-word;
+}
+#postHeader {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: start;
+ background-color: var(--header-background-color);
+ padding: 0px 0px;
+ height: fit-content;
+ border-bottom: 1px solid var(--border-color);
+ font-weight: bold;
+ overflow-wrap: break-word;
+ height: 60px;
+}
+#displayName {
+ display: block;
+ color: var(--text-color);
+ font-size: 1.2em;
+ padding: 0;
+ margin: 0;
+ overflow-wrap: normal;
+ word-wrap: break-word;
+ word-break: break-word;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+ width: 100%;
+}
+#handle {
+ display: block;
+ color: var(--border-color);
+ font-size: 0.8em;
+ padding: 0;
+ margin: 0;
+}
+
+#postLink {
+ color: var(--border-color);
+ font-size: 0.8em;
+ padding: 0;
+ margin: 0;
+}
+#postContent {
+ display: flex;
+ text-align: start;
+ flex-direction: column;
+ padding: 10px;
+ background-color: var(--content-background-color);
+ color: var(--text-color);
+ overflow-wrap: break-word;
+ white-space: pre-line;
+}
+#replyingText {
+ font-size: 0.7em;
+ margin: 0;
+ padding: 0;
+ padding-bottom: 5px;
+}
+#quotingText {
+ font-size: 0.7em;
+ margin: 0;
+ padding: 0;
+ padding-bottom: 5px;
+}
+#postText {
+ margin: 0;
+ padding: 0;
+ overflow-wrap: break-word;
+ word-wrap: normal;
+ word-break: break-word;
+ hyphens: none;
+}
+#headerText {
+ margin-left: 10px;
+ font-size: 0.9em;
+ text-align: start;
+ word-break: break-word;
+ max-width: 80%;
+ max-height: 95%;
+ overflow: hidden;
+ align-self: flex-start;
+ margin-top: auto;
+ margin-bottom: auto;
+}
+#avatar {
+ height: 60px;
+ width: 60px;
+ margin: 0px;
+ margin-left: 0px;
+ overflow: hidden;
+ object-fit: cover;
+ border-right: var(--border-color) 1px solid;
+}
+#carouselContainer {
+ position: relative;
+ width: 100%;
+ margin-top: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+#carouselControls {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+ max-width: 500px;
+ margin-top: 5px;
+}
+#carouselIndicators {
+ display: flex;
+ gap: 5px;
+}
+.indicator {
+ width: 8px;
+ height: 8px;
+ background-color: var(--indicator-inactive-color);
+}
+.indicator.active {
+ background-color: var(--indicator-active-color);
+}
+#prevBtn,
+#nextBtn {
+ background-color: rgba(31, 17, 69, 0.7);
+ color: var(--text-color);
+ border: 1px solid var(--border-color);
+ width: 30px;
+ height: 30px;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+#prevBtn:disabled,
+#nextBtn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+#embedVideo {
+ width: 100%;
+ max-width: 500px;
+ margin-top: 10px;
+ align-self: center;
+}
+
+#embedImages {
+ min-width: min(100%, 500px);
+ max-width: min(100%, 500px);
+ max-height: 500px;
+ object-fit: contain;
+
+ margin: 0;
+}
+
+/* Account Component */
+#accountContainer {
+ display: flex;
+ text-align: start;
+ align-items: center;
+ background-color: var(--background-color);
+ padding: 0px;
+ margin-bottom: 15px;
+ border: 1px solid var(--border-color);
+ min-height: 30px;
+}
+#accountName {
+ margin-left: 10px;
+ font-size: 1em;
+ max-width: 80%;
+
+ /* replace overflow with ellipsis */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+
+.no-avatar {
+ margin-left: 70px !important;
+}
+
+/* App.Svelte */
+/* desktop style */
+
+#Content {
+ display: flex;
+ /* split the screen in half, left for accounts, right for posts */
+ width: 100%;
+ height: 100%;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ background-color: var(--background-color);
+ color: var(--text-color);
+}
+#Feed {
+ overflow-y: scroll;
+ width: 65%;
+ height: 100vh;
+ padding: 20px;
+ padding-bottom: 0;
+ padding-top: 0;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+#spacer {
+ padding: 0;
+ margin: 0;
+ height: 10vh;
+ width: 100%;
+}
+#Account {
+ width: 35%;
+ display: flex;
+ flex-direction: column;
+ border: 1px solid var(--border-color);
+ background-color: var(--content-background-color);
+ height: 80vh;
+ padding: 20px;
+ margin-left: 20px;
+}
+#accountsList {
+ display: flex;
+ flex-direction: column;
+ overflow-y: scroll;
+ height: 100%;
+ width: 100%;
+ padding: 0px;
+ margin: 0px;
+}
+
+#Header {
+ text-align: center;
+ font-size: 2em;
+ margin-bottom: 20px;
+}
+
+/* mobile style */
+@media screen and (max-width: 600px) {
+ #Content {
+ flex-direction: column;
+ width: auto;
+ padding-left: 0px;
+ padding-right: 0px;
+ margin-top: 5%;
+ }
+ #Account {
+ width: 85%;
+ padding-left: 5%;
+ padding-right: 5%;
+ margin-bottom: 20px;
+ margin-left: 5%;
+ margin-right: 5%;
+ height: auto;
+ }
+ #Feed {
+ width: 95%;
+ margin: 0px;
+ margin-left: 10%;
+ margin-right: 10%;
+ padding: 0px;
+ overflow-y: visible;
+ }
+
+ #spacer {
+ height: 0;
+ }
+}
+
+::-webkit-scrollbar {
+ width: 0px;
+ background: transparent;
+ padding: 0;
+ margin: 0;
+}
+::-webkit-scrollbar-thumb {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-track {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-corner {
+ background: transparent;
+ border-radius: 0;
+}
+::-webkit-scrollbar-button {
+ background: transparent;
+ border-radius: 0;
+}
+
+* {
+ scrollbar-width: none;
+ scrollbar-color: transparent transparent;
+ -ms-overflow-style: none; /* IE and Edge */
+ -webkit-overflow-scrolling: touch;
+ -webkit-scrollbar: none; /* Safari */
+}
\ No newline at end of file
diff --git a/theming.ts b/theming.ts
new file mode 100644
index 0000000..3b5964b
--- /dev/null
+++ b/theming.ts
@@ -0,0 +1,32 @@
+import { Plugin } from 'vite';
+import { Config } from './config';
+
+
+// Replaces app.css with the contents of the file specified in the
+// config file.
+export const themePlugin = (): Plugin => {
+ const themeFolder = Config.THEME;
+ console.log(`Using theme folder: ${themeFolder}`);
+ return {
+ name: 'theme-generator',
+ enforce: 'pre', // Ensure this plugin runs first
+ transform(code, id) {
+ if (id.endsWith('app.css')) {
+ // Read the theme file and replace the contents of app.css with it
+ // Needs full path to the file
+ const themeCode = Deno.readTextFileSync(Deno.cwd() + '/themes/' + themeFolder + '/theme.css');
+ // Replace the contents of app.css with the theme code
+
+ // and add a comment at the top
+ const themeComment = `/* Generated from ${themeFolder} */\n`;
+ const themeCodeWithComment = themeComment + themeCode;
+ // Return the theme code as the new contents of app.css
+ return {
+ code: themeCodeWithComment,
+ map: null,
+ };
+ }
+ return null;
+ }
+ };
+};
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
index 20d2272..96d3c8c 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,7 +1,11 @@
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
+import { themePlugin } from "./theming";
// https://vite.dev/config/
export default defineConfig({
- plugins: [svelte()],
+ plugins: [
+ themePlugin(),
+ svelte(),
+ ],
});