mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
update settings
This commit is contained in:
@@ -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}
|
||||
|
||||
+34
@@ -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:
|
||||
|
||||
+58
@@ -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} />
|
||||
|
||||
Reference in New Issue
Block a user