diff --git a/src/app/hooks/useParsedLoginFlows.ts b/src/app/hooks/useParsedLoginFlows.ts index 14ecfb9d..088a514e 100644 --- a/src/app/hooks/useParsedLoginFlows.ts +++ b/src/app/hooks/useParsedLoginFlows.ts @@ -1,16 +1,10 @@ import { useMemo } from 'react'; import { ILoginFlow, IPasswordFlow, ISSOFlow, LoginFlow } from 'matrix-js-sdk/lib/@types/auth'; -import { WithRequiredProp } from '../../types/utils'; -export type Required_SSOFlow = WithRequiredProp<ISSOFlow, 'identity_providers'>; -export const getSSOFlow = (loginFlows: LoginFlow[]): Required_SSOFlow | undefined => - loginFlows.find( - (flow) => - (flow.type === 'm.login.sso' || flow.type === 'm.login.cas') && - 'identity_providers' in flow && - Array.isArray(flow.identity_providers) && - flow.identity_providers.length > 0 - ) as Required_SSOFlow | undefined; +export const getSSOFlow = (loginFlows: LoginFlow[]): ISSOFlow | undefined => + loginFlows.find((flow) => flow.type === 'm.login.sso' || flow.type === 'm.login.cas') as + | ISSOFlow + | undefined; export const getPasswordFlow = (loginFlows: LoginFlow[]): IPasswordFlow | undefined => loginFlows.find((flow) => flow.type === 'm.login.password') as IPasswordFlow; @@ -22,7 +16,7 @@ export const getTokenFlow = (loginFlows: LoginFlow[]): LoginFlow | undefined => export type ParsedLoginFlows = { password?: LoginFlow; token?: LoginFlow; - sso?: Required_SSOFlow; + sso?: ISSOFlow; }; export const useParsedLoginFlows = (loginFlows: LoginFlow[]) => { const parsedFlow: ParsedLoginFlows = useMemo<ParsedLoginFlows>( diff --git a/src/app/pages/auth/SSOLogin.tsx b/src/app/pages/auth/SSOLogin.tsx index 0d3d917f..d0cdaeb6 100644 --- a/src/app/pages/auth/SSOLogin.tsx +++ b/src/app/pages/auth/SSOLogin.tsx @@ -4,69 +4,89 @@ import React, { useMemo } from 'react'; import { useAutoDiscoveryInfo } from '../../hooks/useAutoDiscoveryInfo'; type SSOLoginProps = { - providers: IIdentityProvider[]; - asIcons?: boolean; + providers?: IIdentityProvider[]; redirectUrl: string; + saveScreenSpace?: boolean; }; -export function SSOLogin({ providers, redirectUrl, asIcons }: SSOLoginProps) { +export function SSOLogin({ providers, redirectUrl, saveScreenSpace }: SSOLoginProps) { const discovery = useAutoDiscoveryInfo(); const baseUrl = discovery['m.homeserver'].base_url; const mx = useMemo(() => createClient({ baseUrl }), [baseUrl]); - const getSSOIdUrl = (ssoId: string): string => mx.getSsoLoginUrl(redirectUrl, 'sso', ssoId); + const getSSOIdUrl = (ssoId?: string): string => mx.getSsoLoginUrl(redirectUrl, 'sso', ssoId); - const anyAsBtn = providers.find( - (provider) => !provider.icon || !mx.mxcUrlToHttp(provider.icon, 96, 96, 'crop', false) - ); + const withoutIcon = providers + ? providers.find( + (provider) => !provider.icon || !mx.mxcUrlToHttp(provider.icon, 96, 96, 'crop', false) + ) + : true; + + const renderAsIcons = withoutIcon ? false : saveScreenSpace && providers && providers.length > 2; return ( <Box justifyContent="Center" gap="600" wrap="Wrap"> - {providers.map((provider) => { - const { id, name, icon } = provider; - const iconUrl = icon && mx.mxcUrlToHttp(icon, 96, 96, 'crop', false); + {providers ? ( + providers.map((provider) => { + const { id, name, icon } = provider; + const iconUrl = icon && mx.mxcUrlToHttp(icon, 96, 96, 'crop', false); - const buttonTitle = `Continue with ${name}`; + const buttonTitle = `Continue with ${name}`; + + if (renderAsIcons) { + return ( + <Avatar + style={{ cursor: 'pointer' }} + key={id} + as="a" + href={getSSOIdUrl(id)} + aria-label={buttonTitle} + size="300" + radii="300" + > + <AvatarImage src={iconUrl!} alt={name} title={buttonTitle} /> + </Avatar> + ); + } - if (!anyAsBtn && iconUrl && asIcons) { return ( - <Avatar - style={{ cursor: 'pointer' }} + <Button + style={{ width: '100%' }} key={id} as="a" href={getSSOIdUrl(id)} - aria-label={buttonTitle} - size="300" - radii="300" + size="500" + variant="Secondary" + fill="Soft" + outlined + before={ + iconUrl && ( + <Avatar size="200" radii="300"> + <AvatarImage src={iconUrl} alt={name} /> + </Avatar> + ) + } > - <AvatarImage src={iconUrl} alt={name} title={buttonTitle} /> - </Avatar> + <Text align="Center" size="B500" truncate> + {buttonTitle} + </Text> + </Button> ); - } - - return ( - <Button - style={{ width: '100%' }} - key={id} - as="a" - href={getSSOIdUrl(id)} - size="500" - variant="Secondary" - fill="Soft" - outlined - before={ - iconUrl && ( - <Avatar size="200" radii="300"> - <AvatarImage src={iconUrl} alt={name} /> - </Avatar> - ) - } - > - <Text align="Center" size="B500" truncate> - {buttonTitle} - </Text> - </Button> - ); - })} + }) + ) : ( + <Button + style={{ width: '100%' }} + as="a" + href={getSSOIdUrl()} + size="500" + variant="Secondary" + fill="Soft" + outlined + > + <Text align="Center" size="B500" truncate> + Continue with SSO + </Text> + </Button> + )} </Box> ); } diff --git a/src/app/pages/auth/login/Login.tsx b/src/app/pages/auth/login/Login.tsx index e1689d1e..6b9f1223 100644 --- a/src/app/pages/auth/login/Login.tsx +++ b/src/app/pages/auth/login/Login.tsx @@ -76,9 +76,7 @@ export function Login() { <SSOLogin providers={parsedFlows.sso.identity_providers} redirectUrl={ssoRedirectUrl} - asIcons={ - parsedFlows.password !== undefined && parsedFlows.sso.identity_providers.length > 2 - } + saveScreenSpace={parsedFlows.password !== undefined} /> <span data-spacing-node /> </> diff --git a/src/app/pages/auth/register/Register.tsx b/src/app/pages/auth/register/Register.tsx index c859d0e5..d2986d70 100644 --- a/src/app/pages/auth/register/Register.tsx +++ b/src/app/pages/auth/register/Register.tsx @@ -83,10 +83,7 @@ export function Register() { <SSOLogin providers={sso.identity_providers} redirectUrl={ssoRedirectUrl} - asIcons={ - registerFlows.status === RegisterFlowStatus.FlowRequired && - sso.identity_providers.length > 2 - } + saveScreenSpace={registerFlows.status === RegisterFlowStatus.FlowRequired} /> <span data-spacing-node /> </>