diff --git a/.changeset/add-offline-account-actions.md b/.changeset/add-offline-account-actions.md new file mode 100644 index 0000000000..81891c6c69 --- /dev/null +++ b/.changeset/add-offline-account-actions.md @@ -0,0 +1,5 @@ +--- +default: patch +--- + +Add account switching and logout actions to the homeserver offline screen. diff --git a/src/app/pages/client/SpecVersions.tsx b/src/app/pages/client/SpecVersions.tsx index 39b44a6dd8..d89c95a453 100644 --- a/src/app/pages/client/SpecVersions.tsx +++ b/src/app/pages/client/SpecVersions.tsx @@ -1,10 +1,15 @@ import type { ReactNode } from 'react'; -import { useCallback } from 'react'; -import { Box, Button, Dialog, config, Text } from 'folds'; +import { useCallback, useState } from 'react'; +import { Box, Button, Dialog, config, Spinner, Text, color } from 'folds'; +import { useAtomValue, useSetAtom } from 'jotai'; import { SpecVersionsLoader } from '$components/SpecVersionsLoader'; import { SpecVersionsProvider } from '$hooks/useSpecVersions'; import { SplashScreen } from '$components/splash-screen'; import { useMatrixClient } from '$hooks/useMatrixClient'; +import { logoutClient } from '$client/initMatrix'; +import { activeSessionIdAtom, sessionsAtom, type Session } from '$state/sessions'; +import { AsyncStatus, useAsyncCallback } from '$hooks/useAsyncCallback'; +import { useClientConfig } from '$hooks/useClientConfig'; import type { SpecVersions } from '../../cs-api'; const EMPTY_VERSIONS: SpecVersions = { versions: [] }; @@ -14,6 +19,39 @@ type HomeserverOfflineErrorProps = { onRetry: () => void; }; function HomeserverOfflineError({ baseUrl, onRetry }: HomeserverOfflineErrorProps) { + const mx = useMatrixClient(); + const sessions = useAtomValue(sessionsAtom); + const activeSessionId = useAtomValue(activeSessionIdAtom); + const setActiveSessionId = useSetAtom(activeSessionIdAtom); + const setSessions = useSetAtom(sessionsAtom); + const { disableAccountSwitcher } = useClientConfig(); + const [showAccounts, setShowAccounts] = useState(false); + + const activeSession = + sessions.find((session) => session.userId === activeSessionId) ?? sessions[0]; + const otherSessions = disableAccountSwitcher + ? [] + : sessions.filter((session) => session.userId !== activeSession?.userId); + + const handleSwitch = (session: Session) => { + setActiveSessionId(session.userId); + }; + + const [logoutState, logout] = useAsyncCallback( + useCallback(async () => { + if (!activeSession) return; + + await logoutClient(mx, activeSession); + setSessions({ type: 'DELETE', session: activeSession }); + setActiveSessionId( + sessions.find((session) => session.userId !== activeSession.userId)?.userId + ); + window.location.reload(); + }, [mx, activeSession, sessions, setSessions, setActiveSessionId]) + ); + + const loggingOut = logoutState.status === AsyncStatus.Loading; + return ( @@ -26,11 +64,59 @@ function HomeserverOfflineError({ baseUrl, onRetry }: HomeserverOfflineErrorProp may have a connection issue. Please try again. - + + + {otherSessions.length > 0 && ( + <> + + {showAccounts && ( + + {otherSessions.map((session) => ( + + ))} + + )} + + )} + + {logoutState.status === AsyncStatus.Error && ( + + Failed to logout. {logoutState.error.message} + + )} +