2016-05-30 14:54:08 +02:00
|
|
|
var moreMenuStyle = {
|
2016-05-29 13:04:25 +02:00
|
|
|
position: 'absolute',
|
|
|
|
display: 'block',
|
|
|
|
top: '26px',
|
2016-10-02 09:33:32 +02:00
|
|
|
right: '13px',
|
2016-05-29 13:04:25 +02:00
|
|
|
};
|
|
|
|
var MyFilesRowMoreMenu = React.createClass({
|
2016-10-21 09:56:37 +02:00
|
|
|
propTypes: {
|
|
|
|
title: React.PropTypes.string.isRequired,
|
|
|
|
path: React.PropTypes.string.isRequired,
|
|
|
|
completed: React.PropTypes.bool.isRequired,
|
|
|
|
lbryUri: React.PropTypes.string.isRequired,
|
|
|
|
},
|
|
|
|
handleRevealClicked: function() {
|
2016-05-30 14:54:08 +02:00
|
|
|
lbry.revealFile(this.props.path);
|
|
|
|
},
|
2016-10-21 09:56:37 +02:00
|
|
|
handleRemoveClicked: function() {
|
2016-05-30 14:54:08 +02:00
|
|
|
lbry.deleteFile(this.props.lbryUri, false);
|
|
|
|
},
|
2016-10-21 09:56:37 +02:00
|
|
|
handleDeleteClicked: function() {
|
|
|
|
this.setState({
|
|
|
|
modal: 'confirmDelete',
|
|
|
|
});
|
|
|
|
},
|
|
|
|
handleDeleteConfirmed: function() {
|
|
|
|
lbry.deleteFile(this.props.lbryUri);
|
2016-11-18 05:32:24 +01:00
|
|
|
this.setState({
|
2016-10-21 09:56:37 +02:00
|
|
|
modal: null,
|
|
|
|
});
|
|
|
|
},
|
2016-11-18 05:36:14 +01:00
|
|
|
closeModal: function() {
|
|
|
|
this.setState({
|
2016-10-21 09:56:37 +02:00
|
|
|
modal: null,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
getInitialState: function() {
|
|
|
|
return {
|
|
|
|
modal: null,
|
|
|
|
};
|
2016-05-29 13:04:25 +02:00
|
|
|
},
|
|
|
|
render: function() {
|
|
|
|
return (
|
2016-05-30 14:54:08 +02:00
|
|
|
<div style={moreMenuStyle}>
|
2016-05-29 13:04:25 +02:00
|
|
|
<Menu {...this.props}>
|
2016-08-08 05:31:21 +02:00
|
|
|
<section className="card">
|
2016-10-21 09:56:37 +02:00
|
|
|
<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" />
|
2016-08-08 05:31:21 +02:00
|
|
|
</section>
|
2016-05-29 13:04:25 +02:00
|
|
|
</Menu>
|
2016-11-18 05:36:14 +01:00
|
|
|
<Modal isOpen={this.state.modal == 'confirmDelete'} type="confirm" confirmButtonLabel="Delete File"
|
|
|
|
onConfirmed={this.handleDeleteConfirmed} onAborted={this.closeModal}>
|
2016-10-21 09:56:37 +02:00
|
|
|
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>
|
2016-05-29 13:04:25 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var moreButtonColumnStyle = {
|
2016-08-07 17:27:00 +02:00
|
|
|
height: '120px',
|
|
|
|
display: 'flex',
|
|
|
|
alignItems: 'center',
|
|
|
|
justifyContent: 'center',
|
|
|
|
},
|
|
|
|
moreButtonContainerStyle = {
|
|
|
|
display: 'block',
|
|
|
|
position: 'relative',
|
|
|
|
},
|
|
|
|
moreButtonStyle = {
|
|
|
|
fontSize: '1.3em',
|
|
|
|
},
|
|
|
|
progressBarStyle = {
|
|
|
|
height: '15px',
|
|
|
|
width: '230px',
|
|
|
|
backgroundColor: '#444',
|
|
|
|
border: '2px solid #eee',
|
|
|
|
display: 'inline-block',
|
2016-08-27 08:18:19 +02:00
|
|
|
},
|
2016-08-07 17:27:00 +02:00
|
|
|
artStyle = {
|
|
|
|
maxHeight: '100px',
|
2016-08-26 12:54:30 +02:00
|
|
|
maxWidth: '100%',
|
2016-08-07 17:27:00 +02:00
|
|
|
display: 'block',
|
|
|
|
marginLeft: 'auto',
|
|
|
|
marginRight: 'auto',
|
|
|
|
};
|
2016-05-10 12:36:54 +02:00
|
|
|
var MyFilesRow = React.createClass({
|
2016-05-14 14:26:54 +02:00
|
|
|
onPauseResumeClicked: function() {
|
|
|
|
if (this.props.stopped) {
|
|
|
|
lbry.startFile(this.props.lbryUri);
|
|
|
|
} else {
|
|
|
|
lbry.stopFile(this.props.lbryUri);
|
|
|
|
}
|
|
|
|
},
|
2016-05-10 12:36:54 +02:00
|
|
|
render: function() {
|
2016-05-30 14:54:08 +02:00
|
|
|
//@TODO: Convert progress bar to reusable component
|
|
|
|
|
|
|
|
var progressBarWidth = 230;
|
2016-05-20 12:42:32 +02:00
|
|
|
|
2016-05-14 14:26:54 +02:00
|
|
|
if (this.props.completed) {
|
|
|
|
var pauseLink = null;
|
|
|
|
var curProgressBarStyle = {display: 'none'};
|
|
|
|
} else {
|
|
|
|
var pauseLink = <Link icon={this.props.stopped ? 'icon-play' : 'icon-pause'}
|
|
|
|
label={this.props.stopped ? 'Resume download' : 'Pause download'}
|
|
|
|
onClick={() => { this.onPauseResumeClicked() }} />;
|
|
|
|
|
|
|
|
var curProgressBarStyle = Object.assign({}, progressBarStyle);
|
2016-05-20 12:42:32 +02:00
|
|
|
curProgressBarStyle.width = Math.floor(this.props.ratioLoaded * progressBarWidth) + 'px';
|
|
|
|
curProgressBarStyle.borderRightWidth = progressBarWidth - Math.ceil(this.props.ratioLoaded * progressBarWidth) + 2;
|
2016-05-14 14:26:54 +02:00
|
|
|
}
|
2016-05-16 10:19:41 +02:00
|
|
|
|
|
|
|
if (this.props.showWatchButton) {
|
2016-05-20 12:42:32 +02:00
|
|
|
var watchButton = <WatchLink streamName={this.props.lbryUri} />
|
2016-05-16 10:19:41 +02:00
|
|
|
} else {
|
2016-05-20 12:39:02 +02:00
|
|
|
var watchButton = null;
|
2016-05-16 10:19:41 +02:00
|
|
|
}
|
|
|
|
|
2016-05-10 12:36:54 +02:00
|
|
|
return (
|
2016-08-08 05:31:21 +02:00
|
|
|
<section className="card">
|
|
|
|
<div className="row-fluid">
|
|
|
|
<div className="span3">
|
2016-11-11 13:57:01 +01:00
|
|
|
<Thumbnail src={this.props.imgUrl} alt={'Photo for ' + this.props.title} style={artStyle} />
|
2016-08-08 05:31:21 +02:00
|
|
|
</div>
|
|
|
|
<div className="span8">
|
|
|
|
<h3>{this.props.pending ? this.props.title : <a href={'/?show=' + this.props.lbryUri}>{this.props.title}</a>}</h3>
|
|
|
|
{this.props.pending ? <em>This file is pending confirmation</em>
|
|
|
|
: (
|
|
|
|
<div>
|
|
|
|
<div className={this.props.completed ? 'hidden' : ''} style={curProgressBarStyle}></div>
|
|
|
|
{ ' ' }
|
2016-09-24 10:21:07 +02:00
|
|
|
{this.props.completed
|
|
|
|
? (this.props.isMine
|
|
|
|
? 'Published'
|
|
|
|
: 'Download complete')
|
|
|
|
: (parseInt(this.props.ratioLoaded * 100) + '%')}
|
2016-08-08 05:31:21 +02:00
|
|
|
<div>{ pauseLink }</div>
|
|
|
|
<div>{ watchButton }</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
</div>
|
|
|
|
<div className="span1" style={moreButtonColumnStyle}>
|
|
|
|
{this.props.pending ? null :
|
|
|
|
<div style={moreButtonContainerStyle}>
|
|
|
|
<Link style={moreButtonStyle} ref="moreButton" icon="icon-ellipsis-h" title="More Options" />
|
|
|
|
<MyFilesRowMoreMenu toggleButton={this.refs.moreButton} title={this.props.title}
|
2016-10-21 09:56:37 +02:00
|
|
|
completed={this.props.completed} lbryUri={this.props.lbryUri}
|
|
|
|
fileName={this.props.fileName} path={this.props.path}/>
|
2016-08-07 17:27:00 +02:00
|
|
|
</div>
|
2016-08-08 05:31:21 +02:00
|
|
|
}
|
|
|
|
</div>
|
2016-05-14 14:26:54 +02:00
|
|
|
</div>
|
2016-08-08 05:31:21 +02:00
|
|
|
</section>
|
2016-05-10 12:36:54 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
var MyFilesPage = React.createClass({
|
2016-09-16 18:46:15 +02:00
|
|
|
_fileTimeout: null,
|
|
|
|
_fileInfoCheckNum: 0,
|
2016-09-23 11:56:01 +02:00
|
|
|
_filesOwnership: {},
|
2016-09-16 18:46:15 +02:00
|
|
|
|
2016-05-10 12:36:54 +02:00
|
|
|
getInitialState: function() {
|
|
|
|
return {
|
|
|
|
filesInfo: null,
|
2016-09-24 08:50:13 +02:00
|
|
|
filesOwnershipLoaded: false,
|
2016-09-16 18:46:15 +02:00
|
|
|
filesAvailable: {},
|
2016-05-10 12:36:54 +02:00
|
|
|
};
|
|
|
|
},
|
2016-09-23 11:56:01 +02:00
|
|
|
getDefaultProps: function() {
|
|
|
|
return {
|
|
|
|
show: null,
|
|
|
|
};
|
|
|
|
},
|
2016-08-08 00:13:17 +02:00
|
|
|
componentDidMount: function() {
|
|
|
|
document.title = "My Files";
|
|
|
|
},
|
2016-05-10 12:36:54 +02:00
|
|
|
componentWillMount: function() {
|
2016-09-23 11:56:01 +02:00
|
|
|
this.getFilesOwnership();
|
2016-05-14 14:26:54 +02:00
|
|
|
this.updateFilesInfo();
|
|
|
|
},
|
2016-08-08 02:57:12 +02:00
|
|
|
componentWillUnmount: function() {
|
2016-09-16 18:46:15 +02:00
|
|
|
if (this._fileTimeout)
|
2016-08-08 02:57:12 +02:00
|
|
|
{
|
2016-09-16 18:46:15 +02:00
|
|
|
clearTimeout(this._fileTimeout);
|
2016-08-08 02:57:12 +02:00
|
|
|
}
|
|
|
|
},
|
2016-09-23 11:56:01 +02:00
|
|
|
getFilesOwnership: function() {
|
|
|
|
lbry.getFilesInfo((filesInfo) => {
|
2016-10-20 02:29:35 +02:00
|
|
|
if (!filesInfo) {
|
|
|
|
this.setState({
|
|
|
|
filesOwnershipLoaded: true,
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-09-23 11:56:01 +02:00
|
|
|
var ownershipLoadedCount = 0;
|
|
|
|
for (let i = 0; i < filesInfo.length; i++) {
|
|
|
|
let fileInfo = filesInfo[i];
|
2016-09-24 10:41:31 +02:00
|
|
|
lbry.call('get_my_claim', {name: fileInfo.lbry_uri}, (claim) => {
|
2016-09-24 08:59:46 +02:00
|
|
|
this._filesOwnership[fileInfo.lbry_uri] = !!claim;
|
2016-09-23 11:56:01 +02:00
|
|
|
ownershipLoadedCount++;
|
|
|
|
if (ownershipLoadedCount >= filesInfo.length) {
|
2016-09-24 08:50:13 +02:00
|
|
|
this.setState({
|
|
|
|
filesOwnershipLoaded: true,
|
2016-09-24 10:41:31 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}, (claim) => {
|
|
|
|
this._filesOwnership[fileInfo.lbry_uri] = true;
|
|
|
|
ownershipLoadedCount++;
|
|
|
|
if (ownershipLoadedCount >= filesInfo.length) {
|
|
|
|
this.setState({
|
|
|
|
filesOwnershipLoaded: true,
|
2016-09-24 08:50:13 +02:00
|
|
|
});
|
2016-09-23 11:56:01 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2016-05-14 14:26:54 +02:00
|
|
|
updateFilesInfo: function() {
|
2016-05-10 12:36:54 +02:00
|
|
|
lbry.getFilesInfo((filesInfo) => {
|
2016-09-16 18:46:15 +02:00
|
|
|
if (!filesInfo) {
|
|
|
|
filesInfo = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(this._fileInfoCheckNum % 5)) {
|
|
|
|
// Time to update file availability status
|
|
|
|
|
|
|
|
for (let fileInfo of filesInfo) {
|
|
|
|
let name = fileInfo.lbry_uri;
|
|
|
|
|
2016-11-10 13:33:57 +01:00
|
|
|
if (name === null) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-11-11 14:17:43 +01:00
|
|
|
lbry.lighthouse.search(name, (results) => {
|
2016-09-16 18:46:15 +02:00
|
|
|
var result = results[0];
|
|
|
|
|
2016-09-24 08:41:53 +02:00
|
|
|
var available = result.name == name && result.available;
|
2016-09-16 18:46:15 +02:00
|
|
|
|
|
|
|
if (typeof this.state.filesAvailable[name] === 'undefined' || available != this.state.filesAvailable[name]) {
|
|
|
|
var newFilesAvailable = Object.assign({}, this.state.filesAvailable);
|
|
|
|
newFilesAvailable[name] = available;
|
|
|
|
this.setState({
|
|
|
|
filesAvailable: newFilesAvailable,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this._fileInfoCheckNum += 1;
|
|
|
|
|
2016-05-10 12:36:54 +02:00
|
|
|
this.setState({
|
2016-09-16 18:46:15 +02:00
|
|
|
filesInfo: filesInfo,
|
2016-05-10 12:36:54 +02:00
|
|
|
});
|
2016-09-16 18:46:15 +02:00
|
|
|
|
|
|
|
this._fileTimeout = setTimeout(() => { this.updateFilesInfo() }, 1000);
|
2016-05-10 12:36:54 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
render: function() {
|
2016-09-24 08:50:13 +02:00
|
|
|
if (this.state.filesInfo === null || !this.state.filesOwnershipLoaded) {
|
2016-08-20 03:48:08 +02:00
|
|
|
return (
|
|
|
|
<main className="page">
|
2016-08-21 16:55:32 +02:00
|
|
|
<BusyMessage message="Loading" />
|
2016-08-20 03:48:08 +02:00
|
|
|
</main>
|
|
|
|
);
|
2016-05-16 10:19:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.state.filesInfo.length) {
|
|
|
|
var content = <span>You haven't downloaded anything from LBRY yet. Go <Link href="/" label="search for your first download" />!</span>;
|
2016-05-10 12:36:54 +02:00
|
|
|
} else {
|
2016-08-07 17:27:00 +02:00
|
|
|
var content = [],
|
2016-08-07 17:29:08 +02:00
|
|
|
seenUris = {};
|
|
|
|
|
2016-05-16 10:19:41 +02:00
|
|
|
for (let fileInfo of this.state.filesInfo) {
|
2016-05-30 14:54:08 +02:00
|
|
|
let {completed, written_bytes, total_bytes, lbry_uri, file_name, download_path,
|
2016-08-07 17:27:00 +02:00
|
|
|
stopped, metadata} = fileInfo;
|
2016-07-26 15:02:28 +02:00
|
|
|
|
2016-09-24 10:21:07 +02:00
|
|
|
var isMine = this._filesOwnership[lbry_uri];
|
|
|
|
|
|
|
|
if (!metadata || seenUris[lbry_uri] || (this.props.show == 'downloaded' && isMine) ||
|
|
|
|
(this.props.show == 'published' && !isMine)) {
|
2016-07-26 15:02:28 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-08-07 17:29:08 +02:00
|
|
|
seenUris[lbry_uri] = true;
|
|
|
|
|
2016-06-27 22:38:08 +02:00
|
|
|
let {title, thumbnail} = metadata;
|
2016-05-16 10:19:41 +02:00
|
|
|
|
2016-08-03 12:43:10 +02:00
|
|
|
if (!fileInfo.pending && typeof metadata == 'object') {
|
|
|
|
var {title, thumbnail} = metadata;
|
|
|
|
var pending = false;
|
|
|
|
} else {
|
|
|
|
var title = null;
|
|
|
|
var thumbnail = null;
|
|
|
|
var pending = true;
|
|
|
|
}
|
|
|
|
|
2016-05-16 10:19:41 +02:00
|
|
|
var ratioLoaded = written_bytes / total_bytes;
|
2016-09-02 10:50:44 +02:00
|
|
|
|
|
|
|
var mediaType = lbry.getMediaType(metadata.content_type, file_name);
|
|
|
|
var showWatchButton = (mediaType == 'video');
|
2016-05-16 10:19:41 +02:00
|
|
|
|
2016-08-07 17:29:08 +02:00
|
|
|
content.push(<MyFilesRow key={lbry_uri} lbryUri={lbry_uri} title={title || ('lbry://' + lbry_uri)} completed={completed} stopped={stopped}
|
2016-05-30 14:54:08 +02:00
|
|
|
ratioLoaded={ratioLoaded} imgUrl={thumbnail} path={download_path}
|
2016-09-16 18:46:15 +02:00
|
|
|
showWatchButton={showWatchButton} pending={pending}
|
2016-09-24 10:21:07 +02:00
|
|
|
available={this.state.filesAvailable[lbry_uri]} isMine={isMine} />);
|
2016-05-10 12:36:54 +02:00
|
|
|
}
|
|
|
|
}
|
2016-05-16 10:19:41 +02:00
|
|
|
return (
|
2016-05-23 14:16:14 +02:00
|
|
|
<main className="page">
|
2016-08-08 05:31:21 +02:00
|
|
|
{content}
|
2016-05-16 10:19:41 +02:00
|
|
|
</main>
|
|
|
|
);
|
2016-05-10 12:36:54 +02:00
|
|
|
}
|
2016-06-27 22:38:08 +02:00
|
|
|
});
|