update settings

This commit is contained in:
plebeius.eth
2024-05-15 21:20:14 +02:00
parent 4e68b0c1c3
commit 7d9fd2cce7
9 changed files with 299 additions and 61 deletions
@@ -0,0 +1,43 @@
.setting {
margin-left: 10px;
}
.setting textarea {
display: block;
font-family: dejavu sans mono, consolas, andale mono, lucida console, monospace;
outline: none;
border: 1px solid #aaa;
font-size: 11px;
margin: 0 2px 0 0;
padding: 2px 4px 3px;
min-height: 150px;
width: 95%;
}
.setting textarea:focus {
border-color: 1px solid #98e;
}
.setting button {
cursor: pointer;
}
.saveResetAccount {
margin-top: 15px;
}
.setting textarea {
margin-bottom: 5px;
}
.setting div {
margin-top: 5px;
}
.deleteAccount, .deleteAccount button {
color: red;
}
.setting .createAccount {
margin-left: 5px;
}
@@ -153,7 +153,7 @@ const AccountSettings = () => {
));
return (
<div className={styles.accountSettings}>
<div className={styles.setting}>
<div>
<select value={account?.name} onChange={(e) => setActiveAccount(e.target.value)}>
{accountsOptions}
@@ -1,3 +1,37 @@
.setting {
margin-left: 10px;
}
.setting button {
cursor: pointer;
text-transform: capitalize;
}
.cryptoAddressInput input[type="text"] {
padding: 2px 0;
margin-bottom: 5px;
outline: none;
border: 1px solid #aaa;
padding: 2px 4px 3px;
}
.infoButton {
padding: 0 5px;
}
.cryptoAddressInfo {
word-break: break-word;
}
.cryptoAddressInfo ol {
padding-bottom: 10px;
padding-left: 15px;
}
.saveButton {
margin: 0 5px;
}
.red {
color: red;
}
@@ -109,12 +109,12 @@ const CryptoAddressSetting = () => {
defaultValue={cryptoState.cryptoAddress || (account?.author?.shortAddress.includes('.') ? account.author.shortAddress : '')}
onChange={(e) => setCryptoState((prevState) => ({ ...prevState, cryptoAddress: e.target.value }))}
/>
<button className={styles.saveButton} onClick={saveCryptoAddress}>
{t('save')}
</button>
<button className={styles.infoButton} onClick={() => setShowCryptoAddressInfo(!showCryptoAddressInfo)}>
{showCryptoAddressInfo ? 'x' : '?'}
</button>
<button className={styles.button} onClick={saveCryptoAddress}>
{t('save')}
</button>
{showCryptoAddressInfo && (
<div className={styles.cryptoAddressInfo}>
steps to set a .eth user address:
@@ -0,0 +1,58 @@
.addWallet {
margin-bottom: 7px;
}
.save {
margin-left: 5px;
}
.walletTitle {
text-transform: lowercase;
font-style: italic;
margin-left: 7px;
}
.walletBox {
border: 1px solid var(--border-contrast);
border-radius: 7px;
margin-bottom: 0.5em;
padding: 7px;
position: relative;
display: inline-block;
}
.walletFieldTitle {
margin-top: 10px;
font-style: italic;
text-transform: lowercase;
}
.walletField input {
width: 200px;
padding: 2px;
box-shadow: var(--box-shadow-input);
}
.copyMessage {
padding-top: 10px;
}
.copyMessage a {
color: var(--text-primary);
}
.copyMessage a:hover {
text-decoration: underline;
}
.show {
display: block;
}
.hide {
display: none;
}
.toggleWallet {
margin-right: 7px;
}
@@ -0,0 +1,152 @@
import { useState } from 'react';
import { Account, setAccount, useAccount } from '@plebbit/plebbit-react-hooks';
import styles from './crypto-wallets-setting.module.css';
import { Trans, useTranslation } from 'react-i18next';
interface Wallet {
chainTicker: string;
address: string;
timestamp: number;
signature: string;
}
const getWalletMessageToSign = (authorAddress: string, timestamp: number): string => {
const messageToSign = {
domainSeparator: 'plebbit-author-wallet',
authorAddress,
timestamp,
};
return JSON.stringify(messageToSign);
};
const CryptoWalletsForm = ({ account }: { account: Account | undefined }) => {
const { t } = useTranslation();
if (!account) {
throw Error('CryptoWalletsForm account prop must be defined');
}
const authorAddress = account?.author?.address;
const defaultWalletObject: Wallet = { chainTicker: '', address: '', timestamp: 0, signature: '' };
const walletsFromAccount = Object.keys(account?.author?.wallets || {}).map(
(chainTicker): Wallet => ({
chainTicker,
address: account.author.wallets[chainTicker].address,
timestamp: account.author.wallets[chainTicker].timestamp,
signature: account.author.wallets[chainTicker].signature.signature,
}),
);
const defaultWalletsArray: Wallet[] = walletsFromAccount.length ? walletsFromAccount : [];
const [walletsArray, setWalletsArray] = useState<Wallet[]>(defaultWalletsArray);
const setWalletsArrayProperty = (index: number, property: keyof Wallet, value: string | number) => {
const newArray = [...walletsArray];
newArray[index] = { ...newArray[index], [property]: value };
setWalletsArray(newArray);
};
const [hasCopied, setHasCopied] = useState(false);
const copyMessageToSign = (wallet: any, index: number) => {
if (!wallet.chainTicker) {
return alert('missing chain ticker');
}
if (!wallet.address) {
return alert('missing address');
}
const timestamp = wallet.timestamp || Math.floor(Date.now() / 1000);
const messageToSign = getWalletMessageToSign(authorAddress, timestamp);
if (timestamp !== wallet.timestamp) {
setWalletsArrayProperty(index, 'timestamp', timestamp);
}
navigator.clipboard.writeText(messageToSign);
setHasCopied(true);
setTimeout(() => {
setHasCopied(false);
}, 2000);
};
const [showWallet, setShowWallet] = useState<boolean[]>(walletsArray.map(() => false));
const toggleShowWallet = (index: number) => {
const newShowWallet = [...showWallet];
newShowWallet[index] = !newShowWallet[index];
setShowWallet(newShowWallet);
};
const save = () => {
const wallets: { [key: string]: { address: string; timestamp: number; signature: { signature: string; type: string } } } = {};
walletsArray.forEach((wallet) => {
if (wallet.chainTicker && wallet.address && wallet.signature && wallet.timestamp) {
wallets[wallet.chainTicker] = {
address: wallet.address,
timestamp: wallet.timestamp,
signature: {
signature: wallet.signature,
type: 'eip191',
},
};
}
});
setAccount({ ...account, author: { ...account.author, wallets } });
alert(t('saved'));
};
const walletsInputs = walletsArray.map((wallet, index) => (
<>
<div className={styles.walletTitle}>
{t('wallet')} #{index + 1}
</div>
<div key={index} className={styles.walletBox}>
<button className={styles.toggleWallet} onClick={() => toggleShowWallet(index)}>
{showWallet[index] ? t('hide') : t('show')}
</button>
<button onClick={() => setWalletsArray([...walletsArray.slice(0, index), ...walletsArray.slice(index + 1)])}>{t('remove')}</button>
<div className={`${showWallet[index] ? styles.show : styles.hide}`}>
<div className={styles.walletField}>
<div className={styles.walletFieldTitle}>{t('chain_ticker')}</div>
<input onChange={(e) => setWalletsArrayProperty(index, 'chainTicker', e.target.value)} value={wallet.chainTicker} placeholder='eth/sol/avax' />
</div>
<div className={styles.walletField}>
<div className={styles.walletFieldTitle}>{t('wallet_address')}</div>
<input onChange={(e) => setWalletsArrayProperty(index, 'address', e.target.value)} value={wallet.address} placeholder='0x...' />
</div>
<div className={`${styles.walletField} ${styles.copyMessage}`}>
<Trans
i18nKey='copy_message_etherscan'
values={{ copy: hasCopied ? t('copied') : t('copy') }}
components={{
1: <button onClick={() => copyMessageToSign(wallet, index)} />,
// eslint-disable-next-line
2: <a href='https://etherscan.io/verifiedSignatures' target='_blank' rel='noopener noreferrer' />,
}}
/>
</div>
<div className={styles.walletField}>
<div className={styles.walletFieldTitle}>{t('paste_signature')}</div>
<input onChange={(e) => setWalletsArrayProperty(index, 'signature', e.target.value)} value={wallet.signature} placeholder='0x...' />
<button className={styles.save} onClick={save}>
{t('save')}
</button>
</div>
</div>
</div>
</>
));
return (
<>
<div className={styles.addWallet}>
<Trans i18nKey='add_wallet' components={{ 1: <button onClick={() => setWalletsArray([...walletsArray, defaultWalletObject])} /> }} />
</div>
{walletsInputs}
</>
);
};
const CryptoWalletsSetting = () => {
const account = useAccount();
return account && <CryptoWalletsForm account={account} />;
};
export default CryptoWalletsSetting;
@@ -0,0 +1 @@
export { default } from './crypto-wallets-setting';
@@ -8,6 +8,10 @@
z-index: 900;
}
.settingsModal label, .settingsModal button, .settingsModal select {
cursor: pointer;
}
.settingsModal {
top: 25px;
width: 394px;
@@ -28,7 +32,7 @@
border-left: var(--settings-modal-border-left);
}
.settingsModal select, .settingsModal button, .settingsModal textarea {
.settingsModal select, .settingsModal button, .settingsModal textarea, .settingsModal input[type='text'] {
filter: var(--filter80);
}
@@ -69,7 +73,6 @@
height: 18px;
display: block;
background-size: 100%;
cursor: pointer;
position: absolute;
top: 5px;
image-rendering: pixelated;
@@ -88,7 +91,6 @@
.hideButton, .showButton {
vertical-align: text-bottom;
margin-right: 5px;
cursor: pointer;
width: 18px;
height: 18px;
background-repeat: no-repeat;
@@ -110,7 +112,6 @@
}
.category label {
cursor: pointer;
font-weight: 700;
}
@@ -122,50 +123,6 @@
margin-left: 5px;
}
.accountSettings {
margin-left: 10px;
}
.accountSettings textarea {
display: block;
font-family: dejavu sans mono, consolas, andale mono, lucida console, monospace;
outline: none;
border: 1px solid #aaa;
font-size: 11px;
margin: 0 2px 0 0;
padding: 2px 4px 3px;
min-height: 150px;
width: 95%;
}
.accountSettings textarea:focus {
border-color: 1px solid #98e;
}
.accountSettings button {
cursor: pointer;
}
.saveResetAccount {
margin-top: 15px;
}
.accountSettings textarea {
margin-bottom: 5px;
}
.accountSettings div {
margin-top: 5px;
}
.deleteAccount, .deleteAccount button {
color: red;
}
.accountSettings .createAccount {
margin-left: 5px;
}
@media (max-width: 640px) {
.settingsModal {
width: 350px !important;
@@ -6,6 +6,7 @@ import useTheme from '../../hooks/use-theme';
import packageJson from '../../../package.json';
import AccountSettings from './account-settings';
import CryptoAddressSetting from './crypto-address-setting';
import CryptoWalletsSetting from './crypto-wallets-setting';
const commitRef = process.env.REACT_APP_COMMIT_REF;
const isElectron = window.isElectron === true;
@@ -104,14 +105,6 @@ const InterfaceLanguage = () => {
);
};
const CryptoWalletSettings = () => {
return (
<>
<div className={styles.setting}></div>
</>
);
};
const PlebbitOptionsSettings = () => {
return (
<>
@@ -180,7 +173,7 @@ const SettingsModal = () => {
Crypto Wallets
</label>
</div>
{showCryptoWalletSettings && <CryptoWalletSettings />}
{showCryptoWalletSettings && <CryptoWalletsSetting />}
<div className={`${styles.setting} ${styles.category}`}>
<label onClick={() => setShowPlebbitOptionsSettings(!showPlebbitOptionsSettings)}>
<span className={showPlebbitOptionsSettings ? styles.hideButton : styles.showButton} />