@loyalytics/swan-react-native-sdk 2.0.1

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 (204) hide show
  1. package/LICENSE +55 -0
  2. package/README.md +67 -0
  3. package/docs/IOS_NOTIFICATION_EXTENSION_SETUP.md +335 -0
  4. package/ios/README.md +64 -0
  5. package/ios/SwanNotificationServiceExtension/Info.plist +31 -0
  6. package/ios/SwanNotificationServiceExtension/NotificationService.swift +337 -0
  7. package/ios/SwanNotificationServiceExtension/SwanNotificationServiceExtension.entitlements +10 -0
  8. package/lib/commonjs/components/FooterView.js +125 -0
  9. package/lib/commonjs/components/FooterView.js.map +1 -0
  10. package/lib/commonjs/components/FullScreenView.js +172 -0
  11. package/lib/commonjs/components/FullScreenView.js.map +1 -0
  12. package/lib/commonjs/components/HeaderView.js +205 -0
  13. package/lib/commonjs/components/HeaderView.js.map +1 -0
  14. package/lib/commonjs/components/PopUpView.js +186 -0
  15. package/lib/commonjs/components/PopUpView.js.map +1 -0
  16. package/lib/commonjs/config/BatchConfig.js +53 -0
  17. package/lib/commonjs/config/BatchConfig.js.map +1 -0
  18. package/lib/commonjs/constants/ApiUrls.js +56 -0
  19. package/lib/commonjs/constants/ApiUrls.js.map +1 -0
  20. package/lib/commonjs/core/EventQueueManager.js +345 -0
  21. package/lib/commonjs/core/EventQueueManager.js.map +1 -0
  22. package/lib/commonjs/core/FlushManager.js +245 -0
  23. package/lib/commonjs/core/FlushManager.js.map +1 -0
  24. package/lib/commonjs/core/NetworkMonitor.js +97 -0
  25. package/lib/commonjs/core/NetworkMonitor.js.map +1 -0
  26. package/lib/commonjs/index.js +3506 -0
  27. package/lib/commonjs/index.js.map +1 -0
  28. package/lib/commonjs/providers/FirebasePushProvider.js +130 -0
  29. package/lib/commonjs/providers/FirebasePushProvider.js.map +1 -0
  30. package/lib/commonjs/providers/NullPushProvider.js +59 -0
  31. package/lib/commonjs/providers/NullPushProvider.js.map +1 -0
  32. package/lib/commonjs/providers/PushNotificationProvider.js +30 -0
  33. package/lib/commonjs/providers/PushNotificationProvider.js.map +1 -0
  34. package/lib/commonjs/services/DeviceRegistrationService.js +248 -0
  35. package/lib/commonjs/services/DeviceRegistrationService.js.map +1 -0
  36. package/lib/commonjs/services/PushTokenService.js +284 -0
  37. package/lib/commonjs/services/PushTokenService.js.map +1 -0
  38. package/lib/commonjs/state/AuthStateMachine.js +161 -0
  39. package/lib/commonjs/state/AuthStateMachine.js.map +1 -0
  40. package/lib/commonjs/state/DeviceStateMachine.js +104 -0
  41. package/lib/commonjs/state/DeviceStateMachine.js.map +1 -0
  42. package/lib/commonjs/state/PushStateMachine.js +129 -0
  43. package/lib/commonjs/state/PushStateMachine.js.map +1 -0
  44. package/lib/commonjs/types/EventQueue.js +50 -0
  45. package/lib/commonjs/types/EventQueue.js.map +1 -0
  46. package/lib/commonjs/types/SDK.js +2 -0
  47. package/lib/commonjs/types/SDK.js.map +1 -0
  48. package/lib/commonjs/utils/FirebaseNotificationManager.js +492 -0
  49. package/lib/commonjs/utils/FirebaseNotificationManager.js.map +1 -0
  50. package/lib/commonjs/utils/Logger.js +56 -0
  51. package/lib/commonjs/utils/Logger.js.map +1 -0
  52. package/lib/commonjs/utils/SharedCredentialsManager.js +146 -0
  53. package/lib/commonjs/utils/SharedCredentialsManager.js.map +1 -0
  54. package/lib/commonjs/version.js +12 -0
  55. package/lib/commonjs/version.js.map +1 -0
  56. package/lib/module/components/FooterView.js +121 -0
  57. package/lib/module/components/FooterView.js.map +1 -0
  58. package/lib/module/components/FullScreenView.js +167 -0
  59. package/lib/module/components/FullScreenView.js.map +1 -0
  60. package/lib/module/components/HeaderView.js +199 -0
  61. package/lib/module/components/HeaderView.js.map +1 -0
  62. package/lib/module/components/PopUpView.js +181 -0
  63. package/lib/module/components/PopUpView.js.map +1 -0
  64. package/lib/module/config/BatchConfig.js +49 -0
  65. package/lib/module/config/BatchConfig.js.map +1 -0
  66. package/lib/module/constants/ApiUrls.js +52 -0
  67. package/lib/module/constants/ApiUrls.js.map +1 -0
  68. package/lib/module/core/EventQueueManager.js +340 -0
  69. package/lib/module/core/EventQueueManager.js.map +1 -0
  70. package/lib/module/core/FlushManager.js +240 -0
  71. package/lib/module/core/FlushManager.js.map +1 -0
  72. package/lib/module/core/NetworkMonitor.js +92 -0
  73. package/lib/module/core/NetworkMonitor.js.map +1 -0
  74. package/lib/module/index.js +3494 -0
  75. package/lib/module/index.js.map +1 -0
  76. package/lib/module/providers/FirebasePushProvider.js +124 -0
  77. package/lib/module/providers/FirebasePushProvider.js.map +1 -0
  78. package/lib/module/providers/NullPushProvider.js +53 -0
  79. package/lib/module/providers/NullPushProvider.js.map +1 -0
  80. package/lib/module/providers/PushNotificationProvider.js +26 -0
  81. package/lib/module/providers/PushNotificationProvider.js.map +1 -0
  82. package/lib/module/services/DeviceRegistrationService.js +243 -0
  83. package/lib/module/services/DeviceRegistrationService.js.map +1 -0
  84. package/lib/module/services/PushTokenService.js +278 -0
  85. package/lib/module/services/PushTokenService.js.map +1 -0
  86. package/lib/module/state/AuthStateMachine.js +155 -0
  87. package/lib/module/state/AuthStateMachine.js.map +1 -0
  88. package/lib/module/state/DeviceStateMachine.js +98 -0
  89. package/lib/module/state/DeviceStateMachine.js.map +1 -0
  90. package/lib/module/state/PushStateMachine.js +123 -0
  91. package/lib/module/state/PushStateMachine.js.map +1 -0
  92. package/lib/module/types/EventQueue.js +46 -0
  93. package/lib/module/types/EventQueue.js.map +1 -0
  94. package/lib/module/types/SDK.js +2 -0
  95. package/lib/module/types/SDK.js.map +1 -0
  96. package/lib/module/utils/FirebaseNotificationManager.js +486 -0
  97. package/lib/module/utils/FirebaseNotificationManager.js.map +1 -0
  98. package/lib/module/utils/Logger.js +52 -0
  99. package/lib/module/utils/Logger.js.map +1 -0
  100. package/lib/module/utils/SharedCredentialsManager.js +140 -0
  101. package/lib/module/utils/SharedCredentialsManager.js.map +1 -0
  102. package/lib/module/version.js +8 -0
  103. package/lib/module/version.js.map +1 -0
  104. package/lib/typescript/commonjs/package.json +1 -0
  105. package/lib/typescript/commonjs/src/components/FooterView.d.ts +3 -0
  106. package/lib/typescript/commonjs/src/components/FooterView.d.ts.map +1 -0
  107. package/lib/typescript/commonjs/src/components/FullScreenView.d.ts +3 -0
  108. package/lib/typescript/commonjs/src/components/FullScreenView.d.ts.map +1 -0
  109. package/lib/typescript/commonjs/src/components/HeaderView.d.ts +3 -0
  110. package/lib/typescript/commonjs/src/components/HeaderView.d.ts.map +1 -0
  111. package/lib/typescript/commonjs/src/components/PopUpView.d.ts +3 -0
  112. package/lib/typescript/commonjs/src/components/PopUpView.d.ts.map +1 -0
  113. package/lib/typescript/commonjs/src/config/BatchConfig.d.ts +7 -0
  114. package/lib/typescript/commonjs/src/config/BatchConfig.d.ts.map +1 -0
  115. package/lib/typescript/commonjs/src/constants/ApiUrls.d.ts +56 -0
  116. package/lib/typescript/commonjs/src/constants/ApiUrls.d.ts.map +1 -0
  117. package/lib/typescript/commonjs/src/core/EventQueueManager.d.ts +63 -0
  118. package/lib/typescript/commonjs/src/core/EventQueueManager.d.ts.map +1 -0
  119. package/lib/typescript/commonjs/src/core/FlushManager.d.ts +63 -0
  120. package/lib/typescript/commonjs/src/core/FlushManager.d.ts.map +1 -0
  121. package/lib/typescript/commonjs/src/core/NetworkMonitor.d.ts +38 -0
  122. package/lib/typescript/commonjs/src/core/NetworkMonitor.d.ts.map +1 -0
  123. package/lib/typescript/commonjs/src/index.d.ts +663 -0
  124. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  125. package/lib/typescript/commonjs/src/providers/FirebasePushProvider.d.ts +28 -0
  126. package/lib/typescript/commonjs/src/providers/FirebasePushProvider.d.ts.map +1 -0
  127. package/lib/typescript/commonjs/src/providers/NullPushProvider.d.ts +25 -0
  128. package/lib/typescript/commonjs/src/providers/NullPushProvider.d.ts.map +1 -0
  129. package/lib/typescript/commonjs/src/providers/PushNotificationProvider.d.ts +105 -0
  130. package/lib/typescript/commonjs/src/providers/PushNotificationProvider.d.ts.map +1 -0
  131. package/lib/typescript/commonjs/src/services/DeviceRegistrationService.d.ts +60 -0
  132. package/lib/typescript/commonjs/src/services/DeviceRegistrationService.d.ts.map +1 -0
  133. package/lib/typescript/commonjs/src/services/PushTokenService.d.ts +82 -0
  134. package/lib/typescript/commonjs/src/services/PushTokenService.d.ts.map +1 -0
  135. package/lib/typescript/commonjs/src/state/AuthStateMachine.d.ts +61 -0
  136. package/lib/typescript/commonjs/src/state/AuthStateMachine.d.ts.map +1 -0
  137. package/lib/typescript/commonjs/src/state/DeviceStateMachine.d.ts +51 -0
  138. package/lib/typescript/commonjs/src/state/DeviceStateMachine.d.ts.map +1 -0
  139. package/lib/typescript/commonjs/src/state/PushStateMachine.d.ts +61 -0
  140. package/lib/typescript/commonjs/src/state/PushStateMachine.d.ts.map +1 -0
  141. package/lib/typescript/commonjs/src/types/EventQueue.d.ts +85 -0
  142. package/lib/typescript/commonjs/src/types/EventQueue.d.ts.map +1 -0
  143. package/lib/typescript/commonjs/src/types/SDK.d.ts +54 -0
  144. package/lib/typescript/commonjs/src/types/SDK.d.ts.map +1 -0
  145. package/lib/typescript/commonjs/src/utils/FirebaseNotificationManager.d.ts +169 -0
  146. package/lib/typescript/commonjs/src/utils/FirebaseNotificationManager.d.ts.map +1 -0
  147. package/lib/typescript/commonjs/src/utils/Logger.d.ts +32 -0
  148. package/lib/typescript/commonjs/src/utils/Logger.d.ts.map +1 -0
  149. package/lib/typescript/commonjs/src/utils/SharedCredentialsManager.d.ts +54 -0
  150. package/lib/typescript/commonjs/src/utils/SharedCredentialsManager.d.ts.map +1 -0
  151. package/lib/typescript/commonjs/src/version.d.ts +2 -0
  152. package/lib/typescript/commonjs/src/version.d.ts.map +1 -0
  153. package/lib/typescript/module/package.json +1 -0
  154. package/lib/typescript/module/src/components/FooterView.d.ts +3 -0
  155. package/lib/typescript/module/src/components/FooterView.d.ts.map +1 -0
  156. package/lib/typescript/module/src/components/FullScreenView.d.ts +3 -0
  157. package/lib/typescript/module/src/components/FullScreenView.d.ts.map +1 -0
  158. package/lib/typescript/module/src/components/HeaderView.d.ts +3 -0
  159. package/lib/typescript/module/src/components/HeaderView.d.ts.map +1 -0
  160. package/lib/typescript/module/src/components/PopUpView.d.ts +3 -0
  161. package/lib/typescript/module/src/components/PopUpView.d.ts.map +1 -0
  162. package/lib/typescript/module/src/config/BatchConfig.d.ts +7 -0
  163. package/lib/typescript/module/src/config/BatchConfig.d.ts.map +1 -0
  164. package/lib/typescript/module/src/constants/ApiUrls.d.ts +56 -0
  165. package/lib/typescript/module/src/constants/ApiUrls.d.ts.map +1 -0
  166. package/lib/typescript/module/src/core/EventQueueManager.d.ts +63 -0
  167. package/lib/typescript/module/src/core/EventQueueManager.d.ts.map +1 -0
  168. package/lib/typescript/module/src/core/FlushManager.d.ts +63 -0
  169. package/lib/typescript/module/src/core/FlushManager.d.ts.map +1 -0
  170. package/lib/typescript/module/src/core/NetworkMonitor.d.ts +38 -0
  171. package/lib/typescript/module/src/core/NetworkMonitor.d.ts.map +1 -0
  172. package/lib/typescript/module/src/index.d.ts +663 -0
  173. package/lib/typescript/module/src/index.d.ts.map +1 -0
  174. package/lib/typescript/module/src/providers/FirebasePushProvider.d.ts +28 -0
  175. package/lib/typescript/module/src/providers/FirebasePushProvider.d.ts.map +1 -0
  176. package/lib/typescript/module/src/providers/NullPushProvider.d.ts +25 -0
  177. package/lib/typescript/module/src/providers/NullPushProvider.d.ts.map +1 -0
  178. package/lib/typescript/module/src/providers/PushNotificationProvider.d.ts +105 -0
  179. package/lib/typescript/module/src/providers/PushNotificationProvider.d.ts.map +1 -0
  180. package/lib/typescript/module/src/services/DeviceRegistrationService.d.ts +60 -0
  181. package/lib/typescript/module/src/services/DeviceRegistrationService.d.ts.map +1 -0
  182. package/lib/typescript/module/src/services/PushTokenService.d.ts +82 -0
  183. package/lib/typescript/module/src/services/PushTokenService.d.ts.map +1 -0
  184. package/lib/typescript/module/src/state/AuthStateMachine.d.ts +61 -0
  185. package/lib/typescript/module/src/state/AuthStateMachine.d.ts.map +1 -0
  186. package/lib/typescript/module/src/state/DeviceStateMachine.d.ts +51 -0
  187. package/lib/typescript/module/src/state/DeviceStateMachine.d.ts.map +1 -0
  188. package/lib/typescript/module/src/state/PushStateMachine.d.ts +61 -0
  189. package/lib/typescript/module/src/state/PushStateMachine.d.ts.map +1 -0
  190. package/lib/typescript/module/src/types/EventQueue.d.ts +85 -0
  191. package/lib/typescript/module/src/types/EventQueue.d.ts.map +1 -0
  192. package/lib/typescript/module/src/types/SDK.d.ts +54 -0
  193. package/lib/typescript/module/src/types/SDK.d.ts.map +1 -0
  194. package/lib/typescript/module/src/utils/FirebaseNotificationManager.d.ts +169 -0
  195. package/lib/typescript/module/src/utils/FirebaseNotificationManager.d.ts.map +1 -0
  196. package/lib/typescript/module/src/utils/Logger.d.ts +32 -0
  197. package/lib/typescript/module/src/utils/Logger.d.ts.map +1 -0
  198. package/lib/typescript/module/src/utils/SharedCredentialsManager.d.ts +54 -0
  199. package/lib/typescript/module/src/utils/SharedCredentialsManager.d.ts.map +1 -0
  200. package/lib/typescript/module/src/version.d.ts +2 -0
  201. package/lib/typescript/module/src/version.d.ts.map +1 -0
  202. package/package.json +230 -0
  203. package/scripts/generate-version.js +25 -0
  204. package/scripts/setup-ios-extension.js +275 -0
package/LICENSE ADDED
@@ -0,0 +1,55 @@
1
+ PROPRIETARY SOFTWARE LICENSE
2
+
3
+ Copyright (c) 2025 Loyalytics. All Rights Reserved.
4
+
5
+ NOTICE: This software and its source code are proprietary and confidential
6
+ information of Loyalytics ("Proprietary Information").
7
+
8
+ This software is provided to you under a commercial license agreement with
9
+ Loyalytics. You may not use this software except in compliance with the terms
10
+ of such commercial license agreement.
11
+
12
+ RESTRICTIONS:
13
+
14
+ 1. You may NOT redistribute, sublicense, sell, or otherwise transfer this
15
+ software or any portion thereof to any third party.
16
+
17
+ 2. You may NOT modify, adapt, translate, reverse engineer, decompile,
18
+ disassemble, or create derivative works based on this software.
19
+
20
+ 3. You may NOT remove or alter any copyright, trademark, or other proprietary
21
+ notice from this software.
22
+
23
+ 4. You may NOT use this software for any purpose other than as expressly
24
+ authorized in your commercial license agreement with Loyalytics.
25
+
26
+ 5. The software is licensed, not sold. Loyalytics retains all right, title,
27
+ and interest in and to the software, including all intellectual property
28
+ rights therein.
29
+
30
+ AUTHORIZED USE:
31
+
32
+ This software may only be used by authorized customers of Loyalytics who have
33
+ entered into a valid commercial license agreement. Use of this software
34
+ constitutes acceptance of the terms and conditions set forth in such
35
+ agreement.
36
+
37
+ To obtain a commercial license or for more information, please contact:
38
+ Email: support@loyalytics.ai
39
+ Website: https://www.loyalytics.ai/
40
+
41
+ DISCLAIMER:
42
+
43
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
44
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
46
+ LOYALYTICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
47
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
48
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
49
+
50
+ GOVERNING LAW:
51
+
52
+ This license shall be governed by and construed in accordance with the laws
53
+ of India, without regard to its conflict of law provisions.
54
+
55
+ For licensing inquiries, contact: support@loyalytics.ai
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # Swan React Native SDK
2
+
3
+ > **⚠️ PROPRIETARY SOFTWARE:** This SDK is proprietary software owned by Loyalytics.
4
+ > It requires a valid commercial license for use. See [LICENSE](./LICENSE) for terms.
5
+
6
+ ## Installation
7
+
8
+ **Note:** This package is available via npm for authorized customers only. Installation requires a valid commercial license agreement with Loyalytics.
9
+
10
+ ```sh
11
+ npm install @loyalytics/swan-react-native-sdk
12
+ ```
13
+
14
+ Or using yarn:
15
+
16
+ ```sh
17
+ yarn add @loyalytics/swan-react-native-sdk
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ```js
23
+ import SwanSDK from '@loyalytics/swan-react-native-sdk';
24
+
25
+ // Initialize SDK
26
+ const sdk = SwanSDK.getInstance('YOUR_APP_ID', {
27
+ isProduction: false,
28
+ pushNotifications: {
29
+ enabled: true,
30
+ autoRequestPermission: true,
31
+ },
32
+ isProduction: true,
33
+ });
34
+
35
+ // Track events
36
+ sdk.productViewed({ productId: '123' });
37
+
38
+ // Listen for SDK events
39
+ sdk.on('initialized', () => {
40
+ console.log('SDK initialized!');
41
+ });
42
+ ```
43
+
44
+ ## iOS Notification Extension
45
+
46
+ To support Rich Media (Images) and Delivery Tracking (even when the app is killed), you must set up a **Notification Service Extension**.
47
+
48
+ We provide an automated tool and a guide to help you set this up.
49
+
50
+ ```
51
+ node ./node_modules/@loyalytics/swan-react-native-sdk/scripts/setup-ios-extension.js
52
+ ```
53
+
54
+ ## License
55
+
56
+ This software is proprietary and confidential. Unauthorized copying, modification,
57
+ distribution, or use of this software is strictly prohibited.
58
+
59
+ Copyright © 2025 Loyalytics. All Rights Reserved.
60
+
61
+ For licensing inquiries, contact: support@loyalytics.ai
62
+
63
+ See the [LICENSE](./LICENSE) file for full terms.
64
+
65
+ ---
66
+
67
+ Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
@@ -0,0 +1,335 @@
1
+ # iOS Notification Service Extension Setup
2
+
3
+ ## Overview
4
+
5
+ The Swan SDK's Notification Service Extension enables:
6
+ - ✅ **Delivery tracking** when app is killed or in background
7
+ - ✅ **Rich media support** (images in notifications)
8
+ - ✅ **Reliable ACKs** even when app is not running
9
+
10
+ This extension is **required for iOS** to track push notification delivery in all app states.
11
+
12
+ ---
13
+
14
+ ## Why is this needed?
15
+
16
+ ### The iOS Limitation
17
+
18
+ On iOS, when your app is in background or killed state and receives a push notification with a visible alert, React Native's `setBackgroundMessageHandler` **is NOT called**. This is fundamental iOS behavior, not a bug.
19
+
20
+ **What this means:**
21
+ - ❌ No delivery tracking when app is killed
22
+ - ❌ No custom notification display logic in background
23
+ - ❌ No image processing without extension
24
+
25
+ ### The Solution: Notification Service Extension
26
+
27
+ A Notification Service Extension is a separate iOS app extension that:
28
+ - ✅ Runs in a **separate process** from your main app
29
+ - ✅ Intercepts **all incoming notifications** before they're displayed
30
+ - ✅ Has **30 seconds** to process the notification
31
+ - ✅ Can send delivery ACKs, download images, and modify content
32
+
33
+ **Industry standard:** Firebase, OneSignal, CleverTap, Airship all use this approach.
34
+
35
+ ---
36
+
37
+ ## Installation
38
+
39
+ ### Step 1: Install Dependencies
40
+
41
+ ```bash
42
+ npm install react-native-shared-group-preferences
43
+ cd ios && pod install && cd ..
44
+ ```
45
+
46
+ **Why needed:** Share credentials between app and extension.
47
+
48
+ ---
49
+
50
+ ### Step 2: Configure in Xcode
51
+
52
+ #### 2.1 Add Extension Target
53
+
54
+ 1. Open `ios/*.xcworkspace` in Xcode
55
+ 2. Go to **File → New → Target**
56
+ 3. Choose **"Notification Service Extension"**
57
+ 4. **Product Name:** `SwanNotificationServiceExtension`
58
+ 5. **Language:** Swift
59
+ 6. Click **Finish**
60
+ 7. When prompted "Activate scheme?", click **Cancel**
61
+
62
+ #### 2.2 Configure App Groups
63
+
64
+ **App Groups** allow the main app and extension to share credentials.
65
+
66
+ ##### Main App Target
67
+
68
+ 1. Select your **main app target** (e.g., `YourApp`)
69
+ 2. Go to **"Signing & Capabilities"** tab
70
+ 3. Click **"+ Capability"**
71
+ 4. Search for and add **"App Groups"**
72
+ 5. Click **"+"** under App Groups
73
+ 6. Enter: `group.swan.sdk.notifications`
74
+ 7. Click **OK**
75
+
76
+ ##### Extension Target
77
+
78
+ 1. Select **SwanNotificationServiceExtension** target
79
+ 2. Go to **"Signing & Capabilities"** tab
80
+ 3. Click **"+ Capability"**
81
+ 4. Search for and add **"App Groups"**
82
+ 5. Click **"+"** under App Groups
83
+ 6. Enter: `group.swan.sdk.notifications` (**MUST match main app!**)
84
+ 7. Click **OK**
85
+
86
+ **⚠️ IMPORTANT:** Both targets must have the **exact same** App Group ID.
87
+
88
+ #### 2.3 Verify Bundle Identifier
89
+
90
+ 1. Select **SwanNotificationServiceExtension** target
91
+ 2. Go to **"General"** tab
92
+ 3. Check **Bundle Identifier**: Should be `com.yourcompany.app.SwanNotificationServiceExtension`
93
+ 4. Make sure it's a **child** of your main app's bundle ID
94
+
95
+ ---
96
+
97
+ ### Step 3: Run Setup Script
98
+
99
+ Now that the extension target is created, run the setup script to copy the Swan implementation files. This will overwrite the default files created by Xcode.
100
+
101
+ ```bash
102
+ node node_modules/swan-react-native-sdk/scripts/setup-ios-extension.js
103
+ ```
104
+
105
+ **What it does:**
106
+ - Copies extension files to `ios/SwanNotificationServiceExtension/`
107
+ - Validates dependencies
108
+ - Ensures the correct implementation is in place
109
+
110
+ ---
111
+
112
+ ### Step 4: Testing
113
+
114
+ ### Build and Archive
115
+
116
+ ```bash
117
+ # Clean build
118
+ cd ios
119
+ rm -rf build
120
+ xcodebuild clean -workspace YourApp.xcworkspace -scheme YourApp
121
+
122
+ # Build
123
+ xcodebuild -workspace YourApp.xcworkspace -scheme YourApp -configuration Release
124
+
125
+ # Archive (for TestFlight or Ad Hoc)
126
+ xcodebuild -workspace YourApp.xcworkspace -scheme YourApp -configuration Release archive
127
+ ```
128
+
129
+ ### Test on Real Device
130
+
131
+ **IMPORTANT:** Push notifications don't work on iOS Simulator!
132
+
133
+ 1. Archive your app (Product → Archive in Xcode)
134
+ 2. Export to device or upload to TestFlight
135
+ 3. Install on a real iOS device
136
+ 4. Send a test notification
137
+ 5. Check Xcode **Device Console** for logs
138
+
139
+ ### Expected Logs
140
+
141
+ When extension receives a notification:
142
+
143
+ ```
144
+ [SwanSDK Extension] Notification Service Extension triggered
145
+ [SwanSDK Extension] Request identifier: 1234567890
146
+ [SwanSDK Extension] UserInfo: {...}
147
+ [SwanSDK Extension] Found messageId in gcm.message_id: 0:1234567890
148
+ [SwanSDK Extension] Sending delivery ACK for messageId: 0:1234567890
149
+ [SwanSDK Extension] Credentials loaded - appId: YOUR_APP_ID
150
+ [SwanSDK Extension] ACK payload: {...}
151
+ [SwanSDK Extension] ACK response status: 200
152
+ [SwanSDK Extension] ✅ Delivery ACK sent successfully
153
+ ```
154
+
155
+ If image is present:
156
+ ```
157
+ [SwanSDK Extension] Downloading notification image: https://example.com/image.png
158
+ [SwanSDK Extension] ✅ Image downloaded successfully
159
+ ```
160
+
161
+ ### View Logs on Real Device
162
+
163
+ **Option 1: Xcode Device Console**
164
+ 1. Connect device via USB
165
+ 2. Xcode → Window → Devices and Simulators
166
+ 3. Select your device
167
+ 4. Click **"Open Console"**
168
+ 5. Filter by "SwanSDK Extension"
169
+
170
+ **Option 2: Console.app (macOS)**
171
+ 1. Open Console app on Mac
172
+ 2. Select your connected device
173
+ 3. Search for "SwanSDK Extension"
174
+
175
+ ---
176
+
177
+ ## Troubleshooting
178
+
179
+ ### Extension logs don't appear
180
+
181
+ **Symptom:** No `[SwanSDK Extension]` logs when notification arrives
182
+
183
+ **Possible causes:**
184
+
185
+ 1. **Missing mutable-content: 1**
186
+ - Check FCM payload includes `mutable-content: 1` in APNS
187
+ - Without it, iOS won't trigger the extension
188
+
189
+ 2. **App Groups not configured**
190
+ - Verify both targets have "App Groups" capability
191
+ - Verify App Group ID is `group.swan.sdk.notifications` in BOTH targets
192
+ - IDs must match exactly (no typos!)
193
+
194
+ 3. **Extension not included in build**
195
+ - In Xcode, go to Product → Scheme → Edit Scheme
196
+ - Check that SwanNotificationServiceExtension is included
197
+
198
+ 4. **Testing on simulator**
199
+ - Push notifications don't work on iOS Simulator
200
+ - Test on a real device
201
+
202
+ ### Extension runs but no ACK sent
203
+
204
+ **Symptom:** See extension logs but backend doesn't receive ACK
205
+
206
+ **Possible causes:**
207
+
208
+ 1. **Credentials not saved to App Group**
209
+ - Ensure SDK is initialized: `SwanSDK.init({ appId: '...' })`
210
+ - Credentials are saved automatically on init
211
+ - Check logs for: `[SharedCredentials] ✅ Credentials saved to iOS App Group`
212
+
213
+ 2. **App Group ID mismatch**
214
+ - Extension uses `group.swan.sdk.notifications` by default
215
+ - If you changed it, update `NotificationService.swift` line 143
216
+
217
+ 3. **Network issue**
218
+ - Extension has only 30 seconds to complete
219
+ - Check device has internet connection
220
+
221
+ ### Images not appearing
222
+
223
+ **Symptom:** Notification arrives but image doesn't display
224
+
225
+ **Possible causes:**
226
+
227
+ 1. **Image URL invalid**
228
+ - Check image URL is accessible (try in browser)
229
+ - Must be HTTPS (HTTP won't work)
230
+
231
+ 2. **Image format unsupported**
232
+ - Supported: JPEG, PNG, GIF
233
+ - Max size: 10MB (iOS limit)
234
+
235
+ 3. **mutable-content missing**
236
+ - Extension won't run without `mutable-content: 1`
237
+
238
+ ### Build errors
239
+
240
+ **Error:** `No such module 'UserNotifications'`
241
+ - Solution: Make sure deployment target is iOS 10.0+
242
+
243
+ **Error:** `Use of undeclared type 'UNNotificationServiceExtension'`
244
+ - Solution: Verify extension target is set to iOS 10.0+ deployment target
245
+
246
+ **Error:** `Could not find or use auto-linked library 'swiftFoundation'`
247
+ - Solution: Add `use_frameworks!` to Podfile
248
+
249
+ **Error:** `CocoaPods Error: Unable to find compatibility version string for object version '70'`
250
+ - Solution: In Xcode, select your Project (blue icon) → Build Settings (or Info) → Project Format. Change it to **Xcode 16.0-compatible** or later.
251
+
252
+ ---
253
+
254
+ ## Customization
255
+
256
+ ### Custom App Group ID
257
+
258
+ If you want to use a different App Group ID:
259
+
260
+ 1. **In Xcode:** Update App Groups in both targets to use your custom ID (e.g., `group.com.yourcompany.app`)
261
+
262
+ 2. **In SDK:** Configure before calling `SwanSDK.init()`:
263
+
264
+ ```typescript
265
+ import { SharedCredentialsManager } from 'swan-react-native-sdk';
266
+
267
+ // Set custom App Group ID BEFORE SDK init
268
+ SharedCredentialsManager.setAppGroupId('group.com.yourcompany.app');
269
+
270
+ // Then initialize SDK
271
+ await SwanSDK.init({ appId: 'YOUR_APP_ID' });
272
+ ```
273
+
274
+ 3. **In Extension:** Update `NotificationService.swift`:
275
+
276
+ ```swift
277
+ let appGroupId = "group.com.yourcompany.app"
278
+ ```
279
+
280
+
281
+
282
+ ## FAQs
283
+
284
+ ### Q: Do I need to modify the extension code?
285
+
286
+ **A:** No. The extension works out of the box. Only modify if you need custom App Group ID.
287
+
288
+ ### Q: Will this increase my app size?
289
+
290
+ **A:** Minimally. The extension adds ~50KB to your IPA.
291
+
292
+ ### Q: Does this affect app performance?
293
+
294
+ **A:** No. The extension runs in a separate process and only when notifications arrive.
295
+
296
+ ### Q: Can I test without archiving?
297
+
298
+ **A:** Yes, but you must run on a real device. Push doesn't work on simulator.
299
+
300
+ ### Q: What if I already have a Notification Service Extension?
301
+
302
+ **A:** You'll need to merge Swan's code into your existing extension. The key parts are:
303
+ 1. Reading credentials from App Group
304
+ 2. Sending delivery ACK
305
+ 3. Downloading images
306
+
307
+ ### Q: Do I need this for Android?
308
+
309
+ **A:** No. Android data-only push notifications work without an extension. This is iOS-only.
310
+
311
+ ---
312
+
313
+ ## Support
314
+
315
+ If you encounter issues:
316
+
317
+ 1. Check logs in Xcode Device Console
318
+ 2. Verify all steps in this guide
319
+ 3. Test with the provided FCM payload example
320
+ 4. Check that App Group IDs match in both targets
321
+
322
+ For detailed debugging, enable verbose logging:
323
+ - Main app: `SwanSDK.setLoggingEnabled(true)`
324
+ - Extension: Logs are always enabled, check Device Console
325
+
326
+ ---
327
+
328
+ ## Summary
329
+
330
+ ✅ **Install:** `npm install react-native-shared-group-preferences`
331
+ ✅ **Xcode:** Add extension target + configure App Groups
332
+ ✅ **Run:** `node node_modules/swan-react-native-sdk/scripts/setup-ios-extension.js`
333
+ ✅ **Test:** Archive and test on real device
334
+
335
+ That's it! Your iOS notifications now have reliable delivery tracking and rich media support. 🎉
package/ios/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # Swan SDK - iOS Notification Service Extension
2
+
3
+ This directory contains the Notification Service Extension for iOS, which enables:
4
+ - ✅ Delivery tracking when app is killed or backgrounded
5
+ - ✅ Rich media support (images in notifications)
6
+ - ✅ Reliable ACKs in all app states
7
+
8
+ ## Quick Setup
9
+
10
+ ### Step 1: Run Setup Script
11
+
12
+ From your React Native project root:
13
+
14
+ ```bash
15
+ node node_modules/swan-react-native-sdk/scripts/setup-ios-extension.js
16
+ ```
17
+
18
+ This will:
19
+ - Copy extension files to your `ios/` directory
20
+ - Validate dependencies
21
+ - Show setup instructions
22
+
23
+ ### Step 2: Configure in Xcode
24
+
25
+ Follow the instructions shown by the setup script to:
26
+ 1. Add extension target to Xcode
27
+ 2. Configure App Groups
28
+ 3. Replace auto-generated files
29
+
30
+ ### Step 3: Update FCM Payload
31
+
32
+ Ensure your backend includes `mutable-content: 1` in APNS:
33
+
34
+ ```json
35
+ {
36
+ "apns": {
37
+ "payload": {
38
+ "aps": {
39
+ "alert": { "title": "...", "body": "..." },
40
+ "mutable-content": 1
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Full Documentation
48
+
49
+ See complete setup guide: [docs/IOS_NOTIFICATION_EXTENSION_SETUP.md](../docs/IOS_NOTIFICATION_EXTENSION_SETUP.md)
50
+
51
+ ## Files
52
+
53
+ - **SwanNotificationServiceExtension/** - Extension source code
54
+ - `NotificationService.swift` - Main extension logic
55
+ - `Info.plist` - Extension configuration
56
+ - `SwanNotificationServiceExtension.entitlements` - App Group permissions
57
+
58
+ ## Support
59
+
60
+ For issues or questions:
61
+ 1. Check the full documentation
62
+ 2. Verify App Groups are configured correctly
63
+ 3. Test on a real device (not simulator)
64
+ 4. Check Xcode Device Console for logs
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
7
+ <key>CFBundleDisplayName</key>
8
+ <string>SwanNotificationServiceExtension</string>
9
+ <key>CFBundleExecutable</key>
10
+ <string>$(EXECUTABLE_NAME)</string>
11
+ <key>CFBundleIdentifier</key>
12
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+ <key>CFBundleInfoDictionaryVersion</key>
14
+ <string>6.0</string>
15
+ <key>CFBundleName</key>
16
+ <string>$(PRODUCT_NAME)</string>
17
+ <key>CFBundlePackageType</key>
18
+ <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
19
+ <key>CFBundleShortVersionString</key>
20
+ <string>1.0</string>
21
+ <key>CFBundleVersion</key>
22
+ <string>1</string>
23
+ <key>NSExtension</key>
24
+ <dict>
25
+ <key>NSExtensionPointIdentifier</key>
26
+ <string>com.apple.usernotifications.service</string>
27
+ <key>NSExtensionPrincipalClass</key>
28
+ <string>$(PRODUCT_MODULE_NAME).NotificationService</string>
29
+ </dict>
30
+ </dict>
31
+ </plist>