From 402cc633f902c31c2744e4708237d22085fdcfc9 Mon Sep 17 00:00:00 2001 From: Richard Liu Date: Mon, 15 Jul 2024 01:53:20 -0700 Subject: [PATCH] add screen improvements when not logged in (#1828) When logged out, rather than forcing user to register / log in _before_ seeing any kind of add screen, we do it after they see the initial "add pcd" screen. --- .../screens/AddScreen/AddScreen.tsx | 19 +++---- .../screens/AddScreen/JustAddScreen.tsx | 53 ++++++++++++------- .../screens/AddScreen/ProveAndAddScreen.tsx | 9 +++- .../LoginScreens/LoginInterstitialScreen.tsx | 4 +- .../screens/LoginScreens/LoginScreen.tsx | 4 +- .../components/shared/AppHeader.tsx | 7 ++- 6 files changed, 60 insertions(+), 36 deletions(-) diff --git a/apps/passport-client/components/screens/AddScreen/AddScreen.tsx b/apps/passport-client/components/screens/AddScreen/AddScreen.tsx index 3cce3cf342..4dd324f040 100644 --- a/apps/passport-client/components/screens/AddScreen/AddScreen.tsx +++ b/apps/passport-client/components/screens/AddScreen/AddScreen.tsx @@ -6,9 +6,8 @@ import { } from "@pcd/passport-interface"; import { useEffect } from "react"; import { useLocation } from "react-router-dom"; -import { useDispatch, useLoginIfNoSelf, useSelf } from "../../../src/appHooks"; +import { useDispatch } from "../../../src/appHooks"; import { validateRequest } from "../../../src/passportRequest"; -import { pendingRequestKeys } from "../../../src/sessionStorage"; import { useSyncE2EEStorage } from "../../../src/useSyncE2EEStorage"; import { err } from "../../../src/util"; import { AppContainer } from "../../shared/AppContainer"; @@ -23,11 +22,11 @@ import { ProveAndAddScreen } from "./ProveAndAddScreen"; export function AddScreen(): JSX.Element | null { useSyncE2EEStorage(); const dispatch = useDispatch(); - const self = useSelf(); const location = useLocation(); const params = new URLSearchParams(location.search); const request = validateRequest(params); - const screen = getScreen(request); + const autoAdd = params.get("autoAdd") === "true"; + const screen = getScreen(request, autoAdd); useEffect(() => { if (screen === null) { @@ -35,12 +34,6 @@ export function AddScreen(): JSX.Element | null { } }, [dispatch, screen]); - useLoginIfNoSelf(pendingRequestKeys.add, request); - - if (!self) { - return null; - } - if (!screen) { // Need AppContainer to display error return ; @@ -48,12 +41,14 @@ export function AddScreen(): JSX.Element | null { return screen; } -function getScreen(request: PCDRequest): JSX.Element | null { +function getScreen(request: PCDRequest, autoAdd: boolean): JSX.Element | null { switch (request.type) { case PCDRequestType.ProveAndAdd: return ; case PCDRequestType.Add: - return ; + return ( + + ); default: return null; } diff --git a/apps/passport-client/components/screens/AddScreen/JustAddScreen.tsx b/apps/passport-client/components/screens/AddScreen/JustAddScreen.tsx index 61cd61ee85..c251e2777b 100644 --- a/apps/passport-client/components/screens/AddScreen/JustAddScreen.tsx +++ b/apps/passport-client/components/screens/AddScreen/JustAddScreen.tsx @@ -5,13 +5,18 @@ import { requestLogToServer } from "@pcd/passport-interface"; import { getErrorMessage } from "@pcd/util"; -import { useCallback, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import styled from "styled-components"; import { appConfig } from "../../../src/appConfig"; import { useDispatch, useIsSyncSettled, useSelf } from "../../../src/appHooks"; +import { + clearAllPendingRequests, + pendingRequestKeys +} from "../../../src/sessionStorage"; import { useDeserialized } from "../../../src/useDeserialized"; import { err } from "../../../src/util"; import { Button, H2, Spacer } from "../../core"; +import { RippleLoader } from "../../core/RippleLoader"; import { MaybeModal } from "../../modals/Modal"; import { AddedPCD } from "../../shared/AddedPCD"; import { AppContainer } from "../../shared/AppContainer"; @@ -26,9 +31,11 @@ import { useTensionConfetti } from "../ProtocolWorldsScreens/useTensionConfetti" * a PCD into their wallet without proving it. */ export function JustAddScreen({ - request + request, + autoAdd }: { request: PCDAddRequest; + autoAdd: boolean; // Automatically add item on load }): JSX.Element { const dispatch = useDispatch(); const [added, setAdded] = useState(false); @@ -38,14 +45,23 @@ export function JustAddScreen({ const isProtocolWorlds = request.folder === ProtocolWorldsFolderName; const [ref, setRef] = useState(null); const confetti = useTensionConfetti(ref); + const hasAutoAdded = useRef(false); const onAddClick = useCallback(async () => { + // If not logged in, direct user to log in + if (!self) { + clearAllPendingRequests(); + const stringifiedRequest = JSON.stringify(request ?? ""); + + sessionStorage.setItem(pendingRequestKeys.add, stringifiedRequest); + window.location.href = `/#/login?redirectedFromAction=true&${ + pendingRequestKeys.add + }=${encodeURIComponent(stringifiedRequest)}`; + return; + } try { // This is mostly for typechecking and should never throw // because checks if the user is logged in - if (!self) { - throw new Error("User must be logged in"); - } await dispatch({ type: "add-pcds", pcds: [request.pcd], @@ -64,26 +80,23 @@ export function JustAddScreen({ } catch (e) { await err(dispatch, "Error Adding PCD", getErrorMessage(e)); } - }, [ - confetti, - dispatch, - request.folder, - request.pcd, - self, - pcd, - isProtocolWorlds - ]); + }, [confetti, dispatch, self, pcd, isProtocolWorlds, request]); + + useEffect(() => { + if (autoAdd && !hasAutoAdded.current) { + onAddClick(); + hasAutoAdded.current = true; + } + }, [autoAdd, onAddClick]); let content; - if (!syncSettled) { + if (self && !syncSettled) { return ; } else if (!added) { content = ( <> -

- {isProtocolWorlds ? "TENSION DISCOVERED" : "ADD PCD".toUpperCase()} -

+ {isProtocolWorlds &&

{"TENSION DISCOVERED".toUpperCase()}

} {pcd && ( - PCD will be added to folder: + This item will be added to folder:
{request.folder} )} @@ -114,6 +127,8 @@ export function JustAddScreen({ } else { window.location.hash = "#/"; } + } else if (autoAdd) { + content = ; } else { content = window.close()} />; } diff --git a/apps/passport-client/components/screens/AddScreen/ProveAndAddScreen.tsx b/apps/passport-client/components/screens/AddScreen/ProveAndAddScreen.tsx index 7dedf08e7d..bf73f59133 100644 --- a/apps/passport-client/components/screens/AddScreen/ProveAndAddScreen.tsx +++ b/apps/passport-client/components/screens/AddScreen/ProveAndAddScreen.tsx @@ -2,8 +2,13 @@ import { PCDProveAndAddRequest } from "@pcd/passport-interface"; import { PCD, SerializedPCD } from "@pcd/pcd-types"; import { ReactNode, useCallback, useState } from "react"; import styled from "styled-components"; -import { useDispatch, useIsSyncSettled } from "../../../src/appHooks"; +import { + useDispatch, + useIsSyncSettled, + useLoginIfNoSelf +} from "../../../src/appHooks"; import { safeRedirect } from "../../../src/passportRequest"; +import { pendingRequestKeys } from "../../../src/sessionStorage"; import { H2, Spacer } from "../../core"; import { MaybeModal } from "../../modals/Modal"; import { AddedPCD } from "../../shared/AddedPCD"; @@ -27,6 +32,8 @@ export function ProveAndAddScreen({ SerializedPCD | undefined >(); + useLoginIfNoSelf(pendingRequestKeys.add, request); + const onProve = useCallback( async (_: PCD | undefined, serializedPCD: SerializedPCD | undefined) => { if (serializedPCD) { diff --git a/apps/passport-client/components/screens/LoginScreens/LoginInterstitialScreen.tsx b/apps/passport-client/components/screens/LoginScreens/LoginInterstitialScreen.tsx index dc2078719e..164459b0dc 100644 --- a/apps/passport-client/components/screens/LoginScreens/LoginInterstitialScreen.tsx +++ b/apps/passport-client/components/screens/LoginScreens/LoginInterstitialScreen.tsx @@ -32,7 +32,9 @@ export function LoginInterstitialScreen(): JSX.Element { console.log("Redirecting to add screen"); const encReq = encodeURIComponent(pendingRequest.value); clearAllPendingRequests(); - navigate("/add?request=" + encReq, { replace: true }); + navigate("/add?request=" + encReq + "&autoAdd=true", { + replace: true + }); break; } case "halo": { diff --git a/apps/passport-client/components/screens/LoginScreens/LoginScreen.tsx b/apps/passport-client/components/screens/LoginScreens/LoginScreen.tsx index 94b5b39843..60830032c1 100644 --- a/apps/passport-client/components/screens/LoginScreens/LoginScreen.tsx +++ b/apps/passport-client/components/screens/LoginScreens/LoginScreen.tsx @@ -151,8 +151,8 @@ export function LoginScreen(): JSX.Element {

ZUPASS

- To complete this request, you need to either log into your existing - Zupass account, or create a new one. + To complete this request, please login or register with your email + below.
) : ( diff --git a/apps/passport-client/components/shared/AppHeader.tsx b/apps/passport-client/components/shared/AppHeader.tsx index e944965bd9..ed4a74b467 100644 --- a/apps/passport-client/components/shared/AppHeader.tsx +++ b/apps/passport-client/components/shared/AppHeader.tsx @@ -3,7 +3,7 @@ import React, { useCallback } from "react"; import { IoMdSettings } from "react-icons/io"; import { MdInfo, MdOutlineQrCodeScanner, MdRssFeed } from "react-icons/md"; import styled from "styled-components"; -import { useDispatch, useSubscriptions } from "../../src/appHooks"; +import { useDispatch, useSelf, useSubscriptions } from "../../src/appHooks"; import { AppState } from "../../src/state"; export const AppHeader = React.memo(AppHeaderImpl); @@ -18,6 +18,7 @@ function AppHeaderImpl({ isProveOrAddScreen?: boolean; }): JSX.Element { const dispatch = useDispatch(); + const self = useSelf(); const setModal = useCallback( (modal: AppState["modal"]) => @@ -44,6 +45,10 @@ function AppHeaderImpl({ ); const subscriptions = useSubscriptions(); + if (!self) { + return {children}; + } + return (