import { useState, type ReactNode } from "react";
import { ModalDialog } from "../ModalDialog/index.tsx";
import { useCurrentUser } from "../store/index.tsx";
import { AccountIssueView } from "./AccountIssueView.tsx";
import { LoginView } from "./LoginView.tsx";
import { useFetchCurrentUser } from "./useFetchCurrentUser.tsx";
import { UserMismatchView } from "./UserMismatchView.tsx";
import { VerifyAccountView } from "./VerifyPage.tsx";
type CurrentUserFetcherProps = {
children: ReactNode;
};
/**
* Fetches fresh current user data if a local user exists in the app store.
*
* This component uses the Indie Tabletop Client under the hood, so if new
* data is successfully fetched, the onCurrentUser callback will be invoked,
* and it is up to the configuration of the client to store the data.
*
* Importantly, this component also handles the various user account issues
* that we could run into: expired session, user mismatch and account deletion.
*
* All other errors are ignored. This allows users to use the app in offline
* mode, and doesn't interrupt their session if some unexpected error happens,
* which they cannot do anything about anyways.
*/
export function CurrentUserFetcher(props: CurrentUserFetcherProps) {
const { children } = props;
const localUser = useCurrentUser();
const [isOpen, setOpen] = useState(true);
const { result, reload } = useFetchCurrentUser({
// We only want to fetch the current user if they exist in the store, i.e.
// they have logged into the app previously.
performFetch: !!localUser,
// If we are performing a fetch, we want to make sure that it is up to date
// every time the user focuses the window.
revalidateOnFocus: true,
});
if (result.isFailure && result.failure.type === "API_ERROR") {
// The user's session has expired. They should be prompted to
// re-authenticate, as any syncing attemps will fail.
if (result.failure.code === 401) {
return (
<>
reload()}
description={undefined}
reload={reload}
/>
{children}
>
);
}
if (result.failure.code === 404) {
// The user account is not found. The user might have been deleted.
// The user should be notified and instructed to log out, as many
// interactions acrosss the app will be broken.
return (
<>
{children}
>
);
}
}
if (localUser && result.isSuccess) {
const serverUser = result.value;
// The cookie (server) user and the user in local storage are a different
// user. The current user needs to decide which account to use.
if (serverUser.id !== localUser.id) {
return (
<>
{children}
>
);
}
if (!serverUser.isVerified) {
return (
<>
setOpen(false)}
reload={reload}
/>
{children}
>
);
}
}
// In all other cases we simply render the children
return <>{children}>;
}