WIP: new-activity notification #231

Draft
trentlarson wants to merge 80 commits from notify-api into master
5 changed files with 49 additions and 47 deletions
Showing only changes of commit a1f94300ad - Show all commits

View File

@@ -16,8 +16,11 @@ public class NotificationInspectorPlugin: CAPPlugin, CAPBridgedPlugin {
]
}
/// Stable wall-clock target: plugin `userInfo["scheduled_time"]`, or epoch ms in `predictive_<ms>` identifiers.
/// Stable wall-clock target: plugin `userInfo["scheduled_time"]`, or epoch ms in API notification identifiers.
/// (Apple documents `UNTimeIntervalNotificationTrigger.nextTriggerDate()` as resampling ~now+interval when queried.)
/// API notification identifiers use the `api_` prefix.
private static let apiNotificationIdentifierPrefix = "api_"
private func wallClockMillis(from request: UNNotificationRequest) -> (ms: Int64, source: String)? {
let info = request.content.userInfo
if let v = info["scheduled_time"] as? Int64 {
@@ -29,11 +32,11 @@ public class NotificationInspectorPlugin: CAPPlugin, CAPBridgedPlugin {
if let i = info["scheduled_time"] as? Int {
return (Int64(i), "userInfo.scheduled_time")
}
let prefix = "predictive_"
let prefix = Self.apiNotificationIdentifierPrefix
if request.identifier.hasPrefix(prefix) {
let suffix = String(request.identifier.dropFirst(prefix.count))
if let ms = Int64(suffix) {
return (ms, "identifier(predictive_)")
return (ms, "identifier (API notification)")
}
}
return nil

70
package-lock.json generated
View File

@@ -4459,9 +4459,9 @@
}
},
"node_modules/@expo/cli": {
"version": "56.1.13",
"resolved": "https://registry.npmjs.org/@expo/cli/-/cli-56.1.13.tgz",
"integrity": "sha512-7n5VzlBr7TKW0BgWgpEopWy+v8buPhMvbSEsuXD+bI1YIJBopkfWAub0qTvlc357E8wWOvV5MJXYyoeRvoOjoQ==",
"version": "56.1.14",
"resolved": "https://registry.npmjs.org/@expo/cli/-/cli-56.1.14.tgz",
"integrity": "sha512-rSH3ygjEPipEYG6dgiJ116J8KqCQ/BYKcwQDipStSh4IFWJ10RZaYP4u5B74jxfeIWjWrOeqvwB6NZfQBjaQ4Q==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -4471,7 +4471,7 @@
"@expo/devcert": "^1.2.1",
"@expo/env": "~2.3.0",
"@expo/image-utils": "^0.10.1",
"@expo/inline-modules": "^0.0.10",
"@expo/inline-modules": "^0.0.11",
"@expo/json-file": "^10.2.0",
"@expo/log-box": "^56.0.12",
"@expo/metro": "~56.0.0",
@@ -4480,9 +4480,9 @@
"@expo/osascript": "^2.6.0",
"@expo/package-manager": "^1.12.1",
"@expo/plist": "^0.7.0",
"@expo/prebuild-config": "^56.0.14",
"@expo/prebuild-config": "^56.0.15",
"@expo/require-utils": "^56.1.3",
"@expo/router-server": "^56.0.12",
"@expo/router-server": "^56.0.13",
"@expo/schema-utils": "^56.0.0",
"@expo/spawn-async": "^1.8.0",
"@expo/ws-tunnel": "^1.0.1",
@@ -4498,7 +4498,7 @@
"connect": "^3.7.0",
"debug": "^4.3.4",
"dnssd-advertise": "^1.1.4",
"expo-server": "^56.0.4",
"expo-server": "^56.0.5",
"fetch-nodeshim": "^0.4.10",
"getenv": "^2.0.0",
"glob": "^13.0.0",
@@ -5275,9 +5275,9 @@
"optional": true
},
"node_modules/@expo/fingerprint": {
"version": "0.19.3",
"resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.19.3.tgz",
"integrity": "sha512-w9Au2IVrtc0Ct+WRa05DVHGNHXYq6VyPZWuFP+5x055OeZ5q6k5Yg+aJ1gfShmjdOhDftRcsvmWmTdTZlWaTZw==",
"version": "0.19.4",
"resolved": "https://registry.npmjs.org/@expo/fingerprint/-/fingerprint-0.19.4.tgz",
"integrity": "sha512-PsowRlO8+S7JlO8go7yhNEXp7sqlsWDE2AlCwoss7zH0dcajXFo74Fy0KdXEc4UXK7kKoHD37oDgsZ8aHSLr7A==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -5418,9 +5418,9 @@
}
},
"node_modules/@expo/inline-modules": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/@expo/inline-modules/-/inline-modules-0.0.10.tgz",
"integrity": "sha512-DKEfq877UTAmL/gOT5aFhlLNDg/EVmTSca7JQMKDGR6mjFSAcrmQf4GJNsi6ztiaqj6cTnIfoSz0hAYdnr6RJQ==",
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/@expo/inline-modules/-/inline-modules-0.0.11.tgz",
"integrity": "sha512-ZlIfKL61DPnW8YUTdMEjMA31xrDDV6p7Xi8rWYyhd5qXBV8MwGwjuJ7vKeaVaMjRqxJk1N9lv7zlfyvQpRCNNw==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -6602,9 +6602,9 @@
}
},
"node_modules/@expo/prebuild-config": {
"version": "56.0.14",
"resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-56.0.14.tgz",
"integrity": "sha512-JHdMqR7Mf5ApLC50ZwTL0Z86ezrHOMYwoSHcWT6Pha/+1TcC+/J+i7vjhP06wGXQ2Kvjt74p/3mKg2Pd12KjhQ==",
"version": "56.0.15",
"resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-56.0.15.tgz",
"integrity": "sha512-6GC+QjdCkzp/5wjsqgfu/B2+2yf5MyZMtzf9szIPrLt9uKhzV2PdyM0vU0kvbj1YT8weHCtO7bsrzimman0sjA==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -6615,7 +6615,7 @@
"@expo/json-file": "^10.2.0",
"@react-native/normalize-colors": "0.85.3",
"debug": "^4.3.1",
"expo-modules-autolinking": "~56.0.14",
"expo-modules-autolinking": "~56.0.15",
"resolve-from": "^5.0.0",
"semver": "^7.6.0"
}
@@ -6631,9 +6631,9 @@
}
},
"node_modules/@expo/prebuild-config/node_modules/expo-modules-autolinking": {
"version": "56.0.14",
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-56.0.14.tgz",
"integrity": "sha512-9ugtZkheNPYDkW4DZopY1rH2BCbUICaafUEPxRgbLDR5UNRF5K3cdHMIMEt8pxZPq2+eX4wCm+6pbSvdY/DPHg==",
"version": "56.0.15",
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-56.0.15.tgz",
"integrity": "sha512-WqpBFwLzn7DsrUkWltIjVmAjwuI1VdQ2jRMlvk1nh2kVadwdJBkSjUBQWRifsEePNhiMT/rFOovBolUU/ARt5w==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -6677,21 +6677,21 @@
}
},
"node_modules/@expo/router-server": {
"version": "56.0.12",
"resolved": "https://registry.npmjs.org/@expo/router-server/-/router-server-56.0.12.tgz",
"integrity": "sha512-RqKV2/Z8BH/z8l0ngSpG6//5xxJPaF5dTQvSfPQ0nrvCjikGMeIvyj3B9BeLnmZZhxb3gBtXqrj3irAoiIp2aQ==",
"version": "56.0.13",
"resolved": "https://registry.npmjs.org/@expo/router-server/-/router-server-56.0.13.tgz",
"integrity": "sha512-M2H2zHlRBKIPENCWV8Gqo3/9WANCS9vvOMCcdWfS9wD8XXMnDASFniS0bBoGwwS1qq1LIpYzX8m8wdv7Awy88g==",
"license": "MIT",
"optional": true,
"dependencies": {
"debug": "^4.3.4"
},
"peerDependencies": {
"@expo/metro-runtime": "^56.0.13",
"@expo/metro-runtime": "^56.0.14",
"expo": "*",
"expo-constants": "^56.0.16",
"expo-constants": "^56.0.17",
"expo-font": "^56.0.5",
"expo-router": "*",
"expo-server": "^56.0.4",
"expo-server": "^56.0.5",
"react": "*",
"react-dom": "*",
"react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1"
@@ -9923,8 +9923,8 @@
}
},
"node_modules/@timesafari/daily-notification-plugin": {
"version": "3.0.2",
"resolved": "git+https://gitea.anomalistdesign.com/trent_larson/daily-notification-plugin.git#750343ddb945b9688a46b34abcfc31116f1e4586",
"version": "3.0.4",
"resolved": "git+https://gitea.anomalistdesign.com/trent_larson/daily-notification-plugin.git#6de300b7d4d50eae8feef09ba9f7238c210866f0",
"license": "MIT",
"workspaces": [
"packages/*"
@@ -16412,14 +16412,14 @@
}
},
"node_modules/expo-asset": {
"version": "56.0.15",
"resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-56.0.15.tgz",
"integrity": "sha512-BHGi2IAOPQTcOelkUdcz1WIknfCTRjkcpYHX1azjMwgYenrVC+J5qcqJGaC8eUOWLCRtkRJWGnmFQRYtLU1nUQ==",
"version": "56.0.16",
"resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-56.0.16.tgz",
"integrity": "sha512-iIxPo6C6+/d8JxGV74ZKZbIcCz2s8//dVl7oBAj124NcPMFhzdwycFBpMqq5LUxin+lVy5cCoEjv2LD8ulnkiQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"@expo/image-utils": "^0.10.1",
"expo-constants": "~56.0.16"
"expo-constants": "~56.0.17"
},
"peerDependencies": {
"expo": "*",
@@ -16496,9 +16496,9 @@
}
},
"node_modules/expo-modules-jsi": {
"version": "56.0.7",
"resolved": "https://registry.npmjs.org/expo-modules-jsi/-/expo-modules-jsi-56.0.7.tgz",
"integrity": "sha512-iBAj4Xeh/8HT201VVxFlmf+VBfmtQV1ZUoJdLQQENm0+j9gnD2QswZLJyNo3CmNNXl46esJeLR5lpGpYZts/zA==",
"version": "56.0.8",
"resolved": "https://registry.npmjs.org/expo-modules-jsi/-/expo-modules-jsi-56.0.8.tgz",
"integrity": "sha512-tXqFU1MHrf7Ctq+Pw0qOeIPDFl1W51p9nRRZy9vVUn4GNuAk1Av0vrj0SGLvcxJvDf3aGwSzr8o8dgUsX5sG0g==",
"license": "MIT",
"optional": true,
"peerDependencies": {

View File

@@ -4,7 +4,7 @@ export type PendingNotificationInfo = {
identifier: string;
nextTriggerDate?: number | null;
triggerType?: string | null;
/** Epoch ms for intended fire time when known (userInfo or predictive_ id); stable across Refresh. */
/** Epoch ms for intended fire time when known (userInfo or API notification id); stable across refresh. */
wallClockMillis?: number | null;
wallClockSource?: string | null;
};

View File

@@ -22,7 +22,6 @@ import {
getTestMode,
} from "./NotificationDebugConfig";
import {
logNotificationClearing,
logRefreshFailure,
logRefreshStarted,
logRefreshSuccess,
@@ -708,6 +707,7 @@ export async function applyNotificationRefreshPayload(
logScheduleReplacement(timestamps.length);
// Plugin API still exposes clearPredictiveNotifications(); it clears API-managed notifications only.
const plugin = DailyNotification as unknown as {
clearPredictiveNotifications?: () => Promise<void>;
scheduleNotifications?: (options: {
@@ -717,19 +717,17 @@ export async function applyNotificationRefreshPayload(
if (typeof plugin.clearPredictiveNotifications !== "function") {
logger.warn(
"[NativeNotificationService] No clearPredictiveNotifications on plugin; cannot replace schedule",
"[NativeNotificationService] API notification clear unavailable (plugin clearPredictiveNotifications missing); cannot replace schedule",
);
logNotification(
"Schedule replacement aborted (clearPredictiveNotifications unavailable on plugin)",
"Schedule replacement aborted (API notification clear unavailable on plugin)",
);
return;
}
console.log(
"[Notifications] Clearing predictive notifications before refresh",
);
logNotificationClearing("clearPredictiveNotifications");
logNotification("Clearing API notifications before refresh");
await plugin.clearPredictiveNotifications();
logNotification("Cleared API notifications");
if (typeof plugin.scheduleNotifications !== "function") {
logger.warn(

View File

@@ -742,7 +742,8 @@
>
Logs
</router-link>
<!-- Non-production bundles only; route `dev-notifications` must exist (see `includeDevToolkitRoutes`). -->
<!-- Non-production bundles only; route `dev-notifications` must exist
(see `includeDevToolkitRoutes`). -->
<router-link
v-if="isDev"
:to="{ name: 'dev-notifications' }"