Add buttons for deleting downloaded tracks from playlist or album

This commit is contained in:
Lei Nelissen
2022-01-02 17:46:50 +01:00
parent db1c9d8af9
commit 95a008d8af
7 changed files with 52 additions and 8 deletions

View File

@@ -20,6 +20,10 @@ const BaseButton = styled.Pressable`
align-items: center;
justify-content: center;
flex-grow: 1;
${(props) => props.disabled && css`
opacity: 0.25;
`}
`;
const ButtonText = styled.Text<{ active?: boolean }>`
@@ -32,7 +36,7 @@ const ButtonText = styled.Text<{ active?: boolean }>`
`;
const Button = React.forwardRef<View, ButtonProps>(function Button(props, ref) {
const { icon: Icon, title, ...rest } = props;
const { icon: Icon, title, disabled, ...rest } = props;
const defaultStyles = useDefaultStyles();
const [isPressed, setPressed] = useState(false);
const handlePressIn = useCallback(() => setPressed(true), []);
@@ -41,6 +45,7 @@ const Button = React.forwardRef<View, ButtonProps>(function Button(props, ref) {
return (
<BaseButton
{...rest}
disabled={disabled}
ref={ref}
onPressIn={handlePressIn}
onPressOut={handlePressOut}

View File

@@ -51,5 +51,7 @@
"download-playlist": "Download Playlist",
"no-downloads": "You have not yet downloaded any tracks",
"delete-all-tracks": "Delete All Tracks",
"delete-album": "Delete Album",
"delete-playlist": "Delete Playlist",
"total-download-size": "Total Download Size"
}

View File

@@ -48,6 +48,7 @@ export type LocaleKeys = 'play-next'
| 'download-track'
| 'download-album'
| 'download-playlist'
| 'delete-all-tracks'
| 'delete-album'
| 'delete-playlist'
| 'total-download-size'
| 'no-downloads'

View File

@@ -37,7 +37,8 @@ const Album: React.FC = () => {
refresh={refresh}
playButtonText={t('play-album')}
shuffleButtonText={t('shuffle-album')}
downloadText={t('download-album')}
downloadButtonText={t('download-album')}
deleteButtonText={t('delete-album')}
/>
);
};

View File

@@ -37,7 +37,8 @@ const Playlist: React.FC = () => {
listNumberingStyle='index'
playButtonText={t('play-playlist')}
shuffleButtonText={t('shuffle-playlist')}
downloadText={t('download-playlist')}
downloadButtonText={t('download-playlist')}
deleteButtonText={t('delete-playlist')}
/>
);
};

View File

@@ -19,8 +19,10 @@ import { MusicNavigationProp } from 'screens/Music/types';
import DownloadIcon from 'components/DownloadIcon';
import Button from 'components/Button';
import CloudDownArrow from 'assets/cloud-down-arrow.svg';
import Trash from 'assets/trash.svg';
import { useDispatch } from 'react-redux';
import { downloadTrack } from 'store/downloads/actions';
import { downloadTrack, removeDownloadedTrack } from 'store/downloads/actions';
import { selectDownloadedTracks } from 'store/downloads/selectors';
const Screen = Dimensions.get('screen');
@@ -68,7 +70,8 @@ interface TrackListViewProps {
refresh: () => void;
playButtonText: string;
shuffleButtonText: string;
downloadText: string;
downloadButtonText: string;
deleteButtonText: string;
listNumberingStyle?: 'album' | 'index';
}
@@ -80,7 +83,8 @@ const TrackListView: React.FC<TrackListViewProps> = ({
refresh,
playButtonText,
shuffleButtonText,
downloadText,
downloadButtonText,
deleteButtonText,
listNumberingStyle = 'album',
}) => {
const defaultStyles = useDefaultStyles();
@@ -88,6 +92,7 @@ const TrackListView: React.FC<TrackListViewProps> = ({
// Retrieve state
const tracks = useTypedSelector((state) => state.music.tracks.entities);
const isLoading = useTypedSelector((state) => state.music.tracks.isLoading);
const downloadedTracks = useTypedSelector(selectDownloadedTracks(trackIds));
// Retrieve helpers
const getImage = useGetImage();
@@ -110,6 +115,9 @@ const TrackListView: React.FC<TrackListViewProps> = ({
const downloadAllTracks = useCallback(() => {
trackIds.forEach((trackId) => dispatch(downloadTrack(trackId)));
}, [dispatch, trackIds]);
const deleteAllTracks = useCallback(() => {
downloadedTracks.forEach((trackId) => dispatch(removeDownloadedTrack(trackId)));
}, [dispatch, downloadedTracks]);
return (
<ScrollView
@@ -162,7 +170,20 @@ const TrackListView: React.FC<TrackListViewProps> = ({
</TrackContainer>
</TouchableHandler>
)}
<Button icon={CloudDownArrow} title={downloadText} style={{ marginTop: 12 }} onPress={downloadAllTracks} />
<WrappableButtonRow style={{ marginTop: 24 }}>
<WrappableButton
icon={CloudDownArrow}
title={downloadButtonText}
onPress={downloadAllTracks}
disabled={downloadedTracks.length === trackIds.length}
/>
<WrappableButton
icon={Trash}
title={deleteButtonText}
onPress={deleteAllTracks}
disabled={downloadedTracks.length === 0}
/>
</WrappableButtonRow>
</View>
</ScrollView>
);

View File

@@ -0,0 +1,13 @@
import { createSelector, EntityId } from '@reduxjs/toolkit';
import { intersection } from 'lodash';
import { AppState } from 'store';
export const selectDownloadedTracks = (trackIds: EntityId[]) => (
createSelector(
(state: AppState) => state.downloads,
({ entities, ids }) => {
return intersection(trackIds, ids)
.filter((id) => entities[id]?.isComplete);
}
)
);