Make torrent options reusable

This commit is contained in:
Drew DeVault 2017-09-10 20:17:32 +09:00
parent a6dd7cc8bc
commit 176312617c
3 changed files with 187 additions and 165 deletions

View File

@ -10,6 +10,10 @@ export function convertToBitrate(value, unit) {
return value * Rates[unit]; return value * Rates[unit];
} }
export function convertFromBitrate(value, unit) {
return value / Rates[unit];
}
export function formatBitrate(bitrate) { export function formatBitrate(bitrate) {
if (bitrate > Rates["GiB/s"]) { if (bitrate > Rates["GiB/s"]) {
return `${(bitrate / Rates["GiB/s"]).toFixed(2)} GiB/s`; return `${(bitrate / Rates["GiB/s"]).toFixed(2)} GiB/s`;

View File

@ -16,129 +16,10 @@ import fetch from 'isomorphic-fetch';
import bencode from 'bencode'; import bencode from 'bencode';
import moment from 'moment'; import moment from 'moment';
import ToggleContainer from './toggle_container'; import ToggleContainer from './toggle_container';
import TorrentOptions from './torrent_options';
import ws_send from '../socket'; import ws_send from '../socket';
import { convertToBitrate } from '../bitrate';
import date from '../date'; import date from '../date';
class Throttle extends Component {
constructor() {
super();
this.state = {
strategy: "global",
unit: "MiB/s",
limit: 1
};
this.setStrategy = this.setStrategy.bind(this);
}
invokeChange() {
const { onChange } = this.props;
if (!onChange) {
return;
}
const { strategy, limit, unit } = this.state;
switch (strategy) {
case "global":
onChange(null);
break;
case "unlimited":
onChange(-1);
break;
default:
onChange(convertToBitrate(limit, unit));
break;
}
}
setStrategy(strategy) {
this.setState({ strategy });
this.invokeChange();
}
setLimit(limit) {
if (limit <= 0) {
this.setState({ limit: this.state.limit });
return;
}
this.setState({ limit });
this.invokeChange();
}
setUnit(unit) {
this.setState({ unit });
this.invokeChange();
}
render() {
const { legend, prop } = this.props;
return (
<div>
<FormGroup tag="fieldset">
<legend>{legend}</legend>
<FormGroup check className="form-check-inline">
<Label for={`${prop}-global`} check>
<Input
type="radio"
name={prop}
id={`${prop}-global`}
onChange={e => this.setStrategy("global")}
checked={this.state.strategy === "global"}
/> Global
</Label>
</FormGroup>
<FormGroup check className="form-check-inline">
<Label for={`${prop}-unlimited`} check>
<Input
type="radio"
name={prop}
id={`${prop}-unlimited`}
onChange={e => this.setStrategy("unlimited")}
checked={this.state.strategy === "unlimited"}
/> Unlimited
</Label>
</FormGroup>
<FormGroup check className="form-check-inline">
<Label for={`${prop}-custom`} check>
<Input
type="radio"
name={prop}
id={`${prop}-custom`}
onChange={e => this.setStrategy("custom")}
checked={this.state.strategy === "custom"}
/> Custom
</Label>
</FormGroup>
</FormGroup>
{this.state.strategy === "custom" &&
<div className="row">
<FormGroup className="col-md-6">
<Input
type="number"
value={this.state.limit}
onChange={e => this.setLimit(parseFloat(e.target.value))}
/>
</FormGroup>
<FormGroup className="col-md-6">
<Input
type="select"
id="unit"
value={this.state.unit}
onChange={e => this.setUnit(e.target.value)}
>
<option value="b/s">b/s</option>
<option value="KiB/s">KiB/s</option>
<option value="MiB/s">MiB/s</option>
<option value="GiB/s">GiB/s</option>
</Input>
</FormGroup>
</div>
}
</div>
);
}
}
class AddTorrent extends Component { class AddTorrent extends Component {
constructor() { constructor() {
super(); super();
@ -150,9 +31,9 @@ class AddTorrent extends Component {
useMagnet: false, useMagnet: false,
torrent: null, torrent: null,
files: [], files: [],
startImmediately: true, start: true,
uploadThrottle: -1, uploadThrottle: null,
downloadThrottle: -1, downloadThrottle: null,
priority: 3, priority: 3,
}; };
} }
@ -210,7 +91,7 @@ class AddTorrent extends Component {
throttle_down: downloadThrottle throttle_down: downloadThrottle
} }
}, async done => { }, async done => {
if (this.state.startImmediately) { if (this.state.start) {
ws_send("RESUME_TORRENT", { id }); ws_send("RESUME_TORRENT", { id });
} }
dispatch(push(`/torrents/${id}`)); dispatch(push(`/torrents/${id}`));
@ -219,7 +100,7 @@ class AddTorrent extends Component {
uploadFile() { uploadFile() {
this.setState({ loading: true }); this.setState({ loading: true });
const { magnet, file, startImmediately } = this.state; const { magnet, file, start } = this.state;
const { dispatch } = this.props; const { dispatch } = this.props;
const customize = // TODO: File options const customize = // TODO: File options
this.state.priority !== 3 || this.state.priority !== 3 ||
@ -238,12 +119,12 @@ class AddTorrent extends Component {
if (magnet) { if (magnet) {
ws_send("UPLOAD_MAGNET", { ws_send("UPLOAD_MAGNET", {
uri: magnet, uri: magnet,
start: startImmediately && !customize start: start && !customize
}, handleOffer); }, handleOffer);
} else { } else {
ws_send("UPLOAD_TORRENT", { ws_send("UPLOAD_TORRENT", {
size: file.size, size: file.size,
start: startImmediately && !customize start: start && !customize
}, handleOffer); }, handleOffer);
} }
} }
@ -285,47 +166,27 @@ class AddTorrent extends Component {
} }
renderOptions() { renderOptions() {
const {
start,
priority,
downloadThrottle,
uploadThrottle
} = this.state;
return ( return (
<Card> <Card>
<CardBlock> <CardBlock>
<FormGroup> <TorrentOptions
<Label for="start-immediately" check style={{paddingLeft: 0}}> start={start}
<input startChanged={start => this.setState({ start })}
type="checkbox" priority={priority}
checked={this.state.startImmediately} priorityChanged={priority => this.setState({ priority })}
onChange={e => this.setState({ downloadThrottle={downloadThrottle}
startImmediately: !this.state.startImmediately downloadThrottleChanged={downloadThrottle =>
})} this.setState({ downloadThrottle })}
id="start-immediately" uploadThrottle={uploadThrottle}
/> Start immediately uploadThrottleChanged={uploadThrottle =>
</Label> { console.log(uploadThrottle); this.setState({ uploadThrottle }); }}
</FormGroup>
<FormGroup>
<Label for="priority">Priority</Label>
<Input
type="select"
id="priority"
value={this.state.priority}
onChange={e =>
this.setState({ priority: parseInt(e.target.value)})
}
>
<option value="1">Lowest</option>
<option value="2">Low</option>
<option value="3">Normal</option>
<option value="4">High</option>
<option value="5">Highest</option>
</Input>
</FormGroup>
<Throttle
prop="dl-throttle"
legend="Download throttle"
onChange={limit => this.setState({ downloadThrottle: limit })}
/>
<Throttle
prop="ul-throttle"
legend="Upload throttle"
onChange={limit => this.setState({ uploadThrottle: limit })}
/> />
</CardBlock> </CardBlock>
</Card> </Card>

157
src/ui/torrent_options.js Normal file
View File

@ -0,0 +1,157 @@
import React, { Component } from 'react';
import {
FormGroup,
Label,
Input
} from 'reactstrap';
import { convertFromBitrate, convertToBitrate } from '../bitrate';
class Throttle extends Component {
constructor() {
super();
this.setLimit = this.setLimit.bind(this);
this.setUnit = this.setUnit.bind(this);
this.state = { unit: "MiB/s" };
}
setLimit(limit) {
const { onChange } = this.props;
const { unit } = this.state;
const converted = limit <= 0 || limit === null ?
limit : convertToBitrate(limit, unit);
onChange && onChange(converted);
}
setUnit(unit) {
const limit = convertFromBitrate(this.props.limit, this.state.unit);
this.setState({ unit });
this.setLimit(limit);
}
render() {
const { limit, legend, prop } = this.props;
const { unit } = this.state;
return (
<div>
<FormGroup tag="fieldset">
<legend>{legend}</legend>
<FormGroup check className="form-check-inline">
<Label for={`${prop}-global`} check>
<Input
type="radio"
name={prop}
id={`${prop}-global`}
onChange={e => this.setLimit(null)}
checked={limit === null}
/> Global
</Label>
</FormGroup>
<FormGroup check className="form-check-inline">
<Label for={`${prop}-unlimited`} check>
<Input
type="radio"
name={prop}
id={`${prop}-unlimited`}
onChange={e => this.setLimit(-1)}
checked={limit === -1}
/> Unlimited
</Label>
</FormGroup>
<FormGroup check className="form-check-inline">
<Label for={`${prop}-custom`} check>
<Input
type="radio"
name={prop}
id={`${prop}-custom`}
onChange={e => this.setLimit(1)}
checked={limit !== -1 && limit !== null}
/> Custom
</Label>
</FormGroup>
</FormGroup>
{limit !== -1 && limit !== null &&
<div className="row">
<FormGroup className="col-md-6">
<Input
type="number"
value={convertFromBitrate(limit, unit)}
onChange={e => this.setLimit(parseFloat(e.target.value))}
/>
</FormGroup>
<FormGroup className="col-md-6">
<Input
type="select"
id="unit"
value={unit}
onChange={e => this.setUnit(e.target.value)}
>
<option value="b/s">b/s</option>
<option value="KiB/s">KiB/s</option>
<option value="MiB/s">MiB/s</option>
<option value="GiB/s">GiB/s</option>
</Input>
</FormGroup>
</div>
}
</div>
);
}
}
export default class TorrentOptions extends Component {
render() {
const {
start,
startChanged,
priority,
priorityChanged,
downloadThrottle,
downloadThrottleChanged,
uploadThrottle,
uploadThrottleChanged,
} = this.props;
return (
<div>
{typeof start !== undefined &&
<FormGroup>
<Label for="start-immediately" check style={{paddingLeft: 0}}>
<input
type="checkbox"
checked={start}
onChange={e => startChanged(!start)}
id="start-immediately"
/> Start immediately
</Label>
</FormGroup>
}
<FormGroup>
<Label for="priority">Priority</Label>
<Input
type="select"
id="priority"
value={priority}
onChange={e => priorityChanged(parseInt(e.target.value))}
>
<option value="1">Lowest</option>
<option value="2">Low</option>
<option value="3">Normal</option>
<option value="4">High</option>
<option value="5">Highest</option>
</Input>
</FormGroup>
<Throttle
prop="dl-throttle"
legend="Download throttle"
limit={downloadThrottle}
onChange={limit => downloadThrottleChanged(limit)}
/>
<Throttle
prop="ul-throttle"
legend="Upload throttle"
limit={uploadThrottle}
onChange={limit => uploadThrottleChanged(limit)}
/>
</div>
);
}
}