diff --git a/web/cashtab/src/components/Configure/Configure.js b/web/cashtab/src/components/Configure/Configure.js --- a/web/cashtab/src/components/Configure/Configure.js +++ b/web/cashtab/src/components/Configure/Configure.js @@ -18,7 +18,7 @@ ExclamationCircleFilled, } from '@ant-design/icons'; import { WalletContext, AuthenticationContext } from 'utils/context'; -import { SidePaddingCtn } from 'components/Common/Atoms'; +import { SidePaddingCtn, FormLabel } from 'components/Common/Atoms'; import { StyledCollapse } from 'components/Common/StyledCollapse'; import { AntdFormWrapper, @@ -40,6 +40,7 @@ import { Event } from 'utils/GoogleAnalytics'; import ApiError from 'components/Common/ApiError'; import { formatSavedBalance } from 'utils/formatting'; +import { isValidXecAddress } from 'utils/validation'; const { Panel } = Collapse; @@ -318,6 +319,34 @@ } `; +const ContactListActions = styled.div` + text-align: center; + width: 100%; + padding: 10px; + border-radius: 5px; + a { + color: ${props => props.theme.contrast}; + margin: 0; + font-size: 14px; + border: 1px solid ${props => props.theme.contrast}; + border-radius: 5px; + padding: 2px 10px; + opacity: 0.6; + } + a:hover { + opacity: 1; + border-color: ${props => props.theme.eCashBlue}; + color: ${props => props.theme.contrast}; + background: ${props => props.theme.eCashBlue}; + } + ${({ received, ...props }) => + received && + ` + text-align: left; + background: ${props.theme.receivedMessage}; + `} +`; + const AWRow = styled.div` padding: 10px 0; display: flex; @@ -483,6 +512,15 @@ const [contactListArray, setContactListArray] = useState([{}]); + const [showManualAddContactModal, setShowManualAddContactModal] = + useState(false); + const [manualContactName, setManualContactName] = useState(''); + const [manualContactAddress, setManualContactAddress] = useState(''); + const [manualContactNameIsValid, setManualContactNameIsValid] = + useState(null); + const [manualContactAddressIsValid, setManualContactAddressIsValid] = + useState(null); + useEffect(() => { // Update savedWallets every time the active wallet changes updateSavedWallets(wallet); @@ -748,9 +786,149 @@ changeCashtabSettings('sendModal', checkedState); }; + const handleManualAddContactModalOk = async () => { + // if either inputs are invalid then go no further + if (!manualContactNameIsValid || !manualContactAddressIsValid) { + return; + } + + let duplicateContact = false; + let tempContactListArray = contactListArray; + let newContactObj = { + name: manualContactName, + address: manualContactAddress, + }; + + if (!tempContactListArray || tempContactListArray.length === 0) { + // no existing contact list in local storage + tempContactListArray = [{}]; // instantiates to mitigate null pointer issues + tempContactListArray.push(newContactObj); + tempContactListArray.shift(); // remove the initial entry from instantiation + } else { + // contact list exists in local storage + // check if address already exists in contact list + let tempContactListArrayLength = tempContactListArray.length; + for (let i = 0; i < tempContactListArrayLength; i++) { + if (tempContactListArray[i].address === manualContactAddress) { + generalNotification( + manualContactAddress + + ' already exists in the Contact List', + ); + duplicateContact = true; + break; + } + } + // if address does not exist on the contact list, add it + if (!duplicateContact) { + tempContactListArray.push(newContactObj); + generalNotification( + manualContactAddress + ' added to Contact List', + ); + } + } + // update local state array + setContactListArray(tempContactListArray); + + // update localforage + try { + await updateContactListInLocalForage(tempContactListArray); + } catch (err) { + console.log('Error in handleManualAddContactModalOk()'); + console.log(err); + } + + setShowManualAddContactModal(false); + setManualContactName(''); + setManualContactAddress(''); + }; + + const handleManualAddContactModalCancel = () => { + setShowManualAddContactModal(false); + setManualContactName(''); + setManualContactAddress(''); + }; + + const handleManualContactNameInput = e => { + const { value } = e.target; + + if (value && value.length && value.length < 24) { + setManualContactNameIsValid(true); + } else { + setManualContactNameIsValid(false); + } + setManualContactName(value); + }; + + const handleManualContactAddressInput = e => { + const { value } = e.target; + setManualContactAddressIsValid(isValidXecAddress(value)); + setManualContactAddress(value); + }; + return ( + {showManualAddContactModal && ( + handleManualAddContactModalOk()} + onCancel={() => handleManualAddContactModalCancel()} + > + +
+ Name: + + + handleManualContactNameInput(e) + } + /> + + eCash Address: + + + handleManualContactAddressInput(e) + } + /> + +
+
+
+ )} {walletToBeRenamed !== null && ( + > } placeholder="Enter new wallet name" @@ -1059,11 +1237,22 @@

{ - 'Contacts can be added by clicking on a received transaction and looking for the "Add to contacts" icon.' + 'Contacts can be added by clicking on a received transaction and looking for the "Add to contacts" icon or via the "New Contact" button below.' }

)} + + + setShowManualAddContactModal( + true, + ) + } + > + New Contact + + diff --git a/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap b/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap --- a/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap +++ b/web/cashtab/src/components/Configure/__tests__/__snapshots__/Configure.test.js.snap @@ -5,7 +5,7 @@ className="sc-jTzLTM jNRuZd" >

[

[