add Nostr-login package #217
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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'
|
||||||
|
Loading…
Reference in New Issue
Block a user