Skip to content

Commit

Permalink
Add a button for removing download items
Browse files Browse the repository at this point in the history
  • Loading branch information
nukeop committed Oct 6, 2020
1 parent afebb53 commit eafd60b
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 58 deletions.
15 changes: 14 additions & 1 deletion packages/app/app/actions/downloads.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const DOWNLOAD_RESUMED = 'DOWNLOAD_RESUMED';
export const DOWNLOAD_PROGRESS = 'DOWNLOAD_PROGRESS';
export const DOWNLOAD_FINISHED = 'DOWNLOAD_FINISHED';
export const DOWNLOAD_ERROR = 'DOWNLOAD_ERROR';
export const DOWNLOAD_REMOVED = 'DOWNLOAD_REMOVED';
export const CLEAR_FINISHED_DOWNLOADS = 'CLEAR_FINISHED_DOWNLOADS';

export const DownloadStatus = {
Expand All @@ -24,6 +25,7 @@ export const DownloadStatus = {
const changePropertyForItem = ({downloads, uuid, propertyName='status', value}) => {
const changedItem = _.find(downloads, (item) => item.track.uuid === uuid);
_.set(changedItem, propertyName, value);

return downloads;
};

Expand Down Expand Up @@ -106,11 +108,13 @@ export function onDownloadProgress(uuid, progress) {
propertyName: 'completion',
value: progress
});

payload = changePropertyForItem({
payload,
downloads: payload,
uuid,
value: DownloadStatus.STARTED
});

return {
type: DOWNLOAD_PROGRESS,
payload
Expand All @@ -131,6 +135,15 @@ export function onDownloadError(uuid){
};
}

export function onDownloadRemoved(uuid) {
const downloads = store.get('downloads');
const filteredTracks = downloads.filter(item => item.track.uuid !== uuid);
return {
type: DOWNLOAD_REMOVED,
payload: filteredTracks
};
}

export function onDownloadFinished(uuid) {
const downloads = store.get('downloads');
const payload = changePropertyForItem({
Expand Down
66 changes: 34 additions & 32 deletions packages/app/app/components/Downloads/DownloadsItem/index.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,46 @@
import React from 'react';
import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { Icon, Table } from 'semantic-ui-react';
import _ from 'lodash';

import styles from './styles.scss';

const StatusIcon = props => {
switch (props.status) {
case 'Waiting':
return <Icon name='hourglass start'/>;
return <Icon name='hourglass start' />;
case 'Paused':
return <Icon name='pause circle'/>;
return <Icon name='pause circle' />;
case 'Finished':
return <Icon name='checkmark' color='green'/>;
return <Icon name='checkmark' color='green' />;
case 'Started':
return <Icon name='cloud download'/>;
return <Icon name='cloud download' />;
case 'Error':
default:
return <Icon name='times' color='red'/>;
return <Icon name='times' color='red' />;
}
};

const renderAction = (name, callback, uuid) => (
const renderAction = (name, callback) => (
<a
onClick={() => callback(uuid)}
onClick={callback}
href='#'
>
<Icon name={name} />
<Icon fitted name={name} />
</a>
);

const ActionIcon = props => {
const {item, pauseDownload, resumeDownload} = props;
switch (item.status){
const { item, pauseDownload, resumeDownload } = props;
switch (item.status) {
case 'Waiting':
case 'Started':
return renderAction('pause', pauseDownload, item.track.uuid);
return renderAction('pause', pauseDownload);
case 'Paused':
return renderAction('play', resumeDownload, item.track.uuid);
return renderAction('play', resumeDownload);
case 'Error':
default:
return renderAction('redo', resumeDownload, item.track.uuid);
return renderAction('redo', resumeDownload);
}
};

Expand All @@ -60,49 +62,49 @@ ActionIcon.propTypes = {
const DownloadsItem = ({
item,
resumeDownload,
pauseDownload
pauseDownload,
removeDownload
}) => {
const artistName = _.isString(_.get(item, 'track.artist'))
? _.get(item, 'track.artist')
: _.get(item, 'track.artist.name');
const onResumeClick=(uuid) => {
resumeDownload(uuid);
};
const onPauseClick=(uuid) => {
pauseDownload(uuid);
};
const onResumeClick = useCallback(() => resumeDownload(item.track.uuid), [item, resumeDownload]);
const onPauseClick = useCallback(() => pauseDownload(item.track.uuid), [item, pauseDownload]);
const onRemoveClick = useCallback(() => removeDownload(item.track.uuid), [item, removeDownload]);
return (
<Table.Row>
<Table.Row className={styles.downloads_item}>
<Table.Cell>
<StatusIcon status={item.status}/>
{ item.status }
<StatusIcon status={item.status} />
{item.status}
</Table.Cell>
<Table.Cell>
{ artistName } - { _.get(item, 'track.name') }
{artistName} - {_.get(item, 'track.name')}
</Table.Cell>
<Table.Cell>
{ _.round(item.completion*100, 0) + '%' }
{_.round(item.completion * 100, 0) + '%'}
</Table.Cell>
<Table.Cell>
<ActionIcon resumeDownload={onResumeClick} pauseDownload={onPauseClick} item={item}/>
<Table.Cell className={styles.item_buttons}>
<ActionIcon resumeDownload={onResumeClick} pauseDownload={onPauseClick} item={item} />
<a href='#' onClick={onRemoveClick}>
<Icon fitted name='times' />
</a>
</Table.Cell>

</Table.Row>
);
};

DownloadsItem.propTypes = {
item: PropTypes.shape({

}),
resumeDownload: PropTypes.func.isRequired,
pauseDownload: PropTypes.func.isRequired
};

DownloadsItem.defaultProps = {
item: {},
pauseDownload: () => {},
resumeDownload: () => {}
pauseDownload: () => { },
resumeDownload: () => { }
};

export default DownloadsItem;
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.downloads_item {

.item_buttons {
display: flex;
justify-content: space-evenly;
}
}
4 changes: 3 additions & 1 deletion packages/app/app/components/Downloads/DownloadsList/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ const DownloadsList = ({
items,
clearFinishedTracks,
pauseDownload,
resumeDownload
resumeDownload,
removeDownload
}) => {
const [sortAsc, setSort] = useState(true);
const { t } = useTranslation('downloads');
Expand Down Expand Up @@ -55,6 +56,7 @@ const DownloadsList = ({
item={item}
resumeDownload={resumeDownload}
pauseDownload={pauseDownload}
removeDownload={removeDownload}
/>
);
})
Expand Down
4 changes: 3 additions & 1 deletion packages/app/app/components/Downloads/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const Downloads = ({
clearFinishedTracks,
setStringOption,
resumeDownload,
pauseDownload
pauseDownload,
removeDownload
}) => {
const { t } = useTranslation('downloads');

Expand All @@ -46,6 +47,7 @@ const Downloads = ({
clearFinishedTracks={clearFinishedTracks}
resumeDownload={resumeDownload}
pauseDownload={pauseDownload}
removeDownload={removeDownload}
/>
</React.Fragment>
)}
Expand Down
1 change: 1 addition & 0 deletions packages/app/app/containers/DownloadsContainer/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class DownloadsContainer extends React.Component {
clearFinishedTracks={downloadActions.clearFinishedDownloads}
pauseDownload={downloadActions.onDownloadPause}
resumeDownload={downloadActions.onDownloadResume}
removeDownload={downloadActions.onDownloadRemoved}
setStringOption={settingsActions.setStringOption}
/>
);
Expand Down
2 changes: 2 additions & 0 deletions packages/app/app/reducers/downloads.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DOWNLOAD_RESUMED,
DOWNLOAD_PROGRESS,
DOWNLOAD_FINISHED,
DOWNLOAD_REMOVED,
DOWNLOAD_ERROR,
CLEAR_FINISHED_DOWNLOADS,
READ_DOWNLOADS
Expand All @@ -24,6 +25,7 @@ export default function DownloadsReducer(state=initialState, action) {
case DOWNLOAD_PROGRESS:
case DOWNLOAD_FINISHED:
case DOWNLOAD_ERROR:
case DOWNLOAD_REMOVED:
case CLEAR_FINISHED_DOWNLOADS:
return [...action.payload];
default:
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/ipc/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ enum IpcEvents {
DOWNLOAD_PROGRESS = 'download-progress',
DOWNLOAD_FINISHED = 'download-finished',
DOWNLOAD_ERROR = 'download-error',

DOWNLOAD_REMOVED = 'download-removed',

WINDOW_MINIMIZE = 'minimize',
WINDOW_MAXIMIZE = 'maximize',
Expand Down
53 changes: 32 additions & 21 deletions packages/main/src/controllers/download.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,55 @@ import Download from '../services/download';
import Logger, { $mainLogger } from '../services/logger';
import Window from '../services/window';

interface DownloadRef{
interface DownloadRef {
uuid: string;
ref: DownloadItem;
}

@ipcController()
class DownloadIpcCtrl {
private downloadItems: DownloadRef[]=[];
private downloadItems: DownloadRef[] = [];
constructor(
@inject(Download) private download: Download,
@inject($mainLogger) private logger: Logger,
@inject(Window) private window: Window
) {}
) { }

/**
* Start a download using the download service
*/
@ipcEvent(IpcEvents.DOWNLOAD_START)
async onStartDownload(event: IpcMessageEvent, data: NuclearMeta) {
try {
const {uuid} = data;
const downloadRef = this.downloadItems.find((item => item.uuid===uuid));
if (downloadRef){
if (downloadRef.ref.canResume()){
const { uuid } = data;
const downloadRef = this.downloadItems.find((item => item.uuid === uuid));
if (downloadRef) {
if (downloadRef.ref.canResume()) {
downloadRef.ref.resume();
return;
}
this.downloadItems = this.downloadItems.filter((item => item.uuid===uuid));
this.downloadItems = this.downloadItems.filter((item => item.uuid === uuid));
}
const artistName = _.isString(_.get(data, 'artist'))
? _.get(data, 'artist')
: _.get(data, 'artist.name');

const query = `${artistName} ${_.get(data, 'name')}`;
const filename = `${artistName} - ${_.get(data, 'name')}`;

this.logger.log(`Start Download: ${artistName} - ${_.get(data, 'name')}`);

await this.download.start({
query,
filename,
onStart: (item) => {
this.downloadItems = this.downloadItems.filter((item) => item.uuid!==uuid);
this.downloadItems.push({uuid, ref: item});
this.downloadItems = this.downloadItems.filter((item) => item.uuid !== uuid);
this.downloadItems.push({ uuid, ref: item });
},
onProgress: (progress) => {
if (progress.transferredBytes===progress.totalBytes){
if (progress.transferredBytes === progress.totalBytes) {
this.window.send(IpcEvents.DOWNLOAD_FINISHED, uuid);
this.downloadItems = this.downloadItems.filter((item) => item.uuid!==uuid);
this.downloadItems = this.downloadItems.filter((item) => item.uuid !== uuid);
}
this.window.send(IpcEvents.DOWNLOAD_PROGRESS, {
uuid,
Expand All @@ -70,21 +70,32 @@ class DownloadIpcCtrl {
throw error;
}
}


@ipcEvent(IpcEvents.DOWNLOAD_REMOVED)
async onDownloadRemoved(event: IpcMessageEvent, data: NuclearMeta) {
try {
const { uuid } = data;
this.downloadItems = this.downloadItems.filter((item => item.uuid === uuid));
} catch (error) {
this.window.send(IpcEvents.DOWNLOAD_ERROR, { uuid: data.uuid, error });
throw error;
}
}

@ipcEvent(IpcEvents.DOWNLOAD_PAUSE)
async onPauseDownload(event: IpcMessageEvent, data: NuclearMeta) {
try {
const {uuid} = data;
const downloadRef = this.downloadItems.find((item => item.uuid===uuid));
if (downloadRef){
const { uuid } = data;
const downloadRef = this.downloadItems.find((item => item.uuid === uuid));
if (downloadRef) {
downloadRef.ref.pause();
}
} catch (error) {
this.window.send(IpcEvents.DOWNLOAD_ERROR, { uuid: data.uuid, error });
throw error;
}
}

}

export default DownloadIpcCtrl;

0 comments on commit eafd60b

Please sign in to comment.