lbry-desktop/ui/component/selectChannel/view.jsx

230 lines
6.8 KiB
React
Raw Normal View History

2018-03-26 23:32:43 +02:00
// @flow
2019-07-21 23:31:22 +02:00
import React, { Fragment } from 'react';
2018-04-18 06:03:01 +02:00
import { isNameValid } from 'lbry-redux';
2019-02-13 17:27:20 +01:00
import { FormField } from 'component/common/form';
2018-03-26 23:32:43 +02:00
import BusyIndicator from 'component/common/busy-indicator';
import Button from 'component/button';
import analytics from 'analytics';
import { CHANNEL_NEW, CHANNEL_ANONYMOUS, MINIMUM_PUBLISH_BID, INVALID_NAME_ERROR } from 'constants/claim';
2018-03-26 23:32:43 +02:00
type Props = {
channel: string, // currently selected channel
channels: ?Array<ChannelClaim>,
2018-03-26 23:32:43 +02:00
balance: number,
2019-06-12 16:53:27 +02:00
onChannelChange: string => void,
2018-03-26 23:32:43 +02:00
createChannel: (string, number) => Promise<any>,
fetchChannelListMine: () => void,
fetchingChannels: boolean,
2019-10-28 19:53:59 +01:00
emailVerified: boolean,
2018-03-26 23:32:43 +02:00
};
type State = {
newChannelName: string,
newChannelBid: number,
addingChannel: boolean,
creatingChannel: boolean,
newChannelNameError: string,
newChannelBidError: string,
createChannelError: ?string,
};
class ChannelSection extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
newChannelName: '',
newChannelBid: 0.1,
addingChannel: false,
creatingChannel: false,
newChannelNameError: '',
newChannelBidError: '',
createChannelError: undefined,
};
(this: any).handleChannelChange = this.handleChannelChange.bind(this);
(this: any).handleNewChannelNameChange = this.handleNewChannelNameChange.bind(this);
(this: any).handleNewChannelBidChange = this.handleNewChannelBidChange.bind(this);
(this: any).handleCreateChannelClick = this.handleCreateChannelClick.bind(this);
}
componentDidMount() {
2019-10-28 19:53:59 +01:00
const { channels, fetchChannelListMine, fetchingChannels, emailVerified } = this.props;
if (IS_WEB && !emailVerified) {
return;
}
2019-09-24 14:57:55 +02:00
if ((!channels || !channels.length) && !fetchingChannels) {
2018-03-26 23:32:43 +02:00
fetchChannelListMine();
}
}
2019-05-21 02:47:23 +02:00
handleChannelChange(event: SyntheticInputEvent<*>) {
2019-06-12 16:53:27 +02:00
const { onChannelChange } = this.props;
const { newChannelBid } = this.state;
2019-06-12 16:53:27 +02:00
const channel = event.target.value;
2018-03-26 23:32:43 +02:00
2019-06-12 16:53:27 +02:00
if (channel === CHANNEL_NEW) {
2018-03-26 23:32:43 +02:00
this.setState({ addingChannel: true });
2019-06-12 16:53:27 +02:00
onChannelChange(channel);
this.handleNewChannelBidChange(newChannelBid);
2018-03-26 23:32:43 +02:00
} else {
this.setState({ addingChannel: false });
2019-06-12 16:53:27 +02:00
onChannelChange(channel);
2018-03-26 23:32:43 +02:00
}
}
handleNewChannelNameChange(event: SyntheticInputEvent<*>) {
let newChannelName = event.target.value;
if (newChannelName.startsWith('@')) {
newChannelName = newChannelName.slice(1);
}
let newChannelNameError;
2019-07-24 20:21:34 +02:00
if (newChannelName.length > 0 && !isNameValid(newChannelName, false)) {
2019-10-03 23:40:54 +02:00
newChannelNameError = INVALID_NAME_ERROR;
2018-03-26 23:32:43 +02:00
}
this.setState({
newChannelNameError,
newChannelName,
});
}
handleNewChannelBidChange(newChannelBid: number) {
2018-03-26 23:32:43 +02:00
const { balance } = this.props;
let newChannelBidError;
if (newChannelBid === 0) {
newChannelBidError = __('Your deposit cannot be 0');
} else if (newChannelBid === balance) {
newChannelBidError = __('Please decrease your deposit to account for transaction fees');
2018-03-26 23:32:43 +02:00
} else if (newChannelBid > balance) {
newChannelBidError = __('Deposit cannot be higher than your balance');
} else if (newChannelBid < MINIMUM_PUBLISH_BID) {
newChannelBidError = __('Your deposit must be higher');
2018-03-26 23:32:43 +02:00
}
this.setState({
newChannelBid,
newChannelBidError,
});
}
handleCreateChannelClick() {
2019-06-12 16:53:27 +02:00
const { balance, createChannel, onChannelChange } = this.props;
2018-03-26 23:32:43 +02:00
const { newChannelBid, newChannelName } = this.state;
2019-07-24 20:21:34 +02:00
const channelName = `@${newChannelName.trim()}`;
2018-03-26 23:32:43 +02:00
if (newChannelBid > balance) {
return;
}
this.setState({
creatingChannel: true,
createChannelError: undefined,
});
const success = channelClaim => {
2018-03-26 23:32:43 +02:00
this.setState({
creatingChannel: false,
addingChannel: false,
});
2019-10-16 23:36:50 +02:00
analytics.apiLogPublish(channelClaim);
2019-06-12 16:53:27 +02:00
onChannelChange(channelName);
2018-03-26 23:32:43 +02:00
};
const failure = () => {
this.setState({
creatingChannel: false,
createChannelError: __('Unable to create channel due to an internal error.'),
});
};
createChannel(channelName, newChannelBid).then(success, failure);
}
render() {
2019-06-12 16:53:27 +02:00
const channel = this.state.addingChannel ? 'new' : this.props.channel;
2018-03-26 23:32:43 +02:00
const { fetchingChannels, channels = [] } = this.props;
const {
newChannelName,
newChannelNameError,
newChannelBid,
newChannelBidError,
creatingChannel,
createChannelError,
addingChannel,
} = this.state;
return (
2019-07-21 23:31:22 +02:00
<Fragment>
2019-02-13 17:27:20 +01:00
{createChannelError && <div className="error-text">{createChannelError}</div>}
2018-03-26 23:32:43 +02:00
{fetchingChannels ? (
<BusyIndicator message="Updating channels" />
) : (
2019-02-13 17:27:20 +01:00
<fieldset-section>
2019-06-27 01:59:27 +02:00
<FormField
name="channel"
label={__('Channel')}
type="select"
onChange={this.handleChannelChange}
value={channel}
>
2019-02-13 17:27:20 +01:00
<option value={CHANNEL_ANONYMOUS}>{__('Anonymous')}</option>
2019-09-23 17:02:30 +02:00
{channels &&
channels.map(({ name, claim_id: claimId }) => (
<option key={claimId} value={name}>
2019-09-23 17:02:30 +02:00
{name}
</option>
))}
2019-02-13 17:27:20 +01:00
<option value={CHANNEL_NEW}>{__('New channel...')}</option>
</FormField>
</fieldset-section>
2018-03-26 23:32:43 +02:00
)}
{addingChannel && (
2019-07-21 23:31:22 +02:00
<div>
2019-02-13 17:27:20 +01:00
<FormField
label={__('Name')}
2019-02-20 06:20:29 +01:00
name="channel-input"
2019-02-13 17:27:20 +01:00
type="text"
placeholder={__('myChannelName')}
error={newChannelNameError}
value={newChannelName}
onChange={this.handleNewChannelNameChange}
/>
<FormField
className="form-field--price-amount"
2019-02-20 06:20:29 +01:00
name="channel-deposit"
label={__('Deposit (LBC)')}
2019-02-13 17:27:20 +01:00
step="any"
min="0"
type="number"
2019-05-07 23:38:29 +02:00
helper={__('This LBC remains yours. It is a deposit to reserve the name and can be undone at any time.')}
2019-02-13 17:27:20 +01:00
error={newChannelBidError}
value={newChannelBid}
onChange={event => this.handleNewChannelBidChange(parseFloat(event.target.value))}
/>
2018-03-26 23:32:43 +02:00
<div className="card__actions">
<Button
button="primary"
label={!creatingChannel ? __('Create channel') : __('Creating channel...')}
onClick={this.handleCreateChannelClick}
disabled={
2019-05-07 23:38:29 +02:00
!newChannelName || !newChannelBid || creatingChannel || newChannelNameError || newChannelBidError
2018-03-26 23:32:43 +02:00
}
/>
</div>
</div>
)}
2019-07-21 23:31:22 +02:00
</Fragment>
2018-03-26 23:32:43 +02:00
);
}
}
export default ChannelSection;