file list refactor
This commit is contained in:
parent
3b7d093201
commit
7f135275df
7 changed files with 225 additions and 254 deletions
|
@ -4,7 +4,6 @@ import SettingsPage from './page/settings.js';
|
||||||
import HelpPage from './page/help.js';
|
import HelpPage from './page/help.js';
|
||||||
import WatchPage from './page/watch.js';
|
import WatchPage from './page/watch.js';
|
||||||
import ReportPage from './page/report.js';
|
import ReportPage from './page/report.js';
|
||||||
import {MyFilesPage} from './page/my_files.js';
|
|
||||||
import StartPage from './page/start.js';
|
import StartPage from './page/start.js';
|
||||||
import ClaimCodePage from './page/claim_code.js';
|
import ClaimCodePage from './page/claim_code.js';
|
||||||
import ReferralPage from './page/referral.js';
|
import ReferralPage from './page/referral.js';
|
||||||
|
@ -14,6 +13,7 @@ import PublishPage from './page/publish.js';
|
||||||
import DiscoverPage from './page/discover.js';
|
import DiscoverPage from './page/discover.js';
|
||||||
import SplashScreen from './component/splash.js';
|
import SplashScreen from './component/splash.js';
|
||||||
import DeveloperPage from './page/developer.js';
|
import DeveloperPage from './page/developer.js';
|
||||||
|
import {FileListDownloaded, FileListPublished} from './page/file-list.js';
|
||||||
import Drawer from './component/drawer.js';
|
import Drawer from './component/drawer.js';
|
||||||
import Header from './component/header.js';
|
import Header from './component/header.js';
|
||||||
import Modal from './component/modal.js';
|
import Modal from './component/modal.js';
|
||||||
|
@ -164,9 +164,9 @@ var App = React.createClass({
|
||||||
case 'report':
|
case 'report':
|
||||||
return <ReportPage />;
|
return <ReportPage />;
|
||||||
case 'downloaded':
|
case 'downloaded':
|
||||||
return <MyFilesPage show="downloaded" />;
|
return <FileListDownloaded />;
|
||||||
case 'published':
|
case 'published':
|
||||||
return <MyFilesPage show="published" />;
|
return <FileListPublished />;
|
||||||
case 'start':
|
case 'start':
|
||||||
return <StartPage />;
|
return <StartPage />;
|
||||||
case 'claim':
|
case 'claim':
|
||||||
|
|
|
@ -56,11 +56,10 @@ export let FileActions = React.createClass({
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
streamName: React.PropTypes.string,
|
streamName: React.PropTypes.string,
|
||||||
sdHash: React.PropTypes.string,
|
sdHash: React.PropTypes.string.isRequired,
|
||||||
metadata: React.PropTypes.object,
|
metadata: React.PropTypes.object,
|
||||||
path: React.PropTypes.string,
|
path: React.PropTypes.string,
|
||||||
hidden: React.PropTypes.bool,
|
hidden: React.PropTypes.bool,
|
||||||
onRemoveConfirmed: React.PropTypes.func,
|
|
||||||
deleteChecked: React.PropTypes.bool,
|
deleteChecked: React.PropTypes.bool,
|
||||||
},
|
},
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -137,9 +136,10 @@ export let FileActions = React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleRemoveConfirmed: function() {
|
handleRemoveConfirmed: function() {
|
||||||
lbry.deleteFile(this.props.sdHash || this.props.streamName, this.state.deleteChecked);
|
if (this.props.streamName) {
|
||||||
if (this.props.onRemoveConfirmed) {
|
lbry.deleteFile(this.props.streamName, this.state.deleteChecked);
|
||||||
this.props.onRemoveConfirmed();
|
} else {
|
||||||
|
alert('this file cannot be deleted because lbry is a retarded piece of shit');
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
modal: null,
|
modal: null,
|
||||||
|
@ -155,20 +155,12 @@ export let FileActions = React.createClass({
|
||||||
},
|
},
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
this._isMounted = true;
|
this._isMounted = true;
|
||||||
|
this._fileInfoSubscribeId = lbry.fileInfoSubscribe(this.props.sdHash, this.onFileInfoUpdate);
|
||||||
if ('sdHash' in this.props) {
|
|
||||||
alert('render by sd hash is broken');
|
|
||||||
lbry.fileInfoSubscribeByStreamHash(this.props.sdHash, this.fileInfoU);
|
|
||||||
} else if ('streamName' in this.props) {
|
|
||||||
this._fileInfoSubscribeId = lbry.fileInfoSubscribeByName(this.props.streamName, this.onFileInfoUpdate);
|
|
||||||
} else {
|
|
||||||
throw new Error("No stream name or sd hash passed to FileTile");
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
componentWillUnmount: function() {
|
componentWillUnmount: function() {
|
||||||
this._isMounted = false;
|
this._isMounted = false;
|
||||||
if (this._fileInfoSubscribeId) {
|
if (this._fileInfoSubscribeId) {
|
||||||
lbry.fileInfoUnsubscribe(this.props.streamName, this._fileInfoSubscribeId);
|
lbry.fileInfoUnsubscribe(this.props.sdHash, this._fileInfoSubscribeId);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
|
|
|
@ -55,8 +55,7 @@ export let FileTileStream = React.createClass({
|
||||||
metadata: React.PropTypes.object,
|
metadata: React.PropTypes.object,
|
||||||
sdHash: React.PropTypes.string,
|
sdHash: React.PropTypes.string,
|
||||||
hidePrice: React.PropTypes.bool,
|
hidePrice: React.PropTypes.bool,
|
||||||
obscureNsfw: React.PropTypes.bool,
|
obscureNsfw: React.PropTypes.bool
|
||||||
hideOnRemove: React.PropTypes.bool
|
|
||||||
},
|
},
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
|
@ -66,7 +65,6 @@ export let FileTileStream = React.createClass({
|
||||||
},
|
},
|
||||||
getDefaultProps: function() {
|
getDefaultProps: function() {
|
||||||
return {
|
return {
|
||||||
hideOnRemove: false,
|
|
||||||
obscureNsfw: !lbry.getClientSetting('showNsfw'),
|
obscureNsfw: !lbry.getClientSetting('showNsfw'),
|
||||||
hidePrice: false
|
hidePrice: false
|
||||||
}
|
}
|
||||||
|
@ -85,19 +83,11 @@ export let FileTileStream = React.createClass({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onRemove: function() {
|
|
||||||
this.setState({
|
|
||||||
isRemoved: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
render: function() {
|
render: function() {
|
||||||
if (this.props.metadata === null || (this.props.hideOnRemove && this.state.isRemoved)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const metadata = this.props.metadata || {},
|
const metadata = this.props.metadata || {},
|
||||||
obscureNsfw = this.props.obscureNsfw && metadata.nsfw,
|
obscureNsfw = this.props.obscureNsfw && metadata.nsfw,
|
||||||
title = metadata.title ? metadata.title : ('lbry://' + this.props.name);
|
title = metadata.title ? metadata.title : ('lbry://' + this.props.name);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<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">
|
||||||
|
@ -116,7 +106,7 @@ export let FileTileStream = React.createClass({
|
||||||
</TruncatedText>
|
</TruncatedText>
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
<FileActions streamName={this.props.name} metadata={metadata} />
|
<FileActions streamName={this.props.name} sdHash={this.props.sdHash} metadata={metadata} />
|
||||||
<p className="file-tile__description">
|
<p className="file-tile__description">
|
||||||
<TruncatedText lines={3}>
|
<TruncatedText lines={3}>
|
||||||
{metadata.description}
|
{metadata.description}
|
||||||
|
@ -141,7 +131,7 @@ export let FileTile = React.createClass({
|
||||||
_isMounted: false,
|
_isMounted: false,
|
||||||
|
|
||||||
propTypes: {
|
propTypes: {
|
||||||
name: React.PropTypes.string
|
name: React.PropTypes.string.isRequired
|
||||||
},
|
},
|
||||||
|
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
|
@ -167,7 +157,7 @@ export let FileTile = React.createClass({
|
||||||
this._isMounted = false;
|
this._isMounted = false;
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
if (this.state.metadata === null || this.state.sdHash === null) {
|
if (!this.state.metadata || !this.state.sdHash) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
28
js/lbry.js
28
js/lbry.js
|
@ -472,43 +472,37 @@ lbry._updateClaimOwnershipCache = function(claimId) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
lbry._updateSubscribedFileInfoByName = function(name) {
|
lbry._updateSubscribedFileInfo = function(sdHash) {
|
||||||
lbry.getFileInfoByName(name, (fileInfo) => {
|
lbry.getFileInfoBySdHash(sdHash, (fileInfo) => {
|
||||||
if (fileInfo) {
|
if (fileInfo) {
|
||||||
if (this._claimIdOwnershipCache[fileInfo.claim_id] === undefined) {
|
if (this._claimIdOwnershipCache[fileInfo.claim_id] === undefined) {
|
||||||
lbry._updateClaimOwnershipCache(fileInfo.claim_id);
|
lbry._updateClaimOwnershipCache(fileInfo.claim_id);
|
||||||
}
|
}
|
||||||
fileInfo.isMine = !!this._claimIdOwnershipCache[fileInfo.claim_id];
|
fileInfo.isMine = !!this._claimIdOwnershipCache[fileInfo.claim_id];
|
||||||
}
|
}
|
||||||
Object.keys(this._fileInfoSubscribeCallbacks[name]).forEach(function(subscribeId) {
|
Object.keys(this._fileInfoSubscribeCallbacks[sdHash]).forEach(function(subscribeId) {
|
||||||
lbry._fileInfoSubscribeCallbacks[name][subscribeId](fileInfo);
|
lbry._fileInfoSubscribeCallbacks[sdHash][subscribeId](fileInfo);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
if (Object.keys(this._fileInfoSubscribeCallbacks[name]).length) {
|
if (Object.keys(this._fileInfoSubscribeCallbacks[sdHash]).length) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this._updateSubscribedFileInfoByName(name)
|
this._updateSubscribedFileInfo(sdHash)
|
||||||
}, lbry._fileInfoSubscribeInterval);
|
}, lbry._fileInfoSubscribeInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lbry.fileInfoSubscribeByName = function(name, callback) {
|
lbry.fileInfoSubscribe = function(sdHash, callback) {
|
||||||
if (!lbry._fileInfoSubscribeCallbacks[name])
|
if (!lbry._fileInfoSubscribeCallbacks[sdHash])
|
||||||
{
|
{
|
||||||
lbry._fileInfoSubscribeCallbacks[name] = {};
|
lbry._fileInfoSubscribeCallbacks[sdHash] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const subscribeId = ++lbry._fileInfoSubscribeIdCounter;
|
const subscribeId = ++lbry._fileInfoSubscribeIdCounter;
|
||||||
lbry._fileInfoSubscribeCallbacks[name][subscribeId] = callback;
|
lbry._fileInfoSubscribeCallbacks[sdHash][subscribeId] = callback;
|
||||||
lbry._updateSubscribedFileInfoByName(name);
|
lbry._updateSubscribedFileInfo(sdHash);
|
||||||
return subscribeId;
|
return subscribeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// lbry.fileInfoSubscribeByStreamHash = function(sdHash, callback) {
|
|
||||||
// lbry.getFileInfoBySdHash(this.props.sdHash, this.updateFileInfoCallback);
|
|
||||||
// this.getIsMineIfNeeded(this.props.sdHash);
|
|
||||||
// setTimeout(() => { this.updateFileInfo() }, this._fileInfoCheckInterval);
|
|
||||||
// }
|
|
||||||
|
|
||||||
lbry.fileInfoUnsubscribe = function(name, subscribeId) {
|
lbry.fileInfoUnsubscribe = function(name, subscribeId) {
|
||||||
delete lbry._fileInfoSubscribeCallbacks[name][subscribeId];
|
delete lbry._fileInfoSubscribeCallbacks[name][subscribeId];
|
||||||
}
|
}
|
||||||
|
|
194
js/page/file-list.js
Normal file
194
js/page/file-list.js
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
import React from 'react';
|
||||||
|
import lbry from '../lbry.js';
|
||||||
|
import {Link} from '../component/link.js';
|
||||||
|
import FormField from '../component/form.js';
|
||||||
|
import {FileTileStream} from '../component/file-tile.js';
|
||||||
|
import {BusyMessage, Thumbnail} from '../component/common.js';
|
||||||
|
|
||||||
|
|
||||||
|
export let FileListDownloaded = React.createClass({
|
||||||
|
_isMounted: false,
|
||||||
|
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
fileInfos: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
componentDidMount: function() {
|
||||||
|
this._isMounted = true;
|
||||||
|
document.title = "Downloaded Files";
|
||||||
|
|
||||||
|
let publishedFilesSdHashes = [];
|
||||||
|
lbry.getMyClaims((claimsInfo) => {
|
||||||
|
|
||||||
|
if (!this._isMounted) { return; }
|
||||||
|
|
||||||
|
for (let claimInfo of claimsInfo) {
|
||||||
|
let metadata = JSON.parse(claimInfo.value);
|
||||||
|
publishedFilesSdHashes.push(metadata.sources.lbry_sd_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
lbry.getFilesInfo((fileInfos) => {
|
||||||
|
if (!this._isMounted) { return; }
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
fileInfos: fileInfos.filter(({sd_hash}) => {
|
||||||
|
return publishedFilesSdHashes.indexOf(sd_hash) == -1;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
if (this.state.fileInfos === null) {
|
||||||
|
return (
|
||||||
|
<main className="page">
|
||||||
|
<BusyMessage message="Loading" />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
} else if (!this.state.fileInfos.length) {
|
||||||
|
return (
|
||||||
|
<main className="page">
|
||||||
|
<span>You haven't downloaded anything from LBRY yet. Go <Link href="/" label="search for your first download" />!</span>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<main className="page">
|
||||||
|
<FileList fileInfos={this.state.fileInfos} />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export let FileListPublished = React.createClass({
|
||||||
|
_isMounted: false,
|
||||||
|
|
||||||
|
getInitialState: function () {
|
||||||
|
return {
|
||||||
|
fileInfos: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
componentDidMount: function () {
|
||||||
|
this._isMounted = true;
|
||||||
|
document.title = "Published Files";
|
||||||
|
|
||||||
|
lbry.getMyClaims((claimsInfo) => {
|
||||||
|
/**
|
||||||
|
* Build newFileInfos as a sparse array and drop elements in at the same position they
|
||||||
|
* occur in claimsInfo, so the order is preserved even if the API calls inside this loop
|
||||||
|
* return out of order.
|
||||||
|
*/
|
||||||
|
let newFileInfos = Array(claimsInfo.length),
|
||||||
|
claimInfoProcessedCount = 0;
|
||||||
|
|
||||||
|
for (let [i, claimInfo] of claimsInfo.entries()) {
|
||||||
|
let metadata = JSON.parse(claimInfo.value);
|
||||||
|
lbry.getFileInfoBySdHash(metadata.sources.lbry_sd_hash, (fileInfo) => {
|
||||||
|
claimInfoProcessedCount++;
|
||||||
|
if (fileInfo !== false) {
|
||||||
|
newFileInfos[i] = fileInfo;
|
||||||
|
}
|
||||||
|
if (claimInfoProcessedCount >= claimsInfo.length) {
|
||||||
|
/**
|
||||||
|
* newfileInfos may have gaps from claims that don't have associated files in
|
||||||
|
* lbrynet, so filter out any missing elements
|
||||||
|
*/
|
||||||
|
this.setState({
|
||||||
|
fileInfos: newFileInfos.filter(function () {
|
||||||
|
return true
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
if (this.state.fileInfos === null) {
|
||||||
|
return (
|
||||||
|
<main className="page">
|
||||||
|
<BusyMessage message="Loading" />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (!this.state.fileInfos.length) {
|
||||||
|
return (
|
||||||
|
<main className="page">
|
||||||
|
<span>You haven't published anything to LBRY yet.</span> Try <Link href="/?publish" label="publishing" />!
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
<main className="page">
|
||||||
|
<FileList fileInfos={this.state.fileInfos} />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export let FileList = React.createClass({
|
||||||
|
_sortFunctions: {
|
||||||
|
date: function(fileInfos) {
|
||||||
|
return fileInfos.reverse();
|
||||||
|
},
|
||||||
|
title: function(fileInfos) {
|
||||||
|
return fileInfos.sort(function(a, b) {
|
||||||
|
return ((a.metadata ? a.metadata.title.toLowerCase() : a.name) >
|
||||||
|
(b.metadata ? b.metadata.title.toLowerCase() : b.name));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
filename: function(fileInfos) {
|
||||||
|
return fileInfos.sort(function(a, b) {
|
||||||
|
return (a.file_name.toLowerCase() >
|
||||||
|
b.file_name.toLowerCase());
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
propTypes: {
|
||||||
|
fileInfos: React.PropTypes.array.isRequired
|
||||||
|
},
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
sortBy: 'date',
|
||||||
|
};
|
||||||
|
},
|
||||||
|
handleSortChanged: function(event) {
|
||||||
|
this.setState({
|
||||||
|
sortBy: event.target.value,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
var content = [],
|
||||||
|
seenUris = {};
|
||||||
|
|
||||||
|
const fileInfosSorted = this._sortFunctions[this.state.sortBy](this.props.fileInfos);
|
||||||
|
for (let fileInfo of fileInfosSorted) {
|
||||||
|
let {lbry_uri, sd_hash, metadata} = fileInfo;
|
||||||
|
|
||||||
|
if (!metadata || seenUris[lbry_uri]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
seenUris[lbry_uri] = true;
|
||||||
|
content.push(<FileTileStream key={lbry_uri} name={lbry_uri} hideOnRemove={true} sdHash={sd_hash} hidePrice={true} metadata={metadata} />);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section>
|
||||||
|
<span className='sort-section'>
|
||||||
|
Sort by { ' ' }
|
||||||
|
<FormField type="select" onChange={this.handleSortChanged}>
|
||||||
|
<option value="date">Date</option>
|
||||||
|
<option value="title">Title</option>
|
||||||
|
<option value="filename">File name</option>
|
||||||
|
</FormField>
|
||||||
|
</span>
|
||||||
|
{content}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,196 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import lbry from '../lbry.js';
|
|
||||||
import {Link} from '../component/link.js';
|
|
||||||
import FormField from '../component/form.js';
|
|
||||||
import {FileTileStream} from '../component/file-tile.js';
|
|
||||||
import {BusyMessage, Thumbnail} from '../component/common.js';
|
|
||||||
|
|
||||||
export let MyFilesPage = React.createClass({
|
|
||||||
_fileTimeout: null,
|
|
||||||
_fileInfoCheckRate: 300,
|
|
||||||
_fileInfoCheckNum: 0,
|
|
||||||
_sortFunctions: {
|
|
||||||
date: function(filesInfo) {
|
|
||||||
return filesInfo.reverse();
|
|
||||||
},
|
|
||||||
title: function(filesInfo) {
|
|
||||||
return filesInfo.sort(function(a, b) {
|
|
||||||
return ((a.metadata ? a.metadata.title.toLowerCase() : a.name) >
|
|
||||||
(b.metadata ? b.metadata.title.toLowerCase() : b.name));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
filename: function(filesInfo) {
|
|
||||||
return filesInfo.sort(function(a, b) {
|
|
||||||
return (a.file_name.toLowerCase() >
|
|
||||||
b.file_name.toLowerCase());
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
getInitialState: function() {
|
|
||||||
return {
|
|
||||||
filesInfo: null,
|
|
||||||
publishedFilesSdHashes: null,
|
|
||||||
filesAvailable: null,
|
|
||||||
sortBy: 'date',
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getDefaultProps: function() {
|
|
||||||
return {
|
|
||||||
show: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
componentDidMount: function() {
|
|
||||||
document.title = "My Files";
|
|
||||||
},
|
|
||||||
componentWillMount: function() {
|
|
||||||
if (this.props.show == 'downloaded') {
|
|
||||||
this.getPublishedFilesSdHashes(() => {
|
|
||||||
this.updateFilesInfo();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.updateFilesInfo();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getPublishedFilesSdHashes: function(callback) {
|
|
||||||
// Determines which files were published by the user and saves their SD hashes in
|
|
||||||
// this.state.publishedFilesSdHashes. Used on the Downloads page to filter out claims published
|
|
||||||
// by the user.
|
|
||||||
var publishedFilesSdHashes = [];
|
|
||||||
lbry.getMyClaims((claimsInfo) => {
|
|
||||||
for (let claimInfo of claimsInfo) {
|
|
||||||
let metadata = JSON.parse(claimInfo.value);
|
|
||||||
publishedFilesSdHashes.push(metadata.sources.lbry_sd_hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
publishedFilesSdHashes: publishedFilesSdHashes,
|
|
||||||
});
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
componentWillUnmount: function() {
|
|
||||||
if (this._fileTimeout)
|
|
||||||
{
|
|
||||||
clearTimeout(this._fileTimeout);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleSortChanged: function(event) {
|
|
||||||
this.setState({
|
|
||||||
sortBy: event.target.value,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
updateFilesInfo: function() {
|
|
||||||
this._fileInfoCheckNum += 1;
|
|
||||||
|
|
||||||
if (this.props.show == 'published') {
|
|
||||||
// We're in the Published tab, so populate this.state.filesInfo with data from the user's claims
|
|
||||||
lbry.getMyClaims((claimsInfo) => {
|
|
||||||
/**
|
|
||||||
* Build newFilesInfo as a sparse array and drop elements in at the same position they
|
|
||||||
* occur in claimsInfo, so the order is preserved even if the API calls inside this loop
|
|
||||||
* return out of order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
let newFilesInfo = Array(claimsInfo.length);
|
|
||||||
let claimInfoProcessedCount = 0;
|
|
||||||
for (let [i, claimInfo] of claimsInfo.entries()) {
|
|
||||||
let metadata = JSON.parse(claimInfo.value);
|
|
||||||
lbry.getFileInfoBySdHash(metadata.sources.lbry_sd_hash, (fileInfo) => {
|
|
||||||
claimInfoProcessedCount++;
|
|
||||||
if (fileInfo !== false) {
|
|
||||||
newFilesInfo[i] = fileInfo;
|
|
||||||
}
|
|
||||||
if (claimInfoProcessedCount >= claimsInfo.length) {
|
|
||||||
/**
|
|
||||||
* newFilesInfo may have gaps from claims that don't have associated files in
|
|
||||||
* lbrynet, so filter out any missing elements
|
|
||||||
*/
|
|
||||||
this.setState({
|
|
||||||
filesInfo: newFilesInfo.filter(function() { return true }),
|
|
||||||
});
|
|
||||||
|
|
||||||
this._fileTimeout = setTimeout(() => { this.updateFilesInfo() }, 1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// We're in the Downloaded tab, so populate this.state.filesInfo with files the user has in
|
|
||||||
// lbrynet, with published files filtered out.
|
|
||||||
lbry.getFilesInfo((filesInfo) => {
|
|
||||||
this.setState({
|
|
||||||
filesInfo: filesInfo.filter(({sd_hash}) => {
|
|
||||||
return this.state.publishedFilesSdHashes.indexOf(sd_hash) == -1;
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
let newFilesAvailable;
|
|
||||||
if (!(this._fileInfoCheckNum % this._fileInfoCheckRate)) {
|
|
||||||
// Time to update file availability status
|
|
||||||
|
|
||||||
newFilesAvailable = {};
|
|
||||||
let filePeersCheckCount = 0;
|
|
||||||
for (let {sd_hash} of filesInfo) {
|
|
||||||
lbry.getPeersForBlobHash(sd_hash, (peers) => {
|
|
||||||
filePeersCheckCount++;
|
|
||||||
newFilesAvailable[sd_hash] = peers.length >= 0;
|
|
||||||
if (filePeersCheckCount >= filesInfo.length) {
|
|
||||||
this.setState({
|
|
||||||
filesAvailable: newFilesAvailable,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._fileTimeout = setTimeout(() => { this.updateFilesInfo() }, 1000);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if (this.state.filesInfo === null || (this.props.show == 'downloaded' && this.state.publishedFileSdHashes === null)) {
|
|
||||||
return (
|
|
||||||
<main className="page">
|
|
||||||
<BusyMessage message="Loading" />
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
} else if (!this.state.filesInfo.length) {
|
|
||||||
return (
|
|
||||||
<main className="page">
|
|
||||||
{this.props.show == 'downloaded'
|
|
||||||
? <span>You haven't downloaded anything from LBRY yet. Go <Link href="/" label="search for your first download" />!</span>
|
|
||||||
: <span>You haven't published anything to LBRY yet.</span>}
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
var content = [],
|
|
||||||
seenUris = {};
|
|
||||||
|
|
||||||
const filesInfoSorted = this._sortFunctions[this.state.sortBy](this.state.filesInfo);
|
|
||||||
for (let fileInfo of filesInfoSorted) {
|
|
||||||
let {lbry_uri, sd_hash, metadata} = fileInfo;
|
|
||||||
|
|
||||||
if (!metadata || seenUris[lbry_uri]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
seenUris[lbry_uri] = true;
|
|
||||||
content.push(<FileTileStream name={lbry_uri} sdHash={sd_hash} hideOnRemove={true} hidePrice={true} metadata={metadata} />);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<main className="page">
|
|
||||||
<span className='sort-section'>
|
|
||||||
Sort by { ' ' }
|
|
||||||
<FormField type="select" onChange={this.handleSortChanged}>
|
|
||||||
<option value="date">Date</option>
|
|
||||||
<option value="title">Title</option>
|
|
||||||
<option value="filename">File name</option>
|
|
||||||
</FormField>
|
|
||||||
</span>
|
|
||||||
{content}
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -347,12 +347,6 @@ input[type="text"], input[type="search"]
|
||||||
margin: 0px 6px;
|
margin: 0px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error-modal__error-list {
|
|
||||||
border: 1px solid #eee;
|
|
||||||
padding: 8px;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error-modal-overlay {
|
.error-modal-overlay {
|
||||||
background: rgba(#000, .88);
|
background: rgba(#000, .88);
|
||||||
}
|
}
|
||||||
|
@ -371,12 +365,15 @@ input[type="text"], input[type="search"]
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.error-modal {
|
.error-modal {
|
||||||
max-width: none;
|
max-width: none;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
}
|
}
|
||||||
.error-modal__error-list { /*shitty hack/temp fix for long errors making modals unusable*/
|
.error-modal__error-list { /*shitty hack/temp fix for long errors making modals unusable*/
|
||||||
|
border: 1px solid #eee;
|
||||||
|
padding: 8px;
|
||||||
|
list-style: none;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
|
max-width: 400px;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue