···3737 const diffAndSend = (event: InputEvent) => {
3838 const el = event.target as HTMLInputElement;
3939 const result = diff(message, el.value);
4040- var idx = 0;
4040+ let idx = 0;
4141 result.forEach((d) => {
4242 switch (d[0]) {
4343 case -1:
+5-6
src/routes/+page.svelte
···160160 <a href="/todo">todo.</a>
161161 </p>
162162 <p>
163163- <a href="https://github.com/rachel-mp4/xcvr">here</a>
164164- <a href="https://github.com/rachel-mp4/rvcx">are</a>
165165- <a href="https://github.com/rachel-mp4/lrcd">the</a>
166166- <a href="https://github.com/rachel-mp4/lrcproto">relevant</a>
163163+ <a href="https://tangled.sh/@moth11.net/xcvr">here</a>
164164+ <a href="https://tangled.sh/@moth11.net/rvcx">are</a>
165165+ <a href="https://tangled.sh/@moth11.net/lrcd">the</a>
166166+ <a href="https://tangled.sh/@moth11.net/lrcproto">relevant</a>
167167 <a href="https://github.com/rachel-mp4/beeper">codes</a> for this website, don't
168168- judge me too much for them please, i'll probably put them on tangled.sh soon
169169- but i mostly wanted to get this out before i start experimenting with those things
168168+ judge me too much for them please
170169 </p>
171170 <p>
172171 <a href="https://discord.gg/uvAmBtpdKd">join the email list</a>
+28-4
src/routes/p/[handle]/+page.svelte
···11<script lang="ts">
22+ import { DidResolver } from "@atproto/identity";
23 import type { PageProps } from "./$types";
34 import { numToHex, hexToNum, hexToContrast } from "$lib/colors";
45 import { browser } from "$app/environment";
···150151 return "now";
151152 }
152153 };
154154+ const didres = new DidResolver({});
155155+ const getPathToChannel = async (aturi: string): Promise<string | null> => {
156156+ try {
157157+ if (!aturi.startsWith("at://")) {
158158+ throw new Error();
159159+ }
160160+ const sansprefix = aturi.slice(5);
161161+ const splitted = sansprefix.split("/");
162162+ const did = splitted[0];
163163+ const handle = await didres.resolve(did);
164164+ if (!handle) {
165165+ throw new Error();
166166+ }
167167+ const base = import.meta.env.MY_BASE_URL;
168168+ const rkey = splitted[2];
169169+ return `${base}/c/${handle.id}/${rkey}`;
170170+ } catch {
171171+ return null;
172172+ }
173173+ };
174174+ // @ts-expect-error - Svelte 5.36 experimental async support
175175+ let lastSeenLocation = $derived(await getPathToChannel(data.lastSeen.where));
153176</script>
154177155178<main>
···167190 </p>
168191 {/if}
169192 {#if data.lastSeen}
170170- last seen {#if data.lastSeen.where}
171171- {data.lastSeen.where}
193193+ last seen
194194+ {#if data.lastSeen.when}
195195+ {timeSince(data.lastSeen.when) + " ago"}
172196 {/if}
173173- {#if data.lastSeen.when}
174174- {timeSince(data.lastSeen.when)}
197197+ {#if lastSeenLocation !== null}
198198+ <a href={lastSeenLocation}> in this channel</a>
175199 {/if}
176200 {/if}
177201</main>
-7
src/routes/todo/+page.svelte
···11<main>
22 <h2>known bugs</h2>
33 <p>
44- <b> undo/redo in chat </b> is currently disabled because i believe the events
55- which fire on these actions don't provide me with enough information to properly
66- broadcast which text was deleted and which text was appended, so i believe i
77- need to find a diff library that won't force me to delete the whole message and
88- rebroadcast it every history event
99- </p>
1010- <p>
114 <b> inability to validate messages </b> occurs at some points in time, possibly
125 after the backend restarts, but i'm not totally sure how or why, oauth is a bit
136 mysterious to me still and it's likely a silly error somewhere but if you suddenly