reject penging requests on close modals & confirm only selected pending reqs in ConfirmEvent
This commit is contained in:
4
src/assets/icons/checked-light.svg
Normal file
4
src/assets/icons/checked-light.svg
Normal 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 |
@@ -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 |
3
src/assets/icons/unchecked-light.svg
Normal file
3
src/assets/icons/unchecked-light.svg
Normal 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 |
@@ -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 |
@@ -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,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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?'
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 }) => {
|
||||||
|
|||||||
@@ -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',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
37
src/shared/Checkbox/Checkbox.tsx
Normal file
37
src/shared/Checkbox/Checkbox.tsx
Normal 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' },
|
||||||
|
}))
|
||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user