-
Notifications
You must be signed in to change notification settings - Fork 2
architecture-updates #62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This commit introduces a major refactoring to centralize and improve alarm scheduling logic. The core change is the introduction of the `AlarmTimeCalculator` in the domain layer, which is now responsible for all alarm time calculations. Key changes include: - **feat: Add `AlarmTimeCalculator`** - Introduced `AlarmTimeCalculator` interface and its implementation to handle the logic of calculating alarm trigger times, including for repeating alarms and considering future dates. - This moves complex time calculation logic out of the Android-specific `AlarmNotificationScheduler` and into the shared `core` module. - **refactor: Simplify `AlarmInteractor` and `AlarmNotificationScheduler`** - `AlarmInteractor.schedule` method signature changed from `schedule(alarm, reschedule)` to `schedule(alarm, timeInMillis)`. The interactor now schedules an alarm for a specific time, removing its responsibility for calculating that time. - The Android `AlarmNotificationScheduler` is heavily simplified. It no longer calculates *when* an alarm should fire but only schedules a `PendingIntent` for a given `timeInMillis`. - Added an `update(alarm)` method to the `AlarmInteractor` interface and its platform implementations. - **refactor: Update Use Cases** - Use cases like `ScheduleAlarm`, `ScheduleNextAlarm`, `RescheduleFutureAlarms`, and `SnoozeAlarm` are updated to use `AlarmTimeCalculator` to determine alarm times before passing them to the `AlarmInteractor`. - **refactor: Decouple `AlarmPermission`** - Abstracted Android framework dependencies (`AlarmManager`, `Context`) out of `AlarmPermissionImpl` by introducing `PermissionChecker`, `ScreenNavigator`, and `AndroidVersion` interfaces. This improves testability. - **refactor: Replace GlobalScope in `AlarmReceiver`** - Replaced `GlobalScope` with an injected `AppCoroutineScope` to follow structured concurrency best practices. - **test: Enhance and Adapt Tests** - Updated existing tests for ViewModels, use cases, and interactors to accommodate the new `AlarmTimeCalculator` and simplified scheduling logic. - Added comprehensive tests for the new `AlarmPermissionImpl` abstractions.
This commit refactors the iOS application's startup sequence and alarm notification logic for better performance and reliability.
Key changes include:
- **Early Koin Initialization**: Dependency injection is now initialized in the Swift `App.init()` before the UI loads, ensuring services are available sooner.
- **Background Database Prewarming**: The Room database is now prewarmed on a background thread after Koin initialization to prevent UI lag on first access.
- **Deferred Notification Permissions**: The notification permission request is now deferred until after the main UI appears, preventing it from blocking the app's startup.
- **Refined Notification Handling**:
- The `IosAlarmScheduler` now registers notification categories (`Snooze`, `Dismiss`) upon initialization.
- Notification content creation is updated to use the `TimeSensitive` interruption level, which is better suited for alarms than the previously used `Critical` level that requires special entitlements.
- A new `AlarmAudioController.swift` has been added to manage the playback of alarm sounds when a notification is received in the foreground or tapped, ensuring the alarm sound plays correctly.
- The `UNUserNotificationCenter` delegate method now explicitly requests to play the system sound as a fallback, in addition to showing the banner and badge.
…r notifications
This commit introduces a foreground service for handling alarms on Android, making them more reliable and resilient to app closures. It also improves notification handling on both Android and iOS.
### Android Changes
- **Introduced `AlarmService`**: A new foreground service to manage alarm playback, ensuring alarms continue to ring even if the app is closed or killed.
- **`AlarmTimingController`**: Extracted alarm timing logic (ring/pause/restart cycle) into a separate, testable class.
- **Improved Notification Handling**:
- Notifications are now ongoing and cannot be swiped away.
- Full-screen intents are re-triggered if the user navigates away from the alarm screen.
- **`ActiveAlarmManager`**: Tracks the active alarm to re-show the notification if the app is force-closed.
- **`PermissionChecker` Abstraction**: Created interfaces for checking permissions and navigating to system settings to improve testability.
### iOS Changes
- **`NotificationActionDelegate`**: Handles notification actions (snooze, dismiss) in a dedicated class.
- **`IosAlarmNotification`**: Manages the display and dismissal of delivered notifications.
- **`AlarmAudioController`**: A new Swift class to handle alarm audio playback and vibrations when the app is in the foreground.
### Core & Common Changes
- **`AppCoroutineScope`**: Introduced a shared coroutine scope for background tasks, replacing `GlobalScope`.
- **`AudioPlayer` Interface**: Added an `isPlaying` property to the common `AudioPlayer` interface.
This commit updates the GitHub Actions workflow, adds Robolectric for robust Android testing, and enhances the test suites for snoozing and alarm scheduling.
- **CI:**
- Replaced the deprecated `android_build.yml` with a new `build.yml` workflow.
- Upgraded to `actions/checkout@v4`, `actions/setup-java@v4`, and `gradle/actions/setup-gradle@v4`.
- Added separate steps for running tests on `core` and `app` modules.
- Implemented Gradle caching to improve workflow speed.
- Added a step to build and upload the debug APK as a build artifact.
- **Testing:**
- Added Robolectric to enable instrumentation tests in a local JVM, and configured it in `app/build.gradle.kts`.
- Rewrote `AlarmNotificationSchedulerTest` using Robolectric to properly test `AlarmManager` scheduling and cancellation logic.
- Overhauled `SnoozeAlarmTest` to use a fake `DateTimeProvider`, allowing for deterministic tests covering time rollovers (hour, day) and custom durations.
- Injected `DateTimeProvider` into `AlarmTimeCalculatorImpl` to make time-based calculations more testable.
- **UI:**
- Set the `imeAction` to `Done` on the alarm label text field for a better user experience.
This commit introduces a comprehensive suite of unit and integration-style tests for critical alarm scheduling, calculation, and persistence logic.
Key additions include:
- **`AlarmTimeCalculatorImplTest`**: Unit tests for the alarm time calculation logic, covering various scenarios such as non-repeating alarms, repeating alarms, day/month/year rollovers, and scheduling for past vs. future times.
- **`BootPersistenceTest`**: Integration-style tests to verify that alarms are correctly rescheduled after device boot or app updates. It tests scenarios for one-time, repeating, and disabled alarms.
- **`AlarmManagerExtensionsTest`**: Robolectric tests for the `setExactAlarm` and `cancelAlarm` extension functions, ensuring correct behavior with Android's `AlarmManager`.
- **`AlarmReceiverTest`**: Robolectric tests to validate the correct creation of intents with various actions (`ALARM_ACTION`, `SNOOZE_ACTION`, etc.) and boot-related events.
- **Test Fakes and Infrastructure**:
- Added `DateTimeProviderFake` to allow for deterministic time-based testing.
- Created a `TestApplication` for Robolectric tests to prevent Koin initialization conflicts.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.