From ddf3995032edfa0decfde732ecbbf3132a48792c Mon Sep 17 00:00:00 2001 From: nikec <43032218+niikeec@users.noreply.github.com> Date: Wed, 4 Oct 2023 11:05:50 +0200 Subject: [PATCH] [ENG-1178] Add optional auth step to onboarding & update profile section (#1426) * Add login step to onboarding * only show auth loader on first fetch --------- Co-authored-by: Brendan Allan --- .../settings/client/SpacedriveAccount.tsx | 95 +++++---------- interface/app/onboarding/alpha.tsx | 2 +- interface/app/onboarding/index.tsx | 5 + interface/app/onboarding/login.tsx | 110 ++++++++++++++++++ interface/components/LoginButton.tsx | 46 ++++++++ 5 files changed, 190 insertions(+), 68 deletions(-) create mode 100644 interface/app/onboarding/login.tsx create mode 100644 interface/components/LoginButton.tsx diff --git a/interface/app/$libraryId/settings/client/SpacedriveAccount.tsx b/interface/app/$libraryId/settings/client/SpacedriveAccount.tsx index a048b945d..924c8483d 100644 --- a/interface/app/$libraryId/settings/client/SpacedriveAccount.tsx +++ b/interface/app/$libraryId/settings/client/SpacedriveAccount.tsx @@ -1,44 +1,7 @@ import { useQueryClient } from '@tanstack/react-query'; -import { useRef, useState } from 'react'; -import { useBridgeMutation, useBridgeQuery, useBridgeSubscription } from '@sd/client'; -import { Button, Card } from '@sd/ui'; -import { usePlatform } from '~/util/Platform'; - -type State = { status: 'Idle' } | { status: 'LoggingIn' }; - -export function LoginButton({ onLogin }: { onLogin: () => void }) { - const [state, setState] = useState({ status: 'Idle' }); - - const platform = usePlatform(); - - const ret = useRef(null); - - useBridgeSubscription(['auth.loginSession'], { - enabled: state.status === 'LoggingIn', - onData(data) { - if (data === 'Complete') { - onLogin(); - platform.auth.finish?.(ret.current); - } else if (data === 'Error') setState({ status: 'Idle' }); - else { - ret.current = platform.auth.start(data.Start.verification_url_complete); - } - }, - onError() { - setState({ status: 'Idle' }); - } - }); - - return ( - - ); -} +import { useBridgeMutation, useBridgeQuery } from '@sd/client'; +import { Button, Card, Loader } from '@sd/ui'; +import { LoginButton } from '~/components/LoginButton'; export function SpacedriveAccount() { const user = useBridgeQuery(['auth.me'], { @@ -51,36 +14,34 @@ export function SpacedriveAccount() { const queryClient = useQueryClient(); return ( - -
-
- Spacedrive Account - {user.isFetchedAfterMount ? ( - user.data ? ( - - ) : ( - - ) + + {!user.data && ( +
+ {!user.isFetchedAfterMount ? ( + ) : ( - 'Loading...' + )}
-
- {user.data ? ( - <>Loggged in as email {user.data.email} - ) : ( - "Login to Spacedrive bc it's cool idk" - )} + )} + +
+
+ Spacedrive Account + +
+
+ Logged in as {user.data?.email}
); diff --git a/interface/app/onboarding/alpha.tsx b/interface/app/onboarding/alpha.tsx index bca04dc2d..26466687e 100644 --- a/interface/app/onboarding/alpha.tsx +++ b/interface/app/onboarding/alpha.tsx @@ -40,7 +40,7 @@ export default function OnboardingAlpha() { Join Discord - + Continue
diff --git a/interface/app/onboarding/index.tsx b/interface/app/onboarding/index.tsx index aa8bd0c02..87f8051dc 100644 --- a/interface/app/onboarding/index.tsx +++ b/interface/app/onboarding/index.tsx @@ -4,6 +4,7 @@ import { getOnboardingStore } from '@sd/client'; import Alpha from './alpha'; import { useOnboardingContext } from './context'; import CreatingLibrary from './creating-library'; +import Login from './login'; import NewLibrary from './new-library'; import Privacy from './privacy'; @@ -23,6 +24,10 @@ export default [ element: }, { path: 'alpha', element: }, + { + element: , + path: 'login' + }, { element: , path: 'new-library' diff --git a/interface/app/onboarding/login.tsx b/interface/app/onboarding/login.tsx new file mode 100644 index 000000000..326bfd0c0 --- /dev/null +++ b/interface/app/onboarding/login.tsx @@ -0,0 +1,110 @@ +import { AppLogo } from '@sd/assets/images'; +import { useQueryClient } from '@tanstack/react-query'; +import { useNavigate } from 'react-router'; +import { useBridgeMutation, useBridgeQuery } from '@sd/client'; +import { Button, ButtonLink, Loader } from '@sd/ui'; +import { LoginButton } from '~/components/LoginButton'; + +import { OnboardingContainer } from './Layout'; + +export default function OnboardingLogin() { + const navigate = useNavigate(); + const queryClient = useQueryClient(); + + const user = useBridgeQuery(['auth.me'], { + // If the backend returns un unauthorized error we don't want to retry + retry: false + }); + + const logout = useBridgeMutation(['auth.logout']); + + return ( + + {user.isLoading && !user.isFetchedAfterMount ? ( + + ) : user.data ? ( + <> +
+ Spacedrive logo +

+ Logged in as {user.data.email} +

+
+ +
+ + Continue + + +
+ Not you? + +
+
+ + ) : ( + <> +
+ Spacedrive logo +

+ Log in to Spacedrive +

+
+ +
+ navigate('../new-library', { replace: true })} + > + Log in with browser + + +
+ Want to do this later? + + Skip login + +
+
+ + )} +
+ ); +} diff --git a/interface/components/LoginButton.tsx b/interface/components/LoginButton.tsx new file mode 100644 index 000000000..597f82bab --- /dev/null +++ b/interface/components/LoginButton.tsx @@ -0,0 +1,46 @@ +import { useRef, useState } from 'react'; +import { useBridgeSubscription } from '@sd/client'; +import { Button, ButtonProps } from '@sd/ui'; + +import { usePlatform } from '..'; + +type State = { status: 'Idle' } | { status: 'LoggingIn' }; + +interface Props extends ButtonProps { + onLogin?(): void; +} + +export function LoginButton({ children, onLogin, ...props }: Props) { + const [state, setState] = useState({ status: 'Idle' }); + + const platform = usePlatform(); + + const ret = useRef(null); + + useBridgeSubscription(['auth.loginSession'], { + enabled: state.status === 'LoggingIn', + onData(data) { + if (data === 'Complete') { + onLogin?.(); + platform.auth.finish?.(ret.current); + } else if (data === 'Error') setState({ status: 'Idle' }); + else { + ret.current = platform.auth.start(data.Start.verification_url_complete); + } + }, + onError() { + setState({ status: 'Idle' }); + } + }); + + return ( + + ); +}