add Nostr-login package #217

Merged
enes merged 20 commits from nostr-login-9-30 into staging 2024-10-09 08:54:33 +00:00
2 changed files with 100 additions and 109 deletions
Showing only changes of commit 23a04faad8 - Show all commits

View File

@ -86,7 +86,7 @@ export class AuthController {
return Promise.resolve(appPrivateRoutes.relays) return Promise.resolve(appPrivateRoutes.relays)
} }
if (store.getState().auth?.loggedIn) { if (store.getState().auth.loggedIn) {
if (!compareObjects(store.getState().relays?.map, relayMap.map)) if (!compareObjects(store.getState().relays?.map, relayMap.map))
store.dispatch(setRelayMapAction(relayMap.map)) store.dispatch(setRelayMapAction(relayMap.map))
} }

View File

@ -37,8 +37,8 @@ export const MainLayout = () => {
const logout = useLogout() const logout = useLogout()
const [isLoading, setIsLoading] = useState(true) const [isLoading, setIsLoading] = useState(true)
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState(`Loading App`) const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState(`Loading App`)
const isLoggedIn = useAppSelector((state) => state.auth?.loggedIn)
const authState = useAppSelector((state) => state.auth) const authState = useAppSelector((state) => state.auth)
const usersAppData = useAppSelector((state) => state.userAppData)
// Ref to track if `subscribeForSigits` has been called // Ref to track if `subscribeForSigits` has been called
const hasSubscribed = useRef(false) const hasSubscribed = useRef(false)
@ -72,104 +72,6 @@ export const MainLayout = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [dispatch]) }, [dispatch])
useEffect(() => {
const handleNostrAuth = (_: string, opts: NostrLoginAuthOptions) => {
if (opts.type === 'logout') {
logout()
} else {
dispatch(updateNostrLoginAuthMethod(opts.method))
login()
}
}
;(async () => {
try {
const options = {
methods: ['connect', 'extension', 'local'],
noBanner: true,
onAuth: handleNostrAuth
}
await initNostrLogin(options)
console.log('Nostr-Login initialized successfully')
} catch (error) {
console.error('Failed to initialize Nostr-Login', error)
}
})()
}, [dispatch, login, logout])
useEffect(() => {
const metadataController = MetadataController.getInstance()
const restoredState = loadState()
if (restoredState) {
dispatch(restoreState(restoredState))
const { loggedIn, loginMethod, usersPubkey } = restoredState.auth
if (loggedIn) {
if (!loginMethod || !usersPubkey) return logout()
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)
})
} else {
setIsLoading(false)
}
} else {
setIsLoading(false)
}
}, [dispatch, logout])
useEffect(() => {
if (authState && authState.loggedIn && usersAppData) {
const pubkey = authState.usersPubkey || authState.keyPair?.public
if (pubkey && !hasSubscribed.current) {
// Call `subscribeForSigits` only if it hasn't been called before
// #193 disabled websocket subscribtion, until #194 is done
subscribeForSigits(pubkey)
// Mark `subscribeForSigits` as called
hasSubscribed.current = true
}
}
}, [authState, usersAppData])
/**
* 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)))
}
setIsLoading(true)
setLoadingSpinnerDesc(`Loading SIGit history...`)
getUsersAppData()
.then((appData) => {
if (appData) {
dispatch(updateUserAppData(appData))
}
})
.finally(() => setIsLoading(false))
}
}, [authState, dispatch])
useEffect(() => { useEffect(() => {
// Developer login with ?nsec= (not recommended) // Developer login with ?nsec= (not recommended)
const nsec = searchParams.get('nsec') const nsec = searchParams.get('nsec')
@ -201,15 +103,14 @@ export const MainLayout = () => {
}) })
) )
dispatch(updateLoginMethod(LoginMethod.privateKey)) dispatch(updateLoginMethod(LoginMethod.privateKey))
;(async () => {
const authController = new AuthController() const authController = new AuthController()
await authController authController
.authAndGetMetadataAndRelaysMap(publickey) .authAndGetMetadataAndRelaysMap(publickey)
.catch((err) => { .catch((err) => {
console.error('Error occurred in authentication: ' + err) console.error('Error occurred in authentication: ' + err)
return null return null
}) })
})()
} catch (err) { } catch (err) {
console.error(`Error decoding the nsec. ${err}`) console.error(`Error decoding the nsec. ${err}`)
} }
@ -217,6 +118,96 @@ export const MainLayout = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [dispatch, searchParams]) }, [dispatch, searchParams])
useEffect(() => {
const handleNostrAuth = (_: string, opts: NostrLoginAuthOptions) => {
if (opts.type === 'login' || opts.type === 'signup') {
dispatch(updateNostrLoginAuthMethod(opts.method))
login()
}
}
// Initialize the nostr-login
initNostrLogin({
methods: ['connect', 'extension', 'local'],
noBanner: true,
onAuth: handleNostrAuth
}).catch((error) => {
console.error('Failed to initialize Nostr-Login', error)
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dispatch])
useEffect(() => {
const metadataController = MetadataController.getInstance()
const restoredState = loadState()
if (restoredState) {
dispatch(restoreState(restoredState))
const { loggedIn, loginMethod, usersPubkey } = restoredState.auth
if (loggedIn) {
if (!loginMethod || !usersPubkey) return logout()
// Update user profile metadata, old state might be outdated
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)
})
} else {
setIsLoading(false)
}
} else {
setIsLoading(false)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [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 && isLoggedIn) {
const pubkey = authState.usersPubkey || authState.keyPair?.public
if (pubkey && !hasSubscribed.current) {
// Call `subscribeForSigits` only if it hasn't been called before
// #193 disabled websocket subscribtion, until #194 is done
subscribeForSigits(pubkey)
// Mark `subscribeForSigits` as called
hasSubscribed.current = true
}
if (pubkey) {
dispatch(setUserRobotImage(getRoboHashPicture(pubkey)))
}
setIsLoading(true)
setLoadingSpinnerDesc(`Loading SIGit history...`)
getUsersAppData()
.then((appData) => {
if (appData) {
dispatch(updateUserAppData(appData))
}
})
.finally(() => setIsLoading(false))
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dispatch, isLoggedIn])
if (isLoading) return <LoadingSpinner desc={loadingSpinnerDesc} /> if (isLoading) return <LoadingSpinner desc={loadingSpinnerDesc} />
const isDev = import.meta.env.MODE === 'development' const isDev = import.meta.env.MODE === 'development'