Show call support error and disable join button (#2748)

* allow user to end call if error when loading

* show call support missing error if livekit server is not provided

* prevent joining from nav item double click if no livekit support
This commit is contained in:
Ajay Bura 2026-03-09 21:39:58 +11:00 committed by GitHub
commit 4449e7c6e8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 220 additions and 62 deletions

View file

@ -0,0 +1,32 @@
import React, { ReactNode, useCallback, useMemo } from 'react';
import { AutoDiscoveryInfoProvider } from '../../hooks/useAutoDiscoveryInfo';
import { AsyncStatus, useAsyncCallbackValue } from '../../hooks/useAsyncCallback';
import { autoDiscovery, AutoDiscoveryInfo } from '../../cs-api';
import { getMxIdServer } from '../../utils/matrix';
type AutoDiscoveryProps = {
userId: string;
baseUrl: string;
children: ReactNode;
};
export function AutoDiscovery({ userId, baseUrl, children }: AutoDiscoveryProps) {
const [state] = useAsyncCallbackValue(
useCallback(async () => {
const server = getMxIdServer(userId);
return autoDiscovery(fetch, server ?? userId);
}, [userId])
);
const [, info] = state.status === AsyncStatus.Success ? state.data : [];
const fallback: AutoDiscoveryInfo = useMemo(
() => ({
'm.homeserver': {
base_url: baseUrl,
},
}),
[baseUrl]
);
return <AutoDiscoveryInfoProvider value={info ?? fallback}>{children}</AutoDiscoveryInfoProvider>;
}

View file

@ -35,6 +35,7 @@ import { stopPropagation } from '../../utils/keyboard';
import { SyncStatus } from './SyncStatus';
import { AuthMetadataProvider } from '../../hooks/useAuthMetadata';
import { getFallbackSession } from '../../state/sessions';
import { AutoDiscovery } from './AutoDiscovery';
function ClientRootLoading() {
return (
@ -143,7 +144,7 @@ type ClientRootProps = {
};
export function ClientRoot({ children }: ClientRootProps) {
const [loading, setLoading] = useState(true);
const { baseUrl } = getFallbackSession() ?? {};
const { baseUrl, userId } = getFallbackSession() ?? {};
const [loadState, loadMatrix] = useAsyncCallback<MatrixClient, Error, []>(
useCallback(() => {
@ -183,47 +184,55 @@ export function ClientRoot({ children }: ClientRootProps) {
);
return (
<SpecVersions baseUrl={baseUrl!}>
{mx && <SyncStatus mx={mx} />}
{loading && <ClientRootOptions mx={mx} />}
{(loadState.status === AsyncStatus.Error || startState.status === AsyncStatus.Error) && (
<SplashScreen>
<Box direction="Column" grow="Yes" alignItems="Center" justifyContent="Center" gap="400">
<Dialog>
<Box direction="Column" gap="400" style={{ padding: config.space.S400 }}>
{loadState.status === AsyncStatus.Error && (
<Text>{`Failed to load. ${loadState.error.message}`}</Text>
)}
{startState.status === AsyncStatus.Error && (
<Text>{`Failed to start. ${startState.error.message}`}</Text>
)}
<Button variant="Critical" onClick={mx ? () => startMatrix(mx) : loadMatrix}>
<Text as="span" size="B400">
Retry
</Text>
</Button>
</Box>
</Dialog>
</Box>
</SplashScreen>
)}
{loading || !mx ? (
<ClientRootLoading />
) : (
<MatrixClientProvider value={mx}>
<ServerConfigsLoader>
{(serverConfigs) => (
<CapabilitiesProvider value={serverConfigs.capabilities ?? {}}>
<MediaConfigProvider value={serverConfigs.mediaConfig ?? {}}>
<AuthMetadataProvider value={serverConfigs.authMetadata}>
{children}
</AuthMetadataProvider>
</MediaConfigProvider>
</CapabilitiesProvider>
)}
</ServerConfigsLoader>
</MatrixClientProvider>
)}
</SpecVersions>
<AutoDiscovery userId={userId!} baseUrl={baseUrl!}>
<SpecVersions baseUrl={baseUrl!}>
{mx && <SyncStatus mx={mx} />}
{loading && <ClientRootOptions mx={mx} />}
{(loadState.status === AsyncStatus.Error || startState.status === AsyncStatus.Error) && (
<SplashScreen>
<Box
direction="Column"
grow="Yes"
alignItems="Center"
justifyContent="Center"
gap="400"
>
<Dialog>
<Box direction="Column" gap="400" style={{ padding: config.space.S400 }}>
{loadState.status === AsyncStatus.Error && (
<Text>{`Failed to load. ${loadState.error.message}`}</Text>
)}
{startState.status === AsyncStatus.Error && (
<Text>{`Failed to start. ${startState.error.message}`}</Text>
)}
<Button variant="Critical" onClick={mx ? () => startMatrix(mx) : loadMatrix}>
<Text as="span" size="B400">
Retry
</Text>
</Button>
</Box>
</Dialog>
</Box>
</SplashScreen>
)}
{loading || !mx ? (
<ClientRootLoading />
) : (
<MatrixClientProvider value={mx}>
<ServerConfigsLoader>
{(serverConfigs) => (
<CapabilitiesProvider value={serverConfigs.capabilities ?? {}}>
<MediaConfigProvider value={serverConfigs.mediaConfig ?? {}}>
<AuthMetadataProvider value={serverConfigs.authMetadata}>
{children}
</AuthMetadataProvider>
</MediaConfigProvider>
</CapabilitiesProvider>
)}
</ServerConfigsLoader>
</MatrixClientProvider>
)}
</SpecVersions>
</AutoDiscovery>
);
}