polls on atproto pollz.waow.tech
atproto zig
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

handle expired sessions and poll creation indexing delay

- detect 401 responses in api client, clear user state via callback
- layout registers onUnauthorized to reset user on session expiry
- poll creation waits for jetstream indexing before navigating home

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

zzstoatzz 551886ab 1559b3bd

+25 -3
+9
frontend/src/lib/api.ts
··· 1 1 const API = import.meta.env.VITE_API_URL ?? 'https://api.pollz.waow.tech'; 2 2 3 + let onUnauthorized: (() => void) | null = null; 4 + export function setOnUnauthorized(cb: () => void) { 5 + onUnauthorized = cb; 6 + } 7 + 3 8 async function api(path: string, opts?: RequestInit) { 4 9 const res = await fetch(`${API}${path}`, { 5 10 credentials: 'include', 6 11 ...opts 7 12 }); 13 + if (res.status === 401) { 14 + onUnauthorized?.(); 15 + throw new Error('session expired — please log in again'); 16 + } 8 17 if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); 9 18 const text = await res.text(); 10 19 if (!text) return null;
+2 -1
frontend/src/routes/+layout.svelte
··· 1 1 <script lang="ts"> 2 2 import '../app.css'; 3 3 import { loadUser, getUser, setUser, isLoaded } from '$lib/user.svelte'; 4 - import { logout as apiLogout, loginUrl } from '$lib/api'; 4 + import { logout as apiLogout, loginUrl, setOnUnauthorized } from '$lib/api'; 5 5 import { onMount } from 'svelte'; 6 6 7 7 let { children } = $props(); ··· 10 10 11 11 onMount(() => { 12 12 loadUser(); 13 + setOnUnauthorized(() => setUser(null)); 13 14 }); 14 15 15 16 function doLogout() {
+14 -2
frontend/src/routes/new/+page.svelte
··· 1 1 <script lang="ts"> 2 - import { createPoll } from '$lib/api'; 2 + import { createPoll, fetchPoll } from '$lib/api'; 3 3 import { getUser } from '$lib/user.svelte'; 4 4 import { goto } from '$app/navigation'; 5 5 ··· 21 21 22 22 status = 'creating...'; 23 23 try { 24 - await createPoll(text, options); 24 + const result = await createPoll(text, options); 25 + const uri = result?.uri; 26 + if (uri) { 27 + status = 'waiting for indexing...'; 28 + for (let i = 0; i < 15; i++) { 29 + await new Promise((r) => setTimeout(r, 500)); 30 + const poll = await fetchPoll(uri); 31 + if (poll) { 32 + goto('/'); 33 + return; 34 + } 35 + } 36 + } 25 37 goto('/'); 26 38 } catch (e) { 27 39 status = e instanceof Error ? e.message : 'failed to create poll';