2017-06-06 23:19:12 +02:00
|
|
|
import React from "react";
|
2017-08-25 22:26:09 +02:00
|
|
|
import { formatCredits, formatFullPrice } from "util/formatCredits";
|
2017-06-06 23:19:12 +02:00
|
|
|
import lbry from "../lbry.js";
|
2016-04-10 02:00:56 +02:00
|
|
|
|
2016-11-22 21:19:08 +01:00
|
|
|
//component/icon.js
|
2017-06-08 06:42:19 +02:00
|
|
|
export class Icon extends React.PureComponent {
|
2017-05-17 10:10:25 +02:00
|
|
|
static propTypes = {
|
2017-01-09 10:09:20 +01:00
|
|
|
icon: React.PropTypes.string.isRequired,
|
2016-11-18 09:01:36 +01:00
|
|
|
className: React.PropTypes.string,
|
2017-01-09 10:09:20 +01:00
|
|
|
fixed: React.PropTypes.bool,
|
2017-06-06 23:19:12 +02:00
|
|
|
};
|
2017-05-17 10:10:25 +02:00
|
|
|
|
|
|
|
render() {
|
2017-06-06 23:19:12 +02:00
|
|
|
const { fixed, className } = this.props;
|
|
|
|
const spanClassName =
|
|
|
|
"icon " +
|
|
|
|
("fixed" in this.props ? "icon-fixed-width " : "") +
|
|
|
|
this.props.icon +
|
|
|
|
" " +
|
|
|
|
(this.props.className || "");
|
|
|
|
return <span className={spanClassName} />;
|
2016-04-10 02:00:56 +02:00
|
|
|
}
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
2016-04-10 02:00:56 +02:00
|
|
|
|
2017-06-08 06:42:19 +02:00
|
|
|
export class TruncatedText extends React.PureComponent {
|
2017-05-17 10:10:25 +02:00
|
|
|
static propTypes = {
|
|
|
|
lines: React.PropTypes.number,
|
2017-06-06 23:19:12 +02:00
|
|
|
};
|
2017-05-17 10:10:25 +02:00
|
|
|
|
2017-05-19 18:17:19 +02:00
|
|
|
static defaultProps = {
|
2017-06-06 23:19:12 +02:00
|
|
|
lines: null,
|
|
|
|
};
|
2017-05-19 18:17:19 +02:00
|
|
|
|
2017-05-17 10:10:25 +02:00
|
|
|
render() {
|
2017-06-06 23:19:12 +02:00
|
|
|
return (
|
|
|
|
<span
|
|
|
|
className="truncated-text"
|
|
|
|
style={{ WebkitLineClamp: this.props.lines }}
|
|
|
|
>
|
|
|
|
{this.props.children}
|
|
|
|
</span>
|
|
|
|
);
|
2016-08-04 10:08:12 +02:00
|
|
|
}
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
|
|
|
|
2017-06-08 06:42:19 +02:00
|
|
|
export class BusyMessage extends React.PureComponent {
|
2017-05-17 10:10:25 +02:00
|
|
|
static propTypes = {
|
|
|
|
message: React.PropTypes.string,
|
2017-06-06 23:19:12 +02:00
|
|
|
};
|
2016-08-04 10:08:12 +02:00
|
|
|
|
2017-05-17 10:10:25 +02:00
|
|
|
render() {
|
2017-06-06 23:19:12 +02:00
|
|
|
return (
|
|
|
|
<span>{this.props.message} <span className="busy-indicator" /></span>
|
|
|
|
);
|
2016-08-21 16:55:32 +02:00
|
|
|
}
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
2016-08-21 16:55:32 +02:00
|
|
|
|
2017-06-08 06:42:19 +02:00
|
|
|
export class CurrencySymbol extends React.PureComponent {
|
2017-05-17 10:10:25 +02:00
|
|
|
render() {
|
|
|
|
return <span>LBC</span>;
|
|
|
|
}
|
|
|
|
}
|
2016-08-08 02:20:14 +02:00
|
|
|
|
2017-06-08 06:42:19 +02:00
|
|
|
export class CreditAmount extends React.PureComponent {
|
2017-05-17 10:10:25 +02:00
|
|
|
static propTypes = {
|
2017-04-13 20:52:26 +02:00
|
|
|
amount: React.PropTypes.number.isRequired,
|
|
|
|
precision: React.PropTypes.number,
|
2017-04-17 22:22:08 +02:00
|
|
|
isEstimate: React.PropTypes.bool,
|
2017-04-17 09:59:06 +02:00
|
|
|
label: React.PropTypes.bool,
|
2017-04-17 11:10:45 +02:00
|
|
|
showFree: React.PropTypes.bool,
|
2017-08-23 02:59:36 +02:00
|
|
|
showFullPrice: React.PropTypes.bool,
|
2017-08-20 23:42:00 +02:00
|
|
|
showPlus: React.PropTypes.bool,
|
2017-06-06 23:19:12 +02:00
|
|
|
look: React.PropTypes.oneOf(["indicator", "plain"]),
|
2017-09-04 19:35:41 +02:00
|
|
|
fee: React.PropTypes.bool,
|
2017-06-06 23:19:12 +02:00
|
|
|
};
|
2017-05-17 10:10:25 +02:00
|
|
|
|
|
|
|
static defaultProps = {
|
2017-08-11 05:02:36 +02:00
|
|
|
precision: 2,
|
2017-05-17 10:10:25 +02:00
|
|
|
label: true,
|
2017-08-20 23:42:00 +02:00
|
|
|
showFree: false,
|
2017-06-06 23:19:12 +02:00
|
|
|
look: "indicator",
|
2017-08-23 02:59:36 +02:00
|
|
|
showFree: false,
|
|
|
|
showFullPrice: false,
|
2017-08-20 23:42:00 +02:00
|
|
|
showPlus: false,
|
2017-09-04 19:35:41 +02:00
|
|
|
fee: false,
|
2017-06-06 23:19:12 +02:00
|
|
|
};
|
2017-05-17 10:10:25 +02:00
|
|
|
|
|
|
|
render() {
|
2017-08-11 05:02:36 +02:00
|
|
|
const minimumRenderableAmount = Math.pow(10, -1 * this.props.precision);
|
2017-08-23 02:59:36 +02:00
|
|
|
const { amount, precision, showFullPrice } = this.props;
|
2017-08-11 05:02:36 +02:00
|
|
|
|
2017-08-23 02:59:36 +02:00
|
|
|
let formattedAmount;
|
|
|
|
let fullPrice = formatFullPrice(amount, 2);
|
|
|
|
|
|
|
|
if (showFullPrice) {
|
|
|
|
formattedAmount = fullPrice;
|
|
|
|
} else {
|
|
|
|
formattedAmount = amount > 0 && amount < minimumRenderableAmount
|
|
|
|
? "<" + minimumRenderableAmount
|
|
|
|
: formatCredits(amount, precision);
|
|
|
|
}
|
2017-08-10 05:19:41 +02:00
|
|
|
|
2017-04-17 11:10:45 +02:00
|
|
|
let amountText;
|
2017-08-11 05:02:36 +02:00
|
|
|
if (this.props.showFree && parseFloat(this.props.amount) === 0) {
|
2017-06-06 23:19:12 +02:00
|
|
|
amountText = __("free");
|
2017-04-17 11:10:45 +02:00
|
|
|
} else {
|
2017-08-20 23:42:00 +02:00
|
|
|
if (this.props.label) {
|
|
|
|
amountText =
|
|
|
|
formattedAmount +
|
|
|
|
" " +
|
|
|
|
(parseFloat(amount) == 1 ? __("credit") : __("credits"));
|
|
|
|
} else {
|
|
|
|
amountText = formattedAmount;
|
|
|
|
}
|
|
|
|
if (this.props.showPlus && amount > 0) {
|
|
|
|
amountText = "+" + amountText;
|
|
|
|
}
|
2017-04-17 11:10:45 +02:00
|
|
|
}
|
|
|
|
|
2016-04-10 02:00:56 +02:00
|
|
|
return (
|
2017-08-23 02:59:36 +02:00
|
|
|
<span
|
2017-09-04 19:35:41 +02:00
|
|
|
className={`credit-amount credit-amount--${this.props.look} ${this.props
|
|
|
|
.fee
|
|
|
|
? " meta"
|
|
|
|
: ""}`}
|
2017-08-23 02:59:36 +02:00
|
|
|
title={fullPrice}
|
|
|
|
>
|
2017-04-13 20:52:26 +02:00
|
|
|
<span>
|
2017-04-17 11:10:45 +02:00
|
|
|
{amountText}
|
2017-04-13 20:52:26 +02:00
|
|
|
</span>
|
2017-06-06 23:19:12 +02:00
|
|
|
{this.props.isEstimate
|
|
|
|
? <span
|
|
|
|
className="credit-amount__estimate"
|
|
|
|
title={__("This is an estimate and does not include data fees")}
|
|
|
|
>
|
|
|
|
*
|
|
|
|
</span>
|
|
|
|
: null}
|
2016-04-10 02:00:56 +02:00
|
|
|
</span>
|
|
|
|
);
|
|
|
|
}
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
2016-09-01 08:40:23 +02:00
|
|
|
|
2017-05-17 10:10:25 +02:00
|
|
|
let addressStyle = {
|
2017-06-06 23:19:12 +02:00
|
|
|
fontFamily:
|
|
|
|
'"Consolas", "Lucida Console", "Adobe Source Code Pro", monospace',
|
2016-09-01 08:40:23 +02:00
|
|
|
};
|
2017-06-08 06:42:19 +02:00
|
|
|
export class Address extends React.PureComponent {
|
2017-05-17 10:10:25 +02:00
|
|
|
static propTypes = {
|
2016-09-01 08:40:23 +02:00
|
|
|
address: React.PropTypes.string,
|
2017-06-06 23:19:12 +02:00
|
|
|
};
|
2017-05-17 10:10:25 +02:00
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this._inputElem = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2016-09-01 08:40:23 +02:00
|
|
|
return (
|
2017-06-06 23:19:12 +02:00
|
|
|
<input
|
|
|
|
className="input-copyable"
|
|
|
|
type="text"
|
|
|
|
ref={input => {
|
|
|
|
this._inputElem = input;
|
|
|
|
}}
|
|
|
|
onFocus={() => {
|
|
|
|
this._inputElem.select();
|
|
|
|
}}
|
|
|
|
style={addressStyle}
|
|
|
|
readOnly="readonly"
|
2017-07-16 18:29:46 +02:00
|
|
|
value={this.props.address || ""}
|
2017-06-06 23:19:12 +02:00
|
|
|
/>
|
2016-09-01 08:40:23 +02:00
|
|
|
);
|
|
|
|
}
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
2016-11-11 13:56:55 +01:00
|
|
|
|
2017-06-08 06:42:19 +02:00
|
|
|
export class Thumbnail extends React.PureComponent {
|
2017-05-17 10:10:25 +02:00
|
|
|
static propTypes = {
|
2017-01-13 04:23:12 +01:00
|
|
|
src: React.PropTypes.string,
|
2017-06-06 23:19:12 +02:00
|
|
|
};
|
2017-05-17 10:10:25 +02:00
|
|
|
|
|
|
|
handleError() {
|
2016-11-11 13:56:55 +01:00
|
|
|
if (this.state.imageUrl != this._defaultImageUri) {
|
|
|
|
this.setState({
|
|
|
|
imageUri: this._defaultImageUri,
|
|
|
|
});
|
|
|
|
}
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
2017-06-06 23:19:12 +02:00
|
|
|
this._defaultImageUri = lbry.imagePath("default-thumb.svg");
|
|
|
|
this._maxLoadTime = 10000;
|
|
|
|
this._isMounted = false;
|
2017-05-17 10:10:25 +02:00
|
|
|
|
|
|
|
this.state = {
|
2016-11-11 13:56:55 +01:00
|
|
|
imageUri: this.props.src || this._defaultImageUri,
|
|
|
|
};
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
2017-01-04 21:46:20 +01:00
|
|
|
this._isMounted = true;
|
2016-11-11 13:56:55 +01:00
|
|
|
setTimeout(() => {
|
2017-01-04 21:46:20 +01:00
|
|
|
if (this._isMounted && !this.refs.img.complete) {
|
2016-11-11 13:56:55 +01:00
|
|
|
this.setState({
|
|
|
|
imageUri: this._defaultImageUri,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}, this._maxLoadTime);
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
2017-01-04 21:46:20 +01:00
|
|
|
this._isMounted = false;
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2017-06-06 23:19:12 +02:00
|
|
|
const className = this.props.className ? this.props.className : "",
|
|
|
|
otherProps = Object.assign({}, this.props);
|
2017-04-17 14:27:39 +02:00
|
|
|
delete otherProps.className;
|
2017-06-06 23:19:12 +02:00
|
|
|
return (
|
|
|
|
<img
|
|
|
|
ref="img"
|
|
|
|
onError={() => {
|
|
|
|
this.handleError();
|
|
|
|
}}
|
|
|
|
{...otherProps}
|
|
|
|
className={className}
|
|
|
|
src={this.state.imageUri}
|
|
|
|
/>
|
|
|
|
);
|
2017-05-17 10:10:25 +02:00
|
|
|
}
|
|
|
|
}
|