Merge pull request #71 from nostrband/develop

Many minor fixes in UI, spinners etc.
This commit is contained in:
Nostr.Band 2024-02-15 09:28:45 +03:00 committed by GitHub
commit 34b516a1e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 68 additions and 44 deletions

View File

@ -5,8 +5,6 @@ import { useAppDispatch } from './store/hooks/redux'
import { setApps, setKeys, setPending, setPerms } from './store/reducers/content.slice'
import AppRoutes from './routes/AppRoutes'
import { fetchProfile, ndk } from './modules/nostr'
import { useModalSearchParams } from './hooks/useModalSearchParams'
import { MODAL_PARAMS_KEYS } from './types/modal'
import { ModalInitial } from './components/Modal/ModalInitial/ModalInitial'
import { ModalImportKeys } from './components/Modal/ModalImportKeys/ModalImportKeys'
import { ModalSignUp } from './components/Modal/ModalSignUp/ModalSignUp'
@ -14,7 +12,6 @@ import { ModalLogin } from './components/Modal/ModalLogin/ModalLogin'
function App() {
const [render, setRender] = useState(0)
const { handleOpen } = useModalSearchParams()
const dispatch = useAppDispatch()
const [isConnected, setIsConnected] = useState(false)

View File

@ -3,7 +3,7 @@ import { Button } from '@/shared/Button/Button'
import { Input } from '@/shared/Input/Input'
import { Modal } from '@/shared/Modal/Modal'
import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { Autocomplete, CircularProgress, Stack, Typography } from '@mui/material'
import { Autocomplete, Stack, Typography } from '@mui/material'
import { StyledInput } from './styled'
import { FormEvent, useEffect, useState } from 'react'
import { isEmptyString } from '@/utils/helpers/helpers'
@ -13,6 +13,7 @@ import { selectApps } from '@/store'
import { dbi } from '@/modules/db'
import { useEnqueueSnackbar } from '@/hooks/useEnqueueSnackbar'
import { setApps } from '@/store/reducers/content.slice'
import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner'
export const ModalAppDetails = () => {
const { getModalOpened, createHandleCloseReplace } = useModalSearchParams()
@ -118,7 +119,7 @@ export const ModalAppDetails = () => {
}
}
const isFormValid = !isEmptyString(url) && !isEmptyString(name) && !isEmptyString(icon)
const isFormValid = !isEmptyString(url) && !isEmptyString(name)
return (
<Modal open={isModalOpened} onClose={handleCloseModal}>
@ -165,7 +166,7 @@ export const ModalAppDetails = () => {
/>
<Button varianttype="secondary" type="submit" fullWidth disabled={!isFormValid || isLoading}>
Save changes {isLoading && <CircularProgress sx={{ marginLeft: '0.5rem' }} size={'1rem'} />}
Save changes {isLoading && <LoadingSpinner />}
</Button>
</Stack>
</Modal>

View File

@ -5,7 +5,7 @@ import { Button } from '@/shared/Button/Button'
import { Input } from '@/shared/Input/Input'
import { Modal } from '@/shared/Modal/Modal'
import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { CircularProgress, Stack, Typography, useTheme } from '@mui/material'
import { Stack, Typography, useTheme } from '@mui/material'
import { StyledAppLogo } from './styled'
import { useNavigate } from 'react-router-dom'
import { useForm } from 'react-hook-form'
@ -18,6 +18,7 @@ import { fetchNip05 } from '@/utils/helpers/helpers'
import { DOMAIN } from '@/utils/consts'
import { CheckmarkIcon } from '@/assets'
import { getPublicKey, nip19 } from 'nostr-tools'
import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner'
const FORM_DEFAULT_VALUES = {
username: '',
@ -69,12 +70,13 @@ export const ModalImportKeys = () => {
}
try {
const { type, data } = nip19.decode(debouncedNsec)
const ok = type === 'nsec';
const ok = type === 'nsec'
setIsBadNsec(!ok)
if (ok) {
const npub = nip19.npubEncode(
// @ts-ignore
getPublicKey(data))
getPublicKey(data)
)
setIsTakenByNsec(!!nameNpub && nameNpub === npub)
} else {
setIsTakenByNsec(false)
@ -84,7 +86,8 @@ export const ModalImportKeys = () => {
setIsTakenByNsec(false)
return
}
}, [debouncedNsec])
// eslint-disable-next-line
}, [debouncedNsec])
useEffect(() => {
checkNsecUsername()
@ -106,8 +109,8 @@ export const ModalImportKeys = () => {
if (isLoading) return undefined
try {
const { nsec, username } = values
if (!nsec || !username) throw new Error("Enter username and nsec")
if (nameNpub && !isTakenByNsec) throw new Error("Name taken")
if (!nsec || !username) throw new Error('Enter username and nsec')
if (nameNpub && !isTakenByNsec) throw new Error('Name taken')
setIsLoading(true)
const k: any = await swicCall('importKey', username, nsec)
notify('Key imported!', 'success')
@ -186,16 +189,14 @@ export const ModalImportKeys = () => {
helperTextProps={{
sx: {
'&.helper_text': {
color: isBadNsec
? theme.palette.error.main
: theme.palette.textSecondaryDecorate.main,
color: isBadNsec ? theme.palette.error.main : theme.palette.textSecondaryDecorate.main,
},
},
}}
/>
<Button type="submit" disabled={isLoading}>
Import key {isLoading && <CircularProgress sx={{ marginLeft: '0.5rem' }} size={'1rem'} />}
Import key {isLoading && <LoadingSpinner />}
</Button>
</Stack>
</Modal>

View File

@ -4,7 +4,7 @@ import { useModalSearchParams } from '@/hooks/useModalSearchParams'
import { swicCall } from '@/modules/swic'
import { Modal } from '@/shared/Modal/Modal'
import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { CircularProgress, Stack, Typography } from '@mui/material'
import { Stack, Typography } from '@mui/material'
import { StyledAppLogo } from './styled'
import { Input } from '@/shared/Input/Input'
import { Button } from '@/shared/Button/Button'
@ -16,6 +16,7 @@ import { DOMAIN } from '@/utils/consts'
import { fetchNip05, fetchNpubNames } from '@/utils/helpers/helpers'
import { usePassword } from '@/hooks/usePassword'
import { dbi } from '@/modules/db'
import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner'
const FORM_DEFAULT_VALUES = {
username: '',
@ -142,7 +143,7 @@ export const ModalLogin = () => {
error={!!errors.password}
/>
<Button type="submit" fullWidth disabled={isLoading}>
Add account {isLoading && <CircularProgress sx={{ marginLeft: '0.5rem' }} size={'1rem'} />}
Add account {isLoading && <LoadingSpinner />}
</Button>
</Stack>
</Modal>

View File

@ -1,8 +1,7 @@
import { useModalSearchParams } from '@/hooks/useModalSearchParams'
import { Button } from '@/shared/Button/Button'
import { Modal } from '@/shared/Modal/Modal'
import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { Box, CircularProgress, Stack, Typography } from '@mui/material'
import { Box, Stack, Typography } from '@mui/material'
import { StyledButton, StyledSettingContainer, StyledSynchedText } from './styled'
import { SectionTitle } from '@/shared/SectionTitle/SectionTitle'
import { CheckmarkIcon } from '@/assets'
@ -17,6 +16,7 @@ import { usePassword } from '@/hooks/usePassword'
import { useAppSelector } from '@/store/hooks/redux'
import { selectKeys } from '@/store'
import { isValidPassphase, isWeakPassphase } from '@/modules/keys'
import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner'
type ModalSettingsProps = {
isSynced: boolean
@ -116,15 +116,7 @@ export const ModalSettings: FC<ModalSettingsProps> = ({ isSynced }) => {
{...inputProps}
onChange={handlePasswordChange}
value={enteredPassword}
// helperText={isPasswordInvalid ? 'Invalid password' : ''}
placeholder="Enter a password"
// helperTextProps={{
// sx: {
// '&.helper_text': {
// color: 'red',
// },
// },
// }}
disabled={!isChecked}
/>
{isPasswordInvalid ? (
@ -150,10 +142,9 @@ export const ModalSettings: FC<ModalSettingsProps> = ({ isSynced }) => {
</Typography>
)}
<StyledButton type="submit" fullWidth disabled={!isChecked}>
Sync {isLoading && <CircularProgress sx={{ marginLeft: '0.5rem' }} size={'1rem'} />}
Sync {isLoading && <LoadingSpinner mode="secondary" />}
</StyledButton>
</StyledSettingContainer>
{/* <Button onClick={onClose}>Done</Button> */}
</Stack>
</Modal>
)

View File

@ -2,7 +2,7 @@ import { useEnqueueSnackbar } from '@/hooks/useEnqueueSnackbar'
import { useModalSearchParams } from '@/hooks/useModalSearchParams'
import { Modal } from '@/shared/Modal/Modal'
import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { CircularProgress, Stack, Typography, useTheme } from '@mui/material'
import { Stack, Typography, useTheme } from '@mui/material'
import React, { ChangeEvent, useEffect, useState } from 'react'
import { StyledAppLogo } from './styled'
import { Input } from '@/shared/Input/Input'
@ -12,6 +12,7 @@ import { swicCall } from '@/modules/swic'
import { useNavigate } from 'react-router-dom'
import { DOMAIN } from '@/utils/consts'
import { fetchNip05 } from '@/utils/helpers/helpers'
import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner'
export const ModalSignUp = () => {
const { getModalOpened, createHandleCloseReplace } = useModalSearchParams()
@ -113,7 +114,7 @@ export const ModalSignUp = () => {
}}
/>
<Button fullWidth type="submit" disabled={isLoading}>
Create account {isLoading && <CircularProgress sx={{ marginLeft: '0.5rem' }} size={'1rem'} />}
Create account {isLoading && <LoadingSpinner />}
</Button>
</Stack>
</Modal>

View File

@ -23,7 +23,7 @@ export const Header = () => {
}
const isDarkMode = themeMode === 'dark'
const themeIcon = isDarkMode ? <DarkModeIcon htmlColor="#fff" /> : <LightModeIcon htmlColor="#000" />
const themeIcon = isDarkMode ? <LightModeIcon htmlColor="#fff" /> : <DarkModeIcon htmlColor="#000" />
const handleChangeMode = () => {
dispatch(setThemeMode({ mode: isDarkMode ? 'light' : 'dark' }))

View File

@ -9,6 +9,7 @@ import { useModalSearchParams } from '@/hooks/useModalSearchParams'
import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { useState } from 'react'
import { getReferrerAppUrl } from '@/utils/helpers/helpers'
import { LoadingSpinner } from '@/shared/LoadingSpinner/LoadingSpinner'
const CreatePage = () => {
const notify = useEnqueueSnackbar()
@ -17,6 +18,8 @@ const CreatePage = () => {
const [searchParams] = useSearchParams()
const [isLoading, setIsLoading] = useState(false)
const name = searchParams.get('name') || ''
const token = searchParams.get('token') || ''
const appNpub = searchParams.get('appNpub') || ''
@ -31,12 +34,14 @@ const CreatePage = () => {
const handleClickAddAccount = async () => {
try {
setIsLoading(true)
const key: any = await swicCall('generateKey', name)
const appUrl = getReferrerAppUrl();
const appUrl = getReferrerAppUrl()
console.log('Created', key.npub, 'app', appUrl)
setCreated(true)
setIsLoading(false)
handleOpen(MODAL_PARAMS_KEYS.CONFIRM_CONNECT, {
search: {
@ -53,6 +58,7 @@ const CreatePage = () => {
})
} catch (error: any) {
notify(error.message || error.toString(), 'error')
setIsLoading(false)
}
}
@ -88,7 +94,9 @@ const CreatePage = () => {
<Typography textAlign={'left'} variant="h6" paddingTop="0.5em">
Chosen name: <b>{nip05}</b>
</Typography>
<GetStartedButton onClick={handleClickAddAccount}>Create account</GetStartedButton>
<GetStartedButton onClick={handleClickAddAccount}>
Create account {isLoading && <LoadingSpinner />}
</GetStartedButton>
<Typography textAlign={'left'} variant="h5" paddingTop="1em">
What you need to know:

View File

@ -70,12 +70,19 @@ export const useTriggerConfirmModal = (npub: string, pending: DbPending[], perms
search: {
appNpub: req.appNpub,
reqId: req.id,
popup: isPopup ? 'true' : ''
popup: isPopup ? 'true' : '',
},
})
break
}
}, [connectPendings, filteredPendingReqs.length, handleOpen, isConfirmEventModalOpened, isConfirmConnectModalOpened])
}, [
connectPendings,
filteredPendingReqs.length,
handleOpen,
isConfirmEventModalOpened,
isConfirmConnectModalOpened,
isPopup,
])
const handleOpenConfirmEventModal = useCallback(() => {
if (!filteredPendingReqs.length || connectPendings.length) return undefined
@ -91,12 +98,12 @@ export const useTriggerConfirmModal = (npub: string, pending: DbPending[], perms
handleOpen(MODAL_PARAMS_KEYS.CONFIRM_EVENT, {
search: {
appNpub,
popup: isPopup ? 'true' : ''
popup: isPopup ? 'true' : '',
},
})
break
}
}, [connectPendings.length, filteredPendingReqs.length, handleOpen, prepareEventPendings])
}, [connectPendings.length, filteredPendingReqs.length, handleOpen, prepareEventPendings, isPopup])
useEffect(() => {
handleOpenConfirmEventModal()

View File

@ -48,6 +48,7 @@ export const StyledEmptyAppsBox = styled(Box)(({ theme }) => {
placeItems: 'center',
color: theme.palette.text.primary,
opacity: '0.6',
maxHeight: '100%',
},
}
})

View File

@ -28,20 +28,20 @@ const StyledButton = styled(
},
color: theme.palette.text.primary,
'&.disabled': {
opacity: 0.5,
background: `${theme.palette.backgroundSecondary.default}50`,
cursor: 'not-allowed',
},
}
}
return {
...commonStyles,
'&.button:is(:hover, :active, &, .disabled)': {
'&.button:is(:hover, :active, &)': {
background: theme.palette.primary.main,
},
color: theme.palette.text.secondary,
'&.disabled': {
color: theme.palette.text.secondary,
opacity: 0.5,
background: `${theme.palette.primary.main}50`,
cursor: 'not-allowed',
},
}

View File

@ -0,0 +1,17 @@
import { CircularProgress, CircularProgressProps, styled } from '@mui/material'
import { FC } from 'react'
type LoadingSpinnerProps = CircularProgressProps & {
mode?: 'default' | 'secondary'
}
export const LoadingSpinner: FC<LoadingSpinnerProps> = (props) => {
return <StyledCircularProgress {...props} />
}
export const StyledCircularProgress = styled((props: LoadingSpinnerProps) => (
<CircularProgress size={'1rem'} {...props} />
))(({ theme, mode = 'default' }) => ({
marginLeft: '0.5rem',
color: mode === 'default' ? theme.palette.text.secondary : theme.palette.text.primary,
}))

View File

@ -125,8 +125,7 @@ export const getReferrerAppUrl = () => {
if (!window.document.referrer) return ''
try {
const u = new URL(window.document.referrer.toLocaleLowerCase())
if (u.hostname != DOMAIN && !u.hostname.endsWith("."+DOMAIN))
return u.origin
if (u.hostname !== DOMAIN && !u.hostname.endsWith('.' + DOMAIN)) return u.origin
} catch {}
return ''
}