personal web client for Bluesky
typescript solidjs bluesky atcute
at trunk 1.9 kB view raw
1import { Match, Switch } from 'solid-js'; 2 3import type { AppBskyActorDefs } from '@atcute/bluesky'; 4import { ClientResponseError } from '@atcute/client'; 5import { TokenRefreshError } from '@atcute/oauth-browser-client'; 6import { useQueryClient } from '@mary/solid-query'; 7 8import { formatQueryError } from '~/api/utils/error'; 9 10import { openModal } from '~/globals/modals'; 11 12import { useSession } from '~/lib/states/session'; 13 14import Button from '~/components/button'; 15import SignInDialogLazy from '~/components/main/sign-in-dialog-lazy'; 16 17export interface ErrorViewProps { 18 error: unknown; 19 onRetry?: () => void; 20} 21 22const ErrorView = (props: ErrorViewProps) => { 23 const queryClient = useQueryClient(); 24 25 const { currentAccount } = useSession(); 26 27 return ( 28 <div class="p-4"> 29 <div class="mb-4 text-sm"> 30 <p class="font-bold">Something went wrong</p> 31 <p class="text-pretty text-contrast-muted">{formatQueryError(props.error)}</p> 32 </div> 33 34 <div class="flex flex-wrap gap-4"> 35 <Switch> 36 <Match when={isInvalidTokenError(props.error)}> 37 <Button 38 onClick={() => { 39 type Profile = AppBskyActorDefs.ProfileViewDetailed; 40 41 const did = currentAccount!.did; 42 const profile = queryClient.getQueryData<Profile>(['profile', currentAccount!.did]); 43 44 openModal(() => <SignInDialogLazy relogin={/* @once */ { did, handle: profile?.handle }} />); 45 }} 46 variant="primary" 47 > 48 Sign in again 49 </Button> 50 51 <Button onClick={props.onRetry}>Try again</Button> 52 </Match> 53 54 <Match when> 55 <Button onClick={props.onRetry} variant="primary"> 56 Try again 57 </Button> 58 </Match> 59 </Switch> 60 </div> 61 </div> 62 ); 63}; 64 65export default ErrorView; 66 67const isInvalidTokenError = (err: unknown): boolean => { 68 return ( 69 err instanceof TokenRefreshError || (err instanceof ClientResponseError && err.error === 'invalid_token') 70 ); 71};