Skip to content

Commit 02845c1

Browse files
feat: add GradientCircularProgressIndicator and integrate into DownloadDialogV2
1 parent 3f3e493 commit 02845c1

2 files changed

Lines changed: 95 additions & 1 deletion

File tree

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package com.junkfood.seal.ui.component
2+
3+
import androidx.compose.animation.core.LinearEasing
4+
import androidx.compose.animation.core.RepeatMode
5+
import androidx.compose.animation.core.animateFloat
6+
import androidx.compose.animation.core.infiniteRepeatable
7+
import androidx.compose.animation.core.rememberInfiniteTransition
8+
import androidx.compose.animation.core.tween
9+
import androidx.compose.foundation.Canvas
10+
import androidx.compose.foundation.layout.size
11+
import androidx.compose.material3.MaterialTheme
12+
import androidx.compose.runtime.Composable
13+
import androidx.compose.runtime.getValue
14+
import androidx.compose.ui.Modifier
15+
import androidx.compose.ui.graphics.Brush
16+
import androidx.compose.ui.graphics.StrokeCap
17+
import androidx.compose.ui.graphics.drawscope.Stroke
18+
import androidx.compose.ui.unit.Dp
19+
import androidx.compose.ui.unit.dp
20+
21+
/**
22+
* A premium circular progress indicator with animated gradient colors
23+
* that cycle through the app's theme colors continuously.
24+
*/
25+
@Composable
26+
fun GradientCircularProgressIndicator(
27+
modifier: Modifier = Modifier,
28+
size: Dp = 48.dp,
29+
strokeWidth: Dp = 4.dp
30+
) {
31+
val infiniteTransition = rememberInfiniteTransition(label = "gradientSpinner")
32+
33+
// Rotate the arc around the circle
34+
val rotation by infiniteTransition.animateFloat(
35+
initialValue = 0f,
36+
targetValue = 360f,
37+
animationSpec = infiniteRepeatable(
38+
animation = tween(durationMillis = 1100, easing = LinearEasing),
39+
repeatMode = RepeatMode.Restart
40+
),
41+
label = "rotation"
42+
)
43+
44+
// Animate the sweep angle (arc length) for a breathing effect
45+
val sweepAngle by infiniteTransition.animateFloat(
46+
initialValue = 60f,
47+
targetValue = 270f,
48+
animationSpec = infiniteRepeatable(
49+
animation = tween(durationMillis = 800, easing = LinearEasing),
50+
repeatMode = RepeatMode.Reverse
51+
),
52+
label = "sweep"
53+
)
54+
55+
// Shift gradient colors
56+
val colorShift by infiniteTransition.animateFloat(
57+
initialValue = 0f,
58+
targetValue = 1f,
59+
animationSpec = infiniteRepeatable(
60+
animation = tween(durationMillis = 2000, easing = LinearEasing),
61+
repeatMode = RepeatMode.Restart
62+
),
63+
label = "colorShift"
64+
)
65+
66+
val primary = MaterialTheme.colorScheme.primary
67+
val tertiary = MaterialTheme.colorScheme.tertiary
68+
val secondary = MaterialTheme.colorScheme.secondary
69+
70+
// Rotate through color combinations based on colorShift
71+
val colors = when {
72+
colorShift < 0.33f -> listOf(primary, tertiary, secondary)
73+
colorShift < 0.66f -> listOf(tertiary, secondary, primary)
74+
else -> listOf(secondary, primary, tertiary)
75+
}
76+
77+
Canvas(
78+
modifier = modifier.size(size)
79+
) {
80+
val gradientBrush = Brush.sweepGradient(colors = colors)
81+
82+
drawArc(
83+
brush = gradientBrush,
84+
startAngle = rotation,
85+
sweepAngle = sweepAngle,
86+
useCenter = false,
87+
style = Stroke(
88+
width = strokeWidth.toPx(),
89+
cap = StrokeCap.Round
90+
)
91+
)
92+
}
93+
}

app/src/main/java/com/junkfood/seal/ui/page/downloadv2/configure/DownloadDialogV2.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import com.junkfood.seal.ui.common.HapticFeedback.longPressHapticFeedback
9898
import com.junkfood.seal.ui.common.motion.materialSharedAxisX
9999
import com.junkfood.seal.ui.component.ButtonChip
100100
import com.junkfood.seal.ui.component.DrawerSheetSubtitle
101+
import com.junkfood.seal.ui.component.GradientCircularProgressIndicator
101102
import com.junkfood.seal.ui.component.OutlinedButtonWithIcon
102103
import com.junkfood.seal.ui.component.SealModalBottomSheet
103104
import com.junkfood.seal.ui.component.SealModalBottomSheetM2Variant
@@ -406,7 +407,7 @@ private fun DownloadDialogContent(
406407

407408
is Loading -> {
408409
Column(modifier = Modifier.fillMaxWidth().padding(vertical = 120.dp)) {
409-
CircularProgressIndicator(
410+
GradientCircularProgressIndicator(
410411
modifier = Modifier.align(Alignment.CenterHorizontally)
411412
)
412413
}

0 commit comments

Comments
 (0)