reject penging requests on close modals & confirm only selected pending reqs in ConfirmEvent

This commit is contained in:
Bekbolsun
2024-01-22 21:27:23 +06:00
parent cb70f41010
commit eff6792d64
16 changed files with 196 additions and 100 deletions

View File

@@ -0,0 +1,4 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="24" height="24" rx="8" stroke="white" stroke-opacity="0.33" stroke-width="1.4"/>
<path d="M19 9L11 17L7 13" stroke="white" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 319 B

View File

@@ -1,4 +1,4 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="24" height="24" rx="8" stroke="white" stroke-opacity="0.33" stroke-width="1.4"/> <rect x="1" y="1" width="24" height="24" rx="8" stroke="black" stroke-opacity="0.33" stroke-width="1.4"/>
<path d="M19 9L11 17L7 13" stroke="white" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> <path d="M19 9L11 17L7 13" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 319 B

After

Width:  |  Height:  |  Size: 319 B

View File

@@ -0,0 +1,3 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="24" height="24" rx="8" stroke="white" stroke-opacity="0.33" stroke-width="1.4"/>
</svg>

After

Width:  |  Height:  |  Size: 209 B

View File

@@ -1,3 +1,3 @@
<svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="26" height="26" viewBox="0 0 26 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1" y="1" width="24" height="24" rx="8" stroke="white" stroke-opacity="0.33" stroke-width="1.4"/> <rect x="1" y="1" width="24" height="24" rx="8" stroke="black" stroke-opacity="0.33" stroke-width="1.4"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 209 B

After

Width:  |  Height:  |  Size: 209 B

View File

@@ -4,7 +4,9 @@ import { ReactComponent as SettingsIcon } from './icons/settings.svg'
import { ReactComponent as CopyIcon } from './icons/copy.svg' import { ReactComponent as CopyIcon } from './icons/copy.svg'
import { ReactComponent as CheckmarkIcon } from './icons/checkmark.svg' import { ReactComponent as CheckmarkIcon } from './icons/checkmark.svg'
import { ReactComponent as CheckedIcon } from './icons/checked.svg' import { ReactComponent as CheckedIcon } from './icons/checked.svg'
import { ReactComponent as CheckedLightIcon } from './icons/checked-light.svg'
import { ReactComponent as UnchekedIcon } from './icons/unchecked.svg' import { ReactComponent as UnchekedIcon } from './icons/unchecked.svg'
import { ReactComponent as UnchekedLightIcon } from './icons/unchecked-light.svg'
import { default as AddImageIcon } from './icons/add-image.svg' import { default as AddImageIcon } from './icons/add-image.svg'
export { export {
@@ -14,6 +16,8 @@ export {
CopyIcon, CopyIcon,
CheckmarkIcon, CheckmarkIcon,
CheckedIcon, CheckedIcon,
CheckedLightIcon,
UnchekedIcon, UnchekedIcon,
UnchekedLightIcon,
AddImageIcon, AddImageIcon,
} }

View File

@@ -5,7 +5,7 @@ import { call, getShortenNpub } from '@/utils/helpers'
import { Avatar, Box, Stack, Typography } from '@mui/material' import { Avatar, Box, Stack, Typography } from '@mui/material'
import { useParams, useSearchParams } from 'react-router-dom' import { useParams, useSearchParams } from 'react-router-dom'
import { useAppSelector } from '@/store/hooks/redux' import { useAppSelector } from '@/store/hooks/redux'
import { selectAppsByNpub, selectPendingsByNpub } from '@/store' import { selectAppsByNpub } from '@/store'
import { StyledButton, StyledToggleButtonsGroup } from './styled' import { StyledButton, StyledToggleButtonsGroup } from './styled'
import { ActionToggleButton } from './сomponents/ActionToggleButton' import { ActionToggleButton } from './сomponents/ActionToggleButton'
import { useState } from 'react' import { useState } from 'react'
@@ -21,38 +21,34 @@ export const ModalConfirmConnect = () => {
const { getModalOpened, handleClose } = useModalSearchParams() const { getModalOpened, handleClose } = useModalSearchParams()
const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_CONNECT) const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_CONNECT)
const handleCloseModal = handleClose( const { npub = '' } = useParams<{ npub: string }>()
MODAL_PARAMS_KEYS.CONFIRM_CONNECT, const apps = useAppSelector((state) => selectAppsByNpub(state, npub))
(sp) => {
sp.delete('appNpub')
},
)
const [selectedActionType, setSelectedActionType] = useState<ACTION_TYPE>( const [selectedActionType, setSelectedActionType] = useState<ACTION_TYPE>(
ACTION_TYPE.BASIC, ACTION_TYPE.BASIC,
) )
const { npub = '' } = useParams<{ npub: string }>()
const apps = useAppSelector((state) => selectAppsByNpub(state, npub))
const pending = useAppSelector((state) => selectPendingsByNpub(state, npub))
const [searchParams] = useSearchParams() const [searchParams] = useSearchParams()
const appNpub = searchParams.get('appNpub') || '' const appNpub = searchParams.get('appNpub') || ''
const pendingReqId = searchParams.get('reqId') || '' const pendingReqId = searchParams.get('reqId') || ''
const triggerApp = apps.find((app) => app.appNpub === appNpub) const triggerApp = apps.find((app) => app.appNpub === appNpub)
const open = Boolean(isModalOpened)
const { name, icon = '' } = triggerApp || {} const { name, icon = '' } = triggerApp || {}
const appName = name || getShortenNpub(appNpub) const appName = name || getShortenNpub(appNpub)
const handleActionTypeChange = (_: any, value: ACTION_TYPE) => { const handleActionTypeChange = (_: any, value: ACTION_TYPE) => {
setSelectedActionType(value) setSelectedActionType(value)
} }
const handleCloseModal = handleClose(
MODAL_PARAMS_KEYS.CONFIRM_CONNECT,
async (sp) => {
sp.delete('appNpub')
sp.delete('reqId')
await swicCall('confirm', pendingReqId, false, false)
},
)
async function confirmPending( async function confirmPending(
id: string, id: string,
allow: boolean, allow: boolean,
@@ -62,11 +58,14 @@ export const ModalConfirmConnect = () => {
await swicCall('confirm', id, allow, remember) await swicCall('confirm', id, allow, remember)
console.log('confirmed', id, allow, remember) console.log('confirmed', id, allow, remember)
}) })
handleCloseModal() handleClose(MODAL_PARAMS_KEYS.CONFIRM_CONNECT, async (sp) => {
sp.delete('appNpub')
sp.delete('reqId')
})
} }
return ( return (
<Modal open={open} onClose={handleCloseModal}> <Modal open={isModalOpened} onClose={handleCloseModal}>
<Stack gap={'1rem'} paddingTop={'1rem'}> <Stack gap={'1rem'} paddingTop={'1rem'}>
<Stack <Stack
direction={'row'} direction={'row'}
@@ -123,7 +122,9 @@ export const ModalConfirmConnect = () => {
</StyledButton> </StyledButton>
<StyledButton <StyledButton
fullWidth fullWidth
onClick={() => confirmPending(pendingReqId, true, true)} onClick={() =>
confirmPending(pendingReqId, true, false)
}
> >
Allow {selectedActionType} actions Allow {selectedActionType} actions
</StyledButton> </StyledButton>

View File

@@ -5,7 +5,6 @@ import { call, getShortenNpub } from '@/utils/helpers'
import { import {
Avatar, Avatar,
Box, Box,
Checkbox,
List, List,
ListItem, ListItem,
ListItemIcon, ListItemIcon,
@@ -17,7 +16,7 @@ import { useParams, useSearchParams } from 'react-router-dom'
import { useAppSelector } from '@/store/hooks/redux' import { useAppSelector } from '@/store/hooks/redux'
import { selectAppsByNpub } from '@/store' import { selectAppsByNpub } from '@/store'
import { ActionToggleButton } from './сomponents/ActionToggleButton' import { ActionToggleButton } from './сomponents/ActionToggleButton'
import { FC, useState } from 'react' import { FC, useEffect, useMemo, useState } from 'react'
import { import {
StyledActionsListContainer, StyledActionsListContainer,
StyledButton, StyledButton,
@@ -26,6 +25,8 @@ import {
import { SectionTitle } from '@/shared/SectionTitle/SectionTitle' import { SectionTitle } from '@/shared/SectionTitle/SectionTitle'
import { swicCall } from '@/modules/swic' import { swicCall } from '@/modules/swic'
import { IPendingsByAppNpub } from '@/pages/KeyPage/Key.Page' import { IPendingsByAppNpub } from '@/pages/KeyPage/Key.Page'
import { Checkbox } from '@/shared/Checkbox/Checkbox'
import { DbPending } from '@/modules/db'
enum ACTION_TYPE { enum ACTION_TYPE {
ALWAYS = 'ALWAYS', ALWAYS = 'ALWAYS',
@@ -48,59 +49,86 @@ export const ACTIONS: { [type: string]: string } = {
sign_event: 'Sign event', sign_event: 'Sign event',
} }
type PendingRequest = DbPending & { checked: boolean }
export const ModalConfirmEvent: FC<ModalConfirmEventProps> = ({ export const ModalConfirmEvent: FC<ModalConfirmEventProps> = ({
confirmEventReqs, confirmEventReqs,
}) => { }) => {
const { getModalOpened, handleClose } = useModalSearchParams() const { getModalOpened, handleClose } = useModalSearchParams()
const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_EVENT) const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_EVENT)
const handleCloseModal = handleClose(
MODAL_PARAMS_KEYS.CONFIRM_EVENT,
(sp) => sp.delete('appNpub'),
)
const [selectedActionType, setSelectedActionType] = useState<ACTION_TYPE>(
ACTION_TYPE.ALWAYS,
)
const { npub = '' } = useParams<{ npub: string }>()
const apps = useAppSelector((state) => selectAppsByNpub(state, npub))
const [searchParams] = useSearchParams() const [searchParams] = useSearchParams()
const appNpub = searchParams.get('appNpub') || '' const appNpub = searchParams.get('appNpub') || ''
const pendingReqId = searchParams.get('reqId') || '' const pendingReqId = searchParams.get('reqId') || ''
const currentAppPendingReqs = confirmEventReqs[appNpub]?.pending || [] const { npub = '' } = useParams<{ npub: string }>()
const apps = useAppSelector((state) => selectAppsByNpub(state, npub))
const [selectedActionType, setSelectedActionType] = useState<ACTION_TYPE>(
ACTION_TYPE.ALWAYS,
)
const [pendingRequests, setPendingRequests] = useState<PendingRequest[]>([])
const currentAppPendingReqs = useMemo(
() => confirmEventReqs[appNpub]?.pending || [],
[confirmEventReqs, appNpub],
)
useEffect(() => {
setPendingRequests(
currentAppPendingReqs.map((pr) => ({ ...pr, checked: true })),
)
}, [currentAppPendingReqs])
const triggerApp = apps.find((app) => app.appNpub === appNpub) const triggerApp = apps.find((app) => app.appNpub === appNpub)
const open = Boolean(isModalOpened)
const { name, icon = '' } = triggerApp || {} const { name, icon = '' } = triggerApp || {}
const appName = name || getShortenNpub(appNpub) const appName = name || getShortenNpub(appNpub)
const handleActionTypeChange = (_: any, value: ACTION_TYPE) => { const handleActionTypeChange = (_: any, value: ACTION_TYPE) => {
setSelectedActionType(value) setSelectedActionType(value)
} }
async function confirmPending( const selectedPendingRequests = pendingRequests.filter((pr) => pr.checked)
id: string,
allow: boolean, const handleCloseModal = handleClose(
remember: boolean, MODAL_PARAMS_KEYS.CONFIRM_EVENT,
) { (sp) => {
currentAppPendingReqs.forEach((req) => { sp.delete('appNpub')
sp.delete('reqId')
selectedPendingRequests.forEach(
async (req) => await swicCall('confirm', req.id, false, false),
)
},
)
async function confirmPending(id: string) {
selectedPendingRequests.forEach((req) => {
call(async () => { call(async () => {
await swicCall('confirm', req.id, allow, remember) if (selectedActionType === ACTION_TYPE.ONCE) {
console.log('confirmed', req.id, id, allow, remember) await swicCall('confirm', req.id, true, false)
} else {
await swicCall('confirm', req.id, true, true)
}
console.log('confirmed', req.id, id, selectedActionType)
}) })
}) })
handleCloseModal() handleClose(MODAL_PARAMS_KEYS.CONFIRM_EVENT, (sp) => {
sp.delete('appNpub')
sp.delete('reqId')
})
}
const handleChangeCheckbox = (reqId: string) => () => {
const newPendingRequests = pendingRequests.map((req) => {
if (req.id === reqId) return { ...req, checked: !req.checked }
return req
})
setPendingRequests(newPendingRequests)
} }
return ( return (
<Modal open={open} onClose={handleCloseModal}> <Modal open={isModalOpened} onClose={handleCloseModal}>
<Stack gap={'1rem'} paddingTop={'1rem'}> <Stack gap={'1rem'} paddingTop={'1rem'}>
<Stack <Stack
direction={'row'} direction={'row'}
@@ -130,14 +158,19 @@ export const ModalConfirmEvent: FC<ModalConfirmEventProps> = ({
<StyledActionsListContainer marginBottom={'1rem'}> <StyledActionsListContainer marginBottom={'1rem'}>
<SectionTitle>Actions</SectionTitle> <SectionTitle>Actions</SectionTitle>
<List> <List>
{currentAppPendingReqs.map((perm) => { {pendingRequests.map((req) => {
return ( return (
<ListItem> <ListItem>
<ListItemIcon> <ListItemIcon>
<Checkbox color='primary' /> <Checkbox
checked={req.checked}
onChange={handleChangeCheckbox(
req.id,
)}
/>
</ListItemIcon> </ListItemIcon>
<ListItemText> <ListItemText>
{ACTIONS[perm.method]} {ACTIONS[req.method]}
</ListItemText> </ListItemText>
</ListItem> </ListItem>
) )
@@ -173,7 +206,7 @@ export const ModalConfirmEvent: FC<ModalConfirmEventProps> = ({
</StyledButton> </StyledButton>
<StyledButton <StyledButton
fullWidth fullWidth
onClick={() => confirmPending(pendingReqId, true, true)} onClick={() => confirmPending(pendingReqId)}
> >
Allow {ACTION_LABELS[selectedActionType]} Allow {ACTION_LABELS[selectedActionType]}
</StyledButton> </StyledButton>

View File

@@ -8,12 +8,17 @@ import { Modal } from '@/shared/Modal/Modal'
import { MODAL_PARAMS_KEYS } from '@/types/modal' import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { getBunkerLink } from '@/utils/helpers' import { getBunkerLink } from '@/utils/helpers'
import { Stack, Typography } from '@mui/material' import { Stack, Typography } from '@mui/material'
import { useRef } from 'react'
import { useParams } from 'react-router-dom' import { useParams } from 'react-router-dom'
export const ModalConnectApp = () => { export const ModalConnectApp = () => {
const { getModalOpened, handleClose, handleOpen } = useModalSearchParams() const { getModalOpened, handleClose, handleOpen } = useModalSearchParams()
const timerRef = useRef<NodeJS.Timeout>()
const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONNECT_APP) const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONNECT_APP)
const handleCloseModal = handleClose(MODAL_PARAMS_KEYS.CONNECT_APP) const handleCloseModal = handleClose(MODAL_PARAMS_KEYS.CONNECT_APP, () => {
clearTimeout(timerRef.current)
})
const notify = useEnqueueSnackbar() const notify = useEnqueueSnackbar()
@@ -37,6 +42,12 @@ export const ModalConnectApp = () => {
} }
} }
const handleCopy = () => {
timerRef.current = setTimeout(() => {
handleCloseModal()
}, 3000)
}
return ( return (
<Modal <Modal
open={isModalOpened} open={isModalOpened}
@@ -53,7 +64,12 @@ export const ModalConnectApp = () => {
}} }}
fullWidth fullWidth
value={bunkerStr} value={bunkerStr}
endAdornment={<InputCopyButton value={bunkerStr} />} endAdornment={
<InputCopyButton
value={bunkerStr}
onCopy={handleCopy}
/>
}
/> />
<AppLink <AppLink
title='What is this?' title='What is this?'

View File

@@ -2,18 +2,19 @@ import { useModalSearchParams } from '@/hooks/useModalSearchParams'
import { Button } from '@/shared/Button/Button' import { Button } from '@/shared/Button/Button'
import { Modal } from '@/shared/Modal/Modal' import { Modal } from '@/shared/Modal/Modal'
import { MODAL_PARAMS_KEYS } from '@/types/modal' import { MODAL_PARAMS_KEYS } from '@/types/modal'
import { Box, Checkbox, IconButton, Stack, Typography } from '@mui/material' import { Box, IconButton, Stack, Typography } from '@mui/material'
import { import {
StyledButton, StyledButton,
StyledSettingContainer, StyledSettingContainer,
StyledSynchedText, StyledSynchedText,
} from './styled' } from './styled'
import { SectionTitle } from '@/shared/SectionTitle/SectionTitle' import { SectionTitle } from '@/shared/SectionTitle/SectionTitle'
import { CheckedIcon, CheckmarkIcon, UnchekedIcon } from '@/assets' import { CheckmarkIcon } from '@/assets'
import { Input } from '@/shared/Input/Input' import { Input } from '@/shared/Input/Input'
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined' import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined'
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined' import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined'
import { ChangeEvent, useState } from 'react' import { ChangeEvent, useState } from 'react'
import { Checkbox } from '@/shared/Checkbox/Checkbox'
export const ModalSettings = () => { export const ModalSettings = () => {
const { getModalOpened, handleClose } = useModalSearchParams() const { getModalOpened, handleClose } = useModalSearchParams()
@@ -62,10 +63,7 @@ export const ModalSettings = () => {
)} )}
</Stack> </Stack>
<Box> <Box>
<Checkbox <Checkbox />
icon={<UnchekedIcon />}
checkedIcon={<CheckedIcon />}
/>
<Typography variant='caption'> <Typography variant='caption'>
Use this login on multiple devices Use this login on multiple devices
</Typography> </Typography>

View File

@@ -9,11 +9,11 @@ import {
export const StyledSettingContainer = styled((props: StackProps) => ( export const StyledSettingContainer = styled((props: StackProps) => (
<Stack {...props} gap={'1rem'} /> <Stack {...props} gap={'1rem'} />
))(() => ({ ))(({ theme }) => ({
padding: '0.75rem', padding: '0.75rem',
borderRadius: '1rem', borderRadius: '1rem',
background: '#000000', background: theme.palette.background.default,
color: '#fff', color: theme.palette.text.primary,
})) }))
export const StyledButton = styled(Button)(({ theme }) => { export const StyledButton = styled(Button)(({ theme }) => {

View File

@@ -9,6 +9,7 @@ export const StyledContainer = styled((props: BoxProps) => <Box {...props} />)(
display: 'flex', display: 'flex',
alignItems: 'center', alignItems: 'center',
gap: '1rem', gap: '1rem',
cursor: 'pointer',
} }
}, },
) )

View File

@@ -51,46 +51,42 @@ const KeyPage = () => {
const nofity = useEnqueueSnackbar() const nofity = useEnqueueSnackbar()
const [profile, setProfile] = useState<MetaEvent | null>(null)
const userName = profile?.info?.name || getShortenNpub(npub)
const userNameWithPrefix = userName + '@nsec.app'
const [showWarning, setShowWarning] = useState(false)
const filteredApps = apps.filter((a) => a.npub === npub) const filteredApps = apps.filter((a) => a.npub === npub)
const filteredPendingReqs = pending.filter((p) => p.npub === npub) const filteredPendingReqs = pending.filter((p) => p.npub === npub)
const filteredPerms = perms.filter((p) => p.npub === npub) const filteredPerms = perms.filter((p) => p.npub === npub)
// eslint-disable-next-line
const npubConnectPerms = filteredPerms.filter( const npubConnectPerms = filteredPerms.filter(
(perm) => perm.perm === 'connect', (perm) => perm.perm === 'connect',
) )
console.log(npubConnectPerms, '=> npubConnectPerms')
const excludeConnectPeqs = filteredPendingReqs.filter( const excludeConnectPeqs = filteredPendingReqs.filter(
(pr) => pr.method !== 'connect', (pr) => pr.method !== 'connect',
) )
const prepareEventPendings = excludeConnectPeqs.reduce<IPendingsByAppNpub>( const prepareEventPendings = excludeConnectPeqs.reduce<IPendingsByAppNpub>(
(acc, current) => { (acc, current) => {
const isConnected = npubConnectPerms.some(
(cp) => cp.appNpub === current.appNpub,
)
if (!acc[current.appNpub]) { if (!acc[current.appNpub]) {
acc[current.appNpub] = { acc[current.appNpub] = {
pending: [current], pending: [current],
isConnected: npubConnectPerms.some( isConnected,
(cp) => cp.appNpub === current.appNpub,
),
} }
return acc
} }
acc[current.appNpub].pending.push(current) acc[current.appNpub].pending.push(current)
acc[current.appNpub].isConnected = npubConnectPerms.some( acc[current.appNpub].isConnected = isConnected
(cp) => cp.appNpub === current.appNpub,
)
return acc return acc
}, },
{}, {},
) )
const [profile, setProfile] = useState<MetaEvent | null>(null)
const [showWarning, setShowWarning] = useState(false)
const userName = profile?.info?.name || getShortenNpub(npub)
const userNameWithPrefix = userName + '@nsec.app'
const load = useCallback(async () => { const load = useCallback(async () => {
try { try {
const npubToken = npub.includes('#') ? npub.split('#')[0] : npub const npubToken = npub.includes('#') ? npub.split('#')[0] : npub
@@ -122,27 +118,25 @@ const KeyPage = () => {
const handleOpenSettingsModal = () => handleOpen(MODAL_PARAMS_KEYS.SETTINGS) const handleOpenSettingsModal = () => handleOpen(MODAL_PARAMS_KEYS.SETTINGS)
useEffect(() => { const checkBackgroundSigning = useCallback(async () => {
const checkBackgroundSigning = async () => { if (swr) {
if (swr) { const isBackgroundEnable = await swr.pushManager.getSubscription()
const isBackgroundEnable = if (!isBackgroundEnable) setShowWarning(true)
await swr.pushManager.getSubscription() else setShowWarning(false)
if (!isBackgroundEnable) {
setShowWarning(true)
} else {
setShowWarning(false)
}
}
} }
checkBackgroundSigning()
}, []) }, [])
useEffect(() => {
checkBackgroundSigning()
}, [checkBackgroundSigning])
const handleEnableBackground = async () => { const handleEnableBackground = async () => {
await askNotificationPermission() await askNotificationPermission()
try { try {
const r = await swicCall('enablePush') const r = await swicCall('enablePush')
if (!r) return nofity(`Failed to enable push subscription`, 'error') if (!r) return nofity(`Failed to enable push subscription`, 'error')
nofity('Enabled!', 'success') nofity('Enabled!', 'success')
checkBackgroundSigning()
} catch (e) { } catch (e) {
nofity(`Failed to enable push subscription`, 'error') nofity(`Failed to enable push subscription`, 'error')
} }
@@ -157,7 +151,7 @@ const KeyPage = () => {
shownConnectModals.current = {} shownConnectModals.current = {}
shownConfirmEventModals.current = {} shownConfirmEventModals.current = {}
} }
}, [npub]) }, [npub, pending.length])
const connectPendings = filteredPendingReqs.filter( const connectPendings = filteredPendingReqs.filter(
(pr) => pr.method === 'connect', (pr) => pr.method === 'connect',

View File

@@ -15,7 +15,7 @@ const WelcomePage = () => {
const npubInputRef = useRef<HTMLInputElement | null>(null) const npubInputRef = useRef<HTMLInputElement | null>(null)
const passwordInputRef = useRef<HTMLInputElement | null>(null) const passwordInputRef = useRef<HTMLInputElement | null>(null)
if (isKeysExists) return <Navigate to={'/home'} /> // if (isKeysExists) return <Navigate to={'/home'} />
async function generateKey() { async function generateKey() {
try { try {

View File

@@ -8,7 +8,6 @@ import { CircularProgress, Stack } from '@mui/material'
const KeyPage = lazy(() => import('../pages/KeyPage/Key.Page')) const KeyPage = lazy(() => import('../pages/KeyPage/Key.Page'))
const ConfirmPage = lazy(() => import('../pages/Confirm.Page')) const ConfirmPage = lazy(() => import('../pages/Confirm.Page'))
const AppPage = lazy(() => import('../pages/App.Page')) const AppPage = lazy(() => import('../pages/App.Page'))
// const AuthPage = lazy(() => import('../pages/AuthPage/Auth.Page'))
const LoadingSpinner = () => ( const LoadingSpinner = () => (
<Stack height={'100%'} justifyContent={'center'} alignItems={'center'}> <Stack height={'100%'} justifyContent={'center'} alignItems={'center'}>
@@ -24,7 +23,6 @@ const AppRoutes = () => {
<Route path='/' element={<Navigate to={'/home'} />} /> <Route path='/' element={<Navigate to={'/home'} />} />
<Route path='/welcome' element={<WelcomePage />} /> <Route path='/welcome' element={<WelcomePage />} />
<Route path='/home' element={<HomePage />} /> <Route path='/home' element={<HomePage />} />
{/* <Route path='/sign-up' element={<AuthPage />} /> */}
<Route path='/key/:npub' element={<KeyPage />} /> <Route path='/key/:npub' element={<KeyPage />} />
<Route <Route
path='/key/:npub/app/:appNpub' path='/key/:npub/app/:appNpub'

View File

@@ -0,0 +1,37 @@
import { forwardRef } from 'react'
import { Checkbox as MuiCheckbox, CheckboxProps, styled } from '@mui/material'
import {
CheckedIcon,
CheckedLightIcon,
UnchekedIcon,
UnchekedLightIcon,
} from '@/assets'
import { useAppSelector } from '@/store/hooks/redux'
export const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(
(props, ref) => {
const { themeMode } = useAppSelector((state) => state.ui)
return <StyledCheckbox ref={ref} {...props} mode={themeMode} />
},
)
const StyledCheckbox = styled(
forwardRef<HTMLButtonElement, CheckboxProps & { mode: 'dark' | 'light' }>(
({ mode, ...restProps }, ref) => {
const isDarkMode = mode === 'dark'
return (
<MuiCheckbox
{...restProps}
ref={ref}
icon={isDarkMode ? <UnchekedLightIcon /> : <UnchekedIcon />}
checkedIcon={
isDarkMode ? <CheckedLightIcon /> : <CheckedIcon />
}
/>
)
},
),
)(() => ({
'& .MuiSvgIcon-root': { fontSize: '1.5rem' },
}))

View File

@@ -6,12 +6,19 @@ import { StyledContainer } from './styled'
type InputCopyButtonProps = { type InputCopyButtonProps = {
value: string value: string
onCopy?: () => void
} }
export const InputCopyButton: FC<InputCopyButtonProps> = ({ value }) => { export const InputCopyButton: FC<InputCopyButtonProps> = ({
value,
onCopy = () => undefined,
}) => {
const [isCopied, setIsCopied] = useState(false) const [isCopied, setIsCopied] = useState(false)
const handleCopy = () => setIsCopied(true) const handleCopy = () => {
setIsCopied(true)
onCopy && onCopy()
}
useEffect(() => { useEffect(() => {
let timerId: any let timerId: any