mirror of
https://github.com/zoriya/flood.git
synced 2026-06-04 03:27:15 +00:00
Add smart ETA calculator
This commit is contained in:
+100
-21
@@ -121,14 +121,20 @@ var mapProps = function(props, data) {
|
||||
return mappedObject;
|
||||
};
|
||||
|
||||
var createMulticallRequest = function(data) {
|
||||
var createMulticallRequest = function(data, params) {
|
||||
|
||||
params = params || [];
|
||||
|
||||
var methodCall = [];
|
||||
|
||||
if (!util.isArray(data)) {
|
||||
data = [data];
|
||||
}
|
||||
|
||||
for (i = 0, len = data.length; i < len; i++) {
|
||||
methodCall.push({
|
||||
'methodName': data[i],
|
||||
'params': []
|
||||
'params': params
|
||||
});
|
||||
}
|
||||
|
||||
@@ -142,15 +148,78 @@ client.prototype.getTorrentList = function(callback) {
|
||||
rTorrent.get('d.multicall', defaults.torrentPropertyMethods)
|
||||
.then(function(data) {
|
||||
|
||||
// create torrent array, each item in the array being
|
||||
// an object with human-readable property values
|
||||
var torrents = mapProps(defaults.torrentProperties, data, 'torrent-list');
|
||||
try {
|
||||
|
||||
// add percent complete
|
||||
Object.keys(torrents).map(function(hash) {
|
||||
// create torrent array, each item in the array being
|
||||
// an object with human-readable property values
|
||||
var torrents = mapProps(defaults.torrentProperties, data, 'torrent-list');
|
||||
|
||||
torrents[hash]['percentComplete'] = (torrents[hash]['bytesDone'] / torrents[hash]['sizeBytes'] * 100).toFixed(2);
|
||||
});
|
||||
// add percent complete
|
||||
Object.keys(torrents).map(function(hash) {
|
||||
|
||||
var torrent = torrents[hash];
|
||||
var percentComplete = (torrent['bytesDone'] / torrent['sizeBytes'] * 100).toFixed(2);
|
||||
|
||||
var eta = function() {
|
||||
|
||||
if (torrent['downloadRate'] > 0) {
|
||||
|
||||
var seconds = (torrent['sizeBytes'] - torrent['bytesDone']) / torrent['downloadRate'];
|
||||
var years = Math.floor(seconds / 31536000);
|
||||
var weeks = Math.floor((seconds % 31536000) / 604800);
|
||||
var days = Math.floor(((seconds % 31536000) % 604800) / 86400);
|
||||
var hours = Math.floor((((seconds % 31536000) % 604800) % 86400) / 3600);
|
||||
var minutes = Math.floor(((((seconds % 31536000) % 604800) % 86400) % 3600) / 60);
|
||||
var wholeSeconds = Math.floor((((((seconds % 31536000) % 604800) % 86400) % 3600) % 60) / 60);
|
||||
var timeRemaining = {};
|
||||
|
||||
if (years > 0) {
|
||||
timeRemaining = {
|
||||
years: years,
|
||||
weeks: weeks
|
||||
}
|
||||
} else if (weeks > 0) {
|
||||
timeRemaining = {
|
||||
weeks: weeks,
|
||||
days: days
|
||||
}
|
||||
} else if (days > 0) {
|
||||
timeRemaining = {
|
||||
days: days,
|
||||
hours: hours
|
||||
}
|
||||
} else if (hours > 0) {
|
||||
timeRemaining = {
|
||||
hours: hours,
|
||||
minutes: minutes
|
||||
}
|
||||
} else if (minutes > 0) {
|
||||
timeRemaining = {
|
||||
minutes: minutes,
|
||||
seconds: wholeSeconds
|
||||
}
|
||||
} else {
|
||||
timeRemaining = {
|
||||
seconds: wholeSeconds
|
||||
}
|
||||
}
|
||||
|
||||
return timeRemaining;
|
||||
|
||||
} else {
|
||||
|
||||
return 'Infinity';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
torrent['percentComplete'] = percentComplete;
|
||||
torrent['eta'] = eta();
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
callback(null, torrents);
|
||||
}, function(error) {
|
||||
@@ -165,31 +234,41 @@ client.prototype.getTorrentList = function(callback) {
|
||||
|
||||
client.prototype.stopTorrent = function(hash, callback) {
|
||||
|
||||
hash = hash.split(',');
|
||||
|
||||
if (!util.isArray(hash)) {
|
||||
hash = [hash];
|
||||
}
|
||||
|
||||
rTorrent.get('d.stop', hash).then(function(data) {
|
||||
callback(null, data);
|
||||
}, function(error) {
|
||||
console.log(error);
|
||||
callback(error, null);
|
||||
});
|
||||
for (i = 0, len = hash.length; i < len; i++) {
|
||||
|
||||
rTorrent.get('d.stop', [hash[i]]).then(function(data) {
|
||||
callback(null, data);
|
||||
}, function(error) {
|
||||
callback(error, null);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
client.prototype.startTorrent = function(hash, callback) {
|
||||
|
||||
hash = hash.split(',');
|
||||
|
||||
if (!util.isArray(hash)) {
|
||||
hash = [hash];
|
||||
}
|
||||
|
||||
rTorrent.get('d.start', hash).then(function(data) {
|
||||
callback(null, data);
|
||||
}, function(error) {
|
||||
console.log(error);
|
||||
callback(error, null);
|
||||
});
|
||||
for (i = 0, len = hash.length; i < len; i++) {
|
||||
|
||||
rTorrent.get('d.start', [hash[i]]).then(function(data) {
|
||||
callback(null, data);
|
||||
}, function(error) {
|
||||
callback(error, null);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
}
|
||||
|
||||
&--primary {
|
||||
flex: 1;
|
||||
|
||||
.torrent & {
|
||||
color: $torrent--primary--foreground;
|
||||
@@ -66,6 +67,7 @@
|
||||
|
||||
&--secondary {
|
||||
display: flex;
|
||||
flex: 2;
|
||||
font-size: 0.85em;
|
||||
|
||||
&--sub {
|
||||
|
||||
@@ -15,12 +15,12 @@ var performAction = function(action, hash, success, error) {
|
||||
console.error(torrentsData, status, err.toString());
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var TorrentActions = {
|
||||
|
||||
click: function(hash) {
|
||||
|
||||
AppDispatcher.dispatch({
|
||||
actionType: TorrentConstants.TORRENT_CLICK,
|
||||
hash: hash
|
||||
|
||||
@@ -1,15 +1,30 @@
|
||||
var React = require('react');
|
||||
var Action = require('./Action');
|
||||
var UIStore = require('../../stores/UIStore');
|
||||
var TorrentActions = require('../../actions/TorrentActions');
|
||||
|
||||
var getSelectedTorrents = function() {
|
||||
|
||||
return {
|
||||
selectedTorrents: UIStore.getSelectedTorrents()
|
||||
}
|
||||
};
|
||||
|
||||
var FilterBar = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
|
||||
return null;
|
||||
return {
|
||||
selectedTorrents: []
|
||||
};
|
||||
},
|
||||
|
||||
handleClick: function(event) {
|
||||
console.log('click ' + event.target);
|
||||
componentDidMount: function() {
|
||||
UIStore.addChangeListener(this._onUIStoreChange);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
TorrentStore.removeChangeListener(this._onUIStoreChange);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@@ -17,13 +32,30 @@ var FilterBar = React.createClass({
|
||||
return (
|
||||
<nav className="action-bar">
|
||||
<ul className="actions">
|
||||
<Action label="Start Torrent" slug="start-torrent" icon="start" clickHandler={this.handleClick} />
|
||||
<Action label="Stop Torrent" slug="stop-torrent" icon="stop" clickHandler={this.handleClick} />
|
||||
<Action label="Pause Torrent" slug="pause-torrent" icon="pause" clickHandler={this.handleClick} />
|
||||
<Action label="Start Torrent" slug="start-torrent" icon="start" clickHandler={this._start} />
|
||||
<Action label="Stop Torrent" slug="stop-torrent" icon="stop" clickHandler={this._stop} />
|
||||
<Action label="Pause Torrent" slug="pause-torrent" icon="pause" clickHandler={this._pause} />
|
||||
</ul>
|
||||
</nav>
|
||||
);
|
||||
},
|
||||
|
||||
_pause: function() {
|
||||
|
||||
},
|
||||
|
||||
_start: function() {
|
||||
TorrentActions.start(this.state.selectedTorrents);
|
||||
},
|
||||
|
||||
_stop: function() {
|
||||
TorrentActions.stop(this.state.selectedTorrents);
|
||||
},
|
||||
|
||||
_onUIStoreChange: function() {
|
||||
this.setState(getSelectedTorrents);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -24,37 +24,95 @@ var Torrent = React.createClass({
|
||||
var uploadTotal = format.data(torrent.uploadTotal);
|
||||
var downloadRate = format.data(torrent.downloadRate, '/s');
|
||||
var downloadTotal = format.data(torrent.downloadTotal);
|
||||
var completed = format.data(torrent.bytesDone);
|
||||
var totalSize = format.data(torrent.sizeBytes);
|
||||
|
||||
var eta = (function() {
|
||||
|
||||
if (torrent.eta === 'Infinity') {
|
||||
return '∞';
|
||||
} else if (torrent.eta.years > 0) {
|
||||
return (
|
||||
<span>
|
||||
{torrent.eta.years}<em className="unit">y</em>
|
||||
</span>
|
||||
);
|
||||
} else if (torrent.eta.weeks > 0) {
|
||||
return (
|
||||
<span>
|
||||
{torrent.eta.weeks}<em className="unit">w</em>
|
||||
{torrent.eta.days}<em className="unit">d</em>
|
||||
</span>
|
||||
);
|
||||
} else if (torrent.eta.days > 0) {
|
||||
return (
|
||||
<span>
|
||||
{torrent.eta.days}<em className="unit">d</em>
|
||||
{torrent.eta.hours}<em className="unit">h</em>
|
||||
</span>
|
||||
);
|
||||
} else if (torrent.eta.hours > 0) {
|
||||
return (
|
||||
<span>
|
||||
{torrent.eta.hours}<em className="unit">h</em>
|
||||
{torrent.eta.minutes}<em className="unit">m</em>
|
||||
</span>
|
||||
);
|
||||
} else if (torrent.eta.minutes > 0) {
|
||||
return (
|
||||
<span>
|
||||
{torrent.eta.minutes}<em className="unit">m</em>
|
||||
{torrent.eta.seconds}<em className="unit">s</em>
|
||||
</span>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<span>
|
||||
{torrent.eta.seconds}<em className="unit">s</em>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
return (
|
||||
<li className={classes} onClick={this._onClick}>
|
||||
<div className="torrent__details">
|
||||
<span className="torrent__detail--primary">{torrent.name}</span>
|
||||
<span className="torrent__detail--primary">{torrent.name}: {torrent.state}</span>
|
||||
<ul className="torrent__detail--list torrent__detail--secondary">
|
||||
<li className="torrent__detail--secondary--sub">{torrent.state}</li>
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
{uploadRate.value}
|
||||
<em className="unit">{uploadRate.unit}</em>
|
||||
</li>
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
{uploadTotal.value}
|
||||
<em className="unit">{uploadTotal.unit}</em>
|
||||
</li>
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
{downloadRate.value}
|
||||
<em className="unit">{downloadRate.unit}</em>
|
||||
</li>
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
{downloadTotal.value}
|
||||
<em className="unit">{downloadTotal.unit}</em>
|
||||
{eta}
|
||||
</li>
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
<span>
|
||||
{torrent.percentComplete}
|
||||
<em className="unit">%</em>
|
||||
</span>
|
||||
<span>
|
||||
{completed.value}
|
||||
<em className="unit">{completed.unit}</em>
|
||||
</span>
|
||||
</li>
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
{totalSize.value}
|
||||
<em className="unit">{totalSize.unit}</em>
|
||||
</li>
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
{torrent.ratio}
|
||||
</li>
|
||||
<li className="torrent__detail--secondary--sub" onClick={this._onStart}>
|
||||
Start
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
Prs
|
||||
</li>
|
||||
<li className="torrent__detail--secondary--sub" onClick={this._onStop}>
|
||||
Stop
|
||||
<li className="torrent__detail--secondary--sub">
|
||||
Sds
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -65,15 +123,8 @@ var Torrent = React.createClass({
|
||||
|
||||
_onClick: function() {
|
||||
TorrentActions.click(this.props.data.hash);
|
||||
},
|
||||
|
||||
_onStop: function() {
|
||||
TorrentActions.stop(this.props.data.hash);
|
||||
},
|
||||
|
||||
_onStart: function() {
|
||||
TorrentActions.start(this.props.data.hash);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = Torrent;
|
||||
|
||||
@@ -15,7 +15,7 @@ var getSelectedTorrents = function() {
|
||||
return {
|
||||
selectedTorrents: UIStore.getSelectedTorrents()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var TorrentList = React.createClass({
|
||||
|
||||
@@ -61,14 +61,14 @@ var TorrentList = React.createClass({
|
||||
<header className="torrent__header">
|
||||
<span className="torrent__detail--primary">Name</span>
|
||||
<div className="torrent__detail--secondary">
|
||||
<span className="torrent__detail--secondary--sub">State</span>
|
||||
<span className="torrent__detail--secondary--sub">Up</span>
|
||||
<span className="torrent__detail--secondary--sub"> </span>
|
||||
<span className="torrent__detail--secondary--sub">Down</span>
|
||||
<span className="torrent__detail--secondary--sub"> </span>
|
||||
<span className="torrent__detail--secondary--sub">ETA</span>
|
||||
<span className="torrent__detail--secondary--sub">Completed</span>
|
||||
<span className="torrent__detail--secondary--sub">Size</span>
|
||||
<span className="torrent__detail--secondary--sub">Ratio</span>
|
||||
<span className="torrent__detail--secondary--sub">Start</span>
|
||||
<span className="torrent__detail--secondary--sub">Stop</span>
|
||||
<span className="torrent__detail--secondary--sub">Peers</span>
|
||||
<span className="torrent__detail--secondary--sub">Seeds</span>
|
||||
</div>
|
||||
</header>
|
||||
{torrentList}
|
||||
|
||||
Reference in New Issue
Block a user