From 28be6933c81d6318b87ba1a9c3c4ad8258d9e185 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Mon, 13 Apr 2026 16:55:52 -0500 Subject: [PATCH] fix(proguard): disable shrinking for Compose animation classes (#5116) --- app/proguard-rules.pro | 16 +++++----------- desktop/README.md | 2 +- desktop/proguard-rules.pro | 7 +++---- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 7feaa9217..f504e7bb6 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -48,14 +48,8 @@ # curves, transition specs, Animatable internals) which can cause animations to # silently snap in release builds. # -# -keep prevents class merging (EnterTransition/ExitTransition into *Impl, -# VectorizedSpringSpec/TweenSpec elimination, etc.). -# allowshrinking lets R8 remove genuinely unreachable classes (e.g. -# SharedTransition APIs, RepeatableSpec — unused by this app). Verified via -# dex analysis: 278 classes survive in release vs 139 without this rule; -# all actively used classes (AnimatedVisibility, Crossfade, SpringSpec, -# TweenSpec, EnterTransition, ExitTransition, etc.) are preserved. -# allowobfuscation is moot (-dontobfuscate is set above) but explicit for -# clarity. -# The ** wildcard is recursive and covers animation.core.* sub-packages. --keep,allowshrinking,allowobfuscation class androidx.compose.animation.** { *; } +# We use a full -keep here without allowshrinking/allowobfuscation. While it +# might keep some unused transition APIs, R8's aggressive shrinking is known +# to incorrectly remove internal states or merging empty transitions (like None) +# causing AnimatedVisibility and others to snap. +-keep class androidx.compose.animation.** { *; } diff --git a/desktop/README.md b/desktop/README.md index 491e9fe68..975cd59e2 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -32,7 +32,7 @@ Release builds use ProGuard for tree-shaking (unused code removal), significantl - `proguard-rules.pro` — Keep-rules for reflection/JNI-sensitive dependencies (Koin, kotlinx-serialization, Wire protobuf, Room KMP `androidx.room3`, Ktor, Kable BLE, Coil, SQLite JNI, Compose Multiplatform resources) and an anti-merge rule for Compose animation classes. **Key rules:** -- **Compose animation anti-merge** (`-keep,allowshrinking,allowobfuscation class androidx.compose.animation.** { *; }`) — Prevents ProGuard's optimizer from merging animation class hierarchies (e.g. `EnterTransition`/`ExitTransition` into `*Impl`), which causes animations to silently snap. Same rule as Android. +- **Compose animation anti-merge** (`-keep class androidx.compose.animation.** { *; }`) — Prevents ProGuard's optimizer from incorrectly tree-shaking or merging animation class hierarchies (e.g. `EnterTransition`/`ExitTransition` into `*Impl`), which causes animations to silently snap. Same rule as Android. - **Room KMP** — Uses `androidx.room3` package path (Room KMP 3.x). **Troubleshooting ProGuard issues:** diff --git a/desktop/proguard-rules.pro b/desktop/proguard-rules.pro index b4e6cc451..3a074d9ac 100644 --- a/desktop/proguard-rules.pro +++ b/desktop/proguard-rules.pro @@ -150,10 +150,9 @@ # ---- Compose Animation (anti-merge) ---------------------------------------- # Prevent ProGuard from merging animation spec class hierarchies (same issue -# as R8 on Android — EnterTransition/ExitTransition merged into *Impl, -# VectorizedSpringSpec/TweenSpec eliminated). allowshrinking lets ProGuard -# remove genuinely unreachable classes. --keep,allowshrinking,allowobfuscation class androidx.compose.animation.** { *; } +# as R8 on Android). We use a full keep to prevent incorrect tree-shaking +# of internal transitions. +-keep class androidx.compose.animation.** { *; } # ---- AboutLibraries ---------------------------------------------------------