2017-08-24 15:50:14 +02:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import { findDOMNode } from 'react-dom';
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
import { push } from 'react-router-redux';
|
2017-09-07 08:19:11 +02:00
|
|
|
import {
|
|
|
|
Progress,
|
|
|
|
Card,
|
|
|
|
CardBlock,
|
|
|
|
CardTitle,
|
|
|
|
CardText,
|
|
|
|
FormGroup,
|
|
|
|
Label,
|
|
|
|
Input
|
|
|
|
} from 'reactstrap';
|
2017-08-24 15:50:14 +02:00
|
|
|
import fetch from 'isomorphic-fetch';
|
2017-09-07 08:19:11 +02:00
|
|
|
import bencode from 'bencode';
|
2017-09-08 09:47:09 +02:00
|
|
|
import moment from 'moment';
|
|
|
|
import ToggleContainer from './toggle_container';
|
2017-09-10 13:17:32 +02:00
|
|
|
import TorrentOptions from './torrent_options';
|
2017-08-24 15:50:14 +02:00
|
|
|
import ws_send from '../socket';
|
2017-09-10 14:29:43 +02:00
|
|
|
import DateDisplay from './date';
|
2017-09-07 08:19:11 +02:00
|
|
|
|
2017-08-24 15:50:14 +02:00
|
|
|
class AddTorrent extends Component {
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this.state = {
|
|
|
|
loading: false,
|
|
|
|
customize: false,
|
2017-09-07 08:19:11 +02:00
|
|
|
file: null,
|
2017-09-07 10:37:11 +02:00
|
|
|
magnet: null,
|
|
|
|
useMagnet: false,
|
2017-09-07 08:19:11 +02:00
|
|
|
torrent: null,
|
|
|
|
files: [],
|
2017-09-10 13:17:32 +02:00
|
|
|
start: true,
|
|
|
|
uploadThrottle: null,
|
|
|
|
downloadThrottle: null,
|
2017-09-07 08:31:29 +02:00
|
|
|
priority: 3,
|
2017-08-24 15:50:14 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-09-07 10:37:11 +02:00
|
|
|
componentDidMount() {
|
|
|
|
let { magnet } = this.props.match.params;
|
|
|
|
if (magnet) {
|
|
|
|
magnet = decodeURIComponent(magnet);
|
|
|
|
this.setState({ magnet, useMagnet: true });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-24 15:50:14 +02:00
|
|
|
async handleTransferOffer(offer, file) {
|
|
|
|
const headers = new Headers();
|
|
|
|
headers.append("Authorization", "Bearer " + offer.token);
|
2017-09-08 16:40:59 +02:00
|
|
|
const { socket } = this.props;
|
|
|
|
console.log(socket);
|
|
|
|
const a = document.createElement('a');
|
|
|
|
a.href = socket.uri;
|
2017-10-23 06:16:30 +02:00
|
|
|
const url = (a.protocol === "ws:" ? "http://" : "https://") + a.host + a.pathname;
|
2017-08-24 15:50:14 +02:00
|
|
|
try {
|
2017-09-08 16:40:59 +02:00
|
|
|
const resp = await fetch(url,
|
|
|
|
{
|
|
|
|
method: 'POST',
|
|
|
|
body: file,
|
|
|
|
headers: headers
|
|
|
|
}
|
|
|
|
);
|
2017-08-24 15:50:14 +02:00
|
|
|
} catch (ex) {
|
2017-09-07 08:19:11 +02:00
|
|
|
// TODO: something more useful
|
2017-08-24 15:50:14 +02:00
|
|
|
console.log(ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-07 09:56:47 +02:00
|
|
|
applyOptions(id) {
|
|
|
|
const {
|
|
|
|
priority,
|
|
|
|
uploadThrottle,
|
|
|
|
downloadThrottle
|
|
|
|
} = this.state;
|
|
|
|
const { dispatch } = this.props;
|
2017-12-29 20:34:53 +01:00
|
|
|
const customize =
|
2017-09-07 09:56:47 +02:00
|
|
|
priority !== 3 ||
|
2017-12-29 20:34:53 +01:00
|
|
|
uploadThrottle !== null ||
|
|
|
|
downloadThrottle !== null;
|
2017-09-07 09:56:47 +02:00
|
|
|
if (!customize) {
|
|
|
|
dispatch(push(`/torrents/${id}`));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ws_send("UPDATE_RESOURCE", {
|
|
|
|
resource: {
|
|
|
|
id,
|
|
|
|
priority,
|
|
|
|
throttle_up: uploadThrottle,
|
|
|
|
throttle_down: downloadThrottle
|
|
|
|
}
|
|
|
|
}, async done => {
|
2017-09-10 13:17:32 +02:00
|
|
|
if (this.state.start) {
|
2017-09-07 09:56:47 +02:00
|
|
|
ws_send("RESUME_TORRENT", { id });
|
|
|
|
}
|
|
|
|
dispatch(push(`/torrents/${id}`));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-08-24 15:50:14 +02:00
|
|
|
uploadFile() {
|
|
|
|
this.setState({ loading: true });
|
2017-09-10 13:17:32 +02:00
|
|
|
const { magnet, file, start } = this.state;
|
2017-08-24 15:50:14 +02:00
|
|
|
const { dispatch } = this.props;
|
2017-12-29 20:34:53 +01:00
|
|
|
const customize =
|
2017-09-07 09:56:47 +02:00
|
|
|
this.state.priority !== 3 ||
|
2017-12-29 20:34:53 +01:00
|
|
|
this.state.uploadThrottle !== null ||
|
|
|
|
this.state.downloadThrottle !== null;
|
2017-09-07 10:37:11 +02:00
|
|
|
const handleOffer = async offer => {
|
2017-09-07 08:19:11 +02:00
|
|
|
switch (offer.type) {
|
|
|
|
case "TRANSFER_OFFER":
|
|
|
|
return await this.handleTransferOffer(offer, file);
|
|
|
|
case "RESOURCES_EXTANT":
|
|
|
|
const [id] = offer.ids;
|
2017-09-07 09:56:47 +02:00
|
|
|
this.applyOptions.bind(this)(id);
|
2017-09-07 08:19:11 +02:00
|
|
|
break;
|
|
|
|
}
|
2017-09-07 10:37:11 +02:00
|
|
|
};
|
|
|
|
if (magnet) {
|
|
|
|
ws_send("UPLOAD_MAGNET", {
|
|
|
|
uri: magnet,
|
2017-09-10 13:17:32 +02:00
|
|
|
start: start && !customize
|
2017-09-07 10:37:11 +02:00
|
|
|
}, handleOffer);
|
|
|
|
} else {
|
|
|
|
ws_send("UPLOAD_TORRENT", {
|
|
|
|
size: file.size,
|
2017-09-10 13:17:32 +02:00
|
|
|
start: start && !customize
|
2017-09-07 10:37:11 +02:00
|
|
|
}, handleOffer);
|
|
|
|
}
|
2017-09-07 08:19:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
processTorrent(torrent) {
|
|
|
|
const { info } = torrent;
|
|
|
|
if (!info.files) {
|
|
|
|
this.setState({
|
|
|
|
files: [
|
|
|
|
{
|
|
|
|
name: info.name,
|
|
|
|
length: info.length
|
|
|
|
}
|
|
|
|
],
|
|
|
|
torrent
|
2017-08-24 15:50:14 +02:00
|
|
|
});
|
2017-09-07 08:19:11 +02:00
|
|
|
} else {
|
2017-09-08 09:48:18 +02:00
|
|
|
this.setState({
|
|
|
|
files: [/* TODO */],
|
|
|
|
torrent
|
|
|
|
});
|
2017-09-07 08:19:11 +02:00
|
|
|
}
|
2017-08-24 15:50:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
handleFile(e) {
|
|
|
|
const file = e.target.files[0];
|
2017-09-07 08:19:11 +02:00
|
|
|
const reader = new FileReader();
|
|
|
|
reader.onload = e => {
|
|
|
|
try {
|
|
|
|
const torrent = bencode.decode(reader.result, 'utf8');
|
|
|
|
this.processTorrent.bind(this)(torrent);
|
|
|
|
} catch (ex) {
|
|
|
|
// TODO: something meaningful
|
|
|
|
console.log(ex);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
reader.readAsArrayBuffer(file);
|
2017-08-24 15:50:14 +02:00
|
|
|
this.setState({ file });
|
|
|
|
}
|
|
|
|
|
2017-09-07 08:19:11 +02:00
|
|
|
renderOptions() {
|
2017-09-10 13:17:32 +02:00
|
|
|
const {
|
|
|
|
start,
|
|
|
|
priority,
|
|
|
|
downloadThrottle,
|
|
|
|
uploadThrottle
|
|
|
|
} = this.state;
|
|
|
|
|
2017-09-07 08:19:11 +02:00
|
|
|
return (
|
|
|
|
<Card>
|
|
|
|
<CardBlock>
|
2017-09-10 13:17:32 +02:00
|
|
|
<TorrentOptions
|
2017-09-10 14:21:08 +02:00
|
|
|
id="new-torrent"
|
2017-09-10 13:17:32 +02:00
|
|
|
start={start}
|
|
|
|
startChanged={start => this.setState({ start })}
|
|
|
|
priority={priority}
|
|
|
|
priorityChanged={priority => this.setState({ priority })}
|
|
|
|
downloadThrottle={downloadThrottle}
|
|
|
|
downloadThrottleChanged={downloadThrottle =>
|
|
|
|
this.setState({ downloadThrottle })}
|
|
|
|
uploadThrottle={uploadThrottle}
|
|
|
|
uploadThrottleChanged={uploadThrottle =>
|
|
|
|
{ console.log(uploadThrottle); this.setState({ uploadThrottle }); }}
|
2017-09-07 08:31:29 +02:00
|
|
|
/>
|
2017-09-07 08:19:11 +02:00
|
|
|
</CardBlock>
|
|
|
|
</Card>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
renderTorrent() {
|
2017-09-07 10:37:11 +02:00
|
|
|
const { magnet, torrent, file, files, loading } = this.state;
|
2017-09-07 08:19:11 +02:00
|
|
|
|
|
|
|
const details = {
|
|
|
|
"comment": d => d,
|
2017-09-10 14:29:43 +02:00
|
|
|
"creation date": d => <DateDisplay when={moment(new Date(d * 1000))} />,
|
2017-09-07 08:19:11 +02:00
|
|
|
"created by": d => d
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Card style={{marginBottom: "1rem"}}>
|
2017-09-07 10:37:11 +02:00
|
|
|
{torrent &&
|
|
|
|
<CardBlock>
|
|
|
|
<CardTitle>{magnet && "Magnet link" || file.name}</CardTitle>
|
|
|
|
<CardText>
|
|
|
|
<dl style={{marginBottom: "0"}}>
|
2017-09-08 09:54:51 +02:00
|
|
|
{Object.keys(details).map(key => {
|
|
|
|
const val = torrent[key];
|
|
|
|
if (!val) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
if (typeof val === "string" && !val.trim()) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return (
|
2017-09-07 10:37:11 +02:00
|
|
|
<div>
|
|
|
|
<dt>{key}</dt>
|
|
|
|
<dd>{details[key](torrent[key])}</dd>
|
|
|
|
</div>
|
2017-09-08 09:54:51 +02:00
|
|
|
);
|
|
|
|
})}
|
2017-09-07 10:37:11 +02:00
|
|
|
</dl>
|
|
|
|
</CardText>
|
|
|
|
</CardBlock>
|
|
|
|
}
|
2017-09-07 08:19:11 +02:00
|
|
|
<ToggleContainer className="form-group" title="Options">
|
|
|
|
{this.renderOptions.bind(this)()}
|
|
|
|
</ToggleContainer>
|
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
className="btn btn-primary btn-block"
|
2017-09-07 10:37:11 +02:00
|
|
|
disabled={(file || magnet) && loading}
|
2017-09-07 08:19:11 +02:00
|
|
|
onClick={this.uploadFile.bind(this)}
|
|
|
|
>Add torrent</button>
|
|
|
|
{loading ?
|
|
|
|
<Progress
|
|
|
|
value={100}
|
|
|
|
animated={true}
|
|
|
|
striped={true}
|
|
|
|
color="info"
|
|
|
|
className="progress-maxheight"
|
|
|
|
/> : null}
|
|
|
|
</Card>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-08-24 15:50:14 +02:00
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
<h3>Add torrent</h3>
|
2017-09-07 10:37:11 +02:00
|
|
|
{this.state.magnet && this.state.useMagnet &&
|
|
|
|
<p style={{
|
|
|
|
textOverflow: "ellipsis",
|
|
|
|
overflowX: "hidden",
|
|
|
|
whiteSpace: "nowrap"
|
|
|
|
}}>{this.state.magnet}</p>
|
|
|
|
}
|
|
|
|
{(this.state.torrent || this.state.magnet) && this.renderTorrent.bind(this)()}
|
2017-08-24 15:50:14 +02:00
|
|
|
<div className="form-group">
|
|
|
|
<input
|
|
|
|
style={{display: "none"}}
|
|
|
|
type="file"
|
|
|
|
accept=".torrent"
|
|
|
|
onChange={this.handleFile.bind(this)}
|
|
|
|
/>
|
2017-09-07 10:37:11 +02:00
|
|
|
{!this.state.useMagnet && (this.state.torrent ?
|
2017-09-07 08:19:11 +02:00
|
|
|
<div style={{
|
|
|
|
display: "flex",
|
|
|
|
flexDirection: "column",
|
|
|
|
alignItems: "center"
|
|
|
|
}}>
|
2017-08-24 15:50:14 +02:00
|
|
|
<button
|
|
|
|
type="button"
|
2017-09-07 08:19:11 +02:00
|
|
|
className="btn btn-default"
|
|
|
|
onClick={() => findDOMNode(this).querySelector("input[type='file']").click()}
|
|
|
|
>Select a different torrent?</button>
|
2017-08-24 15:50:14 +02:00
|
|
|
</div>
|
2017-09-07 08:19:11 +02:00
|
|
|
:
|
2017-09-07 10:37:11 +02:00
|
|
|
<div>
|
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
className="btn btn-default btn-block"
|
|
|
|
onClick={() => findDOMNode(this).querySelector("input[type='file']").click()}
|
|
|
|
>Select torrent</button>
|
|
|
|
<div className="text-centered" style={{margin: "1rem auto"}}>
|
|
|
|
- or -
|
|
|
|
</div>
|
|
|
|
<FormGroup>
|
|
|
|
<Input
|
|
|
|
type="text"
|
|
|
|
placeholder="Magnet link"
|
|
|
|
value={this.state.magnet}
|
|
|
|
onChange={e => this.setState({ magnet: e.target.value })}
|
|
|
|
/>
|
|
|
|
</FormGroup>
|
|
|
|
<button
|
|
|
|
type="button"
|
|
|
|
className="btn btn-default btn-block"
|
|
|
|
onClick={() => this.setState({ useMagnet: true })}
|
|
|
|
disabled={(() => {
|
|
|
|
const a = document.createElement("a");
|
|
|
|
a.href = this.state.magnet;
|
|
|
|
return a.protocol !== "magnet:";
|
|
|
|
})()}
|
|
|
|
>Add magnet</button>
|
|
|
|
</div>
|
|
|
|
)}
|
2017-08-24 15:50:14 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2017-08-24 14:30:22 +02:00
|
|
|
}
|
2017-08-24 15:50:14 +02:00
|
|
|
|
2017-09-08 16:40:59 +02:00
|
|
|
export default connect(s => ({ socket: s.socket }))(AddTorrent);
|