Commit Graph
379 Commits
Author SHA1 Message Date
darken fbbbf751c5 Add priority hint to device profiles list
- 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
2025-09-29 13:37:01 +02:00
darken 132b3996fc Update signal quality slider range
The signal quality slider in `device_profile_creation_fragment.xml` now ranges from 0 to 100 with a step size of 1, previously 10 to 100 with a step size of 5.
2025-09-29 13:37:01 +02:00
darken 7b41f83a53 Refactor device profiles and settings migration
This commit introduces a new device profile system, moving away from a single "main device" configuration in `GeneralSettings`.

Key changes:
- `DeviceProfilesRepo` now manages a list of `DeviceProfile` objects, allowing for multiple device configurations.
- On first launch with this update, existing "main device" settings from `GeneralSettings` (address, model, keys, signal quality) are migrated into a new default `AppleDeviceProfile`.
- The `MonitorWorker`, `PopUpReaction`, `AutoConnect`, and `PodHistoryRepo` have been updated to use the new `DeviceProfilesRepo` instead of the old `GeneralSettings` for device-specific information.
- `AppleFactory` now uses `DeviceProfilesRepo` to find matching profiles based on IRK.
- `TroubleShooterFragmentVM` now interacts with `DeviceProfilesRepo` for profile management during troubleshooting.
- The `create` method in `ApplePodsFactory` and its implementations are now `suspend` functions to allow for asynchronous operations like fetching profiles from the repository.
- Old "main device" preference keys in `GeneralSettings` have been renamed with an "old" prefix and will be removed in a future update.
- A new `currentProfiles()` extension function provides a convenient way to get the current list of profiles.
2025-09-29 13:37:01 +02:00
darken b6027186c0 Distinguish between UNKNOWN and missing profile
This commit modifies the `AppleFactory` to correctly handle `PodDevice.Model.UNKNOWN`.

Previously, if a device's model was `UNKNOWN`, it wouldn't match any profile and `isIRKMatch` would be false. This change ensures that `isIRKMatch` reflects the actual IRK match status, regardless of whether a specific profile is found.

Devices with an `UNKNOWN` model can now match profiles that are also marked as `UNKNOWN`, allowing for generic profile matching when the specific model isn't identified.
2025-09-29 13:37:01 +02:00
darken d2d126e9d9 Enable per-app language preferences
This commit enables the automatic generation of per-app language preferences by configuring the Android Gradle Plugin.

A `resources.properties` file is added to specify `en` as the `unqualifiedResLocale`, which serves as the default/fallback locale.

Additionally, `.kotlin` is added to `.gitignore` to exclude Kotlin build-related files.
2025-09-29 13:37:01 +02:00
darken 89632d864a Remove deviceModel property from ApplePodsFactory interface
Removed the deviceModel property from ApplePodsFactory interface and all 25 implementing classes across AirPods, Beats, and misc device factories. This simplifies the factory pattern as the model information can be derived from the concrete implementation type itself.
2025-09-29 13:37:01 +02:00
darken 2cd209ee03 Add TODO for profile migration
This commit adds a TODO comment to `GeneralSettings.kt` to migrate settings related to signal quality and main device details to the new device profiles system.
2025-09-29 13:37:01 +02:00
darken b96d6ef4db Improve device profile creation UI and fix navigation bar overlaps
- 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
2025-09-29 13:37:01 +02:00
darken d6af8e21cc Remove TitleLarge from device profile creation toolbar
The `titleTextAppearance` was removed from the toolbar in `device_profile_creation_fragment.xml` to use the default appearance.
2025-09-29 13:37:01 +02:00
darken ae2d1c6868 Refactor: Rename devices package to profiles
This commit renames the `devices` package and its contents to `profiles` for better clarity and consistency. This includes renaming classes, files, and updating import statements and navigation graph references.
2025-09-29 13:37:00 +02:00
darken 98cf4ff3e7 Refactor device profiles: Add creation UI and drag-to-reorder
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.
2025-09-29 13:37:00 +02:00
darken 679c9cd070 wip 2025-09-29 13:36:59 +02:00
darken 5b281303d9 Use Uri.toUri() extension
This commit updates the `OverviewFragment` to use the `androidx.core.net.toUri()` extension function when creating Uris for system settings intents. This replaces the direct usage of `Uri.parse()`.
2025-09-29 13:36:46 +02:00
darken cb28bbfaf3 Remove item count debug subtitle in OverviewFragment
The subtitle showing the number of items in the list was only visible in debug builds and has been removed.
2025-09-29 13:36:46 +02:00
darken cd190389cd Update all device implementations to support profiles
- Update all Apple device classes to use AppleMeta with profile support
- Modify device factories to inject profile information during creation
- Update UI components to handle profile-aware device metadata
- Refactor reaction systems to work with profile-based devices
- Update monitor worker and cache to support profile relationships
- Ensure consistent meta structure across all device types

All devices now properly reference their associated profiles through
the meta.profile field, enabling profile-based functionality.
2025-09-29 13:36:46 +02:00
darken 0af469af07 Add core device profile infrastructure
- Implement DeviceProfile interface with sealed interface pattern
- Add AppleDeviceProfile for Apple devices with IRK support
- Create DeviceProfilesRepo for profile persistence with Moshi
- Add NameBasedPolyJsonAdapterFactory for polymorphic JSON serialization
- Update PodDevice.Meta to include profile reference
- Extend ApplePods with AppleMeta containing profile information
- Add utility extensions for profile-based device filtering

This establishes the foundation for device profile management system.
2025-09-29 13:36:46 +02:00
darken 1689153070 Implement profile-based device separation in overview UI
- 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
2025-09-29 13:36:46 +02:00
darken 520458b107 Consolidate strings.xml files from app-common to app module
- 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.
2025-09-29 13:36:46 +02:00
darken be8f4919c8 Merge main and common module to simplify. 2025-09-29 13:36:43 +02:00
darken deb012600d Remove "Show all devices" setting and always show all devices.
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.
2025-09-29 13:36:21 +02:00
darken 15371e01ef Refactor device configuration UI and move troubleshooter
- 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
2025-09-29 13:36:21 +02:00
darken 16392d5721 Refactor buildSrc and update dependencies
This commit refactors the `buildSrc` module by:
- Removing the `setupLibraryDefaults()` extension function from `ProjectConfig.kt` as its functionality is largely covered by standard Gradle plugin configurations.
- Inlining version numbers for Moshi and various testing libraries directly into `Dependencies.kt`, removing them from `Versions.kt`. This simplifies version management for these specific libraries.
- Removing unused version declarations from `Versions.kt`.

Additionally, this commit updates the following dependencies:
- Kotlin from 2.1.21 to 2.2.10
- Android Gradle Plugin from 8.11.0 to 8.12.2
- KSP from 2.1.21-2.0.1 to 2.2.10-2.0.2
- Dagger from 2.56.2 to 2.57.1
- AndroidX Navigation from 2.8.9 to 2.9.3

The `targetSdk` was also removed from the `app-common` module's `defaultConfig` as it's typically inherited or set at the app level.
2025-08-31 15:30:12 +02:00
darken 2edf5411ce Allow keeping "connected" notification after disconnect
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.
2025-08-31 10:11:45 +02:00
darken 89e46d3858 Update translations 2025-08-30 17:12:36 +02:00
darken da45eb5dda Update translations 2025-08-30 17:12:36 +02:00
darken a1868f495d Update translations 2025-08-30 17:12:36 +02:00
darken ceb5034c3b Update translations 2025-08-30 17:12:36 +02:00
darken 02ff7089c0 Refactor GPlay billing error handling and translations
This commit introduces localized error messages for Google Play billing issues and refactors the error handling in `UpgradeRepoGplay`.

- `BillingException` and `BillingResultException` now implement `HasLocalizedError` to provide user-friendly error messages.
- New string translations for billing error labels and descriptions have been added for various languages.
- `UpgradeRepoGplay` now includes an `error` field in its `Info` state to propagate billing errors.
- The `upgradeInfo` flow in `UpgradeRepoGplay` has been updated with a `retryWhen` operator to handle errors more gracefully. If an error occurs but the pro state was recent, it emits a grace period state. Otherwise, it emits the error.
- `OverviewFragmentVM` now observes `upgradeState` and posts any non-pro errors to `errorEvents` for display.
2025-08-30 17:12:36 +02:00
darken c325112b44 Apply translation updates and add Norwegian Bokmål
This commit incorporates various translation improvements across multiple languages (Ukrainian, Greek, French, Turkish, Spanish (Mexico), Arabic, Korean, Urdu (India), Indonesian, Romanian, Zulu) for UI strings and Play Store metadata.

Additionally, this commit introduces new translations for Norwegian Bokmål (nb) for the Play Store listing (title, short description, full description) and adds initial string resources for Romansh (rm).
2025-08-30 16:42:28 +02:00
darken c97c8f4852 Refactor: Introduce EdgeToEdgeHelper for consistent inset handling
This commit introduces an `EdgeToEdgeHelper` class to centralize and simplify the application of window insets for edge-to-edge display.

Key changes:
- Created `EdgeToEdgeHelper` to manage padding based on system bar insets.
- Migrated various Fragments (`OverviewFragment`, `OnboardingFragment`, `SettingsFragment`, `TroubleShooterFragment`) to use `EdgeToEdgeHelper` for consistent padding.
- Removed manual inset handling from `Activity2` and `Fragment2` as `EdgeToEdgeHelper` now manages this.
- Enabled edge-to-edge display in `MainActivity`.
- Minor updates to `BillingClientConnection` for product details fetching and `build.gradle.kts` for configuration.
2025-07-03 00:14:58 +02:00
darken 6b2073eff2 Update AGP, SDK, and BillingClient
This commit updates:
- Android Gradle Plugin to 8.11.0
- Compile/Target SDK to 36
- Google Play Billing Library to 8.0.0

The `BillingClient` is updated to use the new `PendingPurchasesParams` and `QueryPurchasesParams` APIs.
2025-07-03 00:14:58 +02:00
darken 977f135c50 Allow empty keys to clear IRK/EncKey
This commit modifies the handling of Identity Resolving Key (IRK) and Encryption Key (EncKey) to allow users to clear these values by providing an empty input.

Specifically:
- In `GeneralSettingsFragment.kt`, the `onKey` callbacks for both IRK and EncKey dialogs now use `takeIf { it.isNotEmpty() }` after converting the input hex string to a byte array. This ensures that an empty input results in `null` being set for the respective key.
- In `PodMonitor.kt`, when determining the main device, `mainDeviceIdentityKey.value` is now checked with `takeIf { it.isNotEmpty() }` to ensure an empty IRK is treated as no IRK being configured.
- In `AppleFactory.kt`, when attempting to decrypt the private payload, `mainDeviceEncryptionKey.value` is now checked with `takeIf { it.isNotEmpty() }` to ensure an empty EncKey prevents decryption attempts.
2025-06-30 14:12:32 +02:00
darken 9460584891 More language updates and mapping changes 2025-06-22 21:28:55 +02:00
darken d9f0de2e05 Add translations for Filipino, Albanian, Sardinian, and Urdu
This commit introduces new translations and updates existing ones for the CAPod application in Filipino (fil), Albanian (sq-rAL), Sardinian (sc-rIT), and Urdu (ur-rIN).

Specifically, it:
- Adds comprehensive translations for various UI elements, settings, permissions, and status messages in Albanian (`app/src/main/res/values-sq-rAL/strings.xml` and `app-common/src/main/res/values-sq-rAL/strings.xml`).
- Adds translations for Google Play related strings in Sardinian (`app/src/gplay/res/values-sc-rIT/strings.xml`).
- Adds translations for FOSS-specific upgrade options in Sardinian (`app/src/foss/res/values-sc-rIT/strings.xml`).
- Adds comprehensive translations for various UI elements, settings, permissions, and status messages in Sardinian (`app/src/main/res/values-sc-rIT/strings.xml`).
- Updates and expands translations in Filipino (`app-common/src/main/res/values-fil/strings.xml`), including terms for app names, general UI elements, permissions, device states, and settings.
- Adds comprehensive translations for various UI elements, settings, permissions, and status messages in Urdu (`app-common/src/main/res/values-ur-rIN/strings.xml`).
2025-06-22 19:20:47 +02:00
darken e0dc9ea737 Fix escaped quotes in translations
This commit corrects the escaping of quotation marks in several translated strings. Specifically, it replaces `\\\"` with `\"` in:
- Galician (gl-rES) translations for various permission descriptions.
- Telugu (te-rIN) translations for settings descriptions and troubleshooter text.
- Romansh (rm) translations for settings descriptions and troubleshooter text.
2025-06-22 19:20:47 +02:00
darken b4d0904f55 Add translations for Zulu, Finnish, Galician, Kyrgyz, Romansh, Telugu, and Uzbek
This commit introduces new translations for the app in Zulu (zu), Finnish (fi), Galician (gl-rES), Kyrgyz (ky-rKG), Romansh (rm), Telugu (te-rIN), and Uzbek (uz).
2025-06-22 19:20:47 +02:00
darken 2caee59713 More translation updates 2025-06-22 19:20:47 +02:00
darken 6712ba78ba Update app translations 2025-06-22 19:20:47 +02:00
darken b57b3458ab Update translations 2025-06-18 13:17:20 +02:00
darken 6aeee4816c Update translations 2025-06-18 13:17:20 +02:00
darken 7bf472023f Update translations 2025-06-12 08:57:16 +02:00
darken 101fb68205 Translate strings for new notification channel and update descriptions
This commit introduces translations for a new notification channel "Device connected" and updates some existing string descriptions in various languages.

Specifically, it:
- Adds translations for `settings_monitor_connected_notification_label`, `settings_monitor_connected_notification_description`, and `notification_channel_device_status_connected_label` in Spanish (es), French (fr), Estonian (et-rEE), Norwegian (no), Czech (cs), Polish (pl), Catalan (ca), Greek (el), and German (de).
- Updates the full app descriptions in `fastlane/metadata/android/` for Catalan (ca), German (de-DE), Spanish (es-ES), French (fr-FR), Estonian (et), Norwegian (no-NO), Czech (cs-CZ), Polish (pl-PL), and Russian (ru-RU) to replace "phone" with "device" in the context of connecting to AirPods.
- Adds missing Arabic (ar) translations for various strings related to debug logging, settings, troubleshooting, and onboarding.
- Fixes a typo in the German translation for `settings_general_description`.
- Corrects Hebrew (iw) translations for Bluetooth permission descriptions.
2025-06-06 06:57:29 +02:00
darken ffe8a58746 Introduce ApplePods.Flags and UI for key status
This commit introduces a new `Flags` data class within `ApplePods` to store boolean flags related to the device, specifically `isIRKMatch`.

This flag is now passed during the creation of `ApplePods` instances in all `ApplePodsFactory` implementations and the central `AppleFactory`.

The UI has been updated to display a key icon in the overview cards (`DualPodsCardVH` and `SinglePodsCardVH`):
- The icon is only visible if `flags.isIRKMatch` is true.
- The icon changes to a filled key (`ic_key_24`) if `payload.private` is not null (indicating successful decryption), otherwise an outline key (`ic_key_outline_24`) is shown.
- Minor layout adjustments were made in `overview_pods_single_item.xml` and `overview_pods_dual_item.xml` to accommodate the new key icon.
2025-06-06 06:03:41 +02:00
darken 877c5d9013 Introduce BluetoothAddress typealias
This commit introduces a typealias `BluetoothAddress` for `String` to improve code clarity and type safety when dealing with Bluetooth MAC addresses.

The following changes were made:
- Created `BluetoothAddress.kt` defining the typealias.
- Updated various classes to use `BluetoothAddress` instead of `String` for Bluetooth addresses:
    - `RPAChecker`
    - `PopUpReaction`
    - `DeviceSelectionDialogFactory`
    - `MonitorWorker`
    - `GeneralSettings`
    - `BluetoothDevice2`
2025-06-06 06:03:41 +02:00
darken 11a19da0b8 Add helper for HEX string to byte array conversion
This commit introduces a new helper function `fromHex()` that converts a HEX string (with optional separators like spaces or hyphens) into a byte array. It also adds a corresponding `toHex()` function for converting a byte array to a HEX string.

These helpers are now used in various parts of the codebase, including:
- Fake BLE data generation
- AirPod key input dialog
- RPA checker tests
- BaseAirPodsTest

Additionally, a unit test for these conversion functions has been added.
2025-06-06 06:03:41 +02:00
darken a434a0bee0 Disable encryption key setting if no identity key
The encryption key setting for the main device is now disabled if the identity key is not set. This prevents users from trying to set an encryption key for a device that doesn't have an identity key.
2025-06-06 06:03:41 +02:00
darken fc54e540e8 Code fluff
Replace `values()` with `entries` for enum iteration, as recommended by Kotlin for improved performance and consistency.

Also:
- Suppress unused warning in `ByteArrayAdapter`
- Improve logging in `WebpageTool` by including the exception details.
2025-06-06 06:03:41 +02:00
darken e8481cc8cd Add preferences for AirPods Identity and Encryption Keys
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.
2025-06-06 06:03:41 +02:00
darken eb8a9b3b46 Add option for separate connected notification
Closes #28
Closes #18
2025-05-14 21:21:04 +02:00
darken 79ec3ba932 Remove obsolete configuration in manifest 2025-05-14 21:04:28 +02:00