New: Show downloading status for artist progress bar

(cherry picked from commit ac806a2933bf2dc0c96d471ec143fca8e1f5282f)
pull/4532/head
Mark McDowall 1 year ago committed by Bogdan
parent f1dede240d
commit af12fad185

@ -1,4 +1,10 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import React, {
useCallback,
useEffect,
useMemo,
useRef,
useState,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { SelectProvider } from 'App/SelectContext';
import NoArtist from 'Artist/NoArtist';
@ -22,6 +28,7 @@ import {
setArtistView,
} from 'Store/Actions/artistIndexActions';
import { executeCommand } from 'Store/Actions/commandActions';
import { fetchQueueDetails } from 'Store/Actions/queueActions';
import scrollPositions from 'Store/scrollPositions';
import createArtistClientSideCollectionItemsSelector from 'Store/Selectors/createArtistClientSideCollectionItemsSelector';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
@ -48,7 +55,7 @@ import ArtistIndexTable from './Table/ArtistIndexTable';
import ArtistIndexTableOptions from './Table/ArtistIndexTableOptions';
import styles from './ArtistIndex.css';
function getViewComponent(view) {
function getViewComponent(view: string) {
if (view === 'posters') {
return ArtistIndexPosters;
}
@ -94,6 +101,10 @@ const ArtistIndex = withScrollPosition((props: ArtistIndexProps) => {
const [jumpToCharacter, setJumpToCharacter] = useState<string | null>(null);
const [isSelectMode, setIsSelectMode] = useState(false);
useEffect(() => {
dispatch(fetchQueueDetails({ all: true }));
}, [dispatch]);
const onRssSyncPress = useCallback(() => {
dispatch(
executeCommand({

@ -50,6 +50,12 @@
}
}
.downloading {
composes: legendItemColor;
background-color: var(--purple);
}
.statistics {
display: flex;
justify-content: space-between;

@ -2,6 +2,7 @@
// Please do not change this file!
interface CssExports {
'continuing': string;
'downloading': string;
'ended': string;
'footer': string;
'legendItem': string;

@ -113,6 +113,16 @@ export default function ArtistIndexFooter() {
/>
<div>{translate('MissingTracksArtistNotMonitored')}</div>
</div>
<div className={styles.legendItem}>
<div
className={classNames(
styles.downloading,
enableColorImpairedMode && 'colorImpaired'
)}
/>
<div>{translate('ArtistIndexFooterDownloading')}</div>
</div>
</div>
<div className={styles.statistics}>

@ -183,13 +183,15 @@ function ArtistIndexBanner(props: ArtistIndexBannerProps) {
</div>
<ArtistIndexProgressBar
artistId={artistId}
monitored={monitored}
status={status}
trackCount={trackCount}
trackFileCount={trackFileCount}
totalTrackCount={totalTrackCount}
posterWidth={bannerWidth}
width={bannerWidth}
detailedProgressBar={detailedProgressBar}
isStandalone={false}
/>
{showTitle ? (

@ -160,13 +160,15 @@ function ArtistIndexOverview(props: ArtistIndexOverviewProps) {
</div>
<ArtistIndexProgressBar
artistId={artistId}
monitored={monitored}
status={status}
trackCount={trackCount}
trackFileCount={trackFileCount}
totalTrackCount={totalTrackCount}
posterWidth={posterWidth}
width={posterWidth}
detailedProgressBar={overviewOptions.detailedProgressBar}
isStandalone={false}
/>
</div>

@ -183,13 +183,15 @@ function ArtistIndexPoster(props: ArtistIndexPosterProps) {
</div>
<ArtistIndexProgressBar
artistId={artistId}
monitored={monitored}
status={status}
trackCount={trackCount}
trackFileCount={trackFileCount}
totalTrackCount={totalTrackCount}
posterWidth={posterWidth}
width={posterWidth}
detailedProgressBar={detailedProgressBar}
isStandalone={false}
/>
{showTitle ? (

@ -1,4 +1,8 @@
import React from 'react';
import { useSelector } from 'react-redux';
import createArtistQueueItemsDetailsSelector, {
ArtistQueueDetails,
} from 'Artist/Index/createArtistQueueDetailsSelector';
import ProgressBar from 'Components/ProgressBar';
import { sizes } from 'Helpers/Props';
import getProgressBarKind from 'Utilities/Artist/getProgressBarKind';
@ -6,35 +10,51 @@ import translate from 'Utilities/String/translate';
import styles from './ArtistIndexProgressBar.css';
interface ArtistIndexProgressBarProps {
artistId: number;
monitored: boolean;
status: string;
trackCount: number;
trackFileCount: number;
totalTrackCount: number;
posterWidth: number;
width: number;
detailedProgressBar: boolean;
isStandalone: boolean;
}
function ArtistIndexProgressBar(props: ArtistIndexProgressBarProps) {
const {
artistId,
monitored,
status,
trackCount,
trackFileCount,
totalTrackCount,
posterWidth,
width,
detailedProgressBar,
isStandalone,
} = props;
const queueDetails: ArtistQueueDetails = useSelector(
createArtistQueueItemsDetailsSelector(artistId)
);
const newDownloads = queueDetails.count - queueDetails.tracksWithFiles;
const progress = trackCount ? (trackFileCount / trackCount) * 100 : 100;
const text = `${trackFileCount} / ${trackCount}`;
const text = newDownloads
? `${trackFileCount} + ${newDownloads} / ${trackCount}`
: `${trackFileCount} / ${trackCount}`;
return (
<ProgressBar
className={styles.progressBar}
containerClassName={styles.progress}
containerClassName={isStandalone ? undefined : styles.progress}
progress={progress}
kind={getProgressBarKind(status, monitored, progress)}
kind={getProgressBarKind(
status,
monitored,
progress,
queueDetails.count > 0
)}
size={detailedProgressBar ? sizes.MEDIUM : sizes.SMALL}
showText={detailedProgressBar}
text={text}
@ -42,8 +62,9 @@ function ArtistIndexProgressBar(props: ArtistIndexProgressBarProps) {
trackFileCount,
trackCount,
totalTrackCount,
downloadingCount: queueDetails.count,
})}
width={posterWidth}
width={width}
/>
);
}

@ -9,13 +9,13 @@ import ArtistNameLink from 'Artist/ArtistNameLink';
import DeleteArtistModal from 'Artist/Delete/DeleteArtistModal';
import EditArtistModalConnector from 'Artist/Edit/EditArtistModalConnector';
import createArtistIndexItemSelector from 'Artist/Index/createArtistIndexItemSelector';
import ArtistIndexProgressBar from 'Artist/Index/ProgressBar/ArtistIndexProgressBar';
import ArtistStatusCell from 'Artist/Index/Table/ArtistStatusCell';
import { ARTIST_SEARCH, REFRESH_ARTIST } from 'Commands/commandNames';
import HeartRating from 'Components/HeartRating';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import ProgressBar from 'Components/ProgressBar';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
@ -23,7 +23,6 @@ import Column from 'Components/Table/Column';
import TagListConnector from 'Components/TagListConnector';
import { icons } from 'Helpers/Props';
import { executeCommand } from 'Store/Actions/commandActions';
import getProgressBarKind from 'Utilities/Artist/getProgressBarKind';
import formatBytes from 'Utilities/Number/formatBytes';
import translate from 'Utilities/String/translate';
import AlbumsCell from './AlbumsCell';
@ -301,23 +300,18 @@ function ArtistIndexRow(props: ArtistIndexRowProps) {
}
if (name === 'trackProgress') {
const progress = trackCount
? (trackFileCount / trackCount) * 100
: 100;
return (
<VirtualTableRowCell key={name} className={styles[name]}>
<ProgressBar
progress={progress}
kind={getProgressBarKind(status, monitored, progress)}
showText={true}
text={`${trackFileCount} / ${trackCount}`}
title={translate('ArtistProgressBarText', {
trackFileCount,
trackCount,
totalTrackCount,
})}
<ArtistIndexProgressBar
artistId={artistId}
monitored={monitored}
status={status}
trackCount={trackCount}
trackFileCount={trackFileCount}
totalTrackCount={totalTrackCount}
width={125}
detailedProgressBar={true}
isStandalone={true}
/>
</VirtualTableRowCell>
);

@ -0,0 +1,36 @@
import { createSelector } from 'reselect';
import AppState from 'App/State/AppState';
export interface ArtistQueueDetails {
count: number;
tracksWithFiles: number;
}
function createArtistQueueDetailsSelector(artistId: number) {
return createSelector(
(state: AppState) => state.queue.details.items,
(queueItems) => {
return queueItems.reduce(
(acc: ArtistQueueDetails, item) => {
if (item.artistId !== artistId) {
return acc;
}
acc.count += item.trackFileCount ?? 0;
if (item.trackHasFileCount) {
acc.tracksWithFiles += item.trackHasFileCount;
}
return acc;
},
{
count: 0,
tracksWithFiles: 0,
}
);
}
);
}
export default createArtistQueueDetailsSelector;

@ -1,6 +1,15 @@
import { kinds } from 'Helpers/Props';
function getProgressBarKind(status, monitored, progress) {
function getProgressBarKind(
status: string,
monitored: boolean,
progress: number,
isDownloading: boolean
) {
if (isDownloading) {
return kinds.PURPLE;
}
if (progress === 100) {
return status === 'ended' ? kinds.SUCCESS : kinds.PRIMARY;
}

@ -25,6 +25,8 @@ interface Queue extends ModelBase {
protocol: string;
downloadClient: string;
outputPath: string;
trackFileCount: number;
trackHasFileCount: number;
artistId?: number;
albumId?: number;
}

@ -38,6 +38,8 @@ namespace Lidarr.Api.V1.Queue
public bool DownloadClientHasPostImportCategory { get; set; }
public string Indexer { get; set; }
public string OutputPath { get; set; }
public int TrackFileCount { get; set; }
public int TrackHasFileCount { get; set; }
public bool DownloadForced { get; set; }
}
@ -53,6 +55,8 @@ namespace Lidarr.Api.V1.Queue
var customFormats = model.RemoteAlbum?.CustomFormats;
var customFormatScore = model.Artist?.QualityProfile?.Value?.CalculateCustomFormatScore(customFormats) ?? 0;
var albumRelease = model.Album?.AlbumReleases?.Value?.SingleOrDefault(x => x.Monitored);
return new QueueResource
{
Id = model.Id,
@ -80,6 +84,8 @@ namespace Lidarr.Api.V1.Queue
DownloadClientHasPostImportCategory = model.DownloadClientHasPostImportCategory,
Indexer = model.Indexer,
OutputPath = model.OutputPath,
TrackFileCount = albumRelease?.Tracks?.Value?.Count ?? 0,
TrackHasFileCount = albumRelease?.Tracks?.Value?.Count(x => x.HasFile) ?? 0,
DownloadForced = model.DownloadForced
};
}

@ -111,12 +111,13 @@
"ArtistClickToChangeAlbum": "Click to change album",
"ArtistEditor": "Artist Editor",
"ArtistFolderFormat": "Artist Folder Format",
"ArtistIndexFooterDownloading": "Downloading",
"ArtistIsMonitored": "Artist is monitored",
"ArtistIsUnmonitored": "Artist is unmonitored",
"ArtistMonitoring": "Artist Monitoring",
"ArtistName": "Artist Name",
"ArtistNameHelpText": "The name of the artist/album to exclude (can be anything meaningful)",
"ArtistProgressBarText": "{trackFileCount} / {trackCount} (Total: {totalTrackCount})",
"ArtistProgressBarText": "{trackFileCount} / {trackCount} (Total: {totalTrackCount}, Downloading: {downloadingCount})",
"ArtistType": "Artist Type",
"Artists": "Artists",
"ArtistsEditRootFolderHelpText": "Moving artists to the same root folder can be used to rename artist folders to match updated name or naming format",

Loading…
Cancel
Save