This commit is contained in:
Jeremy Kauffman 2017-04-10 14:12:07 -04:00
parent cbb3da2795
commit 029b0b9c3a
10 changed files with 265 additions and 200 deletions

View file

@ -157,7 +157,7 @@ export const AuthOverlay = React.createClass({
getInitialState: function() { getInitialState: function() {
return { return {
stage: "welcome", stage: "pending",
stageProps: {} stageProps: {}
}; };
}, },
@ -167,36 +167,36 @@ export const AuthOverlay = React.createClass({
}); });
}, },
componentWillMount: function() { componentWillMount: function() {
// lbryio.authenticate().then(function(user) { lbryio.authenticate().then(function(user) {
// if (!user.HasVerifiedEmail) { //oops I fucked this up if (!user.HasVerifiedEmail) { //oops I fucked this up
// this.setState({ this.setState({
// stage: "email", stage: "email",
// stageProps: { stageProps: {
// onEmailSaved: function() { onEmailSaved: function() {
// this.setState({ this.setState({
// stage: "confirm", stage: "confirm",
// stageProps: { stageProps: {
// onEmailConfirmed: function() { this.setState({ stage: "welcome"}) }.bind(this) onEmailConfirmed: function() { this.setState({ stage: "welcome"}) }.bind(this)
// } }
// }) })
// }.bind(this) }.bind(this)
// } }
// }) })
// } else { } else {
// this.endAuth() this.endAuth()
// } }
// }.bind(this)).catch((err) => { }.bind(this)).catch((err) => {
// this.setState({ this.setState({
// stage: "error", stage: "error",
// stageProps: { errorText: err.message } stageProps: { errorText: err.message }
// }) })
// document.dispatchEvent(new CustomEvent('unhandledError', { document.dispatchEvent(new CustomEvent('unhandledError', {
// detail: { detail: {
// message: err.message, message: err.message,
// data: err.stack data: err.stack
// } }
// })); }));
// }) })
}, },
render: function() { render: function() {
if (!this.state.stage || lbryio.user && lbryio.user.HasVerifiedEmail) { if (!this.state.stage || lbryio.user && lbryio.user.HasVerifiedEmail) {

View file

@ -294,7 +294,7 @@ export let FileActions = React.createClass({
? <FileActionsRow outpoint={this.props.outpoint} metadata={this.props.metadata} uri={this.props.uri} ? <FileActionsRow outpoint={this.props.outpoint} metadata={this.props.metadata} uri={this.props.uri}
contentType={this.props.contentType} /> contentType={this.props.contentType} />
: <div> : <div>
<div className="button-set-item empty">This file is not currently available.</div> <div className="button-set-item empty">Content unavailable.</div>
<ToolTip label="Why?" <ToolTip label="Why?"
body="The content on LBRY is hosted by its users. It appears there are no users connected that have this file at the moment." body="The content on LBRY is hosted by its users. It appears there are no users connected that have this file at the moment."
className="button-set-item" /> className="button-set-item" />

View file

@ -140,6 +140,7 @@ export let FileTileStream = React.createClass({
{ !this.props.hidePrice { !this.props.hidePrice
? <FilePrice uri={this.props.uri} /> ? <FilePrice uri={this.props.uri} />
: null} : null}
<<<<<<< dd3f3ec4d00066633b136925111bae7193b3c6a8
<div className="card__title-primary"> <div className="card__title-primary">
<div className="meta"><a href={'?show=' + this.props.uri}>{lbryUri}</a></div> <div className="meta"><a href={'?show=' + this.props.uri}>{lbryUri}</a></div>
<h3> <h3>
@ -159,9 +160,25 @@ export let FileTileStream = React.createClass({
{isConfirmed {isConfirmed
? metadata.description ? metadata.description
: <span className="empty">This file is pending confirmation.</span>} : <span className="empty">This file is pending confirmation.</span>}
=======
<div className="meta"><a href={'?show=' + this.props.uri}>{'lbry://' + this.props.uri}</a></div>
<h3 className="file-tile__title">
<a href={'?show=' + this.props.uri}>
<TruncatedText lines={1}>
{title}
>>>>>>> more
</TruncatedText> </TruncatedText>
</p> </a>
</div> </h3>
<ChannelIndicator uri={this.props.uri} claimInfo={this.props.claimInfo} />
<FileActions uri={this.props.uri} outpoint={this.props.outpoint} metadata={metadata} contentType={this._contentType} />
<p className="file-tile__description">
<TruncatedText lines={3}>
{isConfirmed
? metadata.description
: <span className="empty">This file is pending confirmation.</span>}
</TruncatedText>
</p>
</div> </div>
</div> </div>
{this.state.showNsfwHelp {this.state.showNsfwHelp
@ -180,9 +197,12 @@ export let FileTileStream = React.createClass({
export let FileCardStream = React.createClass({ export let FileCardStream = React.createClass({
_fileInfoSubscribeId: null, _fileInfoSubscribeId: null,
_isMounted: null, _isMounted: null,
_metadata: null,
propTypes: { propTypes: {
metadata: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.object]), uri: React.PropTypes.string,
claimInfo: React.PropTypes.object,
outpoint: React.PropTypes.string, outpoint: React.PropTypes.string,
hideOnRemove: React.PropTypes.bool, hideOnRemove: React.PropTypes.bool,
hidePrice: React.PropTypes.bool, hidePrice: React.PropTypes.bool,
@ -207,6 +227,11 @@ export let FileCardStream = React.createClass({
this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate); this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.outpoint, this.onFileInfoUpdate);
} }
}, },
componentWillMount: function() {
const {value: {stream: {metadata, source: {contentType}}}} = this.props.claimInfo;
this._metadata = metadata;
this._contentType = contentType;
},
componentWillUnmount: function() { componentWillUnmount: function() {
if (this._fileInfoSubscribeId) { if (this._fileInfoSubscribeId) {
lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId); lbry.fileInfoUnsubscribe(this.props.outpoint, this._fileInfoSubscribeId);
@ -220,7 +245,7 @@ export let FileCardStream = React.createClass({
} }
}, },
handleMouseOver: function() { handleMouseOver: function() {
if (this.props.obscureNsfw && this.props.metadata && this.props.metadata.nsfw) { if (this.props.obscureNsfw && this.props.metadata && this._metadata.nsfw) {
this.setState({ this.setState({
showNsfwHelp: true, showNsfwHelp: true,
}); });
@ -238,11 +263,16 @@ export let FileCardStream = React.createClass({
return null; return null;
} }
<<<<<<< dd3f3ec4d00066633b136925111bae7193b3c6a8
const lbryUri = uri.normalizeLbryUri(this.props.uri); const lbryUri = uri.normalizeLbryUri(this.props.uri);
const metadata = this.props.metadata; const metadata = this.props.metadata;
=======
const metadata = this._metadata;
>>>>>>> more
const isConfirmed = typeof metadata == 'object'; const isConfirmed = typeof metadata == 'object';
const title = isConfirmed ? metadata.title : lbryUri; const title = isConfirmed ? metadata.title : lbryUri;
const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw; const obscureNsfw = this.props.obscureNsfw && isConfirmed && metadata.nsfw;
console.log(this.props);
return ( return (
<section className={ 'card card--small ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}> <section className={ 'card card--small ' + (obscureNsfw ? 'card--obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
<div className="card__inner"> <div className="card__inner">
@ -254,10 +284,15 @@ export let FileCardStream = React.createClass({
</TruncatedText> </TruncatedText>
</a> </a>
</h4> </h4>
<<<<<<< dd3f3ec4d00066633b136925111bae7193b3c6a8
<div className="card__subtitle"><a href={'?show=' + lbryUri}>{lbryUri}</a></div></div> <div className="card__subtitle"><a href={'?show=' + lbryUri}>{lbryUri}</a></div></div>
<ChannelIndicator uri={lbryUri} metadata={metadata} contentType={this.props.contentType} <ChannelIndicator uri={lbryUri} metadata={metadata} contentType={this.props.contentType}
hasSignature={this.props.hasSignature} signatureIsValid={this.props.signatureIsValid} /> hasSignature={this.props.hasSignature} signatureIsValid={this.props.signatureIsValid} />
=======
<ChannelIndicator uri={this.props.uri} claimInfo={this.props.claimInfo} />
</div>
>>>>>>> more
<div className="card__media"> <div className="card__media">
<a href={'?show=' + this.props.uri}><Thumbnail src={metadata.thumbnail} alt={'Photo for ' + (title || this.props.uri)} /></a> <a href={'?show=' + this.props.uri}><Thumbnail src={metadata.thumbnail} alt={'Photo for ' + (title || this.props.uri)} /></a>
</div> </div>
@ -325,7 +360,11 @@ export let FileTile = React.createClass({
const {txid, nout, has_signature, signature_is_valid, const {txid, nout, has_signature, signature_is_valid,
value: {stream: {metadata, source: {contentType}}}} = this.state.claimInfo; value: {stream: {metadata, source: {contentType}}}} = this.state.claimInfo;
return <FileTileStream outpoint={txid + ':' + nout} metadata={metadata} contentType={contentType} return
hasSignature={has_signature} signatureIsValid={signature_is_valid} {... this.props} />; return this.props.displayStyle == 'card' ?
<FileCardStream outpoint={txid + ':' + nout} metadata={metadata} contentType={contentType}
hasSignature={has_signature} signatureIsValid={signature_is_valid} {... this.props}/> :
<FileTileStream outpoint={txid + ':' + nout} metadata={metadata} contentType={contentType}
hasSignature={has_signature} signatureIsValid={signature_is_valid} {... this.props} />;
} }
}); });

View file

@ -51,7 +51,7 @@ export let FormField = React.createClass({
if (this.props.type == 'checkbox') { if (this.props.type == 'checkbox') {
return this.refs.field.checked; return this.refs.field.checked;
} else if (this.props.type == 'file') { } else if (this.props.type == 'file') {
return this.refs.field.files[0].path; return this.refs.field.files.length && this.refs.field.files[0].path;
} else { } else {
return this.refs.field.value; return this.refs.field.value;
} }
@ -121,6 +121,9 @@ export let FormRow = React.createClass({
getValue: function() { getValue: function() {
return this.refs.field.getValue(); return this.refs.field.getValue();
}, },
getSelectedElement: function() {
return this.refs.field.getSelectedElement();
},
render: function() { render: function() {
const fieldProps = Object.assign({}, this.props), const fieldProps = Object.assign({}, this.props),
elementId = formFieldId(), elementId = formFieldId(),

View file

@ -62,7 +62,6 @@ lbryio.call = function(resource, action, params={}, method='get') {
})); }));
} }
} else { } else {
console.info(`${resource}.${action} response data:`, response);
resolve(response.data); resolve(response.data);
} }
}); });
@ -75,11 +74,9 @@ lbryio.call = function(resource, action, params={}, method='get') {
const fullParams = {app_id: lbryio._accessToken, ...params}; const fullParams = {app_id: lbryio._accessToken, ...params};
if (method == 'get') { if (method == 'get') {
console.info('GET ', CONNECTION_STRING + resource + '/' + action, ' | params:', fullParams);
xhr.open('get', CONNECTION_STRING + resource + '/' + action + '?' + querystring.stringify(fullParams), true); xhr.open('get', CONNECTION_STRING + resource + '/' + action + '?' + querystring.stringify(fullParams), true);
xhr.send(); xhr.send();
} else if (method == 'post') { } else if (method == 'post') {
console.info('POST ', CONNECTION_STRING + resource + '/' + action, '| params: ', fullParams);
xhr.open('post', CONNECTION_STRING + resource + '/' + action, true); xhr.open('post', CONNECTION_STRING + resource + '/' + action, true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(querystring.stringify(fullParams)); xhr.send(querystring.stringify(fullParams));

View file

@ -6,7 +6,7 @@ import {Link} from '../component/link.js';
import Modal from '../component/modal.js'; import Modal from '../component/modal.js';
var PublishPage = React.createClass({ var PublishPage = React.createClass({
_requiredFields: ['name', 'bid', 'meta_title', 'meta_author', 'meta_license', 'meta_description'], _requiredFields: ['name', 'bid', 'meta_title'],
_updateChannelList: function(channel) { _updateChannelList: function(channel) {
// Calls API to update displayed list of channels. If a channel name is provided, will select // Calls API to update displayed list of channels. If a channel name is provided, will select
@ -85,7 +85,9 @@ var PublishPage = React.createClass({
publishArgs.file_path = this.refs.file.getValue(); publishArgs.file_path = this.refs.file.getValue();
} }
console.log(publishArgs);
lbry.publish(publishArgs, (message) => { lbry.publish(publishArgs, (message) => {
console.log(message);
this.handlePublishStarted(); this.handlePublishStarted();
}, null, (error) => { }, null, (error) => {
this.handlePublishError(error); this.handlePublishError(error);
@ -112,6 +114,7 @@ var PublishPage = React.createClass({
rawName: '', rawName: '',
name: '', name: '',
bid: '', bid: '',
hasFile: false,
feeAmount: '', feeAmount: '',
feeCurrency: 'USD', feeCurrency: 'USD',
channel: 'anonymous', channel: 'anonymous',
@ -237,7 +240,7 @@ var PublishPage = React.createClass({
isFee: feeEnabled isFee: feeEnabled
}); });
}, },
handeLicenseChange: function(event) { handleLicenseChange: function(event) {
var licenseType = event.target.options[event.target.selectedIndex].getAttribute('data-license-type'); var licenseType = event.target.options[event.target.selectedIndex].getAttribute('data-license-type');
var newState = { var newState = {
copyrightChosen: licenseType == 'copyright', copyrightChosen: licenseType == 'copyright',
@ -245,8 +248,7 @@ var PublishPage = React.createClass({
}; };
if (licenseType == 'copyright') { if (licenseType == 'copyright') {
var author = this.refs.meta_author.getValue(); newState.copyrightNotice = 'All rights reserved.'
newState.copyrightNotice = 'Copyright ' + (new Date().getFullYear()) + (author ? ' ' + author : '');
} }
this.setState(newState); this.setState(newState);
@ -277,7 +279,7 @@ var PublishPage = React.createClass({
const newChannelName = (event.target.value.startsWith('@') ? event.target.value : '@' + event.target.value); const newChannelName = (event.target.value.startsWith('@') ? event.target.value : '@' + event.target.value);
if (newChannelName.length > 1 && !lbry.nameIsValid(newChannelName.substr(1), false)) { if (newChannelName.length > 1 && !lbry.nameIsValid(newChannelName.substr(1), false)) {
this.refs.newChannelName.showAdvice('LBRY channel names must contain only letters, numbers and dashes.'); this.refs.newChannelName.showError('LBRY channel names must contain only letters, numbers and dashes.');
return; return;
} }
@ -292,7 +294,7 @@ var PublishPage = React.createClass({
}, },
handleCreateChannelClick: function (event) { handleCreateChannelClick: function (event) {
if (this.state.newChannelName.length < 5) { if (this.state.newChannelName.length < 5) {
this.refs.newChannelName.showAdvice('LBRY channel names must be at least 4 characters in length.'); this.refs.newChannelName.showError('LBRY channel names must be at least 4 characters in length.');
return; return;
} }
@ -311,7 +313,7 @@ var PublishPage = React.createClass({
}, 5000); }, 5000);
}, (error) => { }, (error) => {
// TODO: better error handling // TODO: better error handling
this.refs.newChannelName.showAdvice('Unable to create channel due to an internal error.'); this.refs.newChannelName.showError('Unable to create channel due to an internal error.');
this.setState({ this.setState({
creatingChannel: false, creatingChannel: false,
}); });
@ -334,7 +336,27 @@ var PublishPage = React.createClass({
}, },
componentDidUpdate: function() { componentDidUpdate: function() {
}, },
// Also getting a type warning here too onFileChange: function() {
if (this.refs.file.getValue()) {
this.setState({ hasFile: true })
} else {
this.setState({ hasFile: false })
}
},
getNameBidHelpText: function() {
if (!this.state.name) {
return "Select a URL for this publish.";
} else if (!this.state.nameResolved) {
return "This URL is unused.";
} else if (this.state.myClaimExists) {
return "You have already used this URL. Publishing to it again will update your previous publish."
} else if (this.state.topClaimValue) {
return <span>A deposit of at least <strong>{this.state.topClaimValue}</strong> {this.state.topClaimValue == 1 ? 'credit' : 'credits'}
is required to win <strong>{this.state.name}</strong>. However, you can still get a perminent URL for any amount.</span>
} else {
return '';
}
},
render: function() { render: function() {
if (this.state.channels === null) { if (this.state.channels === null) {
return null; return null;
@ -345,153 +367,136 @@ var PublishPage = React.createClass({
<form onSubmit={this.handleSubmit}> <form onSubmit={this.handleSubmit}>
<section className="card"> <section className="card">
<div className="card__title-primary"> <div className="card__title-primary">
<h4>LBRY Name</h4> <h4>Content</h4>
<div className="card__subtitle">
What are you publishing?
</div>
</div> </div>
<div className="card__content"> <div className="card__content">
<FormRow label="lbry://" type="text" ref="name" placeholder="lbry://myname" value={this.state.rawName} onChange={this.handleNameChange} <FormRow label="lbry://" type="text" ref="name" placeholder="lbry://myname" value={this.state.rawName} onChange={this.handleNameChange}
helper={(<div>What LBRY name would you like to claim for this file? <Link label="Read more" href="https://lbry.io/faq/naming" />.</div>)} /> helper={(<div>What LBRY name would you like to claim for this file? <Link label="Read more" href="https://lbry.io/faq/naming" />.</div>)} />
{ <FormRow name="file" label="File" ref="file" type="file" onChange={this.onFileChange}
(!this.state.name helper={this.state.myClaimExists ? "If you don't choose a file, the file from your existing claim will be used." : null}/>
? null </div>
: (!this.state.nameResolved { !this.state.hasFile ? '' :
? <em> The name <strong>{this.state.name}</strong> is available.</em> <div className="card__content">
: (this.state.myClaimExists <FormRow label="Title" type="text" ref="meta_title" name="title" placeholder="Me Not Being A Loser" />
? <em> You already have a claim on the name <strong>{this.state.name}</strong>. You can use this page to update your claim.</em> <FormRow type="text" label="Thumbnail URL" ref="meta_thumbnail" name="thumbnail" placeholder="http://mycompany.com/images/ep_1.jpg" />
: <em> The name <strong>{this.state.name}</strong> is currently claimed for <strong>{this.state.topClaimValue}</strong> {this.state.topClaimValue == 1 ? 'credit' : 'credits'}.</em>))) <FormRow label="Description" type="textarea" ref="meta_description" name="description" placeholder="Description of your content" />
} <FormRow label="Language" type="select" defaultValue="en" ref="meta_language" name="language">
<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>
<FormRow type="select" label="Maturity" defaultValue="en" ref="meta_nsfw" name="nsfw">
<option value=""></option>
<option value="0">All Ages</option>
<option value="1">Adults Only</option>
</FormRow>
</div> }
</section>
<section className="card">
<div className="card__title-primary">
<h4>Access</h4>
<div className="card__subtitle">
How much does this content cost ?
</div>
</div>
<div className="card__content">
<div className="form-row__label-row">
<label className="form-row__label">Price</label>
</div>
<FormRow label="Free" type="radio" name="isFree" value="1" onChange={ () => { this.handleFeePrefChange(false) } } checked={!this.state.isFee} />
<FormField type="radio" name="isFree" label={!this.state.isFee ? 'Choose price...' : 'Price ' }
onChange={ () => { this.handleFeePrefChange(true) } } checked={this.state.isFee} />
<span className={!this.state.isFee ? 'hidden' : ''}>
<FormField type="number" step="0.01" placeholder="1.00" onChange={this.handleFeeAmountChange} /> <FormField type="select" onChange={this.handleFeeCurrencyChange}>
<option value="USD">US Dollars</option>
<option value="LBC">LBRY credits</option>
</FormField>
</span>
{ this.state.isFee ?
<div className="help">
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" ref="meta_license" name="license" onChange={this.handleLicenseChange}>
<option data-url="https://creativecommons.org/licenses/by/4.0/legalcode">Creative Commons Attribution 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-sa/4.0/legalcode">Creative Commons Attribution-ShareAlike 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nd/4.0/legalcode">Creative Commons Attribution-NoDerivatives 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc/4.0/legalcode">Creative Commons Attribution-NonCommercial 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International</option>
<option>Public Domain</option>
<option data-license-type="copyright" {... this.state.copyrightChosen ? {value: this.state.copyrightNotice} : {}}>Copyrighted...</option>
<option data-license-type="other" {... this.state.otherLicenseChosen ? {value: this.state.otherLicenseDescription} : {}}>Other...</option>
</FormRow>
<FormField type="hidden" ref="meta_license_url" name="license_url" value={this.getLicenseUrl()} />
{this.state.copyrightChosen
? <FormRow label="Copyright notice" type="text" name="copyright-notice"
value={this.state.copyrightNotice} onChange={this.handleCopyrightNoticeChange} />
: null}
{this.state.otherLicenseChosen ?
<FormRow label="License description" type="text" name="other-license-description" onChange={this.handleOtherLicenseDescriptionChange} />
: null}
{this.state.otherLicenseChosen ?
<FormRow label="License URL" type="text" name="other-license-url" onChange={this.handleOtherLicenseUrlChange} />
: null}
</div> </div>
</section> </section>
<section className="card"> <section className="card">
<h4>Channel</h4> <div className="card__title-primary">
<div className="form-row"> <h4>Identity</h4>
<FormField type="select" onChange={this.handleChannelChange} value={this.state.channel}> <div className="card__subtitle">
Who created this content?
</div>
</div>
<div className="card__content">
<FormRow type="select" tabIndex="1" onChange={this.handleChannelChange} value={this.state.channel}>
<option key="anonymous" value="anonymous">Anonymous</option> <option key="anonymous" value="anonymous">Anonymous</option>
{this.state.channels.map(({name}) => <option key={name} value={name}>{name}</option>)} {this.state.channels.map(({name}) => <option key={name} value={name}>{name}</option>)}
<option key="new" value="new">New channel...</option> <option key="new" value="new">New identity...</option>
</FormField> </FormRow>
{this.state.channel == 'new'
? <section>
<label>Name <FormField type="text" onChange={this.handleNewChannelNameChange} ref={newChannelName => { this.refs.newChannelName = newChannelName }}
value={this.state.newChannelName} /></label>
<label>Bid amount <FormField type="text-number" onChange={this.handleNewChannelBidChange} value={this.state.newChannelBid} /> LBC</label>
<Link button="primary" label={!this.state.creatingChannel ? 'Create channel' : 'Creating channel...'} onClick={this.handleCreateChannelClick} disabled={this.state.creatingChannel} />
</section>
: null}
<div className="help">What channel would you like to publish this file under?</div>
</div> </div>
{this.state.channel == 'new' ?
<div className="card__content">
<FormRow label="Name" type="text" onChange={this.handleNewChannelNameChange} ref={newChannelName => { this.refs.newChannelName = newChannelName }}
value={this.state.newChannelName} />
<FormRow label="Deposit" step="0.01" defaultValue="0.01" type="number" onChange={this.handleNewChannelBidChange} value={this.state.newChannelBid} />
<div className="form-row-submit">
<Link button="primary" label={!this.state.creatingChannel ? 'Creating identity' : 'Creating identity...'} onClick={this.handleCreateChannelClick} disabled={this.state.creatingChannel} />
</div>
</div>
: null}
</section> </section>
<section className="card"> <section className="card">
<div className="card__title-primary"><h4>Choose File</h4></div> <div className="card__title-primary">
<h4>Address</h4>
<div className="card__subtitle">Where should this content permanently reside?</div>
</div>
<div className="card__content"> <div className="card__content">
<FormField name="file" ref="file" type="file" /> <FormRow label="lbry://" type="text" ref="name" placeholder="lbry://myname" value={this.state.rawName} onChange={this.handleNameChange}
{ this.state.myClaimExists ? <div className="help">If you don't choose a file, the file from your existing claim will be used.</div> : null } helper={(<div>Select a URL for this publish. <Link label="Read more" href="https://lbry.io/faq/naming" />.</div>)} />
</div>
</section>
<section className="card">
<h4>Bid Amount</h4>
<div className="form-row">
Credits <FormField ref="bid" type="text-number" onChange={this.handleBidChange} value={this.state.bid} placeholder={this.state.nameResolved ? this.state.topClaimValue + 10 : 100} />
<div className="help">How much would you like to bid for this name?
{ !this.state.nameResolved ? <span> 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.</span>
: (this.state.topClaimIsMine ? <span> You currently control this name with a bid of <strong>{this.state.myClaimValue}</strong> {this.state.myClaimValue == 1 ? 'credit' : 'credits'}.</span>
: (this.state.myClaimExists ? <span> You have a non-winning bid on this name for <strong>{this.state.myClaimValue}</strong> {this.state.myClaimValue == 1 ? 'credit' : 'credits'}.
To control this name, you'll need to increase your bid to more than <strong>{this.state.topClaimValue}</strong> {this.state.topClaimValue == 1 ? 'credit' : 'credits'}.</span>
: <span> You must bid over <strong>{this.state.topClaimValue}</strong> {this.state.topClaimValue == 1 ? 'credit' : 'credits'} to claim this name.</span>)) }
</div>
</div>
</section>
<section className="card">
<h4>Fee</h4>
<div className="form-row">
<label>
<FormField type="radio" onChange={ () => { this.handleFeePrefChange(false) } } checked={!this.state.isFee} /> No fee
</label>
<label>
<FormField type="radio" onChange={ () => { this.handleFeePrefChange(true) } } checked={this.state.isFee} /> { !this.state.isFee ? 'Choose fee...' : 'Fee ' }
<span className={!this.state.isFee ? 'hidden' : ''}>
<FormField type="text-number" onChange={this.handleFeeAmountChange} /> <FormField type="select" onChange={this.handleFeeCurrencyChange}>
<option value="USD">US Dollars</option>
<option value="LBC">LBRY credits</option>
</FormField>
</span>
</label>
<div className="help">
<p>How much would you like to charge for this file?</p>
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>
</div>
</section>
<section className="card">
<h4>Your Content</h4>
<div className="form-row">
<label htmlFor="title">Title</label><FormField type="text" ref="meta_title" name="title" placeholder="My Show, Episode 1" />
</div>
<div className="form-row">
<label htmlFor="author">Author</label><FormField type="text" ref="meta_author" name="author" placeholder="My Company, Inc." />
</div>
<div className="form-row">
<label htmlFor="license">License</label><FormField type="select" ref="meta_license" name="license" onChange={this.handeLicenseChange}>
<option data-url="https://creativecommons.org/licenses/by/4.0/legalcode">Creative Commons Attribution 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-sa/4.0/legalcode">Creative Commons Attribution-ShareAlike 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nd/4.0/legalcode">Creative Commons Attribution-NoDerivatives 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc/4.0/legalcode">Creative Commons Attribution-NonCommercial 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International</option>
<option data-url="https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode">Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International</option>
<option>Public Domain</option>
<option data-license-type="copyright" {... this.state.copyrightChosen ? {value: this.state.copyrightNotice} : {}}>Copyrighted...</option>
<option data-license-type="other" {... this.state.otherLicenseChosen ? {value: this.state.otherLicenseDescription} : {}}>Other...</option>
</FormField>
<FormField type="hidden" ref="meta_license_url" name="license_url" value={this.getLicenseUrl()} />
</div>
{this.state.copyrightChosen
? <div className="form-row">
<label htmlFor="copyright-notice" value={this.state.copyrightNotice}>Copyright notice</label><FormField type="text" name="copyright-notice" value={this.state.copyrightNotice} onChange={this.handleCopyrightNoticeChange} />
</div>
: null}
{this.state.otherLicenseChosen
? <div className="form-row">
<label htmlFor="other-license-description">License description</label><FormField type="text" name="other-license-description" onChange={this.handleOtherLicenseDescriptionChange} />
</div>
: null}
{this.state.otherLicenseChosen
? <div className="form-row">
<label htmlFor="other-license-url">License URL</label> <FormField type="text" name="other-license-url" onChange={this.handleOtherLicenseUrlChange} />
</div>
: null}
<div className="form-row">
<label htmlFor="language">Language</label> <FormField type="select" defaultValue="en" ref="meta_language" name="language">
<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>
</FormField>
</div>
<div className="form-row">
<label htmlFor="description">Description</label> <FormField type="textarea" ref="meta_description" name="description" placeholder="Description of your content" />
</div>
<div className="form-row">
<label><FormField type="checkbox" ref="meta_nsfw" name="nsfw" placeholder="Description of your content" /> Not Safe For Work</label>
</div>
</section>
<section className="card">
<h4>Additional Content Information (Optional)</h4>
<div className="form-row">
<label htmlFor="meta_thumbnail">Thumbnail URL</label> <FormField type="text" ref="meta_thumbnail" name="thumbnail" placeholder="http://mycompany.com/images/ep_1.jpg" />
</div> </div>
{ this.state.rawName ?
<div className="card__content">
<FormRow ref="bid"
type="number"
step="0.01"
label="Deposit"
defaultValue="0.01"
onChange={this.handleBidChange}
value={this.state.bid}
placeholder={this.state.nameResolved ? this.state.topClaimValue + 10 : 100}
helper={this.getNameBidHelpText()} />
</div> : '' }
</section> </section>
<div className="card-series-submit"> <div className="card-series-submit">

View file

@ -95,12 +95,12 @@ var SettingsPage = React.createClass({
</div> </div>
<div className="card__content"> <div className="card__content">
<h4>Max Upload</h4> <h4>Max Upload</h4>
<FormField type="radio" <FormRow type="radio"
name="max_upload_pref" name="max_upload_pref"
onChange={this.onMaxUploadPrefChange.bind(this, false)} onChange={this.onMaxUploadPrefChange.bind(this, false)}
defaultChecked={!this.state.isMaxUpload} defaultChecked={!this.state.isMaxUpload}
label="Unlimited" /> label="Unlimited" />
<FormField type="radio" <FormRow type="radio"
name="max_upload_pref" name="max_upload_pref"
onChange={this.onMaxUploadPrefChange.bind(this, true)} onChange={this.onMaxUploadPrefChange.bind(this, true)}
defaultChecked={this.state.isMaxUpload} defaultChecked={this.state.isMaxUpload}
@ -116,20 +116,23 @@ var SettingsPage = React.createClass({
</div> </div>
<div className="card__content"> <div className="card__content">
<h4>Max Download</h4> <h4>Max Download</h4>
<label style={settingsRadioOptionStyles}> <FormField label="Unlimited"
<input type="radio" name="max_download_pref" onChange={this.onMaxDownloadPrefChange.bind(this, false)} defaultChecked={!this.state.isMaxDownload}/> Unlimited type="radio"
</label> name="max_download_pref"
onChange={this.onMaxDownloadPrefChange.bind(this, false)}
defaultChecked={!this.state.isMaxDownload} />
{ /*
<label style={settingsRadioOptionStyles}> <label style={settingsRadioOptionStyles}>
<input type="radio" name="max_download_pref" onChange={this.onMaxDownloadPrefChange.bind(this, true)} defaultChecked={this.state.isMaxDownload}/> { this.state.isMaxDownload ? 'Up to' : 'Choose limit...' } <input type="radio" name="max_download_pref" onChange={this.onMaxDownloadPrefChange.bind(this, true)} defaultChecked={this.state.isMaxDownload}/> { this.state.isMaxDownload ? 'Up to' : 'Choose limit...' }
<span className={ this.state.isMaxDownload ? '' : 'hidden'}> <input type="number" min="0" step=".5" defaultValue={this.state.daemonSettings.max_download} style={settingsNumberFieldStyles} onChange={this.onMaxDownloadFieldChange}/> MB/s</span> <span className={ this.state.isMaxDownload ? '' : 'hidden'}> <input type="number" min="0" step=".5" defaultValue={this.state.daemonSettings.max_download} style={settingsNumberFieldStyles} onChange={this.onMaxDownloadFieldChange}/> MB/s</span>
</label> </label> */ }
</div> </div>
</section> </section>
<section className="card"> <section className="card">
<div className="card__content"> <div className="card__content">
<h3>Content</h3> <h3>Content</h3>
</div> </div>
<div class="card__content"> <div className="card__content">
<FormRow type="checkbox" <FormRow type="checkbox"
onChange={this.onShowUnavailableChange} onChange={this.onShowUnavailableChange}
defaultChecked={this.state.showUnavailable} defaultChecked={this.state.showUnavailable}
@ -145,7 +148,7 @@ var SettingsPage = React.createClass({
<div className="card__content"> <div className="card__content">
<h3>Share Diagnostic Data</h3> <h3>Share Diagnostic Data</h3>
</div> </div>
<div class="card__content"> <div className="card__content">
<FormRow type="checkbox" <FormRow type="checkbox"
onChange={this.onShareDataChange} onChange={this.onShareDataChange}
defaultChecked={this.state.daemonSettings.share_debug_info} defaultChecked={this.state.daemonSettings.share_debug_info}

View file

@ -152,7 +152,7 @@ var SendToAddressSection = React.createClass({
<h3>Send Credits</h3> <h3>Send Credits</h3>
</div> </div>
<div className="card__content"> <div className="card__content">
<FormRow label="Amount" type="number" placeholder="1.23" size="10" onChange={this.setAmount} /> <FormRow label="Amount" step="0.01" type="number" placeholder="1.23" size="10" onChange={this.setAmount} />
</div> </div>
<div className="card__content"> <div className="card__content">
<FormRow label="Recipient Address" placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs" type="text" size="60" onChange={this.setAddress} /> <FormRow label="Recipient Address" placeholder="bbFxRyXXXXXXXXXXXZD8nE7XTLUxYnddTs" type="text" size="60" onChange={this.setAddress} />

View file

@ -95,8 +95,9 @@ $width-card-small: $spacing-vertical * 12;
} }
.card__subtitle { .card__subtitle {
color: $color-meta-light; color: $color-help;
font-size: 0.85em; font-size: 0.85em;
line-height: $font-line-height * 1 / 0.85;
} }
.card-series-submit .card-series-submit

View file

@ -1,21 +1,21 @@
@import "../global"; @import "../global";
$width-input-border: 2px;
.form-row-submit .form-row-submit
{ {
margin-top: $spacing-vertical; margin-top: $spacing-vertical;
} }
$height-input: $spacing-vertical * 1.5;
.form-row__label-row { .form-row__label-row {
margin-top: $spacing-vertical * 2/3; margin-top: $spacing-vertical * 2/3;
margin-bottom: $spacing-vertical * 1/3; margin-bottom: $spacing-vertical * 1/3;
line-height: 1; line-height: 1;
font-size: 0.9em;
} }
.form-row__label-row--prefix { .form-row__label-row--prefix {
float: left; float: left;
margin-right: 5px; margin-right: 5px;
line-height: $height-input;
} }
.form-field { .form-field {
@ -26,8 +26,19 @@ $height-input: $spacing-vertical * 1.5;
cursor: pointer; cursor: pointer;
} }
select {
transition: outline $transition-standard;
cursor: pointer;
box-sizing: border-box;
padding-left: 5px;
padding-right: 5px;
height: $spacing-vertical;
&:focus {
outline: $width-input-border solid $color-primary;
}
}
textarea, textarea,
select,
input[type="text"], input[type="text"],
input[type="password"], input[type="password"],
input[type="email"], input[type="email"],
@ -54,9 +65,10 @@ $height-input: $spacing-vertical * 1.5;
input[type="number"], input[type="number"],
input[type="search"], input[type="search"],
input[type="date"] { input[type="date"] {
border-bottom: 2px solid $color-form-border; border-bottom: $width-input-border solid $color-form-border;
line-height: $spacing-vertical - 4; line-height: 1px;
height: $height-input; padding-top: $spacing-vertical * 1/3;
padding-bottom: $spacing-vertical * 1/3;
&.form-field__input--error { &.form-field__input--error {
border-color: $color-error; border-color: $color-error;
} }
@ -73,7 +85,7 @@ $height-input: $spacing-vertical * 1.5;
} }
textarea { textarea {
border: 2px solid $color-form-border; border: $width-input-border solid $color-form-border;
} }
} }
@ -93,7 +105,12 @@ $height-input: $spacing-vertical * 1.5;
} }
.form-field__input-number { .form-field__input-number {
width: 100px; width: 70px;
text-align: right;
}
.form-field__input-textarea {
width: 330px;
} }
.form-field__error, .form-field__helper { .form-field__error, .form-field__helper {