feat: sync and update with all changes from solar-punk-ltd fork (#730)
* fix: swap error caused by invalid id and batchcount * fix: enhance creation messages for admin drive and user drives * fix: identity and wallet creation * fix: asset preview types * fix: fm search unicode text * fix: feed identity and stamp usage * fix: ui display changes * fix: stamp buy and dilute * fix: vite polyfill warning for stream * fix: standard mode postage stamp purchase reserves incorrect size and duration * fix: add syncing message for Bee node and update page state handling * refactor: stamp depth and amount validation --------- Co-authored-by: Balint Ujvari <balint.ujvari@solarpunk.buzz> Co-authored-by: Bálint Ujvári <58116288+bosi95@users.noreply.github.com> Co-authored-by: rolandlor <33499567+rolandlor@users.noreply.github.com>
This commit is contained in:
@@ -40,7 +40,7 @@ export default function ExpandableListItem({ label, value, tooltip }: Props): Re
|
||||
)}
|
||||
{value && (
|
||||
<Box flex={1} textAlign="right">
|
||||
<Typography variant="body2">
|
||||
<Typography variant="body2" component="div">
|
||||
{value}
|
||||
{tooltip && (
|
||||
<Tooltip title={tooltip} placement="top" arrow>
|
||||
|
||||
@@ -16,11 +16,17 @@ const useStyles = makeStyles()(theme => ({
|
||||
header: {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
marginBottom: theme.spacing(0.25),
|
||||
borderLeft: `${theme.spacing(0.25)}px solid rgba(0,0,0,0)`,
|
||||
borderLeft: `${theme.spacing(0.25)} solid rgba(0,0,0,0)`,
|
||||
wordBreak: 'break-word',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
'&:focus-within': {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
headerOpen: {
|
||||
borderLeft: `${theme.spacing(0.25)}px solid ${theme.palette.primary.main}`,
|
||||
borderLeft: `${theme.spacing(0.25)} solid ${theme.palette.primary.main}`,
|
||||
},
|
||||
copyValue: {
|
||||
cursor: 'pointer',
|
||||
@@ -95,35 +101,35 @@ export default function ExpandableListItemInput({
|
||||
}
|
||||
|
||||
return (
|
||||
<ListItemButton className={`${classes.header} ${open ? classes.headerOpen : ''}`}>
|
||||
<Box display="flex" flexDirection="column" width="100%">
|
||||
<Box display="flex" flexDirection="row" alignItems="center" width="100%">
|
||||
{label && (
|
||||
<Box flex={1} minWidth={0}>
|
||||
<Typography variant="body1" className={classes.unselectableLabel} component="span">
|
||||
{label}
|
||||
</Typography>
|
||||
<>
|
||||
<ListItemButton className={`${classes.header} ${open ? classes.headerOpen : ''}`}>
|
||||
<Box display="flex" flexDirection="column" width="100%">
|
||||
<Box display="flex" flexDirection="row" alignItems="center" width="100%">
|
||||
{label && (
|
||||
<Box flex={1} minWidth={0}>
|
||||
<Typography variant="body1" className={classes.unselectableLabel} component="span">
|
||||
{label}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Box flex={3} display="flex" alignItems="center" justifyContent="flex-end" minWidth={0} gap={1}>
|
||||
{!open && value && (
|
||||
<Typography
|
||||
variant="body2"
|
||||
component="span"
|
||||
sx={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}
|
||||
>
|
||||
{value}
|
||||
</Typography>
|
||||
)}
|
||||
{!expandedOnly && !locked && (
|
||||
<IconButton size="small" className={classes.copyValue} onClick={toggleOpen}>
|
||||
{open ? <Minus strokeWidth={1} /> : <Edit strokeWidth={1} />}
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
<Box flex={3} display="flex" alignItems="center" justifyContent="flex-end" minWidth={0} gap={1}>
|
||||
{!open && value && (
|
||||
<Typography
|
||||
variant="body2"
|
||||
component="span"
|
||||
sx={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}
|
||||
>
|
||||
{value}
|
||||
</Typography>
|
||||
)}
|
||||
{!expandedOnly && !locked && (
|
||||
<IconButton size="small" className={classes.copyValue} onClick={toggleOpen}>
|
||||
{open ? <Minus strokeWidth={1} /> : <Edit strokeWidth={1} />}
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<Box display="flex" flexDirection="column" width="100%">
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<Box display="flex" alignItems="center" width="100%" minWidth={0}>
|
||||
<InputBase
|
||||
value={inputValue}
|
||||
@@ -146,36 +152,38 @@ export default function ExpandableListItemInput({
|
||||
/>
|
||||
</Box>
|
||||
{helperText && <ExpandableListItemNote>{helperText}</ExpandableListItemNote>}
|
||||
<Box mt={2}>
|
||||
<ExpandableListItemActions>
|
||||
<SwarmButton
|
||||
disabled={
|
||||
loading ||
|
||||
inputValue === value ||
|
||||
Boolean(confirmLabelDisabled) ||
|
||||
(inputValue === '' && value === undefined)
|
||||
}
|
||||
loading={loading}
|
||||
iconType={confirmIcon ?? Check}
|
||||
onClick={() => {
|
||||
onConfirm?.(inputValue.trim())
|
||||
}}
|
||||
>
|
||||
{confirmLabel || 'Save'}
|
||||
</SwarmButton>
|
||||
<SwarmButton
|
||||
disabled={loading || inputValue === value || inputValue === ''}
|
||||
iconType={X}
|
||||
onClick={() => setInputValue(value || '')}
|
||||
cancel
|
||||
>
|
||||
Cancel
|
||||
</SwarmButton>
|
||||
</ExpandableListItemActions>
|
||||
</Box>
|
||||
</Box>
|
||||
</Collapse>
|
||||
</Box>
|
||||
</ListItemButton>
|
||||
</Collapse>
|
||||
</Box>
|
||||
</ListItemButton>
|
||||
<Collapse in={open} timeout="auto" unmountOnExit>
|
||||
<Box mt={2}>
|
||||
<ExpandableListItemActions>
|
||||
<SwarmButton
|
||||
disabled={
|
||||
loading ||
|
||||
inputValue === value ||
|
||||
Boolean(confirmLabelDisabled) ||
|
||||
(inputValue === '' && value === undefined)
|
||||
}
|
||||
loading={loading}
|
||||
iconType={confirmIcon ?? Check}
|
||||
onClick={() => {
|
||||
onConfirm?.(inputValue.trim())
|
||||
}}
|
||||
>
|
||||
{confirmLabel || 'Save'}
|
||||
</SwarmButton>
|
||||
<SwarmButton
|
||||
disabled={loading || inputValue === value || inputValue === ''}
|
||||
iconType={X}
|
||||
onClick={() => setInputValue(value || '')}
|
||||
cancel
|
||||
>
|
||||
Cancel
|
||||
</SwarmButton>
|
||||
</ExpandableListItemActions>
|
||||
</Box>
|
||||
</Collapse>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,11 +10,17 @@ const useStyles = makeStyles()(theme => ({
|
||||
header: {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
marginBottom: theme.spacing(0.25),
|
||||
borderLeft: `${theme.spacing(0.25)}px solid rgba(0,0,0,0)`,
|
||||
borderLeft: `${theme.spacing(0.25)} solid rgba(0,0,0,0)`,
|
||||
wordBreak: 'break-word',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
'&:focus-within': {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
headerOpen: {
|
||||
borderLeft: `${theme.spacing(0.25)}px solid ${theme.palette.primary.main}`,
|
||||
borderLeft: `${theme.spacing(0.25)} solid ${theme.palette.primary.main}`,
|
||||
},
|
||||
copyValue: {
|
||||
cursor: 'pointer',
|
||||
@@ -69,7 +75,7 @@ export default function ExpandableListItemKey({ label, value, expanded }: Props)
|
||||
|
||||
return (
|
||||
<ListItemButton className={`${classes.header} ${open ? classes.headerOpen : ''}`}>
|
||||
<Grid container direction="column" justifyContent="space-between" alignItems="stretch">
|
||||
<Grid container direction="column" justifyContent="space-between" alignItems="stretch" style={{ width: '100%' }}>
|
||||
<Grid container direction="row" justifyContent="space-between" alignItems="center">
|
||||
{label && (
|
||||
<Typography variant="body1" component="span">
|
||||
|
||||
@@ -10,11 +10,17 @@ const useStyles = makeStyles()(theme => ({
|
||||
header: {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
marginBottom: theme.spacing(0.25),
|
||||
borderLeft: `${theme.spacing(0.25)}px solid rgba(0,0,0,0)`,
|
||||
borderLeft: `${theme.spacing(0.25)} solid rgba(0,0,0,0)`,
|
||||
wordBreak: 'break-word',
|
||||
'&:hover': {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
'&:focus-within': {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
},
|
||||
},
|
||||
headerOpen: {
|
||||
borderLeft: `${theme.spacing(0.25)}px solid ${theme.palette.primary.main}`,
|
||||
borderLeft: `${theme.spacing(0.25)} solid ${theme.palette.primary.main}`,
|
||||
},
|
||||
openLinkIcon: {
|
||||
cursor: 'pointer',
|
||||
|
||||
@@ -139,7 +139,7 @@ export default function SideBar(): ReactElement {
|
||||
label: 'File Manager',
|
||||
path: ROUTES.FILEMANAGER,
|
||||
icon: FileManagerIcon,
|
||||
pathMatcherSubstring: '/filemanager/',
|
||||
pathMatcherSubstring: '/filemanager',
|
||||
},
|
||||
{
|
||||
label: 'Account',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BatchId, Bee } from '@ethersphere/bee-js'
|
||||
import { Bee, PostageBatch } from '@ethersphere/bee-js'
|
||||
import { Box } from '@mui/material'
|
||||
import Button from '@mui/material/Button'
|
||||
import Dialog from '@mui/material/Dialog'
|
||||
@@ -8,19 +8,48 @@ import DialogTitle from '@mui/material/DialogTitle'
|
||||
import Input from '@mui/material/Input'
|
||||
import { useSnackbar } from 'notistack'
|
||||
import React, { ReactElement, ReactNode, useState } from 'react'
|
||||
import { makeStyles } from 'tss-react/mui'
|
||||
|
||||
interface Props {
|
||||
type: 'Topup' | 'Dilute'
|
||||
icon: ReactNode
|
||||
bee: Bee
|
||||
stamp: BatchId
|
||||
import { CheckState } from '../providers/Bee'
|
||||
|
||||
const useStyles = makeStyles()(theme => ({
|
||||
buttonSelected: {
|
||||
color: 'white',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
'&:hover': {
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: 'white',
|
||||
'@media (hover: none)': {
|
||||
color: 'white',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
},
|
||||
},
|
||||
buttonUnselected: {
|
||||
color: '#dd7700',
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
}))
|
||||
|
||||
export enum StampExtensionType {
|
||||
Topup = 'Topup',
|
||||
Dilute = 'Dilute',
|
||||
}
|
||||
|
||||
export default function StampExtensionModal({ type, icon, bee, stamp }: Props): ReactElement {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [amount, setAmount] = useState('')
|
||||
interface Props {
|
||||
type: StampExtensionType
|
||||
icon: ReactNode
|
||||
bee: Bee
|
||||
stamp: PostageBatch
|
||||
status: CheckState
|
||||
}
|
||||
|
||||
export default function StampExtensionModal({ type, icon, bee, stamp, status }: Props): ReactElement {
|
||||
const { classes } = useStyles()
|
||||
const [open, setOpen] = useState<boolean>(false)
|
||||
const [amount, setAmount] = useState<string>('')
|
||||
const { enqueueSnackbar } = useSnackbar()
|
||||
const label = `${type} ${stamp.toHex().substring(0, 8)}`
|
||||
const label = `${type} ${stamp.batchID.toHex().substring(0, 8)}`
|
||||
|
||||
const handleClickOpen = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
setOpen(true)
|
||||
@@ -32,23 +61,65 @@ export default function StampExtensionModal({ type, icon, bee, stamp }: Props):
|
||||
}
|
||||
|
||||
const handleAction = async () => {
|
||||
if (type === 'Topup') {
|
||||
if (status !== CheckState.OK) {
|
||||
enqueueSnackbar(`Node connection status is not ${CheckState.OK}: ${status}`, { variant: 'error' })
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (type === StampExtensionType.Topup) {
|
||||
const isAmountInvalid = BigInt(amount) <= BigInt(0)
|
||||
|
||||
if (isAmountInvalid) {
|
||||
enqueueSnackbar(`Invalid amount: ${amount}, it must be greate than 0`, { variant: 'error' })
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await bee.topUpBatch(stamp, amount)
|
||||
await bee.topUpBatch(stamp.batchID, amount)
|
||||
enqueueSnackbar(`Successfully topped up stamp, your changes will appear soon`, { variant: 'success' })
|
||||
} catch (error) {
|
||||
enqueueSnackbar(`Failed to topup stamp: ${error || 'Unknown reason'}`, { variant: 'error' })
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (type === 'Dilute') {
|
||||
if (type === StampExtensionType.Dilute) {
|
||||
const newDepth = parseInt(amount, 10)
|
||||
const ttlDays = stamp.duration.toDays()
|
||||
const currentDepth = stamp.depth
|
||||
const maxHalvings = Math.floor(Math.log2(ttlDays)) + currentDepth
|
||||
const isDepthInvalid = newDepth > maxHalvings || newDepth <= currentDepth
|
||||
|
||||
if (isDepthInvalid) {
|
||||
enqueueSnackbar(`Invalid depth: ${newDepth} (${currentDepth} < new depth < ${maxHalvings})`, {
|
||||
variant: 'error',
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (ttlDays <= 2) {
|
||||
enqueueSnackbar(`TTL: ${ttlDays} <= 2 days, cannot dilute stamp (min. TTL is 1 day)`, {
|
||||
variant: 'warning',
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await bee.diluteBatch(stamp, parseInt(amount, 10))
|
||||
await bee.diluteBatch(stamp.batchID, newDepth)
|
||||
enqueueSnackbar(`Successfully diluted stamp, your changes will appear soon`, { variant: 'success' })
|
||||
} catch (error) {
|
||||
enqueueSnackbar(`Failed to dilute stamp: ${error || 'Unknown reason'}`, { variant: 'error' })
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
enqueueSnackbar(`Failed to extend stamp, unknown operation: ${type}`, { variant: 'error' })
|
||||
}
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement | HTMLInputElement>) => {
|
||||
@@ -57,7 +128,7 @@ export default function StampExtensionModal({ type, icon, bee, stamp }: Props):
|
||||
|
||||
return (
|
||||
<Box mb={2}>
|
||||
<Button variant="contained" onClick={handleClickOpen} startIcon={icon}>
|
||||
<Button className={classes.buttonSelected} variant="contained" onClick={handleClickOpen} startIcon={icon}>
|
||||
{type}
|
||||
</Button>
|
||||
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
|
||||
@@ -68,7 +139,7 @@ export default function StampExtensionModal({ type, icon, bee, stamp }: Props):
|
||||
margin="dense"
|
||||
id="name"
|
||||
type="text"
|
||||
placeholder={type === 'Topup' ? 'Amount to add' : 'New depth to dilute'}
|
||||
placeholder={type === StampExtensionType.Topup ? 'Amount to add' : 'New depth to dilute'}
|
||||
fullWidth
|
||||
value={amount}
|
||||
onChange={handleChange}
|
||||
@@ -78,7 +149,14 @@ export default function StampExtensionModal({ type, icon, bee, stamp }: Props):
|
||||
<Button onClick={handleClose} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button disabled={amount === ''} onClick={handleAction} color="primary">
|
||||
<Button
|
||||
disabled={amount === ''}
|
||||
onClick={async () => {
|
||||
await handleAction()
|
||||
handleClose()
|
||||
}}
|
||||
color="primary"
|
||||
>
|
||||
{type}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -75,6 +75,7 @@ export function SwarmSelect({
|
||||
value={value}
|
||||
className={classes.select}
|
||||
displayEmpty
|
||||
onChange={onChange}
|
||||
renderValue={(value: unknown) => (value ? renderValue(value) : placeholder)}
|
||||
MenuProps={{ MenuListProps: { disablePadding: true }, PaperProps: { square: true } }}
|
||||
>
|
||||
|
||||
@@ -57,7 +57,7 @@ export function SwarmTextInput({
|
||||
variant="filled"
|
||||
className={classes.field}
|
||||
defaultValue={defaultValue || ''}
|
||||
InputProps={{ disableUnderline: true }}
|
||||
slotProps={{ input: { disableUnderline: true } }}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
)
|
||||
@@ -73,7 +73,7 @@ export function SwarmTextInput({
|
||||
className={classes.field}
|
||||
defaultValue={defaultValue || ''}
|
||||
onChange={onChange}
|
||||
InputProps={{ disableUnderline: true }}
|
||||
slotProps={{ input: { disableUnderline: true } }}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
)
|
||||
|
||||
@@ -24,14 +24,14 @@ const useStyles = makeStyles()(theme => ({
|
||||
},
|
||||
},
|
||||
buttonSelected: {
|
||||
color: 'white',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: 'white',
|
||||
'&:hover': {
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: 'white',
|
||||
color: 'white',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
'@media (hover: none)': {
|
||||
color: 'white',
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: theme.palette.secondary.main,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user