New: Download Clients for Manual Grabs

This commit is contained in:
Qstick
2021-03-18 00:07:25 -04:00
parent fd27018caa
commit 881313ef2b
209 changed files with 12229 additions and 127 deletions

View File

@@ -3,6 +3,7 @@ import React, { Component } from 'react';
import Icon from 'Components/Icon';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
import Popover from 'Components/Tooltip/Popover';
import { icons, kinds, tooltipPositions } from 'Helpers/Props';
@@ -15,8 +16,59 @@ import Peers from './Peers';
import ProtocolLabel from './ProtocolLabel';
import styles from './SearchIndexRow.css';
function getDownloadIcon(isGrabbing, isGrabbed, grabError) {
if (isGrabbing) {
return icons.SPINNER;
} else if (isGrabbed) {
return icons.DOWNLOADING;
} else if (grabError) {
return icons.DOWNLOADING;
}
return icons.DOWNLOAD;
}
function getDownloadTooltip(isGrabbing, isGrabbed, grabError) {
if (isGrabbing) {
return '';
} else if (isGrabbed) {
return translate('AddedToDownloadClient');
} else if (grabError) {
return grabError;
}
return translate('AddToDownloadClient');
}
class SearchIndexRow extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
isConfirmGrabModalOpen: false
};
}
//
// Listeners
onGrabPress = () => {
const {
guid,
indexerId,
onGrabPress
} = this.props;
onGrabPress({
guid,
indexerId
});
}
//
// Render
@@ -39,6 +91,9 @@ class SearchIndexRow extends Component {
leechers,
indexerFlags,
columns,
isGrabbing,
isGrabbed,
grabError,
longDateFormat,
timeFormat
} = this.props;
@@ -214,11 +269,13 @@ class SearchIndexRow extends Component {
key={column.name}
className={styles[column.name]}
>
<IconButton
className={styles.downloadLink}
name={icons.DOWNLOAD}
title={'Grab'}
to={downloadUrl}
<SpinnerIconButton
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
kind={grabError ? kinds.DANGER : kinds.DEFAULT}
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
isDisabled={isGrabbed}
isSpinning={isGrabbing}
onPress={this.onGrabPress}
/>
<IconButton
@@ -259,8 +316,17 @@ SearchIndexRow.propTypes = {
leechers: PropTypes.number,
indexerFlags: PropTypes.arrayOf(PropTypes.string).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
onGrabPress: PropTypes.func.isRequired,
isGrabbing: PropTypes.bool.isRequired,
isGrabbed: PropTypes.bool.isRequired,
grabError: PropTypes.string,
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired
};
SearchIndexRow.defaultProps = {
isGrabbing: false,
isGrabbed: false
};
export default SearchIndexRow;

View File

@@ -48,7 +48,8 @@ class SearchIndexTable extends Component {
items,
columns,
longDateFormat,
timeFormat
timeFormat,
onGrabPress
} = this.props;
const release = items[rowIndex];
@@ -65,6 +66,7 @@ class SearchIndexTable extends Component {
guid={release.guid}
longDateFormat={longDateFormat}
timeFormat={timeFormat}
onGrabPress={onGrabPress}
/>
</VirtualTableRow>
);
@@ -118,7 +120,8 @@ SearchIndexTable.propTypes = {
scroller: PropTypes.instanceOf(Element).isRequired,
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
onSortPress: PropTypes.func.isRequired
onSortPress: PropTypes.func.isRequired,
onGrabPress: PropTypes.func.isRequired
};
export default SearchIndexTable;

View File

@@ -1,20 +1,20 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { setReleasesSort } from 'Store/Actions/releaseActions';
import { grabRelease, setReleasesSort } from 'Store/Actions/releaseActions';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import SearchIndexTable from './SearchIndexTable';
function createMapStateToProps() {
return createSelector(
(state) => state.app.dimensions,
(state) => state.releases.columns,
(state) => state.releases,
createUISettingsSelector(),
(dimensions, columns, uiSettings) => {
(dimensions, releases, uiSettings) => {
return {
isSmallScreen: dimensions.isSmallScreen,
columns,
longDateFormat: uiSettings.longDateFormat,
timeFormat: uiSettings.timeFormat
timeFormat: uiSettings.timeFormat,
...releases
};
}
);
@@ -24,6 +24,9 @@ function createMapDispatchToProps(dispatch, props) {
return {
onSortPress(sortKey) {
dispatch(setReleasesSort({ sortKey }));
},
onGrabPress(payload) {
dispatch(grabRelease(payload));
}
};
}