import { Box } from '@mui/material' import Container from '@mui/material/Container' import { useEffect, useState } from 'react' import { useDispatch, useSelector } from 'react-redux' import { Outlet } from 'react-router-dom' import { AppBar } from '../components/AppBar/AppBar' import { restoreState, setAuthState, setMetadataEvent } from '../store/actions' import { clearAuthToken, clearState, getRoboHashPicture, loadState, saveNsecBunkerDelegatedKey } from '../utils' import { LoadingSpinner } from '../components/LoadingSpinner' import { Dispatch } from '../store/store' import { MetadataController, NostrController } from '../controllers' import { LoginMethods } from '../store/auth/types' import { setUserRobotImage } from '../store/userRobotImage/action' import { State } from '../store/rootReducer' import { Event, kinds } from 'nostr-tools' export const MainLayout = () => { const dispatch: Dispatch = useDispatch() const [isLoading, setIsLoading] = useState(true) const authState = useSelector((state: State) => state.auth) useEffect(() => { const metadataController = new MetadataController() const logout = () => { dispatch( setAuthState({ keyPair: undefined, loggedIn: false, usersPubkey: undefined, loginMethod: undefined, nsecBunkerPubkey: undefined }) ) dispatch(setMetadataEvent(metadataController.getEmptyMetadataEvent())) // clear authToken saved in local storage clearAuthToken() clearState() // update nsecBunker delegated key const newDelegatedKey = NostrController.getInstance().generateDelegatedKey() saveNsecBunkerDelegatedKey(newDelegatedKey) } const restoredState = loadState() if (restoredState) { dispatch(restoreState(restoredState)) const { loggedIn, loginMethod, usersPubkey, nsecBunkerRelays } = restoredState.auth if (loggedIn) { if (!loginMethod || !usersPubkey) return logout() if (loginMethod === LoginMethods.nsecBunker) { if (!nsecBunkerRelays) return logout() const nostrController = NostrController.getInstance() nostrController.nsecBunkerInit(nsecBunkerRelays).then(() => { nostrController.createNsecBunkerSigner(usersPubkey) }) } const handleMetadataEvent = (event: Event) => { dispatch(setMetadataEvent(event)) } metadataController.on(usersPubkey, (kind: number, event: Event) => { if (kind === kinds.Metadata) { handleMetadataEvent(event) } }) metadataController.findMetadata(usersPubkey).then((metadataEvent) => { if (metadataEvent) handleMetadataEvent(metadataEvent) }) } } setIsLoading(false) }, [dispatch]) /** * When authState change user logged in / or app reloaded * we set robohash avatar in the global state based on user npub * so that avatar will be consistent across the app when kind 0 is empty */ useEffect(() => { if (authState && authState.loggedIn) { const pubkey = authState.usersPubkey || authState.keyPair?.public if (pubkey) { dispatch(setUserRobotImage(getRoboHashPicture(pubkey))) } } }, [authState]) if (isLoading) return return ( <> ) }