appsonair-react-native-apppush 0.0.1-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +540 -0
  3. package/android/build.gradle +177 -0
  4. package/android/gradle.properties +15 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/AndroidManifestNew.xml +2 -0
  7. package/android/src/main/java/com/appsonairreactnativeapppush/AppsonairReactNativeApppushModuleImpl.kt +767 -0
  8. package/android/src/main/java/com/appsonairreactnativeapppush/AppsonairReactNativeApppushPackage.kt +43 -0
  9. package/android/src/newarch/java/com/appsonairreactnativeapppush/AppsonairReactNativeApppushModule.kt +199 -0
  10. package/android/src/oldarch/java/com/appsonairreactnativeapppush/AppsonairReactNativeApppushModule.kt +249 -0
  11. package/appsonair-react-native-apppush.podspec +77 -0
  12. package/ios/AppsonairReactNativeApppush-Bridging-Header.h +12 -0
  13. package/ios/AppsonairReactNativeApppush.h +28 -0
  14. package/ios/AppsonairReactNativeApppush.mm +494 -0
  15. package/ios/AppsonairReactNativeApppushImpl.swift +594 -0
  16. package/lib/commonjs/NativeAppsonairApppush.js +48 -0
  17. package/lib/commonjs/NativeAppsonairApppush.js.map +1 -0
  18. package/lib/commonjs/index.js +686 -0
  19. package/lib/commonjs/index.js.map +1 -0
  20. package/lib/commonjs/types.js +2 -0
  21. package/lib/commonjs/types.js.map +1 -0
  22. package/lib/module/NativeAppsonairApppush.js +47 -0
  23. package/lib/module/NativeAppsonairApppush.js.map +1 -0
  24. package/lib/module/index.js +612 -0
  25. package/lib/module/index.js.map +1 -0
  26. package/lib/module/types.js +2 -0
  27. package/lib/module/types.js.map +1 -0
  28. package/lib/typescript/commonjs/package.json +1 -0
  29. package/lib/typescript/commonjs/src/NativeAppsonairApppush.d.ts +134 -0
  30. package/lib/typescript/commonjs/src/NativeAppsonairApppush.d.ts.map +1 -0
  31. package/lib/typescript/commonjs/src/index.d.ts +392 -0
  32. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  33. package/lib/typescript/commonjs/src/types.d.ts +221 -0
  34. package/lib/typescript/commonjs/src/types.d.ts.map +1 -0
  35. package/lib/typescript/module/package.json +1 -0
  36. package/lib/typescript/module/src/NativeAppsonairApppush.d.ts +134 -0
  37. package/lib/typescript/module/src/NativeAppsonairApppush.d.ts.map +1 -0
  38. package/lib/typescript/module/src/index.d.ts +392 -0
  39. package/lib/typescript/module/src/index.d.ts.map +1 -0
  40. package/lib/typescript/module/src/types.d.ts +221 -0
  41. package/lib/typescript/module/src/types.d.ts.map +1 -0
  42. package/package.json +119 -0
  43. package/react-native.config.js +14 -0
  44. package/src/NativeAppsonairApppush.ts +188 -0
  45. package/src/index.tsx +745 -0
  46. package/src/types.ts +284 -0
package/src/types.ts ADDED
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Cross-platform types for the AppsOnAir Push SDK.
3
+ *
4
+ * Where the two native SDKs disagree, this file defines the single shape the
5
+ * wrapper exposes and the native bridges normalise to. Every such decision
6
+ * traces to a row in `appsonair-push-notification-android/CROSS_PLATFORM_PARITY.md`;
7
+ * the row id is cited so the reason survives.
8
+ */
9
+
10
+ // MARK: - Configuration
11
+
12
+ export interface PushConfig {
13
+ /** Print SDK logs to the console. Keep `false` in production. */
14
+ debug?: boolean;
15
+ }
16
+
17
+ /**
18
+ * There is deliberately no `appGroupId` option.
19
+ *
20
+ * The parity audit's A1 row proposes one, but the native iOS initializer is
21
+ * `initialize(debug:swizzle:)` — it takes no App Group argument. iOS resolves the
22
+ * group itself, from an `AppsOnAirAppGroup` string in the app's Info.plist, else
23
+ * the convention `group.<bundle-id>.appsonair`. Accepting the value here would be
24
+ * a knob that silently does nothing, so it is configured where it is actually
25
+ * read. See the README's iOS setup section.
26
+ */
27
+
28
+ // MARK: - Notification payload
29
+
30
+ /** An action button attached to the notification payload. */
31
+ export interface NotificationActionButton {
32
+ id: string;
33
+ title: string;
34
+ }
35
+
36
+ /** A media attachment, or one entry synthesised from `imageUrl`. */
37
+ export interface NotificationAttachment {
38
+ id: string | null;
39
+ url: string;
40
+ }
41
+
42
+ /**
43
+ * A received or tapped notification.
44
+ *
45
+ * Parity C1: iOS emits 14 fields, Android 6. This is the union — fields the
46
+ * running platform cannot source resolve to `null` (or `[]`), never `undefined`.
47
+ * The per-field platform notes below are the authoritative support matrix.
48
+ */
49
+ export interface PushNotification {
50
+ /** Payload `notification_id`. */
51
+ id: string | null;
52
+ /** Payload `campaign_id`. **iOS only** — `null` on Android. */
53
+ campaignId: string | null;
54
+ /** Payload `template_id`. **iOS only** — `null` on Android. */
55
+ templateId: string | null;
56
+ /** Payload `sent_at`, ISO-8601 exactly as received. **iOS only.** */
57
+ sentAt: string | null;
58
+
59
+ title: string | null;
60
+ /** Second line above the body. **iOS only** — Android has no subtitle concept. */
61
+ subtitle: string | null;
62
+ body: string | null;
63
+
64
+ /** Payload `url` — deep link opened on tap. */
65
+ launchUrl: string | null;
66
+ /** Payload `image_url`. On iOS this loses to `attachments` when both are present. */
67
+ imageUrl: string | null;
68
+ /** Payload `attachments`. **iOS only** — always `[]` on Android. */
69
+ attachments: NotificationAttachment[];
70
+ /** Payload `actions`. Supported on both platforms. */
71
+ actionButtons: NotificationActionButton[];
72
+ /** Payload `badge_increment`. **iOS only** — `null` on Android. */
73
+ badgeIncrement: number | null;
74
+ /** Payload `collapse_id` (iOS) / `collapse_key` (Android). */
75
+ collapseId: string | null;
76
+ /** Sound file name in `res/raw`, no extension. **Android only** — `null` on iOS. */
77
+ sound: string | null;
78
+ /** Notification channel id. **Android only** — `null` on iOS. */
79
+ channelId: string | null;
80
+
81
+ /**
82
+ * Flattened string map of the payload's custom keys.
83
+ *
84
+ * Parity C1: Android's native `data` map is already `Map<String, String>`;
85
+ * the iOS bridge flattens `userInfo` to match, so this field has the same
86
+ * meaning on both platforms.
87
+ */
88
+ data: Record<string, string>;
89
+
90
+ /**
91
+ * The complete unmodified payload. Shapes differ per platform (APNs `userInfo`
92
+ * vs the FCM data bundle) — reach for `data` first, and use this only for keys
93
+ * that survive neither flattening nor the typed fields above.
94
+ */
95
+ rawPayload: Record<string, unknown>;
96
+ }
97
+
98
+ // MARK: - Events
99
+
100
+ export interface TokenUpdatedEvent {
101
+ /** APNs hex token on iOS, FCM registration token on Android. */
102
+ token: string;
103
+ /**
104
+ * Parity B1/C8: which APNs endpoint the backend must use.
105
+ * **iOS only** — always `null` on Android, where FCM routes for you.
106
+ */
107
+ environment: 'sandbox' | 'production' | null;
108
+ }
109
+
110
+ export interface NotificationOpenedEvent {
111
+ notification: PushNotification;
112
+ /** `null` when the notification body was tapped; set for an action-button tap. */
113
+ actionId: string | null;
114
+ /** The payload's launch URL, if any. */
115
+ url: string | null;
116
+ }
117
+
118
+ export interface NotificationReceivedEvent {
119
+ notification: PushNotification;
120
+ }
121
+
122
+ /**
123
+ * Fired while the app is in the foreground, before the notification is displayed.
124
+ *
125
+ * Parity B4/F7: `preventDefault()` is exposed, presentation options are not —
126
+ * iOS lets the OS present, Android builds the notification itself, so any
127
+ * option set would mean different things on each platform.
128
+ */
129
+ export interface NotificationWillDisplayEvent {
130
+ notification: PushNotification;
131
+ /**
132
+ * Suppress the system notification. Must be called synchronously in the handler.
133
+ *
134
+ * **Honoured on Android only.** The Android SDK calls its foreground listeners
135
+ * on FCM's background thread, so the bridge can park there while JS decides.
136
+ * iOS's `handleWillPresent(notification:)` returns its presentation options
137
+ * synchronously with no completion handler to hold open, so by the time a JS
138
+ * handler runs the notification has already been presented. On iOS this event
139
+ * is informational and calling `preventDefault()` does nothing.
140
+ */
141
+ preventDefault: () => void;
142
+ }
143
+
144
+ export interface PermissionChangedEvent {
145
+ granted: boolean;
146
+ }
147
+
148
+ export interface PushSubscriptionState {
149
+ id: string | null;
150
+ token: string | null;
151
+ optedIn: boolean;
152
+ }
153
+
154
+ export interface PushSubscriptionChangedEvent {
155
+ previous: PushSubscriptionState;
156
+ current: PushSubscriptionState;
157
+ }
158
+
159
+ export interface UserState {
160
+ /** The external id linked via `login()`. `null` while anonymous. */
161
+ externalId: string | null;
162
+ /** The AppsOnAir-assigned device id. */
163
+ appsOnAirId: string;
164
+ }
165
+
166
+ export interface UserStateChangedEvent {
167
+ current: UserState;
168
+ }
169
+
170
+ /**
171
+ * A data-only push that is delivered without being displayed.
172
+ *
173
+ * Parity F5 — supported on both platforms, but the two are triggered
174
+ * differently and your backend has to send for both:
175
+ *
176
+ * - **iOS** uses the APNs transport flag, `content-available: 1`.
177
+ * - **Android** has no transport-level equivalent in FCM, so the SDK keys off a
178
+ * `silent: "true"` entry in the data payload. A data push *without* that key
179
+ * renders as a visible notification and fires no listener here.
180
+ *
181
+ * On iOS the OS completion handler is invoked as soon as the event is emitted,
182
+ * so a handler cannot extend the background execution window.
183
+ */
184
+ export interface SilentNotificationEvent {
185
+ data: Record<string, string>;
186
+ }
187
+
188
+ /** Firebase Installation ID. Parity B2: **Android only.** */
189
+ export interface InstallationIdEvent {
190
+ id: string;
191
+ }
192
+
193
+ /**
194
+ * Parity C5: the union of both platforms' error codes in one casing.
195
+ * `tokenRegistrationFailed` is the shared name for iOS `apnsRegistrationFailed`
196
+ * and Android `TOKEN_FETCH_FAILED`.
197
+ *
198
+ * Native `PushError.cause` is dropped — a `Throwable` does not cross the bridge.
199
+ */
200
+ export type PushErrorCode =
201
+ | 'notInitialized'
202
+ | 'permissionDenied'
203
+ /** **Android only.** No `google-services.json`, or the plugin was not applied. */
204
+ | 'firebaseNotConfigured'
205
+ | 'tokenRegistrationFailed'
206
+ | 'installationIdFetchFailed'
207
+ | 'unknown';
208
+
209
+ export interface PushErrorEvent {
210
+ code: PushErrorCode;
211
+ message: string;
212
+ }
213
+
214
+ // MARK: - Enums
215
+
216
+ /** Parity C6: one casing for both platforms; the bridge maps to the native enum. */
217
+ export type LogLevel =
218
+ | 'none'
219
+ | 'fatal'
220
+ | 'error'
221
+ | 'warn'
222
+ | 'info'
223
+ | 'debug'
224
+ | 'verbose';
225
+
226
+ /**
227
+ * Parity C7: iOS reports all five states. Android has no granular type and
228
+ * reports only `authorized` or `denied` — it can never return `notDetermined`,
229
+ * so do not branch on that value for a cross-platform pre-prompt.
230
+ */
231
+ export type PermissionStatus =
232
+ | 'notDetermined'
233
+ | 'denied'
234
+ | 'authorized'
235
+ | 'provisional'
236
+ | 'ephemeral';
237
+
238
+ export interface RequestPermissionOptions {
239
+ /**
240
+ * When permission was already permanently denied, send the user to the OS
241
+ * settings screen instead of failing silently. Defaults to `false`.
242
+ */
243
+ fallbackToSettings?: boolean;
244
+ }
245
+
246
+ // MARK: - Android notification channels
247
+
248
+ /** Mirrors `NotificationManager.IMPORTANCE_*`. */
249
+ export type NotificationChannelImportance =
250
+ | 'none'
251
+ | 'min'
252
+ | 'low'
253
+ | 'default'
254
+ | 'high'
255
+ | 'max';
256
+
257
+ /** Parity F4: **Android only.** A no-op on iOS, which has no channel concept. */
258
+ export interface NotificationChannelConfig {
259
+ id: string;
260
+ name: string;
261
+ importance?: NotificationChannelImportance;
262
+ description?: string;
263
+ /** Sound file name in `res/raw`, without extension. */
264
+ sound?: string;
265
+ }
266
+
267
+ // MARK: - Background sync
268
+
269
+ /**
270
+ * Parity H1: the two native APIs share no method name, parameter, or unit —
271
+ * iOS takes seconds via BGTaskScheduler, Android minutes via WorkManager. This
272
+ * is the single shape; each bridge converts.
273
+ */
274
+ export interface BackgroundSyncOptions {
275
+ /** Defaults to 60. iOS converts to seconds and treats it as a *minimum* delay. */
276
+ intervalMinutes?: number;
277
+ /** Android WorkManager constraint. Ignored on iOS. Defaults to `true`. */
278
+ requireNetwork?: boolean;
279
+ }
280
+
281
+ /** Returned by every `on*` subscribe helper. Call `remove()` to unsubscribe. */
282
+ export interface Subscription {
283
+ remove: () => void;
284
+ }