Merge branch 'refactor/sync-npub' of https://github.com/nostrband/noauth into refactor/sync-npub
This commit is contained in:
3
.env
3
.env
@ -2,4 +2,5 @@
|
|||||||
# change if you're using a different noauthd server
|
# change if you're using a different noauthd server
|
||||||
REACT_APP_WEB_PUSH_PUBKEY=BNW_39YcKbV4KunFxFhvMW5JUs8AljfFnGUeZpaerO-gwCoWyQat5ol0xOGB8MLaqqCbz0iptd2Qv3SToSGynMk
|
REACT_APP_WEB_PUSH_PUBKEY=BNW_39YcKbV4KunFxFhvMW5JUs8AljfFnGUeZpaerO-gwCoWyQat5ol0xOGB8MLaqqCbz0iptd2Qv3SToSGynMk
|
||||||
#REACT_APP_NOAUTHD_URL=http://localhost:8000
|
#REACT_APP_NOAUTHD_URL=http://localhost:8000
|
||||||
REACT_APP_NOAUTHD_URL=https://noauthd.login.nostrapps.org
|
REACT_APP_NOAUTHD_URL=https://noauthd.login.nostrapps.org
|
||||||
|
REACT_APP_DOMAIN=nsec.app
|
@ -56,6 +56,7 @@ export const ModalImportKeys = () => {
|
|||||||
value={enteredNsec}
|
value={enteredNsec}
|
||||||
onChange={handleNsecChange}
|
onChange={handleNsecChange}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
type='password'
|
||||||
/>
|
/>
|
||||||
<Button type='submit'>Import nsec</Button>
|
<Button type='submit'>Import nsec</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
@ -19,7 +19,7 @@ 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, FC, useState } from 'react'
|
import { ChangeEvent, FC, useEffect, useState } from 'react'
|
||||||
import { Checkbox } from '@/shared/Checkbox/Checkbox'
|
import { Checkbox } from '@/shared/Checkbox/Checkbox'
|
||||||
import { useEnqueueSnackbar } from '@/hooks/useEnqueueSnackbar'
|
import { useEnqueueSnackbar } from '@/hooks/useEnqueueSnackbar'
|
||||||
import { swicCall } from '@/modules/swic'
|
import { swicCall } from '@/modules/swic'
|
||||||
@ -47,6 +47,9 @@ export const ModalSettings: FC<ModalSettingsProps> = ({ isSynced }) => {
|
|||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => setIsChecked(isSynced), [isModalOpened])
|
||||||
|
|
||||||
const handlePasswordChange = (e: ChangeEvent<HTMLInputElement>) => {
|
const handlePasswordChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
setIsPasswordInvalid(false)
|
setIsPasswordInvalid(false)
|
||||||
setEnteredPassword(e.target.value)
|
setEnteredPassword(e.target.value)
|
||||||
@ -104,61 +107,61 @@ export const ModalSettings: FC<ModalSettingsProps> = ({ isSynced }) => {
|
|||||||
checked={isChecked}
|
checked={isChecked}
|
||||||
/>
|
/>
|
||||||
<Typography variant='caption'>
|
<Typography variant='caption'>
|
||||||
Use this login on multiple devices
|
Use this key on multiple devices
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Input
|
||||||
|
fullWidth
|
||||||
|
endAdornment={
|
||||||
|
<IconButton
|
||||||
|
size='small'
|
||||||
|
onClick={handlePasswordTypeChange}
|
||||||
|
>
|
||||||
|
{isPasswordShown ? (
|
||||||
|
<VisibilityOffOutlinedIcon htmlColor='#6b6b6b' />
|
||||||
|
) : (
|
||||||
|
<VisibilityOutlinedIcon htmlColor='#6b6b6b' />
|
||||||
|
)}
|
||||||
|
</IconButton>
|
||||||
|
}
|
||||||
|
type={isPasswordShown ? 'text' : 'password'}
|
||||||
|
onChange={handlePasswordChange}
|
||||||
|
value={enteredPassword}
|
||||||
|
helperText={
|
||||||
|
isPasswordInvalid ? 'Invalid password' : ''
|
||||||
|
}
|
||||||
|
placeholder='Enter a password'
|
||||||
|
helperTextProps={{
|
||||||
|
sx: {
|
||||||
|
'&.helper_text': {
|
||||||
|
color: 'red',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
disabled={!isChecked}
|
||||||
|
/>
|
||||||
{isSynced ? (
|
{isSynced ? (
|
||||||
<Typography variant='body2' color={'GrayText'}>
|
<Typography variant='body2' color={'GrayText'}>
|
||||||
This uploads your <u>private key</u>, encrypted by
|
To change your password, type a new one and sync.
|
||||||
your password, to Nsec App's server.
|
|
||||||
</Typography>
|
</Typography>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<Typography variant='body2' color={'GrayText'}>
|
||||||
<Input
|
This key will be encrypted and stored on our server. You can use the password to download this key onto another device.
|
||||||
fullWidth
|
</Typography>
|
||||||
endAdornment={
|
|
||||||
<IconButton
|
|
||||||
size='small'
|
|
||||||
onClick={handlePasswordTypeChange}
|
|
||||||
>
|
|
||||||
{isPasswordShown ? (
|
|
||||||
<VisibilityOffOutlinedIcon htmlColor='#6b6b6b' />
|
|
||||||
) : (
|
|
||||||
<VisibilityOutlinedIcon htmlColor='#6b6b6b' />
|
|
||||||
)}
|
|
||||||
</IconButton>
|
|
||||||
}
|
|
||||||
type={isPasswordShown ? 'text' : 'password'}
|
|
||||||
onChange={handlePasswordChange}
|
|
||||||
value={enteredPassword}
|
|
||||||
helperText={
|
|
||||||
isPasswordInvalid ? 'Invalid password' : ''
|
|
||||||
}
|
|
||||||
placeholder='Enter a password'
|
|
||||||
helperTextProps={{
|
|
||||||
sx: {
|
|
||||||
'&.helper_text': {
|
|
||||||
color: 'red',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
disabled={!isChecked}
|
|
||||||
/>
|
|
||||||
<StyledButton
|
|
||||||
type='submit'
|
|
||||||
fullWidth
|
|
||||||
disabled={!isChecked}
|
|
||||||
>
|
|
||||||
Sync{' '}
|
|
||||||
{isLoading && (
|
|
||||||
<CircularProgress
|
|
||||||
sx={{ marginLeft: '0.5rem' }}
|
|
||||||
size={'1rem'}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</StyledButton>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
|
<StyledButton
|
||||||
|
type='submit'
|
||||||
|
fullWidth
|
||||||
|
disabled={!isChecked}
|
||||||
|
>
|
||||||
|
Sync{' '}
|
||||||
|
{isLoading && (
|
||||||
|
<CircularProgress
|
||||||
|
sx={{ marginLeft: '0.5rem' }}
|
||||||
|
size={'1rem'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</StyledButton>
|
||||||
</StyledSettingContainer>
|
</StyledSettingContainer>
|
||||||
<Button onClick={onClose}>Done</Button>
|
<Button onClick={onClose}>Done</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
@ -63,7 +63,7 @@ export interface DbSchema extends Dexie {
|
|||||||
|
|
||||||
export const db = new Dexie('noauthdb') as DbSchema
|
export const db = new Dexie('noauthdb') as DbSchema
|
||||||
|
|
||||||
db.version(7).stores({
|
db.version(8).stores({
|
||||||
keys: 'npub',
|
keys: 'npub',
|
||||||
apps: 'appNpub,npub,name,timestamp',
|
apps: 'appNpub,npub,name,timestamp',
|
||||||
perms: 'id,npub,appNpub,perm,value,timestamp',
|
perms: 'id,npub,appNpub,perm,value,timestamp',
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { Fragment } from 'react'
|
import { Fragment } from 'react'
|
||||||
import { ItemKey } from './components/ItemKey'
|
import { ItemKey } from './components/ItemKey'
|
||||||
import { Box, Stack, Typography } from '@mui/material'
|
import { Box, Stack, Typography } from '@mui/material'
|
||||||
import { AddAccountButton } from './styled'
|
import { AddAccountButton, GetStartedButton, LearnMoreButton } from './styled'
|
||||||
import { useAppSelector } from '@/store/hooks/redux'
|
import { useAppSelector } from '@/store/hooks/redux'
|
||||||
import { selectKeys } from '@/store'
|
import { selectKeys } from '@/store'
|
||||||
import { SectionTitle } from '@/shared/SectionTitle/SectionTitle'
|
import { SectionTitle } from '@/shared/SectionTitle/SectionTitle'
|
||||||
import { useModalSearchParams } from '@/hooks/useModalSearchParams'
|
import { useModalSearchParams } from '@/hooks/useModalSearchParams'
|
||||||
import { MODAL_PARAMS_KEYS } from '@/types/modal'
|
import { MODAL_PARAMS_KEYS } from '@/types/modal'
|
||||||
|
import { DOMAIN } from '@/utils/consts'
|
||||||
|
|
||||||
const HomePage = () => {
|
const HomePage = () => {
|
||||||
const keys = useAppSelector(selectKeys)
|
const keys = useAppSelector(selectKeys)
|
||||||
@ -15,16 +16,34 @@ const HomePage = () => {
|
|||||||
const { handleOpen } = useModalSearchParams()
|
const { handleOpen } = useModalSearchParams()
|
||||||
const handleClickAddAccount = () => handleOpen(MODAL_PARAMS_KEYS.INITIAL)
|
const handleClickAddAccount = () => handleOpen(MODAL_PARAMS_KEYS.INITIAL)
|
||||||
|
|
||||||
|
const handleLearnMore = () => {
|
||||||
|
// @ts-ignore
|
||||||
|
window.open(`https://info.${DOMAIN}`, '_blank').focus();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack maxHeight={'100%'} overflow={'auto'}>
|
<Stack maxHeight={'100%'} overflow={'auto'}>
|
||||||
<SectionTitle marginBottom={'0.5rem'}>
|
<SectionTitle marginBottom={'0.5rem'}>
|
||||||
{isNoKeys ? 'Welcome!' : 'Keys:'}
|
{isNoKeys ? 'Welcome' : 'Keys:'}
|
||||||
</SectionTitle>
|
</SectionTitle>
|
||||||
<Stack gap={'0.5rem'} overflow={'auto'}>
|
<Stack gap={'0.5rem'} overflow={'auto'}>
|
||||||
{isNoKeys && (
|
{isNoKeys && (
|
||||||
<Typography textAlign={'center'} variant='h5'>
|
<>
|
||||||
Hello, this is a key storage app for Nostr
|
<Typography textAlign={'left'} variant='h6' paddingTop='1em'>
|
||||||
</Typography>
|
Nsec.app is a novel key storage app for Nostr.
|
||||||
|
</Typography>
|
||||||
|
<GetStartedButton onClick={handleClickAddAccount}>
|
||||||
|
Get started
|
||||||
|
</GetStartedButton>
|
||||||
|
<Typography textAlign={'left'} variant='h6' paddingTop='2em'>
|
||||||
|
Your keys are stored in your browser and
|
||||||
|
can be used in many Nostr apps without the
|
||||||
|
need for a browser extension.
|
||||||
|
</Typography>
|
||||||
|
<LearnMoreButton onClick={handleLearnMore}>
|
||||||
|
Learn more
|
||||||
|
</LearnMoreButton>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
{!isNoKeys && (
|
{!isNoKeys && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { AppButtonProps, Button } from '@/shared/Button/Button'
|
import { AppButtonProps, Button } from '@/shared/Button/Button'
|
||||||
import { styled } from '@mui/material'
|
import { styled } from '@mui/material'
|
||||||
import PersonAddAltRoundedIcon from '@mui/icons-material/PersonAddAltRounded'
|
import PersonAddAltRoundedIcon from '@mui/icons-material/PersonAddAltRounded'
|
||||||
|
import PlayArrowOutlinedIcon from '@mui/icons-material/PlayArrowOutlined'
|
||||||
|
import HelpOutlineOutlinedIcon from '@mui/icons-material/HelpOutlineOutlined'
|
||||||
|
|
||||||
export const AddAccountButton = styled((props: AppButtonProps) => (
|
export const AddAccountButton = styled((props: AppButtonProps) => (
|
||||||
<Button {...props} startIcon={<PersonAddAltRoundedIcon />} />
|
<Button {...props} startIcon={<PersonAddAltRoundedIcon />} />
|
||||||
@ -8,3 +10,17 @@ export const AddAccountButton = styled((props: AppButtonProps) => (
|
|||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
padding: '0.35rem 1rem',
|
padding: '0.35rem 1rem',
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
export const GetStartedButton = styled((props: AppButtonProps) => (
|
||||||
|
<Button {...props} startIcon={<PlayArrowOutlinedIcon />} />
|
||||||
|
))(() => ({
|
||||||
|
alignSelf: 'left',
|
||||||
|
padding: '0.35rem 1rem',
|
||||||
|
}))
|
||||||
|
|
||||||
|
export const LearnMoreButton = styled((props: AppButtonProps) => (
|
||||||
|
<Button {...props} startIcon={<HelpOutlineOutlinedIcon />} />
|
||||||
|
))(() => ({
|
||||||
|
alignSelf: 'left',
|
||||||
|
padding: '0.35rem 1rem',
|
||||||
|
}))
|
||||||
|
@ -19,12 +19,12 @@ export const useBackgroundSigning = () => {
|
|||||||
try {
|
try {
|
||||||
await askNotificationPermission()
|
await askNotificationPermission()
|
||||||
const result = await swicCall('enablePush')
|
const result = await swicCall('enablePush')
|
||||||
if (!result) throw new Error('Failed to enable push subscription')
|
if (!result) throw new Error('Failed to activate the push subscription')
|
||||||
notify('Push notifications enabled!', 'success')
|
notify('Push notifications enabled!', 'success')
|
||||||
setShowWarning(false)
|
setShowWarning(false)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
notify(
|
notify(
|
||||||
`Failed to enable push subscription: ${error.message}`,
|
`Failed to enable push subscription: ${error}`,
|
||||||
'error',
|
'error',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ const AppRoutes = () => {
|
|||||||
<Routes>
|
<Routes>
|
||||||
<Route path='/' element={<Layout />}>
|
<Route path='/' element={<Layout />}>
|
||||||
<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='/key/:npub' element={<KeyPage />} />
|
<Route path='/key/:npub' element={<KeyPage />} />
|
||||||
<Route
|
<Route
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
export const NIP46_RELAYS = ['wss://relay.login.nostrapps.org']
|
export const NIP46_RELAYS = ['wss://relay.login.nostrapps.org']
|
||||||
export const NOAUTHD_URL = process.env.REACT_APP_NOAUTHD_URL
|
export const NOAUTHD_URL = process.env.REACT_APP_NOAUTHD_URL
|
||||||
export const WEB_PUSH_PUBKEY = process.env.REACT_APP_WEB_PUSH_PUBKEY
|
export const WEB_PUSH_PUBKEY = process.env.REACT_APP_WEB_PUSH_PUBKEY
|
||||||
|
export const DOMAIN = process.env.REACT_APP_DOMAIN
|
||||||
|
|
||||||
export enum ACTION_TYPE {
|
export enum ACTION_TYPE {
|
||||||
BASIC = 'basic',
|
BASIC = 'basic',
|
||||||
|
Reference in New Issue
Block a user