diff --git a/.forgejo/workflows/deploy.yaml b/.forgejo/workflows/deploy.yaml index 7f20d99..c6a05d0 100644 --- a/.forgejo/workflows/deploy.yaml +++ b/.forgejo/workflows/deploy.yaml @@ -6,26 +6,15 @@ on: - main - astra/ci - jobs: deploy: name: Deploy runs-on: ubuntu-latest steps: - - name: Checkout main repo + - name: Checkout 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 991a625..42a517f 100644 --- a/.gitignore +++ b/.gitignore @@ -149,7 +149,4 @@ dist .yarn/unplugged .yarn/build-state.yml .yarn/install-state.gz -.pnp.* - -# Config files -config.ts \ No newline at end of file +.pnp.* \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 581839a..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -# MIT License - -Copyright (c) 2025 Witchcraft Systems - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md index 5fd9458..6194e14 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,3 @@ # pds-dash -a frontend dashboard with stats for your ATProto PDS. - -## setup - -### prerequisites - -- [deno](https://deno.com/manual/getting_started/installation) - -### installing - -clone the repo, copy `config.ts.example` to `config.ts` and edit it to your liking. - -then, install dependencies using deno: - -```sh -deno install -``` - -### development server - -local develompent server with hot reloading: - -```sh -deno task dev -``` - -### building - -to build the optimized bundle run: - -```sh -deno task build -``` - -the output will be in the `dist/` directory. - -## deploying - -we use our own CI/CD workflow at [`.forgejo/workflows/deploy.yaml`](.forgejo/workflows/deploy.yaml), but it boils down to building the project bundle and deploying it to a web server. it'll probably make more sense to host it on the same domain as your PDS, but it doesn't affect anything if you host it somewhere else. - -## configuring - -[`config.ts`](config.ts) is the main configuration file, you can find more information in the file itself. - -## theming - -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. - -currently, the name of the theme is determined by the directory name, and the theme itself is defined in `theme.css` inside that directory. - -you can switch themes by changing the `theme` property in `config.ts`. - -the favicon is located at [`public/favicon.ico`](public/favicon.ico) - -## license - -MIT +Frontend with stats for your ATProto PDS \ No newline at end of file diff --git a/config.ts b/config.ts new file mode 100644 index 0000000..fe28a5a --- /dev/null +++ b/config.ts @@ -0,0 +1,28 @@ +/** + * 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 + * @default "https://deer.social" + */ + static readonly FRONTEND_URL: string = "https://deer.social"; + + /** + * Maximum number of posts to show in the feed (across all users) + * @default 100 + */ + static readonly MAX_POSTS: number = 100; + + /** + * Footer text for the dashboard + * @default "Astrally projected from witchcraft.systems" + */ + static readonly FOOTER_TEXT: string = "Astrally projected from witchcraft.systems"; +} \ No newline at end of file diff --git a/config.ts.example b/config.ts.example deleted file mode 100644 index 87894d3..0000000 --- a/config.ts.example +++ /dev/null @@ -1,44 +0,0 @@ -/** - * 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 90a8393..0616852 100644 --- a/deno.lock +++ b/deno.lock @@ -1,5 +1,5 @@ { - "version": "5", + "version": "4", "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,9 +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", "npm:typescript@~5.7.2": "5.7.3", "npm:vite@^6.3.1": "6.3.2_picomatch@4.0.2" @@ -55,129 +53,79 @@ "integrity": "sha512-GEhUCk9c4XbNxi+0YZHZsV4fYNd6HejfWuN4Ti4c02DauX+LyX5WY1Y3WfyZ8Pxxl0zqhs+MLtW98cMh86vv6g==" }, "@esbuild/aix-ppc64@0.25.2": { - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", - "os": ["aix"], - "cpu": ["ppc64"] + "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==" }, "@esbuild/android-arm64@0.25.2": { - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", - "os": ["android"], - "cpu": ["arm64"] + "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==" }, "@esbuild/android-arm@0.25.2": { - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", - "os": ["android"], - "cpu": ["arm"] + "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==" }, "@esbuild/android-x64@0.25.2": { - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", - "os": ["android"], - "cpu": ["x64"] + "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==" }, "@esbuild/darwin-arm64@0.25.2": { - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", - "os": ["darwin"], - "cpu": ["arm64"] + "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==" }, "@esbuild/darwin-x64@0.25.2": { - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", - "os": ["darwin"], - "cpu": ["x64"] + "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==" }, "@esbuild/freebsd-arm64@0.25.2": { - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", - "os": ["freebsd"], - "cpu": ["arm64"] + "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==" }, "@esbuild/freebsd-x64@0.25.2": { - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", - "os": ["freebsd"], - "cpu": ["x64"] + "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==" }, "@esbuild/linux-arm64@0.25.2": { - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", - "os": ["linux"], - "cpu": ["arm64"] + "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==" }, "@esbuild/linux-arm@0.25.2": { - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", - "os": ["linux"], - "cpu": ["arm"] + "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==" }, "@esbuild/linux-ia32@0.25.2": { - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", - "os": ["linux"], - "cpu": ["ia32"] + "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==" }, "@esbuild/linux-loong64@0.25.2": { - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", - "os": ["linux"], - "cpu": ["loong64"] + "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==" }, "@esbuild/linux-mips64el@0.25.2": { - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", - "os": ["linux"], - "cpu": ["mips64el"] + "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==" }, "@esbuild/linux-ppc64@0.25.2": { - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", - "os": ["linux"], - "cpu": ["ppc64"] + "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==" }, "@esbuild/linux-riscv64@0.25.2": { - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", - "os": ["linux"], - "cpu": ["riscv64"] + "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==" }, "@esbuild/linux-s390x@0.25.2": { - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", - "os": ["linux"], - "cpu": ["s390x"] + "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==" }, "@esbuild/linux-x64@0.25.2": { - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", - "os": ["linux"], - "cpu": ["x64"] + "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==" }, "@esbuild/netbsd-arm64@0.25.2": { - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", - "os": ["netbsd"], - "cpu": ["arm64"] + "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==" }, "@esbuild/netbsd-x64@0.25.2": { - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", - "os": ["netbsd"], - "cpu": ["x64"] + "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==" }, "@esbuild/openbsd-arm64@0.25.2": { - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", - "os": ["openbsd"], - "cpu": ["arm64"] + "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==" }, "@esbuild/openbsd-x64@0.25.2": { - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", - "os": ["openbsd"], - "cpu": ["x64"] + "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==" }, "@esbuild/sunos-x64@0.25.2": { - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", - "os": ["sunos"], - "cpu": ["x64"] + "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==" }, "@esbuild/win32-arm64@0.25.2": { - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", - "os": ["win32"], - "cpu": ["arm64"] + "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==" }, "@esbuild/win32-ia32@0.25.2": { - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", - "os": ["win32"], - "cpu": ["ia32"] + "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==" }, "@esbuild/win32-x64@0.25.2": { - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", - "os": ["win32"], - "cpu": ["x64"] + "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==" }, "@jridgewell/gen-mapping@0.3.8": { "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", @@ -204,104 +152,64 @@ ] }, "@rollup/rollup-android-arm-eabi@4.40.0": { - "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==", - "os": ["android"], - "cpu": ["arm"] + "integrity": "sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg==" }, "@rollup/rollup-android-arm64@4.40.0": { - "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==", - "os": ["android"], - "cpu": ["arm64"] + "integrity": "sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w==" }, "@rollup/rollup-darwin-arm64@4.40.0": { - "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==", - "os": ["darwin"], - "cpu": ["arm64"] + "integrity": "sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ==" }, "@rollup/rollup-darwin-x64@4.40.0": { - "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==", - "os": ["darwin"], - "cpu": ["x64"] + "integrity": "sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA==" }, "@rollup/rollup-freebsd-arm64@4.40.0": { - "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==", - "os": ["freebsd"], - "cpu": ["arm64"] + "integrity": "sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg==" }, "@rollup/rollup-freebsd-x64@4.40.0": { - "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==", - "os": ["freebsd"], - "cpu": ["x64"] + "integrity": "sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw==" }, "@rollup/rollup-linux-arm-gnueabihf@4.40.0": { - "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==", - "os": ["linux"], - "cpu": ["arm"] + "integrity": "sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA==" }, "@rollup/rollup-linux-arm-musleabihf@4.40.0": { - "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==", - "os": ["linux"], - "cpu": ["arm"] + "integrity": "sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg==" }, "@rollup/rollup-linux-arm64-gnu@4.40.0": { - "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==", - "os": ["linux"], - "cpu": ["arm64"] + "integrity": "sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg==" }, "@rollup/rollup-linux-arm64-musl@4.40.0": { - "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==", - "os": ["linux"], - "cpu": ["arm64"] + "integrity": "sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ==" }, "@rollup/rollup-linux-loongarch64-gnu@4.40.0": { - "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==", - "os": ["linux"], - "cpu": ["loong64"] + "integrity": "sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg==" }, "@rollup/rollup-linux-powerpc64le-gnu@4.40.0": { - "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==", - "os": ["linux"], - "cpu": ["ppc64"] + "integrity": "sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw==" }, "@rollup/rollup-linux-riscv64-gnu@4.40.0": { - "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==", - "os": ["linux"], - "cpu": ["riscv64"] + "integrity": "sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA==" }, "@rollup/rollup-linux-riscv64-musl@4.40.0": { - "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==", - "os": ["linux"], - "cpu": ["riscv64"] + "integrity": "sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ==" }, "@rollup/rollup-linux-s390x-gnu@4.40.0": { - "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==", - "os": ["linux"], - "cpu": ["s390x"] + "integrity": "sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw==" }, "@rollup/rollup-linux-x64-gnu@4.40.0": { - "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==", - "os": ["linux"], - "cpu": ["x64"] + "integrity": "sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ==" }, "@rollup/rollup-linux-x64-musl@4.40.0": { - "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==", - "os": ["linux"], - "cpu": ["x64"] + "integrity": "sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw==" }, "@rollup/rollup-win32-arm64-msvc@4.40.0": { - "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==", - "os": ["win32"], - "cpu": ["arm64"] + "integrity": "sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ==" }, "@rollup/rollup-win32-ia32-msvc@4.40.0": { - "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==", - "os": ["win32"], - "cpu": ["ia32"] + "integrity": "sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA==" }, "@rollup/rollup-win32-x64-msvc@4.40.0": { - "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==", - "os": ["win32"], - "cpu": ["x64"] + "integrity": "sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ==" }, "@sveltejs/acorn-typescript@1.0.5_acorn@8.14.1": { "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", @@ -338,8 +246,7 @@ "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==" }, "acorn@8.14.1": { - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "bin": true + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==" }, "aria-query@5.3.2": { "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==" @@ -367,7 +274,7 @@ }, "esbuild@0.25.2": { "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", - "optionalDependencies": [ + "dependencies": [ "@esbuild/aix-ppc64", "@esbuild/android-arm", "@esbuild/android-arm64", @@ -393,9 +300,7 @@ "@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==" @@ -410,15 +315,10 @@ "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", "dependencies": [ "picomatch" - ], - "optionalPeers": [ - "picomatch" ] }, "fsevents@2.3.3": { - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "os": ["darwin"], - "scripts": true + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==" }, "is-reference@3.0.3": { "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", @@ -447,12 +347,8 @@ "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==", - "bin": true + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==" }, "picocolors@1.1.1": { "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" @@ -474,9 +370,6 @@ "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", @@ -497,9 +390,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==", @@ -520,11 +413,7 @@ "sade", "svelte", "typescript" - ], - "bin": true - }, - "svelte-infinite-loading@1.4.0": { - "integrity": "sha512-Jo+f/yr/HmZQuIiiKKzAHVFXdAUWHW2RBbrcQTil8JVk1sCm/riy7KTJVzjBgQvHasrFQYKF84zvtc9/Y4lFYg==" + ] }, "svelte@5.28.1_acorn@8.14.1": { "integrity": "sha512-iOa9WmfNG95lSOSJdMhdjJ4Afok7IRAQYXpbnxhd5EINnXseG0GVa9j6WPght4eX78XfFez45Fi+uRglGKPV/Q==", @@ -553,31 +442,24 @@ ] }, "typescript@5.7.3": { - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "bin": true + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==" }, "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": { @@ -593,9 +475,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", "npm:typescript@~5.7.2", "npm:vite@^6.3.1" diff --git a/index.html b/index.html index adcfab3..f71d006 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + diff --git a/package.json b/package.json index 3b293c0..9f84465 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,7 @@ "@atcute/bluesky": "^2.0.2", "@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" + "moment": "^2.30.1" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^5.0.3", diff --git a/src/App.svelte b/src/App.svelte index 798b8a7..95912e2 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1,88 +1,131 @@
- {#await accountsPromise} -

Loading...

- {:then accountsData} -
-

ATProto PDS

-

Home to {accountsData.length} accounts

-
- {#each accountsData as accountObject} - - {/each} -
-

{@html Config.FOOTER_TEXT}

+ {#await accountsPromise} +

Loading...

+ {:then accountsData} +
+

ATProto PDS

+

Home to {accountsData.length} accounts

+
+ {#each accountsData as accountObject} + + {/each}
- {:catch error} -

Error: {error.message}

- {/await} +

{@html Config.FOOTER_TEXT}

+
+ {:catch error} +

Error: {error.message}

+ {/await} + {#await postsPromise} +

Loading...

+ {:then postsData}
- {#each posts as postObject} + {#each postsData as postObject} {/each} -
+ {/await}
diff --git a/src/app.css b/src/app.css index cb315e4..b89ecff 100644 --- a/src/app.css +++ b/src/app.css @@ -1,4 +1,83 @@ -@import url('./themes/colors.css'); +@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; +} + body { - background-color: red; + 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; } \ No newline at end of file diff --git a/src/lib/AccountComponent.svelte b/src/lib/AccountComponent.svelte index faf6251..e324393 100644 --- a/src/lib/AccountComponent.svelte +++ b/src/lib/AccountComponent.svelte @@ -12,17 +12,37 @@ 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 1cacc28..69ea88b 100644 --- a/src/lib/PostComponent.svelte +++ b/src/lib/PostComponent.svelte @@ -71,7 +71,7 @@ >

@{post.authorHandle}{post.authorHandle}

@@ -125,7 +125,7 @@
@@ -141,16 +141,150 @@ controls > {/if} - {#if post.gifLink} - Post GIF - {/if} diff --git a/src/lib/pdsfetch.ts b/src/lib/pdsfetch.ts index d57aff4..aa3fc85 100644 --- a/src/lib/pdsfetch.ts +++ b/src/lib/pdsfetch.ts @@ -13,21 +13,16 @@ 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"; interface AccountMetadata { - did: At.Did; + did: string; displayName: string; handle: string; avatarCid: string | null; - currentCursor?: string; } - -let accountsMetadata: AccountMetadata[] = []; - interface atUriObject { repo: string; collection: string; @@ -47,7 +42,6 @@ class Post { replyingUri: atUriObject | null; imagesCid: string[] | null; videosLinkCid: string | null; - gifLink: string | null; constructor( record: ComAtprotoRepoListRecords.Record, @@ -71,11 +65,10 @@ 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( - (imageRecord: any) => imageRecord.image.ref.$link, + this.imagesCid = post.embed.images.map((imageRecord: any) => + imageRecord.image.ref.$link ); break; case "app.bsky.embed.video": @@ -88,8 +81,8 @@ class Post { this.quotingUri = processAtUri(post.embed.record.record.uri); switch (post.embed.media.$type) { case "app.bsky.embed.images": - this.imagesCid = post.embed.media.images.map( - (imageRecord) => imageRecord.image.ref.$link, + this.imagesCid = post.embed.media.images.map((imageRecord) => + imageRecord.image.ref.$link ); break; @@ -99,11 +92,6 @@ 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; } } } @@ -123,57 +111,78 @@ const rpc = new XRPC({ }), }); -const getDidsFromPDS = async (): Promise => { +const getDidsFromPDS = async () : Promise => { const { data } = await rpc.get("com.atproto.sync.listRepos", { params: {}, }); - return data.repos.map((repo: any) => repo.did) as At.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 => { + // gonna assume self exists in the app.bsky.actor.profile + try { + const { data } = await rpc.get("com.atproto.repo.getRecord", { + params: { + repo: did, + collection: "app.bsky.actor.profile", + rkey: "self", + }, + }); + const value = data.value as AppBskyActorProfile.Record; + const handle = await blueskyHandleFromDid(did); const account: AccountMetadata = { did: did, - handle: "", // Guaranteed to be filled out later - displayName: "", + handle: handle, + displayName: value.displayName || "", avatarCid: null, }; - - try { - const { data } = await rpc.get("com.atproto.repo.getRecord", { - params: { - repo: did, - collection: "app.bsky.actor.profile", - rkey: "self", - }, - }); - const value = data.value as AppBskyActorProfile.Record; - account.displayName = value.displayName || ""; - if (value.avatar) { - account.avatarCid = value.avatar.ref["$link"]; - } - } catch (e) { - console.warn(`Error fetching profile for ${did}:`, e); + if (value.avatar) { + account.avatarCid = value.avatar.ref["$link"]; } - - try { - account.handle = await blueskyHandleFromDid(did); - } catch (e) { - console.error(`Error fetching handle for ${did}:`, e); - return null; - } - return account; + } + catch (e) { + console.error(`Error fetching metadata for ${did}:`, e); + return { + did: "error", + displayName: "", + avatarCid: null, + handle: "error", + }; + } }; -const getAllMetadataFromPds = async (): Promise => { +const getAllMetadataFromPds = async () : Promise => { const dids = await getDidsFromPDS(); const metadata = await Promise.all( dids.map(async (repo: `did:${string}:${string}`) => { return await getAccountMetadata(repo); }), ); - return metadata.filter((account) => account !== null) as AccountMetadata[]; + return metadata.filter(account => account.did !== "error"); +}; + +const fetchPosts = async (did: string) => { + try { + const { data } = await rpc.get("com.atproto.repo.listRecords", { + params: { + repo: did as At.Identifier, + collection: "app.bsky.feed.post", + limit: Config.MAX_POSTS, + }, + }); + return { + records: data.records as ComAtprotoRepoListRecords.Record[], + did: did, + error: false + }; + } catch (e) { + console.error(`Error fetching posts for ${did}:`, e); + return { + records: [], + did: did, + error: true + }; + } }; const identityResolve = async (did: At.Did) => { @@ -209,151 +218,27 @@ const blueskyHandleFromDid = async (did: At.Did) => { } }; -interface PostsAcc { - posts: ComAtprotoRepoListRecords.Record[]; - account: AccountMetadata; -} -const getCutoffDate = (postAccounts: PostsAcc[]) => { - const now = Date.now(); - let cutoffDate: Date | null = null; - postAccounts.forEach((postAcc) => { - const latestPost = new Date( - (postAcc.posts[postAcc.posts.length - 1].value as AppBskyFeedPost.Record) - .createdAt, - ); - if (!cutoffDate) { - cutoffDate = latestPost; - } else { - if (latestPost > cutoffDate) { - cutoffDate = latestPost; +const fetchAllPosts = async () => { + const users: AccountMetadata[] = await getAllMetadataFromPds(); + const postRecords = await Promise.all( + users.map(async (metadata: AccountMetadata) => + await fetchPosts(metadata.did) + ), + ); + const validPostRecords = postRecords.filter(record => !record.error); + const posts: Post[] = validPostRecords.flatMap((userFetch) => + userFetch.records.map((record) => { + const user = users.find((user: AccountMetadata) => + user.did == userFetch.did + ); + if (!user) { + throw new Error(`User with DID ${userFetch.did} not found`); } - } - }); - if (cutoffDate) { - return cutoffDate; - } else { - return new Date(now); - } -}; - -const filterPostsByDate = (posts: PostsAcc[], cutoffDate: Date) => { - // filter posts for each account that are older than the cutoff date and save the cursor of the last post included - const filteredPosts: PostsAcc[] = posts.map((postAcc) => { - const filtered = postAcc.posts.filter((post) => { - const postDate = new Date( - (post.value as AppBskyFeedPost.Record).createdAt, - ); - return postDate >= cutoffDate; - }); - if (filtered.length > 0) { - postAcc.account.currentCursor = processAtUri(filtered[filtered.length - 1].uri).rkey; - } - return { - posts: filtered, - account: postAcc.account, - }; - }); - 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(); - } - - const postsAcc: PostsAcc[] = await Promise.all( - accountsMetadata.map(async (account) => { - const posts = await fetchPostsForUser( - account.did, - account.currentCursor || null, - ); - if (posts) { - return { - posts: posts, - account: account, - }; - } else { - return { - posts: [], - account: account, - }; - } - }), + return new Post(record, user); + }) ); - const recordsFiltered = postsAcc.filter((postAcc) => - postAcc.posts.length > 0 - ); - const cutoffDate = getCutoffDate(recordsFiltered); - const recordsCutoff = filterPostsByDate(recordsFiltered, cutoffDate); - // update the accountMetadata with the new cursor - accountsMetadata = accountsMetadata.map((account) => { - const postAcc = recordsCutoff.find( - (postAcc) => postAcc.account.did == account.did, - ); - if (postAcc) { - account.currentCursor = postAcc.account.currentCursor; - } - return account; - } - ); - // throw the records in a big single array - let records = recordsCutoff.flatMap((postAcc) => postAcc.posts); - // sort the records by timestamp - records = records.sort((a, b) => { - const aDate = new Date( - (a.value as AppBskyFeedPost.Record).createdAt, - ).getTime(); - const bDate = new Date( - (b.value as AppBskyFeedPost.Record).createdAt, - ).getTime(); - return bDate - aDate; - }); - // filter out posts that are in the future - if (!Config.SHOW_FUTURE_POSTS) { - const now = Date.now(); - records = records.filter((post) => { - const postDate = new Date( - (post.value as AppBskyFeedPost.Record).createdAt, - ).getTime(); - return postDate <= now; - }); - } - - const newPosts = records.map((record) => { - const account = accountsMetadata.find( - (account) => account.did == processAtUri(record.uri).repo, - ); - if (!account) { - throw new Error( - `Account with DID ${processAtUri(record.uri).repo} not found`, - ); - } - return new Post(record, account); - }); - // release the mutex - release(); - return newPosts; + posts.sort((a, b) => b.timestamp - a.timestamp); + return posts.slice(0, Config.MAX_POSTS); }; - -const fetchPostsForUser = async (did: At.Did, cursor: string | null) => { - try { - const { data } = await rpc.get("com.atproto.repo.listRecords", { - params: { - repo: did as At.Identifier, - collection: "app.bsky.feed.post", - limit: Config.MAX_POSTS, - cursor: cursor || undefined, - }, - }); - return data.records as ComAtprotoRepoListRecords.Record[]; - } catch (e) { - console.error(`Error fetching posts for ${did}:`, e); - return null; - } -}; - -export { getAllMetadataFromPds, getNextPosts, Post }; +export { fetchAllPosts, getAllMetadataFromPds, Post }; export type { AccountMetadata }; diff --git a/src/main.ts b/src/main.ts index d47b930..664a057 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,9 @@ -import { mount } from "svelte"; -import "./app.css"; -import App from "./App.svelte"; +import { mount } from 'svelte' +import './app.css' +import App from './App.svelte' const app = mount(App, { - target: document.getElementById("app")!, -}); + target: document.getElementById('app')!, +}) -export default app; +export default app diff --git a/svelte.config.js b/svelte.config.js index de2ddd6..b0683fd 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,7 +1,7 @@ -import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' export default { // Consult https://svelte.dev/docs#compile-time-svelte-preprocess // for more information about preprocessors preprocess: vitePreprocess(), -}; +} diff --git a/themes/default/theme.css b/themes/default/theme.css deleted file mode 100644 index e4061ec..0000000 --- a/themes/default/theme.css +++ /dev/null @@ -1,423 +0,0 @@ -/* 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 deleted file mode 100644 index 58c399e..0000000 --- a/themes/express/theme.css +++ /dev/null @@ -1,375 +0,0 @@ -@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 deleted file mode 100644 index 8ad63d4..0000000 --- a/themes/witchcraft/theme.css +++ /dev/null @@ -1,373 +0,0 @@ -@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 deleted file mode 100644 index 3b5964b..0000000 --- a/theming.ts +++ /dev/null @@ -1,32 +0,0 @@ -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 96d3c8c..d32eba1 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,11 +1,7 @@ -import { defineConfig } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import { themePlugin } from "./theming"; +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' // https://vite.dev/config/ export default defineConfig({ - plugins: [ - themePlugin(), - svelte(), - ], -}); + plugins: [svelte()], +})