pds dash for shimaenaga.veryroundbird.house (based off of pds.witchcraft.systems)

Compare changes

Choose any two refs to compare.

Changed files
+113 -17
.tangled
workflows
src
themes
birdrights
+17 -15
.tangled/workflows/build.yml
···
dependencies:
nixpkgs:
- deno
+
- openssh
+
- su
steps:
+
- name: "Pretend we have a real local user"
+
command: |
+
echo "🪶 pretend root is a real user"
+
echo "root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash" >> /etc/passwd
+
- name: "Copy config to server"
command: |
echo "🪶 copying config from secrets"
-
CONF=$(cat << "EOF"
-
${{ secrets.CONFIG }}
-
EOF
-
)
-
echo "🪶 debugging config"
-
echo "${CONF}" > config.ts
-
cat config.ts
+
echo "${CONFIG}" > config.ts
- name: "Set up Deno"
command: |
···
- name: "SSH setup"
command: |
+
echo "🪶 setting up ssh connection"
mkdir ~/.ssh
-
echo "${{secrets.SSH_KEY}}" > ~/.ssh/id_tangledsh
+
echo "${SSH_KEY}" > ~/.ssh/id_tangledsh
chmod 600 ~/.ssh/id_tangledsh
-
cat > ~/.ssh/config << EOF
+
cat > /etc/ssh/ssh_config << EOF
Host deploy
-
HostName ${{ secrets.SERVER_HOST }}
-
User ${{ secrets.SERVER_USER }}
+
HostName ${SERVER_HOST}
+
User ${SERVER_USER}
IdentityFile ~/.ssh/id_tangledsh
-
StrictHostKeyChecking accept-new
+
StrictHostKeyChecking no
+
UserKnownHostsFile /dev/null
BatchMode yes
PasswordAuthentication no
PubkeyAuthentication yes
EOF
-
chmod 600 ~/.ssh/config
-
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
-
echo "🪶 setting up ssh connection"
+
chmod 600 /etc/ssh/ssh_config
+
ssh-keyscan -H $SERVER_HOST >> ~/.ssh/known_hosts
- name: "Deploy via SCP"
command: |
+1 -1
README.md
···
* Replaced favicon
* Ported in guestbook functionality from another PDS frontpage (see new config options)
* Secret unique easter egg :)
-
* Wrote deploy pipeline for tangled.sh
+
* Wrote deploy pipeline for tangled.sh (WORK IN PROGRESS help try #5 - changing ssh perms?)
you can see it running at [my pds!](https://shimaenaga.veryroundbird.house)
+2 -1
src/App.svelte
···
<script lang="ts">
import PostComponent from "./lib/PostComponent.svelte";
+
import GuestbookPostComponent from "./lib/GuestbookPostComponent.svelte";
import AccountComponent from "./lib/AccountComponent.svelte";
import InfiniteLoading from "svelte-infinite-loading";
import { getNextPosts, Post, getAllMetadataFromPds, fetchGuestbookPosts } from "./lib/pdsfetch";
···
<div id="guestbookPosts">
{#if guestbookPosts.length > 0}
{#each guestbookPosts as postObject}
-
<PostComponent post={postObject as Post} />
+
<GuestbookPostComponent post={postObject.post} />
{/each}
{:else}
<p class="noGuestbookPosts">No guestbook posts yet!</p>
+92
src/lib/GuestbookPostComponent.svelte
···
+
<script lang="ts">
+
import { Post } from "./pdsfetch";
+
import { Config } from "../../config";
+
import { onMount } from "svelte";
+
import moment from "moment";
+
+
let { post }: { post: Post } = $props();
+
console.log(post);
+
</script>
+
+
<div class="postContainer">
+
<div class="postHeader">
+
{#if post.author.avatar}
+
<img
+
class="avatar"
+
src="{post.author.avatar}"
+
alt="avatar of {post.author.displayName}"
+
/>
+
{/if}
+
<div class="headerText">
+
<a class="displayName" href="{Config.FRONTEND_URL}/profile/{post.author.did}">{post.author.displayName}</a>
+
<p class="handle">
+
<a href="{Config.FRONTEND_URL}/profile/{post.author.handle}"
+
>@{post.author.handle}</a
+
>
+
<a
+
class="postLink" href="{Config.FRONTEND_URL}/profile/{post.author.did}/post/{post.record.id}"
+
>{moment(post.record.createdAt).isBefore(moment().subtract(1, "month"))
+
? moment(post.record.createdAt).format("MMM D, YYYY")
+
: moment(post.record.createdAt).fromNow()}</a>
+
</p>
+
</div>
+
</div>
+
<div class="postContent">
+
{#if post.record.quote}
+
<a
+
class="quotingText"
+
href="{Config.FRONTEND_URL}/profile/{post.record.quote.uri}/post/{post
+
.quotingUri.rkey}">quoting {post.quotingUri.repo}</a
+
>
+
{/if}
+
<div class="postText">{post.record.text}</div>
+
{#if post.record.imagesCid && post.record.imagesCid.length > 0}
+
<div id="carouselContainer">
+
<img
+
class="embedImages"
+
alt="Post Image {currentImageIndex + 1} of {post.record.imagesCid.length}"
+
src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.record.author.did}&cid={post.record
+
.imagesCid[currentImageIndex]}"
+
/>
+
+
{#if post.imagesCid.length > 1}
+
<div class="carouselControls">
+
<button
+
id="prevBtn"
+
onclick={prevImage}
+
disabled={currentImageIndex === 0}>←</button
+
>
+
<div class="carouselIndicators">
+
{#each post.record.imagesCid as _, i}
+
<div
+
class="indicator {i === currentImageIndex ? 'active' : ''}"
+
></div>
+
{/each}
+
</div>
+
<button
+
class="nextBtn"
+
onclick={nextImage}
+
disabled={currentImageIndex === post.imagesCid.length - 1}
+
>→</button
+
>
+
</div>
+
{/if}
+
</div>
+
{/if}
+
{#if post.record.videosLinkCid}
+
<!-- svelte-ignore a11y_media_has_caption -->
+
<video
+
class="embedVideo"
+
src="{Config.PDS_URL}/xrpc/com.atproto.sync.getBlob?did={post.authorDid}&cid={post.videosLinkCid}"
+
controls
+
></video>
+
{/if}
+
{#if post.gifLink}
+
<img
+
class="embedVideo"
+
src="{post.record.gifLink}"
+
alt="Post GIF"
+
/>
+
{/if}
+
</div>
+
</div>
+1
themes/birdrights/theme.css
···
padding: 10px;
gap: 10px;
z-index: 10;
+
grid-template-rows: auto 1fr;
}
#guestbookContents:popover-open {