diff --git a/src/ExtStates/NotAuthenticated.tsx b/src/ExtStates/NotAuthenticated.tsx index 8625495..bfb33d4 100644 --- a/src/ExtStates/NotAuthenticated.tsx +++ b/src/ExtStates/NotAuthenticated.tsx @@ -1,11 +1,16 @@ -import React, { useCallback, useContext, useEffect, useRef, useState } from "react"; -import { Spacer } from "../common/Spacer"; -import { CustomButton, TextItalic, TextP, TextSpan } from "../App-styles"; +import React, { + useCallback, + useContext, + useEffect, + useRef, + useState, +} from 'react'; +import { Spacer } from '../common/Spacer'; +import { CustomButton, TextP, TextSpan } from '../App-styles'; import { Box, Button, ButtonBase, - Checkbox, Dialog, DialogActions, DialogContent, @@ -16,22 +21,20 @@ import { Switch, TextField, Typography, -} from "@mui/material"; -import Logo1 from "../assets/svgs/Logo1.svg"; -import Logo1Dark from "../assets/svgs/Logo1Dark.svg"; -import Info from "../assets/svgs/Info.svg"; + useTheme, +} from '@mui/material'; +import Logo1Dark from '../assets/svgs/Logo1Dark.svg'; import HelpIcon from '@mui/icons-material/Help'; -import { CustomizedSnackbars } from "../components/Snackbar/Snackbar"; -import { set } from "lodash"; -import { cleanUrl, gateways, isUsingLocal } from "../background"; -import { GlobalContext } from "../App"; +import { CustomizedSnackbars } from '../components/Snackbar/Snackbar'; +import { cleanUrl, gateways } from '../background'; +import { GlobalContext } from '../App'; import Tooltip, { TooltipProps, tooltipClasses } from '@mui/material/Tooltip'; +import ThemeSelector from '../components/Theme/ThemeSelector'; const manifestData = { - version: "0.5.3", + version: '0.5.3', }; - export const HtmlTooltip = styled(({ className, ...props }: TooltipProps) => ( ))(({ theme }) => ({ @@ -47,20 +50,18 @@ function removeTrailingSlash(url) { return url.replace(/\/+$/, ''); } - export const NotAuthenticated = ({ getRootProps, getInputProps, setExtstate, - apiKey, setApiKey, globalApiKey, handleSetGlobalApikey, currentNode, setCurrentNode, - useLocalNode, - setUseLocalNode + useLocalNode, + setUseLocalNode, }) => { const [isValidApiKey, setIsValidApiKey] = useState(null); const [hasLocalNode, setHasLocalNode] = useState(null); @@ -68,27 +69,28 @@ export const NotAuthenticated = ({ const [openSnack, setOpenSnack] = React.useState(false); const [infoSnack, setInfoSnack] = React.useState(null); const [show, setShow] = React.useState(false); - const [mode, setMode] = React.useState("list"); + const [mode, setMode] = React.useState('list'); const [customNodes, setCustomNodes] = React.useState(null); // const [currentNode, setCurrentNode] = React.useState({ // url: "http://127.0.0.1:12391", // }); const [importedApiKey, setImportedApiKey] = React.useState(null); //add and edit states - const [url, setUrl] = React.useState("https://"); - const [customApikey, setCustomApiKey] = React.useState(""); - const [showSelectApiKey, setShowSelectApiKey] = useState(false) - const [enteredApiKey, setEnteredApiKey] = useState('') + const [url, setUrl] = React.useState('https://'); + const [customApikey, setCustomApiKey] = React.useState(''); + const [showSelectApiKey, setShowSelectApiKey] = useState(false); + const [enteredApiKey, setEnteredApiKey] = useState(''); const [customNodeToSaveIndex, setCustomNodeToSaveIndex] = React.useState(null); - const { showTutorial, hasSeenGettingStarted } = useContext(GlobalContext); + const { showTutorial, hasSeenGettingStarted } = useContext(GlobalContext); + const theme = useTheme(); const importedApiKeyRef = useRef(null); const currentNodeRef = useRef(null); const hasLocalNodeRef = useRef(null); - const isLocal = cleanUrl(currentNode?.url) === "127.0.0.1:12391"; + const isLocal = cleanUrl(currentNode?.url) === '127.0.0.1:12391'; const handleFileChangeApiKey = (event) => { - setShowSelectApiKey(false) + setShowSelectApiKey(false); const file = event.target.files[0]; // Get the selected file if (file) { const reader = new FileReader(); @@ -96,34 +98,32 @@ 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 - }) + url: 'http://127.0.0.1:12391', + apikey: text, + }); } else { copyPrev[findLocalIndex] = { - url: "http://127.0.0.1:12391", - apikey: text - } + url: 'http://127.0.0.1:12391', + 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" + 'Failed to set custom nodes:', + error.message || 'An error occurred' ); }); - return copyPrev - }) - + return copyPrev; + }); } - }; reader.readAsText(file); // Read the file as text } @@ -133,22 +133,20 @@ export const NotAuthenticated = ({ try { const url = `http://127.0.0.1:12391/admin/status`; const response = await fetch(url, { - method: "GET", + method: 'GET', headers: { - "Content-Type": "application/json", + 'Content-Type': 'application/json', }, }); 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(() => { @@ -157,25 +155,27 @@ export const NotAuthenticated = ({ useEffect(() => { window - .sendMessage("getCustomNodesFromStorage") + .sendMessage('getCustomNodesFromStorage') .then((response) => { - - setCustomNodes(response || []); - if(window?.electronAPI?.setAllowedDomains){ - window.electronAPI.setAllowedDomains(response?.map((node)=> node.url)) + 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); } - 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( - "Failed to get custom nodes from storage:", - error.message || "An error occurred" + 'Failed to get custom nodes from storage:', + error.message || 'An error occurred' ); }); }, []); @@ -191,56 +191,58 @@ export const NotAuthenticated = ({ hasLocalNodeRef.current = hasLocalNode; }, [hasLocalNode]); - - const validateApiKey = useCallback(async (key, fromStartUp) => { try { - 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 (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)) + ) { 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 + if (data2 === '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"); + throw new Error('Please turn on your local node'); } //check custom nodes // !gateways.some(gateway => apiKey?.url?.includes(gateway)) const isCurrentNodeLocal = - cleanUrl(currentNodeRef.current?.url) === "127.0.0.1:12391"; + cleanUrl(currentNodeRef.current?.url) === '127.0.0.1:12391'; if (isLocalKey && !isCurrentNodeLocal) { setIsValidApiKey(false); setUseLocalNode(false); @@ -248,90 +250,88 @@ export const NotAuthenticated = ({ } let payload = {}; - if (currentNodeRef.current?.url === "http://127.0.0.1:12391") { + if (currentNodeRef.current?.url === 'http://127.0.0.1:12391') { payload = { apikey: importedApiKeyRef.current || key?.apikey, url: currentNodeRef.current?.url, }; - if(!payload?.apikey){ + if (!payload?.apikey) { try { - const generateUrl = "http://127.0.0.1:12391/admin/apikey/generate"; + const generateUrl = 'http://127.0.0.1:12391/admin/apikey/generate'; const generateRes = await fetch(generateUrl, { - method: "POST", - }) + method: 'POST', + }); let res; - try { - res = await generateRes.clone().json(); - } catch (e) { - res = await generateRes.text(); - } + try { + res = await generateRes.clone().json(); + } catch (e) { + res = await generateRes.text(); + } if (res != null && !res.error && res.length >= 8) { payload = { apikey: res, url: currentNodeRef.current?.url, }; - + setImportedApiKey(res); // Store the file content in the state - - 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: res - }) - } else { - copyPrev[findLocalIndex] = { - url: "http://127.0.0.1:12391", - apikey: res - } - } - window - .sendMessage("setCustomNodes", copyPrev) - .catch((error) => { - console.error( - "Failed to set custom nodes:", - error.message || "An error occurred" + + 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: res, + }); + } else { + copyPrev[findLocalIndex] = { + url: 'http://127.0.0.1:12391', + apikey: res, + }; + } + window + .sendMessage('setCustomNodes', copyPrev) + .catch((error) => { + console.error( + 'Failed to set custom nodes:', + error.message || 'An error occurred' + ); + }); + return copyPrev; }); - return copyPrev - }) - - } } catch (error) { - console.error(error) + console.error(error); } } } 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 + if (data2 === 'true') { + isValid = true; } } - if (isValid) { window - .sendMessage("setApiKey", payload) + .sendMessage('setApiKey', payload) .then((response) => { if (response) { handleSetGlobalApikey(payload); @@ -344,31 +344,30 @@ export const NotAuthenticated = ({ }) .catch((error) => { console.error( - "Failed to set API key:", - error.message || "An error occurred" + 'Failed to set API key:', + error.message || 'An error occurred' ); }); } else { setIsValidApiKey(false); setUseLocalNode(false); - if(!fromStartUp){ + if (!fromStartUp) { setInfoSnack({ - type: "error", - message: "Select a valid apikey", + type: 'error', + message: 'Select a valid apikey', }); setOpenSnack(true); } - } } catch (error) { setIsValidApiKey(false); setUseLocalNode(false); if (fromStartUp) { setCurrentNode({ - url: "http://127.0.0.1:12391", + url: 'http://127.0.0.1:12391', }); window - .sendMessage("setApiKey", "isGateway") + .sendMessage('setApiKey', 'isGateway') .then((response) => { if (response) { setApiKey(null); @@ -377,20 +376,20 @@ export const NotAuthenticated = ({ }) .catch((error) => { console.error( - "Failed to set API key:", - error.message || "An error occurred" + 'Failed to set API key:', + error.message || 'An error occurred' ); }); - return + return; } - if(!fromStartUp){ - setInfoSnack({ - type: "error", - message: error?.message || "Select a valid apikey", - }); - setOpenSnack(true); - } - console.error("Error validating API key:", error); + if (!fromStartUp) { + setInfoSnack({ + type: 'error', + message: error?.message || 'Select a valid apikey', + }); + setOpenSnack(true); + } + console.error('Error validating API key:', error); } }, []); @@ -401,7 +400,7 @@ export const NotAuthenticated = ({ }, [apiKey]); const addCustomNode = () => { - setMode("add-node"); + setMode('add-node'); }; const saveCustomNodes = (myNodes, isFullListOfNodes) => { let nodes = [...(myNodes || [])]; @@ -418,26 +417,28 @@ export const NotAuthenticated = ({ } setCustomNodes(nodes); - + setCustomNodeToSaveIndex(null); if (!nodes) return; window - .sendMessage("setCustomNodes", nodes) + .sendMessage('setCustomNodes', nodes) .then((response) => { if (response) { - setMode("list"); - setUrl("https://"); - setCustomApiKey(""); - if(window?.electronAPI?.setAllowedDomains){ - window.electronAPI.setAllowedDomains(nodes?.map((node) => node.url)) - } + setMode('list'); + setUrl('https://'); + setCustomApiKey(''); + if (window?.electronAPI?.setAllowedDomains) { + window.electronAPI.setAllowedDomains( + nodes?.map((node) => node.url) + ); + } // add alert if needed } }) .catch((error) => { console.error( - "Failed to set custom nodes:", - error.message || "An error occurred" + 'Failed to set custom nodes:', + error.message || 'An error occurred' ); }); }; @@ -448,8 +449,8 @@ export const NotAuthenticated = ({
@@ -457,40 +458,55 @@ export const NotAuthenticated = ({ - 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 + {/* @@ -500,98 +516,119 @@ export const NotAuthenticated = ({ - 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' - } - }} + 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. + + + } > - Create account - + { + 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 + - - {"Using node: "} {currentNode?.url} + {'Using node: '} {currentNode?.url} <> <> - For advanced users + + For advanced users + { if (response) { setApiKey(null); @@ -613,8 +650,8 @@ export const NotAuthenticated = ({ }) .catch((error) => { console.error( - "Failed to set API key:", - error.message || "An error occurred" + 'Failed to set API key:', + error.message || 'An error occurred' ); }); } @@ -623,18 +660,23 @@ export const NotAuthenticated = ({ defaultChecked /> } - label={`Use ${isLocal ? "Local" : "Custom"} Node`} + label={`Use ${isLocal ? 'Local' : 'Custom'} Node`} /> - {currentNode?.url === "http://127.0.0.1:12391" && ( + {currentNode?.url === 'http://127.0.0.1:12391' && ( <> - {`api key : ${importedApiKey}`} @@ -652,8 +694,8 @@ export const NotAuthenticated = ({ Build version: {manifestData?.version} @@ -673,60 +715,60 @@ export const NotAuthenticated = ({ aria-describedby="alert-dialog-description" fullWidth > - {"Custom nodes"} + {'Custom nodes'} - {mode === "list" && ( + {mode === 'list' && ( http://127.0.0.1:12391 )} - {mode === "add-node" && ( + {mode === 'add-node' && ( <> + type="file" + accept=".txt" + hidden + onChange={handleFileChangeApiKey} // File input handler + /> + - - + - - - + )} - { - showTutorial('create-account', true) - }} sx={{ - position: 'fixed', - bottom: '25px', - right: '25px' - }}> - - + { + showTutorial('create-account', true); + }} + sx={{ + position: 'fixed', + bottom: '25px', + right: '25px', + }} + > + + + + ); -}; \ No newline at end of file +};