Compare commits
6 Commits
feature/ad
...
refactor/h
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41f390cf59 | ||
|
|
8c0b5f379e | ||
|
|
905dc7ac1b | ||
|
|
ca25712d20 | ||
|
|
051eaf001f | ||
|
|
4a2362f6b9 |
@@ -14,7 +14,7 @@ export const useProfile = (npub: string) => {
|
|||||||
const [profile, setProfile] = useState<MetaEvent | null>(null)
|
const [profile, setProfile] = useState<MetaEvent | null>(null)
|
||||||
const currentKey = useAppSelector((state) => selectKeyByNpub(state, npub))
|
const currentKey = useAppSelector((state) => selectKeyByNpub(state, npub))
|
||||||
|
|
||||||
const userName = getProfileUsername(profile) || currentKey?.name
|
const userName = currentKey?.name || getProfileUsername(profile)
|
||||||
const userAvatar = profile?.info?.picture || ''
|
const userAvatar = profile?.info?.picture || ''
|
||||||
const avatarTitle = getFirstLetter(userName)
|
const avatarTitle = getFirstLetter(userName)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Avatar, Stack, Toolbar, Typography, Divider, DividerProps, styled } from '@mui/material'
|
import { Avatar, Stack, Toolbar, Typography, Divider, DividerProps, styled } from '@mui/material'
|
||||||
import { StyledAppBar, StyledAppLogo, StyledAppName, StyledProfileContainer, StyledThemeButton } from './styled'
|
import { StyledAppBar, StyledAppLogo, StyledAppName, StyledProfileContainer, StyledThemeButton } from './styled'
|
||||||
import { Menu } from './components/Menu'
|
import { Menu } from './components/Menu'
|
||||||
import { useNavigate, useParams } from 'react-router-dom'
|
import { useNavigate, useParams, useSearchParams } from 'react-router-dom'
|
||||||
import { ProfileMenu } from './components/ProfileMenu'
|
import { ProfileMenu } from './components/ProfileMenu'
|
||||||
import { useProfile } from '@/hooks/useProfile'
|
import { useProfile } from '@/hooks/useProfile'
|
||||||
import DarkModeIcon from '@mui/icons-material/DarkMode'
|
import DarkModeIcon from '@mui/icons-material/DarkMode'
|
||||||
@@ -10,6 +10,7 @@ import { useAppDispatch, useAppSelector } from '@/store/hooks/redux'
|
|||||||
import { setThemeMode } from '@/store/reducers/ui.slice'
|
import { setThemeMode } from '@/store/reducers/ui.slice'
|
||||||
import { useSessionStorage } from 'usehooks-ts'
|
import { useSessionStorage } from 'usehooks-ts'
|
||||||
import { RELOAD_STORAGE_KEY } from '@/utils/consts'
|
import { RELOAD_STORAGE_KEY } from '@/utils/consts'
|
||||||
|
import { useCallback } from 'react'
|
||||||
|
|
||||||
export const Header = () => {
|
export const Header = () => {
|
||||||
const themeMode = useAppSelector((state) => state.ui.themeMode)
|
const themeMode = useAppSelector((state) => state.ui.themeMode)
|
||||||
@@ -17,9 +18,12 @@ export const Header = () => {
|
|||||||
const dispatch = useAppDispatch()
|
const dispatch = useAppDispatch()
|
||||||
const [needReload] = useSessionStorage(RELOAD_STORAGE_KEY, false)
|
const [needReload] = useSessionStorage(RELOAD_STORAGE_KEY, false)
|
||||||
|
|
||||||
|
const [searchParams] = useSearchParams()
|
||||||
|
const isPopupMode = searchParams.get('popup') === 'true'
|
||||||
|
|
||||||
const { npub = '' } = useParams<{ npub: string }>()
|
const { npub = '' } = useParams<{ npub: string }>()
|
||||||
const { userName, userAvatar, avatarTitle } = useProfile(npub)
|
const { userName, userAvatar, avatarTitle } = useProfile(npub)
|
||||||
const showProfile = Boolean(npub)
|
const isKeyPage = Boolean(npub)
|
||||||
|
|
||||||
const handleNavigate = () => {
|
const handleNavigate = () => {
|
||||||
navigate(`/key/${npub}`)
|
navigate(`/key/${npub}`)
|
||||||
@@ -32,12 +36,17 @@ export const Header = () => {
|
|||||||
dispatch(setThemeMode({ mode: isDarkMode ? 'light' : 'dark' }))
|
dispatch(setThemeMode({ mode: isDarkMode ? 'light' : 'dark' }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const renderMenus = useCallback(() => {
|
||||||
|
if (isPopupMode && isKeyPage) return null
|
||||||
|
return isKeyPage ? <ProfileMenu /> : <Menu />
|
||||||
|
}, [isPopupMode, isKeyPage])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledAppBar position={needReload ? 'relative' : 'fixed'}>
|
<StyledAppBar position={needReload ? 'relative' : 'fixed'}>
|
||||||
<Toolbar sx={{ padding: '12px' }}>
|
<Toolbar sx={{ padding: '12px' }}>
|
||||||
<Stack direction={'row'} justifyContent={'space-between'} alignItems={'center'} width={'100%'}>
|
<Stack direction={'row'} justifyContent={'space-between'} alignItems={'center'} width={'100%'}>
|
||||||
{showProfile && (
|
{isKeyPage && (
|
||||||
<StyledProfileContainer>
|
<StyledProfileContainer nonclickable={isPopupMode}>
|
||||||
<Avatar src={userAvatar} alt={userName} onClick={handleNavigate} className="avatar">
|
<Avatar src={userAvatar} alt={userName} onClick={handleNavigate} className="avatar">
|
||||||
{avatarTitle}
|
{avatarTitle}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
@@ -47,7 +56,7 @@ export const Header = () => {
|
|||||||
</StyledProfileContainer>
|
</StyledProfileContainer>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!showProfile && (
|
{!isKeyPage && (
|
||||||
<StyledAppName>
|
<StyledAppName>
|
||||||
<StyledAppLogo />
|
<StyledAppLogo />
|
||||||
<span>Nsec.app</span>
|
<span>Nsec.app</span>
|
||||||
@@ -56,7 +65,7 @@ export const Header = () => {
|
|||||||
|
|
||||||
<StyledThemeButton onClick={handleChangeMode}>{themeIcon}</StyledThemeButton>
|
<StyledThemeButton onClick={handleChangeMode}>{themeIcon}</StyledThemeButton>
|
||||||
|
|
||||||
{showProfile ? <ProfileMenu /> : <Menu />}
|
{renderMenus()}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
<StyledDivider />
|
<StyledDivider />
|
||||||
|
|||||||
@@ -32,18 +32,23 @@ export const StyledAppName = styled((props: TypographyProps) => (
|
|||||||
marginLeft: '0.5rem',
|
marginLeft: '0.5rem',
|
||||||
}))
|
}))
|
||||||
|
|
||||||
export const StyledProfileContainer = styled((props: StackProps) => <Stack {...props} />)(() => ({
|
export const StyledProfileContainer = styled((props: StackProps & { nonclickable: boolean }) => <Stack {...props} />)(
|
||||||
gap: '1rem',
|
({ nonclickable = false }) => ({
|
||||||
flexDirection: 'row',
|
gap: '1rem',
|
||||||
alignItems: 'center',
|
flexDirection: 'row',
|
||||||
flex: 1,
|
alignItems: 'center',
|
||||||
'& .avatar': {
|
flex: 1,
|
||||||
cursor: 'pointer',
|
'& .avatar': {
|
||||||
},
|
cursor: 'pointer',
|
||||||
'& .username': {
|
},
|
||||||
cursor: 'pointer',
|
'& .username': {
|
||||||
},
|
cursor: 'pointer',
|
||||||
}))
|
},
|
||||||
|
'& > *': {
|
||||||
|
pointerEvents: nonclickable ? 'none' : 'initial',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
export const StyledThemeButton = styled(IconButton)({
|
export const StyledThemeButton = styled(IconButton)({
|
||||||
margin: '0 0.5rem',
|
margin: '0 0.5rem',
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import NDK, {
|
|||||||
NDKSubscriptionCacheUsage,
|
NDKSubscriptionCacheUsage,
|
||||||
NDKUser,
|
NDKUser,
|
||||||
} from '@nostr-dev-kit/ndk'
|
} from '@nostr-dev-kit/ndk'
|
||||||
import { NOAUTHD_URL, WEB_PUSH_PUBKEY, NIP46_RELAYS, MIN_POW, MAX_POW, KIND_RPC, DOMAIN } from '../utils/consts'
|
import { NOAUTHD_URL, WEB_PUSH_PUBKEY, NIP46_RELAYS, MIN_POW, MAX_POW, KIND_RPC, DOMAIN, REQ_TTL } from '../utils/consts'
|
||||||
// import { Nip04 } from './nip04'
|
// import { Nip04 } from './nip04'
|
||||||
import { fetchNip05, getReqPerm, getShortenNpub, isPackagePerm } from '@/utils/helpers/helpers'
|
import { fetchNip05, getReqPerm, getShortenNpub, isPackagePerm } from '@/utils/helpers/helpers'
|
||||||
import { NostrPowEvent, minePow } from './pow'
|
import { NostrPowEvent, minePow } from './pow'
|
||||||
@@ -310,6 +310,13 @@ export class NoauthBackend {
|
|||||||
this.apps = await dbi.listApps()
|
this.apps = await dbi.listApps()
|
||||||
console.log('started apps', this.apps)
|
console.log('started apps', this.apps)
|
||||||
|
|
||||||
|
// drop old pending reqs
|
||||||
|
const pending = await dbi.listPending()
|
||||||
|
for (const p of pending) {
|
||||||
|
if (p.timestamp < Date.now() - REQ_TTL)
|
||||||
|
await dbi.removePending(p.id)
|
||||||
|
}
|
||||||
|
|
||||||
const sub = await this.swg.registration.pushManager.getSubscription()
|
const sub = await this.swg.registration.pushManager.getSubscription()
|
||||||
|
|
||||||
for (const k of this.enckeys) {
|
for (const k of this.enckeys) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useModalSearchParams } from '@/hooks/useModalSearchParams'
|
import { useModalSearchParams } from '@/hooks/useModalSearchParams'
|
||||||
import { DbPending, DbPerm } from '@/modules/db'
|
import { DbPending, DbPerm } from '@/modules/db'
|
||||||
import { MODAL_PARAMS_KEYS } from '@/types/modal'
|
import { MODAL_PARAMS_KEYS } from '@/types/modal'
|
||||||
import { ACTION_TYPE } from '@/utils/consts'
|
import { ACTION_TYPE, REQ_TTL } from '@/utils/consts'
|
||||||
import { useCallback, useEffect, useRef } from 'react'
|
import { useCallback, useEffect, useRef } from 'react'
|
||||||
import { useSearchParams } from 'react-router-dom'
|
import { useSearchParams } from 'react-router-dom'
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ export const useTriggerConfirmModal = (npub: string, pending: DbPending[], perms
|
|||||||
const isConfirmConnectModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_CONNECT)
|
const isConfirmConnectModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_CONNECT)
|
||||||
const isConfirmEventModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_EVENT)
|
const isConfirmEventModalOpened = getModalOpened(MODAL_PARAMS_KEYS.CONFIRM_EVENT)
|
||||||
|
|
||||||
const filteredPendingReqs = pending.filter((p) => p.npub === npub)
|
const filteredPendingReqs = pending.filter((p) => p.npub === npub && p.timestamp > Date.now() - REQ_TTL)
|
||||||
const filteredPerms = perms.filter((p) => p.npub === npub)
|
const filteredPerms = perms.filter((p) => p.npub === npub)
|
||||||
|
|
||||||
const npubConnectPerms = filteredPerms.filter((perm) => perm.perm === 'connect' || perm.perm === ACTION_TYPE.BASIC)
|
const npubConnectPerms = filteredPerms.filter((perm) => perm.perm === 'connect' || perm.perm === ACTION_TYPE.BASIC)
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ export const KIND_RPC = 24133
|
|||||||
|
|
||||||
export const RELOAD_STORAGE_KEY = 'reload'
|
export const RELOAD_STORAGE_KEY = 'reload'
|
||||||
|
|
||||||
|
export const REQ_TTL = 60000 // 1 min
|
||||||
|
|
||||||
export enum ACTION_TYPE {
|
export enum ACTION_TYPE {
|
||||||
BASIC = 'basic',
|
BASIC = 'basic',
|
||||||
ADVANCED = 'advanced',
|
ADVANCED = 'advanced',
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const getShortenNpub = (npub = '') => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getProfileUsername = (profile: MetaEvent | null) => {
|
export const getProfileUsername = (profile: MetaEvent | null) => {
|
||||||
if (!profile) return null
|
if (!profile) return undefined
|
||||||
return profile?.info?.name || profile?.info?.display_name
|
return profile?.info?.name || profile?.info?.display_name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +72,7 @@ export function isPackagePerm(perm: string, reqPerm: string) {
|
|||||||
case 'sign_event:10002':
|
case 'sign_event:10002':
|
||||||
case 'sign_event:30023':
|
case 'sign_event:30023':
|
||||||
case 'sign_event:10000':
|
case 'sign_event:10000':
|
||||||
|
case 'sign_event:27235':
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user