import React from 'react'; import lbry from '../lbry.js'; import uri from '../uri.js'; import {FormField, FormRow} from '../component/form.js'; import {Link} from '../component/link.js'; import Modal from '../component/modal.js'; var PublishPage = React.createClass({ _requiredFields: ['name', 'bid', 'meta_title', 'meta_author', 'meta_license', 'meta_description'], _updateChannelList: function(channel) { // Calls API to update displayed list of channels. If a channel name is provided, will select // that channel at the same time (used immediately after creating a channel) lbry.channel_list_mine().then((channels) => { this.setState({ channels: channels, ... channel ? {channel} : {} }); }); }, handleSubmit: function(event) { if (typeof event !== 'undefined') { event.preventDefault(); } this.setState({ submitting: true, }); var checkFields = this._requiredFields.slice(); if (!this.state.myClaimExists) { checkFields.push('file'); } var missingFieldFound = false; for (let fieldName of checkFields) { var field = this.refs[fieldName]; if (field.getValue() === '') { field.showRequiredError(); if (!missingFieldFound) { field.focus(); missingFieldFound = true; } } } if (missingFieldFound) { this.setState({ submitting: false, }); return; } if (this.state.nameIsMine) { // Pre-populate with existing metadata var metadata = Object.assign({}, this.state.myClaimMetadata); if (this.refs.file.getValue() !== '') { delete metadata.sources; } } else { var metadata = {}; } for (let metaField of ['title', 'author', 'description', 'thumbnail', 'license', 'license_url', 'language', 'nsfw']) { var value = this.refs['meta_' + metaField].getValue(); if (value !== '') { metadata[metaField] = value; } } var licenseUrl = this.refs.meta_license_url.getValue(); if (licenseUrl) { metadata.license_url = licenseUrl; } var doPublish = () => { var publishArgs = { name: this.state.name, bid: parseFloat(this.state.bid), metadata: metadata, ... this.state.channel != 'new' && this.state.channel != 'anonymous' ? {channel_name: this.state.channel} : {}, }; if (this.refs.file.getValue() !== '') { publishArgs.file_path = this.refs.file.getValue(); } lbry.publish(publishArgs, (message) => { this.handlePublishStarted(); }, null, (error) => { this.handlePublishError(error); }); }; if (this.state.isFee) { lbry.getUnusedAddress((address) => { metadata.fee = {}; metadata.fee[this.state.feeCurrency] = { amount: parseFloat(this.state.feeAmount), address: address, }; doPublish(); }); } else { doPublish(); } }, getInitialState: function() { return { channels: null, rawName: '', name: '', bid: '', feeAmount: '', feeCurrency: 'USD', channel: 'anonymous', newChannelName: '@', newChannelBid: '', nameResolved: false, topClaimValue: 0.0, myClaimValue: 0.0, myClaimMetadata: null, myClaimExists: null, copyrightNotice: '', otherLicenseDescription: '', otherLicenseUrl: '', uploadProgress: 0.0, uploaded: false, errorMessage: null, submitting: false, creatingChannel: false, modal: null, }; }, handlePublishStarted: function() { this.setState({ modal: 'publishStarted', }); }, handlePublishStartedConfirmed: function() { window.location = "?published"; }, handlePublishError: function(error) { this.setState({ submitting: false, modal: 'error', errorMessage: error.message, }); }, handleNameChange: function(event) { var rawName = event.target.value; if (!rawName) { this.setState({ rawName: '', name: '', nameResolved: false, }); return; } if (!lbry.nameIsValid(rawName, false)) { this.refs.name.showError('LBRY names must contain only letters, numbers and dashes.'); return; } this.setState({ rawName: rawName, }); const name = rawName.toLowerCase(); lbry.getMyClaim(name, (myClaimInfo) => { if (name != this.refs.name.getValue().toLowerCase()) { // A new name has been typed already, so bail return; } lbry.resolve({uri: name}).then((claimInfo) => { if (name != this.refs.name.getValue()) { return; } if (!claimInfo) { this.setState({ name: name, nameResolved: false, myClaimExists: false, }); } else { const topClaimIsMine = (myClaimInfo && myClaimInfo.claim.amount >= claimInfo.claim.amount); const newState = { name: name, nameResolved: true, topClaimValue: parseFloat(claimInfo.claim.amount), myClaimExists: !!myClaimInfo, myClaimValue: myClaimInfo ? parseFloat(myClaimInfo.claim.amount) : null, myClaimMetadata: myClaimInfo ? myClaimInfo.value : null, topClaimIsMine: topClaimIsMine, }; if (topClaimIsMine) { newState.bid = myClaimInfo.claim.amount; } else if (this.state.myClaimMetadata) { // Just changed away from a name we have a claim on, so clear pre-fill newState.bid = ''; } this.setState(newState); } }, () => { // Assume an error means the name is available this.setState({ name: name, nameResolved: false, myClaimExists: false, }); }); }); }, handleBidChange: function(event) { this.setState({ bid: event.target.value, }); }, handleFeeAmountChange: function(event) { this.setState({ feeAmount: event.target.value, }); }, handleFeeCurrencyChange: function(event) { this.setState({ feeCurrency: event.target.value, }); }, handleFeePrefChange: function(feeEnabled) { this.setState({ isFee: feeEnabled }); }, handeLicenseChange: function(event) { var licenseType = event.target.options[event.target.selectedIndex].getAttribute('data-license-type'); var newState = { copyrightChosen: licenseType == 'copyright', otherLicenseChosen: licenseType == 'other', }; if (licenseType == 'copyright') { var author = this.refs.meta_author.getValue(); newState.copyrightNotice = 'Copyright ' + (new Date().getFullYear()) + (author ? ' ' + author : ''); } this.setState(newState); }, handleCopyrightNoticeChange: function(event) { this.setState({ copyrightNotice: event.target.value, }); }, handleOtherLicenseDescriptionChange: function(event) { this.setState({ otherLicenseDescription: event.target.value, }); }, handleOtherLicenseUrlChange: function(event) { this.setState({ otherLicenseUrl: event.target.value, }); }, handleChannelChange: function (event) { const channel = event.target.value; this.setState({ channel: channel, }); }, handleNewChannelNameChange: function (event) { const newChannelName = (event.target.value.startsWith('@') ? event.target.value : '@' + event.target.value); if (newChannelName.length > 1 && !lbry.nameIsValid(newChannelName.substr(1), false)) { this.refs.newChannelName.showAdvice('LBRY channel names must contain only letters, numbers and dashes.'); return; } this.setState({ newChannelName: newChannelName, }); }, handleNewChannelBidChange: function (event) { this.setState({ newChannelBid: event.target.value, }); }, handleCreateChannelClick: function (event) { if (this.state.newChannelName.length < 5) { this.refs.newChannelName.showAdvice('LBRY channel names must be at least 4 characters in length.'); return; } this.setState({ creatingChannel: true, }); const newChannelName = this.state.newChannelName; lbry.channel_new({channel_name: newChannelName, amount: parseInt(this.state.newChannelBid)}).then(() => { setTimeout(() => { this.setState({ creatingChannel: false, }); this._updateChannelList(newChannelName); }, 5000); }, (error) => { // TODO: better error handling this.refs.newChannelName.showAdvice('Unable to create channel due to an internal error.'); this.setState({ creatingChannel: false, }); }); }, getLicenseUrl: function() { if (!this.refs.meta_license) { return ''; } else if (this.state.otherLicenseChosen) { return this.state.otherLicenseUrl; } else { return this.refs.meta_license.getSelectedElement().getAttribute('data-url') || '' ; } }, componentWillMount: function() { this._updateChannelList(); }, componentDidMount: function() { document.title = "Publish"; }, componentDidUpdate: function() { }, // Also getting a type warning here too render: function() { if (this.state.channels === null) { return null; } return (

LBRY Name

What LBRY name would you like to claim for this file? .
)} /> { (!this.state.name ? null : (!this.state.nameResolved ? The name {this.state.name} is available. : (this.state.myClaimExists ? You already have a claim on the name {this.state.name}. You can use this page to update your claim. : The name {this.state.name} is currently claimed for {this.state.topClaimValue} {this.state.topClaimValue == 1 ? 'credit' : 'credits'}.))) }

Channel

{this.state.channels.map(({name}) => )} {this.state.channel == 'new' ?
: null}
What channel would you like to publish this file under?

Choose File

{ this.state.myClaimExists ?
If you don't choose a file, the file from your existing claim will be used.
: null }

Bid Amount

Credits
How much would you like to bid for this name? { !this.state.nameResolved ? Since this name is not currently resolved, you may bid as low as you want, but higher bids help prevent others from claiming your name. : (this.state.topClaimIsMine ? You currently control this name with a bid of {this.state.myClaimValue} {this.state.myClaimValue == 1 ? 'credit' : 'credits'}. : (this.state.myClaimExists ? You have a non-winning bid on this name for {this.state.myClaimValue} {this.state.myClaimValue == 1 ? 'credit' : 'credits'}. To control this name, you'll need to increase your bid to more than {this.state.topClaimValue} {this.state.topClaimValue == 1 ? 'credit' : 'credits'}. : You must bid over {this.state.topClaimValue} {this.state.topClaimValue == 1 ? 'credit' : 'credits'} to claim this name.)) }

Fee

How much would you like to charge for this file?

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.

Your Content

{this.state.copyrightChosen ?
: null} {this.state.otherLicenseChosen ?
: null} {this.state.otherLicenseChosen ?
: null}

Additional Content Information (Optional)

Your file has been published to LBRY at the address lbry://{this.state.name}!

You will now be taken to your My Files page, where your newly published file will be listed. The file will take a few minutes to appear for other LBRY users; until then it will be listed as "pending."
The following error occurred when attempting to publish your file: {this.state.errorMessage}
); } }); export default PublishPage;