Compare commits

..

No commits in common. "7c80643aba266fc0279c593f1951931f3fbb9ce2" and "e2b3dc13fb2679d23de1b8c5a450330fbe854159" have entirely different histories.

5 changed files with 27 additions and 81 deletions

View File

@ -1,14 +1,12 @@
import { createPortal } from 'react-dom'
import styles from './style.module.scss' import styles from './style.module.scss'
import { PropsWithChildren } from 'react'
interface Props { interface Props {
desc?: string desc?: string
variant?: 'small' | 'default' variant?: 'small' | 'default'
} }
export const LoadingSpinner = (props: PropsWithChildren<Props>) => { export const LoadingSpinner = (props: Props) => {
const { desc, children, variant = 'default' } = props const { desc, variant = 'default' } = props
switch (variant) { switch (variant) {
case 'small': case 'small':
@ -22,22 +20,16 @@ export const LoadingSpinner = (props: PropsWithChildren<Props>) => {
) )
default: default:
return createPortal( return (
<div className={styles.loadingSpinnerOverlay}> <div className={styles.loadingSpinnerOverlay}>
<div <div
className={styles.loadingSpinnerContainer} className={styles.loadingSpinnerContainer}
data-variant={variant} data-variant={variant}
> >
<div className={styles.loadingSpinner}></div> <div className={styles.loadingSpinner}></div>
{desc && ( {desc && <p className={styles.loadingSpinnerDesc}>{desc}</p>}
<div className={styles.loadingSpinnerDesc}>
{desc}
{children}
</div>
)}
</div> </div>
</div>, </div>
document.getElementById('root')!
) )
} }
} }

View File

@ -42,15 +42,11 @@
width: 100%; width: 100%;
padding: 15px; padding: 15px;
border-top: solid 1px rgba(0, 0, 0, 0.1); border-top: solid 1px rgba(0, 0, 0, 0.1);
text-align: center;
color: rgba(0, 0, 0, 0.5); color: rgba(0, 0, 0, 0.5);
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
} }
@keyframes spin { @keyframes spin {

View File

@ -18,16 +18,12 @@ import {
} from '../../store/actions' } from '../../store/actions'
import { LoginMethods } from '../../store/auth/types' import { LoginMethods } from '../../store/auth/types'
import { Dispatch } from '../../store/store' import { Dispatch } from '../../store/store'
import { npubToHex, queryNip05, timeout } from '../../utils' import { npubToHex, queryNip05 } from '../../utils'
import { hexToBytes } from '@noble/hashes/utils' import { hexToBytes } from '@noble/hashes/utils'
import { NIP05_REGEX } from '../../constants' import { NIP05_REGEX } from '../../constants'
import styles from './styles.module.scss' import styles from './styles.module.scss'
import { TimeoutError } from '../../types/errors/TimeoutError'
const EXTENSION_LOGIN_DELAY_SECONDS = 2
const EXTENSION_LOGIN_TIMEOUT_SECONDS = EXTENSION_LOGIN_DELAY_SECONDS + 10
export const Nostr = () => { export const Nostr = () => {
const [searchParams] = useSearchParams() const [searchParams] = useSearchParams()
@ -40,7 +36,6 @@ export const Nostr = () => {
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('') const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
const [isExtensionSlow, setIsExtensionSlow] = useState(false)
const [inputValue, setInputValue] = useState('') const [inputValue, setInputValue] = useState('')
const [authUrl, setAuthUrl] = useState<string>() const [authUrl, setAuthUrl] = useState<string>()
@ -77,39 +72,27 @@ export const Nostr = () => {
} }
const loginWithExtension = async () => { const loginWithExtension = async () => {
try { setIsLoading(true)
// Wait EXTENSION_LOGIN_DELAY_SECONDS before showing extension delay message setLoadingSpinnerDesc('Capturing pubkey from nostr extension')
const waitTimeout = window.setTimeout(() => {
setIsExtensionSlow(true)
}, 2000)
setIsLoading(true) nostrController
setLoadingSpinnerDesc('Capturing pubkey from nostr extension') .capturePublicKey()
.then(async (pubkey) => {
dispatch(updateLoginMethod(LoginMethods.extension))
const pubkey = await nostrController.capturePublicKey() setLoadingSpinnerDesc('Authenticating and finding metadata')
dispatch(updateLoginMethod(LoginMethods.extension)) const redirectPath =
await authController.authAndGetMetadataAndRelaysMap(pubkey)
setLoadingSpinnerDesc('Authenticating and finding metadata') if (redirectPath) navigateAfterLogin(redirectPath)
const redirectPath = await Promise.race([ })
authController.authAndGetMetadataAndRelaysMap(pubkey), .catch((err) => {
timeout(EXTENSION_LOGIN_TIMEOUT_SECONDS * 1000) toast.error('Error capturing public key from nostr extension: ' + err)
]) })
.finally(() => {
if (redirectPath) { setIsLoading(false)
window.clearTimeout(waitTimeout) setLoadingSpinnerDesc('')
navigateAfterLogin(redirectPath) })
}
} catch (error) {
if (error instanceof TimeoutError) {
toast.error("Extension didn't respond in time")
} else {
toast.error('Error capturing public key from nostr extension: ' + error)
}
} finally {
setIsLoading(false)
setLoadingSpinnerDesc('')
setIsExtensionSlow(false)
}
} }
/** /**
@ -371,25 +354,7 @@ export const Nostr = () => {
return ( return (
<> <>
{isLoading && ( {isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
<LoadingSpinner desc={loadingSpinnerDesc}>
{isExtensionSlow && (
<>
<p>Extension is not responding</p>
<Button
fullWidth
variant="contained"
onClick={() => {
setLoadingSpinnerDesc('')
setIsLoading(false)
}}
>
Close
</Button>
</>
)}
</LoadingSpinner>
)}
{isNostrExtensionAvailable && ( {isNostrExtensionAvailable && (
<> <>

View File

@ -1,6 +0,0 @@
export class TimeoutError extends Error {
constructor() {
super('Timeout')
this.name = this.constructor.name
}
}

View File

@ -1,4 +1,3 @@
import { TimeoutError } from '../types/errors/TimeoutError.ts'
import { CurrentUserFile } from '../types/file.ts' import { CurrentUserFile } from '../types/file.ts'
import { SigitFile } from './file.ts' import { SigitFile } from './file.ts'
@ -64,7 +63,7 @@ export const timeout = (ms: number = 60000) => {
// Set a timeout using setTimeout // Set a timeout using setTimeout
setTimeout(() => { setTimeout(() => {
// Reject the promise with an Error indicating a timeout // Reject the promise with an Error indicating a timeout
reject(new TimeoutError()) reject(new Error('Timeout'))
}, ms) // Timeout duration in milliseconds }, ms) // Timeout duration in milliseconds
}) })
} }