Fix WaveformSlider thumb and progress fill misalignment#6421
Conversation
PR checklist ✅All required conditions are satisfied:
🎉 Great job! This PR is ready for review. |
SDK Size Comparison 📏
|
f49a78f to
4f65595
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
WalkthroughThe WaveformSlider composable is refactored to measure available width via ChangesWaveform Slider Refactoring and Testing
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/audio/WaveformSlider.kt (1)
187-190:⚠️ Potential issue | 🟠 Major | ⚡ Quick winGuard
totalBars <= 1to prevent Infinity/NaN geometry mathAt Line 189,
barSpacing = spaceWidth / totalSpacescan divide by zero whentotalBars == 1(totalSpaces == 0), and Line 188/189 can also produce invalid geometry whentotalBars == 0. This can propagate intotopLeft.xand break drawing.Suggested fix
Canvas( modifier = modifier.graphicsLayer { scaleX = if (isRtl) -1f else 1f }, ) { + if (totalBars <= 0) return@Canvas + val canvasW = size.width val canvasH = size.height val spaceWidth = canvasW * BarSpacingRatio val barsWidth = canvasW - spaceWidth val totalSpaces = totalBars - 1 val barWidth = barsWidth / totalBars - val barSpacing = spaceWidth / totalSpaces + val barSpacing = if (totalSpaces > 0) spaceWidth / totalSpaces else 0f🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/audio/WaveformSlider.kt` around lines 187 - 190, Guard against totalBars <= 1 in WaveformSlider.kt: compute totalSpaces = max(0, totalBars - 1) and if totalBars <= 1 set barWidth and barSpacing to safe defaults (e.g., barsWidth and 0 or barsWidth / 1 and 0) so you never divide by zero; update calculations that use barWidth/barSpacing (including any computation of topLeft.x) to use these guarded values so geometry stays finite when totalBars is 0 or 1.
🧹 Nitpick comments (1)
stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/audio/WaveformSliderTest.kt (1)
34-57: ⚡ Quick winConsider adding one RTL snapshot case for this suite
Given the RTL-specific rendering/progress path in the slider, one Paparazzi snapshot wrapped with RTL layout direction would help prevent regressions on that branch too.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/audio/WaveformSliderTest.kt` around lines 34 - 57, Add a Paparazzi RTL snapshot to cover the slider's RTL-specific rendering: create a new test (e.g., fun `slider rtl progress`) that uses the existing snapshot helper snapshotWithDarkModeRow but wraps the composable in an RTL layout direction (either by passing a layoutDirection param if snapshotWithDarkModeRow supports it, or by wrapping the content with CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl) around one of the existing fixtures like StaticWaveformSliderMidway() or FullWaveformTrack()); this new test should mirror one of the existing cases so RTL rendering/progress is validated.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In
`@stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/audio/WaveformSlider.kt`:
- Around line 187-190: Guard against totalBars <= 1 in WaveformSlider.kt:
compute totalSpaces = max(0, totalBars - 1) and if totalBars <= 1 set barWidth
and barSpacing to safe defaults (e.g., barsWidth and 0 or barsWidth / 1 and 0)
so you never divide by zero; update calculations that use barWidth/barSpacing
(including any computation of topLeft.x) to use these guarded values so geometry
stays finite when totalBars is 0 or 1.
---
Nitpick comments:
In
`@stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/audio/WaveformSliderTest.kt`:
- Around line 34-57: Add a Paparazzi RTL snapshot to cover the slider's
RTL-specific rendering: create a new test (e.g., fun `slider rtl progress`) that
uses the existing snapshot helper snapshotWithDarkModeRow but wraps the
composable in an RTL layout direction (either by passing a layoutDirection param
if snapshotWithDarkModeRow supports it, or by wrapping the content with
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Rtl)
around one of the existing fixtures like StaticWaveformSliderMidway() or
FullWaveformTrack()); this new test should mirror one of the existing cases so
RTL rendering/progress is validated.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 814481a3-3f3e-4040-8ffa-54b2ecfeca3b
⛔ Files ignored due to path filters (5)
stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.audio_WaveformSliderTest_full_track.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.audio_WaveformSliderTest_slider_paused.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.audio_WaveformSliderTest_slider_playing_at_start.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.audio_WaveformSliderTest_slider_playing_midway.pngis excluded by!**/*.pngstream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.components.audio_WaveformSliderTest_slider_without_thumb.pngis excluded by!**/*.png
📒 Files selected for processing (3)
stream-chat-android-compose/api/stream-chat-android-compose.apistream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/components/audio/WaveformSlider.ktstream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/components/audio/WaveformSliderTest.kt
4f65595 to
7ee8fe3
Compare
|
|
🚀 Available in v7.2.0 |


Goal
Fix two visual bugs in
StaticWaveformSlider:adjustBarWidthToLimit = falseandwaveformData.size < visibleBarLimit, the threshold wasscaled down by
size / visibleBarLimiteven though the bars span the full canvas, so only afraction of bars got colored.
its X offset depended on a
widthPxstate that was only populated afteronSizeChangedtriggered a recomposition.
Implementation
Box+onSizeChanged/mutableFloatStateOf(0f)withBoxWithConstraints,reading
constraints.maxWidthat composition time.visibleBarLimittototalBarsso the colored region matches the rendered bar layout in all three cases (
adjustBarWidthToLimittrue/false,
sizegreater/less than the limit).@param stylekdoc entry; collapse the nestedwhenfortotalBarsintominOf(...).🎨 UI Changes
Testing
StaticWaveformSliderpreviews in the IDE; thumb should sit at the correct progress on firstrender.
aligned.
Summary by CodeRabbit