mirror of
https://github.com/LBRYFoundation/lbry-desktop.git
synced 2025-08-27 07:23:31 +00:00
Merge branch 'es6-classes' into redux
This commit is contained in:
commit
d6680a7ae5
22 changed files with 726 additions and 563 deletions
|
@ -9,23 +9,28 @@ import {CreditAmount, Address} from "../component/common.js";
|
||||||
import {getLocal, getSession, setSession, setLocal} from '../utils.js';
|
import {getLocal, getSession, setSession, setLocal} from '../utils.js';
|
||||||
|
|
||||||
|
|
||||||
const SubmitEmailStage = React.createClass({
|
class SubmitEmailStage extends React.Component {
|
||||||
getInitialState: function() {
|
constructor(props) {
|
||||||
return {
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
rewardType: null,
|
rewardType: null,
|
||||||
email: '',
|
email: '',
|
||||||
submitting: false
|
submitting: false
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
handleEmailChanged: function(event) {
|
|
||||||
|
handleEmailChanged(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
email: event.target.value,
|
email: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
onEmailSaved: function(email) {
|
|
||||||
|
onEmailSaved(email) {
|
||||||
this.props.setStage("confirm", { email: email })
|
this.props.setStage("confirm", { email: email })
|
||||||
},
|
}
|
||||||
handleSubmit: function(event) {
|
|
||||||
|
handleSubmit(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -42,38 +47,43 @@ const SubmitEmailStage = React.createClass({
|
||||||
}
|
}
|
||||||
this.setState({ submitting: false });
|
this.setState({ submitting: false });
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={(event) => { this.handleSubmit(event) }}>
|
||||||
<FormRow ref={(ref) => { this._emailRow = ref }} type="text" label="Email" placeholder="scrwvwls@lbry.io"
|
<FormRow ref={(ref) => { this._emailRow = ref }} type="text" label="Email" placeholder="scrwvwls@lbry.io"
|
||||||
name="email" value={this.state.email}
|
name="email" value={this.state.email}
|
||||||
onChange={this.handleEmailChanged} />
|
onChange={(event) => { this.handleEmailChanged(event) }} />
|
||||||
<div className="form-row-submit">
|
<div className="form-row-submit">
|
||||||
<Link button="primary" label="Next" disabled={this.state.submitting} onClick={this.handleSubmit} />
|
<Link button="primary" label="Next" disabled={this.state.submitting} onClick={(event) => { this.handleSubmit(event) }} />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const ConfirmEmailStage = React.createClass({
|
class ConfirmEmailStage extends React.Component {
|
||||||
getInitialState: function() {
|
constructor(props) {
|
||||||
return {
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
rewardType: null,
|
rewardType: null,
|
||||||
code: '',
|
code: '',
|
||||||
submitting: false,
|
submitting: false,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
handleCodeChanged: function(event) {
|
|
||||||
|
handleCodeChanged(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
code: event.target.value,
|
code: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleSubmit: function(event) {
|
|
||||||
|
handleSubmit(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.setState({
|
this.setState({
|
||||||
submitting: true,
|
submitting: true,
|
||||||
|
@ -93,16 +103,17 @@ const ConfirmEmailStage = React.createClass({
|
||||||
onSubmitError(new Error("Your email is still not verified.")) //shouldn't happen?
|
onSubmitError(new Error("Your email is still not verified.")) //shouldn't happen?
|
||||||
}
|
}
|
||||||
}, onSubmitError);
|
}, onSubmitError);
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={(event) => { this.handleSubmit(event) }}>
|
||||||
<FormRow label="Verification Code" ref={(ref) => { this._codeRow = ref }} type="text"
|
<FormRow label="Verification Code" ref={(ref) => { this._codeRow = ref }} type="text"
|
||||||
name="code" placeholder="a94bXXXXXXXXXXXXXX" value={this.state.code} onChange={this.handleCodeChanged}
|
name="code" placeholder="a94bXXXXXXXXXXXXXX" value={this.state.code} onChange={(event) => { this.handleCodeChanged(event) }}
|
||||||
helper="A verification code is required to access this version."/>
|
helper="A verification code is required to access this version."/>
|
||||||
<div className="form-row-submit form-row-submit--with-footer">
|
<div className="form-row-submit form-row-submit--with-footer">
|
||||||
<Link button="primary" label="Verify" disabled={this.state.submitting} onClick={this.handleSubmit} />
|
<Link button="primary" label="Verify" disabled={this.state.submitting} onClick={(event) => { this.handleSubmit(event)}} />
|
||||||
</div>
|
</div>
|
||||||
<div className="form-field__helper">
|
<div className="form-field__helper">
|
||||||
No code? <Link onClick={() => { this.props.setStage("nocode")}} label="Click here" />.
|
No code? <Link onClick={() => { this.props.setStage("nocode")}} label="Click here" />.
|
||||||
|
@ -111,25 +122,26 @@ const ConfirmEmailStage = React.createClass({
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const WelcomeStage = React.createClass({
|
class WelcomeStage extends React.Component {
|
||||||
propTypes: {
|
constructor(props) {
|
||||||
endAuth: React.PropTypes.func,
|
super(props);
|
||||||
},
|
|
||||||
getInitialState: function() {
|
this.state = {
|
||||||
return {
|
|
||||||
hasReward: false,
|
hasReward: false,
|
||||||
rewardAmount: null,
|
rewardAmount: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
|
||||||
onRewardClaim: function(reward) {
|
onRewardClaim(reward) {
|
||||||
this.setState({
|
this.setState({
|
||||||
hasReward: true,
|
hasReward: true,
|
||||||
rewardAmount: reward.amount
|
rewardAmount: reward.amount
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
!this.state.hasReward ?
|
!this.state.hasReward ?
|
||||||
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY" {...this.props}>
|
<Modal type="custom" isOpen={true} contentLabel="Welcome to LBRY" {...this.props}>
|
||||||
|
@ -140,7 +152,7 @@ const WelcomeStage = React.createClass({
|
||||||
<p>Below, LBRY is controlled by users -- you -- via blockchain and decentralization.</p>
|
<p>Below, LBRY is controlled by users -- you -- via blockchain and decentralization.</p>
|
||||||
<p>Thank you for making content freedom possible! Here's a nickel, kid.</p>
|
<p>Thank you for making content freedom possible! Here's a nickel, kid.</p>
|
||||||
<div style={{textAlign: "center", marginBottom: "12px"}}>
|
<div style={{textAlign: "center", marginBottom: "12px"}}>
|
||||||
<RewardLink type="new_user" button="primary" onRewardClaim={this.onRewardClaim} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} />
|
<RewardLink type="new_user" button="primary" onRewardClaim={(event) => { this.onRewardClaim(event) }} onRewardFailure={() => this.props.setStage(null)} onConfirmed={() => { this.props.setStage(null) }} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</Modal> :
|
</Modal> :
|
||||||
|
@ -156,11 +168,13 @@ const WelcomeStage = React.createClass({
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
WelcomeStage.propTypes = {
|
||||||
|
endAuth: React.PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
class ErrorStage extends React.Component {
|
||||||
const ErrorStage = React.createClass({
|
render() {
|
||||||
render: function() {
|
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<p>An error was encountered that we cannot continue from.</p>
|
<p>An error was encountered that we cannot continue from.</p>
|
||||||
|
@ -170,29 +184,32 @@ const ErrorStage = React.createClass({
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
const PendingStage = React.createClass({
|
class PendingStage extends React.Component {
|
||||||
render: function() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<p>Preparing for first access <span className="busy-indicator"></span></p>
|
<p>Preparing for first access <span className="busy-indicator"></span></p>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
const CodeRequiredStage = React.createClass({
|
class CodeRequiredStage extends React.Component {
|
||||||
_balanceSubscribeId: null,
|
constructor(props) {
|
||||||
getInitialState: function() {
|
super(props);
|
||||||
return {
|
|
||||||
|
this._balanceSubscribeId = nullp
|
||||||
|
|
||||||
|
this.state = {
|
||||||
balance: 0,
|
balance: 0,
|
||||||
address: getLocal('wallet_address')
|
address: getLocal('wallet_address')
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
componentWillMount: function() {
|
componentWillMount() {
|
||||||
this._balanceSubscribeId = lbry.balanceSubscribe((balance) => {
|
this._balanceSubscribeId = lbry.balanceSubscribe((balance) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
balance: balance
|
balance: balance
|
||||||
|
@ -205,13 +222,15 @@ const CodeRequiredStage = React.createClass({
|
||||||
this.setState({ address: address });
|
this.setState({ address: address });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
componentWillUnmount: function() {
|
|
||||||
|
componentWillUnmount() {
|
||||||
if (this._balanceSubscribeId) {
|
if (this._balanceSubscribeId) {
|
||||||
lbry.balanceUnsubscribe(this._balanceSubscribeId)
|
lbry.balanceUnsubscribe(this._balanceSubscribeId)
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
const disabled = this.state.balance < 1;
|
const disabled = this.state.balance < 1;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -234,31 +253,36 @@ const CodeRequiredStage = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
export const AuthOverlay = React.createClass({
|
export class AuthOverlay extends React.Component {
|
||||||
_stages: {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._stages = {
|
||||||
pending: PendingStage,
|
pending: PendingStage,
|
||||||
error: ErrorStage,
|
error: ErrorStage,
|
||||||
nocode: CodeRequiredStage,
|
nocode: CodeRequiredStage,
|
||||||
email: SubmitEmailStage,
|
email: SubmitEmailStage,
|
||||||
confirm: ConfirmEmailStage,
|
confirm: ConfirmEmailStage,
|
||||||
welcome: WelcomeStage
|
welcome: WelcomeStage
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
this.state = {
|
||||||
stage: "pending",
|
stage: "pending",
|
||||||
stageProps: {}
|
stageProps: {}
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
setStage: function(stage, stageProps = {}) {
|
|
||||||
|
setStage(stage, stageProps = {}) {
|
||||||
this.setState({
|
this.setState({
|
||||||
stage: stage,
|
stage: stage,
|
||||||
stageProps: stageProps
|
stageProps: stageProps
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
componentWillMount: function() {
|
|
||||||
|
componentWillMount() {
|
||||||
lbryio.authenticate().then((user) => {
|
lbryio.authenticate().then((user) => {
|
||||||
if (!user.HasVerifiedEmail) {
|
if (!user.HasVerifiedEmail) {
|
||||||
if (getLocal('auth_bypassed')) {
|
if (getLocal('auth_bypassed')) {
|
||||||
|
@ -284,8 +308,9 @@ export const AuthOverlay = React.createClass({
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
if (!this.state.stage) {
|
if (!this.state.stage) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -294,9 +319,9 @@ export const AuthOverlay = React.createClass({
|
||||||
this.state.stage != "welcome" ?
|
this.state.stage != "welcome" ?
|
||||||
<ModalPage className="modal-page--full" isOpen={true} contentLabel="Authentication" {...this.props}>
|
<ModalPage className="modal-page--full" isOpen={true} contentLabel="Authentication" {...this.props}>
|
||||||
<h1>LBRY Early Access</h1>
|
<h1>LBRY Early Access</h1>
|
||||||
<StageContent {...this.state.stageProps} setStage={this.setStage} />
|
<StageContent {...this.state.stageProps} setStage={(stage, stageProps) => { this.setStage(stage, stageProps) }} />
|
||||||
</ModalPage> :
|
</ModalPage> :
|
||||||
<StageContent setStage={this.setStage} {...this.state.stageProps} />
|
<StageContent setStage={(stage, stageProps) => { this.setStage(stage, stageProps) }} {...this.state.stageProps} />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
|
@ -2,65 +2,69 @@ import React from 'react';
|
||||||
import lbry from '../lbry.js';
|
import lbry from '../lbry.js';
|
||||||
|
|
||||||
//component/icon.js
|
//component/icon.js
|
||||||
export let Icon = React.createClass({
|
export class Icon extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
icon: React.PropTypes.string.isRequired,
|
icon: React.PropTypes.string.isRequired,
|
||||||
className: React.PropTypes.string,
|
className: React.PropTypes.string,
|
||||||
fixed: React.PropTypes.bool,
|
fixed: React.PropTypes.bool,
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
static defaultProps = {
|
||||||
|
lines: null
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
const {fixed, className, ...other} = this.props;
|
const {fixed, className, ...other} = this.props;
|
||||||
const spanClassName = ('icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') +
|
const spanClassName = ('icon ' + ('fixed' in this.props ? 'icon-fixed-width ' : '') +
|
||||||
this.props.icon + ' ' + (this.props.className || ''));
|
this.props.icon + ' ' + (this.props.className || ''));
|
||||||
return <span className={spanClassName} {... other}></span>
|
return <span className={spanClassName} {... other}></span>
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export let TruncatedText = React.createClass({
|
export class TruncatedText extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
lines: React.PropTypes.number
|
lines: React.PropTypes.number,
|
||||||
},
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
lines: null,
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
render: function() {
|
render() {
|
||||||
return <span className="truncated-text" style={{ WebkitLineClamp: this.props.lines }}>{this.props.children}</span>;
|
return <span className="truncated-text" style={{ WebkitLineClamp: this.props.lines }}>{this.props.children}</span>;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export let BusyMessage = React.createClass({
|
export class BusyMessage extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
message: React.PropTypes.string
|
message: React.PropTypes.string,
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return <span>{this.props.message} <span className="busy-indicator"></span></span>
|
return <span>{this.props.message} <span className="busy-indicator"></span></span>
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export let CurrencySymbol = React.createClass({
|
export class CurrencySymbol extends React.Component {
|
||||||
render: function() { return <span>LBC</span>; }
|
render() {
|
||||||
});
|
return <span>LBC</span>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export let CreditAmount = React.createClass({
|
export class CreditAmount extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
amount: React.PropTypes.number.isRequired,
|
amount: React.PropTypes.number.isRequired,
|
||||||
precision: React.PropTypes.number,
|
precision: React.PropTypes.number,
|
||||||
isEstimate: React.PropTypes.bool,
|
isEstimate: React.PropTypes.bool,
|
||||||
label: React.PropTypes.bool,
|
label: React.PropTypes.bool,
|
||||||
showFree: React.PropTypes.bool,
|
showFree: React.PropTypes.bool,
|
||||||
look: React.PropTypes.oneOf(['indicator', 'plain']),
|
look: React.PropTypes.oneOf(['indicator', 'plain']),
|
||||||
},
|
}
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
static defaultProps = {
|
||||||
precision: 1,
|
precision: 1,
|
||||||
label: true,
|
label: true,
|
||||||
showFree: false,
|
showFree: false,
|
||||||
look: 'indicator',
|
look: 'indicator',
|
||||||
}
|
}
|
||||||
},
|
|
||||||
render: function() {
|
render() {
|
||||||
const formattedAmount = lbry.formatCredits(this.props.amount, this.props.precision);
|
const formattedAmount = lbry.formatCredits(this.props.amount, this.props.precision);
|
||||||
let amountText;
|
let amountText;
|
||||||
if (this.props.showFree && parseFloat(formattedAmount) == 0) {
|
if (this.props.showFree && parseFloat(formattedAmount) == 0) {
|
||||||
|
@ -80,45 +84,56 @@ export let CreditAmount = React.createClass({
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
var addressStyle = {
|
let addressStyle = {
|
||||||
fontFamily: '"Consolas", "Lucida Console", "Adobe Source Code Pro", monospace',
|
fontFamily: '"Consolas", "Lucida Console", "Adobe Source Code Pro", monospace',
|
||||||
};
|
};
|
||||||
export let Address = React.createClass({
|
export class Address extends React.Component {
|
||||||
_inputElem: null,
|
static propTypes = {
|
||||||
propTypes: {
|
|
||||||
address: React.PropTypes.string,
|
address: React.PropTypes.string,
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._inputElem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<input className="input-copyable" type="text" ref={(input) => { this._inputElem = input; }}
|
<input className="input-copyable" type="text" ref={(input) => { this._inputElem = input; }}
|
||||||
onFocus={() => { this._inputElem.select(); }} style={addressStyle} readOnly="readonly" value={this.props.address}></input>
|
onFocus={() => { this._inputElem.select(); }} style={addressStyle} readOnly="readonly" value={this.props.address}></input>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export let Thumbnail = React.createClass({
|
export class Thumbnail extends React.Component {
|
||||||
_defaultImageUri: lbry.imagePath('default-thumb.svg'),
|
static propTypes = {
|
||||||
_maxLoadTime: 10000,
|
|
||||||
_isMounted: false,
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
src: React.PropTypes.string,
|
src: React.PropTypes.string,
|
||||||
},
|
}
|
||||||
handleError: function() {
|
|
||||||
|
handleError() {
|
||||||
if (this.state.imageUrl != this._defaultImageUri) {
|
if (this.state.imageUrl != this._defaultImageUri) {
|
||||||
this.setState({
|
this.setState({
|
||||||
imageUri: this._defaultImageUri,
|
imageUri: this._defaultImageUri,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._defaultImageUri = lbry.imagePath('default-thumb.svg')
|
||||||
|
this._maxLoadTime = 10000
|
||||||
|
this._isMounted = false
|
||||||
|
|
||||||
|
this.state = {
|
||||||
imageUri: this.props.src || this._defaultImageUri,
|
imageUri: this.props.src || this._defaultImageUri,
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
componentDidMount: function() {
|
|
||||||
|
componentDidMount() {
|
||||||
this._isMounted = true;
|
this._isMounted = true;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this._isMounted && !this.refs.img.complete) {
|
if (this._isMounted && !this.refs.img.complete) {
|
||||||
|
@ -127,14 +142,16 @@ export let Thumbnail = React.createClass({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, this._maxLoadTime);
|
}, this._maxLoadTime);
|
||||||
},
|
}
|
||||||
componentWillUnmount: function() {
|
|
||||||
|
componentWillUnmount() {
|
||||||
this._isMounted = false;
|
this._isMounted = false;
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
const className = this.props.className ? this.props.className : '',
|
const className = this.props.className ? this.props.className : '',
|
||||||
otherProps = Object.assign({}, this.props)
|
otherProps = Object.assign({}, this.props)
|
||||||
delete otherProps.className;
|
delete otherProps.className;
|
||||||
return <img ref="img" onError={this.handleError} {...otherProps} className={className} src={this.state.imageUri} />
|
return <img ref="img" onError={() => { this.handleError() }} {...otherProps} className={className} src={this.state.imageUri} />
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ class FileActions extends React.Component {
|
||||||
<DropDownMenuItem key={1} onClick={() => openModal('confirmRemove')} label="Remove..." />
|
<DropDownMenuItem key={1} onClick={() => openModal('confirmRemove')} label="Remove..." />
|
||||||
</DropDownMenu> : '' }
|
</DropDownMenu> : '' }
|
||||||
<Modal type="confirm" isOpen={modal == 'affirmPurchase'}
|
<Modal type="confirm" isOpen={modal == 'affirmPurchase'}
|
||||||
contentLabel="Confirm Purchase" onConfirmed={this.onAffirmPurchase.bind(this)} onAborted={closeModal}>
|
contentLabel="Confirm Purchase" onConfirmed={this.onAffirmPurchase.bind(this)} onAborted={this.closeModal.bind(this)}>
|
||||||
This will purchase <strong>{title}</strong> for <strong><FilePrice uri={uri} look="plain" /></strong> credits.
|
This will purchase <strong>{title}</strong> for <strong><FilePrice uri={uri} look="plain" /></strong> credits.
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal isOpen={modal == 'notEnoughCredits'} contentLabel="Not enough credits"
|
<Modal isOpen={modal == 'notEnoughCredits'} contentLabel="Not enough credits"
|
||||||
|
|
|
@ -10,33 +10,29 @@ function formFieldId() {
|
||||||
return "form-field-" + (++formFieldCounter);
|
return "form-field-" + (++formFieldCounter);
|
||||||
}
|
}
|
||||||
|
|
||||||
export let FormField = React.createClass({
|
export class FormField extends React.Component {
|
||||||
_fieldRequiredText: 'This field is required',
|
static propTypes = {
|
||||||
_type: null,
|
|
||||||
_element: null,
|
|
||||||
|
|
||||||
propTypes: {
|
|
||||||
type: React.PropTypes.string.isRequired,
|
type: React.PropTypes.string.isRequired,
|
||||||
prefix: React.PropTypes.string,
|
prefix: React.PropTypes.string,
|
||||||
postfix: React.PropTypes.string,
|
postfix: React.PropTypes.string,
|
||||||
hasError: React.PropTypes.bool
|
hasError: React.PropTypes.bool
|
||||||
},
|
|
||||||
handleFileChosen: function(path) {
|
|
||||||
this.refs.field.value = path;
|
|
||||||
if (this.props.onChange) { // Updating inputs programmatically doesn't generate an event, so we have to make our own
|
|
||||||
const event = new Event('change', {bubbles: true})
|
|
||||||
this.refs.field.dispatchEvent(event); // This alone won't generate a React event, but we use it to attach the field as a target
|
|
||||||
this.props.onChange(event);
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
getInitialState: function() {
|
constructor(props) {
|
||||||
return {
|
super(props);
|
||||||
|
|
||||||
|
this._fieldRequiredText = 'This field is required';
|
||||||
|
this._type = null;
|
||||||
|
this._element = null;
|
||||||
|
|
||||||
|
this.state = {
|
||||||
isError: null,
|
isError: null,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
|
||||||
componentWillMount: function() {
|
componentWillMount() {
|
||||||
if (['text', 'number', 'radio', 'checkbox'].includes(this.props.type)) {
|
if (['text', 'number', 'radio', 'checkbox', 'file'].includes(this.props.type)) {
|
||||||
this._element = 'input';
|
this._element = 'input';
|
||||||
this._type = this.props.type;
|
this._type = this.props.type;
|
||||||
} else if (this.props.type == 'text-number') {
|
} else if (this.props.type == 'text-number') {
|
||||||
|
@ -49,8 +45,9 @@ export let FormField = React.createClass({
|
||||||
// Non <input> field, e.g. <select>, <textarea>
|
// Non <input> field, e.g. <select>, <textarea>
|
||||||
this._element = this.props.type;
|
this._element = this.props.type;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
componentDidMount: function() {
|
|
||||||
|
componentDidMount() {
|
||||||
/**
|
/**
|
||||||
* We have to add the webkitdirectory attribute here because React doesn't allow it in JSX
|
* We have to add the webkitdirectory attribute here because React doesn't allow it in JSX
|
||||||
* https://github.com/facebook/react/issues/3468
|
* https://github.com/facebook/react/issues/3468
|
||||||
|
@ -58,27 +55,41 @@ export let FormField = React.createClass({
|
||||||
if (this.props.type == 'directory') {
|
if (this.props.type == 'directory') {
|
||||||
this.refs.field.webkitdirectory = true;
|
this.refs.field.webkitdirectory = true;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
showError: function(text) {
|
|
||||||
|
handleFileChosen(path) {
|
||||||
|
this.refs.field.value = path;
|
||||||
|
if (this.props.onChange) { // Updating inputs programmatically doesn't generate an event, so we have to make our own
|
||||||
|
const event = new Event('change', {bubbles: true})
|
||||||
|
this.refs.field.dispatchEvent(event); // This alone won't generate a React event, but we use it to attach the field as a target
|
||||||
|
this.props.onChange(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showError(text) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isError: true,
|
isError: true,
|
||||||
errorMessage: text,
|
errorMessage: text,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
focus: function() {
|
|
||||||
|
focus() {
|
||||||
this.refs.field.focus();
|
this.refs.field.focus();
|
||||||
},
|
}
|
||||||
getValue: function() {
|
|
||||||
|
getValue() {
|
||||||
if (this.props.type == 'checkbox') {
|
if (this.props.type == 'checkbox') {
|
||||||
return this.refs.field.checked;
|
return this.refs.field.checked;
|
||||||
} else {
|
} else {
|
||||||
return this.refs.field.value;
|
return this.refs.field.value;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
getSelectedElement: function() {
|
|
||||||
|
getSelectedElement() {
|
||||||
return this.refs.field.options[this.refs.field.selectedIndex];
|
return this.refs.field.options[this.refs.field.selectedIndex];
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
// Pass all unhandled props to the field element
|
// Pass all unhandled props to the field element
|
||||||
const otherProps = Object.assign({}, this.props),
|
const otherProps = Object.assign({}, this.props),
|
||||||
isError = this.state.isError !== null ? this.state.isError : this.props.hasError,
|
isError = this.state.isError !== null ? this.state.isError : this.props.hasError,
|
||||||
|
@ -114,45 +125,56 @@ export let FormField = React.createClass({
|
||||||
{ isError && this.state.errorMessage ? <div className="form-field__error">{this.state.errorMessage}</div> : '' }
|
{ isError && this.state.errorMessage ? <div className="form-field__error">{this.state.errorMessage}</div> : '' }
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
export let FormRow = React.createClass({
|
export class FormRow extends React.Component {
|
||||||
_fieldRequiredText: 'This field is required',
|
static propTypes = {
|
||||||
propTypes: {
|
label: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element]),
|
||||||
label: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.element])
|
|
||||||
// helper: React.PropTypes.html,
|
// helper: React.PropTypes.html,
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._fieldRequiredText = 'This field is required';
|
||||||
|
|
||||||
|
this.state = {
|
||||||
isError: false,
|
isError: false,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
|
||||||
showError: function(text) {
|
showError(text) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isError: true,
|
isError: true,
|
||||||
errorMessage: text,
|
errorMessage: text,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
showRequiredError: function() {
|
|
||||||
|
showRequiredError() {
|
||||||
this.showError(this._fieldRequiredText);
|
this.showError(this._fieldRequiredText);
|
||||||
},
|
}
|
||||||
clearError: function(text) {
|
|
||||||
|
clearError(text) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isError: false,
|
isError: false,
|
||||||
errorMessage: ''
|
errorMessage: ''
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
getValue: function() {
|
|
||||||
|
getValue() {
|
||||||
return this.refs.field.getValue();
|
return this.refs.field.getValue();
|
||||||
},
|
}
|
||||||
getSelectedElement: function() {
|
|
||||||
|
getSelectedElement() {
|
||||||
return this.refs.field.getSelectedElement();
|
return this.refs.field.getSelectedElement();
|
||||||
},
|
}
|
||||||
focus: function() {
|
|
||||||
|
focus() {
|
||||||
this.refs.field.focus();
|
this.refs.field.focus();
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
const fieldProps = Object.assign({}, this.props),
|
const fieldProps = Object.assign({}, this.props),
|
||||||
elementId = formFieldId(),
|
elementId = formFieldId(),
|
||||||
renderLabelInFormField = formFieldNestedLabelTypes.includes(this.props.type);
|
renderLabelInFormField = formFieldNestedLabelTypes.includes(this.props.type);
|
||||||
|
@ -174,4 +196,4 @@ export let FormRow = React.createClass({
|
||||||
{ this.state.isError ? <div className="form-field__error">{this.state.errorMessage}</div> : '' }
|
{ this.state.isError ? <div className="form-field__error">{this.state.errorMessage}</div> : '' }
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ export default Link
|
||||||
|
|
||||||
// return (
|
// return (
|
||||||
// <a className={className} href={this.props.href || 'javascript:;'} title={this.props.title}
|
// <a className={className} href={this.props.href || 'javascript:;'} title={this.props.title}
|
||||||
// onClick={this.handleClick} {... 'style' in this.props ? {style: this.props.style} : {}}>
|
// onClick={(event) => { this.handleClick() }} {... 'style' in this.props ? {style: this.props.style} : {}}>
|
||||||
// {content}
|
// {content}
|
||||||
// </a>
|
// </a>
|
||||||
// );
|
// );
|
||||||
|
|
|
@ -3,25 +3,28 @@ import lbry from '../lbry.js';
|
||||||
import {BusyMessage, Icon} from './common.js';
|
import {BusyMessage, Icon} from './common.js';
|
||||||
import Link from 'component/link'
|
import Link from 'component/link'
|
||||||
|
|
||||||
var LoadScreen = React.createClass({
|
class LoadScreen extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
message: React.PropTypes.string.isRequired,
|
message: React.PropTypes.string.isRequired,
|
||||||
details: React.PropTypes.string,
|
details: React.PropTypes.string,
|
||||||
isWarning: React.PropTypes.bool,
|
isWarning: React.PropTypes.bool,
|
||||||
},
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
isWarning: false,
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
getInitialState: function() {
|
constructor(props) {
|
||||||
return {
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
message: null,
|
message: null,
|
||||||
details: null,
|
details: null,
|
||||||
isLagging: false,
|
isLagging: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
|
||||||
render: function() {
|
static defaultProps = {
|
||||||
|
isWarning: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
const imgSrc = lbry.imagePath('lbry-white-485x160.png');
|
const imgSrc = lbry.imagePath('lbry-white-485x160.png');
|
||||||
return (
|
return (
|
||||||
<div className="load-screen">
|
<div className="load-screen">
|
||||||
|
@ -35,7 +38,7 @@ var LoadScreen = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
export default LoadScreen;
|
export default LoadScreen;
|
||||||
|
|
|
@ -2,19 +2,19 @@ import React from 'react';
|
||||||
import {Icon} from './common.js';
|
import {Icon} from './common.js';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
|
|
||||||
export let DropDownMenuItem = React.createClass({
|
export class DropDownMenuItem extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
href: React.PropTypes.string,
|
href: React.PropTypes.string,
|
||||||
label: React.PropTypes.string,
|
label: React.PropTypes.string,
|
||||||
icon: React.PropTypes.string,
|
icon: React.PropTypes.string,
|
||||||
onClick: React.PropTypes.func,
|
onClick: React.PropTypes.func,
|
||||||
},
|
}
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
static defaultProps = {
|
||||||
iconPosition: 'left',
|
iconPosition: 'left',
|
||||||
}
|
}
|
||||||
},
|
|
||||||
render: function() {
|
render() {
|
||||||
var icon = (this.props.icon ? <Icon icon={this.props.icon} fixed /> : null);
|
var icon = (this.props.icon ? <Icon icon={this.props.icon} fixed /> : null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -26,23 +26,27 @@ export let DropDownMenuItem = React.createClass({
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export let DropDownMenu = React.createClass({
|
export class DropDownMenu extends React.Component {
|
||||||
_isWindowClickBound: false,
|
constructor(props) {
|
||||||
_menuDiv: null,
|
super(props);
|
||||||
|
|
||||||
getInitialState: function() {
|
this._isWindowClickBound = false;
|
||||||
return {
|
this._menuDiv = null;
|
||||||
|
|
||||||
|
this.state = {
|
||||||
menuOpen: false,
|
menuOpen: false,
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
componentWillUnmount: function() {
|
|
||||||
|
componentWillUnmount() {
|
||||||
if (this._isWindowClickBound) {
|
if (this._isWindowClickBound) {
|
||||||
window.removeEventListener('click', this.handleWindowClick, false);
|
window.removeEventListener('click', this.handleWindowClick, false);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
handleMenuIconClick: function(e) {
|
|
||||||
|
handleMenuIconClick(e) {
|
||||||
this.setState({
|
this.setState({
|
||||||
menuOpen: !this.state.menuOpen,
|
menuOpen: !this.state.menuOpen,
|
||||||
});
|
});
|
||||||
|
@ -52,35 +56,38 @@ export let DropDownMenu = React.createClass({
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
handleMenuClick: function(e) {
|
|
||||||
|
handleMenuClick(e) {
|
||||||
// Event bubbles up to the menu after a link is clicked
|
// Event bubbles up to the menu after a link is clicked
|
||||||
this.setState({
|
this.setState({
|
||||||
menuOpen: false,
|
menuOpen: false,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleWindowClick: function(e) {
|
|
||||||
|
handleWindowClick(e) {
|
||||||
if (this.state.menuOpen &&
|
if (this.state.menuOpen &&
|
||||||
(!this._menuDiv || !this._menuDiv.contains(e.target))) {
|
(!this._menuDiv || !this._menuDiv.contains(e.target))) {
|
||||||
this.setState({
|
this.setState({
|
||||||
menuOpen: false
|
menuOpen: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
if (!this.state.menuOpen && this._isWindowClickBound) {
|
if (!this.state.menuOpen && this._isWindowClickBound) {
|
||||||
this._isWindowClickBound = false;
|
this._isWindowClickBound = false;
|
||||||
window.removeEventListener('click', this.handleWindowClick, false);
|
window.removeEventListener('click', this.handleWindowClick, false);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="menu-container">
|
<div className="menu-container">
|
||||||
<Link ref={(span) => this._menuButton = span} button="text" icon="icon-ellipsis-v" onClick={this.handleMenuIconClick} />
|
<Link ref={(span) => this._menuButton = span} button="text" icon="icon-ellipsis-v" onClick={(event) => { this.handleMenuIconClick(event) }} />
|
||||||
{this.state.menuOpen
|
{this.state.menuOpen
|
||||||
? <div ref={(div) => this._menuDiv = div} className="menu" onClick={this.handleMenuClick}>
|
? <div ref={(div) => this._menuDiv = div} className="menu" onClick={(event) => { this.handleMenuClick(event) }}>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactModal from 'react-modal';
|
import ReactModal from 'react-modal';
|
||||||
|
|
||||||
export const ModalPage = React.createClass({
|
export class ModalPage extends React.Component {
|
||||||
render: function() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<ReactModal onCloseRequested={this.props.onAborted || this.props.onConfirmed} {...this.props}
|
<ReactModal onCloseRequested={this.props.onAborted || this.props.onConfirmed} {...this.props}
|
||||||
className={(this.props.className || '') + ' modal-page'}
|
className={(this.props.className || '') + ' modal-page'}
|
||||||
|
@ -13,6 +13,4 @@ export const ModalPage = React.createClass({
|
||||||
</ReactModal>
|
</ReactModal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default ModalPage;
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ import ReactModal from 'react-modal';
|
||||||
import Link from 'component/link';
|
import Link from 'component/link';
|
||||||
|
|
||||||
|
|
||||||
export const Modal = React.createClass({
|
export class Modal extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
type: React.PropTypes.oneOf(['alert', 'confirm', 'custom']),
|
type: React.PropTypes.oneOf(['alert', 'confirm', 'custom']),
|
||||||
overlay: React.PropTypes.bool,
|
overlay: React.PropTypes.bool,
|
||||||
onConfirmed: React.PropTypes.func,
|
onConfirmed: React.PropTypes.func,
|
||||||
|
@ -13,18 +13,18 @@ export const Modal = React.createClass({
|
||||||
abortButtonLabel: React.PropTypes.string,
|
abortButtonLabel: React.PropTypes.string,
|
||||||
confirmButtonDisabled: React.PropTypes.bool,
|
confirmButtonDisabled: React.PropTypes.bool,
|
||||||
abortButtonDisabled: React.PropTypes.bool,
|
abortButtonDisabled: React.PropTypes.bool,
|
||||||
},
|
}
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
static defaultProps = {
|
||||||
type: 'alert',
|
type: 'alert',
|
||||||
overlay: true,
|
overlay: true,
|
||||||
confirmButtonLabel: 'OK',
|
confirmButtonLabel: 'OK',
|
||||||
abortButtonLabel: 'Cancel',
|
abortButtonLabel: 'Cancel',
|
||||||
confirmButtonDisabled: false,
|
confirmButtonDisabled: false,
|
||||||
abortButtonDisabled: false,
|
abortButtonDisabled: false,
|
||||||
};
|
}
|
||||||
},
|
|
||||||
render: function() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<ReactModal onCloseRequested={this.props.onAborted || this.props.onConfirmed} {...this.props}
|
<ReactModal onCloseRequested={this.props.onAborted || this.props.onConfirmed} {...this.props}
|
||||||
className={(this.props.className || '') + ' modal'}
|
className={(this.props.className || '') + ' modal'}
|
||||||
|
@ -43,31 +43,35 @@ export const Modal = React.createClass({
|
||||||
</ReactModal>
|
</ReactModal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export const ExpandableModal = React.createClass({
|
export class ExpandableModal extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
expandButtonLabel: React.PropTypes.string,
|
expandButtonLabel: React.PropTypes.string,
|
||||||
extraContent: React.PropTypes.element,
|
extraContent: React.PropTypes.element,
|
||||||
},
|
}
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
static defaultProps = {
|
||||||
confirmButtonLabel: 'OK',
|
confirmButtonLabel: 'OK',
|
||||||
expandButtonLabel: 'Show More...',
|
expandButtonLabel: 'Show More...',
|
||||||
hideButtonLabel: 'Show Less',
|
hideButtonLabel: 'Show Less',
|
||||||
}
|
}
|
||||||
},
|
|
||||||
getInitialState: function() {
|
constructor(props) {
|
||||||
return {
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
expanded: false,
|
expanded: false,
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
toggleExpanded: function() {
|
|
||||||
|
toggleExpanded() {
|
||||||
this.setState({
|
this.setState({
|
||||||
expanded: !this.state.expanded,
|
expanded: !this.state.expanded,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<Modal type="custom" {... this.props}>
|
<Modal type="custom" {... this.props}>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
|
@ -77,11 +81,11 @@ export const ExpandableModal = React.createClass({
|
||||||
<div className="modal__buttons">
|
<div className="modal__buttons">
|
||||||
<Link button="primary" label={this.props.confirmButtonLabel} className="modal__button" onClick={this.props.onConfirmed} />
|
<Link button="primary" label={this.props.confirmButtonLabel} className="modal__button" onClick={this.props.onConfirmed} />
|
||||||
<Link button="alt" label={!this.state.expanded ? this.props.expandButtonLabel : this.props.hideButtonLabel}
|
<Link button="alt" label={!this.state.expanded ? this.props.expandButtonLabel : this.props.hideButtonLabel}
|
||||||
className="modal__button" onClick={this.toggleExpanded} />
|
className="modal__button" onClick={() => { this.toggleExpanded() }} />
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default Modal;
|
export default Modal;
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export const Notice = React.createClass({
|
export class Notice extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
isError: React.PropTypes.bool,
|
isError: React.PropTypes.bool,
|
||||||
},
|
}
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
static defaultProps = {
|
||||||
isError: false,
|
isError: false,
|
||||||
};
|
}
|
||||||
},
|
|
||||||
render: function() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<section className={'notice ' + (this.props.isError ? 'notice--error ' : '') + (this.props.className || '')}>
|
<section className={'notice ' + (this.props.isError ? 'notice--error ' : '') + (this.props.className || '')}>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default Notice;
|
export default Notice;
|
|
@ -5,14 +5,25 @@ import Modal from 'component/modal';
|
||||||
import rewards from 'rewards';
|
import rewards from 'rewards';
|
||||||
import Link from 'component/link'
|
import Link from 'component/link'
|
||||||
|
|
||||||
export let RewardLink = React.createClass({
|
export class RewardLink extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
type: React.PropTypes.string.isRequired,
|
type: React.PropTypes.string.isRequired,
|
||||||
claimed: React.PropTypes.bool,
|
claimed: React.PropTypes.bool,
|
||||||
onRewardClaim: React.PropTypes.func,
|
onRewardClaim: React.PropTypes.func,
|
||||||
onRewardFailure: React.PropTypes.func
|
onRewardFailure: React.PropTypes.func
|
||||||
},
|
}
|
||||||
refreshClaimable: function() {
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
claimable: true,
|
||||||
|
pending: false,
|
||||||
|
errorMessage: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshClaimable() {
|
||||||
switch(this.props.type) {
|
switch(this.props.type) {
|
||||||
case 'new_user':
|
case 'new_user':
|
||||||
this.setState({ claimable: true });
|
this.setState({ claimable: true });
|
||||||
|
@ -26,18 +37,13 @@ export let RewardLink = React.createClass({
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
componentWillMount: function() {
|
|
||||||
this.refreshClaimable();
|
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
claimable: true,
|
|
||||||
pending: false,
|
|
||||||
errorMessage: null
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
claimReward: function() {
|
componentWillMount() {
|
||||||
|
this.refreshClaimable();
|
||||||
|
}
|
||||||
|
|
||||||
|
claimReward() {
|
||||||
this.setState({
|
this.setState({
|
||||||
pending: true
|
pending: true
|
||||||
})
|
})
|
||||||
|
@ -55,28 +61,30 @@ export let RewardLink = React.createClass({
|
||||||
pending: false
|
pending: false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
clearError: function() {
|
|
||||||
|
clearError() {
|
||||||
if (this.props.onRewardFailure) {
|
if (this.props.onRewardFailure) {
|
||||||
this.props.onRewardFailure()
|
this.props.onRewardFailure()
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
errorMessage: null
|
errorMessage: null
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="reward-link">
|
<div className="reward-link">
|
||||||
{this.props.claimed
|
{this.props.claimed
|
||||||
? <span><Icon icon="icon-check" /> Reward claimed.</span>
|
? <span><Icon icon="icon-check" /> Reward claimed.</span>
|
||||||
: <Link button={this.props.button ? this.props.button : 'alt'} disabled={this.state.pending || !this.state.claimable }
|
: <Link button={this.props.button ? this.props.button : 'alt'} disabled={this.state.pending || !this.state.claimable }
|
||||||
label={ this.state.pending ? "Claiming..." : "Claim Reward"} onClick={this.claimReward} />}
|
label={ this.state.pending ? "Claiming..." : "Claim Reward"} onClick={() => { this.claimReward() }} />}
|
||||||
{this.state.errorMessage ?
|
{this.state.errorMessage ?
|
||||||
<Modal isOpen={true} contentLabel="Reward Claim Error" className="error-modal" onConfirmed={this.clearError}>
|
<Modal isOpen={true} contentLabel="Reward Claim Error" className="error-modal" onConfirmed={() => { this.clearError() }}>
|
||||||
{this.state.errorMessage}
|
{this.state.errorMessage}
|
||||||
</Modal>
|
</Modal>
|
||||||
: ''}
|
: ''}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
|
@ -1,18 +1,19 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import lbry from '../lbry.js';
|
import lbry from '../lbry.js';
|
||||||
|
|
||||||
export const SnackBar = React.createClass({
|
export class SnackBar extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
_displayTime: 5, // in seconds
|
this._displayTime = 5; // in seconds
|
||||||
|
this._hideTimeout = null;
|
||||||
|
|
||||||
_hideTimeout: null,
|
this.state = {
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
snacks: []
|
snacks: []
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
|
||||||
handleSnackReceived: function(event) {
|
handleSnackReceived(event) {
|
||||||
// if (this._hideTimeout) {
|
// if (this._hideTimeout) {
|
||||||
// clearTimeout(this._hideTimeout);
|
// clearTimeout(this._hideTimeout);
|
||||||
// }
|
// }
|
||||||
|
@ -20,14 +21,17 @@ export const SnackBar = React.createClass({
|
||||||
let snacks = this.state.snacks;
|
let snacks = this.state.snacks;
|
||||||
snacks.push(event.detail);
|
snacks.push(event.detail);
|
||||||
this.setState({ snacks: snacks});
|
this.setState({ snacks: snacks});
|
||||||
},
|
}
|
||||||
componentWillMount: function() {
|
|
||||||
|
componentWillMount() {
|
||||||
document.addEventListener('globalNotice', this.handleSnackReceived);
|
document.addEventListener('globalNotice', this.handleSnackReceived);
|
||||||
},
|
}
|
||||||
componentWillUnmount: function() {
|
|
||||||
|
componentWillUnmount() {
|
||||||
document.removeEventListener('globalNotice', this.handleSnackReceived);
|
document.removeEventListener('globalNotice', this.handleSnackReceived);
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
if (!this.state.snacks.length) {
|
if (!this.state.snacks.length) {
|
||||||
this._hideTimeout = null; //should be unmounting anyway, but be safe?
|
this._hideTimeout = null; //should be unmounting anyway, but be safe?
|
||||||
return null;
|
return null;
|
||||||
|
@ -51,7 +55,7 @@ export const SnackBar = React.createClass({
|
||||||
<a className="snack-bar__action" href={snack.linkTarget}>{snack.linkText}</a> : ''}
|
<a className="snack-bar__action" href={snack.linkTarget}>{snack.linkText}</a> : ''}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default SnackBar;
|
export default SnackBar;
|
|
@ -2,21 +2,26 @@ import React from 'react';
|
||||||
import lbry from '../lbry.js';
|
import lbry from '../lbry.js';
|
||||||
import LoadScreen from './load_screen.js';
|
import LoadScreen from './load_screen.js';
|
||||||
|
|
||||||
var SplashScreen = React.createClass({
|
export class SplashScreen extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
message: React.PropTypes.string,
|
message: React.PropTypes.string,
|
||||||
onLoadDone: React.PropTypes.func,
|
onLoadDone: React.PropTypes.func,
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
details: 'Starting daemon',
|
details: 'Starting daemon',
|
||||||
isLagging: false,
|
isLagging: false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
|
||||||
updateStatus: function() {
|
updateStatus() {
|
||||||
lbry.status().then(this._updateStatusCallback);
|
lbry.status().then((status) => { this._updateStatusCallback(status) });
|
||||||
},
|
}
|
||||||
_updateStatusCallback: function(status) {
|
|
||||||
|
_updateStatusCallback(status) {
|
||||||
const startupStatus = status.startup_status
|
const startupStatus = status.startup_status
|
||||||
if (startupStatus.code == 'started') {
|
if (startupStatus.code == 'started') {
|
||||||
// Wait until we are able to resolve a name before declaring
|
// Wait until we are able to resolve a name before declaring
|
||||||
|
@ -40,8 +45,9 @@ var SplashScreen = React.createClass({
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.updateStatus();
|
this.updateStatus();
|
||||||
}, 500);
|
}, 500);
|
||||||
},
|
}
|
||||||
componentDidMount: function() {
|
|
||||||
|
componentDidMount() {
|
||||||
lbry.connect().then((isConnected) => {
|
lbry.connect().then((isConnected) => {
|
||||||
if (isConnected) {
|
if (isConnected) {
|
||||||
this.updateStatus();
|
this.updateStatus();
|
||||||
|
@ -53,10 +59,11 @@ var SplashScreen = React.createClass({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return <LoadScreen message={this.props.message} details={this.state.details} isWarning={this.state.isLagging} />
|
return <LoadScreen message={this.props.message} details={this.state.details} isWarning={this.state.isLagging} />
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default SplashScreen;
|
export default SplashScreen;
|
||||||
|
|
|
@ -1,38 +1,44 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export let ToolTip = React.createClass({
|
export class ToolTip extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
body: React.PropTypes.string.isRequired,
|
body: React.PropTypes.string.isRequired,
|
||||||
label: React.PropTypes.string.isRequired
|
label: React.PropTypes.string.isRequired
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
showTooltip: false,
|
showTooltip: false,
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
handleClick: function() {
|
|
||||||
|
handleClick() {
|
||||||
this.setState({
|
this.setState({
|
||||||
showTooltip: !this.state.showTooltip,
|
showTooltip: !this.state.showTooltip,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleTooltipMouseOut: function() {
|
|
||||||
|
handleTooltipMouseOut() {
|
||||||
this.setState({
|
this.setState({
|
||||||
showTooltip: false,
|
showTooltip: false,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<span className={'tooltip ' + (this.props.className || '')}>
|
<span className={'tooltip ' + (this.props.className || '')}>
|
||||||
<a className="tooltip__link" onClick={this.handleClick}>
|
<a className="tooltip__link" onClick={() => { this.handleClick() }}>
|
||||||
{this.props.label}
|
{this.props.label}
|
||||||
</a>
|
</a>
|
||||||
<div className={'tooltip__body ' + (this.state.showTooltip ? '' : ' hidden')}
|
<div className={'tooltip__body ' + (this.state.showTooltip ? '' : ' hidden')}
|
||||||
onMouseOut={this.handleTooltipMouseOut}>
|
onMouseOut={() => { this.handleTooltipMouseOut() }}>
|
||||||
{this.props.body}
|
{this.props.body}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default ToolTip
|
export default ToolTip
|
|
@ -51,7 +51,7 @@ class VideoPlayButton extends React.Component {
|
||||||
icon="icon-play"
|
icon="icon-play"
|
||||||
onClick={this.onWatchClick.bind(this)} />
|
onClick={this.onWatchClick.bind(this)} />
|
||||||
{modal}
|
{modal}
|
||||||
<Modal contentLabel="Not enough credits" isOpen={modal == 'notEnoughCredits'} onConfirmed={closeModal}>
|
<Modal contentLabel="Not enough credits" isOpen={modal == 'notEnoughCredits'} onConfirmed={() => { this.closeModal() }}>
|
||||||
You don't have enough LBRY credits to pay for this stream.
|
You don't have enough LBRY credits to pay for this stream.
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -63,7 +63,7 @@ class VideoPlayButton extends React.Component {
|
||||||
This will purchase <strong>{title}</strong> for <strong><FilePrice uri={uri} look="plain" /></strong> credits.
|
This will purchase <strong>{title}</strong> for <strong><FilePrice uri={uri} look="plain" /></strong> credits.
|
||||||
</Modal>
|
</Modal>
|
||||||
<Modal
|
<Modal
|
||||||
isOpen={modal == 'timedOut'} onConfirmed={closeModal} contentLabel="Timed Out">
|
isOpen={modal == 'timedOut'} onConfirmed={() => { this.closeModal() }} contentLabel="Timed Out">
|
||||||
Sorry, your download timed out :(
|
Sorry, your download timed out :(
|
||||||
</Modal>
|
</Modal>
|
||||||
</div>);
|
</div>);
|
||||||
|
|
|
@ -6,34 +6,40 @@ import Link from '../component/link';
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const {ipcRenderer} = require('electron');
|
const {ipcRenderer} = require('electron');
|
||||||
|
|
||||||
const DeveloperPage = React.createClass({
|
class DeveloperPage extends React.Component {
|
||||||
getInitialState: function() {
|
constructor(props) {
|
||||||
return {
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
showDeveloperMenu: lbry.getClientSetting('showDeveloperMenu'),
|
showDeveloperMenu: lbry.getClientSetting('showDeveloperMenu'),
|
||||||
useCustomLighthouseServers: lbry.getClientSetting('useCustomLighthouseServers'),
|
useCustomLighthouseServers: lbry.getClientSetting('useCustomLighthouseServers'),
|
||||||
customLighthouseServers: lbry.getClientSetting('customLighthouseServers').join('\n'),
|
customLighthouseServers: lbry.getClientSetting('customLighthouseServers').join('\n'),
|
||||||
upgradePath: '',
|
upgradePath: '',
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
handleShowDeveloperMenuChange: function(event) {
|
|
||||||
|
handleShowDeveloperMenuChange(event) {
|
||||||
lbry.setClientSetting('showDeveloperMenu', event.target.checked);
|
lbry.setClientSetting('showDeveloperMenu', event.target.checked);
|
||||||
lbry.showMenuIfNeeded();
|
lbry.showMenuIfNeeded();
|
||||||
this.setState({
|
this.setState({
|
||||||
showDeveloperMenu: event.target.checked,
|
showDeveloperMenu: event.target.checked,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleUseCustomLighthouseServersChange: function(event) {
|
|
||||||
|
handleUseCustomLighthouseServersChange(event) {
|
||||||
lbry.setClientSetting('useCustomLighthouseServers', event.target.checked);
|
lbry.setClientSetting('useCustomLighthouseServers', event.target.checked);
|
||||||
this.setState({
|
this.setState({
|
||||||
useCustomLighthouseServers: event.target.checked,
|
useCustomLighthouseServers: event.target.checked,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleUpgradeFileChange: function(event) {
|
|
||||||
|
handleUpgradeFileChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
upgradePath: event.target.value,
|
upgradePath: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleForceUpgradeClick: function() {
|
|
||||||
|
handleForceUpgradeClick() {
|
||||||
let upgradeSent = false;
|
let upgradeSent = false;
|
||||||
if (!this.state.upgradePath) {
|
if (!this.state.upgradePath) {
|
||||||
alert('Please select a file to upgrade from');
|
alert('Please select a file to upgrade from');
|
||||||
|
@ -51,37 +57,38 @@ const DeveloperPage = React.createClass({
|
||||||
alert('Failed to start upgrade. Is "' + this.state.upgradePath + '" a valid path to the upgrade?');
|
alert('Failed to start upgrade. Is "' + this.state.upgradePath + '" a valid path to the upgrade?');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
<section className="card">
|
<section className="card">
|
||||||
<h3>Developer Settings</h3>
|
<h3>Developer Settings</h3>
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<label><FormField type="checkbox" onChange={this.handleShowDeveloperMenuChange} checked={this.state.showDeveloperMenu} /> Show developer menu</label>
|
<label><FormField type="checkbox" onChange={(event) => { this.handleShowDeveloperMenuChange() }} checked={this.state.showDeveloperMenu} /> Show developer menu</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<label><FormField type="checkbox" onChange={this.handleUseCustomLighthouseServersChange} checked={this.state.useCustomLighthouseServers} /> Use custom search servers</label>
|
<label><FormField type="checkbox" onChange={(event) => { this.handleUseCustomLighthouseServersChange() }} checked={this.state.useCustomLighthouseServers} /> Use custom search servers</label>
|
||||||
</div>
|
</div>
|
||||||
{this.state.useCustomLighthouseServers
|
{this.state.useCustomLighthouseServers
|
||||||
? <div className="form-row">
|
? <div className="form-row">
|
||||||
<label>
|
<label>
|
||||||
Custom search servers (one per line)
|
Custom search servers (one per line)
|
||||||
<div><FormField type="textarea" className="developer-page__custom-lighthouse-servers" value={this.state.customLighthouseServers} onChange={this.handleCustomLighthouseServersChange} checked={this.state.debugMode} /></div>
|
<div><FormField type="textarea" className="developer-page__custom-lighthouse-servers" value={this.state.customLighthouseServers} onChange={(event) => { this.handleCustomLighthouseServersChange() }} checked={this.state.debugMode} /></div>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
</section>
|
</section>
|
||||||
<section className="card">
|
<section className="card">
|
||||||
<div className="form-row">
|
<div className="form-row">
|
||||||
<FormField name="file" ref="file" type="file" onChange={this.handleUpgradeFileChange}/>
|
<FormField name="file" ref="file" type="file" onChange={(event) => { this.handleUpgradeFileChange() }}/>
|
||||||
|
|
||||||
<Link label="Force Upgrade" button="alt" onClick={this.handleForceUpgradeClick} />
|
<Link label="Force Upgrade" button="alt" onClick={(event) => { this.handleForceUpgradeClick() }} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default DeveloperPage;
|
export default DeveloperPage;
|
||||||
|
|
|
@ -5,14 +5,17 @@ import Link from 'component/link';
|
||||||
import SubHeader from 'component/subHeader'
|
import SubHeader from 'component/subHeader'
|
||||||
import {version as uiVersion} from 'json!../../../package.json';
|
import {version as uiVersion} from 'json!../../../package.json';
|
||||||
|
|
||||||
var HelpPage = React.createClass({
|
class HelpPage extends React.Component {
|
||||||
getInitialState: function() {
|
constructor(props) {
|
||||||
return {
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
versionInfo: null,
|
versionInfo: null,
|
||||||
lbryId: null,
|
lbryId: null,
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
componentWillMount: function() {
|
|
||||||
|
componentWillMount() {
|
||||||
lbry.getVersionInfo((info) => {
|
lbry.getVersionInfo((info) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
versionInfo: info,
|
versionInfo: info,
|
||||||
|
@ -23,8 +26,9 @@ var HelpPage = React.createClass({
|
||||||
lbryId: info.lbry_id,
|
lbryId: info.lbry_id,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
let ver, osName, platform, newVerLink;
|
let ver, osName, platform, newVerLink;
|
||||||
if (this.state.versionInfo) {
|
if (this.state.versionInfo) {
|
||||||
ver = this.state.versionInfo;
|
ver = this.state.versionInfo;
|
||||||
|
@ -116,6 +120,6 @@ var HelpPage = React.createClass({
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default HelpPage;
|
export default HelpPage;
|
||||||
|
|
|
@ -6,10 +6,41 @@ import Link from 'component/link';
|
||||||
import rewards from 'rewards';
|
import rewards from 'rewards';
|
||||||
import Modal from 'component/modal';
|
import Modal from 'component/modal';
|
||||||
|
|
||||||
var PublishPage = React.createClass({
|
class PublishPage extends React.Component {
|
||||||
_requiredFields: ['meta_title', 'name', 'bid', 'tos_agree'],
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
_updateChannelList: function(channel) {
|
this._requiredFields = ['meta_title', 'name', 'bid', 'tos_agree'];
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
channels: null,
|
||||||
|
rawName: '',
|
||||||
|
name: '',
|
||||||
|
bid: 10,
|
||||||
|
hasFile: false,
|
||||||
|
feeAmount: '',
|
||||||
|
feeCurrency: 'USD',
|
||||||
|
channel: 'anonymous',
|
||||||
|
newChannelName: '@',
|
||||||
|
newChannelBid: 10,
|
||||||
|
nameResolved: null,
|
||||||
|
myClaimExists: null,
|
||||||
|
topClaimValue: 0.0,
|
||||||
|
myClaimValue: 0.0,
|
||||||
|
myClaimMetadata: null,
|
||||||
|
copyrightNotice: '',
|
||||||
|
otherLicenseDescription: '',
|
||||||
|
otherLicenseUrl: '',
|
||||||
|
uploadProgress: 0.0,
|
||||||
|
uploaded: false,
|
||||||
|
errorMessage: null,
|
||||||
|
submitting: false,
|
||||||
|
creatingChannel: false,
|
||||||
|
modal: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateChannelList(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
|
||||||
// that channel at the same time (used immediately after creating a channel)
|
// that channel at the same time (used immediately after creating a channel)
|
||||||
lbry.channel_list_mine().then((channels) => {
|
lbry.channel_list_mine().then((channels) => {
|
||||||
|
@ -19,8 +50,9 @@ var PublishPage = React.createClass({
|
||||||
... channel ? {channel} : {}
|
... channel ? {channel} : {}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleSubmit: function(event) {
|
|
||||||
|
handleSubmit(event) {
|
||||||
if (typeof event !== 'undefined') {
|
if (typeof event !== 'undefined') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
@ -113,51 +145,27 @@ var PublishPage = React.createClass({
|
||||||
} else {
|
} else {
|
||||||
doPublish();
|
doPublish();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
handlePublishStarted() {
|
||||||
channels: null,
|
|
||||||
rawName: '',
|
|
||||||
name: '',
|
|
||||||
bid: 10,
|
|
||||||
hasFile: false,
|
|
||||||
feeAmount: '',
|
|
||||||
feeCurrency: 'USD',
|
|
||||||
channel: 'anonymous',
|
|
||||||
newChannelName: '@',
|
|
||||||
newChannelBid: 10,
|
|
||||||
nameResolved: null,
|
|
||||||
myClaimExists: null,
|
|
||||||
topClaimValue: 0.0,
|
|
||||||
myClaimValue: 0.0,
|
|
||||||
myClaimMetadata: null,
|
|
||||||
copyrightNotice: '',
|
|
||||||
otherLicenseDescription: '',
|
|
||||||
otherLicenseUrl: '',
|
|
||||||
uploadProgress: 0.0,
|
|
||||||
uploaded: false,
|
|
||||||
errorMessage: null,
|
|
||||||
submitting: false,
|
|
||||||
creatingChannel: false,
|
|
||||||
modal: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
handlePublishStarted: function() {
|
|
||||||
this.setState({
|
this.setState({
|
||||||
modal: 'publishStarted',
|
modal: 'publishStarted',
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handlePublishStartedConfirmed: function() {
|
|
||||||
|
handlePublishStartedConfirmed() {
|
||||||
this.props.navigate('/published')
|
this.props.navigate('/published')
|
||||||
},
|
}
|
||||||
handlePublishError: function(error) {
|
|
||||||
|
handlePublishError(error) {
|
||||||
this.setState({
|
this.setState({
|
||||||
submitting: false,
|
submitting: false,
|
||||||
modal: 'error',
|
modal: 'error',
|
||||||
errorMessage: error.message,
|
errorMessage: error.message,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleNameChange: function(event) {
|
|
||||||
|
handleNameChange(event) {
|
||||||
var rawName = event.target.value;
|
var rawName = event.target.value;
|
||||||
|
|
||||||
if (!rawName) {
|
if (!rawName) {
|
||||||
|
@ -224,28 +232,33 @@ var PublishPage = React.createClass({
|
||||||
myClaimExists: false,
|
myClaimExists: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleBidChange: function(event) {
|
|
||||||
|
handleBidChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
bid: event.target.value,
|
bid: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleFeeAmountChange: function(event) {
|
|
||||||
|
handleFeeAmountChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
feeAmount: event.target.value,
|
feeAmount: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleFeeCurrencyChange: function(event) {
|
|
||||||
|
handleFeeCurrencyChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
feeCurrency: event.target.value,
|
feeCurrency: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleFeePrefChange: function(feeEnabled) {
|
|
||||||
|
handleFeePrefChange(feeEnabled) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isFee: feeEnabled
|
isFee: feeEnabled
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleLicenseChange: function(event) {
|
|
||||||
|
handleLicenseChange(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',
|
||||||
|
@ -257,30 +270,35 @@ var PublishPage = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState(newState);
|
this.setState(newState);
|
||||||
},
|
}
|
||||||
handleCopyrightNoticeChange: function(event) {
|
|
||||||
|
handleCopyrightNoticeChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
copyrightNotice: event.target.value,
|
copyrightNotice: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleOtherLicenseDescriptionChange: function(event) {
|
|
||||||
|
handleOtherLicenseDescriptionChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
otherLicenseDescription: event.target.value,
|
otherLicenseDescription: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleOtherLicenseUrlChange: function(event) {
|
|
||||||
|
handleOtherLicenseUrlChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
otherLicenseUrl: event.target.value,
|
otherLicenseUrl: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleChannelChange: function (event) {
|
|
||||||
|
handleChannelChange(event) {
|
||||||
const channel = event.target.value;
|
const channel = event.target.value;
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
channel: channel,
|
channel: channel,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleNewChannelNameChange: function (event) {
|
|
||||||
|
handleNewChannelNameChange(event) {
|
||||||
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 && !lbryuri.isValidName(newChannelName.substr(1), false)) {
|
if (newChannelName.length > 1 && !lbryuri.isValidName(newChannelName.substr(1), false)) {
|
||||||
|
@ -293,18 +311,21 @@ var PublishPage = React.createClass({
|
||||||
this.setState({
|
this.setState({
|
||||||
newChannelName: newChannelName,
|
newChannelName: newChannelName,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleNewChannelBidChange: function (event) {
|
|
||||||
|
handleNewChannelBidChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
newChannelBid: event.target.value,
|
newChannelBid: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleTOSChange: function(event) {
|
|
||||||
|
handleTOSChange(event) {
|
||||||
this.setState({
|
this.setState({
|
||||||
TOSAgreed: event.target.checked,
|
TOSAgreed: event.target.checked,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
handleCreateChannelClick: function (event) {
|
|
||||||
|
handleCreateChannelClick(event) {
|
||||||
if (this.state.newChannelName.length < 5) {
|
if (this.state.newChannelName.length < 5) {
|
||||||
this.refs.newChannelName.showError('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;
|
||||||
|
@ -330,8 +351,9 @@ var PublishPage = React.createClass({
|
||||||
creatingChannel: false,
|
creatingChannel: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
getLicenseUrl: function() {
|
|
||||||
|
getLicenseUrl() {
|
||||||
if (!this.refs.meta_license) {
|
if (!this.refs.meta_license) {
|
||||||
return '';
|
return '';
|
||||||
} else if (this.state.otherLicenseChosen) {
|
} else if (this.state.otherLicenseChosen) {
|
||||||
|
@ -339,20 +361,21 @@ var PublishPage = React.createClass({
|
||||||
} else {
|
} else {
|
||||||
return this.refs.meta_license.getSelectedElement().getAttribute('data-url') || '' ;
|
return this.refs.meta_license.getSelectedElement().getAttribute('data-url') || '' ;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
componentWillMount: function() {
|
|
||||||
|
componentWillMount() {
|
||||||
this._updateChannelList();
|
this._updateChannelList();
|
||||||
},
|
}
|
||||||
componentDidUpdate: function() {
|
|
||||||
},
|
onFileChange() {
|
||||||
onFileChange: function() {
|
|
||||||
if (this.refs.file.getValue()) {
|
if (this.refs.file.getValue()) {
|
||||||
this.setState({ hasFile: true })
|
this.setState({ hasFile: true })
|
||||||
} else {
|
} else {
|
||||||
this.setState({ hasFile: false })
|
this.setState({ hasFile: false })
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
getNameBidHelpText: function() {
|
|
||||||
|
getNameBidHelpText() {
|
||||||
if (!this.state.name) {
|
if (!this.state.name) {
|
||||||
return "Select a URL for this publish.";
|
return "Select a URL for this publish.";
|
||||||
} else if (this.state.nameResolved === false) {
|
} else if (this.state.nameResolved === false) {
|
||||||
|
@ -365,13 +388,15 @@ var PublishPage = React.createClass({
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
closeModal: function() {
|
|
||||||
|
closeModal() {
|
||||||
this.setState({
|
this.setState({
|
||||||
modal: null,
|
modal: null,
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
if (this.state.channels === null) {
|
if (this.state.channels === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -380,7 +405,7 @@ var PublishPage = React.createClass({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="main--single-column">
|
<main className="main--single-column">
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={(event) => { this.handleSubmit(event) }}>
|
||||||
<section className="card">
|
<section className="card">
|
||||||
<div className="card__title-primary">
|
<div className="card__title-primary">
|
||||||
<h4>Content</h4>
|
<h4>Content</h4>
|
||||||
|
@ -389,7 +414,7 @@ var PublishPage = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<FormRow name="file" label="File" ref="file" type="file" onChange={this.onFileChange}
|
<FormRow name="file" label="File" ref="file" type="file" onChange={(event) => { this.onFileChange(event) }}
|
||||||
helper={this.state.myClaimExists ? "If you don't choose a file, the file from your existing claim will be used." : null}/>
|
helper={this.state.myClaimExists ? "If you don't choose a file, the file from your existing claim will be used." : null}/>
|
||||||
</div>
|
</div>
|
||||||
{ !this.state.hasFile ? '' :
|
{ !this.state.hasFile ? '' :
|
||||||
|
@ -439,7 +464,7 @@ var PublishPage = React.createClass({
|
||||||
<FormField type="radio" name="isFree" label={!this.state.isFee ? 'Choose price...' : 'Price ' }
|
<FormField type="radio" name="isFree" label={!this.state.isFee ? 'Choose price...' : 'Price ' }
|
||||||
onChange={ () => { this.handleFeePrefChange(true) } } defaultChecked={this.state.isFee} />
|
onChange={ () => { this.handleFeePrefChange(true) } } defaultChecked={this.state.isFee} />
|
||||||
<span className={!this.state.isFee ? 'hidden' : ''}>
|
<span className={!this.state.isFee ? 'hidden' : ''}>
|
||||||
<FormField type="number" className="form-field__input--inline" step="0.01" placeholder="1.00" onChange={this.handleFeeAmountChange} /> <FormField type="select" onChange={this.handleFeeCurrencyChange}>
|
<FormField type="number" className="form-field__input--inline" step="0.01" placeholder="1.00" onChange={(event) => this.handleFeeAmountChange(event)} /> <FormField type="select" onChange={(event) => { this.handleFeeCurrencyChange(event) }}>
|
||||||
<option value="USD">US Dollars</option>
|
<option value="USD">US Dollars</option>
|
||||||
<option value="LBC">LBRY credits</option>
|
<option value="LBC">LBRY credits</option>
|
||||||
</FormField>
|
</FormField>
|
||||||
|
@ -448,7 +473,7 @@ var PublishPage = React.createClass({
|
||||||
<div className="form-field__helper">
|
<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.
|
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> : '' }
|
||||||
<FormRow label="License" type="select" ref="meta_license" name="license" onChange={this.handleLicenseChange}>
|
<FormRow label="License" type="select" ref="meta_license" name="license" onChange={(event) => { this.handleLicenseChange(event) }}>
|
||||||
<option></option>
|
<option></option>
|
||||||
<option>Public Domain</option>
|
<option>Public Domain</option>
|
||||||
<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/4.0/legalcode">Creative Commons Attribution 4.0 International</option>
|
||||||
|
@ -463,13 +488,13 @@ var PublishPage = React.createClass({
|
||||||
<FormField type="hidden" ref="meta_license_url" name="license_url" value={this.getLicenseUrl()} />
|
<FormField type="hidden" ref="meta_license_url" name="license_url" value={this.getLicenseUrl()} />
|
||||||
{this.state.copyrightChosen
|
{this.state.copyrightChosen
|
||||||
? <FormRow label="Copyright notice" type="text" name="copyright-notice"
|
? <FormRow label="Copyright notice" type="text" name="copyright-notice"
|
||||||
value={this.state.copyrightNotice} onChange={this.handleCopyrightNoticeChange} />
|
value={this.state.copyrightNotice} onChange={(event) => { this.handleCopyrightNoticeChange(event) }} />
|
||||||
: null}
|
: null}
|
||||||
{this.state.otherLicenseChosen ?
|
{this.state.otherLicenseChosen ?
|
||||||
<FormRow label="License description" type="text" name="other-license-description" onChange={this.handleOtherLicenseDescriptionChange} />
|
<FormRow label="License description" type="text" name="other-license-description" onChange={(event) => { this.handleOtherLicenseDescriptionChange() }} />
|
||||||
: null}
|
: null}
|
||||||
{this.state.otherLicenseChosen ?
|
{this.state.otherLicenseChosen ?
|
||||||
<FormRow label="License URL" type="text" name="other-license-url" onChange={this.handleOtherLicenseUrlChange} />
|
<FormRow label="License URL" type="text" name="other-license-url" onChange={(event) => { this.handleOtherLicenseUrlChange(event) }} />
|
||||||
: null}
|
: null}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -482,7 +507,7 @@ var PublishPage = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<FormRow type="select" tabIndex="1" onChange={this.handleChannelChange} value={this.state.channel}>
|
<FormRow type="select" tabIndex="1" onChange={(event) => { this.handleChannelChange(event) }} 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 identity...</option>
|
<option key="new" value="new">New identity...</option>
|
||||||
|
@ -490,17 +515,17 @@ var PublishPage = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
{this.state.channel == 'new' ?
|
{this.state.channel == 'new' ?
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<FormRow label="Name" type="text" onChange={this.handleNewChannelNameChange} ref={newChannelName => { this.refs.newChannelName = newChannelName }}
|
<FormRow label="Name" type="text" onChange={(event) => { this.handleNewChannelNameChange(event) }} ref={newChannelName => { this.refs.newChannelName = newChannelName }}
|
||||||
value={this.state.newChannelName} />
|
value={this.state.newChannelName} />
|
||||||
<FormRow label="Deposit"
|
<FormRow label="Deposit"
|
||||||
postfix="LBC"
|
postfix="LBC"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
type="number"
|
type="number"
|
||||||
helper={lbcInputHelp}
|
helper={lbcInputHelp}
|
||||||
onChange={this.handleNewChannelBidChange}
|
onChange={(event) => { this.handleNewChannelBidChange(event) }}
|
||||||
value={this.state.newChannelBid} />
|
value={this.state.newChannelBid} />
|
||||||
<div className="form-row-submit">
|
<div className="form-row-submit">
|
||||||
<Link button="primary" label={!this.state.creatingChannel ? 'Create identity' : 'Creating identity...'} onClick={this.handleCreateChannelClick} disabled={this.state.creatingChannel} />
|
<Link button="primary" label={!this.state.creatingChannel ? 'Create identity' : 'Creating identity...'} onClick={(event) => { this.handleCreateChannelClick(event) }} disabled={this.state.creatingChannel} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
|
@ -513,7 +538,7 @@ var PublishPage = React.createClass({
|
||||||
<div className="card__subtitle">Where should this content permanently reside? <Link label="Read more" href="https://lbry.io/faq/naming" />.</div>
|
<div className="card__subtitle">Where should this content permanently reside? <Link label="Read more" href="https://lbry.io/faq/naming" />.</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<FormRow prefix="lbry://" type="text" ref="name" placeholder="myname" value={this.state.rawName} onChange={this.handleNameChange}
|
<FormRow prefix="lbry://" type="text" ref="name" placeholder="myname" value={this.state.rawName} onChange={(event) => { this.handleNameChange(event) }}
|
||||||
helper={this.getNameBidHelpText()} />
|
helper={this.getNameBidHelpText()} />
|
||||||
</div>
|
</div>
|
||||||
{ this.state.rawName ?
|
{ this.state.rawName ?
|
||||||
|
@ -523,7 +548,7 @@ var PublishPage = React.createClass({
|
||||||
step="0.01"
|
step="0.01"
|
||||||
label="Deposit"
|
label="Deposit"
|
||||||
postfix="LBC"
|
postfix="LBC"
|
||||||
onChange={this.handleBidChange}
|
onChange={(event) => { this.handleBidChange(event) }}
|
||||||
value={this.state.bid}
|
value={this.state.bid}
|
||||||
placeholder={this.state.nameResolved ? this.state.topClaimValue + 10 : 100}
|
placeholder={this.state.nameResolved ? this.state.topClaimValue + 10 : 100}
|
||||||
helper={lbcInputHelp} />
|
helper={lbcInputHelp} />
|
||||||
|
@ -537,29 +562,29 @@ var PublishPage = React.createClass({
|
||||||
<div className="card__content">
|
<div className="card__content">
|
||||||
<FormRow label={
|
<FormRow label={
|
||||||
<span>I agree to the <Link href="https://www.lbry.io/termsofservice" label="LBRY terms of service" checked={this.state.TOSAgreed} /></span>
|
<span>I agree to the <Link href="https://www.lbry.io/termsofservice" label="LBRY terms of service" checked={this.state.TOSAgreed} /></span>
|
||||||
} type="checkbox" name="tos_agree" ref={(field) => { this.refs.tos_agree = field }} onChange={this.handleTOSChange} />
|
} type="checkbox" name="tos_agree" ref={(field) => { this.refs.tos_agree = field }} onChange={(event) => { this.handleTOSChange(event)}} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div className="card-series-submit">
|
<div className="card-series-submit">
|
||||||
<Link button="primary" label={!this.state.submitting ? 'Publish' : 'Publishing...'} onClick={this.handleSubmit} disabled={this.state.submitting} />
|
<Link button="primary" label={!this.state.submitting ? 'Publish' : 'Publishing...'} onClick={(event) => { this.handleSubmit(event) }} disabled={this.state.submitting} />
|
||||||
<Link button="cancel" onClick={lbry.back} label="Cancel" />
|
<Link button="cancel" onClick={lbry.back} label="Cancel" />
|
||||||
<input type="submit" className="hidden" />
|
<input type="submit" className="hidden" />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<Modal isOpen={this.state.modal == 'publishStarted'} contentLabel="File published"
|
<Modal isOpen={this.state.modal == 'publishStarted'} contentLabel="File published"
|
||||||
onConfirmed={this.handlePublishStartedConfirmed}>
|
onConfirmed={(event) => { this.handlePublishStartedConfirmed(event) }}>
|
||||||
<p>Your file has been published to LBRY at the address <code>lbry://{this.state.name}</code>!</p>
|
<p>Your file has been published to LBRY at the address <code>lbry://{this.state.name}</code>!</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>
|
<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>
|
</Modal>
|
||||||
<Modal isOpen={this.state.modal == 'error'} contentLabel="Error publishing file"
|
<Modal isOpen={this.state.modal == 'error'} contentLabel="Error publishing file"
|
||||||
onConfirmed={this.closeModal}>
|
onConfirmed={(event) => { this.closeModal(event) }}>
|
||||||
The following error occurred when attempting to publish your file: {this.state.errorMessage}
|
The following error occurred when attempting to publish your file: {this.state.errorMessage}
|
||||||
</Modal>
|
</Modal>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default PublishPage;
|
export default PublishPage;
|
||||||
|
|
|
@ -3,8 +3,17 @@ import Link from 'component/link';
|
||||||
import Modal from '../component/modal.js';
|
import Modal from '../component/modal.js';
|
||||||
import lbry from '../lbry.js';
|
import lbry from '../lbry.js';
|
||||||
|
|
||||||
var ReportPage = React.createClass({
|
class ReportPage extends React.Component {
|
||||||
submitMessage: function() {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
submitting: false,
|
||||||
|
modal: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
submitMessage() {
|
||||||
if (this._messageArea.value) {
|
if (this._messageArea.value) {
|
||||||
this.setState({
|
this.setState({
|
||||||
submitting: true
|
submitting: true
|
||||||
|
@ -17,19 +26,15 @@ var ReportPage = React.createClass({
|
||||||
});
|
});
|
||||||
this._messageArea.value = '';
|
this._messageArea.value = '';
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
closeModal: function() {
|
|
||||||
|
closeModal() {
|
||||||
this.setState({
|
this.setState({
|
||||||
modal: null,
|
modal: null,
|
||||||
})
|
})
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
submitting: false,
|
|
||||||
modal: null,
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
render: function() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<main className="main--single-column">
|
<main className="main--single-column">
|
||||||
<section className="card">
|
<section className="card">
|
||||||
|
@ -39,7 +44,7 @@ var ReportPage = React.createClass({
|
||||||
<textarea ref={(t) => this._messageArea = t} cols="80" rows="10" name="message" type="text"/>
|
<textarea ref={(t) => this._messageArea = t} cols="80" rows="10" name="message" type="text"/>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-row form-row-submit">
|
<div className="form-row form-row-submit">
|
||||||
<button onClick={this.submitMessage} className={'button-block button-primary ' + (this.state.submitting ? 'disabled' : '')}>{this.state.submitting ? 'Submitting...' : 'Submit Report'}</button>
|
<button onClick={(event) => { this.submitMessage(event) }} className={'button-block button-primary ' + (this.state.submitting ? 'disabled' : '')}>{this.state.submitting ? 'Submitting...' : 'Submit Report'}</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section className="card">
|
<section className="card">
|
||||||
|
@ -47,12 +52,12 @@ var ReportPage = React.createClass({
|
||||||
You can also <Link href="https://github.com/lbryio/lbry/issues" label="submit an issue on GitHub"/>.
|
You can also <Link href="https://github.com/lbryio/lbry/issues" label="submit an issue on GitHub"/>.
|
||||||
</section>
|
</section>
|
||||||
<Modal isOpen={this.state.modal == 'submitted'} contentLabel="Bug report submitted"
|
<Modal isOpen={this.state.modal == 'submitted'} contentLabel="Bug report submitted"
|
||||||
onConfirmed={this.closeModal}>
|
onConfirmed={(event) => { this.closeModal(event) }}>
|
||||||
Your bug report has been submitted! Thank you for your feedback.
|
Your bug report has been submitted! Thank you for your feedback.
|
||||||
</Modal>
|
</Modal>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default ReportPage;
|
export default ReportPage;
|
||||||
|
|
|
@ -4,16 +4,17 @@ import {CreditAmount, Icon} from 'component/common.js';
|
||||||
import SubHeader from 'component/subHeader'
|
import SubHeader from 'component/subHeader'
|
||||||
import {RewardLink} from 'component/reward-link';
|
import {RewardLink} from 'component/reward-link';
|
||||||
|
|
||||||
const RewardTile = React.createClass({
|
export class RewardTile extends React.Component {
|
||||||
propTypes: {
|
static propTypes = {
|
||||||
type: React.PropTypes.string.isRequired,
|
type: React.PropTypes.string.isRequired,
|
||||||
title: React.PropTypes.string.isRequired,
|
title: React.PropTypes.string.isRequired,
|
||||||
description: React.PropTypes.string.isRequired,
|
description: React.PropTypes.string.isRequired,
|
||||||
claimed: React.PropTypes.bool.isRequired,
|
claimed: React.PropTypes.bool.isRequired,
|
||||||
value: React.PropTypes.number.isRequired,
|
value: React.PropTypes.number.isRequired,
|
||||||
onRewardClaim: React.PropTypes.func
|
onRewardClaim: React.PropTypes.func
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<section className="card">
|
<section className="card">
|
||||||
<div className="card__inner">
|
<div className="card__inner">
|
||||||
|
@ -31,19 +32,23 @@ const RewardTile = React.createClass({
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export let RewardsPage = React.createClass({
|
export class RewardsPage extends React.Component {
|
||||||
componentWillMount: function() {
|
constructor(props) {
|
||||||
this.loadRewards()
|
super(props);
|
||||||
},
|
|
||||||
getInitialState: function() {
|
this.state = {
|
||||||
return {
|
|
||||||
userRewards: null,
|
userRewards: null,
|
||||||
failed: null
|
failed: null,
|
||||||
};
|
};
|
||||||
},
|
}
|
||||||
loadRewards: function() {
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.loadRewards()
|
||||||
|
}
|
||||||
|
|
||||||
|
loadRewards() {
|
||||||
lbryio.call('reward', 'list', {}).then((userRewards) => {
|
lbryio.call('reward', 'list', {}).then((userRewards) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
userRewards: userRewards,
|
userRewards: userRewards,
|
||||||
|
@ -51,8 +56,9 @@ export let RewardsPage = React.createClass({
|
||||||
}, () => {
|
}, () => {
|
||||||
this.setState({failed: true })
|
this.setState({failed: true })
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<main className="main--single-column">
|
<main className="main--single-column">
|
||||||
<SubHeader />
|
<SubHeader />
|
||||||
|
@ -66,6 +72,6 @@ export let RewardsPage = React.createClass({
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default RewardsPage;
|
export default RewardsPage;
|
||||||
|
|
|
@ -3,62 +3,76 @@ import {FormField, FormRow} from 'component/form.js';
|
||||||
import SubHeader from 'component/subHeader'
|
import SubHeader from 'component/subHeader'
|
||||||
import lbry from 'lbry.js';
|
import lbry from 'lbry.js';
|
||||||
|
|
||||||
var SettingsPage = React.createClass({
|
class SettingsPage extends React.Component {
|
||||||
setDaemonSetting: function(name, value) {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
const daemonSettings = this.props.daemonSettings
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
isMaxUpload: daemonSettings && daemonSettings.max_upload != 0,
|
||||||
|
isMaxDownload: daemonSettings && daemonSettings.max_download != 0,
|
||||||
|
showNsfw: lbry.getClientSetting('showNsfw'),
|
||||||
|
showUnavailable: lbry.getClientSetting('showUnavailable'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setDaemonSetting(name, value) {
|
||||||
this.props.setDaemonSetting(name, value)
|
this.props.setDaemonSetting(name, value)
|
||||||
},
|
}
|
||||||
setClientSetting: function(name, value) {
|
|
||||||
|
setClientSetting(name, value) {
|
||||||
lbry.setClientSetting(name, value)
|
lbry.setClientSetting(name, value)
|
||||||
this._onSettingSaveSuccess()
|
this._onSettingSaveSuccess()
|
||||||
},
|
}
|
||||||
onRunOnStartChange: function (event) {
|
|
||||||
|
onRunOnStartChange(event) {
|
||||||
this.setDaemonSetting('run_on_startup', event.target.checked);
|
this.setDaemonSetting('run_on_startup', event.target.checked);
|
||||||
},
|
}
|
||||||
onShareDataChange: function (event) {
|
|
||||||
|
onShareDataChange(event) {
|
||||||
this.setDaemonSetting('share_usage_data', event.target.checked);
|
this.setDaemonSetting('share_usage_data', event.target.checked);
|
||||||
},
|
}
|
||||||
onDownloadDirChange: function(event) {
|
|
||||||
|
onDownloadDirChange(event) {
|
||||||
this.setDaemonSetting('download_directory', event.target.value);
|
this.setDaemonSetting('download_directory', event.target.value);
|
||||||
},
|
}
|
||||||
onMaxUploadPrefChange: function(isLimited) {
|
|
||||||
|
onMaxUploadPrefChange(isLimited) {
|
||||||
if (!isLimited) {
|
if (!isLimited) {
|
||||||
this.setDaemonSetting('max_upload', 0.0);
|
this.setDaemonSetting('max_upload', 0.0);
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
isMaxUpload: isLimited
|
isMaxUpload: isLimited
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
onMaxUploadFieldChange: function(event) {
|
|
||||||
|
onMaxUploadFieldChange(event) {
|
||||||
this.setDaemonSetting('max_upload', Number(event.target.value));
|
this.setDaemonSetting('max_upload', Number(event.target.value));
|
||||||
},
|
}
|
||||||
onMaxDownloadPrefChange: function(isLimited) {
|
|
||||||
|
onMaxDownloadPrefChange(isLimited) {
|
||||||
if (!isLimited) {
|
if (!isLimited) {
|
||||||
this.setDaemonSetting('max_download', 0.0);
|
this.setDaemonSetting('max_download', 0.0);
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
isMaxDownload: isLimited
|
isMaxDownload: isLimited
|
||||||
});
|
});
|
||||||
},
|
|
||||||
onMaxDownloadFieldChange: function(event) {
|
|
||||||
this.setDaemonSetting('max_download', Number(event.target.value));
|
|
||||||
},
|
|
||||||
getInitialState: function() {
|
|
||||||
const daemonSettings = this.props.daemonSettings
|
|
||||||
|
|
||||||
return {
|
|
||||||
isMaxUpload: daemonSettings && daemonSettings.max_upload != 0,
|
|
||||||
isMaxDownload: daemonSettings && daemonSettings.max_download != 0,
|
|
||||||
showNsfw: lbry.getClientSetting('showNsfw'),
|
|
||||||
showUnavailable: lbry.getClientSetting('showUnavailable'),
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
onShowNsfwChange: function(event) {
|
|
||||||
lbry.setClientSetting('showNsfw', event.target.checked);
|
|
||||||
},
|
|
||||||
onShowUnavailableChange: function(event) {
|
|
||||||
|
|
||||||
},
|
onMaxDownloadFieldChange(event) {
|
||||||
render: function() {
|
this.setDaemonSetting('max_download', Number(event.target.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
onShowNsfwChange(event) {
|
||||||
|
lbry.setClientSetting('showNsfw', event.target.checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
onShowUnavailableChange(event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
const {
|
const {
|
||||||
daemonSettings
|
daemonSettings
|
||||||
} = this.props
|
} = this.props
|
||||||
|
@ -185,6 +199,6 @@ var SettingsPage = React.createClass({
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default SettingsPage;
|
export default SettingsPage;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import lbry from '../lbry.js';
|
import lbry from '../lbry.js';
|
||||||
|
|
||||||
var StartPage = React.createClass({
|
class StartPage extends React.Component {
|
||||||
componentWillMount: function() {
|
componentWillMount() {
|
||||||
lbry.stop();
|
lbry.stop();
|
||||||
},
|
}
|
||||||
render: function() {
|
|
||||||
|
render() {
|
||||||
return (
|
return (
|
||||||
<main className="main--single-column">
|
<main className="main--single-column">
|
||||||
<h3>LBRY is Closed</h3>
|
<h3>LBRY is Closed</h3>
|
||||||
|
@ -13,6 +14,6 @@ var StartPage = React.createClass({
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
export default StartPage;
|
export default StartPage;
|
||||||
|
|
Loading…
Add table
Reference in a new issue