still not quite releasable, but much progress

This commit is contained in:
Jeremy Kauffman 2017-04-30 23:38:14 -04:00
parent da538a7a23
commit 5b11c2575a
5 changed files with 167 additions and 50 deletions

View file

@ -145,12 +145,22 @@ var App = React.createClass({
},
onSearch: function(term) {
this._storeHistoryOfNextRender = true;
const isShow = term.startsWith('lbry://');
this.setState({
viewingPage: "search",
appUrl: "?search=" + encodeURIComponent(term),
viewingPage: isShow ? "show" : "search",
appUrl: (isShow ? "?show=" : "?search=") + encodeURIComponent(term),
pageArgs: term
});
},
onSubmit: function(uri) {
this._storeHistoryOfNextRender = true;
this.setState({
address: uri,
appUrl: "?show=" + encodeURIComponent(uri),
viewingPage: "show",
pageArgs: uri
})
},
handleUpgradeClicked: function() {
// Make a new directory within temp directory so the filename is guaranteed to be available
const dir = fs.mkdtempSync(app.getPath('temp') + require('path').sep);
@ -265,7 +275,7 @@ var App = React.createClass({
this._fullScreenPages.includes(this.state.viewingPage) ?
mainContent :
<div id="window">
<Header onSearch={this.onSearch} address={address} wunderBarIcon={wunderBarIcon} viewingPage={this.state.viewingPage} />
<Header onSearch={this.onSearch} onSubmit={this.onSubmit} address={address} wunderBarIcon={wunderBarIcon} viewingPage={this.state.viewingPage} />
<div id="main-content">
{mainContent}
</div>

View file

@ -97,9 +97,6 @@ export let FileTileStream = React.createClass({
</a>
</h3>
</div>
<div className="card__actions">
<FileActions uri={this.props.uri} outpoint={this.props.outpoint} metadata={metadata} contentType={this.props.contentType} />
</div>
<div className="card__content">
<p className="file-tile__description">
<TruncatedText lines={2}>
@ -238,13 +235,10 @@ export let FileTile = React.createClass({
claimInfo: null
}
},
componentDidMount: function() {
this._isMounted = true;
lbry.resolve({uri: this.props.uri}).then((resolutionInfo) => {
resolve: function(uri) {
lbry.resolve({uri: uri}).then((resolutionInfo) => {
if (this._isMounted && resolutionInfo && resolutionInfo.claim && resolutionInfo.claim.value &&
resolutionInfo.claim.value.stream && resolutionInfo.claim.value.stream.metadata) {
resolutionInfo.claim.value.stream && resolutionInfo.claim.value.stream.metadata) {
// In case of a failed lookup, metadata will be null, in which case the component will never display
this.setState({
claimInfo: resolutionInfo.claim,
@ -252,6 +246,16 @@ export let FileTile = React.createClass({
}
});
},
componentWillReceiveProps: function(nextProps) {
if (nextProps.uri != this.props.uri) {
this.setState(this.getInitialState());
this.resolve(nextProps.uri);
}
},
componentDidMount: function() {
this._isMounted = true;
this.resolve(this.props.uri);
},
componentWillUnmount: function() {
this._isMounted = false;
},
@ -261,6 +265,10 @@ export let FileTile = React.createClass({
return <FileCardStream outpoint={null} metadata={{title: this.props.uri, description: "Loading..."}} contentType={null} hidePrice={true}
hasSignature={false} signatureIsValid={false} uri={this.props.uri} />
}
if (this.props.showEmpty)
{
return <div className="empty">Empty file tile for {this.props.uri}</div>
}
return null;
}

View file

@ -1,4 +1,5 @@
import React from 'react';
import lbryuri from '../lbryuri.js';
import {Link} from './link.js';
import {Icon, CreditAmount} from './common.js';
@ -6,6 +7,11 @@ var Header = React.createClass({
_balanceSubscribeId: null,
_isMounted: false,
propTypes: {
onSearch: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired
},
getInitialState: function() {
return {
balance: 0
@ -35,7 +41,7 @@ var Header = React.createClass({
</div>
<div className="header__item header__item--wunderbar">
<WunderBar address={this.props.address} icon={this.props.wunderBarIcon}
onSearch={this.props.onSearch} viewingPage={this.props.viewingPage} />
onSearch={this.props.onSearch} onSubmit={this.props.onSubmit} viewingPage={this.props.viewingPage} />
</div>
<div className="header__item">
<Link href="?wallet" button="text" icon="icon-bank" label={lbry.formatCredits(this.state.balance, 1)} ></Link>
@ -57,9 +63,11 @@ let WunderBar = React.createClass({
_userTypingTimer: null,
_input: null,
_stateBeforeSearch: null,
_resetOnNextBlur: true,
propTypes: {
onSearch: React.PropTypes.func.isRequired
onSearch: React.PropTypes.func.isRequired,
onSubmit: React.PropTypes.func.isRequired
},
getInitialState: function() {
@ -85,11 +93,12 @@ let WunderBar = React.createClass({
let searchTerm = event.target.value;
this._userTypingTimer = setTimeout(() => {
this._resetOnNextBlur = false;
this.props.onSearch(searchTerm);
}, 800); // 800ms delay, tweak for faster/slower
},
componentWillReceiveProps(nextProps) {
if (nextProps.viewingPage !== this.props.viewingPage) {
if (nextProps.viewingPage !== this.props.viewingPage || nextProps.address != this.props.address) {
this.setState({ address: nextProps.address, icon: nextProps.icon });
}
},
@ -109,8 +118,15 @@ let WunderBar = React.createClass({
this.setState(newState);
},
onBlur: function() {
this.setState(Object.assign({}, this._stateBeforeSearch, { isActive: false }));
this._input.value = this.state.address;
let commonState = {isActive: false};
if (this._resetOnNextBlur) {
this.setState(Object.assign({}, this._stateBeforeSearch, commonState));
this._input.value = this.state.address;
} else {
this._resetOnNextBlur = true;
this._stateBeforeSearch = this.state;
this.setState(commonState);
}
},
componentDidUpdate: function() {
this._input.value = this.state.address;
@ -119,6 +135,12 @@ let WunderBar = React.createClass({
this._focusPending = false;
}
},
onKeyPress: function(event) {
if (event.charCode == 13 && this._input.value) {
clearTimeout(this._userTypingTimer);
this.props.onSubmit(lbryuri.normalize(this._input.value));
}
},
onReceiveRef: function(ref) {
this._input = ref;
},
@ -131,6 +153,7 @@ let WunderBar = React.createClass({
onFocus={this.onFocus}
onBlur={this.onBlur}
onChange={this.onChange}
onKeyPress={this.onKeyPress}
value={this.state.address}
placeholder="Find movies, music, games, and more" />
</div>

View file

@ -48,9 +48,22 @@ let SearchResults = React.createClass({
_isMounted: false,
search: function(term) {
lighthouse.search(term).then(this.searchCallback);
if (!this.state.searching) {
this.setState({ searching: true })
}
},
componentWillMount: function () {
this._isMounted = true;
lighthouse.search(this.props.query).then(this.searchCallback);
this.search(this.props.query);
},
componentWillReceiveProps: function (nextProps) {
if (nextProps.query != this.props.query) {
this.search(nextProps.query);
}
},
componentWillUnmount: function () {
@ -77,9 +90,9 @@ let SearchResults = React.createClass({
render: function () {
return this.state.searching ?
<BusyMessage message="Looking up the Dewey Decimals" /> :
(this.state.results.length ?
(this.state.results && this.state.results.length ?
<SearchResultList results={this.state.results} /> :
<SearchNoResults query={thisprops.query} />);
<SearchNoResults query={this.props.query} />);
}
});
@ -123,14 +136,22 @@ let SearchPage = React.createClass({
render: function() {
return (
<main>
<main className="main--single-column">
{ this.isValidUri(this.props.query) ?
<div>
<h3>lbry://{this.props.query}</h3>
<div><BusyMessage message="Resolving the URL" /></div>
</div> : '' }
<h3>Search</h3>
<SearchResults query={this.props.query} />
<section className="section-spaced">
<h3 className="card-row__header">
Exact URL
<ToolTip label="?" body="This is the resolution of a LBRY URL and not controlled by LBRY Inc." className="tooltip--header"/>
</h3>
<FileTile uri={this.props.query} showEmpty={true} />
</section> : '' }
<section className="section-spaced">
<h3 className="card-row__header">
Search Results for {this.props.query}
<ToolTip label="?" body="These search results are provided by LBRY, Inc." className="tooltip--header"/>
</h3>
<SearchResults query={this.props.query} />
</section>
</main>
);
}

View file

@ -19,6 +19,10 @@ var FormatItem = React.createClass({
const {thumbnail, author, title, description, language, license} = this.props.metadata;
const mediaType = lbry.getMediaType(this.props.contentType);
if (!this.props.contentType && [author, language, license].filter().length === 0) {
return null;
}
return (
<table className="table-standard">
<tbody>
@ -42,12 +46,15 @@ var FormatItem = React.createClass({
let ShowPage = React.createClass({
_uri: null,
_isMounted: false,
propTypes: {
uri: React.PropTypes.string,
},
getInitialState: function() {
return {
outpoint: null,
metadata: null,
contentType: null,
hasSignature: false,
@ -56,43 +63,91 @@ let ShowPage = React.createClass({
costIncludesData: null,
uriLookupComplete: null,
isDownloaded: null,
isFailed: false,
};
},
componentWillUnmount: function() {
this._isMounted = false;
},
componentWillReceiveProps: function(nextProps) {
if (nextProps.uri != this.props.uri) {
this.loadUri(nextProps.uri);
}
},
componentWillMount: function() {
this._uri = lbryuri.normalize(this.props.uri);
this.loadUri(this.props.uri);
},
lbry.resolve({uri: this._uri}).then(({ claim: {txid, nout, has_signature, signature_is_valid, value: {stream: {metadata, source: {contentType}}}}}) => {
const outpoint = txid + ':' + nout;
loadUri: function(uri) {
this._uri = lbryuri.normalize(uri);
lbry.file_list({outpoint}).then((fileInfo) => {
this.setState({
isDownloaded: fileInfo.length > 0,
lbry.resolve({uri: this._uri}).then((resolveData) => {
if (resolveData) {
let {claim: {txid, nout, has_signature, signature_is_valid, value: {stream: {metadata, source: {contentType}}}}} = resolveData;
const outpoint = txid + ':' + nout;
lbry.file_list({outpoint}).then((fileInfo) => {
this.setState({
isDownloaded: fileInfo.length > 0,
});
});
});
lbry.setTitle(metadata.title ? metadata.title : this._uri)
lbry.setTitle(metadata.title ? metadata.title : this._uri)
this.setState({
outpoint: outpoint,
metadata: metadata,
hasSignature: has_signature,
signatureIsValid: signature_is_valid,
contentType: contentType,
uriLookupComplete: true,
});
});
if (this._isMounted) {
this.setState({
outpoint: outpoint,
metadata: metadata,
hasSignature: has_signature,
signatureIsValid: signature_is_valid,
contentType: contentType,
uriLookupComplete: true,
});
}
lbry.getCostInfo(this._uri).then(({cost, includesData}) => {
this.setState({
cost: cost,
costIncludesData: includesData,
});
lbry.getCostInfo(this._uri).then(({cost, includesData}) => {
if (this._isMounted) {
this.setState({
cost: cost,
costIncludesData: includesData,
});
}
});
} else {
if (this._isMounted) {
this.setState(Object.assign({}, this.getInitialState(), {
uriLookupComplete: true,
isFailed: true
}));
}
}
});
},
render: function() {
const metadata = this.state.metadata;
const title = metadata ? this.state.metadata.title : this._uri;
if (this.state.isFailed) {
return <main className="main--single-column">
<section className="card">
<div className="card__inner">
<div className="card__title-identity"><h1>{this._uri}</h1></div>
</div>
<div className="card__content">
<p>
This location is not yet in use.
{ ' ' }
<Link href="?publish" label="Put something here" />.
</p>
</div>
</section>
</main>
}
return (
<main className="main--single-column">
<section className="show-page-media">
@ -107,7 +162,7 @@ let ShowPage = React.createClass({
? <span style={{float: "right"}}><FilePrice uri={this._uri} metadata={this.state.metadata} /></span>
: null}
<h1>{title}</h1>
{ this.state.uriLookupComplete ?
{ this.state.uriLookupComplete && this.state.outpoint ?
<div>
<div className="card__subtitle">
<UriIndicator uri={this._uri} hasSignature={this.state.hasSignature} signatureIsValid={this.state.signatureIsValid} />