lbry-desktop/ui/js/page/publish/view.jsx

1077 lines
31 KiB
React
Raw Normal View History

2017-06-06 23:19:12 +02:00
import React from "react";
import lbry from "lbry";
import lbryuri from "lbryuri";
import { FormField, FormRow } from "component/form.js";
import Link from "component/link";
import rewards from "rewards";
import Modal from "component/modal";
2017-06-15 21:30:56 +02:00
import Notice from "component/notice";
2017-07-10 16:49:12 +02:00
import { BusyMessage } from "component/common";
2016-11-22 21:19:08 +01:00
2017-06-08 06:42:19 +02:00
class PublishPage extends React.PureComponent {
2017-05-17 10:10:25 +02:00
constructor(props) {
super(props);
2017-06-15 21:30:56 +02:00
this._requiredFields = ["name", "bid", "meta_title", "tosAgree"];
this._defaultCopyrightNotice = "All rights reserved.";
2017-05-17 10:10:25 +02:00
this.state = {
2017-06-06 23:19:12 +02:00
rawName: "",
name: "",
2017-05-17 10:10:25 +02:00
bid: 10,
hasFile: false,
2017-06-06 23:19:12 +02:00
feeAmount: "",
feeCurrency: "USD",
channel: "anonymous",
newChannelName: "@",
2017-05-17 10:10:25 +02:00
newChannelBid: 10,
2017-06-15 21:30:56 +02:00
meta_title: "",
meta_thumbnail: "",
meta_description: "",
meta_language: "en",
meta_nsfw: "0",
licenseType: "",
copyrightNotice: this._defaultCopyrightNotice,
2017-06-06 23:19:12 +02:00
otherLicenseDescription: "",
otherLicenseUrl: "",
2017-06-15 21:30:56 +02:00
tosAgree: false,
prefillDone: false,
2017-05-17 10:10:25 +02:00
uploadProgress: 0.0,
uploaded: false,
errorMessage: null,
submitting: false,
creatingChannel: false,
modal: null,
};
}
_updateChannelList(channel) {
2017-07-10 16:49:12 +02:00
const { fetchingChannels, fetchChannelListMine } = this.props;
if (!fetchingChannels) fetchChannelListMine();
2017-05-17 10:10:25 +02:00
}
handleSubmit(event) {
2017-06-06 23:19:12 +02:00
if (typeof event !== "undefined") {
2016-10-19 08:36:42 +02:00
event.preventDefault();
}
this.setState({
submitting: true,
});
2017-04-12 16:55:19 +02:00
let checkFields = this._requiredFields;
if (!this.myClaimExists()) {
2017-06-06 23:19:12 +02:00
checkFields.unshift("file");
}
2017-04-12 16:55:19 +02:00
let missingFieldFound = false;
for (let fieldName of checkFields) {
2017-04-12 16:55:19 +02:00
const field = this.refs[fieldName];
if (field) {
2017-06-06 23:19:12 +02:00
if (field.getValue() === "" || field.getValue() === false) {
2017-04-12 16:55:19 +02:00
field.showRequiredError();
if (!missingFieldFound) {
field.focus();
missingFieldFound = true;
}
} else {
field.clearError();
}
}
}
if (missingFieldFound) {
this.setState({
submitting: false,
});
return;
}
2017-06-15 21:30:56 +02:00
let metadata = {};
2017-06-15 21:30:56 +02:00
for (let metaField of ["title", "description", "thumbnail", "language"]) {
const value = this.state["meta_" + metaField];
if (value) {
metadata[metaField] = value;
}
}
2017-06-15 21:30:56 +02:00
metadata.license = this.getLicense();
metadata.licenseUrl = this.getLicenseUrl();
metadata.nsfw = !!parseInt(this.state.meta_nsfw);
var doPublish = () => {
var publishArgs = {
name: this.state.name,
bid: parseFloat(this.state.bid),
metadata: metadata,
2017-06-06 23:19:12 +02:00
...(this.state.channel != "new" && this.state.channel != "anonymous"
? { channel_name: this.state.channel }
: {}),
};
2017-06-06 23:19:12 +02:00
if (this.refs.file.getValue() !== "") {
publishArgs.file_path = this.refs.file.getValue();
}
2017-04-10 14:32:40 +02:00
2017-06-17 19:59:18 +02:00
const success = claim => {};
const failure = error => this.handlePublishError(error);
this.handlePublishStarted();
this.props.publish(publishArgs).then(success, failure);
};
if (this.state.isFee) {
2017-06-06 23:19:12 +02:00
lbry.wallet_unused_address().then(address => {
2017-06-06 17:14:08 +02:00
metadata.fee = {
currency: this.state.feeCurrency,
amount: parseFloat(this.state.feeAmount),
address: address,
};
doPublish();
});
} else {
doPublish();
}
2017-05-17 10:10:25 +02:00
}
handlePublishStarted() {
this.setState({
2017-06-06 23:19:12 +02:00
modal: "publishStarted",
});
2017-05-17 10:10:25 +02:00
}
handlePublishStartedConfirmed() {
2017-06-06 23:19:12 +02:00
this.props.navigate("/published");
2017-05-17 10:10:25 +02:00
}
handlePublishError(error) {
this.setState({
submitting: false,
2017-06-06 23:19:12 +02:00
modal: "error",
errorMessage: error.message,
});
2017-05-17 10:10:25 +02:00
}
claim() {
const { claimsByUri } = this.props;
const { uri } = this.state;
return claimsByUri[uri];
}
topClaimValue() {
if (!this.claim()) return null;
return parseFloat(this.claim().amount);
}
myClaimExists() {
const { myClaims } = this.props;
const { name } = this.state;
if (!name) return false;
return !!myClaims.find(claim => claim.name === name);
}
topClaimIsMine() {
const myClaimInfo = this.myClaimInfo();
const { claimsByUri } = this.props;
const { uri } = this.state;
if (!uri) return null;
const claim = claimsByUri[uri];
if (!claim) return true;
if (!myClaimInfo) return false;
return myClaimInfo.amount >= claimInfo.amount;
}
myClaimInfo() {
2017-06-15 21:30:56 +02:00
const { name } = this.state;
return Object.values(this.props.myClaims).find(
claim => claim.name === name
);
}
2017-05-17 10:10:25 +02:00
handleNameChange(event) {
var rawName = event.target.value;
2016-07-15 14:04:47 +02:00
2017-06-17 19:59:18 +02:00
this.nameChanged(rawName);
}
nameChanged(rawName) {
if (!rawName) {
2016-07-15 14:04:47 +02:00
this.setState({
2017-06-06 23:19:12 +02:00
rawName: "",
name: "",
uri: "",
});
2016-07-15 14:04:47 +02:00
return;
}
if (!lbryuri.isValidName(rawName, false)) {
2017-06-06 23:19:12 +02:00
this.refs.name.showError(
__("LBRY names must contain only letters, numbers and dashes.")
);
return;
}
2017-06-17 19:59:18 +02:00
let channel = "";
if (this.state.channel !== "anonymous") channel = this.state.channel;
const name = rawName.toLowerCase();
2017-06-17 19:59:18 +02:00
const uri = lbryuri.build({ contentName: name, channelName: channel });
this.setState({
rawName: rawName,
name: name,
2017-06-15 21:30:56 +02:00
prefillDone: false,
uri,
});
2017-06-17 19:59:18 +02:00
if (this.resolveUriTimeout) {
clearTimeout(this.resolveUriTimeout);
this.resolveUriTimeout = undefined;
}
const resolve = () => this.props.resolveUri(uri);
this.resolveUriTimeout = setTimeout(resolve.bind(this), 500, {
once: true,
});
2017-05-17 10:10:25 +02:00
}
2017-06-15 21:30:56 +02:00
handlePrefillClicked() {
const {license, licenseUrl, title, thumbnail, description,
language, nsfw} = this.myClaimInfo().value.stream.metadata;
let newState = {
meta_title: title,
meta_thumbnail: thumbnail,
meta_description: description,
meta_language: language,
meta_nsfw: nsfw,
};
if (license == this._defaultCopyrightNotice) {
newState.licenseType = "copyright";
newState.copyrightNotice = this._defaultCopyrightNotice;
} else {
// If the license URL or description matches one of the drop-down options, use that
let licenseType = "other"; // Will be overridden if we find a match
for (let option of this._meta_license.getOptions()) {
if (
option.getAttribute("data-url") === licenseUrl ||
option.text === license
) {
licenseType = option.value;
}
}
if (licenseType == "other") {
newState.otherLicenseDescription = license;
newState.otherLicenseUrl = licenseUrl;
}
newState.licenseType = licenseType;
}
this.setState(newState);
}
2017-05-17 10:10:25 +02:00
handleBidChange(event) {
2016-07-15 14:04:47 +02:00
this.setState({
bid: event.target.value,
2016-07-15 14:04:47 +02:00
});
2017-05-17 10:10:25 +02:00
}
handleFeeAmountChange(event) {
2016-07-15 14:04:47 +02:00
this.setState({
feeAmount: event.target.value,
});
2017-05-17 10:10:25 +02:00
}
handleFeeCurrencyChange(event) {
this.setState({
feeCurrency: event.target.value,
});
2017-05-17 10:10:25 +02:00
}
handleFeePrefChange(feeEnabled) {
this.setState({
2017-06-06 23:19:12 +02:00
isFee: feeEnabled,
2016-07-15 14:04:47 +02:00
});
2017-05-17 10:10:25 +02:00
}
2017-06-15 21:30:56 +02:00
handleMetadataChange(event) {
/**
* This function is used for all metadata inputs that store the final value directly into state.
* The only exceptions are inputs related to license description and license URL, which require
* more complex logic and the final value is determined at submit time.
*/
this.setState({
["meta_" + event.target.name]: event.target.value,
});
}
2016-09-20 12:40:24 +02:00
2017-06-15 21:30:56 +02:00
handleLicenseTypeChange(event) {
this.setState({
licenseType: event.target.value,
});
2017-05-17 10:10:25 +02:00
}
handleCopyrightNoticeChange(event) {
2016-09-20 12:40:24 +02:00
this.setState({
copyrightNotice: event.target.value,
});
2017-05-17 10:10:25 +02:00
}
handleOtherLicenseDescriptionChange(event) {
2016-09-20 12:40:24 +02:00
this.setState({
otherLicenseDescription: event.target.value,
});
2017-05-17 10:10:25 +02:00
}
handleOtherLicenseUrlChange(event) {
2016-09-20 12:40:24 +02:00
this.setState({
otherLicenseUrl: event.target.value,
});
2017-05-17 10:10:25 +02:00
}
2017-06-17 19:59:18 +02:00
handleChannelChange(channelName) {
this.setState({
2017-06-17 19:59:18 +02:00
channel: channelName,
});
2017-06-17 19:59:18 +02:00
const nameChanged = () => this.nameChanged(this.state.rawName);
setTimeout(nameChanged.bind(this), 500, { once: true });
2017-05-17 10:10:25 +02:00
}
handleTOSChange(event) {
this.setState({
2017-06-15 21:30:56 +02:00
tosAgree: event.target.checked,
});
2017-05-17 10:10:25 +02:00
}
handleCreateChannelClick(event) {
if (this.state.newChannelName.length < 5) {
2017-06-06 23:19:12 +02:00
this.refs.newChannelName.showError(
__("LBRY channel names must be at least 4 characters in length.")
);
return;
}
this.setState({
creatingChannel: true,
});
const newChannelName = this.state.newChannelName;
2017-06-06 23:19:12 +02:00
lbry
.channel_new({
channel_name: newChannelName,
2017-06-09 01:25:42 +02:00
amount: parseFloat(this.state.newChannelBid),
2017-06-06 23:19:12 +02:00
})
.then(
() => {
setTimeout(() => {
this.setState({
creatingChannel: false,
});
this._updateChannelList(newChannelName);
2017-06-28 20:00:10 +02:00
}, 10000);
2017-06-06 23:19:12 +02:00
},
error => {
// TODO: better error handling
this.refs.newChannelName.showError(
__("Unable to create channel due to an internal error.")
);
this.setState({
creatingChannel: false,
});
}
);
2017-05-17 10:10:25 +02:00
}
2017-06-15 21:30:56 +02:00
getLicense() {
switch (this.state.licenseType) {
case "copyright":
return this.state.copyrightNotice;
case "other":
return this.state.otherLicenseDescription;
default:
return this._meta_license.getSelectedElement().text;
}
}
2017-05-17 10:10:25 +02:00
getLicenseUrl() {
2017-06-15 21:30:56 +02:00
switch (this.state.licenseType) {
case "copyright":
return "";
case "other":
return this.state.otherLicenseUrl;
default:
return this._meta_license.getSelectedElement().getAttribute("data-url");
2016-09-20 12:40:24 +02:00
}
2017-05-17 10:10:25 +02:00
}
componentWillMount() {
this.props.fetchClaimListMine();
this._updateChannelList();
2017-05-17 10:10:25 +02:00
}
onFileChange() {
2017-04-10 20:12:07 +02:00
if (this.refs.file.getValue()) {
2017-06-06 23:19:12 +02:00
this.setState({ hasFile: true });
2017-04-10 20:12:07 +02:00
} else {
2017-06-06 23:19:12 +02:00
this.setState({ hasFile: false });
2017-04-10 20:12:07 +02:00
}
2017-05-17 10:10:25 +02:00
}
getNameBidHelpText() {
if (
this.state.uri &&
2017-06-17 19:59:18 +02:00
this.props.resolvingUris.indexOf(this.state.uri) !== -1 &&
this.claim() === undefined
) {
2017-06-15 21:30:56 +02:00
return __("Checking...");
} else if (!this.state.name) {
2017-05-22 14:29:30 +02:00
return __("Select a URL for this publish.");
} else if (!this.claim()) {
2017-05-22 14:29:30 +02:00
return __("This URL is unused.");
2017-06-17 19:59:18 +02:00
} else if (this.myClaimExists() && !this.state.prefillDone) {
return (
<Notice>
{__("You already have a claim with this name.")}{" "}
<Link
label={__("Use data from my existing claim")}
onClick={() => this.handlePrefillClicked()}
/>
</Notice>
2017-06-06 23:19:12 +02:00
);
2017-06-17 19:59:18 +02:00
} else if (this.claim()) {
if (this.topClaimValue() === 1) {
2017-06-19 14:58:39 +02:00
return (
<span>
{__(
2017-06-20 14:08:52 +02:00
'A deposit of at least one credit is required to win "%s". However, you can still get a permanent URL for any amount.',
this.state.name
2017-06-19 14:58:39 +02:00
)}
</span>
);
} else {
return (
<span>
{__(
2017-06-20 14:08:52 +02:00
'A deposit of at least "%s" credits is required to win "%s". However, you can still get a permanent URL for any amount.',
2017-06-17 19:59:18 +02:00
this.topClaimValue(),
2017-06-20 14:08:52 +02:00
this.state.name
2017-06-19 14:58:39 +02:00
)}
</span>
);
}
2017-04-10 20:12:07 +02:00
} else {
2017-06-06 23:19:12 +02:00
return "";
2017-04-10 20:12:07 +02:00
}
2017-05-17 10:10:25 +02:00
}
closeModal() {
2017-04-12 16:55:19 +02:00
this.setState({
modal: null,
});
2017-05-17 10:10:25 +02:00
}
render() {
2017-06-06 23:19:12 +02:00
const lbcInputHelp = __(
"This LBC remains yours and the deposit can be undone at any time."
);
2017-04-12 16:55:19 +02:00
2016-05-23 17:14:21 +02:00
return (
<main className="main--single-column">
2017-06-06 23:19:12 +02:00
<form
onSubmit={event => {
this.handleSubmit(event);
}}
>
<section className="card">
2017-04-10 14:32:40 +02:00
<div className="card__title-primary">
2017-05-22 14:29:30 +02:00
<h4>{__("Content")}</h4>
2017-04-10 20:12:07 +02:00
<div className="card__subtitle">
2017-05-22 14:29:30 +02:00
{__("What are you publishing?")}
2017-04-10 20:12:07 +02:00
</div>
2017-04-10 14:32:40 +02:00
</div>
<div className="card__content">
2017-06-06 23:19:12 +02:00
<FormRow
name="file"
label="File"
ref="file"
type="file"
onChange={event => {
this.onFileChange(event);
}}
helper={
this.myClaimExists()
2017-06-06 23:19:12 +02:00
? __(
"If you don't choose a file, the file from your existing claim will be used."
)
: null
}
/>
</div>
2017-06-15 21:30:56 +02:00
{!this.state.hasFile && !this.myClaimExists()
? null
2017-06-06 23:19:12 +02:00
: <div>
<div className="card__content">
<FormRow
label={__("Title")}
type="text"
name="title"
2017-06-15 21:30:56 +02:00
value={this.state.meta_title}
placeholder="Titular Title"
onChange={event => {
this.handleMetadataChange(event);
}}
2017-06-06 23:19:12 +02:00
/>
</div>
<div className="card__content">
<FormRow
type="text"
label={__("Thumbnail URL")}
name="thumbnail"
2017-06-15 21:30:56 +02:00
value={this.state.meta_thumbnail}
2017-06-06 23:19:12 +02:00
placeholder="http://spee.ch/mylogo"
2017-06-15 21:30:56 +02:00
onChange={event => {
this.handleMetadataChange(event);
}}
2017-06-06 23:19:12 +02:00
/>
</div>
<div className="card__content">
<FormRow
label={__("Description")}
2017-06-15 21:30:56 +02:00
type="SimpleMDE"
2017-06-06 23:19:12 +02:00
ref="meta_description"
name="description"
2017-06-15 21:30:56 +02:00
value={this.state.meta_description}
2017-06-06 23:19:12 +02:00
placeholder={__("Description of your content")}
2017-06-15 21:30:56 +02:00
onChange={event => {
this.handleMetadataChange(event);
}}
2017-06-06 23:19:12 +02:00
/>
</div>
<div className="card__content">
<FormRow
label={__("Language")}
type="select"
2017-06-15 21:30:56 +02:00
value={this.state.meta_language}
2017-06-06 23:19:12 +02:00
name="language"
2017-06-15 21:30:56 +02:00
onChange={event => {
this.handleMetadataChange(event);
}}
2017-06-06 23:19:12 +02:00
>
<option value="en">{__("English")}</option>
<option value="zh">{__("Chinese")}</option>
<option value="fr">{__("French")}</option>
<option value="de">{__("German")}</option>
<option value="jp">{__("Japanese")}</option>
<option value="ru">{__("Russian")}</option>
<option value="es">{__("Spanish")}</option>
</FormRow>
</div>
<div className="card__content">
<FormRow
type="select"
label={__("Maturity")}
2017-06-15 21:30:56 +02:00
value={this.state.meta_nsfw}
2017-06-06 23:19:12 +02:00
name="nsfw"
2017-06-15 21:30:56 +02:00
onChange={event => {
this.handleMetadataChange(event);
}}
2017-06-06 23:19:12 +02:00
>
{/* <option value=""></option> */}
<option value="0">{__("All Ages")}</option>
<option value="1">{__("Adults Only")}</option>
</FormRow>
</div>
</div>}
</section>
2016-05-23 17:14:21 +02:00
<section className="card">
2017-04-10 20:12:07 +02:00
<div className="card__title-primary">
2017-05-22 14:29:30 +02:00
<h4>{__("Access")}</h4>
2017-04-10 20:12:07 +02:00
<div className="card__subtitle">
2017-05-22 14:29:30 +02:00
{__("How much does this content cost?")}
2017-04-10 20:12:07 +02:00
</div>
</div>
2017-04-10 14:32:40 +02:00
<div className="card__content">
2017-04-10 20:12:07 +02:00
<div className="form-row__label-row">
2017-05-22 14:29:30 +02:00
<label className="form-row__label">{__("Price")}</label>
</div>
2017-06-06 23:19:12 +02:00
<FormRow
label={__("Free")}
type="radio"
name="isFree"
value="1"
onChange={() => {
this.handleFeePrefChange(false);
}}
defaultChecked={!this.state.isFee}
/>
<FormField
type="radio"
name="isFree"
label={!this.state.isFee ? __("Choose price...") : __("Price ")}
onChange={() => {
this.handleFeePrefChange(true);
}}
defaultChecked={this.state.isFee}
/>
<span className={!this.state.isFee ? "hidden" : ""}>
<FormField
type="number"
className="form-field__input--inline"
step="0.01"
placeholder="1.00"
2017-06-09 01:25:42 +02:00
min="0.01"
2017-06-06 23:19:12 +02:00
onChange={event => this.handleFeeAmountChange(event)}
2017-06-15 21:30:56 +02:00
/>{" "}
2017-06-06 23:19:12 +02:00
<FormField
type="select"
onChange={event => {
this.handleFeeCurrencyChange(event);
}}
>
<option value="USD">{__("US Dollars")}</option>
<option value="LBC">{__("LBRY credits")}</option>
</FormField>
</span>
{this.state.isFee
? <div className="form-field__helper">
{__(
"If you choose to price this content in dollars, the number of credits charged will be adjusted based on the value of LBRY credits at the time of purchase."
)}
</div>
: ""}
<FormRow
label="License"
type="select"
2017-06-15 21:30:56 +02:00
value={this.state.licenseType}
ref={row => {
this._meta_license = row;
}}
2017-06-06 23:19:12 +02:00
onChange={event => {
2017-06-15 21:30:56 +02:00
this.handleLicenseTypeChange(event);
2017-06-06 23:19:12 +02:00
}}
>
<option />
2017-06-15 21:30:56 +02:00
<option value="publicDomain">{__("Public Domain")}</option>
<option
value="cc-by"
data-url="https://creativecommons.org/licenses/by/4.0/legalcode"
>
2017-06-06 23:19:12 +02:00
{__("Creative Commons Attribution 4.0 International")}
</option>
2017-06-15 21:30:56 +02:00
<option
value="cc-by-sa"
data-url="https://creativecommons.org/licenses/by-sa/4.0/legalcode"
>
2017-06-06 23:19:12 +02:00
{__(
"Creative Commons Attribution-ShareAlike 4.0 International"
)}
</option>
2017-06-15 21:30:56 +02:00
<option
value="cc-by-nd"
data-url="https://creativecommons.org/licenses/by-nd/4.0/legalcode"
>
2017-06-06 23:19:12 +02:00
{__(
"Creative Commons Attribution-NoDerivatives 4.0 International"
)}
</option>
2017-06-15 21:30:56 +02:00
<option
value="cc-by-nc"
data-url="https://creativecommons.org/licenses/by-nc/4.0/legalcode"
>
2017-06-06 23:19:12 +02:00
{__(
"Creative Commons Attribution-NonCommercial 4.0 International"
)}
</option>
2017-06-15 21:30:56 +02:00
<option
value="cc-by-nc-sa"
data-url="https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode"
>
2017-06-06 23:19:12 +02:00
{__(
"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International"
)}
</option>
2017-06-15 21:30:56 +02:00
<option
value="cc-by-nc-nd"
data-url="https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode"
>
2017-06-06 23:19:12 +02:00
{__(
"Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International"
)}
</option>
2017-06-15 21:30:56 +02:00
<option value="copyright">
2017-06-06 23:19:12 +02:00
{__("Copyrighted...")}
</option>
2017-06-15 21:30:56 +02:00
<option value="other">
2017-06-06 23:19:12 +02:00
{__("Other...")}
</option>
2017-04-10 20:12:07 +02:00
</FormRow>
2017-06-15 21:30:56 +02:00
{this.state.licenseType == "copyright"
2017-06-06 23:19:12 +02:00
? <FormRow
label={__("Copyright notice")}
type="text"
name="copyright-notice"
value={this.state.copyrightNotice}
onChange={event => {
this.handleCopyrightNoticeChange(event);
}}
/>
2017-04-10 20:12:07 +02:00
: null}
2017-06-15 21:30:56 +02:00
{this.state.licenseType == "other"
2017-06-06 23:19:12 +02:00
? <FormRow
label={__("License description")}
type="text"
name="other-license-description"
2017-06-15 21:30:56 +02:00
value={this.state.otherLicenseDescription}
2017-06-06 23:19:12 +02:00
onChange={event => {
2017-06-15 21:30:56 +02:00
this.handleOtherLicenseDescriptionChange(event);
2017-06-06 23:19:12 +02:00
}}
/>
2017-04-10 20:12:07 +02:00
: null}
2017-06-15 21:30:56 +02:00
{this.state.licenseType == "other"
2017-06-06 23:19:12 +02:00
? <FormRow
label={__("License URL")}
type="text"
name="other-license-url"
2017-06-15 21:30:56 +02:00
value={this.state.otherLicenseUrl}
2017-06-06 23:19:12 +02:00
onChange={event => {
this.handleOtherLicenseUrlChange(event);
}}
/>
2017-04-10 20:12:07 +02:00
: null}
2016-08-08 05:31:21 +02:00
</div>
</section>
2017-06-17 19:59:18 +02:00
<ChannelSection
{...this.props}
handleChannelChange={this.handleChannelChange.bind(this)}
channel={this.state.channel}
/>
<section className="card">
2017-04-10 20:12:07 +02:00
<div className="card__title-primary">
2017-05-22 14:29:30 +02:00
<h4>{__("Address")}</h4>
2017-06-06 23:19:12 +02:00
<div className="card__subtitle">
{__("Where should this content permanently reside?")}
{" "}
<Link
label={__("Read more")}
href="https://lbry.io/faq/naming"
/>.
</div>
2017-04-10 20:12:07 +02:00
</div>
<div className="card__content">
2017-06-06 23:19:12 +02:00
<FormRow
2017-06-17 19:59:18 +02:00
prefix={`lbry://${this.state.channel === "anonymous"
? ""
: `${this.state.channel}/`}`}
2017-06-06 23:19:12 +02:00
type="text"
ref="name"
placeholder="myname"
value={this.state.rawName}
onChange={event => {
this.handleNameChange(event);
}}
helper={this.getNameBidHelpText()}
/>
2017-06-15 21:30:56 +02:00
{this.myClaimExists() && !this.state.prefillDone
? <Notice>
{__("You already have a claim with this name.")}{" "}
<Link
label={__("Use data from my existing claim")}
onClick={() => this.handlePrefillClicked()}
/>
</Notice>
: null}
</div>
2017-06-06 23:19:12 +02:00
{this.state.rawName
? <div className="card__content">
<FormRow
ref="bid"
type="number"
step="0.01"
label={__("Deposit")}
postfix="LBC"
onChange={event => {
this.handleBidChange(event);
}}
value={this.state.bid}
placeholder={this.claim() ? this.topClaimValue() + 10 : 100}
2017-06-06 23:19:12 +02:00
helper={lbcInputHelp}
/>
</div>
: ""}
</section>
2016-05-23 17:14:21 +02:00
<section className="card">
<div className="card__title-primary">
2017-05-22 14:29:30 +02:00
<h4>{__("Terms of Service")}</h4>
</div>
<div className="card__content">
2017-06-06 23:19:12 +02:00
<FormRow
label={
<span>
{__("I agree to the")}
{" "}
<Link
href="https://www.lbry.io/termsofservice"
label={__("LBRY terms of service")}
/>
</span>
}
type="checkbox"
2017-06-15 21:30:56 +02:00
checked={this.state.tosAgree}
2017-06-06 23:19:12 +02:00
onChange={event => {
this.handleTOSChange(event);
}}
/>
</div>
</section>
<div className="card-series-submit">
2017-06-06 23:19:12 +02:00
<Link
button="primary"
label={
!this.state.submitting ? __("Publish") : __("Publishing...")
}
onClick={event => {
this.handleSubmit(event);
}}
disabled={this.state.submitting}
/>
<Link
button="cancel"
onClick={this.props.back}
label={__("Cancel")}
/>
<input type="submit" className="hidden" />
</div>
</form>
2017-06-06 23:19:12 +02:00
<Modal
isOpen={this.state.modal == "publishStarted"}
contentLabel={__("File published")}
onConfirmed={event => {
this.handlePublishStartedConfirmed(event);
}}
>
<p>
{__("Your file has been published to LBRY at the address")}
{" "}<code>{this.state.uri}</code>!
2017-06-06 23:19:12 +02:00
</p>
<p>
{__(
'The file will take a few minutes to appear for other LBRY users. Until then it will be listed as "pending" under your published files.'
)}
</p>
</Modal>
2017-06-06 23:19:12 +02:00
<Modal
isOpen={this.state.modal == "error"}
contentLabel={__("Error publishing file")}
onConfirmed={event => {
this.closeModal(event);
}}
>
{__(
"The following error occurred when attempting to publish your file"
)}: {this.state.errorMessage}
</Modal>
</main>
2016-05-23 17:14:21 +02:00
);
}
2017-05-17 10:10:25 +02:00
}
2016-11-22 21:19:08 +01:00
2017-06-17 19:59:18 +02:00
class ChannelSection extends React.PureComponent {
constructor(props) {
super(props);
this.state = {
newChannelName: "@",
newChannelBid: 10,
addingChannel: false,
};
}
handleChannelChange(event) {
const channel = event.target.value;
if (channel === "new") this.setState({ addingChannel: true });
else {
this.setState({ addingChannel: false });
this.props.handleChannelChange(event.target.value);
}
}
handleNewChannelNameChange(event) {
const newChannelName = event.target.value.startsWith("@")
? event.target.value
: "@" + event.target.value;
if (
newChannelName.length > 1 &&
!lbryuri.isValidName(newChannelName.substr(1), false)
) {
this.refs.newChannelName.showError(
__("LBRY channel names must contain only letters, numbers and dashes.")
);
return;
} else {
this.refs.newChannelName.clearError();
}
this.setState({
newChannelName,
});
}
handleNewChannelBidChange(event) {
this.setState({
newChannelBid: event.target.value,
});
}
handleCreateChannelClick(event) {
if (this.state.newChannelName.length < 5) {
this.refs.newChannelName.showError(
__("LBRY channel names must be at least 4 characters in length.")
);
return;
}
this.setState({
creatingChannel: true,
});
const newChannelName = this.state.newChannelName;
const amount = parseFloat(this.state.newChannelBid);
this.setState({
creatingChannel: true,
});
const success = (() => {
this.setState({
creatingChannel: false,
addingChannel: false,
channel: newChannelName,
});
this.props.handleChannelChange(newChannelName);
}).bind(this);
const failure = (err => {
this.setState({
creatingChannel: false,
});
this.refs.newChannelName.showError(
__("Unable to create channel due to an internal error.")
);
}).bind(this);
this.props.createChannel(newChannelName, amount).then(success, failure);
}
render() {
const lbcInputHelp = __(
"This LBC remains yours and the deposit can be undone at any time."
);
const { fetchingChannels, channels } = this.props;
let channelContent = [];
if (channels.length > 0) {
channelContent.push(
<FormRow
key="channel"
type="select"
tabIndex="1"
onChange={this.handleChannelChange.bind(this)}
value={this.props.channel}
>
<option key="anonymous" value="anonymous">
{__("Anonymous")}
</option>
{this.props.channels.map(({ name }) =>
<option key={name} value={name}>{name}</option>
)}
<option key="new" value="new">
{__("New identity...")}
</option>
</FormRow>
);
if (fetchingChannels) {
channelContent.push(
<BusyMessage message="Updating channels" key="loading" />
);
}
} else if (fetchingChannels) {
channelContent.push(
<BusyMessage message="Loading channels" key="loading" />
);
}
return (
<section className="card">
<div className="card__title-primary">
<h4>{__("Identity")}</h4>
<div className="card__subtitle">
{__("Who created this content?")}
</div>
</div>
<div className="card__content">
{channelContent}
</div>
{this.state.addingChannel &&
<div className="card__content">
<FormRow
label={__("Name")}
type="text"
onChange={event => {
this.handleNewChannelNameChange(event);
}}
value={this.state.newChannelName}
/>
<FormRow
label={__("Deposit")}
postfix="LBC"
step="0.1"
min="0"
type="number"
helper={lbcInputHelp}
ref="newChannelName"
onChange={this.handleNewChannelBidChange.bind(this)}
value={this.state.newChannelBid}
/>
<div className="form-row-submit">
<Link
button="primary"
label={
!this.state.creatingChannel
? __("Create identity")
: __("Creating identity...")
}
onClick={this.handleCreateChannelClick.bind(this)}
disabled={this.state.creatingChannel}
/>
</div>
</div>}
</section>
);
}
}
2016-11-22 21:19:08 +01:00
export default PublishPage;