Replace PodDeviceCache (raw BLE scan bytes) with DeviceStateCache that stores decoded combined device state (battery, charging, model) per profile.
Battery values persist across app restarts with per-slot timestamps. Cached-only cards appear for offline devices with muted visuals and a staleness indicator. Fallback chain: AAP -> BLE -> cached.
Move BLE key and AAP connection icons into the SignalBadge pill.
Add BleKeyState enum on PodDevice to expose IRK/ENC state cleanly.
Key icon: outlined for IRK-only, solid for IRK+ENC.
Bluetooth icon shown when AAP transport is active.
Full integration of the Apple Accessory Protocol (AAP) over L2CAP, enabling direct communication with AirPods for 1% battery granularity, ANC mode control, Conversation Awareness toggle, and private key exchange for BLE encrypted battery.
BluetoothHeadset.connect() requires MODIFY_PHONE_STATE on modern Android, which is a system-only permission. Detect the SecurityException and stop further attempts instead of retrying every second.
The keep button's onClick handler was already named onKeep but the label said Close. Renamed to Keep for clarity alongside the Delete/Share buttons. Added dedicated string resource with translations for all 75 locales.
After sharing a debug log or sending a contact form email, show a dialog on return asking if the send was successful. Confirming deletes the log session and closes/navigates back.
Introduce DebugSession sealed interface as single source of truth for session lifecycle (Recording, Compressing, Ready, Failed). Auto-compress after recording stops. Replace scattered clear/delete actions with a session manager bottom sheet on the Support screen.
Rewrite SKU type system from data class to interface hierarchy supporting both IAP and subscriptions. Add subscription query, offer matching, and billing flow launch for yearly plans with optional free trial.
FOSS: Add sponsor-gate with 10-second timer and snackbar nudge.
Add dedicated Compose upgrade screens for both FOSS and gplay flavors, presenting pro benefits before the purchase/sponsor action. Migrate all upgrade dialog callers to navigate to the new screen instead.
Reorder support screen items with category headers, add log session count to clear action, fix contact form hint strings, filter active recordings from log picker, convert RecorderActivity to Compose with proper system bar insets and Material 3 color tokens, refresh log metadata on resume, add wiki link to settings, and move support entry under Other category
Add structured contact form with category selection (Question/Feature/Bug), description with word count validation, expected behavior field for bugs, and debug log picker with inline recording.
Enhance RecorderActivity with full-screen hero layout, file list, Share/Keep/Discard actions. Migrate debug logs from flat files to session directories in external files dir. Add DebugLogZipper, EmailTool attachment support, log folder size display, and clear stored logs.
Gate theme mode, style, and color settings behind pro/upgrade status.
Add Material Design 3 surface container color tokens to all color palettes.
Move upgrade prompt string to main resources with generic wording.
Disable theme preference items for non-pro users instead of late rejection.
Replace the legacy AppWidgetProvider/RemoteViews implementation with Glance AppWidget for reactive updates, proper centering, and a unified render state model.
- Add BatteryGlanceWidget with collectAsState for live device/profile/upgrade data
- Add WidgetRenderState sealed class and WidgetRenderStateMapper
- Add GlanceWidgetContent (Glance composables) and ComposeWidgetPreview (config preview)
- Fix centering by passing spacing via modifier param (no trailing padding on last item)
- Remove old XML widget layouts and RemoteViews rendering code
Monitor mode and scanner mode are functional settings, not appearance
settings. Give them their own "Monitoring" category header and place
them at the top of the general settings screen.
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 color presets, custom color picker, transparency slider, and device
label toggle to the widget configuration screen. Widget preview updates
in real-time. Use profile label as device name in both preview and
actual widget.
Explains that single-pod detection is an Apple limitation, not an app bug.
Users experiencing this issue will now understand it only affects the
"primary pod" (microphone pod) and can be configured in iOS settings.
Closes#38, Closes#329
This commit introduces a new card to the Overview screen that informs the user that the app is actively monitoring for devices when there are profiles configured but no devices are currently connected.
- Shows hint when 2+ profiles exist explaining order determines priority
- Appears as flat list item at bottom, less intrusive than card
- Prevents dragging hint item, keeps it at bottom
- Uses book icon for informational guidance
- Fix navigation bar overlap issues in profile creation and list screens
- Add proper edge-to-edge handling with dynamic padding for navigation bars
- Improve paired device selection with "None" option and clear functionality
- Add localized error messages for key validation with proper placeholders
- Centralize default signal quality value in DeviceProfile companion object
- Add unsaved changes detection and confirmation dialogs
- Enhance drag handle touch target size with FrameLayout wrapper
- Restore device address in profile editing and improve change tracking
- Localize all user-facing strings following project guidelines
This commit introduces a new UI for creating and editing device profiles. Users can now define profile names, select device models, set minimum signal quality, and optionally add identity and encryption keys.
The device manager screen now supports drag-and-drop reordering of profiles. The order of profiles in the list now determines their priority, with items at the top having higher priority. The internal data structure for device profiles has been updated, and the `PodMonitor` now sorts devices based on this new profile priority.
- Add UnmatchedDevicesCard to show/hide devices without profiles
- Separate devices with profiles from unmatched devices in overview
- Add priority-based sorting (profile.priority with 0 = highest)
- Add compiler args for experimental unsigned types and annotation targets
- Add string resources for unmatched devices UI
- Refactor overview to handle both profiled and non-profiled devices
The UI now shows:
1. Devices with configured profiles first (sorted by priority)
2. Collapsible section for unmatched devices with toggle button
3. Session-persistent show/hide state for unmatched devices
- Merged all 76 locale strings.xml files from app-common to app module
- Removed app-common module dependency from app/build.gradle.kts
- Removed app-common from settings.gradle
- Fixed all BuildConfig and R class import statements
- Updated fully qualified R references from eu.darken.capod.common.R to R
- Deleted entire app-common directory and all associated files
- Added temporary fallback for missing GITSHA BuildConfig field
The project now has a simplified structure with all string resources
consolidated in the app module, eliminating the unnecessary app-common
module while maintaining full functionality.
Builds successfully for both FOSS and Google Play variants.
This commit removes the "Show all devices" toggle from General Settings. The app will now always display all nearby Bluetooth devices in the overview, simplifying the UI and device discovery.
The corresponding preference `core.showall.enabled` and its usage have been removed. The debug setting `showUnfiltered` no longer affects this behavior.
- Change "No primary device" card to "No device configured" with clearer messaging
- Replace troubleshoot action with "Manage devices" button that navigates to device manager
- Move troubleshooter from overview to Settings → Support section
- Add concise troubleshooter description for settings preference
- Update navigation to support troubleshooter access from settings
- Improve user experience by providing more intuitive device management flow
This commit introduces a new setting that allows users to keep the "connected" notification visible even after the monitored device disconnects.
When this setting is enabled and the "Extra notification" is also active, the `MonitorWorker` will no longer cancel the connected notification upon finishing. This provides users with the option to see the last known battery levels after disconnection.
A new preference `keepConnectedNotificationAfterDisconnect` is added to `GeneralSettings` and the UI.
This commit introduces settings for users to input their AirPods' Identity Resolving Key (IRK) and Encryption Key. These keys, obtainable via a MacBook, allow CAPod to reliably identify the AirPods and decrypt detailed status information.
Key changes:
- Added new preferences in General Settings for IRK and Encryption Key.
- Implemented a custom dialog for key input, including validation and a link to a guide.
- Added a Moshi adapter for serializing/deserializing `ByteArray` to/from Base64 for storing the keys.
- Included new string resources for labels, descriptions, and explanations related to the keys.
- Added new icons for the key preferences.
* Improve compat options: Add alternative method for receiving BLE scan results via PendingIntents
* Add missing logtags
* Reduce log spam
* Make the linter happy