refactor: rename internal notification ID prefix from predictive_ to api_
This commit is contained in:
@@ -170,10 +170,10 @@ object DailyNotificationConstants {
|
||||
const val DUAL_NOTIFY_SCHEDULE_ID_PREFIX = "dual_notify_"
|
||||
|
||||
/**
|
||||
* Prefix for API/predictive batch notification schedule IDs (`predictive_<epochMillis>`).
|
||||
* Matches iOS [predictiveNotificationPrefix]; must not overlap daily reminders or dual schedules.
|
||||
* Prefix for API-managed batch notification schedule IDs (`api_<epochMillis>`).
|
||||
* Matches iOS [apiNotificationPrefix]; must not overlap daily reminders or dual schedules.
|
||||
*/
|
||||
const val PREDICTIVE_SCHEDULE_ID_PREFIX = "predictive_"
|
||||
const val API_SCHEDULE_ID_PREFIX = "api_"
|
||||
|
||||
// ============================================================
|
||||
// Request Code Versioning
|
||||
|
||||
@@ -745,7 +745,7 @@ open class DailyNotificationPlugin : Plugin() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one-shot API/predictive notifications at epoch-ms timestamps (additive; does not clear others).
|
||||
* Add one-shot API-managed notifications at epoch-ms timestamps (additive; does not clear others).
|
||||
* Caller should invoke [clearPredictiveNotifications] first when replacing a full batch.
|
||||
*/
|
||||
@PluginMethod
|
||||
@@ -770,7 +770,7 @@ open class DailyNotificationPlugin : Plugin() {
|
||||
is Number -> raw.toLong()
|
||||
else -> continue
|
||||
}
|
||||
if (ScheduleHelper.schedulePredictiveNotification(context!!, getDatabase(), epochMillis)) {
|
||||
if (ScheduleHelper.scheduleApiNotification(context!!, getDatabase(), epochMillis)) {
|
||||
scheduledCount++
|
||||
}
|
||||
}
|
||||
@@ -785,7 +785,7 @@ open class DailyNotificationPlugin : Plugin() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel only API/predictive notification schedules (`predictive_*`).
|
||||
* Cancel only API-managed notification schedules (`api_*`).
|
||||
* Does not affect Daily Reminders, user-created schedules, dual schedules, or fetch jobs.
|
||||
*/
|
||||
@PluginMethod
|
||||
@@ -795,13 +795,13 @@ open class DailyNotificationPlugin : Plugin() {
|
||||
if (context == null) {
|
||||
return@launch call.reject("Context not available")
|
||||
}
|
||||
Log.i("DailyNotificationPlugin", "Clearing predictive notifications")
|
||||
val cleared = ScheduleHelper.clearPredictiveSchedules(context!!, getDatabase())
|
||||
Log.i("DailyNotificationPlugin", "Cleared $cleared predictive schedules")
|
||||
Log.i("DailyNotificationPlugin", "Clearing API-managed notifications")
|
||||
val cleared = ScheduleHelper.clearApiSchedules(context!!, getDatabase())
|
||||
Log.i("DailyNotificationPlugin", "Cleared $cleared API-managed schedule(s)")
|
||||
call.resolve()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to clear predictive notifications", e)
|
||||
call.reject("Failed to clear predictive notifications: ${e.message}")
|
||||
Log.e(TAG, "Failed to clear API-managed notifications", e)
|
||||
call.reject("Failed to clear API-managed notifications: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2999,12 +2999,12 @@ object ScheduleHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule one API/predictive notification at an epoch-ms trigger time.
|
||||
* Uses the predictive_ ID namespace so [clearPredictiveSchedules] can replace batches safely.
|
||||
* Schedule one API-managed notification at an epoch-ms trigger time.
|
||||
* Uses the api_ ID namespace so [clearApiSchedules] can replace batches safely.
|
||||
*
|
||||
* @return true when scheduled, false when timestamp is stale (in the past)
|
||||
*/
|
||||
suspend fun schedulePredictiveNotification(
|
||||
suspend fun scheduleApiNotification(
|
||||
context: Context,
|
||||
database: DailyNotificationDatabase,
|
||||
epochMillis: Long,
|
||||
@@ -3016,9 +3016,9 @@ object ScheduleHelper {
|
||||
return false
|
||||
}
|
||||
|
||||
// Predictive/API notifications use the predictive_ namespace so they can be safely
|
||||
// API-managed notifications use the api_ namespace so they can be safely
|
||||
// replaced without affecting Daily Reminder schedules.
|
||||
val scheduleId = "${DailyNotificationConstants.PREDICTIVE_SCHEDULE_ID_PREFIX}${epochMillis}"
|
||||
val scheduleId = "${DailyNotificationConstants.API_SCHEDULE_ID_PREFIX}${epochMillis}"
|
||||
|
||||
val config = UserNotificationConfig(
|
||||
enabled = true,
|
||||
@@ -3131,24 +3131,24 @@ object ScheduleHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel only predictive/API notification schedules (`predictive_*` prefix).
|
||||
* Cancel only API-managed notification schedules (`api_*` prefix).
|
||||
* Removes matching alarms, persisted schedules, and notification content.
|
||||
* Does not disable Daily Reminders, user schedules, dual schedules, or fetch jobs.
|
||||
*/
|
||||
suspend fun clearPredictiveSchedules(context: Context, database: DailyNotificationDatabase): Int {
|
||||
suspend fun clearApiSchedules(context: Context, database: DailyNotificationDatabase): Int {
|
||||
return try {
|
||||
val prefix = DailyNotificationConstants.PREDICTIVE_SCHEDULE_ID_PREFIX
|
||||
val prefix = DailyNotificationConstants.API_SCHEDULE_ID_PREFIX
|
||||
val all = database.scheduleDao().getAll()
|
||||
val predictiveSchedules = all.filter { it.id.startsWith(prefix) }
|
||||
if (predictiveSchedules.isEmpty()) {
|
||||
Log.d("ScheduleHelper", "clearPredictiveSchedules: no predictive schedules found")
|
||||
val apiSchedules = all.filter { it.id.startsWith(prefix) }
|
||||
if (apiSchedules.isEmpty()) {
|
||||
Log.d("ScheduleHelper", "clearApiSchedules: no API-managed schedules found")
|
||||
return 0
|
||||
}
|
||||
|
||||
val notificationManager =
|
||||
context.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager
|
||||
|
||||
predictiveSchedules.forEach { schedule ->
|
||||
apiSchedules.forEach { schedule ->
|
||||
NotifyReceiver.cancelNotification(
|
||||
context,
|
||||
scheduleId = schedule.id,
|
||||
@@ -3157,7 +3157,7 @@ object ScheduleHelper {
|
||||
notificationManager.cancel(schedule.id.hashCode())
|
||||
}
|
||||
|
||||
predictiveSchedules.forEach { database.scheduleDao().deleteById(it.id) }
|
||||
apiSchedules.forEach { database.scheduleDao().deleteById(it.id) }
|
||||
|
||||
database.notificationContentDao().getAllNotifications()
|
||||
.filter { it.id.startsWith(prefix) }
|
||||
@@ -3166,10 +3166,10 @@ object ScheduleHelper {
|
||||
notificationManager.cancel(content.id.hashCode())
|
||||
}
|
||||
|
||||
Log.i("ScheduleHelper", "clearPredictiveSchedules: cancelled and removed ${predictiveSchedules.size} predictive schedule(s)")
|
||||
predictiveSchedules.size
|
||||
Log.i("ScheduleHelper", "clearApiSchedules: cancelled and removed ${apiSchedules.size} API-managed schedule(s)")
|
||||
apiSchedules.size
|
||||
} catch (e: Exception) {
|
||||
Log.e("ScheduleHelper", "clearPredictiveSchedules failed", e)
|
||||
Log.e("ScheduleHelper", "clearApiSchedules failed", e)
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.robolectric.annotation.Config
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(sdk = [28])
|
||||
class ClearPredictiveSchedulesTest {
|
||||
class ClearApiSchedulesTest {
|
||||
|
||||
private lateinit var context: Context
|
||||
private lateinit var database: DailyNotificationDatabase
|
||||
@@ -32,12 +32,12 @@ class ClearPredictiveSchedulesTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun schedulePredictiveNotification_usesPredictiveIdNamespace() {
|
||||
fun scheduleApiNotification_usesApiIdNamespace() {
|
||||
val epochMillis = System.currentTimeMillis() + 300_000
|
||||
val expectedId = "${DailyNotificationConstants.PREDICTIVE_SCHEDULE_ID_PREFIX}${epochMillis}"
|
||||
val expectedId = "${DailyNotificationConstants.API_SCHEDULE_ID_PREFIX}${epochMillis}"
|
||||
|
||||
val scheduled = runBlocking {
|
||||
ScheduleHelper.schedulePredictiveNotification(context, database, epochMillis)
|
||||
ScheduleHelper.scheduleApiNotification(context, database, epochMillis)
|
||||
}
|
||||
|
||||
assertEquals(true, scheduled)
|
||||
@@ -47,9 +47,9 @@ class ClearPredictiveSchedulesTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clearPredictiveSchedules_removesOnlyPredictiveAndPreservesDailyReminder() {
|
||||
fun clearApiSchedules_removesOnlyApiManagedAndPreservesDailyReminder() {
|
||||
val dailyReminderId = DailyNotificationConstants.DEFAULT_SCHEDULE_ID
|
||||
val predictiveId = "${DailyNotificationConstants.PREDICTIVE_SCHEDULE_ID_PREFIX}1740000000000"
|
||||
val apiId = "${DailyNotificationConstants.API_SCHEDULE_ID_PREFIX}1740000000000"
|
||||
val userScheduleId = "notify_1740000000001"
|
||||
|
||||
runBlocking {
|
||||
@@ -64,7 +64,7 @@ class ClearPredictiveSchedulesTest {
|
||||
)
|
||||
database.scheduleDao().upsert(
|
||||
Schedule(
|
||||
id = predictiveId,
|
||||
id = apiId,
|
||||
kind = "notify",
|
||||
enabled = true,
|
||||
nextRunAt = System.currentTimeMillis() + 120_000
|
||||
@@ -81,14 +81,14 @@ class ClearPredictiveSchedulesTest {
|
||||
}
|
||||
|
||||
val cleared = runBlocking {
|
||||
ScheduleHelper.clearPredictiveSchedules(context, database)
|
||||
ScheduleHelper.clearApiSchedules(context, database)
|
||||
}
|
||||
|
||||
assertEquals(1, cleared)
|
||||
|
||||
runBlocking {
|
||||
assertNotNull(database.scheduleDao().getById(dailyReminderId))
|
||||
assertNull(database.scheduleDao().getById(predictiveId))
|
||||
assertNull(database.scheduleDao().getById(apiId))
|
||||
assertNotNull(database.scheduleDao().getById(userScheduleId))
|
||||
}
|
||||
}
|
||||
@@ -32,9 +32,9 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
// Background task identifiers
|
||||
private let fetchTaskIdentifier = "org.timesafari.dailynotification.fetch"
|
||||
private let notifyTaskIdentifier = "org.timesafari.dailynotification.notify"
|
||||
/// Prefix for deterministic UNNotificationRequest identifiers: `predictive_\(Int(timestamp))` with `timestamp` in epoch milliseconds.
|
||||
private let predictiveNotificationPrefix = "predictive_"
|
||||
/// Stable identifier for the dual (New Activity) user notification. Used for replace and cancelDualSchedule; must not conflict with Daily Reminder (`predictive_*`).
|
||||
/// Prefix for deterministic UNNotificationRequest identifiers: `api_\(Int(timestamp))` with `timestamp` in epoch milliseconds.
|
||||
private let apiNotificationPrefix = "api_"
|
||||
/// Stable identifier for the dual (New Activity) user notification. Used for replace and cancelDualSchedule; must not conflict with Daily Reminder (`api_*`).
|
||||
private let dualNotificationRequestIdentifier = "org.timesafari.dailynotification.dual"
|
||||
/// UserDefaults key for persisted dual schedule config (userNotification + relationship) for relationship resolution when fetch completes.
|
||||
private let dualScheduleConfigKey = "dual_schedule_config"
|
||||
@@ -430,7 +430,7 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
/// Cancel the dual (New Activity) schedule only. Does not affect Daily Reminder (`predictive_*`).
|
||||
/// Cancel the dual (New Activity) schedule only. Does not affect Daily Reminder (`api_*`).
|
||||
@objc func cancelDualSchedule(_ call: CAPPluginCall) {
|
||||
do {
|
||||
performCancelDualSchedule()
|
||||
@@ -1085,7 +1085,7 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
return interval > 0 ? interval : (24 * 60 * 60)
|
||||
}
|
||||
|
||||
/// Epoch milliseconds for the next local occurrence of `hour`:`minute` (used only to build predictive IDs from HH:mm schedules).
|
||||
/// Epoch milliseconds for the next local occurrence of `hour`:`minute` (used only to build API notification IDs from HH:mm schedules).
|
||||
private func epochMillisNextDailyOccurrence(hour: Int, minute: Int) -> Int64 {
|
||||
var comp = DateComponents()
|
||||
comp.hour = hour
|
||||
@@ -1097,12 +1097,12 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
return Int64(next.timeIntervalSince1970 * 1000)
|
||||
}
|
||||
|
||||
private func predictiveNotificationId(epochMillis: Int64) -> String {
|
||||
"\(predictiveNotificationPrefix)\(epochMillis)"
|
||||
private func apiNotificationId(epochMillis: Int64) -> String {
|
||||
"\(apiNotificationPrefix)\(epochMillis)"
|
||||
}
|
||||
|
||||
/// Reads persisted millis for a reminder, or derives from stored `time` (HH:mm) for legacy rows.
|
||||
private func predictiveEpochMillis(from reminder: [String: Any]) -> Int64? {
|
||||
private func apiEpochMillis(from reminder: [String: Any]) -> Int64? {
|
||||
if let n = reminder["predictiveEpochMillis"] as? NSNumber {
|
||||
return n.int64Value
|
||||
}
|
||||
@@ -1118,22 +1118,22 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
return epochMillisNextDailyOccurrence(hour: hour, minute: minute)
|
||||
}
|
||||
|
||||
// MARK: - Predictive batch API (replace-all UNUserNotificationCenter)
|
||||
// MARK: - API batch notifications (replace-all UNUserNotificationCenter)
|
||||
|
||||
/// Removes only pending and delivered notifications whose identifiers begin with `predictive_`. Does not touch dual/org IDs or other stacks.
|
||||
/// Removes only pending and delivered notifications whose identifiers begin with `api_`. Does not touch dual/org IDs or other stacks.
|
||||
@objc func clearAllNotifications(_ call: CAPPluginCall) {
|
||||
NSLog("DNP-BATCH: clearAllNotifications — removing predictive_* pending and delivered only")
|
||||
print("DNP-BATCH: clearAllNotifications — removing predictive_* pending and delivered only")
|
||||
NSLog("DNP-BATCH: clearAllNotifications — removing api_* pending and delivered only")
|
||||
print("DNP-BATCH: clearAllNotifications — removing api_* pending and delivered only")
|
||||
let center = notificationCenter
|
||||
let prefix = predictiveNotificationPrefix
|
||||
let prefix = apiNotificationPrefix
|
||||
let group = DispatchGroup()
|
||||
|
||||
group.enter()
|
||||
center.getPendingNotificationRequests { requests in
|
||||
let ids = requests.map { $0.identifier }.filter { $0.hasPrefix(prefix) }
|
||||
center.removePendingNotificationRequests(withIdentifiers: ids)
|
||||
NSLog("DNP-BATCH: cleared \(ids.count) pending predictive id(s)")
|
||||
print("DNP-BATCH: cleared \(ids.count) pending predictive id(s)")
|
||||
NSLog("DNP-BATCH: cleared \(ids.count) pending API notification id(s)")
|
||||
print("DNP-BATCH: cleared \(ids.count) pending API notification id(s)")
|
||||
group.leave()
|
||||
}
|
||||
|
||||
@@ -1141,8 +1141,8 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
center.getDeliveredNotifications { notifications in
|
||||
let ids = notifications.map { $0.request.identifier }.filter { $0.hasPrefix(prefix) }
|
||||
center.removeDeliveredNotifications(withIdentifiers: ids)
|
||||
NSLog("DNP-BATCH: cleared \(ids.count) delivered predictive id(s)")
|
||||
print("DNP-BATCH: cleared \(ids.count) delivered predictive id(s)")
|
||||
NSLog("DNP-BATCH: cleared \(ids.count) delivered API notification id(s)")
|
||||
print("DNP-BATCH: cleared \(ids.count) delivered API notification id(s)")
|
||||
group.leave()
|
||||
}
|
||||
|
||||
@@ -1152,7 +1152,7 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
}
|
||||
|
||||
/// Add one-shot reminders at epoch-ms timestamps. Does not remove other requests; identical IDs replace pending entries. Caller should clear first if needed.
|
||||
/// Adds/overwrites predictive notifications using deterministic IDs.
|
||||
/// Adds/overwrites API-managed notifications using deterministic IDs.
|
||||
/// Does NOT clear existing notifications. Caller is responsible for lifecycle.
|
||||
@objc func scheduleNotifications(_ call: CAPPluginCall) {
|
||||
guard let timestamps = call.getArray("timestamps", Double.self) else {
|
||||
@@ -1182,7 +1182,7 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
content.title = "Reminder"
|
||||
content.body = "You have a scheduled notification"
|
||||
|
||||
let id = "\(predictiveNotificationPrefix)\(Int(ts))"
|
||||
let id = "\(apiNotificationPrefix)\(Int(ts))"
|
||||
|
||||
NSLog("DNP-BATCH: scheduling ts=\(ts) interval=\(interval)s id=\(id)")
|
||||
print("DNP-BATCH: scheduling ts=\(ts) interval=\(interval)s id=\(id)")
|
||||
@@ -1262,7 +1262,7 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
)
|
||||
|
||||
let epochMillis = epochMillisNextDailyOccurrence(hour: hour, minute: minute)
|
||||
let requestId = predictiveNotificationId(epochMillis: epochMillis)
|
||||
let requestId = apiNotificationId(epochMillis: epochMillis)
|
||||
|
||||
let request = UNNotificationRequest(
|
||||
identifier: requestId,
|
||||
@@ -1305,8 +1305,8 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
// Cancel the notification (ID from stored epoch millis)
|
||||
let reminders = getRemindersFromUserDefaults()
|
||||
if let stored = reminders.first(where: { ($0["id"] as? String) == reminderId }),
|
||||
let epochMillis = predictiveEpochMillis(from: stored) {
|
||||
let requestId = predictiveNotificationId(epochMillis: epochMillis)
|
||||
let epochMillis = apiEpochMillis(from: stored) {
|
||||
let requestId = apiNotificationId(epochMillis: epochMillis)
|
||||
notificationCenter.removePendingNotificationRequests(withIdentifiers: [requestId])
|
||||
}
|
||||
|
||||
@@ -1321,15 +1321,15 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
|
||||
// Get pending notifications
|
||||
notificationCenter.getPendingNotificationRequests { requests in
|
||||
let reminderRequests = requests.filter { $0.identifier.hasPrefix(self.predictiveNotificationPrefix) }
|
||||
let reminderRequests = requests.filter { $0.identifier.hasPrefix(self.apiNotificationPrefix) }
|
||||
|
||||
// Get stored reminder data from UserDefaults
|
||||
let reminders = self.getRemindersFromUserDefaults()
|
||||
|
||||
var result: [[String: Any]] = []
|
||||
for reminder in reminders {
|
||||
let expectedId: String? = self.predictiveEpochMillis(from: reminder).map {
|
||||
self.predictiveNotificationId(epochMillis: $0)
|
||||
let expectedId: String? = self.apiEpochMillis(from: reminder).map {
|
||||
self.apiNotificationId(epochMillis: $0)
|
||||
}
|
||||
let isScheduled = reminderRequests.contains { expectedId != nil && $0.identifier == expectedId }
|
||||
var reminderInfo = reminder
|
||||
@@ -1352,8 +1352,8 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
// Cancel existing reminder (before UserDefaults update)
|
||||
let remindersBeforeUpdate = getRemindersFromUserDefaults()
|
||||
if let stored = remindersBeforeUpdate.first(where: { ($0["id"] as? String) == reminderId }),
|
||||
let epochMillis = predictiveEpochMillis(from: stored) {
|
||||
let oldRequestId = predictiveNotificationId(epochMillis: epochMillis)
|
||||
let epochMillis = apiEpochMillis(from: stored) {
|
||||
let oldRequestId = apiNotificationId(epochMillis: epochMillis)
|
||||
notificationCenter.removePendingNotificationRequests(withIdentifiers: [oldRequestId])
|
||||
}
|
||||
|
||||
@@ -1421,7 +1421,7 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
)
|
||||
|
||||
let epochMillis = epochMillisNextDailyOccurrence(hour: hour, minute: minute)
|
||||
let requestId = predictiveNotificationId(epochMillis: epochMillis)
|
||||
let requestId = apiNotificationId(epochMillis: epochMillis)
|
||||
|
||||
let request = UNNotificationRequest(
|
||||
identifier: requestId,
|
||||
@@ -1701,7 +1701,7 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
|
||||
let fireDate = Date().addingTimeInterval(TimeInterval(validSeconds))
|
||||
let epochMillis = Int64(fireDate.timeIntervalSince1970 * 1000)
|
||||
let requestId = predictiveNotificationId(epochMillis: epochMillis)
|
||||
let requestId = apiNotificationId(epochMillis: epochMillis)
|
||||
let request = UNNotificationRequest(
|
||||
identifier: requestId,
|
||||
content: notificationContent,
|
||||
@@ -2792,7 +2792,7 @@ extension DailyNotificationPlugin {
|
||||
methods.append(CAPPluginMethod(name: "getScheduledReminders", returnType: CAPPluginReturnPromise))
|
||||
methods.append(CAPPluginMethod(name: "updateDailyReminder", returnType: CAPPluginReturnPromise))
|
||||
|
||||
// Predictive batch API (replace-all UNUserNotificationCenter)
|
||||
// API batch notifications (replace-all UNUserNotificationCenter)
|
||||
methods.append(CAPPluginMethod(name: "clearAllNotifications", returnType: CAPPluginReturnPromise))
|
||||
methods.append(CAPPluginMethod(name: "scheduleNotifications", returnType: CAPPluginReturnPromise))
|
||||
|
||||
|
||||
@@ -603,12 +603,12 @@ export interface DailyNotificationPlugin {
|
||||
getLastNotification(): Promise<NotificationResponse | null>;
|
||||
cancelAllNotifications(): Promise<void>;
|
||||
/**
|
||||
* Add one-shot API/predictive notifications at epoch-ms timestamps (additive).
|
||||
* Android uses `predictive_<timestamp>` schedule IDs; caller should clear first when replacing a batch.
|
||||
* Add one-shot API-managed notifications at epoch-ms timestamps (additive).
|
||||
* Android uses `api_<timestamp>` schedule IDs; caller should clear first when replacing a batch.
|
||||
*/
|
||||
scheduleNotifications(options: { timestamps: number[] }): Promise<void>;
|
||||
/**
|
||||
* Android only: cancel API/predictive notification schedules (`predictive_*`) without
|
||||
* Android only: cancel API-managed notification schedules (`api_*`) without
|
||||
* affecting Daily Reminders, user schedules, dual schedules, or fetch jobs.
|
||||
*/
|
||||
clearPredictiveNotifications(): Promise<void>;
|
||||
|
||||
Reference in New Issue
Block a user