From dcfa7b258e73de6860ca9bc82ccda09de39c831d Mon Sep 17 00:00:00 2001 From: Nicola Benaglia Date: Sat, 12 Apr 2025 15:31:10 +0200 Subject: [PATCH] Refactor sReturn icon and set theme styles --- src/App.tsx | 4812 +++++++++-------- src/Wallets.tsx | 625 ++- src/assets/svgs/CreateThreadIcon.tsx | 14 +- src/assets/svgs/Return.tsx | 27 + src/assets/svgs/SaveIcon.tsx | 5 +- src/assets/svgs/SendNewMessage.tsx | 19 +- src/assets/svgs/StarEmpty.tsx | 24 +- src/assets/svgs/StarFilled.tsx | 2 - src/components/Apps/AppsLibrary.tsx | 383 +- src/components/Apps/AppsLibraryDesktop.tsx | 411 +- src/components/Desktop/DesktopFooter.tsx | 80 +- src/components/Group/Forum/Thread.tsx | 524 +- .../PasswordField/PasswordField.tsx | 89 +- 13 files changed, 3712 insertions(+), 3303 deletions(-) create mode 100644 src/assets/svgs/Return.tsx diff --git a/src/App.tsx b/src/App.tsx index a5dd940..6365115 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,8 +5,8 @@ import { useMemo, useRef, useState, -} from "react"; -import { useDropzone } from "react-dropzone"; +} from 'react'; +import { useDropzone } from 'react-dropzone'; import { Box, Button, @@ -19,32 +19,26 @@ import { DialogContentText, DialogTitle, FormControlLabel, - Input, - InputLabel, - Popover, Tooltip, Typography, -} from "@mui/material"; + useTheme, +} from '@mui/material'; 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 { decryptStoredWallet } from './utils/decryptWallet'; +import { CountdownCircleTimer } from 'react-countdown-circle-timer'; +import Logo1Dark from './assets/svgs/Logo1Dark.svg'; +import RefreshIcon from '@mui/icons-material/Refresh'; +import Copy from './assets/svgs/Copy.svg'; +import ltcLogo from './assets/ltc.png'; 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 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.tsx'; 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 Success from './assets/svgs/Success.svg'; import './utils/seedPhrase/RandomSentenceGenerator'; import EngineeringIcon from '@mui/icons-material/Engineering'; import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; @@ -54,11 +48,11 @@ import { 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"; +} 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 { AddressBox, AppContainer, @@ -72,48 +66,44 @@ import { TextItalic, TextP, TextSpan, -} from "./App-styles"; -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"; +} from './App-styles'; +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 { 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 { cleanUrl, - getFee, getProtocol, getWallets, groupApi, - groupApiLocal, groupApiSocket, - groupApiSocketLocal, storeWallets, -} from "./background"; +} from './background'; import { executeEvent, subscribeToEvent, unsubscribeFromEvent, -} from "./utils/events"; +} from './utils/events'; import { requestQueueCommentCount, requestQueuePublishedAccouncements, -} from "./components/Chat/GroupAnnouncements"; -import { requestQueueGroupJoinRequests } from "./components/Group/GroupJoinRequests"; -import { DrawerComponent } from "./components/Drawer/Drawer"; -import { AddressQRCode } from "./components/AddressQRCode"; -import { Settings } from "./components/Group/Settings"; -import { MainAvatar } from "./components/MainAvatar"; -import { useRetrieveDataLocalStorage } from "./useRetrieveDataLocalStorage"; -import { useQortalGetSaveSettings } from "./useQortalGetSaveSettings"; -import { useRecoilState, useResetRecoilState, useSetRecoilState } from "recoil"; +} from './components/Chat/GroupAnnouncements'; +import { requestQueueGroupJoinRequests } from './components/Group/GroupJoinRequests'; +import { DrawerComponent } from './components/Drawer/Drawer'; +import { AddressQRCode } from './components/AddressQRCode'; +import { Settings } from './components/Group/Settings'; +import { MainAvatar } from './components/MainAvatar'; +import { useRetrieveDataLocalStorage } from './useRetrieveDataLocalStorage'; +import { useQortalGetSaveSettings } from './useQortalGetSaveSettings'; +import { useRecoilState, useResetRecoilState, useSetRecoilState } from 'recoil'; import { canSaveSettingToQdnAtom, enabledDevModeAtom, @@ -129,53 +119,54 @@ import { settingsLocalLastUpdatedAtom, settingsQDNLastUpdatedAtom, sortablePinnedAppsAtom, -} from "./atoms/global"; -import { useAppFullScreen } from "./useAppFullscreen"; -import { NotAuthenticated } from "./ExtStates/NotAuthenticated"; +} 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"; -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 { PdfViewer } from "./common/PdfViewer"; +} 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'; +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 { PdfViewer } from './common/PdfViewer'; +import ThemeSelector from './components/Theme/ThemeSelector'; type extStates = - | "not-authenticated" - | "authenticated" - | "send-qort" - | "web-app-request-connection" - | "web-app-request-payment" - | "web-app-request-authentication" - | "download-wallet" - | "create-wallet" - | "transfer-success-regular" - | "transfer-success-request" - | "wallet-dropped" - | "web-app-request-buy-order" - | "buy-order-submitted" - | "wallets" - | "group"; + | 'not-authenticated' + | 'authenticated' + | 'send-qort' + | 'web-app-request-connection' + | 'web-app-request-payment' + | 'web-app-request-authentication' + | 'download-wallet' + | 'create-wallet' + | 'transfer-success-regular' + | 'transfer-success-request' + | 'wallet-dropped' + | 'web-app-request-buy-order' + | 'buy-order-submitted' + | 'wallets' + | 'group'; interface MyContextInterface { txList: any[]; @@ -199,8 +190,8 @@ const defaultValues: MyContextInterface = { onOk: () => {}, show: () => {}, message: { - publishFee: "", - message: "", + publishFee: '', + message: '', }, }; export let isMobile = false; @@ -221,9 +212,9 @@ const isMobileDevice = () => { if (isMobileDevice()) { isMobile = true; - console.log("Running on a mobile device"); + console.log('Running on a mobile device'); } else { - console.log("Running on a desktop"); + console.log('Running on a desktop'); } export const allQueues = { @@ -237,7 +228,7 @@ const controlAllQueues = (action) => { Object.keys(allQueues).forEach((key) => { const val = allQueues[key]; try { - if (typeof val[action] === "function") { + if (typeof val[action] === 'function') { val[action](); } } catch (error) { @@ -246,7 +237,6 @@ const controlAllQueues = (action) => { }); }; - export const clearAllQueues = () => { Object.keys(allQueues).forEach((key) => { const val = allQueues[key]; @@ -259,31 +249,34 @@ export const clearAllQueues = () => { }; export const pauseAllQueues = () => { - controlAllQueues("pause"); - window.sendMessage("pauseAllQueues", {}).catch((error) => { + controlAllQueues('pause'); + window.sendMessage('pauseAllQueues', {}).catch((error) => { console.error( - "Failed to pause all queues:", - error.message || "An error occurred" - ); - }); -}; -export const resumeAllQueues = () => { - controlAllQueues("resume"); - window.sendMessage("resumeAllQueues", {}).catch((error) => { - console.error( - "Failed to resume all queues:", - error.message || "An error occurred" + 'Failed to pause all queues:', + error.message || 'An error occurred' ); }); }; +export const resumeAllQueues = () => { + controlAllQueues('resume'); + window.sendMessage('resumeAllQueues', {}).catch((error) => { + console.error( + 'Failed to resume all queues:', + error.message || 'An error occurred' + ); + }); +}; 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; @@ -313,6 +306,7 @@ export const getArbitraryEndpointReact = () => { return `/arbitrary/resources/searchsimple`; } }; + export const getBaseApiReactSocket = (customApi?: string) => { if (customApi) { return customApi; @@ -320,16 +314,17 @@ export const getBaseApiReactSocket = (customApi?: string) => { if (globalApiKey?.url) { return `${ - getProtocol(globalApiKey?.url) === "http" ? "ws://" : "wss://" + getProtocol(globalApiKey?.url) === 'http' ? 'ws://' : 'wss://' }${cleanUrl(globalApiKey?.url)}`; } else { return groupApiSocket; } }; + export const isMainWindow = true; function App() { - const [extState, setExtstate] = useState("not-authenticated"); - const [desktopViewMode, setDesktopViewMode] = useState("home"); + const [extState, setExtstate] = useState('not-authenticated'); + const [desktopViewMode, setDesktopViewMode] = useState('home'); const [backupjson, setBackupjson] = useState(null); const [rawWallet, setRawWallet] = useState(null); @@ -338,46 +333,53 @@ function App() { const [decryptedWallet, setdecryptedWallet] = useState(null); const [requestConnection, setRequestConnection] = useState(null); const [requestBuyOrder, setRequestBuyOrder] = useState(null); - const [authenticatedMode, setAuthenticatedMode] = useState("qort"); + const [authenticatedMode, setAuthenticatedMode] = useState('qort'); const [requestAuthentication, setRequestAuthentication] = useState(null); const [userInfo, setUserInfo] = useState(null); const [balance, setBalance] = useState(null); const [ltcBalance, setLtcBalance] = useState(null); - const [paymentTo, setPaymentTo] = useState(""); + const [paymentTo, setPaymentTo] = useState(''); const [paymentAmount, setPaymentAmount] = useState(0); - const [paymentPassword, setPaymentPassword] = useState(""); - const [sendPaymentError, setSendPaymentError] = useState(""); - const [sendPaymentSuccess, setSendPaymentSuccess] = useState(""); + const [paymentPassword, setPaymentPassword] = useState(''); + const [sendPaymentError, setSendPaymentError] = useState(''); + const [sendPaymentSuccess, setSendPaymentSuccess] = useState(''); const [countdown, setCountdown] = useState(null); const [walletToBeDownloaded, setWalletToBeDownloaded] = useState(null); const [walletToBeDownloadedPassword, setWalletToBeDownloadedPassword] = - useState(""); + useState(''); const [isMain, setIsMain] = useState(true); const isMainRef = useRef(false); - const [authenticatePassword, setAuthenticatePassword] = useState(""); + const [authenticatePassword, setAuthenticatePassword] = useState(''); const [sendqortState, setSendqortState] = useState(null); const [isLoading, setIsLoading] = useState(false); const [isLoadingSendCoin, setIsLoadingSendCoin] = useState(false); + const theme = useTheme(); const [ walletToBeDownloadedPasswordConfirm, setWalletToBeDownloadedPasswordConfirm, - ] = useState(""); + ] = useState(''); const [walletToBeDownloadedError, setWalletToBeDownloadedError] = - useState(""); + useState(''); const [walletToBeDecryptedError, setWalletToBeDecryptedError] = - useState(""); + useState(''); const [txList, setTxList] = useState([]); const [memberGroups, setMemberGroups] = useState([]); const [isFocused, setIsFocused] = useState(true); const [hasSettingsChanged, setHasSettingsChanged] = useRecoilState( hasSettingsChangedAtom ); - const balanceSetIntervalRef = useRef(null) - const {downloadResource} = useFetchResources() - const holdRefExtState = useRef("not-authenticated"); + 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, @@ -393,7 +395,7 @@ function App() { show: showInfo, message: messageInfo, } = useModal(); - + const { onCancel: onCancelQortalRequest, onOk: onOkQortalRequest, @@ -409,75 +411,80 @@ 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 [apiKey, setApiKey] = useState(""); + 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 [rootHeight, setRootHeight] = useState('100%'); + const { + isUserBlocked, addToBlockList, - removeBlockFromList, getAllBlockedUsers} = useBlockedAddresses() - const [currentNode, setCurrentNode] = useState({ - url: "http://127.0.0.1:12391", - }); - const [useLocalNode, setUseLocalNode] = useState(false); - - const [confirmRequestRead, setConfirmRequestRead] = useState(false); + removeBlockFromList, + getAllBlockedUsers, + } = useBlockedAddresses(); + const [currentNode, setCurrentNode] = useState({ + url: 'http://127.0.0.1:12391', + }); + const [useLocalNode, setUseLocalNode] = useState(false); + + 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"); + 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) { + if (extState === 'wallet-dropped' && passwordRef.current) { passwordRef.current.focus(); } }, [extState]); useEffect(() => { - const isDevModeFromStorage = localStorage.getItem("isEnabledDevMode"); + const isDevModeFromStorage = localStorage.getItem('isEnabledDevMode'); if (isDevModeFromStorage) { setIsEnabledDevMode(JSON.parse(isDevModeFromStorage)); } }, []); - useEffect(()=> { - isRunningGateway().then((res)=> { - setIsRunningPublicNode(res) - }).catch((error)=> { - console.error(error) + useEffect(() => { + isRunningGateway() + .then((res) => { + setIsRunningPublicNode(res); }) - }, [extState]) + .catch((error) => { + console.error(error); + }); + }, [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 @@ -486,12 +493,12 @@ function App() { }; // Add the event listener to the root HTML document - document.documentElement.addEventListener("dblclick", handleDoubleClick); + document.documentElement.addEventListener('dblclick', handleDoubleClick); // Clean up the event listener on unmount return () => { document.documentElement.removeEventListener( - "dblclick", + 'dblclick', handleDoubleClick ); }; @@ -500,7 +507,9 @@ function App() { const resetAtomSortablePinnedAppsAtom = useResetRecoilState( sortablePinnedAppsAtom ); - const resetAtomIsUsingImportExportSettingsAtom = useResetRecoilState(isUsingImportExportSettingsAtom) + const resetAtomIsUsingImportExportSettingsAtom = useResetRecoilState( + isUsingImportExportSettingsAtom + ); const resetAtomCanSaveSettingToQdnAtom = useResetRecoilState( canSaveSettingToQdnAtom ); @@ -511,22 +520,25 @@ 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; @@ -536,21 +548,21 @@ function App() { ? window.visualViewport.height : window.innerHeight; // Set the height to the root element (usually #root) - document.getElementById("root").style.height = height + "px"; - setRootHeight(height + "px"); + document.getElementById('root').style.height = height + 'px'; + setRootHeight(height + 'px'); }; // Set the initial height resetHeight(); // Add event listeners for resize and visualViewport changes - window.addEventListener("resize", resetHeight); - window.visualViewport?.addEventListener("resize", resetHeight); + window.addEventListener('resize', resetHeight); + window.visualViewport?.addEventListener('resize', resetHeight); // Clean up the event listeners when the component unmounts return () => { - window.removeEventListener("resize", resetHeight); - window.visualViewport?.removeEventListener("resize", resetHeight); + window.removeEventListener('resize', resetHeight); + window.visualViewport?.removeEventListener('resize', resetHeight); }; }, []); const handleSetGlobalApikey = (key) => { @@ -560,48 +572,46 @@ function App() { try { setIsLoading(true); window - .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") + .sendMessage('getApiKey') .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"); - } + if (response) { + handleSetGlobalApikey(response); + setApiKey(response); } }) .catch((error) => { - console.error("Failed to get wallet info:", 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); + }); }); - }) } catch (error) { - } finally { setIsLoading(false); - } - }, []); useEffect(() => { if (extState) { @@ -609,19 +619,17 @@ 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; @@ -648,12 +656,12 @@ function App() { // }, [extState]); const address = useMemo(() => { - if (!rawWallet?.address0) return ""; + if (!rawWallet?.address0) return ''; return rawWallet.address0; }, [rawWallet]); const { getRootProps, getInputProps } = useDropzone({ accept: { - "application/json": [".json"], // Only accept JSON files + 'application/json': ['.json'], // Only accept JSON files }, maxFiles: 1, onDrop: async (acceptedFiles) => { @@ -661,8 +669,8 @@ function App() { const fileContents = await new Promise((resolve, reject) => { const reader = new FileReader(); - reader.onabort = () => reject("File reading was aborted"); - reader.onerror = () => reject("File reading has failed"); + reader.onabort = () => reject('File reading was aborted'); + reader.onerror = () => reject('File reading has failed'); reader.onload = () => { // Resolve the promise with the reader result when reading completes resolve(reader.result); @@ -676,26 +684,26 @@ function App() { let pf: any; try { - if (typeof fileContents !== "string") return; + if (typeof fileContents !== 'string') return; pf = JSON.parse(fileContents); } catch (e) {} try { const requiredFields = [ - "address0", - "salt", - "iv", - "version", - "encryptedSeed", - "mac", - "kdfThreads", + 'address0', + 'salt', + 'iv', + 'version', + 'encryptedSeed', + 'mac', + 'kdfThreads', ]; for (const field of requiredFields) { - if (!(field in pf)) throw new Error(field + " not found in JSON"); + if (!(field in pf)) throw new Error(field + ' not found in JSON'); } setRawWallet(pf); // setExtstate("authenticated"); - setExtstate("wallet-dropped"); + setExtstate('wallet-dropped'); setdecryptedWallet(null); } catch (e) { console.log(e); @@ -724,57 +732,57 @@ 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); window - .sendMessage("balance") + .sendMessage('balance') .then((response) => { if (!response?.error && !isNaN(+response)) { setBalance(response); } - + setQortBalanceLoading(false); }) .catch((error) => { - console.error("Failed to get balance:", error); + console.error('Failed to get balance:', error); setQortBalanceLoading(false); - }).finally(()=> { - balanceSetInterval() + }) + .finally(() => { + balanceSetInterval(); }); }; const getLtcBalanceFunc = () => { setLtcBalanceLoading(true); window - .sendMessage("ltcBalance") + .sendMessage('ltcBalance') .then((response) => { if (!response?.error && !isNaN(+response)) { setLtcBalance(response); @@ -782,11 +790,10 @@ function App() { setLtcBalanceLoading(false); }) .catch((error) => { - console.error("Failed to get LTC balance:", error); + console.error('Failed to get LTC balance:', error); setLtcBalanceLoading(false); }); }; - const clearAllStates = () => { setRequestConnection(null); @@ -794,19 +801,19 @@ function App() { }; const qortalRequestPermissonFromExtension = async (message, event) => { - if (message.action === "QORTAL_REQUEST_PERMISSION") { + if (message.action === 'QORTAL_REQUEST_PERMISSION') { try { if (message?.payload?.checkbox1) { qortalRequestCheckbox1Ref.current = message?.payload?.checkbox1?.value || false; } - setConfirmRequestRead(false) + setConfirmRequestRead(false); await showQortalRequestExtension(message?.payload); if (qortalRequestCheckbox1Ref.current) { event.source.postMessage( { - action: "QORTAL_REQUEST_PERMISSION_RESPONSE", + action: 'QORTAL_REQUEST_PERMISSION_RESPONSE', requestId: message?.requestId, result: { accepted: true, @@ -819,7 +826,7 @@ function App() { } event.source.postMessage( { - action: "QORTAL_REQUEST_PERMISSION_RESPONSE", + action: 'QORTAL_REQUEST_PERMISSION_RESPONSE', requestId: message?.requestId, result: { accepted: true, @@ -830,7 +837,7 @@ function App() { } catch (error) { event.source.postMessage( { - action: "QORTAL_REQUEST_PERMISSION_RESPONSE", + action: 'QORTAL_REQUEST_PERMISSION_RESPONSE', requestId: message?.requestId, result: { accepted: false, @@ -850,43 +857,43 @@ function App() { } const message = event.data; - if (message?.action === "CHECK_FOCUS") { + if (message?.action === 'CHECK_FOCUS') { event.source.postMessage( - { action: "CHECK_FOCUS_RESPONSE", isFocused: isFocusedRef.current }, + { action: 'CHECK_FOCUS_RESPONSE', isFocused: isFocusedRef.current }, event.origin ); - } else if (message.action === "NOTIFICATION_OPEN_DIRECT") { - executeEvent("openDirectMessage", { + } else if (message.action === 'NOTIFICATION_OPEN_DIRECT') { + executeEvent('openDirectMessage', { from: message.payload.from, }); - } else if (message.action === "NOTIFICATION_OPEN_GROUP") { - executeEvent("openGroupMessage", { + } else if (message.action === 'NOTIFICATION_OPEN_GROUP') { + executeEvent('openGroupMessage', { from: message.payload.from, }); - } else if (message.action === "NOTIFICATION_OPEN_ANNOUNCEMENT_GROUP") { - executeEvent("openGroupAnnouncement", { + } else if (message.action === 'NOTIFICATION_OPEN_ANNOUNCEMENT_GROUP') { + executeEvent('openGroupAnnouncement', { from: message.payload.from, }); - } else if (message.action === "NOTIFICATION_OPEN_THREAD_NEW_POST") { - executeEvent("openThreadNewPost", { + } else if (message.action === 'NOTIFICATION_OPEN_THREAD_NEW_POST') { + executeEvent('openThreadNewPost', { data: message.payload.data, }); } else if ( - message.action === "QORTAL_REQUEST_PERMISSION" && + message.action === 'QORTAL_REQUEST_PERMISSION' && message?.isFromExtension ) { qortalRequestPermissonFromExtension(message, event); - } else if (message?.action === "getFileFromIndexedDB") { + } else if (message?.action === 'getFileFromIndexedDB') { handleGetFileFromIndexedDB(event); } }; // Attach the event listener - window.addEventListener("message", messageHandler); + window.addEventListener('message', messageHandler); // Clean up the event listener on component unmount return () => { - window.removeEventListener("message", messageHandler); + window.removeEventListener('message', messageHandler); }; }, []); @@ -906,7 +913,6 @@ function App() { // REMOVED FOR MOBILE APP }; - const getUserInfo = useCallback(async (useTimer?: boolean) => { try { if (useTimer) { @@ -917,14 +923,14 @@ function App() { }); } window - .sendMessage("userInfo") + .sendMessage('userInfo') .then((response) => { if (response && !response.error) { setUserInfo(response); } }) .catch((error) => { - console.error("Failed to get user info:", error); + console.error('Failed to get user info:', error); }); getBalanceFunc(); @@ -938,13 +944,13 @@ function App() { useEffect(() => { return () => { - console.log("exit"); + console.log('exit'); }; }, []); useEffect(() => { if ( - authenticatedMode === "ltc" && + authenticatedMode === 'ltc' && !ltcBalanceLoading && ltcBalance === null ) { @@ -954,9 +960,9 @@ function App() { const confirmPasswordToDownload = async () => { try { - setWalletToBeDownloadedError(""); + setWalletToBeDownloadedError(''); if (!walletToBeDownloadedPassword) { - setSendPaymentError("Please enter your password"); + setSendPaymentError('Please enter your password'); return; } setIsLoading(true); @@ -985,40 +991,41 @@ 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 { if (!walletToBeDownloadedPassword) { - setWalletToBeDownloadedError("Please enter a password"); + setWalletToBeDownloadedError('Please enter a password'); return; } if (!walletToBeDownloadedPasswordConfirm) { - setWalletToBeDownloadedError("Please confirm your password"); + setWalletToBeDownloadedError('Please confirm your password'); return; } if ( walletToBeDownloadedPasswordConfirm !== walletToBeDownloadedPassword ) { - setWalletToBeDownloadedError("Password fields do not match!"); + setWalletToBeDownloadedError('Password fields do not match!'); return; } setIsLoading(true); @@ -1034,21 +1041,21 @@ function App() { () => {} ); window - .sendMessage("decryptWallet", { + .sendMessage('decryptWallet', { password: walletToBeDownloadedPassword, wallet, }) .then((response) => { if (response && !response.error) { setRawWallet(wallet); - saveWalletToLocalStorage(wallet) + saveWalletToLocalStorage(wallet); setWalletToBeDownloaded({ wallet, qortAddress: wallet.address0, }); window - .sendMessage("userInfo") + .sendMessage('userInfo') .then((response2) => { setIsLoading(false); if (response2 && !response2.error) { @@ -1057,7 +1064,7 @@ function App() { }) .catch((error) => { setIsLoading(false); - console.error("Failed to get user info:", error); + console.error('Failed to get user info:', error); }); getBalanceFunc(); @@ -1068,7 +1075,7 @@ function App() { }) .catch((error) => { setIsLoading(false); - console.error("Failed to decrypt wallet:", error); + console.error('Failed to decrypt wallet:', error); }); } catch (error: any) { setWalletToBeDownloadedError(error?.message); @@ -1081,50 +1088,49 @@ function App() { if (hasSettingsChanged) { await showUnsavedChanges({ 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.", + '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 - .sendMessage("logout", {}) + .sendMessage('logout', {}) .then((response) => { if (response) { - executeEvent("logout-event", {}); + executeEvent('logout-event', {}); resetAllStates(); } }) .catch((error) => { console.error( - "Failed to log out:", - error.message || "An error occurred" + 'Failed to log out:', + error.message || 'An error occurred' ); }); } catch (error) {} }; const returnToMain = () => { - setPaymentTo(""); + setPaymentTo(''); setPaymentAmount(0); - setPaymentPassword(""); - setSendPaymentError(""); - setSendPaymentSuccess(""); + setPaymentPassword(''); + setSendPaymentError(''); + setSendPaymentSuccess(''); setCountdown(null); setWalletToBeDownloaded(null); - setWalletToBeDownloadedPassword(""); - setShowSeed(false) - setCreationStep(1) - setExtstate("authenticated"); + setWalletToBeDownloadedPassword(''); + setShowSeed(false); + setCreationStep(1); + setExtstate('authenticated'); setIsOpenSendQort(false); setIsOpenSendQortSuccess(false); }; const resetAllStates = () => { - setExtstate("not-authenticated"); - setAuthenticatedMode("qort"); + setExtstate('not-authenticated'); + setAuthenticatedMode('qort'); setBackupjson(null); setRawWallet(null); setdecryptedWallet(null); @@ -1134,25 +1140,25 @@ function App() { setUserInfo(null); setBalance(null); setLtcBalance(null); - setPaymentTo(""); + setPaymentTo(''); setPaymentAmount(0); - setPaymentPassword(""); - setSendPaymentError(""); - setSendPaymentSuccess(""); + setPaymentPassword(''); + setSendPaymentError(''); + setSendPaymentSuccess(''); setCountdown(null); setWalletToBeDownloaded(null); - setWalletToBeDownloadedPassword(""); - setShowSeed(false) - setCreationStep(1) + setWalletToBeDownloadedPassword(''); + setShowSeed(false); + setCreationStep(1); - setWalletToBeDownloadedPasswordConfirm(""); - setWalletToBeDownloadedError(""); + setWalletToBeDownloadedPasswordConfirm(''); + setWalletToBeDownloadedError(''); setSendqortState(null); setHasLocalNode(false); setTxList([]); setMemberGroups([]); resetAllRecoil(); - if(balanceSetIntervalRef?.current){ + if (balanceSetIntervalRef?.current) { clearInterval(balanceSetIntervalRef?.current); } }; @@ -1165,7 +1171,7 @@ function App() { const authenticateWallet = async () => { try { setIsLoading(true); - setWalletToBeDecryptedError(""); + setWalletToBeDecryptedError(''); await new Promise((res) => { setTimeout(() => { res(); @@ -1173,7 +1179,7 @@ function App() { }); window .sendMessage( - "decryptWallet", + 'decryptWallet', { password: authenticatePassword, wallet: rawWallet, @@ -1182,12 +1188,12 @@ function App() { ) .then((response) => { if (response && !response.error) { - setAuthenticatePassword(""); - setExtstate("authenticated"); - setWalletToBeDecryptedError(""); + setAuthenticatePassword(''); + setExtstate('authenticated'); + setWalletToBeDecryptedError(''); window - .sendMessage("userInfo") + .sendMessage('userInfo') .then((response) => { setIsLoading(false); if (response && !response.error) { @@ -1196,20 +1202,20 @@ function App() { }) .catch((error) => { setIsLoading(false); - console.error("Failed to get user info:", error); + console.error('Failed to get user info:', error); }); getBalanceFunc(); window - .sendMessage("getWalletInfo") + .sendMessage('getWalletInfo') .then((response) => { if (response && response.walletInfo) { setRawWallet(response.walletInfo); } }) .catch((error) => { - console.error("Failed to get wallet info:", error); + console.error('Failed to get wallet info:', error); }); } else if (response?.error) { setIsLoading(false); @@ -1218,10 +1224,10 @@ function App() { }) .catch((error) => { setIsLoading(false); - console.error("Failed to decrypt wallet:", error); + console.error('Failed to decrypt wallet:', error); }); } catch (error) { - setWalletToBeDecryptedError("Unable to authenticate. Wrong password"); + setWalletToBeDecryptedError('Unable to authenticate. Wrong password'); } }; @@ -1231,10 +1237,10 @@ function App() { const handleFocus = () => { setIsFocused(true); if (isMobile) { - window.sendMessage("clearAllNotifications", {}).catch((error) => { + window.sendMessage('clearAllNotifications', {}).catch((error) => { console.error( - "Failed to clear notifications:", - error.message || "An error occurred" + 'Failed to clear notifications:', + error.message || 'An error occurred' ); }); } @@ -1246,18 +1252,18 @@ function App() { }; // Attach the event listeners - window.addEventListener("focus", handleFocus); - window.addEventListener("blur", handleBlur); + window.addEventListener('focus', handleFocus); + window.addEventListener('blur', handleBlur); // Optionally, listen for visibility changes const handleVisibilityChange = () => { - if (document.visibilityState === "visible") { + if (document.visibilityState === 'visible') { setIsFocused(true); if (isMobile) { - window.sendMessage("clearAllNotifications", {}).catch((error) => { + window.sendMessage('clearAllNotifications', {}).catch((error) => { console.error( - "Failed to clear notifications:", - error.message || "An error occurred" + 'Failed to clear notifications:', + error.message || 'An error occurred' ); }); } @@ -1266,13 +1272,13 @@ function App() { } }; - document.addEventListener("visibilitychange", handleVisibilityChange); + document.addEventListener('visibilitychange', handleVisibilityChange); // Cleanup the event listeners on component unmount return () => { - window.removeEventListener("focus", handleFocus); - window.removeEventListener("blur", handleBlur); - document.removeEventListener("visibilitychange", handleVisibilityChange); + window.removeEventListener('focus', handleFocus); + window.removeEventListener('blur', handleBlur); + document.removeEventListener('visibilitychange', handleVisibilityChange); }; }, []); @@ -1282,15 +1288,15 @@ function App() { setOpenSnack(true); setInfoSnack({ type, - message + message, }); }; useEffect(() => { - subscribeToEvent("openGlobalSnackBar", openGlobalSnackBarFunc); + subscribeToEvent('openGlobalSnackBar', openGlobalSnackBarFunc); return () => { - unsubscribeFromEvent("openGlobalSnackBar", openGlobalSnackBarFunc); + unsubscribeFromEvent('openGlobalSnackBar', openGlobalSnackBarFunc); }; }, []); @@ -1302,268 +1308,285 @@ function App() { }; useEffect(() => { - subscribeToEvent("openPaymentInternal", openPaymentInternal); + subscribeToEvent('openPaymentInternal', openPaymentInternal); return () => { - unsubscribeFromEvent("openPaymentInternal", openPaymentInternal); + unsubscribeFromEvent('openPaymentInternal', openPaymentInternal); }; }, []); - - - const renderProfileLeft = ()=> { - - return - - - {authenticatedMode === "qort" && ( - LITECOIN WALLET} - placement="left" - arrow - sx={{ fontSize: "24" }} - slotProps={{ - tooltip: { - sx: { - color: "#ffffff", - backgroundColor: "#444444", - }, + const renderProfileLeft = () => { + return ( + + + + {authenticatedMode === 'qort' && ( + + LITECOIN WALLET + + } + placement="left" + arrow + sx={{ fontSize: '24' }} + slotProps={{ + tooltip: { + sx: { + color: '#ffffff', + backgroundColor: '#444444', }, - arrow: { - sx: { - color: "#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 && ( - - - {ltcBalance} LTC - - { + 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 && ( + + + {ltcBalance} LTC + + + + )} + + + ) : ( + <> + - + + + {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', {}); }} > - {userInfo?.name} + Get QORT at Q-Trade - - - - {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 ( {isMobile && ( )} - {desktopViewMode !== "apps" && - desktopViewMode !== "dev" && - desktopViewMode !== "chat" && ( - <> - {renderProfileLeft()} - - )} + {desktopViewMode !== 'apps' && + desktopViewMode !== 'dev' && + desktopViewMode !== 'chat' && <>{renderProfileLeft()}} - + {!isMobile && ( <> LOG OUT} + title={ + + LOG OUT + + } placement="left" arrow - sx={{ fontSize: "24" }} + sx={{ fontSize: '24' }} slotProps={{ tooltip: { sx: { - color: "#ffffff", - backgroundColor: "#444444", + color: '#ffffff', + backgroundColor: '#444444', }, }, arrow: { sx: { - color: "#444444", + color: '#444444', }, }, }} @@ -1630,9 +1659,9 @@ function App() { setIsOpenDrawerProfile(false); }} style={{ - cursor: "pointer", + cursor: 'pointer', width: '20px', - height: 'auto' + height: 'auto', }} /> @@ -1646,27 +1675,40 @@ function App() { }} > SETTINGS} + title={ + + SETTINGS + + } placement="left" arrow - sx={{ fontSize: "24" }} + sx={{ fontSize: '24' }} slotProps={{ tooltip: { sx: { - color: "#ffffff", - backgroundColor: "#444444", + color: '#ffffff', + backgroundColor: '#444444', }, }, arrow: { sx: { - color: "#444444", + color: '#444444', }, }, }} > @@ -1678,27 +1720,40 @@ function App() { }} > USER LOOKUP} + title={ + + USER LOOKUP + + } placement="left" arrow - sx={{ fontSize: "24" }} + sx={{ fontSize: '24' }} slotProps={{ tooltip: { sx: { - color: "#ffffff", - backgroundColor: "#444444", + color: '#ffffff', + backgroundColor: '#444444', }, }, arrow: { sx: { - color: "#444444", + color: '#444444', }, }, }} > @@ -1706,153 +1761,186 @@ function App() { { - executeEvent('openWalletsApp', {}) + executeEvent('openWalletsApp', {}); }} > WALLETS} + title={ + + WALLETS + + } placement="left" arrow - sx={{ fontSize: "24" }} + sx={{ fontSize: '24' }} slotProps={{ tooltip: { sx: { - color: "#ffffff", - backgroundColor: "#444444", + color: '#ffffff', + backgroundColor: '#444444', }, }, arrow: { sx: { - color: "#444444", + color: '#444444', }, }, }} > - - + {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" && isMainWindow && ( - - - - - + {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" }} + sx={{ fontSize: '24' }} slotProps={{ tooltip: { sx: { - color: "#ffffff", - backgroundColor: "#444444", + color: '#ffffff', + backgroundColor: '#444444', }, }, arrow: { sx: { - color: "#444444", + color: '#444444', }, }, }} @@ -1860,74 +1948,92 @@ 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", - }, + {(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', }, - 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", - }, - }, - }} - > - { - setExtstate("download-wallet"); - setIsOpenDrawerProfile(false); + }, + }} + > + + + + )} + + + + BACKUP WALLET + + } + placement="left" + arrow + sx={{ fontSize: '24' }} + slotProps={{ + tooltip: { + sx: { + color: '#ffffff', + backgroundColor: '#444444', + }, + }, + arrow: { + sx: { + color: '#444444', + }, + }, }} - src={Download} - style={{ - cursor: "pointer", - width: '20px' - }} - /> - + > + { + setExtstate('download-wallet'); + setIsOpenDrawerProfile(false); + }} + src={Download} + style={{ + cursor: 'pointer', + width: '20px', + }} + /> + - + ); @@ -1936,7 +2042,7 @@ function App() { return ( - - - {extState === "not-authenticated" && ( - - )} - {/* {extState !== "not-authenticated" && ( + + + {extState === 'not-authenticated' && ( + + )} + {/* {extState !== "not-authenticated" && ( )} */} - {extState === "authenticated" && isMainWindow && ( - - - - {!isMobile && renderProfile()} - - - - - )} - {isOpenSendQort && isMainWindow && ( - - - - - - - { - setIsOpenSendQort(false); - setIsOpenSendQortSuccess(true); - }} - defaultPaymentTo={paymentTo} - /> - - )} - - {isShowQortalRequest && !isMainWindow && ( - <> - - - - {messageQortalRequest?.text1} - - - {messageQortalRequest?.text2 && ( - <> - - - - {messageQortalRequest?.text2} - - - - - )} - {messageQortalRequest?.text3 && ( - <> - - - {messageQortalRequest?.text3} - - - - - )} - - {messageQortalRequest?.text4 && ( - - {messageQortalRequest?.text4} - + + {!isMobile && renderProfile()} - )} - - {messageQortalRequest?.html && ( -
- )} - - - + )} + {isOpenSendQort && isMainWindow && ( + - {messageQortalRequest?.highlightedText} - - - {messageQortalRequest?.fee && ( - <> - - - - {"Fee: "} - {messageQortalRequest?.fee} - {" QORT"} - - - - )} - {messageQortalRequest?.checkbox1 && ( + - { - qortalRequestCheckbox1Ref.current = e.target.checked; - }} - edge="start" - tabIndex={-1} - disableRipple - defaultChecked={messageQortalRequest?.checkbox1?.value} - sx={{ - "&.Mui-checked": { - color: "white", // Customize the color when checked - }, - "& .MuiSvgIcon-root": { - color: "white", - }, - }} - /> - - - {messageQortalRequest?.checkbox1?.label} - - - )} - - - - onOkQortalRequest("accepted")} - > - accept - - onCancelQortalRequest()} - > - 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) - } + onClick={returnToMain} /> - - - Confirm Wallet Password - - - - setWalletToBeDownloadedPasswordConfirm(e.target.value) - } - /> - - There is no minimum length requirement - + + + { + setIsOpenSendQort(false); + setIsOpenSendQortSuccess(true); + }} + defaultPaymentTo={paymentTo} + /> + + )} - - 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}} - - + {isShowQortalRequest && !isMainWindow && ( + <> + - {messageQortalRequestExtension?.text1} + {messageQortalRequest?.text1} - {messageQortalRequestExtension?.text2 && ( + {messageQortalRequest?.text2 && ( <> - {messageQortalRequestExtension?.text2} + {messageQortalRequest?.text2} )} - {messageQortalRequestExtension?.text3 && ( + {messageQortalRequest?.text3 && ( <> - {messageQortalRequestExtension?.text3} + {messageQortalRequest?.text3} )} - {messageQortalRequestExtension?.text4 && ( + {messageQortalRequest?.text4 && ( - {messageQortalRequestExtension?.text4} + {messageQortalRequest?.text4} )} - {messageQortalRequestExtension?.html && ( + {messageQortalRequest?.html && (
)} - {messageQortalRequestExtension?.highlightedText} + {messageQortalRequest?.highlightedText} - {messageQortalRequestExtension?.json && ( - <> - - - - - - - )} - - {messageQortalRequestExtension?.fee && ( + {messageQortalRequest?.fee && ( <> - {"Fee: "} - {messageQortalRequestExtension?.fee} - {" QORT"} + {'Fee: '} + {messageQortalRequest?.fee} + {' QORT'} )} - {messageQortalRequestExtension?.appFee && ( - <> - - {"App Fee: "} - {messageQortalRequestExtension?.appFee} - {" QORT"} - - - - )} - {messageQortalRequestExtension?.foreignFee && ( - <> - - - - {"Foreign Fee: "} - {messageQortalRequestExtension?.foreignFee} - - - - )} - {messageQortalRequestExtension?.checkbox1 && ( + {messageQortalRequest?.checkbox1 && ( - {messageQortalRequestExtension?.checkbox1?.label} + {messageQortalRequest?.checkbox1?.label} )} -{messageQortalRequestExtension?.confirmCheckbox && ( - setConfirmRequestRead(e.target.checked)} - checked={confirmRequestRead} - edge="start" - tabIndex={-1} - disableRipple - sx={{ - "&.Mui-checked": { - color: "white", - }, - "& .MuiSvgIcon-root": { - color: "white", - }, - }} - /> - } - label={ - - - I have read this request - - - - } - /> - )} - - { - if(messageQortalRequestExtension?.confirmCheckbox && !confirmRequestRead) return - onOkQortalRequestExtension("accepted") + minWidth: '102px', }} + onClick={() => onOkQortalRequest('accepted')} > accept - - + onCancelQortalRequestExtension()} + onClick={() => onCancelQortalRequest()} > 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(); + }} + /> + + + + )} + {rawWallet && extState === 'wallet-dropped' && ( + <> + + + { + setRawWallet(null); + setExtstate('wallets'); + logoutFunc(); + }} + /> + + +
+ +
+ + + + {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 + -
- )} - {isSettingsOpen && ( - - )} - - - {renderProfileLeft()} - - - - + )} + {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} + + + )} + + {messageQortalRequestExtension?.confirmCheckbox && ( + setConfirmRequestRead(e.target.checked)} + checked={confirmRequestRead} + edge="start" + tabIndex={-1} + disableRipple + sx={{ + '&.Mui-checked': { + color: 'white', + }, + '& .MuiSvgIcon-root': { + color: 'white', + }, + }} + /> + } + label={ + + + I have read this request + + + + } + /> + )} + + + + { + if ( + messageQortalRequestExtension?.confirmCheckbox && + !confirmRequestRead + ) + return; + onOkQortalRequestExtension('accepted'); + }} + > + accept + + onCancelQortalRequestExtension()} + > + decline + + + {sendPaymentError} + +
+ )} + {isSettingsOpen && ( + + )} + + + {renderProfileLeft()} + + + + - {extState === "create-wallet" && walletToBeDownloaded && ( - { - showTutorial('important-information', true) - }} sx={{ - position: 'fixed', - bottom: '25px', - right: '25px' - }}> - - + {extState === 'create-wallet' && walletToBeDownloaded && ( + { + showTutorial('important-information', true); + }} + sx={{ + position: 'fixed', + bottom: '25px', + right: '25px', + }} + > + + )} - {isOpenMinting && ( - - )} + {isOpenMinting && ( + + )} + + ); } -export default App; \ No newline at end of file +export default App; diff --git a/src/Wallets.tsx b/src/Wallets.tsx index 4211fd0..fa65b5a 100644 --- a/src/Wallets.tsx +++ b/src/Wallets.tsx @@ -1,48 +1,58 @@ -import React, { useContext, useEffect, useRef, useState } from "react"; -import List from "@mui/material/List"; -import ListItem from "@mui/material/ListItem"; -import Divider from "@mui/material/Divider"; -import ListItemText from "@mui/material/ListItemText"; -import ListItemAvatar from "@mui/material/ListItemAvatar"; -import Avatar from "@mui/material/Avatar"; -import Typography from "@mui/material/Typography"; -import { Box, Button, ButtonBase, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Input } from "@mui/material"; -import { CustomButton } from "./App-styles"; -import { useDropzone } from "react-dropzone"; -import EditIcon from "@mui/icons-material/Edit"; -import { Label } from "./components/Group/AddGroup"; -import { Spacer } from "./common/Spacer"; -import { getWallets, storeWallets, walletVersion } from "./background"; -import { useModal } from "./common/useModal"; -import PhraseWallet from "./utils/generateWallet/phrase-wallet"; -import { decryptStoredWalletFromSeedPhrase } from "./utils/decryptWallet"; -import { crypto } from "./constants/decryptWallet"; -import { LoadingButton } from "@mui/lab"; -import { PasswordField } from "./components"; -import { HtmlTooltip } from "./ExtStates/NotAuthenticated"; -import { GlobalContext } from "./App"; +import React, { useContext, useEffect, useState } from 'react'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import Divider from '@mui/material/Divider'; +import ListItemText from '@mui/material/ListItemText'; +import ListItemAvatar from '@mui/material/ListItemAvatar'; +import Avatar from '@mui/material/Avatar'; +import Typography from '@mui/material/Typography'; +import { + Box, + Button, + ButtonBase, + Dialog, + DialogActions, + DialogContent, + DialogTitle, + IconButton, + Input, +} from '@mui/material'; +import { CustomButton } from './App-styles'; +import { useDropzone } from 'react-dropzone'; +import EditIcon from '@mui/icons-material/Edit'; +import { Label } from './components/Group/AddGroup'; +import { Spacer } from './common/Spacer'; +import { getWallets, storeWallets, walletVersion } from './background'; +import { useModal } from './common/useModal'; +import PhraseWallet from './utils/generateWallet/phrase-wallet'; +import { decryptStoredWalletFromSeedPhrase } from './utils/decryptWallet'; +import { crypto } from './constants/decryptWallet'; +import { LoadingButton } from '@mui/lab'; +import { PasswordField } from './components'; +import { HtmlTooltip } from './ExtStates/NotAuthenticated'; +import { GlobalContext } from './App'; -const parsefilenameQortal = (filename)=> { - return filename.startsWith("qortal_backup_") ? filename.slice(14) : filename; - } +const parsefilenameQortal = (filename) => { + return filename.startsWith('qortal_backup_') ? filename.slice(14) : filename; +}; export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => { const [wallets, setWallets] = useState([]); const [isLoading, setIsLoading] = useState(true); - const [seedValue, setSeedValue] = useState(""); - const [seedName, setSeedName] = useState(""); - const [seedError, setSeedError] = useState(""); - const { hasSeenGettingStarted } = useContext(GlobalContext); + const [seedValue, setSeedValue] = useState(''); + const [seedName, setSeedName] = useState(''); + const [seedError, setSeedError] = useState(''); + const { hasSeenGettingStarted } = useContext(GlobalContext); - const [password, setPassword] = useState(""); + const [password, setPassword] = useState(''); const [isOpenSeedModal, setIsOpenSeedModal] = useState(false); const [isLoadingEncryptSeed, setIsLoadingEncryptSeed] = useState(false); - const { isShow, onCancel, onOk, show, } = useModal(); + const { isShow, onCancel, onOk, show } = useModal(); const { getRootProps, getInputProps } = useDropzone({ accept: { - "application/json": [".json"], // Only accept JSON files + 'application/json': ['.json'], // Only accept JSON files }, onDrop: async (acceptedFiles) => { const files: any = acceptedFiles; @@ -53,8 +63,8 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => { const fileContents = await new Promise((resolve, reject) => { const reader = new FileReader(); - reader.onabort = () => reject("File reading was aborted"); - reader.onerror = () => reject("File reading has failed"); + reader.onabort = () => reject('File reading was aborted'); + reader.onerror = () => reject('File reading has failed'); reader.onload = () => { // Resolve the promise with the reader result when reading completes resolve(reader.result); @@ -63,9 +73,9 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => { // Read the file as text reader.readAsText(file); }); - if (typeof fileContents !== "string") continue; - const parsedData = JSON.parse(fileContents) - importedWallets.push({...parsedData, filename: file?.name}); + if (typeof fileContents !== 'string') continue; + const parsedData = JSON.parse(fileContents); + importedWallets.push({ ...parsedData, filename: file?.name }); } catch (error) { console.error(error); } @@ -108,83 +118,85 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => { }); }; - const handleSetSeedValue = async ()=> { + const handleSetSeedValue = async () => { try { - setIsOpenSeedModal(true) - const {seedValue, seedName, password} = await show({ - message: "", - publishFee: "", + setIsOpenSeedModal(true); + const { seedValue, seedName, password } = await show({ + message: '', + publishFee: '', }); - setIsLoadingEncryptSeed(true) - const res = await decryptStoredWalletFromSeedPhrase(seedValue) + setIsLoadingEncryptSeed(true); + const res = await decryptStoredWalletFromSeedPhrase(seedValue); const wallet2 = new PhraseWallet(res, walletVersion); const wallet = await wallet2.generateSaveWalletData( password, crypto.kdfThreads, () => {} ); - if(wallet?.address0){ - setWallets([...wallets, { - ...wallet, - name: seedName - }]); - setIsOpenSeedModal(false) - setSeedValue('') - setSeedName('') - setPassword('') - setSeedError('') + if (wallet?.address0) { + setWallets([ + ...wallets, + { + ...wallet, + name: seedName, + }, + ]); + setIsOpenSeedModal(false); + setSeedValue(''); + setSeedName(''); + setPassword(''); + setSeedError(''); } else { - setSeedError('Could not create account.') + setSeedError('Could not create account.'); } - } catch (error) { - setSeedError(error?.message || 'Could not create account.') + setSeedError(error?.message || 'Could not create account.'); } finally { - setIsLoadingEncryptSeed(false) + setIsLoadingEncryptSeed(false); } - } + }; const selectedWalletFunc = (wallet) => { setRawWallet(wallet); - setExtState("wallet-dropped"); + setExtState('wallet-dropped'); }; - useEffect(()=> { - setIsLoading(true) - getWallets().then((res)=> { - - if(res && Array.isArray(res)){ - setWallets(res) + useEffect(() => { + setIsLoading(true); + getWallets() + .then((res) => { + if (res && Array.isArray(res)) { + setWallets(res); } - setIsLoading(false) - }).catch((error)=> { - console.error(error) - setIsLoading(false) - }) - }, []) + setIsLoading(false); + }) + .catch((error) => { + console.error(error); + setIsLoading(false); + }); + }, []); - useEffect(()=> { - if(!isLoading && wallets && Array.isArray(wallets)){ - storeWallets(wallets) + useEffect(() => { + if (!isLoading && wallets && Array.isArray(wallets)) { + storeWallets(wallets); } - }, [wallets, isLoading]) + }, [wallets, isLoading]); - if(isLoading) return null + if (isLoading) return null; return (
- {(wallets?.length === 0 || - !wallets) ? ( - <> - No accounts saved - - - ): ( - <> - Your saved accounts - - - )} + {wallets?.length === 0 || !wallets ? ( + <> + No accounts saved + + + ) : ( + <> + Your saved accounts + + + )} {rawWallet && ( @@ -196,174 +208,198 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => { )} {wallets?.length > 0 && ( - - {wallets?.map((wallet, idx) => { - return ( - <> - - - - ); - })} - + + {wallets?.map((wallet, idx) => { + return ( + <> + + + + ); + })} + )} - + - - Already have a Qortal account? Enter your secret backup phrase here to access it. This phrase is one of the ways to recover your account. - - } - > - - - Add seed-phrase - - - Use this option to connect additional Qortal wallets you've already made, in order to login with them afterwards. You will need access to your backup JSON file in order to do so. - - } - > - - - Add account - + disableHoverListener={hasSeenGettingStarted === true} + title={ + + + Already have a Qortal account? Enter your secret backup phrase + here to access it. This phrase is one of the ways to recover + your account. + + + } + > + + Add seed-phrase + + + + + + Use this option to connect additional Qortal wallets you've + already made, in order to login with them afterwards. You will + need access to your backup JSON file in order to do so. + + + } + > + + + Add account + - { - if (e.key === 'Enter' && seedValue && seedName && password) { - onOk({seedValue, seedName, password}); - } - }} - > - - Type or paste in your seed-phrase - - - + { + if (e.key === 'Enter' && seedValue && seedName && password) { + onOk({ seedValue, seedName, password }); + } + }} + > + + Type or paste in your seed-phrase + + + + - setSeedName(e.target.value)} - /> - - - setSeedName(e.target.value)} + /> + + + + + setSeedValue(e.target.value)} autoComplete="off" sx={{ - width: '100%' + width: '100%', }} /> - - - + + + setPassword(e.target.value)} autoComplete="off" sx={{ - width: '100%' + width: '100%', }} /> - - - - - - - + + + + { - if(!seedValue || !seedName || !password) return - onOk({seedValue, seedName, password}); - }} - autoFocus - > - Add - - {seedError} - - - + disabled={!seedValue || !seedName || !password} + variant="contained" + onClick={() => { + if (!seedValue || !seedName || !password) return; + onOk({ seedValue, seedName, password }); + }} + autoFocus + > + Add + + + {seedError} + + +
- ); }; const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => { - const [name, setName] = useState(""); - const [note, setNote] = useState(""); + const [name, setName] = useState(''); + const [note, setNote] = useState(''); const [isEdit, setIsEdit] = useState(false); useEffect(() => { @@ -382,71 +418,81 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => { }} sx={{ width: '100%', - padding: '10px' + padding: '10px', }} - > {wallet?.address0} {wallet?.note} - Login + + Login + } /> { - e.stopPropagation(); - setIsEdit(true); - }} - edge="end" - aria-label="edit" - > - - + sx={{ + alignSelf: 'flex-start', + }} + onClick={(e) => { + e.stopPropagation(); + setIsEdit(true); + }} + edge="end" + aria-label="edit" + > + + {isEdit && ( @@ -455,10 +501,12 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => { value={name} onChange={(e) => setName(e.target.value)} sx={{ - width: "100%", + width: '100%', }} /> + + { maxLength: 100, }} sx={{ - width: "100%", + width: '100%', }} /> + + - - + {combinedListTempAndReal.map((message, index, list) => { let fullMessage = message; if (hashMapMailMessages[message?.identifier]) { fullMessage = hashMapMailMessages[message.identifier]; - if (fullMessage?.error) { return ( {fullMessage?.error} - ); @@ -855,23 +865,23 @@ export const Thread = ({ return ( Downloading from QDN - ); })} - + {!hasLastPage && !isLoading && ( <> - - - - - + First + + + + - -
+ + + +
diff --git a/src/components/PasswordField/PasswordField.tsx b/src/components/PasswordField/PasswordField.tsx index 0c3e8b7..8a96b17 100644 --- a/src/components/PasswordField/PasswordField.tsx +++ b/src/components/PasswordField/PasswordField.tsx @@ -4,56 +4,59 @@ import { TextField, TextFieldProps, styled, -} from "@mui/material"; -import { forwardRef, useState } from "react"; -import VisibilityOffIcon from "@mui/icons-material/VisibilityOff"; -import VisibilityIcon from "@mui/icons-material/Visibility"; + useTheme, +} from '@mui/material'; +import { forwardRef, useState } from 'react'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; +import VisibilityIcon from '@mui/icons-material/Visibility'; export const CustomInput = styled(TextField)(({ theme }) => ({ - width: "183px", - borderRadius: "5px", - backgroundColor: theme.palette.background.paper, - outline: "none", - input: { - fontSize: 10, - fontFamily: "Inter", - fontWeight: 400, - color: theme.palette.text.primary, - "&::placeholder": { - fontSize: 16, - color: theme.palette.text.disabled, - }, - outline: "none", - padding: "10px", + width: '183px', + borderRadius: '5px', + backgroundColor: theme.palette.background.paper, + outline: 'none', + input: { + fontSize: 10, + fontFamily: 'Inter', + fontWeight: 400, + color: theme.palette.text.primary, + '&::placeholder': { + fontSize: 16, + color: theme.palette.text.disabled, }, - "& .MuiOutlinedInput-root": { - "& fieldset": { - border: `0.5px solid ${theme.palette.divider}`, - }, - "&:hover fieldset": { - border: `0.5px solid ${theme.palette.divider}`, - }, - "&.Mui-focused fieldset": { - border: `0.5px solid ${theme.palette.divider}`, - }, + outline: 'none', + padding: '10px', + }, + '& .MuiOutlinedInput-root': { + '& fieldset': { + border: `0.5px solid ${theme.palette.divider}`, }, - "& .MuiInput-underline:before": { - borderBottom: "none", + '&:hover fieldset': { + border: `0.5px solid ${theme.palette.divider}`, }, - "& .MuiInput-underline:hover:not(.Mui-disabled):before": { - borderBottom: "none", + '&.Mui-focused fieldset': { + border: `0.5px solid ${theme.palette.divider}`, }, - "& .MuiInput-underline:after": { - borderBottom: "none", - }, - })); + }, + '& .MuiInput-underline:before': { + borderBottom: 'none', + }, + '& .MuiInput-underline:hover:not(.Mui-disabled):before': { + borderBottom: 'none', + }, + '& .MuiInput-underline:after': { + borderBottom: 'none', + }, +})); export const PasswordField = forwardRef( ({ ...props }, ref) => { const [canViewPassword, setCanViewPassword] = useState(false); + const theme = useTheme(); + return ( ( > @@ -81,7 +87,10 @@ export const PasswordField = forwardRef( >