save
This commit is contained in:
parent
14940a4345
commit
9d565ddbde
@ -12,7 +12,6 @@ import { useState } from 'react'
|
||||
import { swicCall } from '@/modules/swic'
|
||||
import { ACTION_TYPE } from '@/utils/consts'
|
||||
|
||||
|
||||
export const ModalConfirmConnect = () => {
|
||||
const { getModalOpened, createHandleCloseReplace } = useModalSearchParams()
|
||||
const isModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_CONNECT)
|
||||
@ -45,7 +44,7 @@ export const ModalConfirmConnect = () => {
|
||||
sp.delete('appNpub')
|
||||
sp.delete('reqId')
|
||||
await swicCall('confirm', pendingReqId, false, false)
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
const closeModalAfterRequest = createHandleCloseReplace(
|
||||
@ -55,27 +54,27 @@ export const ModalConfirmConnect = () => {
|
||||
sp.delete('appNpub')
|
||||
sp.delete('reqId')
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async function confirmPending(
|
||||
id: string,
|
||||
allow: boolean,
|
||||
remember: boolean,
|
||||
options?: any
|
||||
options?: any,
|
||||
) {
|
||||
call(async () => {
|
||||
await swicCall('confirm', id, allow, remember, options)
|
||||
console.log('confirmed', id, allow, remember, options)
|
||||
closeModalAfterRequest()
|
||||
})
|
||||
if (isPopup) window.close();
|
||||
if (isPopup) window.close()
|
||||
}
|
||||
|
||||
const allow = () => {
|
||||
const options: any = {};
|
||||
const options: any = {}
|
||||
if (selectedActionType === ACTION_TYPE.BASIC)
|
||||
options.perms = [ACTION_TYPE.BASIC];
|
||||
options.perms = [ACTION_TYPE.BASIC]
|
||||
// else
|
||||
// options.perms = ['connect','get_public_key'];
|
||||
confirmPending(pendingReqId, true, true, options)
|
||||
@ -86,16 +85,16 @@ export const ModalConfirmConnect = () => {
|
||||
}
|
||||
|
||||
if (isPopup) {
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
if (document.visibilityState == 'hidden') {
|
||||
disallow();
|
||||
document.addEventListener('visibilitychange', function () {
|
||||
if (document.visibilityState === 'hidden') {
|
||||
disallow()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={isModalOpened}
|
||||
<Modal
|
||||
open={isModalOpened}
|
||||
withCloseButton={!isPopup}
|
||||
onClose={!isPopup ? handleCloseModal : undefined}
|
||||
>
|
||||
@ -147,16 +146,10 @@ export const ModalConfirmConnect = () => {
|
||||
/>
|
||||
</StyledToggleButtonsGroup>
|
||||
<Stack direction={'row'} gap={'1rem'}>
|
||||
<StyledButton
|
||||
onClick={disallow}
|
||||
varianttype='secondary'
|
||||
>
|
||||
<StyledButton onClick={disallow} varianttype='secondary'>
|
||||
Disallow
|
||||
</StyledButton>
|
||||
<StyledButton
|
||||
fullWidth
|
||||
onClick={allow}
|
||||
>
|
||||
<StyledButton fullWidth onClick={allow}>
|
||||
{/* Allow {selectedActionType} actions */}
|
||||
Connect
|
||||
</StyledButton>
|
||||
|
@ -94,10 +94,11 @@ export const ModalConfirmEvent: FC<ModalConfirmEventProps> = ({
|
||||
sp.delete('appNpub')
|
||||
sp.delete('reqId')
|
||||
selectedPendingRequests.forEach(
|
||||
async (req) => await swicCall('confirm', req.id, false, false),
|
||||
async (req) =>
|
||||
await swicCall('confirm', req.id, false, false),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
const closeModalAfterRequest = createHandleCloseReplace(
|
||||
@ -106,8 +107,8 @@ export const ModalConfirmEvent: FC<ModalConfirmEventProps> = ({
|
||||
onClose: (sp) => {
|
||||
sp.delete('appNpub')
|
||||
sp.delete('reqId')
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
async function confirmPending(allow: boolean) {
|
||||
@ -119,7 +120,7 @@ export const ModalConfirmEvent: FC<ModalConfirmEventProps> = ({
|
||||
})
|
||||
})
|
||||
closeModalAfterRequest()
|
||||
if (isPopup) window.close();
|
||||
if (isPopup) window.close()
|
||||
}
|
||||
|
||||
const handleChangeCheckbox = (reqId: string) => () => {
|
||||
@ -141,8 +142,8 @@ export const ModalConfirmEvent: FC<ModalConfirmEventProps> = ({
|
||||
|
||||
if (isPopup) {
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (document.visibilityState == 'hidden') {
|
||||
confirmPending(false);
|
||||
if (document.visibilityState === 'hidden') {
|
||||
confirmPending(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,17 +1,7 @@
|
||||
import * as yup from 'yup'
|
||||
|
||||
export const schema = yup.object().shape({
|
||||
username: yup
|
||||
.string()
|
||||
.test('Domain validation', 'The domain is required!', function (value) {
|
||||
if (!value || !value.trim().length) return false
|
||||
|
||||
const USERNAME_WITH_DOMAIN_REGEXP = new RegExp(
|
||||
/^[\w-.]+@([\w-]+\.)+[\w-]{2,8}$/g,
|
||||
)
|
||||
return USERNAME_WITH_DOMAIN_REGEXP.test(value)
|
||||
})
|
||||
.required(),
|
||||
username: yup.string().required(),
|
||||
password: yup.string().required().min(4),
|
||||
})
|
||||
|
||||
|
@ -10,7 +10,7 @@ import { Button } from '@/shared/Button/Button'
|
||||
import { CheckmarkIcon } from '@/assets'
|
||||
import { swicCall } from '@/modules/swic'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { DOMAIN, NOAUTHD_URL } from '@/utils/consts'
|
||||
import { DOMAIN } from '@/utils/consts'
|
||||
import { fetchNip05 } from '@/utils/helpers/helpers'
|
||||
|
||||
export const ModalSignUp = () => {
|
||||
@ -36,20 +36,17 @@ export const ModalSignUp = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const inputHelperText = enteredValue
|
||||
? (
|
||||
const inputHelperText = enteredValue ? (
|
||||
isAvailable ? (
|
||||
<>
|
||||
<CheckmarkIcon /> Available
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
Already taken
|
||||
</>
|
||||
<>Already taken</>
|
||||
)
|
||||
) : (
|
||||
"Don't worry, username can be changed later."
|
||||
);
|
||||
)
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
const name = enteredValue.trim()
|
||||
@ -96,13 +93,13 @@ export const ModalSignUp = () => {
|
||||
helperTextProps={{
|
||||
sx: {
|
||||
'&.helper_text': {
|
||||
color: enteredValue && isAvailable
|
||||
? theme.palette.success.main
|
||||
: (enteredValue && !isAvailable
|
||||
? theme.palette.error.main
|
||||
: theme.palette.textSecondaryDecorate.main
|
||||
)
|
||||
,
|
||||
color:
|
||||
enteredValue && isAvailable
|
||||
? theme.palette.success.main
|
||||
: enteredValue && !isAvailable
|
||||
? theme.palette.error.main
|
||||
: theme.palette
|
||||
.textSecondaryDecorate.main,
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
40
src/hooks/useProfile.ts
Normal file
40
src/hooks/useProfile.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { fetchProfile } from '@/modules/nostr'
|
||||
import { MetaEvent } from '@/types/meta-event'
|
||||
import { getProfileUsername, getShortenNpub } from '@/utils/helpers/helpers'
|
||||
import { useAppSelector } from '@/store/hooks/redux'
|
||||
import { selectKeyByNpub } from '@/store'
|
||||
|
||||
const getFirstLetter = (text: string | undefined): string | null => {
|
||||
if (!text || text.trim().length === 0) return null
|
||||
return text.substring(0, 1).toUpperCase()
|
||||
}
|
||||
|
||||
export const useProfile = (npub: string) => {
|
||||
const [profile, setProfile] = useState<MetaEvent | null>(null)
|
||||
const currentKey = useAppSelector((state) => selectKeyByNpub(state, npub))
|
||||
|
||||
const userName = getProfileUsername(profile) || currentKey?.name
|
||||
const userAvatar = profile?.info?.picture || ''
|
||||
const avatarTitle = getFirstLetter(userName)
|
||||
|
||||
const loadProfile = useCallback(async () => {
|
||||
try {
|
||||
const response = await fetchProfile(npub)
|
||||
setProfile(response)
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch profile:', error)
|
||||
}
|
||||
}, [npub])
|
||||
|
||||
useEffect(() => {
|
||||
loadProfile()
|
||||
}, [loadProfile])
|
||||
|
||||
return {
|
||||
profile,
|
||||
userName: userName || getShortenNpub(npub),
|
||||
userAvatar,
|
||||
avatarTitle,
|
||||
}
|
||||
}
|
@ -2,35 +2,20 @@ import { Avatar, Stack, Toolbar, Typography } from '@mui/material'
|
||||
import { AppLogo } from '../../assets'
|
||||
import { StyledAppBar, StyledAppName } from './styled'
|
||||
import { Menu } from './components/Menu'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { MetaEvent } from '@/types/meta-event'
|
||||
import { fetchProfile } from '@/modules/nostr'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { ProfileMenu } from './components/ProfileMenu'
|
||||
import { getShortenNpub } from '@/utils/helpers/helpers'
|
||||
import { useProfile } from '@/hooks/useProfile'
|
||||
|
||||
export const Header = () => {
|
||||
const { npub = '' } = useParams<{ npub: string }>()
|
||||
const [profile, setProfile] = useState<MetaEvent | null>(null)
|
||||
const { userName, userAvatar, avatarTitle } = useProfile(npub)
|
||||
const showProfile = Boolean(npub)
|
||||
|
||||
const load = useCallback(async () => {
|
||||
if (!npub) return setProfile(null)
|
||||
const navigate = useNavigate()
|
||||
|
||||
try {
|
||||
const response = await fetchProfile(npub)
|
||||
setProfile(response as any)
|
||||
} catch (e) {
|
||||
return setProfile(null)
|
||||
}
|
||||
}, [npub])
|
||||
|
||||
useEffect(() => {
|
||||
load()
|
||||
}, [load])
|
||||
|
||||
const showProfile = Boolean(npub || profile)
|
||||
const userName = profile?.info?.name || getShortenNpub(npub)
|
||||
const userAvatar = profile?.info?.picture || ''
|
||||
const handleNavigate = () => {
|
||||
navigate(`/key/${npub}`)
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledAppBar position='fixed'>
|
||||
@ -41,17 +26,30 @@ export const Header = () => {
|
||||
alignItems={'center'}
|
||||
width={'100%'}
|
||||
>
|
||||
{showProfile ? (
|
||||
{showProfile && (
|
||||
<Stack
|
||||
gap={'1rem'}
|
||||
direction={'row'}
|
||||
alignItems={'center'}
|
||||
flex={1}
|
||||
>
|
||||
<Avatar src={userAvatar} alt={userName} />
|
||||
<Typography fontWeight={600}>{userName}</Typography>
|
||||
<Avatar
|
||||
src={userAvatar}
|
||||
alt={userName}
|
||||
onClick={handleNavigate}
|
||||
>
|
||||
{avatarTitle}
|
||||
</Avatar>
|
||||
<Typography
|
||||
fontWeight={600}
|
||||
onClick={handleNavigate}
|
||||
>
|
||||
{userName}
|
||||
</Typography>
|
||||
</Stack>
|
||||
) : (
|
||||
)}
|
||||
|
||||
{!showProfile && (
|
||||
<StyledAppName>
|
||||
<AppLogo />
|
||||
<span>Nsec.app</span>
|
||||
|
31
src/layout/Header/components/ListItemProfile.tsx
Normal file
31
src/layout/Header/components/ListItemProfile.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import { useProfile } from '@/hooks/useProfile'
|
||||
import { DbKey } from '@/modules/db'
|
||||
import { Avatar, ListItemIcon, MenuItem, Typography } from '@mui/material'
|
||||
import React, { FC } from 'react'
|
||||
|
||||
type ListItemProfileProps = {
|
||||
onClickItem: () => void
|
||||
} & DbKey
|
||||
|
||||
export const ListItemProfile: FC<ListItemProfileProps> = ({
|
||||
onClickItem,
|
||||
npub,
|
||||
}) => {
|
||||
const { userName, userAvatar, avatarTitle } = useProfile(npub)
|
||||
return (
|
||||
<MenuItem sx={{ gap: '0.5rem' }} onClick={onClickItem}>
|
||||
<ListItemIcon>
|
||||
<Avatar
|
||||
src={userAvatar}
|
||||
alt={userName}
|
||||
sx={{ width: 36, height: 36 }}
|
||||
>
|
||||
{avatarTitle}
|
||||
</Avatar>
|
||||
</ListItemIcon>
|
||||
<Typography variant='body2' noWrap>
|
||||
{userName}
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
)
|
||||
}
|
@ -1,13 +1,7 @@
|
||||
import { DbKey } from '@/modules/db'
|
||||
import { getShortenNpub } from '@/utils/helpers/helpers'
|
||||
import {
|
||||
Avatar,
|
||||
ListItemIcon,
|
||||
MenuItem,
|
||||
Stack,
|
||||
Typography,
|
||||
} from '@mui/material'
|
||||
import React, { FC } from 'react'
|
||||
import { Stack } from '@mui/material'
|
||||
import { FC } from 'react'
|
||||
import { ListItemProfile } from './ListItemProfile'
|
||||
|
||||
type ListProfilesProps = {
|
||||
keys: DbKey[]
|
||||
@ -21,26 +15,12 @@ export const ListProfiles: FC<ListProfilesProps> = ({
|
||||
return (
|
||||
<Stack maxHeight={'10rem'} overflow={'auto'}>
|
||||
{keys.map((key) => {
|
||||
const userName =
|
||||
key?.profile?.info?.name || getShortenNpub(key.npub)
|
||||
const userAvatar = key?.profile?.info?.picture || ''
|
||||
return (
|
||||
<MenuItem
|
||||
sx={{ gap: '0.5rem' }}
|
||||
onClick={() => onClickItem(key)}
|
||||
<ListItemProfile
|
||||
{...key}
|
||||
key={key.npub}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<Avatar
|
||||
src={userAvatar}
|
||||
alt={userName}
|
||||
sx={{ width: 36, height: 36 }}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
<Typography variant='body2' noWrap>
|
||||
{userName}
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
onClickItem={() => onClickItem(key)}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</Stack>
|
||||
|
@ -8,26 +8,26 @@ import {
|
||||
TypographyProps,
|
||||
styled,
|
||||
} from '@mui/material'
|
||||
import { getShortenNpub } from '../../../utils/helpers/helpers'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { useProfile } from '@/hooks/useProfile'
|
||||
|
||||
type ItemKeyProps = DbKey
|
||||
|
||||
export const ItemKey: FC<ItemKeyProps> = (props) => {
|
||||
const { npub, profile } = props
|
||||
const { npub } = props
|
||||
const navigate = useNavigate()
|
||||
const { userName, userAvatar, avatarTitle } = useProfile(npub)
|
||||
|
||||
const handleNavigate = () => {
|
||||
navigate('/key/' + npub)
|
||||
}
|
||||
const { name = '', picture = '' } = profile?.info || {}
|
||||
const userName = name || getShortenNpub(npub)
|
||||
const userAvatar = picture || ''
|
||||
|
||||
return (
|
||||
<StyledKeyContainer onClick={handleNavigate}>
|
||||
<Stack direction={'row'} alignItems={'center'} gap='1rem'>
|
||||
<Avatar src={userAvatar} alt={userName} />
|
||||
<Avatar src={userAvatar} alt={userName}>
|
||||
{avatarTitle}
|
||||
</Avatar>
|
||||
<StyledText variant='body1'>{userName}</StyledText>
|
||||
</Stack>
|
||||
</StyledKeyContainer>
|
||||
|
@ -11,7 +11,6 @@ import { ModalSettings } from '@/components/Modal/ModalSettings/ModalSettings'
|
||||
import { ModalExplanation } from '@/components/Modal/ModalExplanation/ModalExplanation'
|
||||
import { ModalConfirmConnect } from '@/components/Modal/ModalConfirmConnect/ModalConfirmConnect'
|
||||
import { ModalConfirmEvent } from '@/components/Modal/ModalConfirmEvent/ModalConfirmEvent'
|
||||
import { useProfile } from './hooks/useProfile'
|
||||
import { useBackgroundSigning } from './hooks/useBackgroundSigning'
|
||||
import { BackgroundSigningWarning } from './components/BackgroundSigningWarning'
|
||||
import UserValueSection from './components/UserValueSection'
|
||||
@ -22,23 +21,23 @@ import { DOMAIN } from '@/utils/consts'
|
||||
|
||||
const KeyPage = () => {
|
||||
const { npub = '' } = useParams<{ npub: string }>()
|
||||
const { keys, apps, pending, perms } = useAppSelector((state) => state.content)
|
||||
const { keys, apps, pending, perms } = useAppSelector(
|
||||
(state) => state.content,
|
||||
)
|
||||
const isSynced = useLiveQuery(checkNpubSyncQuerier(npub), [npub], false)
|
||||
|
||||
const { handleOpen } = useModalSearchParams()
|
||||
|
||||
// const { userNameWithPrefix } = useProfile(npub)
|
||||
const { handleEnableBackground, showWarning, isEnabling } =
|
||||
useBackgroundSigning()
|
||||
|
||||
const key = keys.find(k => k.npub === npub)
|
||||
const key = keys.find((k) => k.npub === npub)
|
||||
|
||||
let username = ''
|
||||
if (key?.name) {
|
||||
if (key.name.includes('@'))
|
||||
username = key.name
|
||||
else
|
||||
username = `${key?.name}@${DOMAIN}`
|
||||
}
|
||||
if (key.name.includes('@')) username = key.name
|
||||
else username = `${key?.name}@${DOMAIN}`
|
||||
}
|
||||
|
||||
const filteredApps = apps.filter((a) => a.npub === npub)
|
||||
const { prepareEventPendings } = useTriggerConfirmModal(
|
||||
|
@ -1,31 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { fetchProfile } from '@/modules/nostr'
|
||||
import { MetaEvent } from '@/types/meta-event'
|
||||
import { getProfileUsername } from '@/utils/helpers/helpers'
|
||||
import { DOMAIN } from '@/utils/consts'
|
||||
|
||||
export const useProfile = (npub: string) => {
|
||||
const [profile, setProfile] = useState<MetaEvent | null>(null)
|
||||
|
||||
const userName = getProfileUsername(profile, npub)
|
||||
// FIXME use nip05?
|
||||
const userNameWithPrefix = userName + '@' + DOMAIN
|
||||
|
||||
const loadProfile = useCallback(async () => {
|
||||
try {
|
||||
const response = await fetchProfile(npub)
|
||||
setProfile(response)
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch profile:', error)
|
||||
}
|
||||
}, [npub])
|
||||
|
||||
useEffect(() => {
|
||||
loadProfile()
|
||||
}, [loadProfile])
|
||||
|
||||
return {
|
||||
profile,
|
||||
userNameWithPrefix,
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import { Suspense, lazy } from 'react'
|
||||
import { Route, Routes, Navigate } from 'react-router-dom'
|
||||
import HomePage from '../pages/HomePage/Home.Page'
|
||||
import WelcomePage from '../pages/Welcome.Page'
|
||||
import { Layout } from '../layout/Layout'
|
||||
import { CircularProgress, Stack } from '@mui/material'
|
||||
|
||||
|
@ -44,6 +44,10 @@ export type AppDispatch = typeof store.dispatch
|
||||
|
||||
export const selectKeys = (state: RootState) => state.content.keys
|
||||
|
||||
export const selectKeyByNpub = (state: RootState, npub: string) => {
|
||||
return state.content.keys.find((key) => key.npub === npub)
|
||||
}
|
||||
|
||||
export const selectAppsByNpub = memoizeOne((state: RootState, npub: string) => {
|
||||
return state.content.apps.filter((app) => app.npub === npub)
|
||||
}, isDeepEqual)
|
||||
|
@ -1,101 +1,100 @@
|
||||
import { nip19 } from "nostr-tools";
|
||||
import { ACTION_TYPE, NIP46_RELAYS } from "../consts";
|
||||
import { DbPending } from "@/modules/db";
|
||||
import { MetaEvent } from "@/types/meta-event";
|
||||
import { nip19 } from 'nostr-tools'
|
||||
import { ACTION_TYPE, NIP46_RELAYS } from '../consts'
|
||||
import { DbPending } from '@/modules/db'
|
||||
import { MetaEvent } from '@/types/meta-event'
|
||||
|
||||
export async function call(cb: () => any) {
|
||||
try {
|
||||
return await cb();
|
||||
} catch (e) {
|
||||
console.log(`Error: ${e}`);
|
||||
}
|
||||
try {
|
||||
return await cb()
|
||||
} catch (e) {
|
||||
console.log(`Error: ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
export const getShortenNpub = (npub = "") => {
|
||||
return npub.substring(0, 10) + "..." + npub.slice(-4);
|
||||
};
|
||||
export const getShortenNpub = (npub = '') => {
|
||||
return npub.substring(0, 10) + '...' + npub.slice(-4)
|
||||
}
|
||||
|
||||
export const getProfileUsername = (profile: MetaEvent | null, npub: string) => {
|
||||
return (
|
||||
profile?.info?.name || profile?.info?.display_name || getShortenNpub(npub)
|
||||
);
|
||||
};
|
||||
export const getProfileUsername = (profile: MetaEvent | null) => {
|
||||
if (!profile) return null
|
||||
return profile?.info?.name || profile?.info?.display_name
|
||||
}
|
||||
|
||||
export const getBunkerLink = (npub = "") => {
|
||||
if (!npub) return "";
|
||||
const { data: pubkey } = nip19.decode(npub);
|
||||
return `bunker://${pubkey}?relay=${NIP46_RELAYS[0]}`;
|
||||
};
|
||||
export const getBunkerLink = (npub = '') => {
|
||||
if (!npub) return ''
|
||||
const { data: pubkey } = nip19.decode(npub)
|
||||
return `bunker://${pubkey}?relay=${NIP46_RELAYS[0]}`
|
||||
}
|
||||
|
||||
export async function askNotificationPermission() {
|
||||
return new Promise<void>((ok, rej) => {
|
||||
// Let's check if the browser supports notifications
|
||||
if (!("Notification" in window)) {
|
||||
rej("This browser does not support notifications.");
|
||||
} else {
|
||||
Notification.requestPermission().then(() => {
|
||||
if (Notification.permission === "granted") ok();
|
||||
else rej();
|
||||
});
|
||||
}
|
||||
});
|
||||
return new Promise<void>((ok, rej) => {
|
||||
// Let's check if the browser supports notifications
|
||||
if (!('Notification' in window)) {
|
||||
rej('This browser does not support notifications.')
|
||||
} else {
|
||||
Notification.requestPermission().then(() => {
|
||||
if (Notification.permission === 'granted') ok()
|
||||
else rej()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function getSignReqKind(req: DbPending): number | undefined {
|
||||
try {
|
||||
const data = JSON.parse(JSON.parse(req.params)[0]);
|
||||
return data.kind;
|
||||
} catch {}
|
||||
return undefined;
|
||||
try {
|
||||
const data = JSON.parse(JSON.parse(req.params)[0])
|
||||
return data.kind
|
||||
} catch {}
|
||||
return undefined
|
||||
}
|
||||
|
||||
export function getReqPerm(req: DbPending): string {
|
||||
if (req.method === "sign_event") {
|
||||
const kind = getSignReqKind(req);
|
||||
if (kind !== undefined) return `${req.method}:${kind}`;
|
||||
}
|
||||
return req.method;
|
||||
if (req.method === 'sign_event') {
|
||||
const kind = getSignReqKind(req)
|
||||
if (kind !== undefined) return `${req.method}:${kind}`
|
||||
}
|
||||
return req.method
|
||||
}
|
||||
|
||||
export function isPackagePerm(perm: string, reqPerm: string) {
|
||||
if (perm === ACTION_TYPE.BASIC) {
|
||||
switch (reqPerm) {
|
||||
case "connect":
|
||||
case "get_public_key":
|
||||
case "nip04_decrypt":
|
||||
case "nip04_encrypt":
|
||||
case "sign_event:0":
|
||||
case "sign_event:1":
|
||||
case "sign_event:3":
|
||||
case "sign_event:6":
|
||||
case "sign_event:7":
|
||||
case "sign_event:9734":
|
||||
case "sign_event:10002":
|
||||
case "sign_event:30023":
|
||||
case "sign_event:10000":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (perm === ACTION_TYPE.BASIC) {
|
||||
switch (reqPerm) {
|
||||
case 'connect':
|
||||
case 'get_public_key':
|
||||
case 'nip04_decrypt':
|
||||
case 'nip04_encrypt':
|
||||
case 'sign_event:0':
|
||||
case 'sign_event:1':
|
||||
case 'sign_event:3':
|
||||
case 'sign_event:6':
|
||||
case 'sign_event:7':
|
||||
case 'sign_event:9734':
|
||||
case 'sign_event:10002':
|
||||
case 'sign_event:30023':
|
||||
case 'sign_event:10000':
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export async function fetchNip05(value: string, origin?: string) {
|
||||
try {
|
||||
const [username, domain] = value.split("@");
|
||||
try {
|
||||
const [username, domain] = value.split('@')
|
||||
if (!origin) origin = `https://${domain}`
|
||||
const response = await fetch(
|
||||
`${origin}/.well-known/nostr.json?name=${username}`
|
||||
);
|
||||
const getNpub: {
|
||||
names: {
|
||||
[name: string]: string;
|
||||
};
|
||||
} = await response.json();
|
||||
const response = await fetch(
|
||||
`${origin}/.well-known/nostr.json?name=${username}`,
|
||||
)
|
||||
const getNpub: {
|
||||
names: {
|
||||
[name: string]: string
|
||||
}
|
||||
} = await response.json()
|
||||
|
||||
const pubkey = getNpub.names[username];
|
||||
return nip19.npubEncode(pubkey);
|
||||
} catch (e) {
|
||||
console.log("Failed to fetch nip05", value, "error: " + e);
|
||||
const pubkey = getNpub.names[username]
|
||||
return nip19.npubEncode(pubkey)
|
||||
} catch (e) {
|
||||
console.log('Failed to fetch nip05', value, 'error: ' + e)
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user