Merge pull request #175 from lbryio/revert-174-merge-development-electron
Revert "Merge updates from development into Electron branch"
This commit is contained in:
commit
c5da3de3c1
20 changed files with 140 additions and 347 deletions
|
@ -1,23 +1,5 @@
|
||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 0.9.0rc6
|
current_version = 0.1.1
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>[a-z]+)(?P<candidate>\d+))?
|
|
||||||
serialize =
|
|
||||||
{major}.{minor}.{patch}{release}{candidate}
|
|
||||||
{major}.{minor}.{patch}
|
|
||||||
|
|
||||||
[bumpversion:file:package.json]
|
|
||||||
|
|
||||||
[bumpversion:part:release]
|
|
||||||
optional_value = production
|
|
||||||
values =
|
|
||||||
rc
|
|
||||||
production
|
|
||||||
|
|
||||||
[bumpversion:file:CHANGELOG.md]
|
|
||||||
search = [Unreleased]
|
|
||||||
replace = [Unreleased]
|
|
||||||
|
|
||||||
\#\# [{new_version}] - {now:%Y-%m-%d}
|
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,6 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
The format is based on [Keep a Changelog](http://keepachangelog.com/).
|
||||||
|
|
||||||
The LBRY Web UI comes bundled as part of [LBRY App](https://github.com/lbryio/lbry-app). Web UI version numbers track corresponding version of LBRY App.
|
The LBRY Web UI comes bundled as part of [LBRY App](https://github.com/lbryio/lbry-app). Web UI version numbers should always match the corresponding version of LBRY App.
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Changed
|
|
||||||
* Use local file for publishing
|
|
||||||
* Use local file and html5 for video playback
|
|
||||||
* Misc changes needed to make UI compatible with electron
|
|
||||||
|
|
37
dist/quit.html
vendored
37
dist/quit.html
vendored
|
@ -1,37 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<title>LBRY</title>
|
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Raleway:600,300' rel='stylesheet' type='text/css'>
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
|
||||||
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
|
||||||
<link href="./js/mediaelement/mediaelementplayer.css" rel="stylesheet" type="text/css" />
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-194x194.png" sizes="194x194">
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-96x96.png" sizes="96x96">
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/android-chrome-192x192.png" sizes="192x192">
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-16x16.png" sizes="16x16">
|
|
||||||
|
|
||||||
<meta name="msapplication-TileColor" content="#155B4A">
|
|
||||||
<meta name="msapplication-TileImage" content="/img/fav/mstile-144x144.png">
|
|
||||||
<meta name="theme-color" content="#155B4A">
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background-color: "#155b4a"
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<div id="canvas">
|
|
||||||
<div class="load-screen" style="color: white; min-height: 100vh; min-width: 100vw; display: flex; flex-direction: column; align-items: center; justify-content: center;">
|
|
||||||
<img src="./img/lbry-white-485x160.png" alt="LBRY">
|
|
||||||
<div style="margin-top: 24px; width: 325px; text-align: center;">
|
|
||||||
<h3>
|
|
||||||
<span>Shutting Down <span class="busy-indicator"></span>
|
|
||||||
</span>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</html>
|
|
37
dist/warning.html
vendored
37
dist/warning.html
vendored
|
@ -1,37 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<title>LBRY</title>
|
|
||||||
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Raleway:600,300' rel='stylesheet' type='text/css'>
|
|
||||||
<link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,400italic,600italic,600' rel='stylesheet' type='text/css'>
|
|
||||||
<link href="./css/all.css" rel="stylesheet" type="text/css" media="screen,print" />
|
|
||||||
<link href="./js/mediaelement/mediaelementplayer.css" rel="stylesheet" type="text/css" />
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-32x32.png" sizes="32x32">
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-194x194.png" sizes="194x194">
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-96x96.png" sizes="96x96">
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/android-chrome-192x192.png" sizes="192x192">
|
|
||||||
<link rel="icon" type="image/png" href="./img/fav/favicon-16x16.png" sizes="16x16">
|
|
||||||
|
|
||||||
<meta name="msapplication-TileColor" content="#155B4A">
|
|
||||||
<meta name="msapplication-TileImage" content="/img/fav/mstile-144x144.png">
|
|
||||||
<meta name="theme-color" content="#155B4A">
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background-color: "#155b4a"
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<div id="canvas">
|
|
||||||
<div class="load-screen" style="color: white; min-height: 100vh; min-width: 100vw; display: flex; flex-direction: column; align-items: center; justify-content: center;">
|
|
||||||
<img src="./img/lbry-white-485x160.png" alt="LBRY">
|
|
||||||
<div style="margin-top: 24px; width: 325px; text-align: center;">
|
|
||||||
<h3>
|
|
||||||
<span>The daemon has unexpectedly shutdown. Goodbye.
|
|
||||||
</span>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</html>
|
|
30
js/app.js
30
js/app.js
|
@ -1,6 +1,4 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Line} from 'rc-progress';
|
|
||||||
|
|
||||||
import lbry from './lbry.js';
|
import lbry from './lbry.js';
|
||||||
import SettingsPage from './page/settings.js';
|
import SettingsPage from './page/settings.js';
|
||||||
import HelpPage from './page/help.js';
|
import HelpPage from './page/help.js';
|
||||||
|
@ -21,11 +19,6 @@ import Header from './component/header.js';
|
||||||
import Modal from './component/modal.js';
|
import Modal from './component/modal.js';
|
||||||
import {Link} from './component/link.js';
|
import {Link} from './component/link.js';
|
||||||
|
|
||||||
|
|
||||||
const {remote, ipcRenderer} = require('electron');
|
|
||||||
const {download} = remote.require('electron-dl');
|
|
||||||
|
|
||||||
|
|
||||||
var App = React.createClass({
|
var App = React.createClass({
|
||||||
_error_key_labels: {
|
_error_key_labels: {
|
||||||
connectionString: 'API connection string',
|
connectionString: 'API connection string',
|
||||||
|
@ -52,7 +45,6 @@ var App = React.createClass({
|
||||||
modal: null,
|
modal: null,
|
||||||
updateUrl: null,
|
updateUrl: null,
|
||||||
isOldOSX: null,
|
isOldOSX: null,
|
||||||
downloadProgress: null,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
componentWillMount: function() {
|
componentWillMount: function() {
|
||||||
|
@ -78,9 +70,6 @@ var App = React.createClass({
|
||||||
} else if (versionInfo.os_system == 'Linux') {
|
} else if (versionInfo.os_system == 'Linux') {
|
||||||
var updateUrl = 'https://lbry.io/get/lbry.deb';
|
var updateUrl = 'https://lbry.io/get/lbry.deb';
|
||||||
} else if (versionInfo.os_system == 'Windows') {
|
} else if (versionInfo.os_system == 'Windows') {
|
||||||
// A little weird, but for electron, the installer is
|
|
||||||
// actually an exe. Maybe a better url would
|
|
||||||
// be something like /get/windows ?
|
|
||||||
var updateUrl = 'https://lbry.io/get/lbry.msi';
|
var updateUrl = 'https://lbry.io/get/lbry.msi';
|
||||||
} else {
|
} else {
|
||||||
var updateUrl = 'https://lbry.io/get';
|
var updateUrl = 'https://lbry.io/get';
|
||||||
|
@ -108,18 +97,8 @@ var App = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleUpgradeClicked: function() {
|
handleUpgradeClicked: function() {
|
||||||
// TODO: create a callback for onProgress and have the UI
|
lbry.stop();
|
||||||
// show download progress
|
window.location = this.state.updateUrl;
|
||||||
// TODO: remove the saveAs popup. Thats just me being lazy and having
|
|
||||||
// some indication that the download is happening
|
|
||||||
// TODO: calling lbry.stop() ends up displaying the "daemon
|
|
||||||
// unexpectedly stopped" page. Have a better way of shutting down
|
|
||||||
let options = {
|
|
||||||
onProgress: (p) => this.setState({downloadProgress: Math.round(p * 100)}),
|
|
||||||
}
|
|
||||||
download(remote.getCurrentWindow(), this.state.updateUrl, options)
|
|
||||||
.then(dl => ipcRenderer.send('shutdown'));
|
|
||||||
this.setState({modal: 'downloading'});
|
|
||||||
},
|
},
|
||||||
handleSkipClicked: function() {
|
handleSkipClicked: function() {
|
||||||
sessionStorage.setItem('upgradeSkipped', true);
|
sessionStorage.setItem('upgradeSkipped', true);
|
||||||
|
@ -232,11 +211,6 @@ var App = React.createClass({
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
</Modal>
|
</Modal>
|
||||||
// TODO: have color refence css color-primary
|
|
||||||
<Modal isOpen={this.state.modal == 'downloading'} contentLabel="Downloading Update" type="custom">
|
|
||||||
Downloading Update: {this.state.downloadProgress}% Complete
|
|
||||||
<Line percent={this.state.downloadProgress} strokeWidth="4"/>
|
|
||||||
</Modal>
|
|
||||||
<Modal isOpen={this.state.modal == 'error'} contentLabel="Error" type="custom"
|
<Modal isOpen={this.state.modal == 'error'} contentLabel="Error" type="custom"
|
||||||
className="error-modal" overlayClassName="error-modal-overlay" >
|
className="error-modal" overlayClassName="error-modal-overlay" >
|
||||||
<h3 className="modal__header">Error</h3>
|
<h3 className="modal__header">Error</h3>
|
||||||
|
|
|
@ -98,7 +98,7 @@ export let Address = React.createClass({
|
||||||
});
|
});
|
||||||
|
|
||||||
export let Thumbnail = React.createClass({
|
export let Thumbnail = React.createClass({
|
||||||
_defaultImageUri: lbry.imagePath('default-thumb.svg'),
|
_defaultImageUri: '/img/default-thumb.svg',
|
||||||
_maxLoadTime: 10000,
|
_maxLoadTime: 10000,
|
||||||
_isMounted: false,
|
_isMounted: false,
|
||||||
|
|
||||||
|
|
|
@ -38,15 +38,15 @@ var Drawer = React.createClass({
|
||||||
<nav id="drawer">
|
<nav id="drawer">
|
||||||
<div id="drawer-handle">
|
<div id="drawer-handle">
|
||||||
<Link title="Close" onClick={this.props.onCloseDrawer} icon="icon-bars" className="close-drawer-link"/>
|
<Link title="Close" onClick={this.props.onCloseDrawer} icon="icon-bars" className="close-drawer-link"/>
|
||||||
<a href="/"><img src={lbry.imagePath("lbry-dark-1600x528.png")} style={drawerImageStyle}/></a>
|
<a href="/"><img src="./img/lbry-dark-1600x528.png" style={drawerImageStyle}/></a>
|
||||||
</div>
|
</div>
|
||||||
<DrawerItem href='index.html?discover' viewingPage={this.props.viewingPage} label="Discover" icon="icon-search" />
|
<DrawerItem href='/?discover' viewingPage={this.props.viewingPage} label="Discover" icon="icon-search" />
|
||||||
<DrawerItem href='index.html?publish' viewingPage={this.props.viewingPage} label="Publish" icon="icon-upload" />
|
<DrawerItem href='/?publish' viewingPage={this.props.viewingPage} label="Publish" icon="icon-upload" />
|
||||||
<DrawerItem href='index.html?downloaded' subPages={['published']} viewingPage={this.props.viewingPage} label="My Files" icon='icon-cloud-download' />
|
<DrawerItem href='/?downloaded' subPages={['published']} viewingPage={this.props.viewingPage} label="My Files" icon='icon-cloud-download' />
|
||||||
<DrawerItem href="index.html?wallet" subPages={['send', 'receive', 'claim', 'referral']} viewingPage={this.props.viewingPage} label="My Wallet" badge={lbry.formatCredits(this.state.balance) } icon="icon-bank" />
|
<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='index.html?settings' viewingPage={this.props.viewingPage} label="Settings" icon='icon-gear' />
|
<DrawerItem href='/?settings' viewingPage={this.props.viewingPage} label="Settings" icon='icon-gear' />
|
||||||
<DrawerItem href='index.html?help' viewingPage={this.props.viewingPage} label="Help" icon='icon-question-circle' />
|
<DrawerItem href='/?help' viewingPage={this.props.viewingPage} label="Help" icon='icon-question-circle' />
|
||||||
{isLinux ? <Link href="index.html?start" icon="icon-close" className="close-lbry-link" /> : null}
|
{isLinux ? <Link href="/?start" icon="icon-close" className="close-lbry-link" /> : null}
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,15 +121,15 @@ export let FileTileStream = React.createClass({
|
||||||
<section className={ 'file-tile card ' + (obscureNsfw ? 'card-obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
|
<section className={ 'file-tile card ' + (obscureNsfw ? 'card-obscured ' : '') } onMouseEnter={this.handleMouseOver} onMouseLeave={this.handleMouseOut}>
|
||||||
<div className={"row-fluid card-content file-tile__row"}>
|
<div className={"row-fluid card-content file-tile__row"}>
|
||||||
<div className="span3">
|
<div className="span3">
|
||||||
<a href={'/?show=' + this.props.name}><Thumbnail className="file-tile__thumbnail" src={metadata.thumbnail} alt={'Photo for ' + (title || this.props.name)} /></a>
|
<a href={'/?show=' + this.props.name}><Thumbnail className="file-tile__thumbnail" src={metadata.thumbnail} alt={`Photo for ${title}`} /></a>
|
||||||
</div>
|
</div>
|
||||||
<div className="span9">
|
<div className="span9">
|
||||||
{ !this.props.hidePrice
|
{ !this.props.hidePrice
|
||||||
? <FilePrice name={this.props.name} />
|
? <FilePrice name={this.props.name} />
|
||||||
: null}
|
: null}
|
||||||
<div className="meta"><a href={'index.html?show=' + this.props.name}>{'lbry://' + this.props.name}</a></div>
|
<div className="meta"><a href={'/?show=' + this.props.name}>{'lbry://' + this.props.name}</a></div>
|
||||||
<h3 className="file-tile__title">
|
<h3 className="file-tile__title">
|
||||||
<a href={'index.html?show=' + this.props.name}>
|
<a href={'/?show=' + this.props.name}>
|
||||||
<TruncatedText lines={1}>
|
<TruncatedText lines={1}>
|
||||||
{title}
|
{title}
|
||||||
</TruncatedText>
|
</TruncatedText>
|
||||||
|
|
|
@ -56,9 +56,6 @@ var FormField = React.createClass({
|
||||||
getValue: function() {
|
getValue: function() {
|
||||||
if (this.props.type == 'checkbox') {
|
if (this.props.type == 'checkbox') {
|
||||||
return this.refs.field.checked;
|
return this.refs.field.checked;
|
||||||
}
|
|
||||||
else if (this.props.type == 'file') {
|
|
||||||
return this.refs.field.files[0].path;
|
|
||||||
} else {
|
} else {
|
||||||
return this.refs.field.value;
|
return this.refs.field.value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ var SplashScreen = React.createClass({
|
||||||
});
|
});
|
||||||
|
|
||||||
lbry.resolveName('one', () => {
|
lbry.resolveName('one', () => {
|
||||||
window.sessionStorage.setItem('loaded', 'y')
|
|
||||||
this.props.onLoadDone();
|
this.props.onLoadDone();
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -13,9 +13,7 @@ var init = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var canvas = document.getElementById('canvas');
|
var canvas = document.getElementById('canvas');
|
||||||
if (window.sessionStorage.getItem('loaded') == 'y') {
|
|
||||||
ReactDOM.render(<App/>, canvas)
|
|
||||||
} else {
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<SplashScreen message="Connecting" onLoadDone={function() {
|
<SplashScreen message="Connecting" onLoadDone={function() {
|
||||||
// Redirect to the claim code page if needed. Find somewhere better for this logic
|
// Redirect to the claim code page if needed. Find somewhere better for this logic
|
||||||
|
@ -33,7 +31,6 @@ var init = function() {
|
||||||
}}/>,
|
}}/>,
|
||||||
canvas
|
canvas
|
||||||
);
|
);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
|
@ -45,7 +45,14 @@ var PublishPage = React.createClass({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missingFieldFound) {
|
let fileProcessing = false;
|
||||||
|
if (this.state.fileInfo && !this.state.tempFileReady) {
|
||||||
|
this.refs.file.showAdvice('Your file is still processing.');
|
||||||
|
this.refs.file.focus();
|
||||||
|
fileProcessing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missingFieldFound || fileProcessing) {
|
||||||
this.setState({
|
this.setState({
|
||||||
submitting: false,
|
submitting: false,
|
||||||
});
|
});
|
||||||
|
@ -82,7 +89,7 @@ var PublishPage = React.createClass({
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.refs.file.getValue() !== '') {
|
if (this.refs.file.getValue() !== '') {
|
||||||
publishArgs.file_path = this.refs.file.getValue();
|
publishArgs.file_path = this._tempFilePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
lbry.publish(publishArgs, (message) => {
|
lbry.publish(publishArgs, (message) => {
|
||||||
|
@ -107,6 +114,8 @@ var PublishPage = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
this._tempFilePath = null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
rawName: '',
|
rawName: '',
|
||||||
name: '',
|
name: '',
|
||||||
|
@ -118,12 +127,14 @@ var PublishPage = React.createClass({
|
||||||
myClaimValue: 0.0,
|
myClaimValue: 0.0,
|
||||||
myClaimMetadata: null,
|
myClaimMetadata: null,
|
||||||
myClaimExists: null,
|
myClaimExists: null,
|
||||||
|
fileInfo: null,
|
||||||
copyrightNotice: '',
|
copyrightNotice: '',
|
||||||
otherLicenseDescription: '',
|
otherLicenseDescription: '',
|
||||||
otherLicenseUrl: '',
|
otherLicenseUrl: '',
|
||||||
uploadProgress: 0.0,
|
uploadProgress: 0.0,
|
||||||
uploaded: false,
|
uploaded: false,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
|
tempFileReady: false,
|
||||||
submitting: false,
|
submitting: false,
|
||||||
modal: null,
|
modal: null,
|
||||||
};
|
};
|
||||||
|
@ -225,6 +236,56 @@ var PublishPage = React.createClass({
|
||||||
feeCurrency: event.target.value,
|
feeCurrency: event.target.value,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
handleFileChange: function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
var fileInput = event.target;
|
||||||
|
|
||||||
|
this._tempFilePath = null;
|
||||||
|
if (fileInput.files.length == 0) {
|
||||||
|
// File was removed
|
||||||
|
this.setState({
|
||||||
|
fileInfo: null,
|
||||||
|
uploadProgress: 0.0,
|
||||||
|
uploaded: false,
|
||||||
|
tempFileReady: false,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var file = fileInput.files[0];
|
||||||
|
this.setState({
|
||||||
|
fileInfo: {
|
||||||
|
name: file.name,
|
||||||
|
size: file.size,
|
||||||
|
},
|
||||||
|
uploadProgress: 0.0,
|
||||||
|
uploaded: false,
|
||||||
|
tempFileReady: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.upload.addEventListener('progress', (event) => {
|
||||||
|
this.setState({
|
||||||
|
uploadProgress: (event.loaded / event.total),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
xhr.upload.addEventListener('load', (event) => {
|
||||||
|
this.setState({
|
||||||
|
uploaded: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
xhr.addEventListener('load', (event) => {
|
||||||
|
this._tempFilePath = JSON.parse(xhr.responseText);
|
||||||
|
this.setState({
|
||||||
|
tempFileReady: true,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
var formData = new FormData(fileInput.form);
|
||||||
|
formData.append('file', fileInput.files[0]);
|
||||||
|
xhr.open('POST', lbry.webUiUri + '/upload', true);
|
||||||
|
xhr.send(formData);
|
||||||
|
}
|
||||||
|
},
|
||||||
handleFeePrefChange: function(feeEnabled) {
|
handleFeePrefChange: function(feeEnabled) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isFee: feeEnabled
|
isFee: feeEnabled
|
||||||
|
@ -272,6 +333,21 @@ var PublishPage = React.createClass({
|
||||||
document.title = "Publish";
|
document.title = "Publish";
|
||||||
},
|
},
|
||||||
componentDidUpdate: function() {
|
componentDidUpdate: function() {
|
||||||
|
if (this.state.fileInfo && !this.state.tempFileReady) {
|
||||||
|
// A file was chosen but the daemon hasn't finished processing it yet, i.e. it's loading, so
|
||||||
|
// we're displaying a progress bar and need a value for it.
|
||||||
|
|
||||||
|
// React can't unset the "value" prop (to show an "indeterminate" bar) after it's already
|
||||||
|
// been set, so we have to manage it manually.
|
||||||
|
|
||||||
|
if (!this.state.uploaded) {
|
||||||
|
// Still uploading
|
||||||
|
this.refs.progress.setAttribute('value', this.state.uploadProgress);
|
||||||
|
} else {
|
||||||
|
// Fully uploaded and waiting for server to finish processing, so set progress bar to "indeterminite"
|
||||||
|
this.refs.progress.removeAttribute('value');
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// Also getting a type warning here too
|
// Also getting a type warning here too
|
||||||
render: function() {
|
render: function() {
|
||||||
|
@ -294,7 +370,13 @@ var PublishPage = React.createClass({
|
||||||
|
|
||||||
<section className="card">
|
<section className="card">
|
||||||
<h4>Choose File</h4>
|
<h4>Choose File</h4>
|
||||||
<FormField name="file" ref="file" type="file" />
|
<FormField name="file" ref="file" type="file" onChange={this.handleFileChange} />
|
||||||
|
{ !this.state.fileInfo ? '' :
|
||||||
|
(!this.state.tempFileReady ? <div>
|
||||||
|
<progress ref='progress'></progress>
|
||||||
|
{!this.state.uploaded ? <span> Importing file into LBRY...</span> : <span> Processing file...</span>}
|
||||||
|
</div>
|
||||||
|
: <div>File ready for publishing!</div>) }
|
||||||
{ this.state.myClaimExists ? <div className="help">If you don't choose a file, the file from your existing claim will be used.</div> : null }
|
{ this.state.myClaimExists ? <div className="help">If you don't choose a file, the file from your existing claim will be used.</div> : null }
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Icon} from '../component/common.js';
|
|
||||||
import {Link} from '../component/link.js';
|
|
||||||
import lbry from '../lbry.js';
|
import lbry from '../lbry.js';
|
||||||
import LoadScreen from '../component/load_screen.js'
|
import LoadScreen from '../component/load_screen.js'
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const VideoStream = require('videostream');
|
|
||||||
|
|
||||||
|
|
||||||
var WatchPage = React.createClass({
|
var WatchPage = React.createClass({
|
||||||
_isMounted: false,
|
|
||||||
_controlsHideDelay: 3000, // Note: this needs to be shorter than the built-in delay in Electron, or Electron will hide the controls before us
|
|
||||||
_controlsHideTimeout: null,
|
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
name: React.PropTypes.string,
|
name: React.PropTypes.string,
|
||||||
},
|
},
|
||||||
|
@ -22,55 +12,19 @@ var WatchPage = React.createClass({
|
||||||
readyToPlay: false,
|
readyToPlay: false,
|
||||||
loadStatusMessage: "Requesting stream",
|
loadStatusMessage: "Requesting stream",
|
||||||
mimeType: null,
|
mimeType: null,
|
||||||
controlsShown: false,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
lbry.getStream(this.props.name);
|
lbry.getStream(this.props.name);
|
||||||
this.updateLoadStatus();
|
this.updateLoadStatus();
|
||||||
},
|
},
|
||||||
handleBackClicked: function() {
|
|
||||||
history.back();
|
|
||||||
},
|
|
||||||
handleMouseMove: function() {
|
|
||||||
if (this._controlsTimeout) {
|
|
||||||
clearTimeout(this._controlsTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.state.controlsShown) {
|
|
||||||
this.setState({
|
|
||||||
controlsShown: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this._controlsTimeout = setTimeout(() => {
|
|
||||||
if (!this.isMounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
controlsShown: false,
|
|
||||||
});
|
|
||||||
}, this._controlsHideDelay);
|
|
||||||
},
|
|
||||||
handleMouseOut: function() {
|
|
||||||
if (this._controlsTimeout) {
|
|
||||||
clearTimeout(this._controlsTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.controlsShown) {
|
|
||||||
this.setState({
|
|
||||||
controlsShown: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateLoadStatus: function() {
|
updateLoadStatus: function() {
|
||||||
lbry.getFileStatus(this.props.name, (status) => {
|
lbry.getFileStatus(this.props.name, (status) => {
|
||||||
if (!status || !['running', 'stopped'].includes(status.code) || status.written_bytes == 0) {
|
if (!status || !['running', 'stopped'].includes(status.code) || status.written_bytes == 0) {
|
||||||
// Download hasn't started yet, so update status message (if available) then try again
|
// Download hasn't started yet, so update status message (if available) then try again
|
||||||
// TODO: Would be nice to check if we have the MOOV before starting playing
|
|
||||||
if (status) {
|
if (status) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loadStatusMessage: status.message,
|
loadStatusMessage: status.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setTimeout(() => { this.updateLoadStatus() }, 250);
|
setTimeout(() => { this.updateLoadStatus() }, 250);
|
||||||
|
@ -79,17 +33,11 @@ var WatchPage = React.createClass({
|
||||||
readyToPlay: true,
|
readyToPlay: true,
|
||||||
mimeType: status.mime_type,
|
mimeType: status.mime_type,
|
||||||
})
|
})
|
||||||
const mediaFile = {
|
var player = new MediaElementPlayer(this.refs.player, {
|
||||||
createReadStream: function (opts) {
|
mode: 'shim',
|
||||||
// Return a readable stream that provides the bytes
|
plugins: ['flash'],
|
||||||
// between offsets "start" and "end" inclusive
|
setDimensions: false,
|
||||||
console.log('Stream between ' + opts.start + ' and ' + opts.end + '.');
|
});
|
||||||
return fs.createReadStream(status.download_path, opts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var elem = this.refs.video;
|
|
||||||
var videostream = VideoStream(mediaFile, elem);
|
|
||||||
elem.play();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -97,22 +45,10 @@ var WatchPage = React.createClass({
|
||||||
return (
|
return (
|
||||||
!this.state.readyToPlay
|
!this.state.readyToPlay
|
||||||
? <LoadScreen message={'Loading video...'} details={this.state.loadStatusMessage} />
|
? <LoadScreen message={'Loading video...'} details={this.state.loadStatusMessage} />
|
||||||
: <main className="video full-screen" onMouseMove={this.handleMouseMove} onMouseOut={this.handleMouseOut}>
|
: <main className="full-screen">
|
||||||
<video width="100%" height="100%" id="video" ref="video" src={'/view?name=' + this.props.name}
|
<video ref="player" width="100%" height="100%">
|
||||||
controls={this.state.controlsShown}/>
|
<source type={(this.state.mimeType == 'audio/m4a' || this.state.mimeType == 'audio/mp4a-latm') ? 'video/mp4' : this.state.mimeType} src={lbry.webUiUri + '/view?name=' + this.props.name} />
|
||||||
{this.state.controlsShown
|
</video>
|
||||||
? <div className="video__overlay">
|
|
||||||
<div className="video__back">
|
|
||||||
<Link icon="icon-arrow-circle-o-left" className="video__back-link" onClick={this.handleBackClicked}/>
|
|
||||||
<div className="video__back-label">
|
|
||||||
<Icon icon="icon-caret-left" className="video__back-label-arrow" />
|
|
||||||
<div className="video__back-label-content">
|
|
||||||
Back to LBRY
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
: null}
|
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "lbry-web-ui",
|
"name": "lbry-web-ui",
|
||||||
"version": "0.9.0rc6",
|
"version": "1.0.0",
|
||||||
"description": "LBRY web ui",
|
"description": "LBRY web ui",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
@ -25,11 +25,9 @@
|
||||||
"clamp-js-main": "^0.11.1",
|
"clamp-js-main": "^0.11.1",
|
||||||
"mediaelement": "^2.23.4",
|
"mediaelement": "^2.23.4",
|
||||||
"node-sass": "^3.8.0",
|
"node-sass": "^3.8.0",
|
||||||
"rc-progress": "^2.0.6",
|
|
||||||
"react": "^15.4.0",
|
"react": "^15.4.0",
|
||||||
"react-dom": "^15.4.0",
|
"react-dom": "^15.4.0",
|
||||||
"react-modal": "^1.5.2",
|
"react-modal": "^1.5.2"
|
||||||
"videostream": "^2.4.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel": "^6.5.2",
|
"babel": "^6.5.2",
|
||||||
|
@ -47,7 +45,6 @@
|
||||||
"eslint-plugin-jsx-a11y": "^2.2.3",
|
"eslint-plugin-jsx-a11y": "^2.2.3",
|
||||||
"eslint-plugin-react": "^6.7.1",
|
"eslint-plugin-react": "^6.7.1",
|
||||||
"node-sass": "^3.13.0",
|
"node-sass": "^3.13.0",
|
||||||
"webpack": "^1.13.3",
|
"webpack": "^1.13.3"
|
||||||
"webpack-target-electron-renderer": "^0.4.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,4 +11,3 @@
|
||||||
@import "component/_tooltip.scss";
|
@import "component/_tooltip.scss";
|
||||||
@import "component/_load-screen.scss";
|
@import "component/_load-screen.scss";
|
||||||
@import "page/_developer.scss";
|
@import "page/_developer.scss";
|
||||||
@import "page/_watch.scss";
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
.load-screen {
|
.load-screen {
|
||||||
color: white;
|
color: white;
|
||||||
|
background-image: url("/img/lbry-bg.png");
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
min-width: 100vw;
|
min-width: 100vw;
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
.video {
|
|
||||||
background: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video__overlay {
|
|
||||||
position: absolute;
|
|
||||||
top: 0px;
|
|
||||||
left: 0px;
|
|
||||||
color: #fff;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video__back {
|
|
||||||
margin-top: 30px;
|
|
||||||
margin-left: 50px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video__back-link {
|
|
||||||
font-size: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video__back-label {
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 100ms ease-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video__back-link:hover + .video__back-label {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
$video-back-background: #333;
|
|
||||||
$video-back-size: 20px;
|
|
||||||
|
|
||||||
.video__back-label-arrow {
|
|
||||||
color: $video-back-background;
|
|
||||||
font-size: $video-back-size;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video__back-label-content {
|
|
||||||
display: inline-block;
|
|
||||||
margin-left: -2px;
|
|
||||||
font-size: $video-back-size;
|
|
||||||
padding: $spacing-vertical / 2;
|
|
||||||
border-radius: 3px;
|
|
||||||
background-color: $video-back-background;
|
|
||||||
color: #fff;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
6
watch.sh
6
watch.sh
|
@ -16,7 +16,7 @@ if [ ! -d "$DIR/node_modules" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# run sass once without --watch to force update. then run with --watch to keep watching
|
# run sass once without --watch to force update. then run with --watch to keep watching
|
||||||
$DIR/node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none $DIR/scss/
|
$DIR/node_modules/.bin/node-sass --output $DIR/dist/css --sourcemap=none $DIR/scss/
|
||||||
$DIR/node_modules/.bin/node-sass --output $DIR/../app/dist/css --sourcemap=none --watch $DIR/scss/ &
|
$DIR/node_modules/.bin/node-sass --output $DIR/dist/css --sourcemap=none --watch $DIR/scss/ &
|
||||||
|
|
||||||
node_modules/.bin/webpack --config webpack.dev.config.js --progress --colors --watch
|
node_modules/.bin/webpack --progress --colors --watch
|
||||||
|
|
|
@ -33,6 +33,5 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
target: 'electron-main',
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const PATHS = {
|
|
||||||
app: path.join(__dirname, 'app'),
|
|
||||||
dist: path.join(__dirname, '..', 'app', 'dist')
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
entry: ['babel-polyfill', './js/main.js'],
|
|
||||||
output: {
|
|
||||||
path: path.join(PATHS.dist, 'js'),
|
|
||||||
publicPath: '/js/',
|
|
||||||
filename: "bundle.js",
|
|
||||||
pathinfo: true
|
|
||||||
},
|
|
||||||
debug: true,
|
|
||||||
cache: true,
|
|
||||||
devtool: 'eval',
|
|
||||||
module: {
|
|
||||||
preLoaders: [
|
|
||||||
{
|
|
||||||
test: /\.jsx?$/,
|
|
||||||
loaders: ['eslint'],
|
|
||||||
// define an include so we check just the files we need
|
|
||||||
include: PATHS.app
|
|
||||||
}
|
|
||||||
],
|
|
||||||
loaders: [
|
|
||||||
{ test: /\.css$/, loader: "style!css" },
|
|
||||||
{
|
|
||||||
test: /\.jsx?$/,
|
|
||||||
loader: 'babel',
|
|
||||||
query: {
|
|
||||||
cacheDirectory: true,
|
|
||||||
presets:[ 'es2015', 'react', 'stage-2' ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
target: 'electron-main',
|
|
||||||
};
|
|
Loading…
Reference in a new issue