register name dialog redesigned

This commit is contained in:
PhilReact 2025-03-01 22:38:19 +02:00
parent c772e8cebe
commit e02ac2d869
7 changed files with 570 additions and 152 deletions

View File

@ -149,6 +149,8 @@ import { useBlockedAddresses } from "./components/Group/useBlockUsers";
import { WalletIcon } from "./assets/Icons/WalletIcon"; import { WalletIcon } from "./assets/Icons/WalletIcon";
import { DrawerUserLookup } from "./components/Drawer/DrawerUserLookup"; import { DrawerUserLookup } from "./components/Drawer/DrawerUserLookup";
import { UserLookup } from "./components/UserLookup.tsx/UserLookup"; import { UserLookup } from "./components/UserLookup.tsx/UserLookup";
import { RegisterName } from "./components/RegisterName";
import { BuyQortInformation } from "./components/BuyQortInformation";
type extStates = type extStates =
| "not-authenticated" | "not-authenticated"
@ -361,6 +363,7 @@ function App() {
const [hasSettingsChanged, setHasSettingsChanged] = useRecoilState( const [hasSettingsChanged, setHasSettingsChanged] = useRecoilState(
hasSettingsChangedAtom hasSettingsChangedAtom
); );
const balanceSetIntervalRef = useRef(null)
const {downloadResource} = useFetchResources() const {downloadResource} = useFetchResources()
const holdRefExtState = useRef<extStates>("not-authenticated"); const holdRefExtState = useRef<extStates>("not-authenticated");
const isFocusedRef = useRef<boolean>(true); const isFocusedRef = useRef<boolean>(true);
@ -396,10 +399,7 @@ function App() {
message: messageQortalRequestExtension, message: messageQortalRequestExtension,
} = useModal(); } = useModal();
const [openRegisterName, setOpenRegisterName] = useState(false);
const registerNamePopoverRef = useRef(null);
const [isLoadingRegisterName, setIsLoadingRegisterName] = useState(false);
const [registerNameValue, setRegisterNameValue] = useState("");
const [infoSnack, setInfoSnack] = useState(null); const [infoSnack, setInfoSnack] = useState(null);
const [openSnack, setOpenSnack] = useState(false); const [openSnack, setOpenSnack] = useState(false);
const [hasLocalNode, setHasLocalNode] = useState(false); const [hasLocalNode, setHasLocalNode] = useState(false);
@ -702,6 +702,35 @@ function App() {
}; };
}; };
const balanceSetInterval = ()=> {
try {
if(balanceSetIntervalRef?.current){
clearInterval(balanceSetIntervalRef?.current);
}
let isCalling = false;
balanceSetIntervalRef.current = setInterval(async () => {
if (isCalling) return;
isCalling = true;
window
.sendMessage("balance")
.then((response) => {
if (!response?.error && !isNaN(+response)) {
setBalance(response);
}
isCalling = false;
})
.catch((error) => {
console.error("Failed to get balance:", error);
isCalling = false;
});
}, 40000);
} catch (error) {
console.error(error)
}
}
const getBalanceFunc = () => { const getBalanceFunc = () => {
setQortBalanceLoading(true); setQortBalanceLoading(true);
window window
@ -710,11 +739,14 @@ function App() {
if (!response?.error && !isNaN(+response)) { if (!response?.error && !isNaN(+response)) {
setBalance(response); setBalance(response);
} }
setQortBalanceLoading(false); setQortBalanceLoading(false);
}) })
.catch((error) => { .catch((error) => {
console.error("Failed to get balance:", error); console.error("Failed to get balance:", error);
setQortBalanceLoading(false); setQortBalanceLoading(false);
}).finally(()=> {
balanceSetInterval()
}); });
}; };
const getLtcBalanceFunc = () => { const getLtcBalanceFunc = () => {
@ -1121,6 +1153,9 @@ function App() {
setTxList([]); setTxList([]);
setMemberGroups([]); setMemberGroups([]);
resetAllRecoil(); resetAllRecoil();
if(balanceSetIntervalRef?.current){
clearInterval(balanceSetIntervalRef?.current);
}
}; };
function roundUpToDecimals(number, decimals = 8) { function roundUpToDecimals(number, decimals = 8) {
@ -1275,72 +1310,7 @@ function App() {
}; };
}, []); }, []);
const registerName = async () => {
try {
if (!userInfo?.address) throw new Error("Your address was not found");
if(!registerNameValue) throw new Error('Enter a name')
const fee = await getFee("REGISTER_NAME");
await show({
message: "Would you like to register this name?",
publishFee: fee.fee + " QORT",
});
setIsLoadingRegisterName(true);
new Promise((res, rej) => {
window
.sendMessage("registerName", {
name: registerNameValue,
})
.then((response) => {
if (!response?.error) {
res(response);
setIsLoadingRegisterName(false);
setInfoSnack({
type: "success",
message:
"Successfully registered. It may take a couple of minutes for the changes to propagate",
});
setOpenRegisterName(false);
setRegisterNameValue("");
setOpenSnack(true);
setTxList((prev) => [
{
...response,
type: "register-name",
label: `Registered name: awaiting confirmation. This may take a couple minutes.`,
labelDone: `Registered name: success!`,
done: false,
},
...prev.filter((item) => !item.done),
]);
return;
}
setInfoSnack({
type: "error",
message: response?.error,
});
setOpenSnack(true);
rej(response.error);
})
.catch((error) => {
setInfoSnack({
type: "error",
message: error.message || "An error occurred",
});
setOpenSnack(true);
rej(error);
});
});
} catch (error) {
if (error?.message) {
setInfoSnack({
type: "error",
message: error?.message,
});
}
} finally {
setIsLoadingRegisterName(false);
}
};
const renderProfileLeft = ()=> { const renderProfileLeft = ()=> {
@ -1527,7 +1497,6 @@ function App() {
<Spacer height="35px" /> <Spacer height="35px" />
{userInfo && !userInfo?.name && ( {userInfo && !userInfo?.name && (
<TextP <TextP
ref={registerNamePopoverRef}
sx={{ sx={{
textAlign: "center", textAlign: "center",
lineHeight: 1.2, lineHeight: 1.2,
@ -1539,7 +1508,7 @@ function App() {
textDecoration: "underline", textDecoration: "underline",
}} }}
onClick={() => { onClick={() => {
setOpenRegisterName(true); executeEvent('openRegisterName', {})
}} }}
> >
REGISTER NAME REGISTER NAME
@ -3616,52 +3585,6 @@ function App() {
</Box> </Box>
</Dialog> </Dialog>
)} )}
<Popover
open={openRegisterName}
anchorEl={registerNamePopoverRef.current}
onClose={() => {
setOpenRegisterName(false);
setRegisterNameValue("");
}}
anchorOrigin={{
vertical: "bottom",
horizontal: "center",
}}
transformOrigin={{
vertical: "top",
horizontal: "center",
}}
style={{ marginTop: "8px" }}
>
<Box
sx={{
width: "325px",
height: "250px",
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "10px",
padding: "10px",
}}
>
<Label>Choose a name</Label>
<Input
onChange={(e) => setRegisterNameValue(e.target.value)}
value={registerNameValue}
placeholder="Choose a name"
/>
<Spacer height="25px" />
<LoadingButton
loading={isLoadingRegisterName}
loadingPosition="start"
variant="contained"
disabled={!registerNameValue}
onClick={registerName}
>
Register Name
</LoadingButton>
</Box>
</Popover>
{isSettingsOpen && ( {isSettingsOpen && (
<Settings open={isSettingsOpen} setOpen={setIsSettingsOpen} /> <Settings open={isSettingsOpen} setOpen={setIsSettingsOpen} />
)} )}
@ -3678,6 +3601,8 @@ function App() {
{renderProfileLeft()} {renderProfileLeft()}
</DrawerComponent> </DrawerComponent>
<UserLookup isOpenDrawerLookup={isOpenDrawerLookup} setIsOpenDrawerLookup={setIsOpenDrawerLookup} /> <UserLookup isOpenDrawerLookup={isOpenDrawerLookup} setIsOpenDrawerLookup={setIsOpenDrawerLookup} />
<RegisterName balance={balance} show={show} setTxList={setTxList} userInfo={userInfo} setOpenSnack={setOpenSnack} setInfoSnack={setInfoSnack}/>
<BuyQortInformation balance={balance} />
</GlobalContext.Provider> </GlobalContext.Provider>
{extState === "create-wallet" && walletToBeDownloaded && ( {extState === "create-wallet" && walletToBeDownloaded && (
<ButtonBase onClick={()=> { <ButtonBase onClick={()=> {

View File

@ -0,0 +1,154 @@
import React, { useCallback, useContext, useEffect, useState } from 'react'
import {
Avatar,
Box,
Button,
ButtonBase,
Collapse,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Input,
ListItem,
ListItemAvatar,
ListItemButton,
ListItemIcon,
ListItemText,
List,
MenuItem,
Popover,
Select,
TextField,
Typography,
} from "@mui/material";
import { Label } from './Group/AddGroup';
import { Spacer } from '../common/Spacer';
import { LoadingButton } from '@mui/lab';
import { getBaseApiReact, MyContext } from '../App';
import { getFee } from '../background';
import qTradeLogo from "../assets/Icons/q-trade-logo.webp";
import RadioButtonCheckedIcon from '@mui/icons-material/RadioButtonChecked';
import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from '../utils/events';
import { BarSpinner } from '../common/Spinners/BarSpinner/BarSpinner';
export const BuyQortInformation = ({balance}) => {
const [isOpen, setIsOpen] = useState(false)
const openBuyQortInfoFunc = useCallback((e) => {
setIsOpen(true)
}, [ setIsOpen]);
useEffect(() => {
subscribeToEvent("openBuyQortInfo", openBuyQortInfoFunc);
return () => {
unsubscribeFromEvent("openBuyQortInfo", openBuyQortInfoFunc);
};
}, [openBuyQortInfoFunc]);
return (
<Dialog
open={isOpen}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{"Get QORT"}
</DialogTitle>
<DialogContent>
<Box
sx={{
width: "400px",
maxWidth: '90vw',
height: "400px",
maxHeight: '90vh',
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "10px",
padding: "10px",
}}
>
<Typography>Get QORT using Qortal's crosschain trade portal</Typography>
<ButtonBase
sx={{
"&:hover": { backgroundColor: "secondary.main" },
transition: "all 0.1s ease-in-out",
padding: "5px",
borderRadius: "5px",
gap: "5px",
}}
onClick={async () => {
executeEvent("addTab", {
data: { service: "APP", name: "q-trade" },
});
executeEvent("open-apps-mode", {});
setIsOpen(false)
}}
>
<img
style={{
borderRadius: "50%",
height: '30px'
}}
src={qTradeLogo}
/>
<Typography
sx={{
fontSize: "1rem",
}}
>
Trade QORT
</Typography>
</ButtonBase>
<Spacer height='40px' />
<Typography sx={{
textDecoration: 'underline'
}}>Benefits of having QORT</Typography>
<List
sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}
aria-label="contacts"
>
<ListItem disablePadding>
<ListItemIcon>
<RadioButtonCheckedIcon sx={{
color: 'white'
}} />
</ListItemIcon>
<ListItemText primary="Create transactions on the Qortal Blockchain" />
</ListItem>
<ListItem disablePadding>
<ListItemIcon>
<RadioButtonCheckedIcon sx={{
color: 'white'
}} />
</ListItemIcon>
<ListItemText primary="Having at least 4 QORT in your balance allows you to send chat messages at near instant speed." />
</ListItem>
</List>
</Box>
</DialogContent>
<DialogActions>
<Button
variant="contained"
onClick={() => {
setIsOpen(false)
}}
>
Close
</Button>
</DialogActions>
</Dialog>
)
}

View File

@ -2528,6 +2528,7 @@ export const Group = ({
<HomeDesktop <HomeDesktop
name={userInfo?.name}
refreshHomeDataFunc={refreshHomeDataFunc} refreshHomeDataFunc={refreshHomeDataFunc}
myAddress={myAddress} myAddress={myAddress}
isLoadingGroups={isLoadingGroups} isLoadingGroups={isLoadingGroups}

View File

@ -14,6 +14,7 @@ import { NewUsersCTA } from "../Home/NewUsersCTA";
export const HomeDesktop = ({ export const HomeDesktop = ({
refreshHomeDataFunc, refreshHomeDataFunc,
myAddress, myAddress,
name,
isLoadingGroups, isLoadingGroups,
balance, balance,
userInfo, userInfo,
@ -27,6 +28,31 @@ export const HomeDesktop = ({
setDesktopViewMode, setDesktopViewMode,
desktopViewMode, desktopViewMode,
}) => { }) => {
const [checked1, setChecked1] = React.useState(false);
const [checked2, setChecked2] = React.useState(false);
React.useEffect(() => {
if (balance && +balance >= 6) {
setChecked1(true);
}
}, [balance]);
React.useEffect(() => {
if (name) setChecked2(true);
}, [name]);
const isLoaded = React.useMemo(()=> {
if(userInfo !== null) return true
return false
}, [ userInfo])
const hasDoneNameAndBalanceAndIsLoaded = React.useMemo(()=> {
if(isLoaded && checked1 && checked2) return true
return false
}, [checked1, isLoaded, checked2])
return ( return (
<Box <Box
sx={{ sx={{
@ -114,7 +140,9 @@ export const HomeDesktop = ({
}}> }}>
<ListOfThreadPostsWatched /> <ListOfThreadPostsWatched />
</Box> */} </Box> */}
<Box {hasDoneNameAndBalanceAndIsLoaded && (
<>
<Box
sx={{ sx={{
width: "330px", width: "330px",
display: "flex", display: "flex",
@ -150,6 +178,9 @@ export const HomeDesktop = ({
</Box> </Box>
</> </>
)} )}
</>
)}
</Box> </Box>
<QortPrice /> <QortPrice />
</Box> </Box>
@ -185,6 +216,9 @@ export const HomeDesktop = ({
</Typography>{" "} </Typography>{" "}
</Box> </Box>
</Divider> </Divider>
{!hasDoneNameAndBalanceAndIsLoaded && (
<Spacer height="40px" />
)}
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -194,9 +228,14 @@ export const HomeDesktop = ({
justifyContent: "center", justifyContent: "center",
}} }}
> >
<ListOfGroupPromotions /> {hasDoneNameAndBalanceAndIsLoaded && (
<ListOfGroupPromotions />
)}
<Explore setDesktopViewMode={setDesktopViewMode} /> <Explore setDesktopViewMode={setDesktopViewMode} />
</Box> </Box>
<NewUsersCTA balance={balance} /> <NewUsersCTA balance={balance} />
</> </>

View File

@ -12,27 +12,17 @@ import { Box, Typography } from "@mui/material";
import { Spacer } from "../../common/Spacer"; import { Spacer } from "../../common/Spacer";
import { isMobile } from "../../App"; import { isMobile } from "../../App";
import { QMailMessages } from "./QMailMessages"; import { QMailMessages } from "./QMailMessages";
import { executeEvent } from "../../utils/events";
export const ThingsToDoInitial = ({ myAddress, name, hasGroups, balance, userInfo }) => { export const ThingsToDoInitial = ({ myAddress, name, hasGroups, balance, userInfo }) => {
const [checked1, setChecked1] = React.useState(false); const [checked1, setChecked1] = React.useState(false);
const [checked2, setChecked2] = React.useState(false); const [checked2, setChecked2] = React.useState(false);
const [checked3, setChecked3] = React.useState(false); // const [checked3, setChecked3] = React.useState(false);
// const getAddressInfo = async (address) => { // React.useEffect(() => {
// const response = await fetch(getBaseApiReact() + "/addresses/" + address); // if (hasGroups) setChecked3(true);
// const data = await response.json(); // }, [hasGroups]);
// if (data.error && data.error === 124) {
// setChecked1(false);
// } else if (data.address) {
// setChecked1(true);
// }
// };
// const checkInfo = async () => {
// try {
// getAddressInfo(myAddress);
// } catch (error) {}
// };
React.useEffect(() => { React.useEffect(() => {
if (balance && +balance >= 6) { if (balance && +balance >= 6) {
@ -40,9 +30,6 @@ export const ThingsToDoInitial = ({ myAddress, name, hasGroups, balance, userInf
} }
}, [balance]); }, [balance]);
React.useEffect(() => {
if (hasGroups) setChecked3(true);
}, [hasGroups]);
React.useEffect(() => { React.useEffect(() => {
if (name) setChecked2(true); if (name) setChecked2(true);
@ -120,11 +107,14 @@ if(!isLoaded) return null
disableRipple disableRipple
role={undefined} role={undefined}
dense dense
onClick={()=> {
executeEvent("openBuyQortInfo", {})
}}
> >
<ListItemText <ListItemText
sx={{ sx={{
"& .MuiTypography-root": { "& .MuiTypography-root": {
fontSize: "13px", fontSize: "1rem",
fontWeight: 400, fontWeight: 400,
}, },
}} }}
@ -181,9 +171,11 @@ if(!isLoaded) return null
padding: "0px", padding: "0px",
}} disableRipple role={undefined} dense> }} disableRipple role={undefined} dense>
<ListItemText sx={{ <ListItemText onClick={() => {
executeEvent('openRegisterName', {})
}} sx={{
"& .MuiTypography-root": { "& .MuiTypography-root": {
fontSize: "13px", fontSize: "1rem",
fontWeight: 400, fontWeight: 400,
}, },
}} primary={`Register a name`} /> }} primary={`Register a name`} />
@ -202,16 +194,7 @@ if(!isLoaded) return null
</ListItemIcon> </ListItemIcon>
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
<ListItem {/* <ListItem
// secondaryAction={
// <IconButton edge="end" aria-label="comments">
// <InfoIcon
// sx={{
// color: "white",
// }}
// />
// </IconButton>
// }
disablePadding disablePadding
> >
<ListItemButton sx={{ <ListItemButton sx={{
@ -238,7 +221,7 @@ if(!isLoaded) return null
/> />
</ListItemIcon> </ListItemIcon>
</ListItemButton> </ListItemButton>
</ListItem> </ListItem> */}
</List> </List>
)} )}

View File

@ -0,0 +1,312 @@
import React, { useCallback, useContext, useEffect, useState } from 'react'
import {
Avatar,
Box,
Button,
ButtonBase,
Collapse,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Input,
ListItem,
ListItemAvatar,
ListItemButton,
ListItemIcon,
ListItemText,
List,
MenuItem,
Popover,
Select,
TextField,
Typography,
} from "@mui/material";
import { Label } from './Group/AddGroup';
import { Spacer } from '../common/Spacer';
import { LoadingButton } from '@mui/lab';
import { getBaseApiReact, MyContext } from '../App';
import { getFee } from '../background';
import RadioButtonCheckedIcon from '@mui/icons-material/RadioButtonChecked';
import { subscribeToEvent, unsubscribeFromEvent } from '../utils/events';
import { BarSpinner } from '../common/Spinners/BarSpinner/BarSpinner';
import CheckIcon from '@mui/icons-material/Check';
import ErrorIcon from '@mui/icons-material/Error';
enum Availability {
NULL = 'null',
LOADING = 'loading',
AVAILABLE = 'available',
NOT_AVAILABLE = 'not-available'
}
export const RegisterName = ({setOpenSnack, setInfoSnack, userInfo, show, setTxList, balance}) => {
const [isOpen, setIsOpen] = useState(false)
const [registerNameValue, setRegisterNameValue] = useState('')
const [isLoadingRegisterName, setIsLoadingRegisterName] = useState(false)
const [isNameAvailable, setIsNameAvailable] = useState<Availability>(Availability.NULL)
const [nameFee, setNameFee] = useState(null)
const checkIfNameExisits = async (name)=> {
if(!name?.trim()){
setIsNameAvailable(Availability.NULL)
return
}
setIsNameAvailable(Availability.LOADING)
try {
const res = await fetch(`${getBaseApiReact()}/names/` + name);
const data = await res.json()
if(data?.message === 'name unknown'){
setIsNameAvailable(Availability.AVAILABLE)
} else {
setIsNameAvailable(Availability.NOT_AVAILABLE)
}
} catch (error) {
console.error(error)
} finally {
}
}
// Debounce logic
useEffect(() => {
const handler = setTimeout(() => {
checkIfNameExisits(registerNameValue);
}, 500);
// Cleanup timeout if searchValue changes before the timeout completes
return () => {
clearTimeout(handler);
};
}, [registerNameValue]);
const openRegisterNameFunc = useCallback((e) => {
setIsOpen(true)
}, [ setIsOpen]);
useEffect(() => {
subscribeToEvent("openRegisterName", openRegisterNameFunc);
return () => {
unsubscribeFromEvent("openRegisterName", openRegisterNameFunc);
};
}, [openRegisterNameFunc]);
useEffect(()=> {
const nameRegistrationFee = async ()=> {
try {
const fee = await getFee("REGISTER_NAME");
setNameFee(fee?.fee)
} catch (error) {
console.error(error)
}
}
nameRegistrationFee()
}, [])
const registerName = async () => {
try {
if (!userInfo?.address) throw new Error("Your address was not found");
if(!registerNameValue) throw new Error('Enter a name')
const fee = await getFee("REGISTER_NAME");
await show({
message: "Would you like to register this name?",
publishFee: fee.fee + " QORT",
});
setIsLoadingRegisterName(true);
new Promise((res, rej) => {
window
.sendMessage("registerName", {
name: registerNameValue,
})
.then((response) => {
if (!response?.error) {
res(response);
setIsLoadingRegisterName(false);
setInfoSnack({
type: "success",
message:
"Successfully registered. It may take a couple of minutes for the changes to propagate",
});
setIsOpen(false);
setRegisterNameValue("");
setOpenSnack(true);
setTxList((prev) => [
{
...response,
type: "register-name",
label: `Registered name: awaiting confirmation. This may take a couple minutes.`,
labelDone: `Registered name: success!`,
done: false,
},
...prev.filter((item) => !item.done),
]);
return;
}
setInfoSnack({
type: "error",
message: response?.error,
});
setOpenSnack(true);
rej(response.error);
})
.catch((error) => {
setInfoSnack({
type: "error",
message: error.message || "An error occurred",
});
setOpenSnack(true);
rej(error);
});
});
} catch (error) {
if (error?.message) {
setOpenSnack(true)
setInfoSnack({
type: "error",
message: error?.message,
});
}
} finally {
setIsLoadingRegisterName(false);
}
};
return (
<Dialog
open={isOpen}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{"Register name"}
</DialogTitle>
<DialogContent>
<Box
sx={{
width: "400px",
maxWidth: '90vw',
height: "500px",
maxHeight: '90vh',
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "10px",
padding: "10px",
}}
>
<Label>Choose a name</Label>
<TextField
autoComplete='off'
autoFocus
onChange={(e) => setRegisterNameValue(e.target.value)}
value={registerNameValue}
placeholder="Choose a name"
/>
{(!balance || (nameFee && balance && balance < nameFee))&& (
<>
<Spacer height="10px" />
<Box sx={{
display: 'flex',
gap: '5px',
alignItems: 'center'
}}>
<ErrorIcon sx={{
color: 'white'
}} />
<Typography>Your balance is {balance ?? 0} QORT. A name registration requires a {nameFee} QORT fee</Typography>
</Box>
<Spacer height="10px" />
</>
)}
<Spacer height="5px" />
{isNameAvailable === Availability.AVAILABLE && (
<Box sx={{
display: 'flex',
gap: '5px',
alignItems: 'center'
}}>
<CheckIcon sx={{
color: 'white'
}} />
<Typography>{registerNameValue} is available</Typography>
</Box>
)}
{isNameAvailable === Availability.NOT_AVAILABLE && (
<Box sx={{
display: 'flex',
gap: '5px',
alignItems: 'center'
}}>
<ErrorIcon sx={{
color: 'white'
}} />
<Typography>{registerNameValue} is unavailable</Typography>
</Box>
)}
{isNameAvailable === Availability.LOADING && (
<Box sx={{
display: 'flex',
gap: '5px',
alignItems: 'center'
}}>
<BarSpinner width="16px" color="white" />
<Typography>Checking if name already existis</Typography>
</Box>
)}
<Spacer height="25px" />
<Typography sx={{
textDecoration: 'underline'
}}>Benefits of a name</Typography>
<List
sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}
aria-label="contacts"
>
<ListItem disablePadding>
<ListItemIcon>
<RadioButtonCheckedIcon sx={{
color: 'white'
}} />
</ListItemIcon>
<ListItemText primary="Publish data to Qortal: anything from apps to videos. Fully decentralized!" />
</ListItem>
<ListItem disablePadding>
<ListItemIcon>
<RadioButtonCheckedIcon sx={{
color: 'white'
}} />
</ListItemIcon>
<ListItemText primary="Secure ownership of data published by your name. You can even sell your name, along with your data to a third party." />
</ListItem>
</List>
</Box>
</DialogContent>
<DialogActions>
<Button
disabled={isLoadingRegisterName}
variant="contained"
onClick={() => {
setIsOpen(false)
setRegisterNameValue('')
}}
>
Close
</Button>
<Button
disabled={!registerNameValue.trim() ||isLoadingRegisterName || isNameAvailable !== Availability.AVAILABLE || !balance || ((balance && nameFee) && +balance < +nameFee)}
variant="contained"
onClick={registerName}
autoFocus
>
Register Name
</Button>
</DialogActions>
</Dialog>
)
}

View File

@ -24,6 +24,10 @@ const theme = createTheme({
secondary: '#b0b0b0', // Light gray for secondary text secondary: '#b0b0b0', // Light gray for secondary text
disabled: '#808080', // Gray for disabled text disabled: '#808080', // Gray for disabled text
}, },
action: {
// disabledBackground: 'set color of background here',
disabled: 'rgb(255 255 255 / 70%)'
}
}, },
typography: { typography: {
fontFamily: '"Inter", "Roboto", "Helvetica", "Arial", sans-serif', // Font family fontFamily: '"Inter", "Roboto", "Helvetica", "Arial", sans-serif', // Font family