new release #190

Merged
b merged 68 commits from staging into main 2024-09-06 18:59:34 +00:00
10 changed files with 362 additions and 339 deletions
Showing only changes of commit a48751b9a8 - Show all commits

View File

@ -4,125 +4,128 @@ import styles from './style.module.scss'
import { Container } from '../Container' import { Container } from '../Container'
import nostrImage from '../../assets/images/nostr.gif' import nostrImage from '../../assets/images/nostr.gif'
import { appPublicRoutes } from '../../routes' import { appPublicRoutes } from '../../routes'
import { createPortal } from 'react-dom'
export const Footer = () => ( export const Footer = () =>
<footer className={`${styles.borderTop} ${styles.footer}`}> createPortal(
<Container <footer className={`${styles.borderTop} ${styles.footer}`}>
style={{ <Container
paddingBlock: '50px' style={{
}} paddingBlock: '50px'
>
<Box
display={'grid'}
sx={{
gridTemplateColumns: {
xs: '1fr',
md: '0.5fr 2fr 0.5fr'
},
alignItems: {
xs: 'center',
md: 'start'
}
}} }}
gap={'50px'}
> >
<LinkMui <Box
display={'grid'}
sx={{ sx={{
justifySelf: { gridTemplateColumns: {
xs: '1fr',
md: '0.5fr 2fr 0.5fr'
},
alignItems: {
xs: 'center', xs: 'center',
md: 'start' md: 'start'
} }
}} }}
component={Link} gap={'50px'}
to={'/'}
className={styles.logo}
> >
<img src="/logo.svg" alt="Logo" /> <LinkMui
</LinkMui>
<Box
display={'grid'}
sx={{
gap: '15px',
gridTemplateColumns: {
xs: '1fr',
sm: 'repeat(2, 1fr)',
xl: 'repeat(3, 1fr)'
},
borderBlock: {
xs: 'solid 1px rgba(0, 0, 0, 0.1)',
md: 'unset'
},
paddingY: {
xs: '10px',
md: 'unset'
}
}}
component={'nav'}
className={styles.nav}
>
<Button
sx={{ sx={{
justifyContent: 'center' justifySelf: {
xs: 'center',
md: 'start'
}
}} }}
component={Link} component={Link}
to={'/'} to={'/'}
variant={'text'} className={styles.logo}
> >
Home <img src="/logo.svg" alt="Logo" />
</Button> </LinkMui>
<Button <Box
display={'grid'}
sx={{ sx={{
justifyContent: 'center' gap: '15px',
gridTemplateColumns: {
xs: '1fr',
sm: 'repeat(2, 1fr)',
xl: 'repeat(3, 1fr)'
},
borderBlock: {
xs: 'solid 1px rgba(0, 0, 0, 0.1)',
md: 'unset'
},
paddingY: {
xs: '10px',
md: 'unset'
}
}} }}
component={LinkMui} component={'nav'}
href={appPublicRoutes.docs} className={styles.nav}
target="_blank"
variant={'text'}
> >
Documentation <Button
</Button> sx={{
<Button justifyContent: 'center'
}}
component={Link}
to={'/'}
variant={'text'}
>
Home
</Button>
<Button
sx={{
justifyContent: 'center'
}}
component={LinkMui}
href={appPublicRoutes.docs}
target="_blank"
variant={'text'}
>
Documentation
</Button>
<Button
sx={{
justifyContent: 'center'
}}
component={LinkMui}
href={appPublicRoutes.source}
target="_blank"
variant={'text'}
>
Source
</Button>
</Box>
<Box
className={styles.links}
sx={{ sx={{
justifyContent: 'center' justifySelf: {
xs: 'center',
md: 'end'
}
}} }}
component={LinkMui}
href={appPublicRoutes.source}
target="_blank"
variant={'text'}
> >
Source <Button
</Button> component={LinkMui}
href="https://snort.social/npub1yay8e9sqk94jfgdlkpgeelj2t5ddsj2eu0xwt4kh4xw5ses2rauqnstrdv"
target="_blank"
sx={{
minWidth: '45px',
padding: '10px'
}}
variant={'contained'}
>
<img src={nostrImage} width="25" alt="nostr logo" height="25" />
</Button>
</Box>
</Box> </Box>
<Box </Container>
className={styles.links} <div className={`${styles.borderTop} ${styles.credits}`}>
sx={{ Built by&nbsp;
justifySelf: { <a href="https://nostrdev.com/" target="_blank">
xs: 'center', Nostr Dev
md: 'end' </a>{' '}
} 2024.
}} </div>
> </footer>,
<Button document.getElementById('root')!
component={LinkMui} )
href="https://snort.social/npub1yay8e9sqk94jfgdlkpgeelj2t5ddsj2eu0xwt4kh4xw5ses2rauqnstrdv"
target="_blank"
sx={{
minWidth: '45px',
padding: '10px'
}}
variant={'contained'}
>
<img src={nostrImage} width="25" alt="nostr logo" height="25" />
</Button>
</Box>
</Box>
</Container>
<div className={`${styles.borderTop} ${styles.credits}`}>
Built by&nbsp;
<a href="https://nostrdev.com/" target="_blank">
Nostr Dev
</a>{' '}
2024.
</div>
</footer>
)

View File

@ -26,7 +26,6 @@ import {
} from '../utils' } from '../utils'
import { useAppSelector } from '../hooks' import { useAppSelector } from '../hooks'
import styles from './style.module.scss' import styles from './style.module.scss'
import { Footer } from '../components/Footer/Footer'
export const MainLayout = () => { export const MainLayout = () => {
const dispatch: Dispatch = useDispatch() const dispatch: Dispatch = useDispatch()
@ -160,7 +159,6 @@ export const MainLayout = () => {
> >
<Outlet /> <Outlet />
</main> </main>
<Footer />
</> </>
) )
} }

View File

@ -18,6 +18,7 @@ import {
SigitCardDisplayInfo, SigitCardDisplayInfo,
SigitStatus SigitStatus
} from '../../utils' } from '../../utils'
import { Footer } from '../../components/Footer/Footer'
// Unsupported Filter options are commented // Unsupported Filter options are commented
const FILTERS = [ const FILTERS = [
@ -262,6 +263,7 @@ export const HomePage = () => {
))} ))}
</div> </div>
</Container> </Container>
<Footer />
</div> </div>
) )
} }

View File

@ -19,6 +19,7 @@ import {
faWifi faWifi
} from '@fortawesome/free-solid-svg-icons' } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIconStack } from '../../components/FontAwesomeIconStack' import { FontAwesomeIconStack } from '../../components/FontAwesomeIconStack'
import { Footer } from '../../components/Footer/Footer'
export const LandingPage = () => { export const LandingPage = () => {
const navigate = useNavigate() const navigate = useNavigate()
@ -162,6 +163,7 @@ export const LandingPage = () => {
<Outlet /> <Outlet />
</Container> </Container>
<Footer />
</div> </div>
) )
} }

View File

@ -20,6 +20,7 @@ import {
} from '../../utils' } from '../../utils'
import styles from './style.module.scss' import styles from './style.module.scss'
import { Container } from '../../components/Container' import { Container } from '../../components/Container'
import { Footer } from '../../components/Footer/Footer'
export const ProfilePage = () => { export const ProfilePage = () => {
const navigate = useNavigate() const navigate = useNavigate()
@ -285,6 +286,7 @@ export const ProfilePage = () => {
</Box> </Box>
</Container> </Container>
)} )}
<Footer />
</> </>
) )
} }

View File

@ -13,6 +13,7 @@ import { useNavigate } from 'react-router-dom'
import { appPrivateRoutes, getProfileSettingsRoute } from '../../routes' import { appPrivateRoutes, getProfileSettingsRoute } from '../../routes'
import { State } from '../../store/rootReducer' import { State } from '../../store/rootReducer'
import { Container } from '../../components/Container' import { Container } from '../../components/Container'
import { Footer } from '../../components/Footer/Footer'
export const SettingsPage = () => { export const SettingsPage = () => {
const theme = useTheme() const theme = useTheme()
@ -43,56 +44,59 @@ export const SettingsPage = () => {
} }
return ( return (
<Container> <>
<List <Container>
sx={{ <List
width: '100%', sx={{
bgcolor: 'background.paper' width: '100%',
}} bgcolor: 'background.paper'
subheader={ }}
<ListSubheader subheader={
sx={{ <ListSubheader
fontSize: '1.5rem', sx={{
borderBottom: '0.5px solid', fontSize: '1.5rem',
paddingBottom: 2, borderBottom: '0.5px solid',
paddingTop: 2 paddingBottom: 2,
paddingTop: 2
}}
>
Settings
</ListSubheader>
}
>
<ListItemButton
onClick={() => {
navigate(getProfileSettingsRoute(usersPubkey!))
}} }}
> >
Settings <ListItemIcon>
</ListSubheader> <AccountCircleIcon />
} </ListItemIcon>
> {listItem('Profile')}
<ListItemButton </ListItemButton>
onClick={() => { <ListItemButton
navigate(getProfileSettingsRoute(usersPubkey!)) onClick={() => {
}} navigate(appPrivateRoutes.relays)
> }}
<ListItemIcon> >
<AccountCircleIcon /> <ListItemIcon>
</ListItemIcon> <RouterIcon />
{listItem('Profile')} </ListItemIcon>
</ListItemButton> {listItem('Relays')}
<ListItemButton </ListItemButton>
onClick={() => { <ListItemButton
navigate(appPrivateRoutes.relays) onClick={() => {
}} navigate(appPrivateRoutes.cacheSettings)
> }}
<ListItemIcon> >
<RouterIcon /> <ListItemIcon>
</ListItemIcon> <CachedIcon />
{listItem('Relays')} </ListItemIcon>
</ListItemButton> {listItem('Local Cache')}
<ListItemButton </ListItemButton>
onClick={() => { </List>
navigate(appPrivateRoutes.cacheSettings) </Container>
}} <Footer />
> </>
<ListItemIcon>
<CachedIcon />
</ListItemIcon>
{listItem('Local Cache')}
</ListItemButton>
</List>
</Container>
) )
} }

View File

@ -14,6 +14,7 @@ import { toast } from 'react-toastify'
import { localCache } from '../../../services' import { localCache } from '../../../services'
import { LoadingSpinner } from '../../../components/LoadingSpinner' import { LoadingSpinner } from '../../../components/LoadingSpinner'
import { Container } from '../../../components/Container' import { Container } from '../../../components/Container'
import { Footer } from '../../../components/Footer/Footer'
export const CacheSettingsPage = () => { export const CacheSettingsPage = () => {
const theme = useTheme() const theme = useTheme()
@ -50,48 +51,51 @@ export const CacheSettingsPage = () => {
} }
return ( return (
<Container> <>
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />} <Container>
<List {isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
sx={{ <List
width: '100%', sx={{
bgcolor: 'background.paper', width: '100%',
marginTop: 2 bgcolor: 'background.paper',
}} marginTop: 2
subheader={ }}
<ListSubheader subheader={
sx={{ <ListSubheader
fontSize: '1.5rem', sx={{
borderBottom: '0.5px solid', fontSize: '1.5rem',
paddingBottom: 2, borderBottom: '0.5px solid',
paddingTop: 2 paddingBottom: 2,
}} paddingTop: 2
> }}
Cache Setting >
</ListSubheader> Cache Setting
} </ListSubheader>
> }
<ListItemButton disabled> >
<ListItemIcon> <ListItemButton disabled>
<IosShareIcon /> <ListItemIcon>
</ListItemIcon> <IosShareIcon />
{listItem('Export (coming soon)')} </ListItemIcon>
</ListItemButton> {listItem('Export (coming soon)')}
</ListItemButton>
<ListItemButton disabled> <ListItemButton disabled>
<ListItemIcon> <ListItemIcon>
<InputIcon /> <InputIcon />
</ListItemIcon> </ListItemIcon>
{listItem('Import (coming soon)')} {listItem('Import (coming soon)')}
</ListItemButton> </ListItemButton>
<ListItemButton onClick={handleClearData}> <ListItemButton onClick={handleClearData}>
<ListItemIcon> <ListItemIcon>
<ClearIcon sx={{ color: theme.palette.error.main }} /> <ClearIcon sx={{ color: theme.palette.error.main }} />
</ListItemIcon> </ListItemIcon>
{listItem('Clear Cache')} {listItem('Clear Cache')}
</ListItemButton> </ListItemButton>
</List> </List>
</Container> </Container>
<Footer />
</>
) )
} }

View File

@ -32,6 +32,7 @@ import {
unixNow unixNow
} from '../../../utils' } from '../../../utils'
import { Container } from '../../../components/Container' import { Container } from '../../../components/Container'
import { Footer } from '../../../components/Footer/Footer'
export const ProfileSettingsPage = () => { export const ProfileSettingsPage = () => {
const theme = useTheme() const theme = useTheme()
@ -385,6 +386,7 @@ export const ProfileSettingsPage = () => {
</LoadingButton> </LoadingButton>
)} )}
</Container> </Container>
<Footer />
</> </>
) )
} }

View File

@ -27,6 +27,7 @@ import {
shorten shorten
} from '../../../utils' } from '../../../utils'
import styles from './style.module.scss' import styles from './style.module.scss'
import { Footer } from '../../../components/Footer/Footer'
export const RelaysPage = () => { export const RelaysPage = () => {
const usersPubkey = useAppSelector((state) => state.auth?.usersPubkey) const usersPubkey = useAppSelector((state) => state.auth?.usersPubkey)
@ -270,161 +271,164 @@ const RelayItem = ({
}) })
return ( return (
<Box className={styles.relay}> <>
<List> <Box className={styles.relay}>
<ListItem> <List>
<span <ListItem>
className={[ <span
styles.connectionStatus, className={[
relayConnectionStatus styles.connectionStatus,
? relayConnectionStatus === RelayConnectionState.Connected relayConnectionStatus
? styles.connectionStatusConnected ? relayConnectionStatus === RelayConnectionState.Connected
: styles.connectionStatusNotConnected ? styles.connectionStatusConnected
: styles.connectionStatusUnknown : styles.connectionStatusNotConnected
].join(' ')} : styles.connectionStatusUnknown
/> ].join(' ')}
{relayInfo && />
relayInfo.limitation && {relayInfo &&
relayInfo.limitation?.payment_required && ( relayInfo.limitation &&
<Tooltip title="Paid Relay" arrow placement="top"> relayInfo.limitation?.payment_required && (
<ElectricBoltIcon <Tooltip title="Paid Relay" arrow placement="top">
className={styles.lightningIcon} <ElectricBoltIcon
color="warning" className={styles.lightningIcon}
onClick={() => setDisplayRelayInfo((prev) => !prev)} color="warning"
/> onClick={() => setDisplayRelayInfo((prev) => !prev)}
</Tooltip> />
)} </Tooltip>
)}
<ListItemText primary={relayURI} /> <ListItemText primary={relayURI} />
<Box <Box
className={styles.leaveRelayContainer} className={styles.leaveRelayContainer}
onClick={() => handleLeaveRelay(relayURI)} onClick={() => handleLeaveRelay(relayURI)}
> >
<LogoutIcon /> <LogoutIcon />
<span>Leave</span> <span>Leave</span>
</Box> </Box>
</ListItem> </ListItem>
<Divider className={styles.relayDivider} /> <Divider className={styles.relayDivider} />
<ListItem> <ListItem>
<ListItemText <ListItemText
primary="Publish to this relay?" primary="Publish to this relay?"
secondary={ secondary={
relayInfo ? ( relayInfo ? (
<span <span
onClick={() => setDisplayRelayInfo((prev) => !prev)} onClick={() => setDisplayRelayInfo((prev) => !prev)}
className={styles.showInfo} className={styles.showInfo}
> >
Show info{' '} Show info{' '}
{displayRelayInfo ? ( {displayRelayInfo ? (
<KeyboardArrowUpIcon className={styles.showInfoIcon} /> <KeyboardArrowUpIcon className={styles.showInfoIcon} />
) : ( ) : (
<KeyboardArrowDownIcon className={styles.showInfoIcon} /> <KeyboardArrowDownIcon className={styles.showInfoIcon} />
)} )}
</span> </span>
) : ( ) : (
'' ''
) )
} }
/> />
<Switch <Switch
checked={isWriteRelay} checked={isWriteRelay}
onChange={(event) => handleRelayWriteChange(relayURI, event)} onChange={(event) => handleRelayWriteChange(relayURI, event)}
/> />
</ListItem> </ListItem>
{displayRelayInfo && ( {displayRelayInfo && (
<> <>
<Divider className={styles.relayDivider} /> <Divider className={styles.relayDivider} />
<ListItem> <ListItem>
<Box className={styles.relayInfoContainer}> <Box className={styles.relayInfoContainer}>
{relayInfo && {relayInfo &&
Object.keys(relayInfo).map((key: string) => { Object.keys(relayInfo).map((key: string) => {
const infoTitle = capitalizeFirstLetter( const infoTitle = capitalizeFirstLetter(
key.replace('_', ' ') key.replace('_', ' ')
) )
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
let infoValue = (relayInfo as any)[key] let infoValue = (relayInfo as any)[key]
switch (key) { switch (key) {
case 'pubkey': case 'pubkey':
infoValue = shorten(hexToNpub(infoValue), 15) infoValue = shorten(hexToNpub(infoValue), 15)
break break
case 'limitation': case 'limitation':
infoValue = ( infoValue = (
<ul> <ul>
{Object.keys(infoValue).map((valueKey) => ( {Object.keys(infoValue).map((valueKey) => (
<li key={`${relayURI}_${key}_${valueKey}`}> <li key={`${relayURI}_${key}_${valueKey}`}>
<span className={styles.relayInfoSubTitle}> <span className={styles.relayInfoSubTitle}>
{capitalizeFirstLetter( {capitalizeFirstLetter(
valueKey.split('_').join(' ') valueKey.split('_').join(' ')
)} )}
: :
</span>{' '} </span>{' '}
{`${infoValue[valueKey]}`} {`${infoValue[valueKey]}`}
</li> </li>
))} ))}
</ul> </ul>
) )
break break
case 'fees': case 'fees':
infoValue = ( infoValue = (
<ul> <ul>
{Object.keys(infoValue).map((valueKey) => ( {Object.keys(infoValue).map((valueKey) => (
<li key={`${relayURI}_${key}_${valueKey}`}> <li key={`${relayURI}_${key}_${valueKey}`}>
<span className={styles.relayInfoSubTitle}> <span className={styles.relayInfoSubTitle}>
{capitalizeFirstLetter( {capitalizeFirstLetter(
valueKey.split('_').join(' ') valueKey.split('_').join(' ')
)} )}
: :
</span>{' '} </span>{' '}
{`${infoValue[valueKey].map((fee: RelayFee) => `${fee.amount} ${fee.unit}`)}`} {`${infoValue[valueKey].map((fee: RelayFee) => `${fee.amount} ${fee.unit}`)}`}
</li> </li>
))} ))}
</ul> </ul>
) )
break break
default: default:
break break
} }
if (Array.isArray(infoValue)) { if (Array.isArray(infoValue)) {
infoValue = infoValue.join(', ') infoValue = infoValue.join(', ')
} }
return ( return (
<span key={`${relayURI}_${key}_container`}> <span key={`${relayURI}_${key}_container`}>
<span className={styles.relayInfoTitle}> <span className={styles.relayInfoTitle}>
{infoTitle}: {infoTitle}:
</span>{' '} </span>{' '}
{infoValue} {infoValue}
{key === 'pubkey' ? ( {key === 'pubkey' ? (
<ContentCopyIcon <ContentCopyIcon
className={styles.copyItem} className={styles.copyItem}
onClick={() => { onClick={() => {
navigator.clipboard.writeText( navigator.clipboard.writeText(
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
hexToNpub((relayInfo as any)[key]) hexToNpub((relayInfo as any)[key])
) )
toast.success('Copied to clipboard', { toast.success('Copied to clipboard', {
autoClose: 1000, autoClose: 1000,
hideProgressBar: true hideProgressBar: true
}) })
}} }}
/> />
) : null} ) : null}
</span> </span>
) )
})} })}
</Box> </Box>
</ListItem> </ListItem>
</> </>
)} )}
</List> </List>
</Box> </Box>
<Footer />
</>
) )
} }

View File

@ -53,6 +53,7 @@ import { convertToSigitFile, SigitFile } from '../../utils/file.ts'
import { FileDivider } from '../../components/FileDivider.tsx' import { FileDivider } from '../../components/FileDivider.tsx'
import { ExtensionFileBox } from '../../components/ExtensionFileBox.tsx' import { ExtensionFileBox } from '../../components/ExtensionFileBox.tsx'
import { useScale } from '../../hooks/useScale.tsx' import { useScale } from '../../hooks/useScale.tsx'
import { Footer } from '../../components/Footer/Footer.tsx'
interface PdfViewProps { interface PdfViewProps {
files: CurrentUserFile[] files: CurrentUserFile[]
@ -570,6 +571,7 @@ export const VerifyPage = () => {
</StickySideColumns> </StickySideColumns>
)} )}
</Container> </Container>
<Footer />
</> </>
) )
} }