refactor(android): P2.1 Batch A - delegate 7 plugin methods to services

P2.1 Batch A: Pure delegation refactoring (low-risk, read-only operations)

Completed Refactorings:
- checkStatus() → NotificationStatusChecker.getComprehensiveStatus()
- getNotificationStatus() → NotificationStatusChecker + NotificationStatusHelper
- checkPermissionStatus() → PermissionManager.checkPermissionStatus()
- isChannelEnabled() → ChannelManager methods
- isAlarmScheduled() → DailyNotificationScheduler.isScheduled()
- getNextAlarmTime() → DailyNotificationScheduler.getNextAlarmTime()
- getContentCache() → ContentCacheHelper.getLatest()

Service Enhancements:
- Added NotificationStatusChecker.getNotificationStatus() (delegates to helper)
- Added DailyNotificationScheduler.isScheduled() (wraps NotifyReceiver)
- Added DailyNotificationScheduler.getNextAlarmTime() (wraps NotifyReceiver)

Helper Objects Created:
- NotificationStatusHelper: Kotlin object for notification status queries
- ContentCacheHelper: Kotlin object for content cache operations

Code Reduction:
- ~181 lines removed from DailyNotificationPlugin.kt
- Logic moved to service layer (better separation of concerns)
- Plugin class now acts as thin adapter layer

Deferred:
- getExactAlarmStatus() (requires complex service initialization)

All methods maintain same API behavior. Plugin class complexity reduced.
Services already existed - this is delegation, not extraction.

Refs: docs/progress/P2.1-BATCH-A-STATE.md
This commit is contained in:
Matthew Raymer
2025-12-23 11:35:00 +00:00
parent f97f5702d5
commit 87f12a0029
4 changed files with 327 additions and 99 deletions

View File

@@ -12,35 +12,93 @@
**Phase:** P2.1 - Native Plugin Refactoring (Batch A)
**Goal:** Refactor plugin methods to delegate to existing services (thin adapter pattern)
**Status:** 3 of ~10 methods completed, 1 deferred
**Status:** **BATCH A COMPLETE** — 7 methods refactored, 1 deferred
---
## Completed Refactorings
### ✅ Android: `checkStatus()`
- **File:** `android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt`
- **Change:** Delegated to `NotificationStatusChecker.getComprehensiveStatus()`
- **Lines removed:** ~50 lines
- **Service:** `NotificationStatusChecker` (initialized in `load()`)
### ✅ Android: `getNotificationStatus()`
- **File:** `android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt`
- **Change:** Delegated to `NotificationStatusChecker.getNotificationStatus()`
- **Lines removed:** ~35 lines
- **Implementation:**
- Plugin method delegates to `NotificationStatusChecker.getNotificationStatus(database)`
- Java method calls `NotificationStatusHelper.getNotificationStatusBlocking()` (Kotlin helper)
- Helper function handles suspend database operations using coroutines
- **Lines removed:** ~35 lines (logic moved to helper)
- **Service:** `NotificationStatusChecker` (initialized in `load()`)
- **Helper:** `NotificationStatusHelper` (Kotlin object with suspend function + Java-compatible blocking wrapper)
### ✅ Android: `checkPermissionStatus()`
- **File:** `android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt`
- **Change:** Delegated to `PermissionManager.checkPermissionStatus(call)`
- **Lines removed:** ~47 lines
- **Service:** `PermissionManager` (initialized in `load()` with `ChannelManager` dependency)
### ✅ Android: `isChannelEnabled()`
- **File:** `android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt`
- **Change:** Delegated to `ChannelManager` methods
- **Implementation:**
- Uses `channelManager.ensureChannelExists()` to ensure channel exists
- Uses `channelManager.isChannelEnabled()` for channel enabled check
- Uses `channelManager.getChannelImportance()` for importance level
- Uses `channelManager.getDefaultChannelId()` for channel ID
- Keeps app-level notification check in plugin (appropriate for plugin layer)
- **Lines removed:** ~37 lines (channel creation/checking logic moved to service)
- **Service:** `ChannelManager` (initialized in `load()`)
### ✅ Android: `isAlarmScheduled()`
- **File:** `android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt`
- **Change:** Delegated to `DailyNotificationScheduler.isScheduled()`
- **Implementation:**
- Added `isScheduled()` method to `DailyNotificationScheduler` (wraps `NotifyReceiver.isAlarmScheduled()`)
- Plugin method initializes scheduler lazily (requires AlarmManager)
- Delegates to `scheduler.isScheduled(triggerAtMillis)`
- Service method checks actual AlarmManager state via PendingIntent
- **Lines removed:** ~5 lines (direct NotifyReceiver call replaced with service delegation)
- **Service:** `DailyNotificationScheduler` (lazy initialization, requires AlarmManager)
### ✅ Android: `getNextAlarmTime()`
- **File:** `android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt`
- **Change:** Delegated to `DailyNotificationScheduler.getNextAlarmTime()`
- **Implementation:**
- Added `getNextAlarmTime()` method to `DailyNotificationScheduler` (wraps `NotifyReceiver.getNextAlarmTime()`)
- Plugin method initializes scheduler lazily (requires AlarmManager)
- Delegates to `scheduler.getNextAlarmTime()`
- Service method gets actual AlarmManager next alarm clock
- **Lines removed:** ~5 lines (direct NotifyReceiver call replaced with service delegation)
- **Service:** `DailyNotificationScheduler` (lazy initialization, requires AlarmManager)
### ✅ Android: `getContentCache()`
- **File:** `android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt`
- **Change:** Delegated to `ContentCacheHelper.getLatest()`
- **Implementation:**
- Created `ContentCacheHelper` Kotlin object with suspend function for database operations
- Plugin method delegates to `ContentCacheHelper.getLatest(database)`
- Helper function handles suspend database operations using coroutines
- Maintains same API behavior (returns latest ContentCache entry)
- **Lines removed:** ~2 lines (direct database call replaced with helper delegation)
- **Helper:** `ContentCacheHelper` (Kotlin object with suspend function, similar to NotificationStatusHelper)
---
## Deferred / Known Issues
### ⚠️ Android: `getExactAlarmStatus()` - Deferred
- **Reason:** `DailyNotificationExactAlarmManager` requires complex initialization:
- Needs `AlarmManager` (system service)
- Needs `DailyNotificationScheduler` instance
@@ -60,6 +118,7 @@ private var statusChecker: NotificationStatusChecker? = null
private var permissionManager: PermissionManager? = null
private var exactAlarmManager: DailyNotificationExactAlarmManager? = null // ⚠️ null (deferred)
private var channelManager: ChannelManager? = null
private var scheduler: DailyNotificationScheduler? = null // Lazy initialization (requires AlarmManager)
```
### Initialization in `load()` Method
@@ -73,6 +132,7 @@ exactAlarmManager = null // TODO: Requires AlarmManager + DailyNotificationSched
```
**Note:** `exactAlarmManager` is set to `null` because it requires:
- `AlarmManager` from `context.getSystemService(Context.ALARM_SERVICE)`
- `DailyNotificationScheduler` instance (which itself needs initialization)
@@ -81,6 +141,7 @@ exactAlarmManager = null // TODO: Requires AlarmManager + DailyNotificationSched
## Modified Files
### `android/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.kt`
- **Status:** Modified (unstaged)
- **Changes:**
- Added service instance variables (lines ~92-95)
@@ -92,33 +153,45 @@ exactAlarmManager = null // TODO: Requires AlarmManager + DailyNotificationSched
---
## Next Steps (Batch A Continuation)
## Batch A Completion Summary
### Immediate Next Methods (Low Risk)
**✅ All Batch A methods successfully refactored!**
1. **`isChannelEnabled()`** - Delegate to `ChannelManager.isChannelEnabled()`
- **Current:** ~77 lines of channel checking logic
- **Target:** ~5 lines delegation
- **Service:** `ChannelManager` (already initialized)
**Completed:** 7 methods refactored to use service delegation pattern
- `checkStatus()``NotificationStatusChecker`
- `getNotificationStatus()``NotificationStatusChecker` + `NotificationStatusHelper`
- `checkPermissionStatus()``PermissionManager`
- `isChannelEnabled()``ChannelManager`
- `isAlarmScheduled()``DailyNotificationScheduler`
- `getNextAlarmTime()``DailyNotificationScheduler`
- `getContentCache()``ContentCacheHelper`
2. **`isAlarmScheduled()`** - Delegate to `DailyNotificationScheduler.isScheduled()`
- **Current:** Direct AlarmManager access
- **Target:** Service delegation
- **Service:** Needs `DailyNotificationScheduler` instance (may need initialization)
**Deferred:** 1 method (`getExactAlarmStatus()` - requires complex initialization)
3. **`getNextAlarmTime()`** - Delegate to `DailyNotificationScheduler.getNextAlarmTime()`
- **Current:** Direct scheduler access
- **Target:** Service delegation
- **Service:** Needs `DailyNotificationScheduler` instance
**Code Reduction:** ~181 lines removed from plugin class
**New Helpers Created:**
- `NotificationStatusHelper` (Kotlin object)
- `ContentCacheHelper` (Kotlin object)
4. **`getContentCache()`** - Delegate to `DailyNotificationStorage.getContentCache()`
- **Current:** Direct database access
- **Target:** Storage service delegation
- **Service:** Needs `DailyNotificationStorage` instance
**Service Methods Added:**
- `NotificationStatusChecker.getNotificationStatus()`
- `DailyNotificationScheduler.isScheduled()`
- `DailyNotificationScheduler.getNextAlarmTime()`
---
## Next Steps (Batch B)
**Remaining methods** (may require more complex initialization or service setup):
- Additional methods from Batch B plan (`docs/progress/P2.1-BATCH-2.md`)
- Methods requiring complex service dependencies
- Methods with validation/transformation logic
### Service Initialization Needs
Before continuing, may need to:
- Initialize `DailyNotificationScheduler` (requires `AlarmManager`)
- Initialize `DailyNotificationStorage` (may already exist via database)
- Create factory method for `DailyNotificationExactAlarmManager` initialization
@@ -185,6 +258,7 @@ Refs: docs/progress/P2.1-BATCH-1.md
## Rollback Plan
If issues arise:
1. Revert commits for this batch
2. Service methods remain unchanged (no risk)
3. Plugin methods can be restored from git history
@@ -194,4 +268,3 @@ If issues arise:
**Last Updated:** 2025-12-23
**Next Update:** After completing more Batch A methods or resolving `getExactAlarmStatus()` initialization