diff --git a/src/components/App/Splash/SpiningSphere/index.tsx b/src/components/App/Splash/SpiningSphere/index.tsx index 72df649ae..b725120d4 100644 --- a/src/components/App/Splash/SpiningSphere/index.tsx +++ b/src/components/App/Splash/SpiningSphere/index.tsx @@ -1,20 +1,33 @@ -import Lottie from 'react-lottie' +import lottie, { AnimationItem } from 'lottie-web' import { Flex } from '~/components/common/Flex' + +import { useEffect, useRef } from 'react' import preloadData from './preloader.json' -export const SphereAnimation = () => ( - - { + const lottieRef = useRef(null) + + useEffect(() => { + const container = document.getElementById('lottie-sphere-animation') + + if (container) { + lottieRef.current = lottie.loadAnimation({ + container, + animationData: preloadData, loop: true, autoplay: true, - animationData: preloadData, rendererSettings: { preserveAspectRatio: 'xMidYMid slice', }, - }} - width={167} - /> - -) + }) + } + + return () => { + if (lottieRef.current) { + lottieRef.current.destroy() + } + } + }, []) + + return +} diff --git a/src/components/App/Splash/index.tsx b/src/components/App/Splash/index.tsx index b1dd2db84..fe617ce30 100644 --- a/src/components/App/Splash/index.tsx +++ b/src/components/App/Splash/index.tsx @@ -8,9 +8,9 @@ import { getAboutData, getStats } from '~/network/fetchSourcesData' import { useAppStore } from '~/stores/useAppStore' import { useDataStore } from '~/stores/useDataStore' import { colors, formatSplashMessage, formatStatsResponse } from '~/utils' -import { SphereAnimation } from './SpiningSphere' import { AnimatedTextContent } from './animated' -import { Message, initialMessageData } from './constants' +import { initialMessageData, Message } from './constants' +import { SphereAnimation } from './SpiningSphere' export const Splash = () => { const [message, setMessage] = useState(initialMessageData) @@ -61,7 +61,9 @@ export const Splash = () => { } return () => { - clearInterval(intervalId) + if (intervalId) { + clearInterval(intervalId) + } } }, [appMetaData, fetchData, isFetching, message, stats]) diff --git a/src/components/AppContainer/index.tsx b/src/components/AppContainer/index.tsx index 572ced7ae..a9678ab2d 100644 --- a/src/components/AppContainer/index.tsx +++ b/src/components/AppContainer/index.tsx @@ -1,20 +1,16 @@ import { lazy, Suspense } from 'react' import { Route, Routes } from 'react-router-dom' -import { useDataStore } from '~/stores/useDataStore' import { E2ETests } from '~/utils' import { AppProviders } from '../App/Providers' -import { Splash } from '../App/Splash' import { AuthGuard } from '../Auth' const LazyApp = lazy(() => import('../App').then(({ App }) => ({ default: App }))) export const AppContainer = () => { const App = - const { splashDataLoading } = useDataStore((s) => s) return ( - {splashDataLoading && } Loading...}> diff --git a/src/components/Auth/__tests__/index.tsx b/src/components/Auth/__tests__/index.tsx index dae5b633c..cf0076ef1 100644 --- a/src/components/Auth/__tests__/index.tsx +++ b/src/components/Auth/__tests__/index.tsx @@ -142,7 +142,17 @@ describe('Auth Component', () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore sphinx.enable.mockResolvedValue({ pubkey: 'testPubkey' }) - getIsAdminMock.mockResolvedValue({ data: { isAdmin: false, isPublic: false, isMember: false } }) + + getIsAdminMock.mockRejectedValue({ + response: { + status: 401, + data: { + status: 'error', + message: 'Permission denied', + }, + }, + }) + getSignedMessageFromRelayMock.mockResolvedValue({ message: 'testMessage', signature: 'testSignature' }) render( @@ -157,7 +167,13 @@ describe('Auth Component', () => { , ) - await waitFor(() => expect(screen.getByText(message)).toBeInTheDocument()) + await waitFor(() => { + expect(getIsAdminMock).toHaveBeenCalled() + }) + + await waitFor(() => { + expect(screen.getByText(message)).toBeInTheDocument() + }) }) test.skip('the unauthorized state is correctly set when the user lacks proper credentials', async () => { diff --git a/src/components/Auth/index.tsx b/src/components/Auth/index.tsx index b451be49a..677775e7f 100644 --- a/src/components/Auth/index.tsx +++ b/src/components/Auth/index.tsx @@ -5,15 +5,19 @@ import { Flex } from '~/components/common/Flex' import { Text } from '~/components/common/Text' import { isDevelopment, isE2E } from '~/constants' import { getIsAdmin } from '~/network/auth' +import { useDataStore } from '~/stores/useDataStore' import { useFeatureFlagStore } from '~/stores/useFeatureFlagStore' import { useUserStore } from '~/stores/useUserStore' import { sphinxBridge } from '~/testSphinxBridge' import { updateBudget } from '~/utils' import { isAndroid, isWebView } from '~/utils/isWebView' +import { Splash } from '../App/Splash' export const AuthGuard = ({ children }: PropsWithChildren) => { const [unAuthorized, setUnauthorized] = useState(false) const { setBudget, setIsAdmin, setPubKey, setIsAuthenticated } = useUserStore((s) => s) + const { splashDataLoading } = useDataStore((s) => s) + const [renderMainPage, setRenderMainPage] = useState(false) const [ setTrendingTopicsFeatureFlag, @@ -62,12 +66,6 @@ export const AuthGuard = ({ children }: PropsWithChildren) => { try { const res = await getIsAdmin() - if (!res.data.isPublic && !res.data.isAdmin && !res.data.isMember) { - setUnauthorized(true) - - return - } - if (res.data) { localStorage.setItem('admin', JSON.stringify({ isAdmin: res.data.isAdmin })) @@ -80,8 +78,10 @@ export const AuthGuard = ({ children }: PropsWithChildren) => { } setIsAuthenticated(true) + setRenderMainPage(true) } catch (error) { /* not an admin */ + setUnauthorized(true) } }, [ setIsAuthenticated, @@ -125,7 +125,12 @@ export const AuthGuard = ({ children }: PropsWithChildren) => { ) } - return <>{children} + return ( + <> + {splashDataLoading && } + {renderMainPage && children} + + ) } const StyledText = styled(Text)` diff --git a/src/utils/getSignedMessage/index.ts b/src/utils/getSignedMessage/index.ts index 18b9a2fbe..fa366bb00 100644 --- a/src/utils/getSignedMessage/index.ts +++ b/src/utils/getSignedMessage/index.ts @@ -35,7 +35,11 @@ export async function getSignedMessageFromRelay(): Promise<{ message: string; si .then((storedLsat: any) => { signingPromise = null // Reset the promise after it's resolved - const response = { message, signature: storedLsat.signature } + if (!storedLsat) { + return { message: '', signature: '' } + } + + const response = { message, signature: storedLsat?.signature || '' } storeSignatureInLocalStorage({ ...response })