diff --git a/src/App-styles.ts b/src/App-styles.ts index a5f387e..25cafd2 100644 --- a/src/App-styles.ts +++ b/src/App-styles.ts @@ -1,9 +1,4 @@ -import { - Typography, - Box, - TextField, - InputLabel, -} from "@mui/material"; +import { Typography, Box, TextField, InputLabel } from "@mui/material"; import { styled } from "@mui/system"; export const AppContainer = styled(Box)(({ theme }) => ({ @@ -11,9 +6,9 @@ export const AppContainer = styled(Box)(({ theme }) => ({ alignItems: "center", flexDirection: "column", width: "100vw", + background: "rgba(39, 40, 44, 1)", height: "100vh", radius: "15px", - overflow: 'hidden', backgroundColor: theme.palette.background.default, color: theme.palette.text.primary, })); @@ -85,44 +80,70 @@ export const TextSpan = styled("span")(({ theme }) => ({ color: theme.palette.text.primary, })); -export const AddressBox = styled(Box)` - display: flex; - border: 1px solid var(--50-white, rgba(255, 255, 255, 0.5)); - justify-content: space-between; - align-items: center; - width: auto; - height: 25px; - padding: 5px 15px 5px 15px; - gap: 5px; - border-radius: 100px; - font-family: Inter; - font-size: 12px; - font-weight: 600; - line-height: 14.52px; - text-align: left; - color: var(--50-white, rgba(255, 255, 255, 0.5)); - cursor: pointer; - transition: all 0.2s; - &:hover { - background-color: rgba(41, 41, 43, 1); - color: white; - svg path { - fill: white; // Fill color changes to white on hover - } - } -`; +export const AddressBox = styled(Box)(({ theme }) => ({ + display: "flex", + border: `1px solid ${ + theme.palette.mode === "dark" + ? "rgba(255, 255, 255, 0.5)" + : "rgba(0, 0, 0, 0.3)" + }`, + justifyContent: "space-between", + alignItems: "center", + width: "auto", + height: "25px", + padding: "5px 15px", + gap: "5px", + borderRadius: "100px", + fontFamily: "Inter", + fontSize: "12px", + fontWeight: 600, + lineHeight: "14.52px", + textAlign: "left", + backgroundColor: theme.palette.background.default, + color: theme.palette.text.primary, + cursor: "pointer", + transition: "all 0.2s", -export const CustomButton = styled(Box)` - /* Authenticate */ + "&:hover": { + backgroundColor: + theme.palette.mode === "dark" + ? "rgba(41, 41, 43, 1)" + : "rgba(240, 240, 240, 1)", + color: theme.palette.mode === "dark" ? "#fff" : "#000", - box-sizing: border-box; + "svg path": { + fill: theme.palette.mode === "dark" ? "#fff" : "#000", + }, + }, +})); - padding: 15px 20px; - gap: 10px; +export const CustomButton = styled(Box)(({ theme }) => ({ + boxSizing: "border-box", + padding: "15px 20px", + gap: "10px", - border: 0.5px solid rgba(255, 255, 255, 0.5); - filter: drop-shadow(1px 4px 10.5px rgba(0, 0, 0, 0.3)); - border-radius: 5px; + border: `0.5px solid ${ + theme.palette.mode === "dark" + ? "rgba(255, 255, 255, 0.5)" + : "rgba(0, 0, 0, 0.3)" + }`, + filter: "drop-shadow(1px 4px 10.5px rgba(0, 0, 0, 0.3))", + borderRadius: "5px", + + display: "inline-flex", + justifyContent: "center", + alignItems: "center", + + width: "fit-content", + minWidth: "160px", + cursor: "pointer", + transition: "all 0.2s", + + fontWeight: 600, + fontFamily: "Inter", + textAlign: "center", + backgroundColor: theme.palette.background.default, + color: theme.palette.text.primary, "&:hover": { backgroundColor: @@ -172,30 +193,18 @@ export const CustomButtonAccept = styled(Box)( "&:hover": { opacity: 1, -<<<<<<< HEAD backgroundColor: bgColor || (theme.palette.mode === "dark" ? "rgba(41, 41, 43, 1)" : "rgba(230, 230, 230, 1)"), color: color || "#fff", svg: { path: { fill: color || "#fff", -======= - backgroundColor: bgColor ? bgColor : "rgba(41, 41, 43, 1)", // fallback hover bg - color: color || "white", - svg: { - path: { - fill: color || "white", ->>>>>>> ffb39b3 (Bind color and background to selected theme) }, }, }, }) ); -<<<<<<< HEAD export const CustomInput = styled(TextField)(({ theme }) => ({ -======= -export const CustomInput = styled(TextField)({ ->>>>>>> ffb39b3 (Bind color and background to selected theme) width: "183px", // Adjust the width as needed borderRadius: "5px", // backgroundColor: "rgba(30, 30, 32, 1)", @@ -236,7 +245,6 @@ export const CustomInput = styled(TextField)({ }, })); -<<<<<<< HEAD export const CustomLabel = styled(InputLabel)(({ theme }) => ({ fontWeight: 400, fontFamily: "Inter", @@ -246,14 +254,4 @@ export const CustomLabel = styled(InputLabel)(({ theme }) => ({ theme.palette.mode === "dark" ? "rgba(255, 255, 255, 0.5)" : "rgba(0, 0, 0, 0.5)", -})); - -======= -export const CustomLabel = styled(InputLabel)` - font-weight: 400; - font-family: Inter; - font-size: 10px; - line-height: 12px; - color: rgba(255, 255, 255, 0.5); -`; ->>>>>>> ffb39b3 (Bind color and background to selected theme) +})); \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 071ca7a..a5dd940 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -18,25 +18,32 @@ import { DialogContent, DialogContentText, DialogTitle, + FormControlLabel, + Input, + InputLabel, + Popover, Tooltip, Typography, } from "@mui/material"; -import { JsonView, allExpanded, darkStyles } from "react-json-view-lite"; -import "react-json-view-lite/dist/index.css"; +import { JsonView, allExpanded, darkStyles } from 'react-json-view-lite'; +import 'react-json-view-lite/dist/index.css'; import { decryptStoredWallet } from "./utils/decryptWallet"; import { CountdownCircleTimer } from "react-countdown-circle-timer"; +import Logo1 from "./assets/svgs/Logo1.svg"; import Logo1Dark from "./assets/svgs/Logo1Dark.svg"; import RefreshIcon from "@mui/icons-material/Refresh"; +import Logo2 from "./assets/svgs/Logo2.svg"; import Copy from "./assets/svgs/Copy.svg"; import ltcLogo from "./assets/ltc.png"; -import PersonSearchIcon from "@mui/icons-material/PersonSearch"; +import PersonSearchIcon from '@mui/icons-material/PersonSearch'; import qortLogo from "./assets/qort.png"; import { CopyToClipboard } from "react-copy-to-clipboard"; import Download from "./assets/svgs/Download.svg"; import Logout from "./assets/svgs/Logout.svg"; import Return from "./assets/svgs/Return.svg"; -import WarningIcon from "@mui/icons-material/Warning"; +import WarningIcon from '@mui/icons-material/Warning'; import Success from "./assets/svgs/Success.svg"; +import Info from "./assets/svgs/Info.svg"; import CloseIcon from "@mui/icons-material/Close"; import './utils/seedPhrase/RandomSentenceGenerator'; import EngineeringIcon from '@mui/icons-material/Engineering'; @@ -44,9 +51,12 @@ import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; import PriorityHighIcon from '@mui/icons-material/PriorityHigh'; import { createAccount, + generateRandomSentence, saveFileToDisk, saveSeedPhraseToDisk, } from "./utils/generateWallet/generateWallet"; +import { kdf } from "./deps/kdf"; +import { generateSaveWalletData } from "./utils/generateWallet/storeWallet"; import { crypto, walletVersion } from "./constants/decryptWallet"; import PhraseWallet from "./utils/generateWallet/phrase-wallet"; import { @@ -57,6 +67,7 @@ import { AuthenticatedContainerInnerRight, CustomButton, CustomButtonAccept, + CustomInput, CustomLabel, TextItalic, TextP, @@ -65,19 +76,25 @@ import { import { Spacer } from "./common/Spacer"; import { Loader } from "./components/Loader"; import { PasswordField, ErrorText } from "./components"; +import { ChatGroup } from "./components/Chat/ChatGroup"; import { Group, requestQueueMemberNames } from "./components/Group/Group"; import { TaskManager } from "./components/TaskManager/TaskManger"; import { useModal } from "./common/useModal"; +import { LoadingButton } from "@mui/lab"; +import { Label } from "./components/Group/AddGroup"; import { CustomizedSnackbars } from "./components/Snackbar/Snackbar"; import SettingsIcon from "@mui/icons-material/Settings"; -import HelpIcon from "@mui/icons-material/Help"; +import HelpIcon from '@mui/icons-material/Help'; import { cleanUrl, + getFee, getProtocol, getWallets, groupApi, + groupApiLocal, groupApiSocket, + groupApiSocketLocal, storeWallets, } from "./background"; import { @@ -115,12 +132,19 @@ import { } from "./atoms/global"; import { useAppFullScreen } from "./useAppFullscreen"; import { NotAuthenticated } from "./ExtStates/NotAuthenticated"; +import { + openIndexedDB, + showSaveFilePicker, +} from "./components/Apps/useQortalMessageListener"; +import { fileToBase64 } from "./utils/fileReading"; import { handleGetFileFromIndexedDB } from "./utils/indexedDB"; import { CoreSyncStatus } from "./components/CoreSyncStatus"; import { Wallets } from "./Wallets"; +import { RandomSentenceGenerator } from "./utils/seedPhrase/RandomSentenceGenerator"; import { useFetchResources } from "./common/useFetchResources"; import { Tutorials } from "./components/Tutorials/Tutorials"; import { useHandleTutorials } from "./components/Tutorials/useHandleTutorials"; +import BoundedNumericTextField from "./common/BoundedNumericTextField"; import { useHandleUserInfo } from "./components/Group/useHandleUserInfo"; import { Minting } from "./components/Minting/Minting"; import { isRunningGateway } from "./qortalRequests"; @@ -128,14 +152,13 @@ import { QMailStatus } from "./components/QMailStatus"; import { GlobalActions } from "./components/GlobalActions/GlobalActions"; import { useBlockedAddresses } from "./components/Group/useBlockUsers"; import { WalletIcon } from "./assets/Icons/WalletIcon"; +import { DrawerUserLookup } from "./components/Drawer/DrawerUserLookup"; import { UserLookup } from "./components/UserLookup.tsx/UserLookup"; import { RegisterName } from "./components/RegisterName"; import { BuyQortInformation } from "./components/BuyQortInformation"; import { QortPayment } from "./components/QortPayment"; import { GeneralNotifications } from "./components/GeneralNotifications"; -import ThemeSelector from "./components/Theme/ThemeSelector"; import { PdfViewer } from "./common/PdfViewer"; -import ThemeSelector from "./components/Theme/ThemeSelector"; type extStates = | "not-authenticated" @@ -223,6 +246,7 @@ const controlAllQueues = (action) => { }); }; + export const clearAllQueues = () => { Object.keys(allQueues).forEach((key) => { const val = allQueues[key]; @@ -253,13 +277,13 @@ export const resumeAllQueues = () => { }); }; + const defaultValuesGlobal = { openTutorialModal: null, - setOpenTutorialModal: () => {}, -}; + setOpenTutorialModal: ()=> {} +} export const MyContext = createContext(defaultValues); -export const GlobalContext = - createContext(defaultValuesGlobal); +export const GlobalContext = createContext(defaultValuesGlobal); export let globalApiKey: string | null = null; @@ -349,17 +373,11 @@ function App() { const [hasSettingsChanged, setHasSettingsChanged] = useRecoilState( hasSettingsChangedAtom ); - const balanceSetIntervalRef = useRef(null); - const { downloadResource } = useFetchResources(); + const balanceSetIntervalRef = useRef(null) + const {downloadResource} = useFetchResources() const holdRefExtState = useRef("not-authenticated"); const isFocusedRef = useRef(true); - const { - showTutorial, - openTutorialModal, - shownTutorialsInitiated, - setOpenTutorialModal, - hasSeenGettingStarted, - } = useHandleTutorials(); + const {showTutorial, openTutorialModal, shownTutorialsInitiated, setOpenTutorialModal, hasSeenGettingStarted} = useHandleTutorials() const { isShow, onCancel, onOk, show, message } = useModal(); const { isShow: isShowUnsavedChanges, @@ -375,7 +393,7 @@ function App() { show: showInfo, message: messageInfo, } = useModal(); - + const { onCancel: onCancelQortalRequest, onOk: onOkQortalRequest, @@ -391,19 +409,18 @@ function App() { message: messageQortalRequestExtension, } = useModal(); - const [isRunningPublicNode, setIsRunningPublicNode] = useState(false); + const [isRunningPublicNode, setIsRunningPublicNode] = useState(false) const [infoSnack, setInfoSnack] = useState(null); const [openSnack, setOpenSnack] = useState(false); const [hasLocalNode, setHasLocalNode] = useState(false); const [isOpenDrawerProfile, setIsOpenDrawerProfile] = useState(false); - const [isOpenDrawerLookup, setIsOpenDrawerLookup] = useState(false); + const [isOpenDrawerLookup, setIsOpenDrawerLookup] = useState(false) const [apiKey, setApiKey] = useState(""); const [isOpenSendQort, setIsOpenSendQort] = useState(false); const [isOpenSendQortSuccess, setIsOpenSendQortSuccess] = useState(false); const [rootHeight, setRootHeight] = useState("100%"); - const { - isUserBlocked, + const {isUserBlocked, addToBlockList, removeBlockFromList, getAllBlockedUsers} = useBlockedAddresses() const [currentNode, setCurrentNode] = useState({ @@ -413,23 +430,23 @@ function App() { const [confirmRequestRead, setConfirmRequestRead] = useState(false); const [isSettingsOpen, setIsSettingsOpen] = useState(false); - const [showSeed, setShowSeed] = useState(false); - const [creationStep, setCreationStep] = useState(1); - const { getIndividualUserInfo } = useHandleUserInfo(); + const [showSeed, setShowSeed] = useState(false) + const [creationStep, setCreationStep] = useState(1) + const {getIndividualUserInfo} = useHandleUserInfo() const qortalRequestCheckbox1Ref = useRef(null); useRetrieveDataLocalStorage(userInfo?.address); useQortalGetSaveSettings(userInfo?.name, extState === "authenticated"); const [fullScreen, setFullScreen] = useRecoilState(fullScreenAtom); const [isEnabledDevMode, setIsEnabledDevMode] = useRecoilState(enabledDevModeAtom); - const setIsDisabledEditorEnter = useSetRecoilState(isDisabledEditorEnterAtom); - const [isOpenMinting, setIsOpenMinting] = useState(false); + const setIsDisabledEditorEnter = useSetRecoilState(isDisabledEditorEnterAtom) + const [isOpenMinting, setIsOpenMinting] = useState(false) const { toggleFullScreen } = useAppFullScreen(setFullScreen); - const generatorRef = useRef(null); - const exportSeedphrase = () => { - const seedPhrase = generatorRef.current.parsedString; - saveSeedPhraseToDisk(seedPhrase); - }; + const generatorRef = useRef(null) + const exportSeedphrase = ()=> { + const seedPhrase = generatorRef.current.parsedString + saveSeedPhraseToDisk(seedPhrase) + } const passwordRef = useRef(null); useEffect(() => { if (extState === "wallet-dropped" && passwordRef.current) { @@ -443,26 +460,24 @@ function App() { } }, []); - useEffect(() => { - isRunningGateway() - .then((res) => { - setIsRunningPublicNode(res); + useEffect(()=> { + isRunningGateway().then((res)=> { + setIsRunningPublicNode(res) + }).catch((error)=> { + console.error(error) }) - .catch((error) => { - console.error(error); - }); - }, [extState]); + }, [extState]) - useEffect(() => { - if (!shownTutorialsInitiated) return; - if (extState === "not-authenticated") { - showTutorial("create-account"); - } else if (extState === "create-wallet" && walletToBeDownloaded) { - showTutorial("important-information"); - } else if (extState === "authenticated") { - showTutorial("getting-started"); + useEffect(()=> { + if(!shownTutorialsInitiated) return + if(extState === 'not-authenticated'){ + showTutorial('create-account') + } else if(extState === "create-wallet" && walletToBeDownloaded){ + showTutorial('important-information') + } else if(extState === "authenticated"){ + showTutorial('getting-started') } - }, [extState, walletToBeDownloaded, shownTutorialsInitiated]); + }, [extState, walletToBeDownloaded, shownTutorialsInitiated]) useEffect(() => { // Attach a global event listener for double-click @@ -485,9 +500,7 @@ function App() { const resetAtomSortablePinnedAppsAtom = useResetRecoilState( sortablePinnedAppsAtom ); - const resetAtomIsUsingImportExportSettingsAtom = useResetRecoilState( - isUsingImportExportSettingsAtom - ); + const resetAtomIsUsingImportExportSettingsAtom = useResetRecoilState(isUsingImportExportSettingsAtom) const resetAtomCanSaveSettingToQdnAtom = useResetRecoilState( canSaveSettingToQdnAtom ); @@ -498,25 +511,22 @@ function App() { settingsLocalLastUpdatedAtom ); const resetAtomOldPinnedAppsAtom = useResetRecoilState(oldPinnedAppsAtom); - const resetAtomQMailLastEnteredTimestampAtom = useResetRecoilState( - qMailLastEnteredTimestampAtom - ); - const resetAtomMailsAtom = useResetRecoilState(mailsAtom); - const resetGroupPropertiesAtom = useResetRecoilState(groupsPropertiesAtom); - const resetLastPaymentSeenTimestampAtom = useResetRecoilState( - lastPaymentSeenTimestampAtom - ); + const resetAtomQMailLastEnteredTimestampAtom = useResetRecoilState(qMailLastEnteredTimestampAtom) + const resetAtomMailsAtom = useResetRecoilState(mailsAtom) + const resetGroupPropertiesAtom = useResetRecoilState(groupsPropertiesAtom) + const resetLastPaymentSeenTimestampAtom = useResetRecoilState(lastPaymentSeenTimestampAtom) const resetAllRecoil = () => { resetAtomSortablePinnedAppsAtom(); resetAtomCanSaveSettingToQdnAtom(); resetAtomSettingsQDNLastUpdatedAtom(); resetAtomSettingsLocalLastUpdatedAtom(); resetAtomOldPinnedAppsAtom(); - resetAtomIsUsingImportExportSettingsAtom(); - resetAtomQMailLastEnteredTimestampAtom(); - resetAtomMailsAtom(); - resetGroupPropertiesAtom(); - resetLastPaymentSeenTimestampAtom(); + resetAtomIsUsingImportExportSettingsAtom() + resetAtomQMailLastEnteredTimestampAtom() + resetAtomMailsAtom() + resetGroupPropertiesAtom() + resetLastPaymentSeenTimestampAtom() + }; useEffect(() => { if (!isMobile) return; @@ -550,46 +560,48 @@ function App() { try { setIsLoading(true); window - .sendMessage("getApiKey") + .sendMessage("getApiKey") + .then((response) => { + if (response) { + handleSetGlobalApikey(response); + setApiKey(response); + } + }) + .catch((error) => { + console.error( + "Failed to get API key:", + error?.message || "An error occurred" + ); + }).finally(()=> { + window + .sendMessage("getWalletInfo") .then((response) => { - if (response) { - handleSetGlobalApikey(response); - setApiKey(response); + if (response && response?.walletInfo) { + setRawWallet(response?.walletInfo); + if ( + holdRefExtState.current === "web-app-request-payment" || + holdRefExtState.current === "web-app-request-connection" || + holdRefExtState.current === "web-app-request-buy-order" + ) + return; + if (response?.hasKeyPair) { + setExtstate("authenticated"); + } else { + setExtstate("wallet-dropped"); + } } }) .catch((error) => { - console.error( - "Failed to get API key:", - error?.message || "An error occurred" - ); - }) - .finally(() => { - window - .sendMessage("getWalletInfo") - .then((response) => { - if (response && response?.walletInfo) { - setRawWallet(response?.walletInfo); - if ( - holdRefExtState.current === "web-app-request-payment" || - holdRefExtState.current === "web-app-request-connection" || - holdRefExtState.current === "web-app-request-buy-order" - ) - return; - if (response?.hasKeyPair) { - setExtstate("authenticated"); - } else { - setExtstate("wallet-dropped"); - } - } - }) - .catch((error) => { - console.error("Failed to get wallet info:", error); - }); + console.error("Failed to get wallet info:", error); }); + }) } catch (error) { + } finally { setIsLoading(false); + } + }, []); useEffect(() => { if (extState) { @@ -597,17 +609,19 @@ function App() { } }, [extState]); - useEffect(() => { + useEffect(()=> { try { - const val = localStorage.getItem("settings-disable-editor-enter"); - if (val) { - const parsedVal = JSON.parse(val); - if (parsedVal === false || parsedVal === true) { - setIsDisabledEditorEnter(parsedVal); + const val = localStorage.getItem('settings-disable-editor-enter'); + if(val){ + const parsedVal = JSON.parse(val) + if(parsedVal === false || parsedVal === true){ + setIsDisabledEditorEnter(parsedVal) } } - } catch (error) {} - }, []); + } catch (error) { + + } + }, []) useEffect(() => { isFocusedRef.current = isFocused; @@ -710,33 +724,34 @@ function App() { }; }; - const balanceSetInterval = () => { + + const balanceSetInterval = ()=> { try { - if (balanceSetIntervalRef?.current) { + if(balanceSetIntervalRef?.current){ clearInterval(balanceSetIntervalRef?.current); } let isCalling = false; - balanceSetIntervalRef.current = setInterval(async () => { + 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; - }); + .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); + console.error(error) } - }; + } const getBalanceFunc = () => { setQortBalanceLoading(true); @@ -746,15 +761,14 @@ function App() { if (!response?.error && !isNaN(+response)) { setBalance(response); } - + setQortBalanceLoading(false); }) .catch((error) => { console.error("Failed to get balance:", error); setQortBalanceLoading(false); - }) - .finally(() => { - balanceSetInterval(); + }).finally(()=> { + balanceSetInterval() }); }; const getLtcBalanceFunc = () => { @@ -772,6 +786,7 @@ function App() { setLtcBalanceLoading(false); }); }; + const clearAllStates = () => { setRequestConnection(null); @@ -891,6 +906,7 @@ function App() { // REMOVED FOR MOBILE APP }; + const getUserInfo = useCallback(async (useTimer?: boolean) => { try { if (useTimer) { @@ -969,26 +985,25 @@ function App() { } }; - const saveWalletToLocalStorage = async (newWallet) => { + const saveWalletToLocalStorage = async (newWallet)=> { try { - getWallets() - .then((res) => { - if (res && Array.isArray(res)) { - const wallets = [...res, newWallet]; - storeWallets(wallets); - } else { - storeWallets([newWallet]); - } - setIsLoading(false); - }) - .catch((error) => { - console.error(error); - setIsLoading(false); - }); + getWallets().then((res)=> { + + if(res && Array.isArray(res)){ + const wallets = [...res, newWallet] + storeWallets(wallets) + } else { + storeWallets([newWallet]) + } + setIsLoading(false) + }).catch((error)=> { + console.error(error) + setIsLoading(false) + }) } catch (error) { - console.error(error); + console.error(error) } - }; + } const createAccountFunc = async () => { try { @@ -1026,7 +1041,7 @@ function App() { .then((response) => { if (response && !response.error) { setRawWallet(wallet); - saveWalletToLocalStorage(wallet); + saveWalletToLocalStorage(wallet) setWalletToBeDownloaded({ wallet, qortAddress: wallet.address0, @@ -1068,9 +1083,10 @@ function App() { message: "Your settings have changed. If you logout you will lose your changes. Click on the save button in the header to keep your changed settings.", }); - } else if (extState === "authenticated") { + } else if(extState === 'authenticated') { await showUnsavedChanges({ - message: "Are you sure you would like to logout?", + message: + "Are you sure you would like to logout?", }); } window @@ -1099,8 +1115,8 @@ function App() { setCountdown(null); setWalletToBeDownloaded(null); setWalletToBeDownloadedPassword(""); - setShowSeed(false); - setCreationStep(1); + setShowSeed(false) + setCreationStep(1) setExtstate("authenticated"); setIsOpenSendQort(false); setIsOpenSendQortSuccess(false); @@ -1126,8 +1142,8 @@ function App() { setCountdown(null); setWalletToBeDownloaded(null); setWalletToBeDownloadedPassword(""); - setShowSeed(false); - setCreationStep(1); + setShowSeed(false) + setCreationStep(1) setWalletToBeDownloadedPasswordConfirm(""); setWalletToBeDownloadedError(""); @@ -1136,7 +1152,7 @@ function App() { setTxList([]); setMemberGroups([]); resetAllRecoil(); - if (balanceSetIntervalRef?.current) { + if(balanceSetIntervalRef?.current){ clearInterval(balanceSetIntervalRef?.current); } }; @@ -1266,7 +1282,7 @@ function App() { setOpenSnack(true); setInfoSnack({ type, - message, + message }); }; @@ -1293,261 +1309,244 @@ function App() { }; }, []); - const renderProfileLeft = () => { - return ( - - - - {authenticatedMode === "qort" && ( - - LITECOIN WALLET - - } - placement="left" - arrow - sx={{ fontSize: "24" }} - slotProps={{ - tooltip: { - sx: { - color: "#ffffff", - backgroundColor: "#444444", - }, - }, - arrow: { - sx: { - color: "#444444", - }, - }, - }} - > - { - setAuthenticatedMode("ltc"); - }} - src={ltcLogo} - style={{ - cursor: "pointer", - width: "20px", - height: "auto", - }} - /> - - )} - {authenticatedMode === "ltc" && ( - - QORTAL WALLET - - } - placement="left" - arrow - sx={{ fontSize: "24" }} - slotProps={{ - tooltip: { - sx: { - color: "#ffffff", - backgroundColor: "#444444", - }, - }, - arrow: { - sx: { - color: "#444444", - }, - }, - }} - > - { - setAuthenticatedMode("qort"); - }} - src={qortLogo} - style={{ - cursor: "pointer", - width: "20px", - height: "auto", - }} - /> - - )} - - + - {authenticatedMode === "ltc" ? ( - <> - - - - - {rawWallet?.ltcAddress?.slice(0, 6)}... - {rawWallet?.ltcAddress?.slice(-4)} - - - - {ltcBalanceLoading && ( - - )} - {!isNaN(+ltcBalance) && !ltcBalanceLoading && ( - { + + return + + + {authenticatedMode === "qort" && ( + LITECOIN WALLET} + placement="left" + arrow + sx={{ fontSize: "24" }} + slotProps={{ + tooltip: { + sx: { + color: "#ffffff", + backgroundColor: "#444444", + }, + }, + arrow: { + sx: { + color: "#444444", + }, + }, }} > - { + + setAuthenticatedMode("ltc"); }} - > - {ltcBalance} LTC - - - + )} - - - ) : ( - <> - - + {authenticatedMode === "ltc" && ( + QORTAL WALLET} + placement="left" + arrow + sx={{ fontSize: "24" }} + slotProps={{ + tooltip: { + sx: { + color: "#ffffff", + backgroundColor: "#444444", + }, + }, + arrow: { + sx: { + color: "#444444", + }, + }, + }} + > + { + setAuthenticatedMode("qort"); + }} + src={qortLogo} + style={{ + cursor: "pointer", + width: "20px", + height: "auto", + }} + /> + + )} + + + + {authenticatedMode === "ltc" ? ( + <> + + + + + {rawWallet?.ltcAddress?.slice(0, 6)}... + {rawWallet?.ltcAddress?.slice(-4)} + + + + {ltcBalanceLoading && ( + + )} + {!isNaN(+ltcBalance) && !ltcBalanceLoading && ( + - {userInfo?.name} + {ltcBalance} LTC - - - - {rawWallet?.address0?.slice(0, 6)}... - {rawWallet?.address0?.slice(-4)} - - - - {qortBalanceLoading && ( - - )} - {!qortBalanceLoading && balance >= 0 && ( - - - {balance?.toFixed(2)} QORT - - - - )} - - - {userInfo && !userInfo?.name && ( - { - executeEvent("openRegisterName", {}); - }} - > - REGISTER NAME - - )} - - { - setIsOpenSendQort(true); - // setExtstate("send-qort"); - setIsOpenDrawerProfile(false); + - Transfer QORT - - - + /> + )} + + + ) : ( + <> + + { - executeEvent("addTab", { - data: { service: "APP", name: "q-trade" }, - }); - executeEvent("open-apps-mode", {}); + fontSize: "20px", }} > - Get QORT at Q-Trade + {userInfo?.name} - - ); - }; + + + + {rawWallet?.address0?.slice(0, 6)}... + {rawWallet?.address0?.slice(-4)} + + + + {qortBalanceLoading && ( + + )} + {!qortBalanceLoading && balance >= 0 && ( + + + {balance?.toFixed(2)} QORT + + + + )} + + + {userInfo && !userInfo?.name && ( + { + executeEvent('openRegisterName', {}) + }} + > + REGISTER NAME + + )} + + { + setIsOpenSendQort(true); + // setExtstate("send-qort"); + setIsOpenDrawerProfile(false); + }} + > + Transfer QORT + + + + )} + { + executeEvent("addTab", { + data: { service: "APP", name: "q-trade" }, + }); + executeEvent("open-apps-mode", {}); + }} + > + Get QORT at Q-Trade + + + } const renderProfile = () => { return ( @@ -1580,7 +1579,11 @@ function App() { )} {desktopViewMode !== "apps" && desktopViewMode !== "dev" && - desktopViewMode !== "chat" && <>{renderProfileLeft()}} + desktopViewMode !== "chat" && ( + <> + {renderProfileLeft()} + + )} - + {!isMobile && ( <> - LOG OUT - - } + title={LOG OUT} placement="left" arrow sx={{ fontSize: "24" }} @@ -1638,8 +1631,8 @@ function App() { }} style={{ cursor: "pointer", - width: "20px", - height: "auto", + width: '20px', + height: 'auto' }} /> @@ -1653,17 +1646,7 @@ function App() { }} > - SETTINGS - - } + title={SETTINGS} placement="left" arrow sx={{ fontSize: "24" }} @@ -1688,26 +1671,14 @@ function App() { /> - - { setIsOpenDrawerLookup(true); }} > - USER LOOKUP - - } + title={USER LOOKUP} placement="left" arrow sx={{ fontSize: "24" }} @@ -1732,26 +1703,14 @@ function App() { /> - - { - executeEvent("openWalletsApp", {}); + executeEvent('openWalletsApp', {}) }} > - WALLETS - - } + title={WALLETS} placement="left" arrow sx={{ fontSize: "24" }} @@ -1776,131 +1735,111 @@ function App() { /> - - {desktopViewMode !== "home" && ( + + + {desktopViewMode !== 'home' && ( <> + + YOUR ACCOUNT} + placement="left" + arrow + sx={{ fontSize: "24" }} + slotProps={{ + tooltip: { + sx: { + color: "#ffffff", + backgroundColor: "#444444", + }, + }, + arrow: { + sx: { + color: "#444444", + }, + }, + }} + > + { + setIsOpenDrawerProfile(true); + }}> - - YOUR ACCOUNT - - } - placement="left" - arrow - sx={{ fontSize: "24" }} - slotProps={{ - tooltip: { - sx: { - color: "#ffffff", - backgroundColor: "#444444", - }, - }, - arrow: { - sx: { - color: "#444444", - }, - }, - }} - > - { - setIsOpenDrawerProfile(true); - }} - > - - - + + + + )} - + + - - {extState === "authenticated" && ( + + {extState === 'authenticated' && ( )} + {extState === "authenticated" && isMainWindow && ( - - - - + + + + + )} - - { - try { - const res = await isRunningGateway(); - if (res) - throw new Error( - "Cannot view minting details on the gateway" - ); - setIsOpenMinting(true); - } catch (error) { - setOpenSnack(true); - setInfoSnack({ - type: "error", - message: error?.message, - }); - } - }} - > + + { + try { + const res = await isRunningGateway() + if(res) throw new Error('Cannot view minting details on the gateway') + setIsOpenMinting(true) + + } catch (error) { + setOpenSnack(true) + setInfoSnack({ + type: 'error', + message: error?.message + }) + } + }}> - MINTING STATUS - - } + title={MINTING STATUS} placement="left" arrow sx={{ fontSize: "24" }} @@ -1918,95 +1857,77 @@ function App() { }, }} > - + - + {(desktopViewMode === "apps" || desktopViewMode === "home") && ( - { - if (desktopViewMode === "apps") { - showTutorial("qapps", true); - } else { - showTutorial("getting-started", true); - } - }} - > - - TUTORIAL - - } - placement="left" - arrow - sx={{ fontSize: "24" }} - slotProps={{ - tooltip: { - sx: { - color: "#ffffff", - backgroundColor: "#444444", + { + if(desktopViewMode === "apps"){ + showTutorial('qapps', true) + } else { + showTutorial('getting-started', true) + } + }} > + TUTORIAL} + placement="left" + arrow + sx={{ fontSize: "24" }} + slotProps={{ + tooltip: { + sx: { + color: "#ffffff", + backgroundColor: "#444444", + }, }, - }, - arrow: { - sx: { - color: "#444444", + arrow: { + sx: { + color: "#444444", + }, }, - }, - }} - > - - - - )} - - - - BACKUP WALLET - - } - placement="left" - arrow - sx={{ fontSize: "24" }} - slotProps={{ - tooltip: { - sx: { - color: "#ffffff", - backgroundColor: "#444444", - }, - }, - arrow: { - sx: { - color: "#444444", - }, - }, + }} + > + + + + )} + + + BACKUP WALLET} + placement="left" + arrow + sx={{ fontSize: "24" }} + slotProps={{ + tooltip: { + sx: { + color: "#ffffff", + backgroundColor: "#444444", + }, + }, + arrow: { + sx: { + color: "#444444", + }, + }, + }} + > + { + setExtstate("download-wallet"); + setIsOpenDrawerProfile(false); }} - > - { - setExtstate("download-wallet"); - setIsOpenDrawerProfile(false); - }} - src={Download} - style={{ - cursor: "pointer", - width: "20px", - }} - /> - + src={Download} + style={{ + cursor: "pointer", + width: '20px' + }} + /> + - + ); @@ -2049,32 +1970,41 @@ function App() { {/* {extState !== "not-authenticated" && ( )} */} - {extState === "authenticated" && isMainWindow && ( - + - - {!isMobile && renderProfile()} - - - )} - {isOpenSendQort && isMainWindow && ( - - + {messageQortalRequest?.text1} + + + {messageQortalRequest?.text2 && ( + <> + + + + {messageQortalRequest?.text2} + + + + + )} + {messageQortalRequest?.text3 && ( + <> + + + {messageQortalRequest?.text3} + + + + + )} + + {messageQortalRequest?.text4 && ( + + + + + Set up your Qortal account + + + + + + A ‘ { + setShowSeed(true) + }} style={{ + fontSize: '14px', + color: 'steelblue', + cursor: 'pointer' + }}>SEEDPHRASE ’ has been randomly generated in the background. + + + + + If you wish to VIEW THE SEEDPHRASE, click the word 'SEEDPHRASE' in this text. Seedphrases are used to generate the private key for your Qortal account. For security by default, seedphrases are NOT displayed unless specifically chosen. + + + Create your Qortal account by clicking NEXT below. + + + + { + setCreationStep(2) + }}> + Next + + +
+ +
+ + + + Your seedphrase + + + {generatorRef.current?.parsedString} + + + + Export Seedphrase + + + + + + + + + + +
+ + + + Wallet Password + + + + setWalletToBeDownloadedPassword(e.target.value) + } /> - - - { - setIsOpenSendQort(false); - setIsOpenSendQortSuccess(true); - }} - defaultPaymentTo={paymentTo} - /> -
- )} + + + Confirm Wallet Password + + + + setWalletToBeDownloadedPasswordConfirm(e.target.value) + } + /> + + There is no minimum length requirement + Create Account @@ -3172,10 +3254,10 @@ function App() { textAlign: "center", }} > - {messageQortalRequest?.text1} + {messageQortalRequestExtension?.text1} - {messageQortalRequest?.text2 && ( + {messageQortalRequestExtension?.text2 && ( <> - {messageQortalRequest?.text2} + {messageQortalRequestExtension?.text2} )} - {messageQortalRequest?.text3 && ( + {messageQortalRequestExtension?.text3 && ( <> - {messageQortalRequest?.text3} + {messageQortalRequestExtension?.text3} )} - {messageQortalRequest?.text4 && ( + {messageQortalRequestExtension?.text4 && ( - {messageQortalRequest?.text4} + {messageQortalRequestExtension?.text4} )} - {messageQortalRequest?.html && ( + {messageQortalRequestExtension?.html && (
)} @@ -3257,10 +3341,20 @@ function App() { maxWidth: "90%", }} > - {messageQortalRequest?.highlightedText} + {messageQortalRequestExtension?.highlightedText} - {messageQortalRequest?.fee && ( + {messageQortalRequestExtension?.json && ( + <> + + + + + + + )} + + {messageQortalRequestExtension?.fee && ( <> @@ -3274,17 +3368,53 @@ function App() { }} > {"Fee: "} - {messageQortalRequest?.fee} + {messageQortalRequestExtension?.fee} {" QORT"} )} - {messageQortalRequest?.checkbox1 && ( + {messageQortalRequestExtension?.appFee && ( + <> + + {"App Fee: "} + {messageQortalRequestExtension?.appFee} + {" QORT"} + + + + )} + {messageQortalRequestExtension?.foreignFee && ( + <> + + + + {"Foreign Fee: "} + {messageQortalRequestExtension?.foreignFee} + + + + )} + {messageQortalRequestExtension?.checkbox1 && ( - {messageQortalRequest?.checkbox1?.label} + {messageQortalRequestExtension?.checkbox1?.label} )} @@ -3357,7 +3489,9 @@ function App() { gap: "14px", }} > - onOkQortalRequest("accepted")} > accept - - + onCancelQortalRequest()} + onClick={() => onCancelQortalRequestExtension()} > decline - + {sendPaymentError} - - )} - {extState === "web-app-request-buy-order" && !isMainWindow && ( - <> - - - - The Application

{" "} - {requestBuyOrder?.hostname}

- - is requesting {requestBuyOrder?.crosschainAtInfo?.length}{" "} - {`buy order${ - requestBuyOrder?.crosschainAtInfo.length === 1 ? "" : "s" - }`} - -
- - - {requestBuyOrder?.crosschainAtInfo?.reduce((latest, cur) => { - return latest + +cur?.qortAmount; - }, 0)}{" "} - QORT - - - - FOR - - - - {roundUpToDecimals( - requestBuyOrder?.crosschainAtInfo?.reduce((latest, cur) => { - return latest + +cur?.expectedForeignAmount; - }, 0) - )} - {` ${requestBuyOrder?.crosschainAtInfo?.[0]?.foreignBlockchain}`} - - {/* - - - Confirm Wallet Password - - - setPaymentPassword(e.target.value)} - /> */} - - - confirmBuyOrder(false)} - > - accept - - confirmBuyOrder(true)} - > - decline - - - {sendPaymentError} - - )} - - {extState === "web-app-request-payment" && !isMainWindow && ( - <> - - - - The Application

{" "} - {sendqortState?.hostname}

- is requesting a payment -
- - - {sendqortState?.description} - - - - {sendqortState?.amount} QORT - - {/* - - - Confirm Wallet Password - - - setPaymentPassword(e.target.value)} - /> */} - - - confirmPayment(false)} - > - accept - - confirmPayment(true)} - > - decline - - - {sendPaymentError} - - )} - {extState === "web-app-request-connection" && !isMainWindow && ( - <> - -
- -
- - - The Application

{" "} - {requestConnection?.hostname}

- is requestion a connection -
- - - - responseToConnectionRequest( - true, - requestConnection?.hostname, - requestConnection.interactionId - ) - } - > - accept - - - responseToConnectionRequest( - false, - requestConnection?.hostname, - requestConnection.interactionId - ) - } - > - decline - - - - )} - {extState === "web-app-request-authentication" && !isMainWindow && ( - <> - -
- -
- - - The Application

{" "} - {requestConnection?.hostname}

- requests authentication -
- - - - - - Authenticate - - - { - setExtstate("create-wallet"); - }} - > - Create account - - - )} - {extState === "wallets" && ( - <> - - - { - setRawWallet(null); - setExtstate("not-authenticated"); - logoutFunc(); - }} - src={Return} - /> - - - - )} - {rawWallet && extState === "wallet-dropped" && ( - <> - - - { - setRawWallet(null); - setExtstate("wallets"); - logoutFunc(); - }} - src={Return} - /> - - -
- -
- - - - {rawWallet?.name ? rawWallet?.name : rawWallet?.address0} - - - - Authenticate - - - - - <> - - Wallet Password - - - setAuthenticatePassword(e.target.value)} - onKeyDown={(e) => { - if (e.key === "Enter") { - authenticateWallet(); - } - }} - ref={passwordRef} - /> - {useLocalNode ? ( - <> - - - {"Using node: "} {currentNode?.url} - - - ) : ( - <> - - - {"Using public node"} - - - )} - - - - Authenticate - - {walletToBeDecryptedError} - - - )} - {extState === "download-wallet" && ( - <> - - - - - -
- -
- - - - Download Account - - - - {!walletToBeDownloaded && ( - <> - - Confirm Wallet Password - - - - setWalletToBeDownloadedPassword(e.target.value) - } - /> - - - Confirm password - - {walletToBeDownloadedError} - - )} - - {walletToBeDownloaded && ( - <> - { - await saveFileToDiskFunc(); - await showInfo({ - message: `Keep your account file secure.`, - }); - }} - > - Download account - - - )} - - )} - {extState === "create-wallet" && ( - <> - {!walletToBeDownloaded && ( - <> - - - { - if (creationStep === 2) { - setCreationStep(1); - return; - } - setExtstate("not-authenticated"); - setShowSeed(false); - setCreationStep(1); - setWalletToBeDownloadedPasswordConfirm(""); - setWalletToBeDownloadedPassword(""); - }} - src={Return} - /> - - -
- -
- - - Set up your Qortal account - - - - - - A ‘{" "} - { - setShowSeed(true); - }} - style={{ - fontSize: "14px", - color: "steelblue", - cursor: "pointer", - }} - > - SEEDPHRASE - {" "} - ’ has been randomly generated in the background. - - - If you wish to VIEW THE SEEDPHRASE, click the word - 'SEEDPHRASE' in this text. Seedphrases are used to - generate the private key for your Qortal account. For - security by default, seedphrases are NOT displayed unless - specifically chosen. - - - Create your Qortal account by clicking{" "} - - NEXT - {" "} - below. - - - { - setCreationStep(2); - }} - > - Next - - -
- -
- - - - - Your seedphrase - - - - {generatorRef.current?.parsedString} - - - - Export Seedphrase - - - - - - - -
- - - - Wallet Password - - - - setWalletToBeDownloadedPassword(e.target.value) - } - /> - - - Confirm Wallet Password - - - - setWalletToBeDownloadedPasswordConfirm(e.target.value) - } - /> - - - There is no minimum length requirement - - - - - Create Account - - - {walletToBeDownloadedError} - - )} - - {walletToBeDownloaded && ( - <> - - - - - Congrats, you’re all set up! - - - - - - Save your account in a place where you will remember it! - - - - { - await saveFileToDiskFunc(); - returnToMain(); - await showInfo({ - message: `Keep your wallet file secure.`, - }); - }} - > - Backup Account - - - )} - - )} - {isOpenSendQortSuccess && ( - - - - - - The transfer was succesful! - - - { - returnToMain(); - }} - > - Continue - - )} - {extState === "transfer-success-request" && ( - <> - - - - - The transfer was succesful! - - - { - window.close(); - }} - > - Continue - - - )} - {extState === "buy-order-submitted" && ( - <> - - - - - Your buy order was submitted - - - { - window.close(); - }} - > - Close - - - )} - {countdown && ( - - {/* */} - { - window.close(); - }} - size={75} - strokeWidth={8} - > - {({ remainingTime }) => {remainingTime}} - - - )} - {isLoading && } - {isShow && ( - - - {message.paymentFee ? "Payment" : "Publish"} - - - - {message.message} - - {message?.paymentFee && ( - - payment fee: {message.paymentFee} - - )} - {message?.publishFee && ( - - publish fee: {message.publishFee} - - )} - - - - - - - )} - {isShowInfo && ( - - - {"Important Info"} - - - - {messageInfo.message} - - - - - - - )} - {isShowUnsavedChanges && ( - - {"LOGOUT"} - - - {messageUnsavedChanges.message} - - - - - - - - )} - {isShowQortalRequestExtension && isMainWindow && ( - - { - onCancelQortalRequestExtension(); - }} - size={50} - strokeWidth={5} - > - {({ remainingTime }) => {remainingTime}} - - - - - {messageQortalRequestExtension?.text1} - - - {messageQortalRequestExtension?.text2 && ( - <> - - - - {messageQortalRequestExtension?.text2} - - - - - )} - {messageQortalRequestExtension?.text3 && ( - <> - - - {messageQortalRequestExtension?.text3} - - - - - )} - - {messageQortalRequestExtension?.text4 && ( - - - {messageQortalRequestExtension?.text4} - - - )} - - {messageQortalRequestExtension?.html && ( -
- )} - - - - {messageQortalRequestExtension?.highlightedText} - - - {messageQortalRequestExtension?.json && ( - <> - - - - - - )} - - {messageQortalRequestExtension?.fee && ( - <> - - - - {"Fee: "} - {messageQortalRequestExtension?.fee} - {" QORT"} - - - - )} - {messageQortalRequestExtension?.appFee && ( - <> - - {"App Fee: "} - {messageQortalRequestExtension?.appFee} - {" QORT"} - - - - )} - {messageQortalRequestExtension?.foreignFee && ( - <> - - - - {"Foreign Fee: "} - {messageQortalRequestExtension?.foreignFee} - - - - )} - {messageQortalRequestExtension?.checkbox1 && ( - - { - qortalRequestCheckbox1Ref.current = e.target.checked; - }} - edge="start" - tabIndex={-1} - disableRipple - defaultChecked={ - messageQortalRequestExtension?.checkbox1?.value - } - sx={{ - "&.Mui-checked": { - color: "white", // Customize the color when checked - }, - "& .MuiSvgIcon-root": { - color: "white", - }, - }} - /> - - - {messageQortalRequestExtension?.checkbox1?.label} - - - )} - - - - onOkQortalRequestExtension("accepted")} - > - accept - - onCancelQortalRequestExtension()} - > - decline - - - {sendPaymentError} - -
- )} - {isSettingsOpen && ( - - )} - - - {renderProfileLeft()} - - - - + + )} + {isSettingsOpen && ( + + )} + + + {renderProfileLeft()} + + + + {extState === "create-wallet" && walletToBeDownloaded && ( - { - showTutorial("important-information", true); - }} - sx={{ - position: "fixed", - bottom: "25px", - right: "25px", - }} - > - - + { + showTutorial('important-information', true) + }} sx={{ + position: 'fixed', + bottom: '25px', + right: '25px' + }}> + + )} - {isOpenMinting && ( - - )} - + {isOpenMinting && ( + + )} ); } -export default App; +export default App; \ No newline at end of file diff --git a/src/ExtStates/NotAuthenticated.tsx b/src/ExtStates/NotAuthenticated.tsx index 626556b..8625495 100644 --- a/src/ExtStates/NotAuthenticated.tsx +++ b/src/ExtStates/NotAuthenticated.tsx @@ -1,16 +1,11 @@ -import React, { - useCallback, - useContext, - useEffect, - useRef, - useState, -} from "react"; +import React, { useCallback, useContext, useEffect, useRef, useState } from "react"; import { Spacer } from "../common/Spacer"; -import { CustomButton, TextP, TextSpan } from "../App-styles"; +import { CustomButton, TextItalic, TextP, TextSpan } from "../App-styles"; import { Box, Button, ButtonBase, + Checkbox, Dialog, DialogActions, DialogContent, @@ -22,33 +17,37 @@ import { TextField, Typography, } from "@mui/material"; +import Logo1 from "../assets/svgs/Logo1.svg"; import Logo1Dark from "../assets/svgs/Logo1Dark.svg"; -import HelpIcon from "@mui/icons-material/Help"; +import Info from "../assets/svgs/Info.svg"; +import HelpIcon from '@mui/icons-material/Help'; import { CustomizedSnackbars } from "../components/Snackbar/Snackbar"; -import { cleanUrl, gateways } from "../background"; +import { set } from "lodash"; +import { cleanUrl, gateways, isUsingLocal } from "../background"; import { GlobalContext } from "../App"; -import Tooltip, { TooltipProps, tooltipClasses } from "@mui/material/Tooltip"; -import ThemeSelector from "../components/Theme/ThemeSelector"; +import Tooltip, { TooltipProps, tooltipClasses } from '@mui/material/Tooltip'; const manifestData = { version: "0.5.3", }; + export const HtmlTooltip = styled(({ className, ...props }: TooltipProps) => ( ))(({ theme }) => ({ [`& .${tooltipClasses.tooltip}`]: { - backgroundColor: "#232428", - color: "white", + backgroundColor: '#232428', + color: 'white', maxWidth: 320, - padding: "20px", + padding: '20px', fontSize: theme.typography.pxToRem(12), }, })); function removeTrailingSlash(url) { - return url.replace(/\/+$/, ""); + return url.replace(/\/+$/, ''); } + export const NotAuthenticated = ({ getRootProps, getInputProps, @@ -60,8 +59,8 @@ export const NotAuthenticated = ({ handleSetGlobalApikey, currentNode, setCurrentNode, - useLocalNode, - setUseLocalNode, + useLocalNode, + setUseLocalNode }) => { const [isValidApiKey, setIsValidApiKey] = useState(null); const [hasLocalNode, setHasLocalNode] = useState(null); @@ -82,7 +81,7 @@ export const NotAuthenticated = ({ const [enteredApiKey, setEnteredApiKey] = useState('') const [customNodeToSaveIndex, setCustomNodeToSaveIndex] = React.useState(null); - const { showTutorial, hasSeenGettingStarted } = useContext(GlobalContext); + const { showTutorial, hasSeenGettingStarted } = useContext(GlobalContext); const importedApiKeyRef = useRef(null); const currentNodeRef = useRef(null); @@ -97,32 +96,34 @@ export const NotAuthenticated = ({ const text = e.target.result; // Get the file content setImportedApiKey(text); // Store the file content in the state - if (customNodes) { - setCustomNodes((prev) => { - const copyPrev = [...prev]; - const findLocalIndex = copyPrev?.findIndex( - (item) => item?.url === "http://127.0.0.1:12391" - ); - if (findLocalIndex === -1) { + if(customNodes){ + setCustomNodes((prev)=> { + const copyPrev = [...prev] + const findLocalIndex = copyPrev?.findIndex((item)=> item?.url === 'http://127.0.0.1:12391') + if(findLocalIndex === -1){ copyPrev.unshift({ url: "http://127.0.0.1:12391", - apikey: text, - }); + apikey: text + }) } else { copyPrev[findLocalIndex] = { url: "http://127.0.0.1:12391", - apikey: text, - }; + apikey: text + } } - window.sendMessage("setCustomNodes", copyPrev).catch((error) => { + window + .sendMessage("setCustomNodes", copyPrev) + .catch((error) => { console.error( "Failed to set custom nodes:", error.message || "An error occurred" ); }); - return copyPrev; - }); + return copyPrev + }) + } + }; reader.readAsText(file); // Read the file as text } @@ -140,12 +141,14 @@ export const NotAuthenticated = ({ const data = await response.json(); if (data?.height) { setHasLocalNode(true); - return true; + return true } - return false; + return false + } catch (error) { - return false; - } + return false + + } }, []); useEffect(() => { @@ -156,20 +159,18 @@ export const NotAuthenticated = ({ window .sendMessage("getCustomNodesFromStorage") .then((response) => { - setCustomNodes(response || []); - if (window?.electronAPI?.setAllowedDomains) { - window.electronAPI.setAllowedDomains( - response?.map((node) => node.url) - ); - } - if (Array.isArray(response)) { - const findLocal = response?.find( - (item) => item?.url === "http://127.0.0.1:12391" - ); - if (findLocal && findLocal?.apikey) { - setImportedApiKey(findLocal?.apikey); + + setCustomNodes(response || []); + if(window?.electronAPI?.setAllowedDomains){ + window.electronAPI.setAllowedDomains(response?.map((node)=> node.url)) } - } + if(Array.isArray(response)){ + const findLocal = response?.find((item)=> item?.url === 'http://127.0.0.1:12391') + if(findLocal && findLocal?.apikey){ + setImportedApiKey(findLocal?.apikey) + } + } + }) .catch((error) => { console.error( @@ -190,50 +191,48 @@ export const NotAuthenticated = ({ hasLocalNodeRef.current = hasLocalNode; }, [hasLocalNode]); + + const validateApiKey = useCallback(async (key, fromStartUp) => { try { - if (key === "isGateway") return; + if(key === "isGateway") return const isLocalKey = cleanUrl(key?.url) === "127.0.0.1:12391"; - if ( - fromStartUp && - key?.url && - key?.apikey && - !isLocalKey && - !gateways.some((gateway) => key?.url?.includes(gateway)) - ) { + if (fromStartUp && key?.url && key?.apikey && !isLocalKey && !gateways.some(gateway => key?.url?.includes(gateway))) { setCurrentNode({ url: key?.url, apikey: key?.apikey, }); - let isValid = false; + let isValid = false + const url = `${key?.url}/admin/settings/localAuthBypassEnabled`; const response = await fetch(url); // Assuming the response is in plain text and will be 'true' or 'false' const data = await response.text(); - if (data && data === "true") { - isValid = true; + if(data && data === 'true'){ + isValid = true } else { const url2 = `${key?.url}/admin/apikey/test?apiKey=${key?.apikey}`; const response2 = await fetch(url2); - + // Assuming the response is in plain text and will be 'true' or 'false' const data2 = await response2.text(); if (data2 === "true") { - isValid = true; + isValid = true } } - + if (isValid) { setIsValidApiKey(true); setUseLocalNode(true); - return; + return } + } if (!currentNodeRef.current) return; - const stillHasLocal = await checkIfUserHasLocalNode(); + const stillHasLocal = await checkIfUserHasLocalNode() if (isLocalKey && !stillHasLocal && !fromStartUp) { throw new Error("Please turn on your local node"); @@ -308,25 +307,27 @@ export const NotAuthenticated = ({ } else if (currentNodeRef.current) { payload = currentNodeRef.current; } - let isValid = false; + let isValid = false + const url = `${payload?.url}/admin/settings/localAuthBypassEnabled`; const response = await fetch(url); // Assuming the response is in plain text and will be 'true' or 'false' const data = await response.text(); - if (data && data === "true") { - isValid = true; + if(data && data === 'true'){ + isValid = true } else { const url2 = `${payload?.url}/admin/apikey/test?apiKey=${payload?.apikey}`; const response2 = await fetch(url2); - + // Assuming the response is in plain text and will be 'true' or 'false' const data2 = await response2.text(); if (data2 === "true") { - isValid = true; + isValid = true } } + if (isValid) { window @@ -350,13 +351,14 @@ export const NotAuthenticated = ({ } else { setIsValidApiKey(false); setUseLocalNode(false); - if (!fromStartUp) { + if(!fromStartUp){ setInfoSnack({ type: "error", message: "Select a valid apikey", }); setOpenSnack(true); } + } } catch (error) { setIsValidApiKey(false); @@ -379,15 +381,15 @@ export const NotAuthenticated = ({ error.message || "An error occurred" ); }); - return; - } - if (!fromStartUp) { - setInfoSnack({ - type: "error", - message: error?.message || "Select a valid apikey", - }); - setOpenSnack(true); + return } + if(!fromStartUp){ + setInfoSnack({ + type: "error", + message: error?.message || "Select a valid apikey", + }); + setOpenSnack(true); + } console.error("Error validating API key:", error); } }, []); @@ -416,7 +418,7 @@ export const NotAuthenticated = ({ } setCustomNodes(nodes); - + setCustomNodeToSaveIndex(null); if (!nodes) return; window @@ -426,11 +428,9 @@ export const NotAuthenticated = ({ setMode("list"); setUrl("https://"); setCustomApiKey(""); - if (window?.electronAPI?.setAllowedDomains) { - window.electronAPI.setAllowedDomains( - nodes?.map((node) => node.url) - ); - } + if(window?.electronAPI?.setAllowedDomains){ + window.electronAPI.setAllowedDomains(nodes?.map((node) => node.url)) + } // add alert if needed } }) @@ -459,20 +459,15 @@ export const NotAuthenticated = ({ sx={{ textAlign: "center", lineHeight: 1.2, - fontSize: "18px", + fontSize: '18px' }} > - WELCOME TO - - {" "} - QORTAL - + WELCOME TO + QORTAL - + - - - Your wallet is like your digital ID on Qortal, and is how you - will login to the Qortal User Interface. It holds your public - address and the Qortal name you will eventually choose. Every - transaction you make is linked to your ID, and this is where you - manage all your QORT and other tradeable cryptocurrencies on - Qortal. - - - } - > - setExtstate("wallets")}> - {/* */} - Accounts - + + Your wallet is like your digital ID on Qortal, and is how you will login to the Qortal User Interface. It holds your public address and the Qortal name you will eventually choose. Every transaction you make is linked to your ID, and this is where you manage all your QORT and other tradeable cryptocurrencies on Qortal. + + } + > + setExtstate('wallets')}> + {/* */} + Accounts + {/* @@ -518,55 +503,42 @@ export const NotAuthenticated = ({ display: "flex", gap: "10px", alignItems: "center", + }} > - - New users start here! - - - - Creating an account means creating a new wallet and digital ID - to start using Qortal. Once you have made your account, you can - start doing things like obtaining some QORT, buying a name and - avatar, publishing videos and blogs, and much more. - - - } + disableHoverListener={hasSeenGettingStarted === true} + placement="right" + title={ + + New users start here! + + Creating an account means creating a new wallet and digital ID to start using Qortal. Once you have made your account, you can start doing things like obtaining some QORT, buying a name and avatar, publishing videos and blogs, and much more. + + } + > + { + setExtstate("create-wallet"); + }} + sx={{ + backgroundColor: hasSeenGettingStarted === false && 'var(--green)', + color: hasSeenGettingStarted === false && 'black', + "&:hover": { + backgroundColor: hasSeenGettingStarted === false && 'var(--green)', + color: hasSeenGettingStarted === false && 'black' + } + }} > - { - setExtstate("create-wallet"); - }} - sx={{ - backgroundColor: - hasSeenGettingStarted === false && "var(--green)", - color: hasSeenGettingStarted === false && "black", - "&:hover": { - backgroundColor: - hasSeenGettingStarted === false && "var(--green)", - color: hasSeenGettingStarted === false && "black", - }, - }} - > - Create account - + Create account + + @@ -586,19 +558,15 @@ export const NotAuthenticated = ({ gap: "10px", alignItems: "center", flexDirection: "column", - outline: "0.5px solid rgba(255, 255, 255, 0.5)", - padding: "20px 30px", - borderRadius: "5px", + outline: '0.5px solid rgba(255, 255, 255, 0.5)', + padding: '20px 30px', + borderRadius: '5px', }} > <> - - For advanced users - + For advanced users } label={`Use ${isLocal ? "Local" : "Custom"} Node`} @@ -937,7 +907,44 @@ export const NotAuthenticated = ({ )} - + {showSelectApiKey && ( + + {"Enter apikey"} + + + setEnteredApiKey(e.target.value)}/> + + + + + +