From 6aa38d7d20d369e2c75928f3f60769db7bba37f5 Mon Sep 17 00:00:00 2001 From: Matthieu Sieben Date: Mon, 15 Apr 2024 14:08:58 +0200 Subject: [PATCH] feat(oauth-client-browser): simplify login ux & allow popup mode --- .../oauth-client-browser-example/src/app.tsx | 6 +- .../src/login-form.tsx | 78 ++++++++++++------- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/packages/oauth-client-browser-example/src/app.tsx b/packages/oauth-client-browser-example/src/app.tsx index 8b175e4fcd7..d3dc8a67cac 100644 --- a/packages/oauth-client-browser-example/src/app.tsx +++ b/packages/oauth-client-browser-example/src/app.tsx @@ -83,11 +83,7 @@ function App() { ) : ( - void signIn(input)} - /> + ) } diff --git a/packages/oauth-client-browser-example/src/login-form.tsx b/packages/oauth-client-browser-example/src/login-form.tsx index fba84c4d573..6e8b325e560 100644 --- a/packages/oauth-client-browser-example/src/login-form.tsx +++ b/packages/oauth-client-browser-example/src/login-form.tsx @@ -1,4 +1,4 @@ -import { FormEvent, useState } from 'react' +import { FormEvent, useEffect, useState } from 'react' /** * @returns Nice tailwind css form asking to enter either a handle or the host @@ -7,25 +7,59 @@ import { FormEvent, useState } from 'react' export default function LoginForm({ onLogin, loading, - error, + error = null, ...props }: { loading?: boolean error?: null | string - onLogin: (input: string) => void + onLogin: (input: string, options?: { display?: 'popup' | 'page' }) => void } & React.HTMLAttributes) { const [value, setValue] = useState('') - const [loginType, setLoginType] = useState<'handle' | 'host'>('handle') + const [display, setDisplay] = useState<'popup' | 'page'>('popup') + const [localError, setLocalError] = useState(error) + + useEffect(() => { + setLocalError(null) + }, [value]) + + useEffect(() => { + setLocalError(error) + }, [error]) const onSubmit = (e: FormEvent) => { e.preventDefault() if (loading) return - onLogin( - loginType === 'host' && !/^https?:\/\//.test(value) - ? `https://${value}` - : value, - ) + if (value.startsWith('did:')) { + if (value.length > 5) onLogin(value, { display }) + else setLocalError('DID must be at least 6 characters') + return + } + + if (value.startsWith('https://')) { + try { + const url = new URL(value) + if (value !== url.origin) throw new Error('PDS URL must be a origin') + onLogin(value, { display }) + } catch (err) { + setLocalError((err as any)?.message || String(err)) + } + return + } + + if (value.startsWith('http://')) { + setLocalError('PDS URL must be a secure origin') + return + } + + if (value.includes('.') && value.length > 3) { + const handle = value.startsWith('@') ? value.slice(1) : value + if (handle.length > 3) onLogin(handle, { display }) + else setLocalError('Handle must be at least 4 characters') + return + } + + setLocalError('Please provide a valid handle, DID or PDS URL') } return ( @@ -33,35 +67,25 @@ export default function LoginForm({
{/*
*/}
- setValue(e.target.value)} @@ -76,7 +100,9 @@ export default function LoginForm({
- {error ?
{error}
: null} + {localError ? ( +
{localError}
+ ) : null} ) }