Remove Moshi dependency entirely, completing the migration to kotlinx.serialization. All JSON serialization now uses kotlinx with explicit @SerialName annotations for wire format stability.
- Migrate PodDeviceCache from Moshi to kotlinx Json injection
- Add MapIntByteArrayBase64Serializer for BleScanResult cache compat
- Strip @JsonClass/@Json annotations from all dual-annotated classes
- Delete Moshi adapters, ProGuard rules, and build config
- Convert compat tests to pure kotlinx round-trip tests
The debug recording trigger file now stores the session directory path and start timestamp. On app restart, the recorder resumes into the same session directory and log file instead of creating a new one, preserving the original start time so the short-recording guard doesn't reset.
Parse creation time from the embedded filename timestamp instead of relying on filesystem attributes, which are non-deterministic and caused flaky test failures in CI.
Replace Array<String> with List<String> in Zipper.zip().
Add global -opt-in flag for ExperimentalMaterial3Api in build.gradle.kts
and remove per-file @OptIn annotations from 12 Compose screens.
Replace sessions.first() inside fsMutex.withLock with synchronous volatile
read to avoid potential deadlock. Wrap file deletions in IO dispatcher.
Log partial delete failures. Make pendingAutoZips thread-safe via
Collections.synchronizedSet. Add test for ext/cache same-basename IDs.
Extract pure decision functions from AutoConnect and PopUpReaction for testability, following the existing PlayPause pattern. Add FakeDataStoreValue test helper.
Fix reversed Duration.between args in PopUpReaction connection monitor that caused the false-positive age filter to never trigger.
Replace FlowPreference<T> wrapping SharedPreferences with DataStoreValue<T> wrapping AndroidX DataStore. Includes SharedPreferencesMigration for preserving existing user data, kotlinx-serialization for complex types (replacing Moshi for preferences), and comprehensive unit tests for the new infrastructure.
Add user-facing theme preferences with three independent axes:
- Theme mode (System/Dark/Light)
- Theme style (Default/Material You/Medium Contrast/High Contrast)
- Theme color (Blue/Green/Amber)
Includes safe Moshi enum fallback for corrupted preference values,
color palettes for all combinations, and window background sync
to prevent flash during navigation transitions.
Add missing test cases for single-pod one-pod-mode pause direction,
EarDetectionState single-pod properties, and normal-mode steady-state.
Fix stale test comments that incorrectly claimed tests would fail.
Clarify onePodMode flow combine pattern and isWorn field semantics.
Fix edge case where removing a pod while both were in ears didn't trigger pause in one-pod mode. The aggregate boolean (isEitherPodInEar) stayed true, masking the individual pod removal.
See thread by `ZV`:
https://discord.com/channels/548521543039189022/1437499888068726814
The lid state for AirPods Gen 4 was incorrectly reported as UNKNOWN when it should have been NOT_IN_CASE. This commit fixes the issue in both the ANC and non-ANC tests.
This commit replaces the direct usage of GeneralSettings for fetching identity and encryption keys with the DeviceProfilesRepo. BaseAirPodsTest is updated to reflect this change, mocking DeviceProfilesRepo instead of GeneralSettings.