From 5261b475c1ab8cdf711a618bf1ca233f750b4a8c Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 24 Aug 2017 22:32:42 -0400 Subject: [PATCH] Flesh out torrent detail view --- scss/main.scss | 15 ++++ src/reducers/files.js | 24 +++++++ src/reducers/index.js | 2 + src/ui/torrent_details.js | 144 +++++++++++++++++++++++++++++++++++--- src/ui/torrent_table.js | 2 +- 5 files changed, 175 insertions(+), 12 deletions(-) create mode 100644 src/reducers/files.js diff --git a/scss/main.scss b/scss/main.scss index c8ea8e3..f7d2557 100644 --- a/scss/main.scss +++ b/scss/main.scss @@ -88,3 +88,18 @@ } } } + +.btn-very-sm { + padding: 0 0.75rem; + line-height: 1; +} + +.btn-group { + display: flex; + justify-content: space-between; + margin-bottom: 1rem; + + .btn-group { + margin-bottom: 0; + } +} diff --git a/src/reducers/files.js b/src/reducers/files.js new file mode 100644 index 0000000..6b1b068 --- /dev/null +++ b/src/reducers/files.js @@ -0,0 +1,24 @@ +import { + UPDATE_RESOURCES, + RESOURCES_REMOVED +} from '../actions/resources'; + +export default function files(state = {}, action) { + switch (action.type) { + case UPDATE_RESOURCES: + return { + ...state, + ...action.resources + .filter(r => r.type === "file") + .reduce((s, r) => ({ + ...s, + [r.id]: { ...state[r.id], ...r } + }), {}) + }; + case RESOURCES_REMOVED: + return Object.values(state) + .filter(r => action.ids.indexOf(r.id) === -1) + .reduce((s, r) => ({ ...s, [r.id]: r }), {}); + } + return state; +} diff --git a/src/reducers/index.js b/src/reducers/index.js index 709c0f6..ba1dc2b 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -3,11 +3,13 @@ import { routerReducer } from 'react-router-redux' import subscribe from './subscribe'; import filter_subscribe from './filter_subscribe'; import torrents from './torrents'; +import files from './files'; const root = combineReducers({ subscribe, filter_subscribe, torrents, + files, router: routerReducer }); diff --git a/src/ui/torrent_details.js b/src/ui/torrent_details.js index e69af7f..bb6fb8d 100644 --- a/src/ui/torrent_details.js +++ b/src/ui/torrent_details.js @@ -1,26 +1,140 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import { activeTorrents } from '../torrent_state'; +import FontAwesome from 'react-fontawesome'; import { - Button, ButtonGroup, ButtonDropdown, DropdownToggle, DropdownMenu, - DropdownItem + DropdownItem, + Collapse, + Card, + CardBlock, + Progress } from 'reactstrap'; +import ws_send from '../socket'; // TODO: use component lifecycle functions here to invoke // torrent_state.updateSubscriptions +// TODO: fix navigating directly to torrent pages -function Torrent(props) { +function File({ file }) { + // TODO: show progress bar + // TODO: edit priority return ( -
-

{props.torrent.name}

-
+ + {file.path} + {file.priority} + {file.availability} + ); } +// TODO: move to separate component +function CollapseToggle({ text, onToggle, open }) { + return ( + + ); +} + +class Torrent extends Component { + constructor() { + super(); + this.state = { + infoShown: false, + filesShown: false, + trackersShown: false, + peersShown: false + }; + } + + toggleTorrentState(torrent) { + if (torrent.status === "paused") { + ws_send("RESUME_TORRENT", { id: torrent.id }); + } else { + ws_send("PAUSE_TORRENT", { id: torrent.id }); + } + } + + render() { + const { torrent, files } = this.props; + const status = s => s[0].toUpperCase() + s.slice(1); + + return ( +
+

{torrent.name}

+ + {(torrent.progress * 100).toFixed(0)}% + +

+ State: + + {status(torrent.status)} + + +

+ + this.setState({ infoShown: !this.state.infoShown })} + open={this.state.infoShown} + /> + this.setState({ filesShown: !this.state.filesShown })} + open={this.state.filesShown} + /> + this.setState({ trackersShown: !this.state.trackersShown })} + open={this.state.trackersShown} + /> + this.setState({ peersShown: !this.state.peersShown })} + open={this.state.peersShown} + /> + + +
+
Downloading to
+
{torrent.path}
+
Created
+
{torrent.created}
+
+
+ + + + + + {files.map(file => )} + +
+
+
+
+
+ ); + } +} + class TorrentDetails extends Component { constructor() { super(); @@ -34,13 +148,13 @@ class TorrentDetails extends Component {

{active.length} torrents

- {' '} - {' '} + + this.setState({ removeDropdown: !this.state.removeDropdown })} > - + Remove @@ -56,10 +170,17 @@ class TorrentDetails extends Component { render() { const active = activeTorrents(); const { torrents } = this.props; + const { files } = this.props; + const _files = Object.values(files).reduce((s, f) => ({ + ...s, [f.torrent_id]: [...(s[f.torrent_id] || []), f] + }), {}); return (
{active.length > 1 ? this.renderHeader(active) : null} - {active.map(id => )} + {active.map(id => )}
); } @@ -67,5 +188,6 @@ class TorrentDetails extends Component { export default connect(state => ({ router: state.router, - torrents: state.torrents + torrents: state.torrents, + files: state.files }))(TorrentDetails); diff --git a/src/ui/torrent_table.js b/src/ui/torrent_table.js index e582ded..6dee8ef 100644 --- a/src/ui/torrent_table.js +++ b/src/ui/torrent_table.js @@ -33,7 +33,7 @@ class TorrentTable extends Component { {Object.values(torrents).map(t =>