From a7da8d060840c80a1ddf23cf6ee07b0c3f7b0e80 Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Mon, 27 Jul 2026 08:54:02 +0000 Subject: [PATCH] web: timeline Signed-off-by: Seongmin Lee --- web/src/routes/timeline/+page.svelte | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ web/src/routes/timeline/+page.ts | 28 ++++++++++++++++++++++++++++ 2 file(s) changed, 134 insertion(s)(+), 0 deletion(s)(-) diff --git a/web/src/routes/timeline/+page.svelte b/web/src/routes/timeline/+page.svelte new file mode 100644 --- /dev/null +++ b/web/src/routes/timeline/+page.svelte @@ -0,0 +1,106 @@ + + + + Timeline · Tangled + + +
+
+

+

+ {#if data.signedIn} + + + + + {/if} +
+ + {#each data.feed as item (item.event.uri)} + {@const event = item.event} +
+
+ {#if event.$type === "sh.tangled.feed.getTimeline#repoEvent"} + + {#if event.source} + forked + {event.source.owner.handle}/{event.source.slug} + to {event.repo.slug} + {:else} + created {event.repo.slug} + {/if} + {:else if event.$type === "sh.tangled.feed.getTimeline#starEvent"} + + starred + {event.repo.owner.handle}/{event.repo.slug} + {:else if event.$type === "sh.tangled.feed.getTimeline#followEvent"} + + followed + + {/if} + {relativeTime(item.eventAt)} +
+ + {#if event.$type === "sh.tangled.feed.getTimeline#followEvent"} + + {:else} + + {/if} +
+ {:else} + + {/each} +
diff --git a/web/src/routes/timeline/+page.ts b/web/src/routes/timeline/+page.ts new file mode 100644 --- /dev/null +++ b/web/src/routes/timeline/+page.ts @@ -0,0 +1,28 @@ +import { createBobbinClient } from "$lib/api/client"; +import { jsonGet } from "$lib/api/_request"; +import { toHttpError } from "$lib/api/load"; +import type * as ShTangledFeedGetTimeline from "$lib/api/lexicons/types/sh/tangled/feed/getTimeline"; +import type { PageLoad } from "./$types"; + +const PAGE_LIMIT = 50; + +export const load: PageLoad = async (event) => { + const parent = await event.parent(); + const ctx = createBobbinClient({ serviceUrl: parent.publicConfig.bobbinUrl, fetch: event.fetch }); + const viewer = parent.auth?.did; + + // the following feed needs a viewer to resolve the followed set; bobbin 400s without one + const followingOnly = event.url.searchParams.get("following") === "true" && viewer !== undefined; + + try { + // output key is `feed`, not `items`, so the pagination.ts helpers don't apply + const { feed } = await jsonGet( + ctx, + "sh.tangled.feed.getTimeline", + { viewer, followingOnly, limit: PAGE_LIMIT } + ); + return { feed, followingOnly, signedIn: viewer !== undefined }; + } catch (cause) { + toHttpError(cause, "Could not load timeline"); + } +}; -- tangled.sh