Merge pull request 'issue-31' (#35) from issue-31 into main
All checks were successful
Release / build_and_release (push) Successful in 1m8s
All checks were successful
Release / build_and_release (push) Successful in 1m8s
Reviewed-on: https://git.sigit.io/sig/it/pulls/35 Reviewed-by: s <sabir@4gl.io>
This commit is contained in:
commit
d9f9302ab8
7
.prettierrc
Normal file
7
.prettierrc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"trailingComma": "none",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"endOfLine": "auto"
|
||||||
|
}
|
@ -9,6 +9,8 @@
|
|||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
"lint:fix": "eslint . --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
"lint:fix": "eslint . --fix --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
|
"formatter:check": "npx prettier --check \"src/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\"",
|
||||||
|
"formatter:fix": "npx prettier --write \"src/**/*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}\"",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -67,7 +67,7 @@ const App = () => {
|
|||||||
})}
|
})}
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path='*'
|
path="*"
|
||||||
element={
|
element={
|
||||||
<Navigate
|
<Navigate
|
||||||
to={
|
to={
|
||||||
|
@ -87,10 +87,10 @@ export const AppBar = () => {
|
|||||||
const isAuthenticated = authState?.loggedIn === true
|
const isAuthenticated = authState?.loggedIn === true
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppBarMui position='fixed' className={styles.AppBar}>
|
<AppBarMui position="fixed" className={styles.AppBar}>
|
||||||
<Toolbar className={styles.toolbar}>
|
<Toolbar className={styles.toolbar}>
|
||||||
<Box className={styles.logoWrapper}>
|
<Box className={styles.logoWrapper}>
|
||||||
<img src='/logo.png' alt='Logo' onClick={() => navigate('/')} />
|
<img src="/logo.png" alt="Logo" onClick={() => navigate('/')} />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box className={styles.rightSideBox}>
|
<Box className={styles.rightSideBox}>
|
||||||
@ -99,7 +99,7 @@ export const AppBar = () => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(appPublicRoutes.login)
|
navigate(appPublicRoutes.login)
|
||||||
}}
|
}}
|
||||||
variant='contained'
|
variant="contained"
|
||||||
>
|
>
|
||||||
Sign in
|
Sign in
|
||||||
</Button>
|
</Button>
|
||||||
@ -113,7 +113,7 @@ export const AppBar = () => {
|
|||||||
handleClick={handleOpenUserMenu}
|
handleClick={handleOpenUserMenu}
|
||||||
/>
|
/>
|
||||||
<Menu
|
<Menu
|
||||||
id='menu-appbar'
|
id="menu-appbar"
|
||||||
anchorEl={anchorElUser}
|
anchorEl={anchorElUser}
|
||||||
anchorOrigin={{
|
anchorOrigin={{
|
||||||
vertical: 'bottom',
|
vertical: 'bottom',
|
||||||
@ -133,7 +133,7 @@ export const AppBar = () => {
|
|||||||
display: { md: 'none' }
|
display: { md: 'none' }
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant='h6'>{username}</Typography>
|
<Typography variant="h6">{username}</Typography>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={handleProfile}
|
onClick={handleProfile}
|
||||||
@ -145,7 +145,7 @@ export const AppBar = () => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
<Link
|
<Link
|
||||||
to={appPublicRoutes.help}
|
to={appPublicRoutes.help}
|
||||||
target='_blank'
|
target="_blank"
|
||||||
style={{ color: 'inherit', textDecoration: 'inherit' }}
|
style={{ color: 'inherit', textDecoration: 'inherit' }}
|
||||||
>
|
>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
@ -13,16 +13,16 @@ const Username = ({ username, avatarContent, handleClick }: Props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label='account of current user'
|
aria-label="account of current user"
|
||||||
aria-controls='menu-appbar'
|
aria-controls="menu-appbar"
|
||||||
aria-haspopup='true'
|
aria-haspopup="true"
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
color='inherit'
|
color="inherit"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={avatarContent}
|
src={avatarContent}
|
||||||
alt='user-avatar'
|
alt="user-avatar"
|
||||||
className='profile-image'
|
className="profile-image"
|
||||||
style={{
|
style={{
|
||||||
borderWidth: '3px',
|
borderWidth: '3px',
|
||||||
borderStyle: hexKey ? 'solid' : 'none',
|
borderStyle: hexKey ? 'solid' : 'none',
|
||||||
@ -30,7 +30,7 @@ const Username = ({ username, avatarContent, handleClick }: Props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Typography
|
<Typography
|
||||||
variant='h6'
|
variant="h6"
|
||||||
sx={{
|
sx={{
|
||||||
color: '#3e3e3e',
|
color: '#3e3e3e',
|
||||||
padding: '0 8px',
|
padding: '0 8px',
|
||||||
|
@ -152,9 +152,8 @@ export class MetadataController {
|
|||||||
created_at: timestamp
|
created_at: timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
signedMetadataEvent = await this.nostrController.signEvent(
|
signedMetadataEvent =
|
||||||
newMetadataEvent
|
await this.nostrController.signEvent(newMetadataEvent)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.nostrController
|
await this.nostrController
|
||||||
@ -222,9 +221,8 @@ export class MetadataController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sign job request event
|
// sign job request event
|
||||||
const jobSignedEvent = await this.nostrController.signEvent(
|
const jobSignedEvent =
|
||||||
jobEventTemplate
|
await this.nostrController.signEvent(jobEventTemplate)
|
||||||
)
|
|
||||||
|
|
||||||
const relays = [
|
const relays = [
|
||||||
'wss://relay.damus.io',
|
'wss://relay.damus.io',
|
||||||
|
@ -219,12 +219,10 @@ export class NostrController extends EventEmitter {
|
|||||||
|
|
||||||
results.forEach((res, index) => {
|
results.forEach((res, index) => {
|
||||||
if (res.status === 'rejected') {
|
if (res.status === 'rejected') {
|
||||||
failedPublishes.push(
|
failedPublishes.push({
|
||||||
{
|
relay: relays[index],
|
||||||
relay: relays[index],
|
error: res.reason.message
|
||||||
error: res.reason.message
|
})
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -59,13 +59,13 @@ export const MainLayout = () => {
|
|||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}, [dispatch])
|
}, [dispatch])
|
||||||
|
|
||||||
if (isLoading) return <LoadingSpinner desc='Loading App' />
|
if (isLoading) return <LoadingSpinner desc="Loading App" />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AppBar />
|
<AppBar />
|
||||||
|
|
||||||
<Box className='main'>
|
<Box className="main">
|
||||||
<Container
|
<Container
|
||||||
sx={{
|
sx={{
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
|
@ -360,10 +360,10 @@ export const CreatePage = () => {
|
|||||||
if (authUrl) {
|
if (authUrl) {
|
||||||
return (
|
return (
|
||||||
<iframe
|
<iframe
|
||||||
title='Nsecbunker auth'
|
title="Nsecbunker auth"
|
||||||
src={authUrl}
|
src={authUrl}
|
||||||
width='100%'
|
width="100%"
|
||||||
height='500px'
|
height="500px"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -372,13 +372,13 @@ export const CreatePage = () => {
|
|||||||
<>
|
<>
|
||||||
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
||||||
<Box className={styles.container}>
|
<Box className={styles.container}>
|
||||||
<Typography component='label' variant='h6'>
|
<Typography component="label" variant="h6">
|
||||||
Select files
|
Select files
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<MuiFileInput
|
<MuiFileInput
|
||||||
multiple
|
multiple
|
||||||
placeholder='Choose Files'
|
placeholder="Choose Files"
|
||||||
value={selectedFiles}
|
value={selectedFiles}
|
||||||
onChange={(value) => handleSelectFiles(value)}
|
onChange={(value) => handleSelectFiles(value)}
|
||||||
/>
|
/>
|
||||||
@ -386,7 +386,7 @@ export const CreatePage = () => {
|
|||||||
<ul>
|
<ul>
|
||||||
{selectedFiles.map((file, index) => (
|
{selectedFiles.map((file, index) => (
|
||||||
<li key={index}>
|
<li key={index}>
|
||||||
<Typography component='label'>{file.name}</Typography>
|
<Typography component="label">{file.name}</Typography>
|
||||||
<IconButton onClick={() => handleRemoveFile(file)}>
|
<IconButton onClick={() => handleRemoveFile(file)}>
|
||||||
<Clear style={{ color: 'red' }} />{' '}
|
<Clear style={{ color: 'red' }} />{' '}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@ -396,24 +396,24 @@ export const CreatePage = () => {
|
|||||||
|
|
||||||
{displayUserInput && (
|
{displayUserInput && (
|
||||||
<>
|
<>
|
||||||
<Typography component='label' variant='h6'>
|
<Typography component="label" variant="h6">
|
||||||
Select signers and viewers
|
Select signers and viewers
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box className={styles.inputBlock}>
|
<Box className={styles.inputBlock}>
|
||||||
<TextField
|
<TextField
|
||||||
label='nip05 / npub'
|
label="nip05 / npub"
|
||||||
value={userInput}
|
value={userInput}
|
||||||
onChange={(e) => setUserInput(e.target.value)}
|
onChange={(e) => setUserInput(e.target.value)}
|
||||||
helperText={error}
|
helperText={error}
|
||||||
error={!!error}
|
error={!!error}
|
||||||
/>
|
/>
|
||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
<InputLabel id='select-role-label'>Role</InputLabel>
|
<InputLabel id="select-role-label">Role</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
labelId='select-role-label'
|
labelId="select-role-label"
|
||||||
id='demo-simple-select'
|
id="demo-simple-select"
|
||||||
value={userRole}
|
value={userRole}
|
||||||
label='Role'
|
label="Role"
|
||||||
onChange={(e) => setUserRole(e.target.value as UserRole)}
|
onChange={(e) => setUserRole(e.target.value as UserRole)}
|
||||||
>
|
>
|
||||||
<MenuItem value={UserRole.signer}>{UserRole.signer}</MenuItem>
|
<MenuItem value={UserRole.signer}>{UserRole.signer}</MenuItem>
|
||||||
@ -425,7 +425,7 @@ export const CreatePage = () => {
|
|||||||
<Button
|
<Button
|
||||||
disabled={!userInput}
|
disabled={!userInput}
|
||||||
onClick={handleAddUser}
|
onClick={handleAddUser}
|
||||||
variant='contained'
|
variant="contained"
|
||||||
>
|
>
|
||||||
Add
|
Add
|
||||||
</Button>
|
</Button>
|
||||||
@ -437,7 +437,7 @@ export const CreatePage = () => {
|
|||||||
handleRemoveUser={handleRemoveUser}
|
handleRemoveUser={handleRemoveUser}
|
||||||
/>
|
/>
|
||||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||||
<Button onClick={handleCreate} variant='contained'>
|
<Button onClick={handleCreate} variant="contained">
|
||||||
Create
|
Create
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
@ -515,8 +515,8 @@ const DisplayUser = ({
|
|||||||
<img
|
<img
|
||||||
onError={imageLoadError}
|
onError={imageLoadError}
|
||||||
src={userMeta?.picture || roboUrl}
|
src={userMeta?.picture || roboUrl}
|
||||||
alt='Profile Image'
|
alt="Profile Image"
|
||||||
className='profile-image'
|
className="profile-image"
|
||||||
style={{
|
style={{
|
||||||
borderWidth: '3px',
|
borderWidth: '3px',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
@ -524,7 +524,7 @@ const DisplayUser = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Link to={getProfileRoute(user.pubkey)}>
|
<Link to={getProfileRoute(user.pubkey)}>
|
||||||
<Typography component='label' className={styles.name}>
|
<Typography component="label" className={styles.name}>
|
||||||
{userMeta?.display_name ||
|
{userMeta?.display_name ||
|
||||||
userMeta?.name ||
|
userMeta?.name ||
|
||||||
shorten(npub)}
|
shorten(npub)}
|
||||||
@ -549,7 +549,7 @@ const DisplayUser = ({
|
|||||||
</Select>
|
</Select>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Tooltip title='Remove User' arrow>
|
<Tooltip title="Remove User" arrow>
|
||||||
<IconButton onClick={() => handleRemoveUser(user.pubkey)}>
|
<IconButton onClick={() => handleRemoveUser(user.pubkey)}>
|
||||||
<Clear style={{ color: 'red' }} />
|
<Clear style={{ color: 'red' }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
@ -93,7 +93,7 @@ export const DecryptZip = () => {
|
|||||||
<>
|
<>
|
||||||
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
||||||
<Box className={styles.container}>
|
<Box className={styles.container}>
|
||||||
<Typography component='label' variant='h6'>
|
<Typography component="label" variant="h6">
|
||||||
Select encrypted zip file
|
Select encrypted zip file
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
@ -104,11 +104,11 @@ export const DecryptZip = () => {
|
|||||||
>
|
>
|
||||||
{isDraggingOver && (
|
{isDraggingOver && (
|
||||||
<Box className={styles.fileDragOver}>
|
<Box className={styles.fileDragOver}>
|
||||||
<Typography variant='body1'>Drop file here</Typography>
|
<Typography variant="body1">Drop file here</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<MuiFileInput
|
<MuiFileInput
|
||||||
placeholder='Drop file here, or click to select'
|
placeholder="Drop file here, or click to select"
|
||||||
value={selectedFile}
|
value={selectedFile}
|
||||||
onChange={(value) => setSelectedFile(value)}
|
onChange={(value) => setSelectedFile(value)}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@ -119,8 +119,8 @@ export const DecryptZip = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
label='Encryption Key'
|
label="Encryption Key"
|
||||||
variant='outlined'
|
variant="outlined"
|
||||||
value={encryptionKey}
|
value={encryptionKey}
|
||||||
onChange={(e) => setEncryptionKey(e.target.value)}
|
onChange={(e) => setEncryptionKey(e.target.value)}
|
||||||
/>
|
/>
|
||||||
@ -129,7 +129,7 @@ export const DecryptZip = () => {
|
|||||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleDecrypt}
|
onClick={handleDecrypt}
|
||||||
variant='contained'
|
variant="contained"
|
||||||
disabled={!selectedFile || !encryptionKey}
|
disabled={!selectedFile || !encryptionKey}
|
||||||
>
|
>
|
||||||
Decrypt
|
Decrypt
|
||||||
|
@ -10,13 +10,13 @@ export const HomePage = () => {
|
|||||||
<Box className={styles.container}>
|
<Box className={styles.container}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => navigate(appPrivateRoutes.create)}
|
onClick={() => navigate(appPrivateRoutes.create)}
|
||||||
variant='contained'
|
variant="contained"
|
||||||
>
|
>
|
||||||
Create
|
Create
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => navigate(appPrivateRoutes.verify)}
|
onClick={() => navigate(appPrivateRoutes.verify)}
|
||||||
variant='contained'
|
variant="contained"
|
||||||
>
|
>
|
||||||
Verify
|
Verify
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -57,7 +57,7 @@ export const LandingPage = () => {
|
|||||||
? theme.palette.getContrastText(bodyBackgroundColor)
|
? theme.palette.getContrastText(bodyBackgroundColor)
|
||||||
: ''
|
: ''
|
||||||
}}
|
}}
|
||||||
variant='h4'
|
variant="h4"
|
||||||
>
|
>
|
||||||
What is Nostr?
|
What is Nostr?
|
||||||
</Typography>
|
</Typography>
|
||||||
@ -67,14 +67,14 @@ export const LandingPage = () => {
|
|||||||
? theme.palette.getContrastText(bodyBackgroundColor)
|
? theme.palette.getContrastText(bodyBackgroundColor)
|
||||||
: ''
|
: ''
|
||||||
}}
|
}}
|
||||||
variant='body1'
|
variant="body1"
|
||||||
>
|
>
|
||||||
Nostr is a decentralised messaging protocol where YOU own your
|
Nostr is a decentralised messaging protocol where YOU own your
|
||||||
identity. To get started, you must have an existing{' '}
|
identity. To get started, you must have an existing{' '}
|
||||||
<a
|
<a
|
||||||
className='bold-link'
|
className="bold-link"
|
||||||
target='_blank'
|
target="_blank"
|
||||||
href='https://nostr.com/'
|
href="https://nostr.com/"
|
||||||
>
|
>
|
||||||
Nostr account
|
Nostr account
|
||||||
</a>
|
</a>
|
||||||
@ -95,7 +95,7 @@ export const LandingPage = () => {
|
|||||||
<div className={styles.loginBottomBar}>
|
<div className={styles.loginBottomBar}>
|
||||||
<Button
|
<Button
|
||||||
className={styles.loginBtn}
|
className={styles.loginBtn}
|
||||||
variant='contained'
|
variant="contained"
|
||||||
onClick={onSignInClick}
|
onClick={onSignInClick}
|
||||||
>
|
>
|
||||||
GET STARTED
|
GET STARTED
|
||||||
|
@ -53,9 +53,8 @@ export const Login = () => {
|
|||||||
dispatch(updateLoginMethod(LoginMethods.extension))
|
dispatch(updateLoginMethod(LoginMethods.extension))
|
||||||
|
|
||||||
setLoadingSpinnerDesc('Authenticating and finding metadata')
|
setLoadingSpinnerDesc('Authenticating and finding metadata')
|
||||||
const redirectPath = await authController.authenticateAndFindMetadata(
|
const redirectPath =
|
||||||
pubkey
|
await authController.authenticateAndFindMetadata(pubkey)
|
||||||
)
|
|
||||||
|
|
||||||
navigate(redirectPath)
|
navigate(redirectPath)
|
||||||
})
|
})
|
||||||
@ -290,10 +289,10 @@ export const Login = () => {
|
|||||||
if (authUrl) {
|
if (authUrl) {
|
||||||
return (
|
return (
|
||||||
<iframe
|
<iframe
|
||||||
title='Nsecbunker auth'
|
title="Nsecbunker auth"
|
||||||
src={authUrl}
|
src={authUrl}
|
||||||
width='100%'
|
width="100%"
|
||||||
height='500px'
|
height="500px"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -302,21 +301,21 @@ export const Login = () => {
|
|||||||
<>
|
<>
|
||||||
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
{isLoading && <LoadingSpinner desc={loadingSpinnerDesc} />}
|
||||||
<div className={styles.loginPage}>
|
<div className={styles.loginPage}>
|
||||||
<Typography variant='h4'>Welcome to Sigit</Typography>
|
<Typography variant="h4">Welcome to Sigit</Typography>
|
||||||
<TextField
|
<TextField
|
||||||
label='nip05 / npub / nsec / bunker connx string'
|
label="nip05 / npub / nsec / bunker connx string"
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
onChange={(e) => setInputValue(e.target.value)}
|
onChange={(e) => setInputValue(e.target.value)}
|
||||||
sx={{ width: '100%', mt: 2 }}
|
sx={{ width: '100%', mt: 2 }}
|
||||||
/>
|
/>
|
||||||
{isNostrExtensionAvailable && (
|
{isNostrExtensionAvailable && (
|
||||||
<Button onClick={loginWithExtension} variant='text'>
|
<Button onClick={loginWithExtension} variant="text">
|
||||||
Login with extension
|
Login with extension
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||||
<Button disabled={!inputValue} onClick={login} variant='contained'>
|
<Button disabled={!inputValue} onClick={login} variant="contained">
|
||||||
Login
|
Login
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -127,7 +127,7 @@ export const ProfilePage = () => {
|
|||||||
label={label}
|
label={label}
|
||||||
id={label.split(' ').join('-')}
|
id={label.split(' ').join('-')}
|
||||||
value={profileMetadata![key] || ''}
|
value={profileMetadata![key] || ''}
|
||||||
size='small'
|
size="small"
|
||||||
multiline={multiline}
|
multiline={multiline}
|
||||||
rows={rows}
|
rows={rows}
|
||||||
className={styles.textField}
|
className={styles.textField}
|
||||||
@ -166,7 +166,7 @@ export const ProfilePage = () => {
|
|||||||
label={label}
|
label={label}
|
||||||
id={label.split(' ').join('-')}
|
id={label.split(' ').join('-')}
|
||||||
defaultValue={value}
|
defaultValue={value}
|
||||||
size='small'
|
size="small"
|
||||||
className={styles.textField}
|
className={styles.textField}
|
||||||
disabled
|
disabled
|
||||||
type={isPassword ? 'password' : 'text'}
|
type={isPassword ? 'password' : 'text'}
|
||||||
@ -230,18 +230,23 @@ export const ProfilePage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns robohash generate button, loading spinner or no button
|
* @returns robohash generate button, loading spinner or no button
|
||||||
*/
|
*/
|
||||||
const robohashButton = () => {
|
const robohashButton = () => {
|
||||||
if (profileMetadata?.picture?.includes('robohash')) return null
|
if (profileMetadata?.picture?.includes('robohash')) return null
|
||||||
|
|
||||||
return <Tooltip title="Generate a robohash avatar">
|
return (
|
||||||
{avatarLoading ? <CircularProgress style={{padding: 8}} size={22}/>
|
<Tooltip title="Generate a robohash avatar">
|
||||||
: <IconButton onClick={generateRobotAvatar}>
|
{avatarLoading ? (
|
||||||
<SmartToy/>
|
<CircularProgress style={{ padding: 8 }} size={22} />
|
||||||
</IconButton>}
|
) : (
|
||||||
</Tooltip>
|
<IconButton onClick={generateRobotAvatar}>
|
||||||
|
<SmartToy />
|
||||||
|
</IconButton>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -284,7 +289,7 @@ export const ProfilePage = () => {
|
|||||||
}}
|
}}
|
||||||
className={styles.img}
|
className={styles.img}
|
||||||
src={profileMetadata.picture || placeholderAvatar}
|
src={profileMetadata.picture || placeholderAvatar}
|
||||||
alt='Profile Image'
|
alt="Profile Image"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{nostrJoiningBlock && (
|
{nostrJoiningBlock && (
|
||||||
@ -296,7 +301,7 @@ export const ProfilePage = () => {
|
|||||||
}}
|
}}
|
||||||
component={Link}
|
component={Link}
|
||||||
to={`https://njump.me/${nostrJoiningBlock.encodedEventPointer}`}
|
to={`https://njump.me/${nostrJoiningBlock.encodedEventPointer}`}
|
||||||
target='_blank'
|
target="_blank"
|
||||||
>
|
>
|
||||||
On nostr since {nostrJoiningBlock.block.toLocaleString()}
|
On nostr since {nostrJoiningBlock.block.toLocaleString()}
|
||||||
</Typography>
|
</Typography>
|
||||||
@ -333,7 +338,7 @@ export const ProfilePage = () => {
|
|||||||
{isUsersOwnProfile && (
|
{isUsersOwnProfile && (
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
loading={savingProfileMetadata}
|
loading={savingProfileMetadata}
|
||||||
variant='contained'
|
variant="contained"
|
||||||
onClick={handleSaveMetadata}
|
onClick={handleSaveMetadata}
|
||||||
>
|
>
|
||||||
SAVE
|
SAVE
|
||||||
|
@ -455,10 +455,10 @@ export const VerifyPage = () => {
|
|||||||
if (authUrl) {
|
if (authUrl) {
|
||||||
return (
|
return (
|
||||||
<iframe
|
<iframe
|
||||||
title='Nsecbunker auth'
|
title="Nsecbunker auth"
|
||||||
src={authUrl}
|
src={authUrl}
|
||||||
width='100%'
|
width="100%"
|
||||||
height='500px'
|
height="500px"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -469,13 +469,13 @@ export const VerifyPage = () => {
|
|||||||
<Box className={styles.container}>
|
<Box className={styles.container}>
|
||||||
{displayInput && (
|
{displayInput && (
|
||||||
<>
|
<>
|
||||||
<Typography component='label' variant='h6'>
|
<Typography component="label" variant="h6">
|
||||||
Select sigit file
|
Select sigit file
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Box className={styles.inputBlock}>
|
<Box className={styles.inputBlock}>
|
||||||
<MuiFileInput
|
<MuiFileInput
|
||||||
placeholder='Select file'
|
placeholder="Select file"
|
||||||
value={selectedFile}
|
value={selectedFile}
|
||||||
onChange={(value) => setSelectedFile(value)}
|
onChange={(value) => setSelectedFile(value)}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
@ -487,8 +487,8 @@ export const VerifyPage = () => {
|
|||||||
|
|
||||||
{selectedFile && (
|
{selectedFile && (
|
||||||
<TextField
|
<TextField
|
||||||
label='Encryption Key'
|
label="Encryption Key"
|
||||||
variant='outlined'
|
variant="outlined"
|
||||||
value={encryptionKey}
|
value={encryptionKey}
|
||||||
onChange={(e) => setEncryptionKey(e.target.value)}
|
onChange={(e) => setEncryptionKey(e.target.value)}
|
||||||
/>
|
/>
|
||||||
@ -497,7 +497,7 @@ export const VerifyPage = () => {
|
|||||||
|
|
||||||
{selectedFile && encryptionKey && (
|
{selectedFile && encryptionKey && (
|
||||||
<Box sx={{ mt: 2, display: 'flex', justifyContent: 'center' }}>
|
<Box sx={{ mt: 2, display: 'flex', justifyContent: 'center' }}>
|
||||||
<Button onClick={handleDecrypt} variant='contained'>
|
<Button onClick={handleDecrypt} variant="contained">
|
||||||
Decrypt
|
Decrypt
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
@ -509,7 +509,7 @@ export const VerifyPage = () => {
|
|||||||
<>
|
<>
|
||||||
<DisplayMeta meta={meta} nextSigner={nextSinger} />
|
<DisplayMeta meta={meta} nextSigner={nextSinger} />
|
||||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||||
<Button onClick={handleExport} variant='contained'>
|
<Button onClick={handleExport} variant="contained">
|
||||||
Export
|
Export
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
@ -524,7 +524,7 @@ export const VerifyPage = () => {
|
|||||||
<>
|
<>
|
||||||
<DisplayMeta meta={meta} nextSigner={nextSinger} />
|
<DisplayMeta meta={meta} nextSigner={nextSinger} />
|
||||||
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
|
||||||
<Button onClick={handleSign} variant='contained'>
|
<Button onClick={handleSign} variant="contained">
|
||||||
Sign
|
Sign
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
@ -661,7 +661,7 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
|
|||||||
gap: '15px'
|
gap: '15px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant='h6' sx={{ color: textColor }}>
|
<Typography variant="h6" sx={{ color: textColor }}>
|
||||||
Submitted By
|
Submitted By
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box className={styles.user}>
|
<Box className={styles.user}>
|
||||||
@ -671,8 +671,8 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
|
|||||||
metadata[meta.submittedBy]?.picture ||
|
metadata[meta.submittedBy]?.picture ||
|
||||||
getRoboImageUrl(meta.submittedBy)
|
getRoboImageUrl(meta.submittedBy)
|
||||||
}
|
}
|
||||||
alt='Profile Image'
|
alt="Profile Image"
|
||||||
className='profile-image'
|
className="profile-image"
|
||||||
style={{
|
style={{
|
||||||
borderWidth: '3px',
|
borderWidth: '3px',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
@ -680,7 +680,7 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Link to={getProfileRoute(meta.submittedBy)}>
|
<Link to={getProfileRoute(meta.submittedBy)}>
|
||||||
<Typography component='label' className={styles.name}>
|
<Typography component="label" className={styles.name}>
|
||||||
{metadata[meta.submittedBy]?.display_name ||
|
{metadata[meta.submittedBy]?.display_name ||
|
||||||
metadata[meta.submittedBy]?.name ||
|
metadata[meta.submittedBy]?.name ||
|
||||||
shorten(hexToNpub(meta.submittedBy))}
|
shorten(hexToNpub(meta.submittedBy))}
|
||||||
@ -695,7 +695,7 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
|
|||||||
alignItems: 'flex-start'
|
alignItems: 'flex-start'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant='h6' sx={{ color: textColor }}>
|
<Typography variant="h6" sx={{ color: textColor }}>
|
||||||
Files
|
Files
|
||||||
</Typography>
|
</Typography>
|
||||||
<ul>
|
<ul>
|
||||||
@ -741,8 +741,8 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
|
|||||||
<img
|
<img
|
||||||
onError={imageLoadError}
|
onError={imageLoadError}
|
||||||
src={userMeta?.picture || roboUrl}
|
src={userMeta?.picture || roboUrl}
|
||||||
alt='Profile Image'
|
alt="Profile Image"
|
||||||
className='profile-image'
|
className="profile-image"
|
||||||
style={{
|
style={{
|
||||||
borderWidth: '3px',
|
borderWidth: '3px',
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
@ -750,7 +750,7 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Link to={getProfileRoute(user.pubkey)}>
|
<Link to={getProfileRoute(user.pubkey)}>
|
||||||
<Typography component='label' className={styles.name}>
|
<Typography component="label" className={styles.name}>
|
||||||
{userMeta?.display_name ||
|
{userMeta?.display_name ||
|
||||||
userMeta?.name ||
|
userMeta?.name ||
|
||||||
shorten(npub)}
|
shorten(npub)}
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
export class DecryptionError extends Error {
|
export class DecryptionError extends Error {
|
||||||
public message: string = ''
|
public message: string = ''
|
||||||
|
|
||||||
constructor(
|
constructor(public inputError: any) {
|
||||||
public inputError: any
|
|
||||||
) {
|
|
||||||
super()
|
super()
|
||||||
|
|
||||||
if (inputError.message.toLowerCase().includes('expected')) {
|
if (inputError.message.toLowerCase().includes('expected')) {
|
||||||
this.message = `The decryption key length or format is invalid.`
|
this.message = `The decryption key length or format is invalid.`
|
||||||
} else if (inputError.message.includes('The JWK "alg" member was inconsistent')) {
|
} else if (
|
||||||
|
inputError.message.includes('The JWK "alg" member was inconsistent')
|
||||||
|
) {
|
||||||
this.message = `The decryption key is invalid.`
|
this.message = `The decryption key is invalid.`
|
||||||
} else {
|
} else {
|
||||||
this.message = inputError.message || 'An error occurred while decrypting file.'
|
this.message =
|
||||||
|
inputError.message || 'An error occurred while decrypting file.'
|
||||||
}
|
}
|
||||||
|
|
||||||
this.name = 'DecryptionError'
|
this.name = 'DecryptionError'
|
||||||
Object.setPrototypeOf(this, DecryptionError.prototype)
|
Object.setPrototypeOf(this, DecryptionError.prototype)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,14 +66,14 @@ export const decryptArrayBuffer = async (
|
|||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const { cryptoKey, iv } = await importKey(key)
|
const { cryptoKey, iv } = await importKey(key)
|
||||||
|
|
||||||
// Decrypt the data
|
// Decrypt the data
|
||||||
const decryptedData = await window.crypto.subtle.decrypt(
|
const decryptedData = await window.crypto.subtle.decrypt(
|
||||||
{ name: ENCRYPTION_ALGO_NAME, iv },
|
{ name: ENCRYPTION_ALGO_NAME, iv },
|
||||||
cryptoKey,
|
cryptoKey,
|
||||||
encryptedData
|
encryptedData
|
||||||
)
|
)
|
||||||
|
|
||||||
return decryptedData
|
return decryptedData
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new DecryptionError(err)
|
throw new DecryptionError(err)
|
||||||
|
@ -18,8 +18,8 @@ export const uploadToFileStorage = async (
|
|||||||
const unixNow = Math.floor(Date.now() / 1000)
|
const unixNow = Math.floor(Date.now() / 1000)
|
||||||
|
|
||||||
// Create a File object with the Blob data
|
// Create a File object with the Blob data
|
||||||
const file = new File([blob], `zipped-${unixNow}.zip`, {
|
const file = new File([blob], `compressed-${unixNow}.sigit`, {
|
||||||
type: 'application/zip'
|
type: 'application/sigit'
|
||||||
})
|
})
|
||||||
|
|
||||||
// Define event metadata for authorization
|
// Define event metadata for authorization
|
||||||
@ -39,13 +39,13 @@ export const uploadToFileStorage = async (
|
|||||||
const authEvent = await nostrController.signEvent(event)
|
const authEvent = await nostrController.signEvent(event)
|
||||||
|
|
||||||
// URL of the file storage service
|
// URL of the file storage service
|
||||||
const FILE_STORAGE_URL = 'https://blossom.sigit.io'
|
const FILE_STORAGE_URL = 'https://blossom.sigit.io' // REFACTOR: should be an env
|
||||||
|
|
||||||
// Upload the file to the file storage service using Axios
|
// Upload the file to the file storage service using Axios
|
||||||
const response = await axios.put(`${FILE_STORAGE_URL}/upload`, file, {
|
const response = await axios.put(`${FILE_STORAGE_URL}/upload`, file, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: 'Nostr ' + btoa(JSON.stringify(authEvent)), // Set authorization header
|
Authorization: 'Nostr ' + btoa(JSON.stringify(authEvent)), // Set authorization header
|
||||||
'Content-Type': 'application/zip' // Set content type header
|
'Content-Type': 'application/sigit' // Set content type header
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -166,7 +166,9 @@ export const sendDM = async (
|
|||||||
toast.error('An error occurred while publishing DM')
|
toast.error('An error occurred while publishing DM')
|
||||||
|
|
||||||
errResults.forEach((errResult: any) => {
|
errResults.forEach((errResult: any) => {
|
||||||
toast.error(`Publishing to ${errResult.relay} caused the following error: ${errResult.error}`)
|
toast.error(
|
||||||
|
`Publishing to ${errResult.relay} caused the following error: ${errResult.error}`
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
return null
|
return null
|
||||||
|
Loading…
Reference in New Issue
Block a user