mirror of
https://github.com/zoriya/flood.git
synced 2026-05-28 17:33:15 +00:00
Move from Redux to vanilla Flux
This commit is contained in:
@@ -1,79 +0,0 @@
|
||||
import {connect} from 'react-redux';
|
||||
import React from 'react';
|
||||
|
||||
import Action from '../components/action-bar/Action';
|
||||
import {addTorrent, startTorrent, stopTorrent} from '../actions/ClientActions';
|
||||
import {displayModal} from '../actions/UIActions';
|
||||
import {setTorrentsSort} from '../actions/UIActions';
|
||||
import SortDropdown from '../components/action-bar/SortDropdown';
|
||||
import uiSelector from '../selectors/uiSelector';
|
||||
|
||||
const methodsToBind = [
|
||||
'handleAddTorrents',
|
||||
'handleSortChange',
|
||||
'handleStart',
|
||||
'handleStop'
|
||||
];
|
||||
|
||||
class ActionBar extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
selectedTorrents: []
|
||||
};
|
||||
|
||||
methodsToBind.forEach((method) => {
|
||||
this[method] = this[method].bind(this);
|
||||
});
|
||||
}
|
||||
|
||||
handleAddTorrents() {
|
||||
this.props.dispatch(displayModal({
|
||||
modal: 'add-torrents'
|
||||
}));
|
||||
}
|
||||
|
||||
handleSortChange(sortBy) {
|
||||
this.props.dispatch(setTorrentsSort({
|
||||
sortBy
|
||||
}));
|
||||
}
|
||||
|
||||
handleStart() {
|
||||
this.props.dispatch(startTorrent(this.props.torrentList.selected));
|
||||
}
|
||||
|
||||
handleStop() {
|
||||
this.props.dispatch(stopTorrent(this.props.torrentList.selected));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<nav className="action-bar">
|
||||
<div className="actions action-bar__item action-bar__item--sort-torrents">
|
||||
<SortDropdown onSortChange={this.handleSortChange}
|
||||
selectedItem={this.props.torrentList.sortBy} />
|
||||
</div>
|
||||
<div className="actions action-bar__item action-bar__item--torrent-operations">
|
||||
<div className="action-bar__group">
|
||||
<Action label="Start Torrent" slug="start-torrent" icon="start"
|
||||
clickHandler={this.handleStart} />
|
||||
<Action label="Stop Torrent" slug="stop-torrent" icon="stop"
|
||||
clickHandler={this.handleStop} />
|
||||
<Action label="Pause Torrent" slug="pause-torrent" icon="pause"
|
||||
clickHandler={this.handlePause} />
|
||||
</div>
|
||||
<div className="action-bar__group action-bar__group--has-divider">
|
||||
<Action label="Add Torrent" slug="add-torrent" icon="add"
|
||||
clickHandler={this.handleAddTorrents} />
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(uiSelector)(ActionBar);
|
||||
@@ -1,26 +1,21 @@
|
||||
import {connect} from 'react-redux';
|
||||
import React from 'react';
|
||||
|
||||
import ActionBar from '../containers/ActionBar';
|
||||
import ActionBar from '../components/action-bar/ActionBar';
|
||||
import Modals from '../components/modals/Modals';
|
||||
import Sidebar from './Sidebar';
|
||||
import rootSelector from '../selectors/rootSelector';
|
||||
import TorrentList from '../containers/TorrentList';
|
||||
import TorrentListHeader from '../components/torrent-list/TorrentListHeader';
|
||||
import Sidebar from '../components/sidebar/Sidebar';
|
||||
import TorrentListContainer from '../components/torrent-list/TorrentListContainer';
|
||||
|
||||
export default class FloodApp extends React.Component {
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="flood">
|
||||
<Sidebar />
|
||||
<main className="content">
|
||||
<ActionBar />
|
||||
<TorrentList />
|
||||
<TorrentListContainer />
|
||||
</main>
|
||||
<Modals />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import {connect} from 'react-redux';
|
||||
import React from 'react';
|
||||
|
||||
import ClientStats from '../components/sidebar/ClientStats';
|
||||
import {setTorrentsFilter, setTorrentsSearch} from '../actions/UIActions';
|
||||
import StatusFilters from '../components/sidebar/StatusFilters';
|
||||
import SearchBox from '../components/sidebar/SearchBox';
|
||||
import UIActions from '../actions/UIActions';
|
||||
import uiSelector from '../selectors/uiSelector';
|
||||
|
||||
const methodsToBind = [
|
||||
'handleFilterChange',
|
||||
'handleSearchChange'
|
||||
];
|
||||
|
||||
class Sidebar extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
methodsToBind.forEach((method) => {
|
||||
this[method] = this[method].bind(this);
|
||||
});
|
||||
}
|
||||
|
||||
handleFilterChange(value) {
|
||||
this.props.dispatch(setTorrentsFilter(value));
|
||||
}
|
||||
|
||||
handleSearchChange(value) {
|
||||
this.props.dispatch(setTorrentsSearch(value));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<aside className="sidebar">
|
||||
<ClientStats transferData={this.props.transferData} />
|
||||
<SearchBox handleSearchChange={this.handleSearchChange} />
|
||||
<StatusFilters handleFilterChange={this.handleFilterChange}
|
||||
activeFilter={this.props.torrentList.filterBy} />
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(uiSelector)(Sidebar);
|
||||
@@ -1,251 +0,0 @@
|
||||
import _ from 'lodash';
|
||||
import classNames from 'classnames';
|
||||
import {connect} from 'react-redux';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
import {getTorrents, getTorrentDetails} from '../actions/ClientActions';
|
||||
import {handleTorrentClick} from '../actions/UIActions';
|
||||
import Torrent from '../components/torrent-list/Torrent';
|
||||
import TorrentDetails from '../components/torrent-list/TorrentDetails';
|
||||
import torrentSelector from '../selectors/torrentSelector';
|
||||
import UIActions from '../actions/UIActions';
|
||||
import uiSelector from '../selectors/uiSelector';
|
||||
|
||||
const methodsToBind = [
|
||||
'componentDidMount',
|
||||
'componentWillUnmount',
|
||||
'handleDetailsClick',
|
||||
'handleTorrentClick',
|
||||
'getListPadding',
|
||||
'getTorrents',
|
||||
'getViewportLimits',
|
||||
'setScrollPosition',
|
||||
'setViewportHeight',
|
||||
'shouldComponentUpdate'
|
||||
];
|
||||
|
||||
class TorrentList extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
detailsPanelOpen: false,
|
||||
count: 0,
|
||||
maxTorrentIndex: 4,
|
||||
minTorrentIndex: 0,
|
||||
scrollPosition: 0,
|
||||
spaceBottom: 0,
|
||||
spaceTop: 0,
|
||||
torrentCount: 0,
|
||||
torrentFetchInterval: null,
|
||||
torrentHeight: 64,
|
||||
torrentRenderBuffer: 2,
|
||||
viewportHeight: 0
|
||||
};
|
||||
|
||||
methodsToBind.forEach((method) => {
|
||||
this[method] = this[method].bind(this);
|
||||
});
|
||||
|
||||
this.handleScroll = _.throttle(this.setScrollPosition, 150, {
|
||||
leading: true
|
||||
});
|
||||
|
||||
this.handleWindowResize = _.throttle(this.setViewportHeight, 350, {
|
||||
leading: true
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('resize', this.handleWindowResize);
|
||||
this.setViewportHeight();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.handleWindowResize);
|
||||
clearInterval(this.state.torrentFetchInterval);
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
let getTorrents = this.getTorrents;
|
||||
|
||||
this.state.torrentFetchInterval = setInterval(function() {
|
||||
getTorrents();
|
||||
}, 5000);
|
||||
|
||||
getTorrents();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if ((nextProps.selectedTorrents.length !== 1 &&
|
||||
this.state.detailsPanelOpen) || nextProps.torrents.length === 0) {
|
||||
// Close the detail side panel if more than one torrent is selected.
|
||||
this.setState({
|
||||
detailsPanelOpen: false
|
||||
});
|
||||
} else if (this.state.detailsPanelOpen) {
|
||||
// Close the detail side panel if the currently selected torrent isn't
|
||||
// visible.
|
||||
let searchingForSelectedTorrent = true;
|
||||
let index = 0;
|
||||
|
||||
while (searchingForSelectedTorrent) {
|
||||
if (nextProps.torrents[index].hash === nextProps.selectedTorrents[0]) {
|
||||
// The currently selected torrent is visible.
|
||||
searchingForSelectedTorrent = false;
|
||||
} else if (index === nextProps.torrents.length - 1) {
|
||||
// The currently selected torrent is not visible, so clos the details
|
||||
// panel.
|
||||
this.setState({
|
||||
detailsPanelOpen: false
|
||||
});
|
||||
index++;
|
||||
searchingForSelectedTorrent = false;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (nextProps.isFetching === true) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
getTorrents() {
|
||||
this.props.dispatch(getTorrents());
|
||||
}
|
||||
|
||||
handleDetailsClick(torrent) {
|
||||
this.props.dispatch(getTorrentDetails(torrent.hash));
|
||||
this.setState({
|
||||
detailsPanelOpen: !this.state.detailsPanelOpen
|
||||
});
|
||||
}
|
||||
|
||||
handleTorrentClick(hash, event) {
|
||||
if (this.state.detailsPanelOpen) {
|
||||
this.props.dispatch(getTorrentDetails(hash));
|
||||
}
|
||||
|
||||
this.props.dispatch(handleTorrentClick({
|
||||
hash,
|
||||
event,
|
||||
torrentList: this.props.torrents
|
||||
}));
|
||||
}
|
||||
|
||||
getListPadding(minTorrentIndex, maxTorrentIndex, torrentCount) {
|
||||
if (maxTorrentIndex > torrentCount - 1) {
|
||||
maxTorrentIndex = torrentCount - 1;
|
||||
}
|
||||
|
||||
let hiddenBottom = torrentCount - 1 - maxTorrentIndex;
|
||||
let hiddenTop = minTorrentIndex;
|
||||
|
||||
let bottom = maxTorrentIndex <= torrentCount ? hiddenBottom *
|
||||
this.state.torrentHeight : 0;
|
||||
let top = minTorrentIndex > 0 ? hiddenTop * this.state.torrentHeight : 0;
|
||||
|
||||
return {
|
||||
bottom,
|
||||
top
|
||||
};
|
||||
}
|
||||
|
||||
getViewportLimits() {
|
||||
let buffer = 10;
|
||||
|
||||
let elementsInView = Math.floor(this.state.viewportHeight /
|
||||
this.state.torrentHeight);
|
||||
|
||||
let minTorrentIndex = Math.floor(this.state.scrollPosition /
|
||||
this.state.torrentHeight) - buffer;
|
||||
|
||||
let maxTorrentIndex = minTorrentIndex + elementsInView + buffer * 2;
|
||||
|
||||
return {
|
||||
minTorrentIndex,
|
||||
maxTorrentIndex
|
||||
};
|
||||
}
|
||||
|
||||
setScrollPosition() {
|
||||
this.setState({
|
||||
scrollPosition: ReactDOM.findDOMNode(this.refs.torrentList).scrollTop
|
||||
});
|
||||
}
|
||||
|
||||
setViewportHeight() {
|
||||
this.setState({
|
||||
viewportHeight: ReactDOM.findDOMNode(this.refs.torrentList).offsetHeight
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
let classes = classNames({
|
||||
'torrents': true,
|
||||
'has-sidepanel': this.state.detailsPanelOpen
|
||||
});
|
||||
let selectedTorrents = this.props.selectedTorrents;
|
||||
let torrentList = null;
|
||||
let torrents = this.props.torrents;
|
||||
let viewportLimits = this.getViewportLimits();
|
||||
let listPadding = this.getListPadding(viewportLimits.minTorrentIndex,
|
||||
viewportLimits.maxTorrentIndex,
|
||||
torrents.length);
|
||||
|
||||
if (torrents && torrents.length) {
|
||||
torrentList = torrents.map(function(torrent, index) {
|
||||
|
||||
if (index >= viewportLimits.minTorrentIndex &&
|
||||
index <= viewportLimits.maxTorrentIndex) {
|
||||
let isSelected = false;
|
||||
let hash = torrent.hash;
|
||||
|
||||
if (selectedTorrents.indexOf(hash) > -1) {
|
||||
isSelected = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<Torrent key={hash} data={torrent} selected={isSelected}
|
||||
handleClick={this.handleTorrentClick}
|
||||
handleDetailsClick={this.handleDetailsClick} />
|
||||
);
|
||||
}
|
||||
|
||||
}, this);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className="torrent__list__wrapper" onScroll={this.handleScroll}
|
||||
ref="torrentList">
|
||||
<ul className="torrent__list">
|
||||
<li className="torrent__spacer torrent__spacer--top"
|
||||
style={{
|
||||
height: listPadding.top + 'px'
|
||||
}}></li>
|
||||
{torrentList}
|
||||
<li className="torrent__spacer torrent__spacer--bottom"
|
||||
style={{
|
||||
height: listPadding.bottom + 'px'
|
||||
}}></li>
|
||||
</ul>
|
||||
</div>
|
||||
<TorrentDetails selectedTorrents={selectedTorrents}
|
||||
torrents={torrents}
|
||||
visible={this.state.detailsPanelOpen} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default connect(torrentSelector)(TorrentList);
|
||||
Reference in New Issue
Block a user