commit
68b377e7a6
18 changed files with 571 additions and 132 deletions
BIN
dist/img/warning.png
vendored
Normal file
BIN
dist/img/warning.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
6
dist/index.html
vendored
6
dist/index.html
vendored
|
@ -20,8 +20,9 @@
|
|||
</head>
|
||||
<body>
|
||||
<div id="canvas"></div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.6/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-modal/1.5.2/react-modal.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.7.4/polyfill.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Clamp.js/0.5.1/clamp.min.js"></script>
|
||||
<script src="./js/mediaelement/jquery.js"></script>
|
||||
|
@ -32,6 +33,7 @@
|
|||
<script src="./js/component/form.js?i=0"></script>
|
||||
<script src="./js/component/link.js?i=0"></script>
|
||||
<script src="./js/component/menu.js?i=0"></script>
|
||||
<script src="./js/component/modal.js?i=0"></script>
|
||||
<script src="./js/component/header.js?i=0"></script>
|
||||
<script src="./js/component/drawer.js?i=0"></script>
|
||||
<script src="./js/component/splash.js?i=0"></script>
|
||||
|
|
97
js/app.js
97
js/app.js
|
@ -1,4 +1,13 @@
|
|||
var App = React.createClass({
|
||||
_error_key_labels: {
|
||||
connectionString: 'API connection string',
|
||||
method: 'Method',
|
||||
params: 'Parameters',
|
||||
code: 'Error code',
|
||||
message: 'Error message',
|
||||
data: 'Error data',
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
// For now, routes are in format ?page or ?page=args
|
||||
var match, param, val, viewingPage,
|
||||
|
@ -11,35 +20,42 @@ var App = React.createClass({
|
|||
viewingPage: viewingPage,
|
||||
drawerOpen: drawerOpenRaw !== null ? JSON.parse(drawerOpenRaw) : true,
|
||||
pageArgs: val,
|
||||
errorInfo: null,
|
||||
modal: null,
|
||||
startNotice: null,
|
||||
updateUrl: null,
|
||||
isOldOSX: null,
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
lbry.getStartNotice(function(notice) {
|
||||
if (notice) {
|
||||
alert(notice);
|
||||
this.setState({
|
||||
modal: 'startNotice',
|
||||
startNotice: notice
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
componentWillMount: function() {
|
||||
lbry.checkNewVersionAvailable(function(isAvailable) {
|
||||
document.addEventListener('unhandledError', (event) => {
|
||||
this.alertError(event.detail);
|
||||
});
|
||||
|
||||
lbry.checkNewVersionAvailable((isAvailable) => {
|
||||
if (!isAvailable || sessionStorage.getItem('upgradeSkipped')) {
|
||||
return;
|
||||
}
|
||||
|
||||
var message = 'The version of LBRY you\'re using is not up to date.\n\n' +
|
||||
'Choose "OK" to download the latest version.';
|
||||
|
||||
lbry.getVersionInfo(function(versionInfo) {
|
||||
lbry.getVersionInfo((versionInfo) => {
|
||||
var isOldOSX = false;
|
||||
if (versionInfo.os_system == 'Darwin') {
|
||||
var updateUrl = 'https://lbry.io/get/lbry.dmg';
|
||||
|
||||
var maj, min, patch;
|
||||
[maj, min, patch] = versionInfo.lbrynet_version.split('.');
|
||||
if (maj == 0 && min <= 2 && patch <= 2) {
|
||||
// On OS X with version <= 0.2.2, we need to notify user to close manually close LBRY
|
||||
message += '\n\nBefore installing the new version, make sure to exit LBRY, if you started the app ' +
|
||||
'click that LBRY icon in your status bar and choose "Quit."';
|
||||
isOldOSX = true;
|
||||
}
|
||||
} else if (versionInfo.os_system == 'Linux') {
|
||||
var updateUrl = 'https://lbry.io/get/lbry.deb';
|
||||
|
@ -49,13 +65,11 @@ var App = React.createClass({
|
|||
var updateUrl = 'https://lbry.io/get';
|
||||
}
|
||||
|
||||
if (window.confirm(message))
|
||||
{
|
||||
lbry.stop();
|
||||
window.location = updateUrl;
|
||||
} else {
|
||||
sessionStorage.setItem('upgradeSkipped', true);
|
||||
};
|
||||
this.setState({
|
||||
modal: 'upgrade',
|
||||
isOldOSX: isOldOSX,
|
||||
updateUrl: updateUrl,
|
||||
})
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -67,12 +81,40 @@ var App = React.createClass({
|
|||
sessionStorage.setItem('drawerOpen', false);
|
||||
this.setState({ drawerOpen: false });
|
||||
},
|
||||
closeModal: function() {
|
||||
this.setState({
|
||||
modal: null,
|
||||
});
|
||||
},
|
||||
handleUpgradeClicked: function() {
|
||||
lbry.stop();
|
||||
window.location = this.state.updateUrl;
|
||||
},
|
||||
handleSkipClicked: function() {
|
||||
sessionStorage.setItem('upgradeSkipped', true);
|
||||
this.setState({
|
||||
modal: null,
|
||||
});
|
||||
},
|
||||
onSearch: function(term) {
|
||||
this.setState({
|
||||
viewingPage: 'discover',
|
||||
pageArgs: term
|
||||
});
|
||||
},
|
||||
alertError: function(error) {
|
||||
var errorInfoList = [];
|
||||
for (let key of Object.keys(error)) {
|
||||
let val = typeof error[key] == 'string' ? error[key] : JSON.stringify(error[key]);
|
||||
let label = this._error_key_labels[key];
|
||||
errorInfoList.push(<li key={key}><strong>{label}</strong>: <code>{val}</code></li>);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
modal: 'error',
|
||||
errorInfo: <ul className="error-modal__error-list">{errorInfoList}</ul>,
|
||||
});
|
||||
},
|
||||
getHeaderLinks: function()
|
||||
{
|
||||
switch(this.state.viewingPage)
|
||||
|
@ -151,6 +193,29 @@ var App = React.createClass({
|
|||
<Header onOpenDrawer={this.openDrawer} onSearch={this.onSearch} links={headerLinks} viewingPage={this.state.viewingPage} />
|
||||
{mainContent}
|
||||
</div>
|
||||
<Modal isOpen={this.state.modal == 'startNotice'} onConfirmed={this.closeModal}>
|
||||
{this.state.startNotice}
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'upgrade'} type="confirm" confirmButtonLabel="Upgrade" abortButtonLabel="Skip"
|
||||
onConfirmed={this.handleUpgradeClicked} onAborted={this.handleSkipClicked} >
|
||||
<p>The version of LBRY you're using is not up to date. Choose "Upgrade" to get the latest version.</p>
|
||||
{this.state.isOldOSX
|
||||
? <p>Before installing the new version, make sure to exit LBRY. If you started the app, click the LBRY icon in your status bar and choose "Quit."</p>
|
||||
: null}
|
||||
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'error'} type="custom" className="error-modal" overlayClassName="error-modal-overlay" >
|
||||
<h3 className="modal__header">Error</h3>
|
||||
|
||||
<div className="error-modal__content">
|
||||
<div><img className="error-modal__warning-symbol" src={lbry.imagePath('warning.png')} /></div>
|
||||
<p>We're sorry that LBRY has encountered an error. This has been reported and we will investigate the problem.</p>
|
||||
</div>
|
||||
{this.state.errorInfo}
|
||||
<div className="modal__buttons">
|
||||
<Link button="alt" label="OK" className="modal__button" onClick={this.closeModal} />
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -113,3 +113,36 @@ var Address = React.createClass({
|
|||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Thumbnail = React.createClass({
|
||||
_defaultImageUri: '/img/default-thumb.svg',
|
||||
_maxLoadTime: 10000,
|
||||
|
||||
propTypes: {
|
||||
src: React.PropTypes.string.isRequired,
|
||||
},
|
||||
handleError: function() {
|
||||
if (this.state.imageUrl != this._defaultImageUri) {
|
||||
this.setState({
|
||||
imageUri: this._defaultImageUri,
|
||||
});
|
||||
}
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
imageUri: this.props.src || this._defaultImageUri,
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
setTimeout(() => {
|
||||
if (!this.refs.img.complete) {
|
||||
this.setState({
|
||||
imageUri: this._defaultImageUri,
|
||||
});
|
||||
}
|
||||
}, this._maxLoadTime);
|
||||
},
|
||||
render: function() {
|
||||
return <img ref="img" onError={this.handleError} {... this.props} src={this.state.imageUri} />
|
||||
},
|
||||
});
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
var DrawerItem = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
subPages: [],
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
var isSelected = this.props.viewingPage == this.props.href.substr(2);
|
||||
var isSelected = (this.props.viewingPage == this.props.href.substr(2) ||
|
||||
this.props.subPages.indexOf(this.props.viewingPage) != -1);
|
||||
return <Link {...this.props} className={ 'drawer-item ' + (isSelected ? 'drawer-item-selected' : '') } />
|
||||
}
|
||||
});
|
||||
|
@ -32,8 +38,8 @@ var Drawer = React.createClass({
|
|||
</div>
|
||||
<DrawerItem href='/?discover' viewingPage={this.props.viewingPage} label="Discover" icon="icon-search" />
|
||||
<DrawerItem href='/?publish' viewingPage={this.props.viewingPage} label="Publish" icon="icon-upload" />
|
||||
<DrawerItem href='/?downloaded' viewingPage={this.props.viewingPage} label="My Files" icon='icon-cloud-download' />
|
||||
<DrawerItem href="/?wallet" viewingPage={this.props.viewingPage} label="My Wallet" badge={lbry.formatCredits(this.state.balance) } icon="icon-bank" />
|
||||
<DrawerItem href='/?downloaded' subPages={['published']} viewingPage={this.props.viewingPage} label="My Files" icon='icon-cloud-download' />
|
||||
<DrawerItem href="/?wallet" subPages={['send', 'receive', 'claim', 'referral']} viewingPage={this.props.viewingPage} label="My Wallet" badge={lbry.formatCredits(this.state.balance) } icon="icon-bank" />
|
||||
<DrawerItem href='/?settings' viewingPage={this.props.viewingPage} label="Settings" icon='icon-gear' />
|
||||
<DrawerItem href='/?help' viewingPage={this.props.viewingPage} label="Help" icon='icon-question-circle' />
|
||||
{isLinux ? <Link href="/?start" icon="icon-close" className="close-lbry-link" /> : null}
|
||||
|
|
|
@ -93,13 +93,22 @@ var DownloadLink = React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
downloading: false,
|
||||
filePath: null,
|
||||
modal: null,
|
||||
}
|
||||
},
|
||||
closeModal: function() {
|
||||
this.setState({
|
||||
modal: null,
|
||||
})
|
||||
},
|
||||
handleClick: function() {
|
||||
lbry.getCostEstimate(this.props.streamName, (amount) => {
|
||||
lbry.getBalance((balance) => {
|
||||
if (amount > balance) {
|
||||
alert("You don't have enough LBRY credits to pay for this stream.");
|
||||
this.setState({
|
||||
modal: 'notEnoughCredits',
|
||||
});
|
||||
} else {
|
||||
this.startDownload();
|
||||
}
|
||||
|
@ -113,15 +122,27 @@ var DownloadLink = React.createClass({
|
|||
});
|
||||
|
||||
lbry.getStream(this.props.streamName, (streamInfo) => {
|
||||
alert('Downloading to ' + streamInfo.path);
|
||||
console.log(streamInfo);
|
||||
this.setState({
|
||||
modal: 'downloadStarted',
|
||||
filePath: streamInfo.path,
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
var label = (!this.state.downloading ? this.props.label : this.props.downloadingLabel);
|
||||
return <Link button={this.props.button} hidden={this.props.hidden} style={this.props.style}
|
||||
disabled={this.state.downloading} label={label} icon={this.props.icon} onClick={this.handleClick} />;
|
||||
return (
|
||||
<span className="button-container">
|
||||
<Link button={this.props.button} hidden={this.props.hidden} style={this.props.style}
|
||||
disabled={this.state.downloading} label={label} icon={this.props.icon} onClick={this.handleClick} />
|
||||
<Modal isOpen={this.state.modal == 'downloadStarted'} onConfirmed={this.closeModal}>
|
||||
Downloading to {this.state.filePath}
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'notEnoughCredits'} onConfirmed={this.closeModal}>
|
||||
You don't have enough LBRY credits to pay for this stream.
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -138,22 +159,40 @@ var WatchLink = React.createClass({
|
|||
lbry.getCostEstimate(this.props.streamName, (amount) => {
|
||||
lbry.getBalance((balance) => {
|
||||
if (amount > balance) {
|
||||
alert("You don't have enough LBRY credits to pay for this stream.");
|
||||
this.setState({
|
||||
modal: 'notEnoughCredits',
|
||||
});
|
||||
} else {
|
||||
window.location = '?watch=' + this.props.streamName;
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
modal: null,
|
||||
};
|
||||
},
|
||||
closeModal: function() {
|
||||
this.setState({
|
||||
modal: null,
|
||||
});
|
||||
},
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
icon: 'icon-play',
|
||||
label: 'Watch',
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return <Link button={this.props.button} hidden={this.props.hidden} style={this.props.style}
|
||||
label={this.props.label} icon={this.props.icon} onClick={this.handleClick} />;
|
||||
return (
|
||||
<span className="button-container">
|
||||
<Link button={this.props.button} hidden={this.props.hidden} style={this.props.style}
|
||||
label={this.props.label} icon={this.props.icon} onClick={this.handleClick} />
|
||||
<Modal isOpen={this.state.modal == 'notEnoughCredits'} onConfirmed={this.closeModal}>
|
||||
You don't have enough LBRY credits to pay for this stream.
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
});
|
57
js/component/modal.js
Normal file
57
js/component/modal.js
Normal file
|
@ -0,0 +1,57 @@
|
|||
var Modal = React.createClass({
|
||||
propTypes: {
|
||||
type: React.PropTypes.oneOf(['alert', 'confirm', 'custom']),
|
||||
onConfirmed: React.PropTypes.func,
|
||||
onAborted: React.PropTypes.func,
|
||||
confirmButtonLabel: React.PropTypes.string,
|
||||
abortButtonLabel: React.PropTypes.string,
|
||||
confirmButtonDisabled: React.PropTypes.bool,
|
||||
abortButtonDisabled: React.PropTypes.bool,
|
||||
},
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
type: 'alert',
|
||||
confirmButtonLabel: 'OK',
|
||||
abortButtonLabel: 'Cancel',
|
||||
confirmButtonDisabled: false,
|
||||
abortButtonDisabled: false,
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
var props = Object.assign({}, this.props);
|
||||
|
||||
if (typeof props.className == 'undefined') {
|
||||
props.className = 'modal';
|
||||
} else {
|
||||
props.className += ' modal';
|
||||
}
|
||||
|
||||
if (typeof props.overlayClassName == 'undefined') {
|
||||
props.overlayClassName = 'modal-overlay';
|
||||
} else {
|
||||
props.overlayClassName += ' modal-overlay';
|
||||
}
|
||||
|
||||
props.onCloseRequested = props.onAborted || props.onConfirmed;
|
||||
|
||||
if (this.props.type == 'custom') {
|
||||
var buttons = null;
|
||||
} else {
|
||||
var buttons = (
|
||||
<div className="modal__buttons">
|
||||
{this.props.type == 'confirm'
|
||||
? <Link button="alt" label={props.abortButtonLabel} className="modal__button" disabled={this.props.abortButtonDisabled} onClick={props.onAborted} />
|
||||
: null}
|
||||
<Link button="primary" label={props.confirmButtonLabel} className="modal__button" disabled={this.props.confirmButtonDisabled} onClick={props.onConfirmed} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ReactModal {...props}>
|
||||
{this.props.children}
|
||||
{buttons}
|
||||
</ReactModal>
|
||||
);
|
||||
}
|
||||
});
|
48
js/lbry.js
48
js/lbry.js
|
@ -10,14 +10,38 @@ var lbry = {
|
|||
}
|
||||
};
|
||||
|
||||
lbry.jsonrpc_call = function (connectionString, method, params, callback, errorCallback, connectFailedCallback) {
|
||||
lbry.jsonrpc_call = function (connectionString, method, params, callback, errorCallback, connectFailedCallback, timeout) {
|
||||
var xhr = new XMLHttpRequest;
|
||||
if (typeof connectFailedCallback !== 'undefined') {
|
||||
if (timeout) {
|
||||
xhr.timeout = timeout;
|
||||
}
|
||||
|
||||
xhr.addEventListener('error', function (e) {
|
||||
connectFailedCallback(e);
|
||||
});
|
||||
xhr.addEventListener('timeout', function() {
|
||||
connectFailedCallback(new Error('XMLHttpRequest connection timed out'));
|
||||
})
|
||||
}
|
||||
xhr.addEventListener('load', function() {
|
||||
var response = JSON.parse(xhr.responseText);
|
||||
|
||||
if (response.error) {
|
||||
if (errorCallback) {
|
||||
errorCallback(response.error);
|
||||
} else {
|
||||
var errorEvent = new CustomEvent('unhandledError', {
|
||||
detail: {
|
||||
connectionString: connectionString,
|
||||
method: method,
|
||||
params: params,
|
||||
code: response.error.code,
|
||||
message: response.error.message,
|
||||
data: response.error.data
|
||||
}
|
||||
});
|
||||
document.dispatchEvent(errorEvent)
|
||||
}
|
||||
} else if (callback) {
|
||||
callback(response.result);
|
||||
|
@ -25,8 +49,21 @@ lbry.jsonrpc_call = function (connectionString, method, params, callback, errorC
|
|||
});
|
||||
|
||||
if (connectFailedCallback) {
|
||||
xhr.addEventListener('error', function (e) {
|
||||
connectFailedCallback(e);
|
||||
xhr.addEventListener('error', function (event) {
|
||||
connectFailedCallback(event);
|
||||
});
|
||||
} else {
|
||||
xhr.addEventListener('error', function (event) {
|
||||
var errorEvent = new CustomEvent('unhandledError', {
|
||||
detail: {
|
||||
connectionString: connectionString,
|
||||
method: method,
|
||||
params: params,
|
||||
code: xhr.status,
|
||||
message: 'Connection to API server failed'
|
||||
}
|
||||
});
|
||||
document.dispatchEvent(errorEvent);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -122,11 +159,6 @@ lbry.sendToAddress = function(amount, address, callback, errorCallback)
|
|||
lbry.call("send_amount_to_address", { "amount" : amount, "address": address }, callback, errorCallback);
|
||||
}
|
||||
|
||||
lbry.search = function(query, callback)
|
||||
{
|
||||
lbry.lighthouse.call('search', [query], callback);
|
||||
}
|
||||
|
||||
lbry.resolveName = function(name, callback) {
|
||||
lbry.call('resolve_name', { 'name': name }, callback, () => {
|
||||
// For now, assume any error means the name was not resolved
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
lbry.lighthouse = {
|
||||
_search_timeout: 5000,
|
||||
_max_search_tries: 5,
|
||||
|
||||
servers: [
|
||||
'http://lighthouse1.lbry.io:50005',
|
||||
'http://lighthouse2.lbry.io:50005',
|
||||
|
@ -6,9 +9,28 @@ lbry.lighthouse = {
|
|||
],
|
||||
path: '/',
|
||||
|
||||
call: function(method, params, callback, errorCallback, connectFailedCallback) {
|
||||
lbry.jsonrpc_call(this.server + this.path, method, params, callback, errorCallback, connectFailedCallback);
|
||||
call: function(method, params, callback, errorCallback, connectFailedCallback, timeout) {
|
||||
lbry.jsonrpc_call(this.server + this.path, method, params, callback, errorCallback, connectFailedCallback, timeout);
|
||||
},
|
||||
|
||||
search: function(query, callback) {
|
||||
let handleSearchFailed = function(tryNum=0) {
|
||||
if (tryNum > lbry.lighthouse._max_search_tries) {
|
||||
throw new Error(`Could not connect to Lighthouse server. Last server attempted: ${lbry.lighthouse.server}`);
|
||||
} else {
|
||||
// Randomly choose one of the other search servers to switch to
|
||||
let otherServers = lbry.lighthouse.servers.slice();
|
||||
otherServers.splice(otherServers.indexOf(lbry.lighthouse.server), 1);
|
||||
lbry.lighthouse.server = otherServers[Math.round(Math.random() * (otherServers.length - 1))];
|
||||
|
||||
lbry.lighthouse.call('search', [query], callback, undefined, function() {
|
||||
handleSearchFailed(tryNum + 1);
|
||||
}, lbry.lighthouse._search_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
lbry.lighthouse.call('search', [query], callback, undefined, function() { handleSearchFailed() }, lbry.lighthouse._search_timeout);
|
||||
}
|
||||
};
|
||||
|
||||
lbry.lighthouse.server = lbry.lighthouse.servers[Math.round(Math.random() * (lbry.lighthouse.servers.length - 1))];
|
||||
|
|
|
@ -14,6 +14,10 @@ var ClaimCodePage = React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
submitting: false,
|
||||
modal: null,
|
||||
referralCredits: null,
|
||||
activationCredits: null,
|
||||
failureReason: null,
|
||||
}
|
||||
},
|
||||
handleSubmit: function(event) {
|
||||
|
@ -22,15 +26,19 @@ var ClaimCodePage = React.createClass({
|
|||
}
|
||||
|
||||
if (!this.refs.code.value) {
|
||||
alert('Please enter an invitation code or choose "Skip."');
|
||||
this.setState({
|
||||
modal: 'missingCode',
|
||||
});
|
||||
return;
|
||||
} else if (!this.refs.email.value) {
|
||||
alert('Please enter an email address or choose "Skip."');
|
||||
this.setState({
|
||||
modal: 'missingEmail',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
submitting: true
|
||||
submitting: true,
|
||||
});
|
||||
|
||||
lbry.getNewAddress((address) => {
|
||||
|
@ -42,33 +50,25 @@ var ClaimCodePage = React.createClass({
|
|||
var response = JSON.parse(xhr.responseText);
|
||||
|
||||
if (response.success) {
|
||||
var redeemMessage = 'Your invite code has been redeemed. ';
|
||||
if (response.referralCredits > 0) {
|
||||
redeemMessage += 'You have also earned ' + response.referralCredits + ' credits from referrals. A total of ' +
|
||||
(response.activationCredits + response.referralCredits) + ' will be added to your balance shortly.';
|
||||
} else if(response.activationCredits > 0) {
|
||||
redeemMessage += response.activationCredits + ' credits will be added to your balance shortly.';
|
||||
} else {
|
||||
redeemMessage += 'The credits will be added to your balance shortly.';
|
||||
}
|
||||
alert(redeemMessage);
|
||||
localStorage.setItem('claimCodeDone', true);
|
||||
window.location = '?home';
|
||||
} else {
|
||||
alert(response.reason);
|
||||
this.setState({
|
||||
submitting: false
|
||||
modal: 'codeRedeemed',
|
||||
referralCredits: response.referralCredits,
|
||||
activationCredits: response.activationCredits,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
submitting: false,
|
||||
modal: 'codeRedeemFailed',
|
||||
failureReason: response.reason,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('error', () => {
|
||||
this.setState({
|
||||
submitting: false
|
||||
submitting: false,
|
||||
modal: 'couldNotConnect',
|
||||
});
|
||||
alert('LBRY couldn\'t connect to our servers to confirm your invitation code. Please check your ' +
|
||||
'internet connection. If you continue to have problems, you can still browse LBRY and ' +
|
||||
'visit the Settings page to redeem your code later.');
|
||||
});
|
||||
|
||||
xhr.open('POST', 'https://invites.lbry.io', true);
|
||||
|
@ -78,10 +78,19 @@ var ClaimCodePage = React.createClass({
|
|||
});
|
||||
},
|
||||
handleSkip: function() {
|
||||
alert('Welcome to LBRY! You can visit the Wallet page to redeem an invite code at any time.');
|
||||
this.setState({
|
||||
modal: 'skipped',
|
||||
});
|
||||
},
|
||||
handleFinished: function() {
|
||||
localStorage.setItem('claimCodeDone', true);
|
||||
window.location = '?home';
|
||||
},
|
||||
closeModal: function() {
|
||||
this.setState({
|
||||
modal: null,
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<main>
|
||||
|
@ -105,6 +114,31 @@ var ClaimCodePage = React.createClass({
|
|||
</section>
|
||||
</div>
|
||||
</form>
|
||||
<Modal isOpen={this.state.modal == 'missingCode'} onConfirmed={this.closeModal}>
|
||||
Please enter an invitation code or choose "Skip."
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'missingEmail'} onConfirmed={this.closeModal}>
|
||||
Please enter an email address or choose "Skip."
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'codeRedeemFailed'} onConfirmed={this.closeModal}>
|
||||
{this.state.failureReason}
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'codeRedeemed'} onConfirmed={this.handleFinished}>
|
||||
Your invite code has been redeemed.
|
||||
{this.state.referralCredits > 0
|
||||
? `You have also earned {referralCredits} credits from referrals. A total of {activationCredits + referralCredits}
|
||||
will be added to your balance shortly.`
|
||||
: (this.state.activationCredits > 0
|
||||
? `{this.state.activationCredits} credits will be added to your balance shortly.`
|
||||
: 'The credits will be added to your balance shortly.')}
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'skipped'} onConfirmed={this.handleFinished}>
|
||||
Welcome to LBRY! You can visit the Wallet page to redeem an invite code at any time.
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'couldNotConnect'} onConfirmed={this.closeModal}>
|
||||
<p>LBRY couldn't connect to our servers to confirm your invitation code. Please check your internet connection.</p>
|
||||
If you continue to have problems, you can still browse LBRY and visit the Settings page to redeem your code later.
|
||||
</Modal>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ var SearchResultRow = React.createClass({
|
|||
<section className={ 'card ' + (obscureNsfw ? 'card-obscured ' : '') + (this.props.compact ? 'card-compact' : '')} onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
|
||||
<div className="row-fluid card-content" style={style}>
|
||||
<div className="span3">
|
||||
<a href={'/?show=' + this.props.name}><img src={this.props.imgUrl || '/img/default-thumb.svg'} alt={'Photo for ' + (this.props.title || this.props.name)} style={searchRowImgStyle} /></a>
|
||||
<a href={'/?show=' + this.props.name}><Thumbnail src={this.props.imgUrl} alt={'Photo for ' + (this.props.title || this.props.name)} style={searchRowImgStyle} /></a>
|
||||
</div>
|
||||
<div className="span9">
|
||||
<span style={searchRowCostStyle}>
|
||||
|
@ -179,7 +179,7 @@ var FeaturedContentItem = React.createClass({
|
|||
componentDidMount: function() {
|
||||
this.resolveSearch = true;
|
||||
|
||||
lbry.search(this.props.name, function(results) {
|
||||
lbry.lighthouse.search(this.props.name, function(results) {
|
||||
var result = results[0];
|
||||
var metadata = result.value;
|
||||
if (this.resolveSearch)
|
||||
|
@ -201,7 +201,7 @@ var FeaturedContentItem = React.createClass({
|
|||
}
|
||||
|
||||
return (<div style={featuredContentItemContainerStyle}>
|
||||
<SearchResultRow name={this.props.name} title={this.state.title} imgUrl={this.state.metadata.thumbnail || '/img/default-thumb.svg'}
|
||||
<SearchResultRow name={this.props.name} title={this.state.title} imgUrl={this.state.metadata.thumbnail}
|
||||
description={this.state.metadata.description} mediaType={lbry.getMediaType(this.state.metadata.content_type)}
|
||||
cost={this.state.amount} nsfw={this.state.metadata.nsfw} available={this.state.available} compact />
|
||||
</div>);
|
||||
|
@ -257,7 +257,7 @@ var DiscoverPage = React.createClass({
|
|||
query: this.props.query,
|
||||
});
|
||||
|
||||
lbry.search(this.props.query, this.searchCallback);
|
||||
lbry.lighthouse.search(this.props.query, this.searchCallback);
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
|
|
|
@ -5,31 +5,48 @@ var moreMenuStyle = {
|
|||
right: '13px',
|
||||
};
|
||||
var MyFilesRowMoreMenu = React.createClass({
|
||||
onRevealClicked: function() {
|
||||
propTypes: {
|
||||
title: React.PropTypes.string.isRequired,
|
||||
path: React.PropTypes.string.isRequired,
|
||||
completed: React.PropTypes.bool.isRequired,
|
||||
lbryUri: React.PropTypes.string.isRequired,
|
||||
},
|
||||
handleRevealClicked: function() {
|
||||
lbry.revealFile(this.props.path);
|
||||
},
|
||||
onRemoveClicked: function() {
|
||||
handleRemoveClicked: function() {
|
||||
lbry.deleteFile(this.props.lbryUri, false);
|
||||
},
|
||||
onDeleteClicked: function() {
|
||||
var alertText = 'Are you sure you\'d like to delete "' + this.props.title + '?" This will ' +
|
||||
(this.completed ? ' stop the download and ' : '') +
|
||||
'permanently remove the file from your system.';
|
||||
|
||||
if (confirm(alertText)) {
|
||||
lbry.deleteFile(this.props.lbryUri);
|
||||
}
|
||||
handleDeleteClicked: function() {
|
||||
this.setState({
|
||||
modal: 'confirmDelete',
|
||||
});
|
||||
},
|
||||
handleDeleteConfirmed: function() {
|
||||
lbry.deleteFile(this.props.lbryUri);
|
||||
lbry.setState({
|
||||
modal: null,
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
modal: null,
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div style={moreMenuStyle}>
|
||||
<Menu {...this.props}>
|
||||
<section className="card">
|
||||
<MenuItem onClick={this.onRevealClicked} label="Reveal file" /> {/* @TODO: Switch to OS specific wording */}
|
||||
<MenuItem onClick={this.onRemoveClicked} label="Remove from LBRY" />
|
||||
<MenuItem onClick={this.onDeleteClicked} label="Remove and delete file" />
|
||||
<MenuItem onClick={this.handleRevealClicked} label="Reveal file" /> {/* @TODO: Switch to OS specific wording */}
|
||||
<MenuItem onClick={this.handleRemoveClicked} label="Remove from LBRY" />
|
||||
<MenuItem onClick={this.handleDeleteClicked} label="Remove and delete file" />
|
||||
</section>
|
||||
</Menu>
|
||||
<Modal isOpen={this.state.modal == 'confirmDelete'} type="confirm" confirmButtonLabel="Delete File" onConfirmed={this.handleDeleteConfirmed}>
|
||||
Are you sure you'd like to delete <cite>{this.props.title}</cite>? This will {this.props.completed ? ' stop the download and ' : ''}
|
||||
permanently remove the file from your system.
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -98,7 +115,7 @@ var MyFilesRow = React.createClass({
|
|||
<section className="card">
|
||||
<div className="row-fluid">
|
||||
<div className="span3">
|
||||
<img src={this.props.imgUrl || '/img/default-thumb.svg'} alt={'Photo for ' + this.props.title} style={artStyle} />
|
||||
<Thumbnail src={this.props.imgUrl} alt={'Photo for ' + this.props.title} style={artStyle} />
|
||||
</div>
|
||||
<div className="span8">
|
||||
<h3>{this.props.pending ? this.props.title : <a href={'/?show=' + this.props.lbryUri}>{this.props.title}</a>}</h3>
|
||||
|
@ -123,8 +140,8 @@ var MyFilesRow = React.createClass({
|
|||
<div style={moreButtonContainerStyle}>
|
||||
<Link style={moreButtonStyle} ref="moreButton" icon="icon-ellipsis-h" title="More Options" />
|
||||
<MyFilesRowMoreMenu toggleButton={this.refs.moreButton} title={this.props.title}
|
||||
lbryUri={this.props.lbryUri} fileName={this.props.fileName}
|
||||
path={this.props.path}/>
|
||||
completed={this.props.completed} lbryUri={this.props.lbryUri}
|
||||
fileName={this.props.fileName} path={this.props.path}/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
@ -208,7 +225,11 @@ var MyFilesPage = React.createClass({
|
|||
for (let fileInfo of filesInfo) {
|
||||
let name = fileInfo.lbry_uri;
|
||||
|
||||
lbry.search(name, (results) => {
|
||||
if (name === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
lbry.lighthouse.search(name, (results) => {
|
||||
var result = results[0];
|
||||
|
||||
var available = result.name == name && result.available;
|
||||
|
|
|
@ -81,14 +81,8 @@ var PublishPage = React.createClass({
|
|||
console.log(publishArgs);
|
||||
lbry.publish(publishArgs, (message) => {
|
||||
this.handlePublishStarted();
|
||||
this.setState({
|
||||
submitting: false,
|
||||
});
|
||||
}, null, (error) => {
|
||||
this.handlePublishError(error);
|
||||
this.setState({
|
||||
submitting: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -125,18 +119,26 @@ var PublishPage = React.createClass({
|
|||
otherLicenseUrl: '',
|
||||
uploadProgress: 0.0,
|
||||
uploaded: false,
|
||||
errorMessage: null,
|
||||
tempFileReady: false,
|
||||
submitting: false,
|
||||
modal: null,
|
||||
};
|
||||
},
|
||||
handlePublishStarted: function() {
|
||||
alert(`Your file ${this.refs.meta_title.getValue()} has been published to LBRY at the address lbry://${this.state.name}!\n\n` +
|
||||
`You will now be taken to your My Files page, where your newly published file will be listed. Your file will take a few minutes to appear for other LBRY users; until then it will be listed as "pending."`);
|
||||
this.setState({
|
||||
modal: 'publishStarted',
|
||||
});
|
||||
},
|
||||
handlePublishStartedConfirmed: function() {
|
||||
window.location = "?published";
|
||||
},
|
||||
handlePublishError: function(error) {
|
||||
alert(`The following error occurred when attempting to publish your file:\n\n` +
|
||||
error.message);
|
||||
this.setState({
|
||||
submitting: false,
|
||||
modal: 'error',
|
||||
errorMessage: error.message,
|
||||
});
|
||||
},
|
||||
handleNameChange: function(event) {
|
||||
var rawName = event.target.value;
|
||||
|
@ -335,7 +337,7 @@ var PublishPage = React.createClass({
|
|||
(!this.state.name ? '' :
|
||||
(! this.state.nameResolved ? <em> The name <strong>{this.state.name}</strong> is available.</em>
|
||||
: (this.state.myClaimExists ? <em> You already have a claim on the name <strong>{this.state.name}</strong>. You can use this page to update your claim.</em>
|
||||
: <em> The name <strong>{this.state.name}</strong> is currently claimed for <strong>{lbry.formatCredits(this.state.topClaimValue)}</strong> credits.</em>)))
|
||||
: <em> The name <strong>{this.state.name}</strong> is currently claimed for <strong>{this.state.topClaimValue}</strong> {this.state.topClaimValue == 1 ? 'credit' : 'credits'}.</em>)))
|
||||
}
|
||||
<div className="help">What LBRY name would you like to claim for this file?</div>
|
||||
</div>
|
||||
|
@ -356,13 +358,13 @@ var PublishPage = React.createClass({
|
|||
<section className="card">
|
||||
<h4>Bid Amount</h4>
|
||||
<div className="form-row">
|
||||
Credits <FormField ref="bid" style={publishNumberStyle} type="text" onChange={this.handleBidChange} value={this.state.bid} placeholder={this.state.nameResolved ? lbry.formatCredits(this.state.topClaimValue + 10) : 100} />
|
||||
Credits <FormField ref="bid" style={publishNumberStyle} type="text" onChange={this.handleBidChange} value={this.state.bid} placeholder={this.state.nameResolved ? this.state.topClaimValue + 10 : 100} />
|
||||
<div className="help">How much would you like to bid for this name?
|
||||
{ !this.state.nameResolved ? <span> Since this name is not currently resolved, you may bid as low as you want, but higher bids help prevent others from claiming your name.</span>
|
||||
: (this.state.topClaimIsMine ? <span> You currently control this name with a bid of <strong>{lbry.formatCredits(this.state.myClaimValue)}</strong> credits.</span>
|
||||
: (this.state.myClaimExists ? <span> You have a non-winning bid on this name for <strong>{lbry.formatCredits(this.state.myClaimValue)}</strong> credits.
|
||||
To control this name, you'll need to increase your bid to at least <strong>{lbry.formatCredits(this.state.myClaimValue)}</strong> credits.</span>
|
||||
: <span> You must bid over <strong>{lbry.formatCredits(this.state.topClaimValue)}</strong> credits to claim this name.</span>)) }
|
||||
: (this.state.topClaimIsMine ? <span> You currently control this name with a bid of <strong>{this.state.myClaimValue}</strong> {this.state.myClaimValue == 1 ? 'credit' : 'credits'}.</span>
|
||||
: (this.state.myClaimExists ? <span> You have a non-winning bid on this name for <strong>{this.state.myClaimValue}</strong> {this.state.myClaimValue == 1 ? 'credit' : 'credits'}.
|
||||
To control this name, you'll need to increase your bid to more than <strong>{this.state.topClaimValue}</strong> {this.state.topClaimValue == 1 ? 'credit' : 'credits'}.</span>
|
||||
: <span> You must bid over <strong>{this.state.topClaimValue}</strong> {this.state.topClaimValue == 1 ? 'credit' : 'credits'} to claim this name.</span>)) }
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -463,6 +465,14 @@ var PublishPage = React.createClass({
|
|||
<input type='submit' className='hidden' />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<Modal isOpen={this.state.modal == 'publishStarted'} onConfirmed={this.handlePublishStartedConfirmed}>
|
||||
<p>Your file has been published to LBRY at the address <code>lbry://{this.state.name}</code>!</p>
|
||||
You will now be taken to your My Files page, where your newly published file will be listed. The file will take a few minutes to appear for other LBRY users; until then it will be listed as "pending."
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'error'} onConfirmed={this.closeModal}>
|
||||
The following error occurred when attempting to publish your file: {this.state.errorMessage}
|
||||
</Modal>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@ var ReferralPage = React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
submitting: false,
|
||||
modal: null,
|
||||
referralCredits: null,
|
||||
failureReason: null,
|
||||
}
|
||||
},
|
||||
handleSubmit: function(event) {
|
||||
|
@ -22,15 +25,17 @@ var ReferralPage = React.createClass({
|
|||
}
|
||||
|
||||
if (!this.refs.code.value) {
|
||||
alert('Please enter a referral code.');
|
||||
return;
|
||||
this.setState({
|
||||
modal: 'missingCode',
|
||||
});
|
||||
} else if (!this.refs.email.value) {
|
||||
alert('Please enter an email address.');
|
||||
return;
|
||||
this.setState({
|
||||
modal: 'missingEmail',
|
||||
});
|
||||
}
|
||||
|
||||
this.setState({
|
||||
submitting: true
|
||||
submitting: true,
|
||||
});
|
||||
|
||||
lbry.getNewAddress((address) => {
|
||||
|
@ -42,29 +47,24 @@ var ReferralPage = React.createClass({
|
|||
var response = JSON.parse(xhr.responseText);
|
||||
|
||||
if (response.success) {
|
||||
if (response.referralCredits > 0) {
|
||||
alert('You have earned ' + response.referralCredits + ' credits from referrals. ' +
|
||||
'We will credit your account shortly. Thanks!');
|
||||
} else {
|
||||
alert('You have not earned any new referral credits since the last time you checked. ' +
|
||||
'Please check back in a week or two.');
|
||||
}
|
||||
|
||||
window.location = '?home';
|
||||
} else {
|
||||
alert(response.reason);
|
||||
this.setState({
|
||||
submitting: false
|
||||
modal: 'referralInfo',
|
||||
referralCredits: response.referralCredits,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
submitting: false,
|
||||
modal: 'lookupFailed',
|
||||
failureReason: response.reason,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('error', () => {
|
||||
this.setState({
|
||||
submitting: false
|
||||
submitting: false,
|
||||
modal: 'couldNotConnect',
|
||||
});
|
||||
alert('LBRY couldn\'t connect to our servers to confirm your referral code. Please check your ' +
|
||||
'internet connection.');
|
||||
});
|
||||
|
||||
xhr.open('POST', 'https://invites.lbry.io/check', true);
|
||||
|
@ -73,6 +73,15 @@ var ReferralPage = React.createClass({
|
|||
'&email=' + encodeURIComponent(email));
|
||||
});
|
||||
},
|
||||
closeModal: function() {
|
||||
this.setState({
|
||||
modal: null,
|
||||
});
|
||||
},
|
||||
handleFinished: function() {
|
||||
localStorage.setItem('claimCodeDone', true);
|
||||
window.location = '?home';
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<main>
|
||||
|
@ -94,6 +103,17 @@ var ReferralPage = React.createClass({
|
|||
</section>
|
||||
</div>
|
||||
</form>
|
||||
<Modal isOpen={this.state.modal == 'referralInfo'} onConfirmed={this.handleFinished}>
|
||||
{this.state.referralCredits > 0
|
||||
? `You have earned {response.referralCredits} credits from referrals. We will credit your account shortly. Thanks!`
|
||||
: 'You have not earned any new referral credits since the last time you checked. Please check back in a week or two.'}
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'lookupFailed'} onConfirmed={this.closeModal}>
|
||||
{this.state.failureReason}
|
||||
</Modal>
|
||||
<Modal isOpen={this.state.modal == 'couldNotConnect'} onConfirmed={this.closeModal}>
|
||||
LBRY couldn't connect to our servers to confirm your referral code. Please check your internet connection.
|
||||
</Modal>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@ var ReportPage = React.createClass({
|
|||
});
|
||||
lbry.reportBug(this._messageArea.value, () => {
|
||||
this.setState({
|
||||
submitting: false
|
||||
submitting: false,
|
||||
modal: 'submitted',
|
||||
});
|
||||
alert("Your bug report has been submitted! Thank you for your feedback.");
|
||||
});
|
||||
this._messageArea.value = '';
|
||||
}
|
||||
|
@ -16,9 +16,15 @@ var ReportPage = React.createClass({
|
|||
componentDidMount: function() {
|
||||
document.title = "Report an Issue";
|
||||
},
|
||||
closeModal: function() {
|
||||
this.setState({
|
||||
modal: null,
|
||||
})
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
submitting: false,
|
||||
modal: null,
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
|
@ -38,6 +44,9 @@ var ReportPage = React.createClass({
|
|||
<h3>Developer?</h3>
|
||||
You can also <Link href="https://github.com/lbryio/lbry/issues" label="submit an issue on GitHub"/>.
|
||||
</section>
|
||||
<Modal isOpen={this.state.modal == 'submitted'} onConfirmed={this.closeModal}>
|
||||
Your bug report has been submitted! Thank you for your feedback.
|
||||
</Modal>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ var FormatItem = React.createClass({
|
|||
return (
|
||||
<div className="row-fluid">
|
||||
<div className="span4">
|
||||
<img src={thumbnail || '/img/default-thumb.svg'} alt={'Photo for ' + title} style={formatItemImgStyle} />
|
||||
<Thumbnail src={thumbnail} alt={'Photo for ' + title} style={formatItemImgStyle} />
|
||||
</div>
|
||||
<div className="span8">
|
||||
<p>{description}</p>
|
||||
|
@ -117,7 +117,7 @@ var DetailPage = React.createClass({
|
|||
componentWillMount: function() {
|
||||
document.title = 'lbry://' + this.props.name;
|
||||
|
||||
lbry.search(this.props.name, (results) => {
|
||||
lbry.lighthouse.search(this.props.name, (results) => {
|
||||
var result = results[0];
|
||||
|
||||
if (result.name != this.props.name) {
|
||||
|
|
|
@ -17,6 +17,7 @@ var AddressSection = React.createClass({
|
|||
getInitialState: function() {
|
||||
return {
|
||||
address: null,
|
||||
modal: null,
|
||||
}
|
||||
},
|
||||
componentWillMount: function() {
|
||||
|
@ -58,7 +59,9 @@ var SendToAddressSection = React.createClass({
|
|||
|
||||
if ((this.state.balance - this.state.amount) < 1)
|
||||
{
|
||||
alert("Insufficient balance: after this transaction you would have less than 1 LBC in your wallet.")
|
||||
this.setState({
|
||||
modal: 'insufficientBalance',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -85,6 +88,11 @@ var SendToAddressSection = React.createClass({
|
|||
})
|
||||
});
|
||||
},
|
||||
closeModal: function() {
|
||||
this.setState({
|
||||
modal: null,
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {
|
||||
address: "",
|
||||
|
@ -136,6 +144,9 @@ var SendToAddressSection = React.createClass({
|
|||
: ''
|
||||
}
|
||||
</form>
|
||||
<Modal isOpen={this.state.modal === 'insufficientBalance'} onConfirmed={this.closeModal}>
|
||||
Insufficient balance: after this transaction you would have less than 1 LBC in your wallet.
|
||||
</Modal>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
@ -168,7 +179,7 @@ var TransactionList = React.createClass({
|
|||
{
|
||||
transactionItems.push({
|
||||
id: txid,
|
||||
date: new Date(parseInt(tx["timestamp"]) * 1000),
|
||||
date: tx["timestamp"] ? (new Date(parseInt(tx["timestamp"]) * 1000)) : null,
|
||||
amount: condensedTransactions[txid]
|
||||
});
|
||||
delete condensedTransactions[txid];
|
||||
|
@ -187,8 +198,8 @@ var TransactionList = React.createClass({
|
|||
rows.push(
|
||||
<tr key={item.id}>
|
||||
<td>{ (item.amount > 0 ? '+' : '' ) + item.amount }</td>
|
||||
<td>{ item.date.toLocaleDateString() }</td>
|
||||
<td>{ item.date.toLocaleTimeString() }</td>
|
||||
<td>{ item.date ? item.date.toLocaleDateString() : <span className="empty">(Transaction pending)</span> }</td>
|
||||
<td>{ item.date ? item.date.toLocaleTimeString() : <span className="empty">(Transaction pending)</span> }</td>
|
||||
<td>
|
||||
<a className="button-text" href={"https://explorer.lbry.io/tx/"+item.id} target="_blank">{item.id.substr(0, 7)}</a>
|
||||
</td>
|
||||
|
|
|
@ -78,6 +78,11 @@ label {
|
|||
display: block;
|
||||
}
|
||||
|
||||
code {
|
||||
font: 0.8em Consolas, 'Lucida Console', 'Source Sans', monospace;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
p
|
||||
{
|
||||
margin-bottom: 0.8em;
|
||||
|
@ -132,6 +137,13 @@ input[type="text"], input[type="search"]
|
|||
}
|
||||
}
|
||||
|
||||
.button-container {
|
||||
+ .button-container
|
||||
{
|
||||
margin-left: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.button-block
|
||||
{
|
||||
cursor: pointer;
|
||||
|
@ -143,10 +155,6 @@ input[type="text"], input[type="search"]
|
|||
text-align: center;
|
||||
border-radius: 2px;
|
||||
text-transform: uppercase;
|
||||
+ .button-block
|
||||
{
|
||||
margin-left: 12px;
|
||||
}
|
||||
.icon
|
||||
{
|
||||
top: 0em;
|
||||
|
@ -225,3 +233,73 @@ input[type="text"], input[type="search"]
|
|||
margin-top: $spacing-vertical;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
background-color: rgba(255, 255, 255, 0.74902);
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
background: rgb(255, 255, 255);
|
||||
overflow: auto;
|
||||
border-radius: 4px;
|
||||
outline: none;
|
||||
padding: 36px;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
.modal__header {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.modal__buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.modal__button {
|
||||
margin: 0px 6px;
|
||||
}
|
||||
|
||||
.error-modal__error-list {
|
||||
border: 1px solid #eee;
|
||||
padding: 8px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.error-modal-overlay {
|
||||
background: rgba(#000, .88);
|
||||
}
|
||||
|
||||
.error-modal {
|
||||
max-width: none;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.error-modal__content {
|
||||
display: flex;
|
||||
padding: 0px 8px 10px 10px;
|
||||
}
|
||||
|
||||
.error-modal__warning-symbol {
|
||||
margin-top: 6px;
|
||||
margin-right: 7px;
|
||||
}
|
Loading…
Reference in a new issue