Allow for retring individual tracks
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useMemo, useRef } from 'react';
|
||||
import { useTypedSelector } from 'store';
|
||||
import CloudIcon from 'assets/cloud.svg';
|
||||
import CloudExclamationMarkIcon from 'assets/cloud-exclamation-mark.svg';
|
||||
@@ -6,6 +6,7 @@ import InternalDriveIcon from 'assets/internal-drive.svg';
|
||||
import useDefaultStyles from './Colors';
|
||||
import { EntityId } from '@reduxjs/toolkit';
|
||||
import Svg, { Circle } from 'react-native-svg';
|
||||
import { Animated, Easing } from 'react-native';
|
||||
|
||||
interface DownloadIconProps {
|
||||
trackId: EntityId;
|
||||
@@ -14,10 +15,40 @@ interface DownloadIconProps {
|
||||
}
|
||||
|
||||
function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
|
||||
// determine styles
|
||||
const defaultStyles = useDefaultStyles();
|
||||
const entity = useTypedSelector((state) => state.downloads.entities[trackId]);
|
||||
const iconFill = fill || defaultStyles.textHalfOpacity.color;
|
||||
|
||||
// Get download icon from state
|
||||
const entity = useTypedSelector((state) => state.downloads.entities[trackId]);
|
||||
|
||||
// Memoize calculations for radius and circumference of the circle
|
||||
const radius = useMemo(() => size / 2, [size]);
|
||||
const circumference = useMemo(() => radius * 2 * Math.PI, [radius]);
|
||||
|
||||
// Initialize refs for the circle and the animated value
|
||||
const circleRef = useRef<Circle>(null);
|
||||
const offsetAnimation = useRef(new Animated.Value(entity?.progress || 0)).current;
|
||||
|
||||
// Whenever the progress changes, trigger the animation
|
||||
useEffect(() => {
|
||||
Animated.timing(offsetAnimation, {
|
||||
toValue: (circumference * (1 - (entity?.progress || 0))),
|
||||
duration: 250,
|
||||
useNativeDriver: false,
|
||||
easing: Easing.ease,
|
||||
}).start();
|
||||
}, [entity?.progress, offsetAnimation, circumference]);
|
||||
|
||||
// On mount, subscribe to changes in the animation value and then
|
||||
// apply them to the circle using native props
|
||||
useEffect(() => {
|
||||
const subscription = offsetAnimation.addListener((offset) => {
|
||||
circleRef.current?.setNativeProps({ strokeDashoffset: offset.value });
|
||||
});
|
||||
|
||||
return () => offsetAnimation.removeListener(subscription);
|
||||
}, [offsetAnimation]);
|
||||
|
||||
if (!entity) {
|
||||
return (
|
||||
@@ -25,7 +56,7 @@ function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
|
||||
);
|
||||
}
|
||||
|
||||
const { isComplete, isFailed, progress } = entity;
|
||||
const { isComplete, isFailed } = entity;
|
||||
|
||||
if (isComplete) {
|
||||
return (
|
||||
@@ -40,9 +71,6 @@ function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
|
||||
}
|
||||
|
||||
if (!isComplete && !isFailed) {
|
||||
const radius = size / 2;
|
||||
const circumference = radius * 2 * Math.PI;
|
||||
|
||||
return (
|
||||
<Svg width={size} height={size} transform={[{ rotate: '-90deg' }]}>
|
||||
<Circle
|
||||
@@ -50,9 +78,10 @@ function DownloadIcon({ trackId, size = 16, fill }: DownloadIconProps) {
|
||||
cy={radius}
|
||||
r={radius - 1}
|
||||
stroke={iconFill}
|
||||
ref={circleRef}
|
||||
strokeWidth={1.5}
|
||||
strokeDasharray={[ circumference, circumference ]}
|
||||
strokeDashoffset={circumference * (1 - progress)}
|
||||
strokeDashoffset={circumference}
|
||||
strokeLinecap='round'
|
||||
fill='transparent'
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user