Responsiveness and tabs #179

Merged
enes merged 23 commits from 177-sticky-side-columns into staging 2024-09-05 07:30:55 +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 nostrImage from '../../assets/images/nostr.gif'
import { appPublicRoutes } from '../../routes'
import { createPortal } from 'react-dom'
export const Footer = () => (
<footer className={`${styles.borderTop} ${styles.footer}`}>
<Container
style={{
paddingBlock: '50px'
}}
>
<Box
display={'grid'}
sx={{
gridTemplateColumns: {
xs: '1fr',
md: '0.5fr 2fr 0.5fr'
},
alignItems: {
xs: 'center',
md: 'start'
}
export const Footer = () =>
createPortal(
<footer className={`${styles.borderTop} ${styles.footer}`}>
<Container
style={{
paddingBlock: '50px'
}}
gap={'50px'}
>
<LinkMui
<Box
display={'grid'}
sx={{
justifySelf: {
gridTemplateColumns: {
xs: '1fr',
md: '0.5fr 2fr 0.5fr'
},
alignItems: {
xs: 'center',
md: 'start'
}
}}
component={Link}
to={'/'}
className={styles.logo}
gap={'50px'}
>
<img src="/logo.svg" alt="Logo" />
</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
<LinkMui
sx={{
justifyContent: 'center'
justifySelf: {
xs: 'center',
md: 'start'
}
}}
component={Link}
to={'/'}
variant={'text'}
className={styles.logo}
>
Home
</Button>
<Button
<img src="/logo.svg" alt="Logo" />
</LinkMui>
<Box
display={'grid'}
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}
href={appPublicRoutes.docs}
target="_blank"
variant={'text'}
component={'nav'}
className={styles.nav}
>
Documentation
</Button>
<Button
<Button
sx={{
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={{
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
className={styles.links}
sx={{
justifySelf: {
xs: 'center',
md: 'end'
}
}}
>
<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>
</Container>
<div className={`${styles.borderTop} ${styles.credits}`}>
Built by&nbsp;
<a href="https://nostrdev.com/" target="_blank">
Nostr Dev
</a>{' '}
2024.
</div>
</footer>
)
</Container>
<div className={`${styles.borderTop} ${styles.credits}`}>
Built by&nbsp;
<a href="https://nostrdev.com/" target="_blank">
Nostr Dev
</a>{' '}
2024.
</div>
</footer>,
document.getElementById('root')!
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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