wallet server selection style

This commit is contained in:
Sean Yesmunt 2019-12-13 14:47:50 -05:00
parent 7872f8b7f8
commit 9d83de7eea
8 changed files with 107 additions and 85 deletions

View file

@ -909,7 +909,6 @@
"Choose a different provider's wallet server.": "Choose a different provider's wallet server.", "Choose a different provider's wallet server.": "Choose a different provider's wallet server.",
"Host": "Host", "Host": "Host",
"Port": "Port", "Port": "Port",
"Available": "Available",
"Unable to load your saved preferences.": "Unable to load your saved preferences.", "Unable to load your saved preferences.": "Unable to load your saved preferences.",
"Add/Delete": "Add/Delete", "Add/Delete": "Add/Delete",
"%numberOfMonthsSincePublish% years ago": "%numberOfMonthsSincePublish% years ago", "%numberOfMonthsSincePublish% years ago": "%numberOfMonthsSincePublish% years ago",
@ -919,12 +918,11 @@
"%numberOfMonthsSincePublish% month ago": "%numberOfMonthsSincePublish% month ago", "%numberOfMonthsSincePublish% month ago": "%numberOfMonthsSincePublish% month ago",
"%numberOfMonthsSincePublish% months ago": "%numberOfMonthsSincePublish% months ago", "%numberOfMonthsSincePublish% months ago": "%numberOfMonthsSincePublish% months ago",
"%numberOfDaysSincePublish% days ago": "%numberOfDaysSincePublish% days ago", "%numberOfDaysSincePublish% days ago": "%numberOfDaysSincePublish% days ago",
"%numberOfDaysSincePublish% day ago": "%numberOfDaysSincePublish% day ago",
"The wallet server took a bit too long. Resetting defaults just in case. Shutdown (Cmd/Ctrl+Q) LBRY and restart if this continues.": "The wallet server took a bit too long. Resetting defaults just in case. Shutdown (Cmd/Ctrl+Q) LBRY and restart if this continues.", "The wallet server took a bit too long. Resetting defaults just in case. Shutdown (Cmd/Ctrl+Q) LBRY and restart if this continues.": "The wallet server took a bit too long. Resetting defaults just in case. Shutdown (Cmd/Ctrl+Q) LBRY and restart if this continues.",
"Provide a description and link to your license": "Provide a description and link to your license", "Provide a description and link to your license": "Provide a description and link to your license",
"Walletserver preference": "Walletserver preference",
"Wallet servers": "Wallet servers", "Wallet servers": "Wallet servers",
"In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications.": "In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications.", "In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications.": "In response to a complaint we received under the US Digital Millennium Copyright Act, we have blocked access to this content from our applications.",
"Followers": "Followers", "Followers": "Followers",
"%numberOfDaysSincePublish% day ago": "%numberOfDaysSincePublish% day ago",
"%number% files hidden due to your %content_viewing_preferences_link%": "%number% files hidden due to your %content_viewing_preferences_link%" "%number% files hidden due to your %content_viewing_preferences_link%": "%number% files hidden due to your %content_viewing_preferences_link%"
} }

View file

@ -1,47 +1,63 @@
// @flow // @flow
import * as ICONS from 'constants/icons';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import Button from 'component/button'; import Button from 'component/button';
import { FormField } from 'component/common/form'; import { Form, FormField } from 'component/common/form';
type Props = { type Props = {
update: (string) => void, update: ([string, string]) => void,
}; };
const VALID_IPADDRESS_REGEX = new RegExp('^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\.)){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'); const VALID_IPADDRESS_REGEX = new RegExp(
const VALID_HOSTNAME_REGEX = new RegExp('^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(\\.))+([A-Za-z]|[A-Za-z][A-Za-z]*[A-Za-z])$'); '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\.)){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$'
);
const VALID_HOSTNAME_REGEX = new RegExp(
'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])(\\.))+([A-Za-z]|[A-Za-z][A-Za-z]*[A-Za-z])$'
);
const VALID_PORT_REGEX = new RegExp('^([0-9]){1,5}$'); const VALID_PORT_REGEX = new RegExp('^([0-9]){1,5}$');
function ServerInputRow(props: Props) { function ServerInputRow(props: Props) {
const { update } = props; const { update } = props;
const [hostString, setHostString] = useState(''); const [hostString, setHostString] = useState('');
const [portString, setPortString] = useState(''); const [portString, setPortString] = useState('');
const [validServerString, setValidServerString] = useState(false); const [validServerString, setValidServerString] = useState(false);
useEffect(() => { useEffect(() => {
setValidServerString((VALID_IPADDRESS_REGEX.test(hostString) || VALID_HOSTNAME_REGEX.test(hostString)) && VALID_PORT_REGEX.test(portString)); setValidServerString(
(VALID_IPADDRESS_REGEX.test(hostString) || VALID_HOSTNAME_REGEX.test(hostString)) &&
VALID_PORT_REGEX.test(portString)
);
}, [hostString, portString, validServerString, setValidServerString]); }, [hostString, portString, validServerString, setValidServerString]);
function onClick() { function onSubmit() {
update([hostString, portString]); update([hostString, portString]);
setHostString(''); setHostString('');
setPortString(''); setPortString('');
} }
return ( return (
<tr> <Form onSubmit={onSubmit}>
<td> <div className="section__actions">
<FormField type="text" value={hostString} onChange={e => setHostString(e.target.value)} /> <FormField
</td> type="text"
<td> label={__('Host')}
<FormField type="text" value={portString} onChange={e => setPortString(e.target.value)} /> placeholder={'code.freezepeach.fun'}
</td> value={hostString}
<td /> onChange={e => setHostString(e.target.value)}
<td> />
<Button button={'link'} icon={ICONS.ADD} disabled={!validServerString} onClick={onClick} /> <span className="form-field__conjuction">:</span>
</td> <FormField
</tr> type="text"
label={__('Port')}
placeholder={'50001'}
value={portString}
onChange={e => setPortString(e.target.value)}
/>
</div>
<div className="section__actions">
<Button type="submit" button="primary" label={__('Add')} disabled={!validServerString} />
</div>
</Form>
); );
} }

View file

@ -4,12 +4,11 @@ import React, { useState, useEffect } from 'react';
import { FormField } from 'component/common/form'; import { FormField } from 'component/common/form';
import Button from 'component/button'; import Button from 'component/button';
import * as ICONS from 'constants/icons'; import * as ICONS from 'constants/icons';
import Icon from 'component/common/icon';
import ServerInputRow from './internal/inputRow'; import ServerInputRow from './internal/inputRow';
type DaemonSettings = { type DaemonSettings = {
lbryum_servers: Array<>, lbryum_servers: Array<string>,
}; };
type DaemonStatus = { type DaemonStatus = {
@ -33,7 +32,7 @@ type Props = {
setCustomWalletServers: any => void, setCustomWalletServers: any => void,
clearWalletServers: () => void, clearWalletServers: () => void,
customWalletServers: ServerConfig, customWalletServers: ServerConfig,
saveServerConfig: string => void, saveServerConfig: (Array<string>) => void,
fetchDaemonSettings: () => void, fetchDaemonSettings: () => void,
hasWalletServerPrefs: boolean, hasWalletServerPrefs: boolean,
daemonStatus: DaemonStatus, daemonStatus: DaemonStatus,
@ -88,13 +87,13 @@ function SettingWalletServer(props: Props) {
clearWalletServers(); clearWalletServers();
} }
function onAdd(serverTuple) { function onAdd(serverTuple: Array<string>) {
let newServerConfig = serverConfig.concat(); let newServerConfig = serverConfig.concat();
newServerConfig.push(serverTuple); newServerConfig.push(serverTuple);
updateServers(newServerConfig); updateServers(newServerConfig);
} }
function onDelete(i) { function onDelete(i: number) {
const newServerConfig = serverConfig.concat(); const newServerConfig = serverConfig.concat();
newServerConfig.splice(i, 1); newServerConfig.splice(i, 1);
updateServers(newServerConfig); updateServers(newServerConfig);
@ -107,13 +106,12 @@ function SettingWalletServer(props: Props) {
return ( return (
<React.Fragment> <React.Fragment>
<label>{__('Wallet servers')}</label> <fieldset-section>
<fieldset>
<FormField <FormField
type="radio" type="radio"
name="default_wallet_servers" name="default_wallet_servers"
checked={!advancedMode} checked={!advancedMode}
label={__('lbry.tv')} label={__('Use official lbry.tv wallet servers')}
onChange={e => { onChange={e => {
if (e.target.checked) { if (e.target.checked) {
doClear(); doClear();
@ -130,42 +128,41 @@ function SettingWalletServer(props: Props) {
setCustomWalletServers(makeServerParam(customWalletServers)); setCustomWalletServers(makeServerParam(customWalletServers));
} }
}} }}
label={__('customize')} label={__('Use custom wallet servers')}
/> />
</fieldset> {advancedMode && (
{advancedMode && ( <div>
<div> {serverConfig &&
<table className="table table--transactions"> serverConfig.map((entry, index) => {
<thead> const [host, port] = entry;
<tr> const available = activeWalletServers.some(
<th>{__('Host')}</th> s => s.host === entry[0] && String(s.port) === entry[1] && s.availability
<th>{__('Port')} </th> );
<th>{__('Available')} </th>
<th>{__('Add/Delete')} </th> return (
</tr> <div
</thead> key={`${host}:${port}`}
<tbody> className="section section--padded card--inline form-field__internal-option"
{serverConfig && >
serverConfig.map((entry, i) => ( <h3>
<tr key={`${entry[0]}:${entry[1]}`}> {host}:{port}
<td>{entry[0]}</td> </h3>
<td>{entry[1]}</td> <span className="help">{available ? 'Connected' : 'Not connected'}</span>
<td> <Button
{activeWalletServers.some( button="close"
s => s.host === entry[0] && String(s.port) === entry[1] && s.availability title={__('Remove custom wallet server')}
) && <Icon icon={ICONS.SUBSCRIBE} />} icon={ICONS.REMOVE}
</td> onClick={() => onDelete(index)}
<td> />
<Button button={'link'} icon={ICONS.REMOVE} onClick={() => onDelete(i)} /> </div>
</td> );
</tr> })}
))} <div className="form-field__internal-option">
<ServerInputRow update={onAdd} /> <ServerInputRow update={onAdd} />
</tbody> </div>
</table> </div>
</div> )}
)} </fieldset-section>
<p className="help">{__(`Choose a different provider's wallet server.`)}</p>
</React.Fragment> </React.Fragment>
); );
} }

View file

@ -39,10 +39,7 @@ type State = {
error: boolean, error: boolean,
isRunning: boolean, isRunning: boolean,
launchWithIncompatibleDaemon: boolean, launchWithIncompatibleDaemon: boolean,
walletServerAvailable: boolean,
waitingForWallet: number, waitingForWallet: number,
hasPopulated: boolean,
hasReconnected: boolean,
}; };
export default class SplashScreen extends React.PureComponent<Props, State> { export default class SplashScreen extends React.PureComponent<Props, State> {
@ -129,8 +126,12 @@ export default class SplashScreen extends React.PureComponent<Props, State> {
}); });
} else if (this.state.waitingForWallet > MAX_WALLET_WAIT && launchedModal === false && !modal) { } else if (this.state.waitingForWallet > MAX_WALLET_WAIT && launchedModal === false && !modal) {
clearWalletServers(); clearWalletServers();
doShowSnackBar(__('The wallet server took a bit too long. Resetting defaults just in case. Shutdown (Cmd/Ctrl+Q) LBRY and restart if this continues.')); doShowSnackBar(
this.setState({waitingForWallet: 0}); __(
'The wallet server took a bit too long. Resetting defaults just in case. Shutdown (Cmd/Ctrl+Q) LBRY and restart if this continues.'
)
);
this.setState({ waitingForWallet: 0 });
this.updateStatusCallback(status); this.updateStatusCallback(status);
} else { } else {
this.updateStatusCallback(status); this.updateStatusCallback(status);
@ -151,7 +152,7 @@ export default class SplashScreen extends React.PureComponent<Props, State> {
this.hasRecordedUser = true; this.hasRecordedUser = true;
} }
const { wallet, startup_status: startupStatus, blockchain_headers: blockchainHeaders } = status; const { wallet, startup_status: startupStatus } = status;
// If the wallet is locked, stop doing anything and make the user input their password // If the wallet is locked, stop doing anything and make the user input their password
if (status.is_running && !waitingForUnlock) { if (status.is_running && !waitingForUnlock) {
@ -161,7 +162,7 @@ export default class SplashScreen extends React.PureComponent<Props, State> {
return; return;
} else if (startupStatus && !startupStatus.wallet && wallet && wallet.available_servers < 1) { } else if (startupStatus && !startupStatus.wallet && wallet && wallet.available_servers < 1) {
this.setState({waitingForWallet: this.state.waitingForWallet + (UPDATE_INTERVAL / 1000)}); this.setState({ waitingForWallet: this.state.waitingForWallet + UPDATE_INTERVAL / 1000 });
} else if (wallet && wallet.blocks_behind > 0) { } else if (wallet && wallet.blocks_behind > 0) {
this.setState({ this.setState({
message: __('Blockchain Sync'), message: __('Blockchain Sync'),

View file

@ -103,12 +103,6 @@ fieldset-group {
cursor: default; cursor: default;
} }
.form-field__help {
@extend .help;
margin-top: var(--spacing-miniscule);
margin-bottom: var(--spacing-small);
}
.form-field--short { .form-field--short {
width: 25em; width: 25em;
} }
@ -120,3 +114,24 @@ fieldset-group {
.form-field--address { .form-field--address {
min-width: 18em; min-width: 18em;
} }
.form-field__help {
@extend .help;
margin-top: var(--spacing-miniscule);
margin-bottom: var(--spacing-small);
}
.form-field__conjuction {
padding-top: 1rem;
}
fieldset-section {
.form-field__internal-option {
margin-top: var(--spacing-small);
margin-left: 2.2rem;
&:first-of-type {
margin-top: var(--spacing-small); // Extra specificity needed here since _section.scss is applied after this file
}
}
}

View file

@ -1,4 +1,5 @@
.section { .section {
position: relative;
margin-top: var(--spacing-large); margin-top: var(--spacing-large);
&:first-of-type { &:first-of-type {

View file

@ -179,12 +179,6 @@ a {
} }
} }
.card {
.help:last-child {
margin-bottom: 0;
}
}
.help { .help {
display: block; display: block;
font-size: var(--font-small); font-size: var(--font-small);

View file

@ -130,7 +130,7 @@ const sharedStateFilters = {
}, },
}, },
blocked: { source: 'blocked', property: 'blockedChannels' }, blocked: { source: 'blocked', property: 'blockedChannels' },
settings: { source: 'settings', property: 'sharedPreferences'}, settings: { source: 'settings', property: 'sharedPreferences' },
}; };
const sharedStateCb = ({ dispatch, getState }) => { const sharedStateCb = ({ dispatch, getState }) => {