Save settings more reasonably

This commit is contained in:
John Furrow
2016-05-03 20:44:47 -07:00
parent 5e8640457f
commit 2eac7fb035
20 changed files with 207 additions and 193 deletions
@@ -4,8 +4,8 @@ import AppDispatcher from '../dispatcher/AppDispatcher';
import ActionTypes from '../constants/ActionTypes';
const SettingsActions = {
fetchSettings: () => {
return axios.get('/client/settings')
fetchSettings: (property) => {
return axios.get('/client/settings', {params: {property}})
.then((json = {}) => {
return json.data;
})
@@ -16,6 +16,7 @@ const SettingsActions = {
});
})
.catch((error) => {
console.trace(error);
AppDispatcher.dispatchServerAction({
type: ActionTypes.SETTINGS_FETCH_REQUEST_ERROR,
error
@@ -35,6 +36,7 @@ const SettingsActions = {
});
})
.catch((error) => {
console.error(error);
AppDispatcher.dispatchServerAction({
type: ActionTypes.SETTINGS_SAVE_REQUEST_ERROR,
error
@@ -5,12 +5,6 @@ import ActionTypes from '../constants/ActionTypes';
const TorrentActions = {
addTorrentsByUrls: (options) => {
axios.post('/ui/torrent-location', {
destination: options.destination
})
.catch((error) => {
console.log(error);
});
return axios.post('/client/add', options)
.then((json = {}) => {
return json.data;
@@ -34,12 +28,6 @@ const TorrentActions = {
},
addTorrentsByFiles: (filesData, destination) => {
axios.post('/ui/torrent-location', {
destination
})
.catch((error) => {
console.log(error);
});
return axios.post('/client/add-files', filesData)
.then((json = {}) => {
return json.data;
@@ -81,25 +69,6 @@ const TorrentActions = {
});
},
fetchLatestTorrentLocation: () => {
return axios.get('/ui/torrent-location')
.then((json = {}) => {
return json.data;
})
.then((data) => {
AppDispatcher.dispatchServerAction({
type: ActionTypes.UI_LATEST_TORRENT_LOCATION_REQUEST_SUCCESS,
data
});
})
.catch((error) => {
AppDispatcher.dispatchServerAction({
type: ActionTypes.UI_LATEST_TORRENT_LOCATION_REQUEST_ERROR,
error
});
});
},
fetchTorrents: () => {
return axios.get('/client/torrents')
.then((json = {}) => {
+2 -5
View File
@@ -6,17 +6,14 @@ import ApplicationContent from './components/layout/ApplicationContent';
import ApplicationLoadingIndicator from './components/layout/ApplicationLoadingIndicator';
import Modals from './components/modals/Modals';
import Sidebar from './components/panels/Sidebar';
import SettingsStore from './stores/SettingsStore';
import TorrentActions from './actions/TorrentActions';
import TorrentDetailsView from './components/panels/TorrentDetailsView';
import TorrentListView from './components/panels/TorrentListView';
import UIActions from './actions/UIActions';
class FloodApp extends React.Component {
componentDidMount() {
TorrentActions.fetchLatestTorrentLocation();
window.addEventListener('click', () => {
UIActions.dismissContextMenu();
});
SettingsStore.fetchSettings();
}
render() {
@@ -2,8 +2,30 @@ import React from 'react';
import LoadingIndicatorDots from '../icons/LoadingIndicatorDots';
import ModalActions from './ModalActions';
import SettingsStore from '../../stores/SettingsStore';
const METHODS_TO_BIND = ['handleStartTorrentsToggle'];
export default class AddTorrents extends React.Component {
constructor() {
super();
this.state = {
startTorrentsOnLoad: true
};
METHODS_TO_BIND.forEach((method) => {
this[method] = this[method].bind(this);
});
}
componentWillMount() {
let startTorrentsOnLoad = SettingsStore.getSettings('startTorrentsOnLoad');
if (startTorrentsOnLoad !== true) {
this.setState({startTorrentsOnLoad: false});
}
}
getActions() {
let icon = null;
let primaryButtonText = 'Add Torrent';
@@ -15,8 +37,8 @@ export default class AddTorrents extends React.Component {
return [
{
checked: true,
clickHandler: this.props.onStartTorrentsToggle,
checked: this.state.startTorrentsOnLoad,
clickHandler: this.handleStartTorrentsToggle,
content: 'Start Torrent',
triggerDismiss: false,
type: 'checkbox'
@@ -42,6 +64,13 @@ export default class AddTorrents extends React.Component {
];
}
handleStartTorrentsToggle(value) {
SettingsStore.saveSettings({id: 'startTorrentsOnLoad', data: value});
if (!!this.props.onStartTorrentsToggle) {
this.props.onStartTorrentsToggle(value);
}
}
render() {
return (
<ModalActions actions={this.getActions()} dismiss={this.props.dismiss} />
@@ -8,13 +8,15 @@ import Close from '../icons/Close';
import File from '../icons/File';
import Files from '../icons/Files';
import ModalActions from './ModalActions';
import SettingsStore from '../../stores/SettingsStore';
import TorrentActions from '../../actions/TorrentActions';
const METHODS_TO_BIND = [
'handleAddTorrents',
'handleDestinationChange',
'handleFileDrop',
'handleFileRemove'
'handleFileRemove',
'handleStartTorrentsToggle'
];
export default class AddTorrents extends React.Component {
@@ -104,6 +106,8 @@ export default class AddTorrents extends React.Component {
return;
}
SettingsStore.saveSettings({id: 'torrentDestination', data: this.state.destination});
this.setState({isAddingTorrents: true});
let fileData = new FormData();
@@ -117,6 +121,10 @@ export default class AddTorrents extends React.Component {
TorrentActions.addTorrentsByFiles(fileData, this.state.destination);
}
handleStartTorrentsToggle(value) {
this.setState({startTorrents: value});
}
handleDestinationChange(destination) {
this.setState({destination});
}
@@ -133,6 +141,7 @@ export default class AddTorrents extends React.Component {
<AddTorrentsDestination onChange={this.handleDestinationChange} />
<AddTorrentsActions dismiss={this.props.dismissModal}
onAddTorrentsClick={this.handleAddTorrents}
onStartTorrentsToggle={this.handleStartTorrentsToggle}
isAddingTorrents={this.state.isAddingTorrents} />
</div>
);
@@ -2,6 +2,7 @@ import React from 'react';
import AddTorrentsActions from './AddTorrentsActions';
import AddTorrentsDestination from './AddTorrentsDestination';
import SettingsStore from '../../stores/SettingsStore';
import TextboxRepeater from '../forms/TextboxRepeater';
import TorrentActions from '../../actions/TorrentActions';
@@ -39,6 +40,7 @@ export default class AddTorrents extends React.Component {
destination: this.state.destination,
start: this.state.startTorrents
});
SettingsStore.saveSettings({id: 'torrentDestination', data: this.state.destination});
}
handleDestinationChange(destination) {
@@ -2,12 +2,9 @@ import classnames from 'classnames';
import React from 'react';
import EventTypes from '../../constants/EventTypes';
import UIStore from '../../stores/UIStore';
import SettingsStore from '../../stores/SettingsStore';
const METHODS_TO_BIND = [
'handleDestinationChange',
'onLatestTorrentLocationChange'
];
const METHODS_TO_BIND = ['handleDestinationChange'];
export default class AddTorrents extends React.Component {
constructor() {
@@ -23,22 +20,13 @@ export default class AddTorrents extends React.Component {
}
componentWillMount() {
let destination = UIStore.getLatestTorrentLocation();
let destination = SettingsStore.getSettings('torrentDestination');
if (this.props.suggested) {
destination = this.props.suggested;
}
this.setState({destination});
}
componentDidMount() {
UIStore.listen(EventTypes.UI_LATEST_TORRENT_LOCATION_CHANGE, this.onLatestTorrentLocationChange);
UIStore.fetchLatestTorrentLocation();
}
componentWillUnmount() {
UIStore.unlisten(EventTypes.UI_LATEST_TORRENT_LOCATION_CHANGE, this.onLatestTorrentLocationChange);
}
handleDestinationChange(event) {
let destination = event.target.value;
@@ -49,20 +37,6 @@ export default class AddTorrents extends React.Component {
this.setState({destination});
}
onLatestTorrentLocationChange() {
if (this.props.suggested) {
return;
}
let destination = UIStore.getLatestTorrentLocation();
if (this.props.onChange) {
this.props.onChange(destination);
}
this.setState({destination});
}
render() {
let textboxClasses = classnames('textbox', {
'is-fulfilled': this.state.destination && this.state.destination !== ''
@@ -32,7 +32,7 @@ export default class AddTorrents extends React.Component {
componentDidMount() {
SettingsStore.listen(EventTypes.SETTINGS_FETCH_REQUEST_SUCCESS, this.handleSettingsFetchRequestSuccess);
SettingsStore.fetchSettings(EventTypes.SETTINGS_FETCH_REQUEST_ERROR, this.handleSettingsFetchRequestError);
SettingsStore.fetchSettings('speedLimits');
}
componentWillUnmount() {
@@ -65,10 +65,17 @@ export default class AddTorrents extends React.Component {
}
handleSaveSettingsClick() {
SettingsStore.saveSettings(this.state.settings);
let settingsToSave = Object.keys(this.state.settings).map((settingsKey) => {
return {
id: settingsKey,
data: this.state.settings[settingsKey]
};
});
SettingsStore.saveSettings(settingsToSave);
}
handleSettingsFetchRequestError() {
handleSettingsFetchRequestError(error) {
console.log(error);
}
@@ -10,19 +10,14 @@ import SettingsStore from '../../stores/SettingsStore';
import TransferDataStore from '../../stores/TransferDataStore';
const METHODS_TO_BIND = ['handleSettingsFetchRequestSuccess', 'onTransferDataRequestSuccess'];
const SPEEDS = [1024, 10240, 102400, 512000, 1048576, 2097152, 5242880, 10485760, 0];
const DEFAULT_SPEEDS = [1024, 10240, 102400, 512000, 1048576, 2097152, 5242880, 10485760, 0];
class SpeedLimitDropdown extends React.Component {
constructor() {
super();
this.state = {
settings: {
speedLimits: {
download: [],
upload: []
}
},
speedLimits: {},
throttle: null
};
@@ -33,7 +28,7 @@ class SpeedLimitDropdown extends React.Component {
componentDidMount() {
SettingsStore.listen(EventTypes.SETTINGS_FETCH_REQUEST_SUCCESS, this.handleSettingsFetchRequestSuccess);
SettingsStore.fetchSettings(EventTypes.SETTINGS_FETCH_REQUEST_ERROR, this.handleSettingsFetchRequestError);
SettingsStore.fetchSettings('speedLimits');
TransferDataStore.listen(
EventTypes.CLIENT_TRANSFER_DATA_REQUEST_SUCCESS,
this.onTransferDataRequestSuccess
@@ -87,8 +82,9 @@ class SpeedLimitDropdown extends React.Component {
let insertCurrentThrottle = true;
let currentThrottle = this.state.throttle;
let speeds = this.state.speedLimits[property] || DEFAULT_SPEEDS;
let items = this.state.settings.speedLimits[property].map((bytes) => {
let items = speeds.map((bytes) => {
let selected = false;
bytes = Number(bytes);
@@ -113,7 +109,7 @@ class SpeedLimitDropdown extends React.Component {
if (insertCurrentThrottle && currentThrottle) {
// Find the position to insert the current throttle setting so that it
// remains sorted from lowest to highest.
let insertionPoint = _.sortedIndex(SPEEDS, currentThrottle[property]);
let insertionPoint = _.sortedIndex(speeds, currentThrottle[property]);
items.splice(insertionPoint, 0, {
displayName: this.getHumanReadableSpeed(currentThrottle[property]),
@@ -138,9 +134,11 @@ class SpeedLimitDropdown extends React.Component {
}
handleSettingsFetchRequestSuccess() {
this.setState({
settings: SettingsStore.getSettings()
});
let speedLimits = SettingsStore.getSettings('speedLimits');
if (!!speedLimits) {
this.setState({speedLimits});
}
}
render() {
@@ -18,7 +18,7 @@ const METHODS_TO_BIND = [
'onTransferHistoryRequestSuccess'
];
class ClientStats extends React.Component {
class TransferData extends React.Component {
constructor() {
super();
@@ -165,8 +165,8 @@ class ClientStats extends React.Component {
}
ClientStats.defaultProps = {
TransferData.defaultProps = {
historyLength: 1
};
export default ClientStats;
export default TransferData;
@@ -52,7 +52,6 @@ export default class Torrent extends React.Component {
let downloadTotal = format.data(torrent.downloadTotal);
let eta = format.eta(torrent.eta);
let ratio = format.ratio(torrent.ratio);
let secondaryDetails = [];
let totalSize = format.data(torrent.sizeBytes);
let uploadRate = format.data(torrent.uploadRate, '/s');
let uploadTotal = format.data(torrent.uploadTotal);
@@ -63,8 +62,23 @@ export default class Torrent extends React.Component {
let isActivelyDownloading = downloadRate.value > 0 || uploadRate.value > 0;
let wasAddedRecently = (Date.now() - added.getTime()) < 1000 * 60 * 10; // Was added in the last 10 minutes.
let secondaryDetails = [
<li className="torrent__details--secondary torrent__details--speed
torrent__details--speed--download" key="download-rate">
<span className="torrent__details__icon"><DownloadThickIcon /></span>
{downloadRate.value}
<em className="unit">{downloadRate.unit}</em>
</li>,
<li className="torrent__details--secondary torrent__details--speed
torrent__details--speed--upload" key="upload-rate">
<span className="torrent__details__icon"><UploadThickIcon /></span>
{uploadRate.value}
<em className="unit">{uploadRate.unit}</em>
</li>
];
if (isActivelyDownloading) {
secondaryDetails.push(
secondaryDetails.unshift(
<li className="torrent__details--secondary torrent__details--eta"
key="eta">
<span className="torrent__details__icon"><ClockIcon /></span>
@@ -75,18 +89,7 @@ export default class Torrent extends React.Component {
if (isActivelyDownloading || wasAddedRecently) {
secondaryDetails.push(
<li className="torrent__details--secondary torrent__details--speed
torrent__details--speed--download" key="download-rate">
<span className="torrent__details__icon"><DownloadThickIcon /></span>
{downloadRate.value}
<em className="unit">{downloadRate.unit}</em>
</li>,
<li className="torrent__details--secondary torrent__details--speed
torrent__details--speed--upload" key="upload-rate">
<span className="torrent__details__icon"><UploadThickIcon /></span>
{uploadRate.value}
<em className="unit">{uploadRate.unit}</em>
</li>
);
}
@@ -2,6 +2,8 @@ import classnames from 'classnames';
import React from 'react';
import ReactDOM from 'react-dom';
import UIActions from '../../actions/UIActions';
export default class ContextMenu extends React.Component {
constructor() {
super();
@@ -13,6 +15,8 @@ export default class ContextMenu extends React.Component {
}
componentDidMount() {
document.addEventListener('click', UIActions.dismissContextMenu);
if (this.props.onMenuOpen) {
this.props.onMenuOpen();
}
@@ -25,6 +29,8 @@ export default class ContextMenu extends React.Component {
}
componentWillUnmount() {
document.removeEventListener('click', UIActions.dismissContextMenu);
if (this.props.onMenuClose) {
this.props.onMenuClose();
}
@@ -9,11 +9,15 @@ class SettingsStoreClass extends BaseStore {
super();
}
fetchSettings() {
SettingsActions.fetchSettings();
fetchSettings(property) {
SettingsActions.fetchSettings(property);
}
getSettings() {
getSettings(property) {
if (property) {
return this.settings[property];
}
return this.settings;
}
@@ -27,6 +31,7 @@ class SettingsStoreClass extends BaseStore {
}
saveSettings(settings) {
this.settings[settings.id] = settings.data;
SettingsActions.saveSettings(settings);
}
}
-19
View File
@@ -25,10 +25,6 @@ class UIStoreClass extends BaseStore {
}
}
fetchLatestTorrentLocation() {
TorrentActions.fetchLatestTorrentLocation();
}
getActiveContextMenu() {
return this.activeContextMenu;
}
@@ -45,15 +41,6 @@ class UIStoreClass extends BaseStore {
return this.torrentDetailsHash;
}
handleLatestTorrentLocationRequestSuccess(location) {
this.latestTorrentLocation = location;
this.emit(EventTypes.UI_LATEST_TORRENT_LOCATION_CHANGE);
}
handleLatestTorrentLocationRequestError(error) {
console.log(error);
}
handleTorrentClick(hash) {
this.torrentDetailsHash = hash;
this.emit(EventTypes.UI_TORRENT_DETAILS_HASH_CHANGE);
@@ -133,12 +120,6 @@ UIStore.dispatcherID = AppDispatcher.register((payload) => {
case ActionTypes.UI_DISPLAY_CONTEXT_MENU:
UIStore.setActiveContextMenu(action.data);
break;
case ActionTypes.UI_LATEST_TORRENT_LOCATION_REQUEST_SUCCESS:
UIStore.handleLatestTorrentLocationRequestSuccess(action.data.path);
break;
case ActionTypes.UI_LATEST_TORRENT_LOCATION_REQUEST_ERROR:
UIStore.handleLatestTorrentLocationRequestError(action.error);
break;
}
});