Queue downloads seperately so we don't overwhelm the app

This commit is contained in:
Lei Nelissen
2022-01-15 17:25:24 +01:00
parent 81ccb6b1f9
commit 7ea4857997
10 changed files with 199 additions and 33 deletions

View File

@@ -1,12 +1,14 @@
import React, { useEffect, useMemo, useRef } from 'react';
import { useTypedSelector } from 'store';
import CloudIcon from 'assets/cloud.svg';
import CloudDownArrow from 'assets/cloud-down-arrow.svg';
import CloudExclamationMarkIcon from 'assets/cloud-exclamation-mark.svg';
import InternalDriveIcon from 'assets/internal-drive.svg';
import useDefaultStyles from './Colors';
import { EntityId } from '@reduxjs/toolkit';
import Svg, { Circle, CircleProps } from 'react-native-svg';
import { Animated, Easing } from 'react-native';
import styled from 'styled-components/native';
interface DownloadIconProps {
trackId: EntityId;
@@ -14,6 +16,17 @@ interface DownloadIconProps {
fill?: string;
}
const DownloadContainer = styled.View`
position: relative;
`;
const IconOverlay = styled.View`
position: absolute;
top: 0;
left: 0;
transform: scale(0.5);
`;
function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
// determine styles
const defaultStyles = useDefaultStyles();
@@ -21,6 +34,7 @@ function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
// Get download icon from state
const entity = useTypedSelector((state) => state.downloads.entities[trackId]);
const isQueued = useTypedSelector((state) => state.downloads.queued.includes(trackId));
// Memoize calculations for radius and circumference of the circle
const radius = useMemo(() => size / 2, [size]);
@@ -52,43 +66,46 @@ function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
return () => offsetAnimation.removeListener(subscription);
}, [offsetAnimation]);
if (!entity) {
if (!entity && !isQueued) {
return (
<CloudIcon width={size} height={size} fill={iconFill} />
);
}
const { isComplete, isFailed } = entity;
if (isComplete) {
if (entity?.isComplete) {
return (
<InternalDriveIcon width={size} height={size} fill={iconFill} />
);
}
if (isFailed) {
if (entity?.isFailed) {
return (
<CloudExclamationMarkIcon width={size} height={size} fill={iconFill} />
);
}
if (!isComplete && !isFailed) {
if (isQueued || (!entity?.isFailed && !entity?.isComplete)) {
return (
<Svg width={size} height={size} transform={[{ rotate: '-90deg' }]}>
<Circle
cx={radius}
cy={radius}
r={radius - 1}
stroke={iconFill}
// @ts-expect-error react-native-svg has outdated react-native typings
ref={circleRef}
strokeWidth={1.5}
strokeDasharray={[ circumference, circumference ]}
strokeDashoffset={circumference}
strokeLinecap='round'
fill='transparent'
/>
</Svg>
<DownloadContainer>
<Svg width={size} height={size} transform={[{ rotate: '-90deg' }]}>
<Circle
cx={radius}
cy={radius}
r={radius - 1}
stroke={iconFill}
// @ts-expect-error react-native-svg has outdated react-native typings
ref={circleRef}
strokeWidth={1.5}
strokeDasharray={[ circumference, circumference ]}
strokeDashoffset={circumference}
strokeLinecap='round'
fill='transparent'
/>
</Svg>
<IconOverlay>
<CloudDownArrow width={size} height={size} fill={iconFill} />
</IconOverlay>
</DownloadContainer>
);
}