react-native-push-signal 0.1.4 → 0.1.7

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 (103) hide show
  1. package/LICENSE +1 -1
  2. package/PushSignal.podspec +2 -12
  3. package/README.md +3 -11
  4. package/README.ru.md +3 -11
  5. package/android/build.gradle +1 -62
  6. package/android/consumer-rules.pro +3 -3
  7. package/android/src/main/AndroidManifest.xml +2 -2
  8. package/android/src/main/java/com/pushsignal/PushModels.kt +15 -0
  9. package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalCenter.kt +24 -71
  10. package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalInitProvider.kt +1 -1
  11. package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalMessagingService.kt +1 -1
  12. package/android/src/main/java/com/pushsignal/PushSignalModule.kt +88 -0
  13. package/android/src/main/java/com/pushsignal/PushSignalPackage.kt +30 -0
  14. package/ios/PushSignal.h +4 -0
  15. package/ios/PushSignal.mm +57 -0
  16. package/ios/PushSignalCenter.h +26 -0
  17. package/ios/PushSignalCenter.m +608 -0
  18. package/ios/PushSignalLaunchStore.m +6 -9
  19. package/lib/module/NativePushSignal.js +5 -0
  20. package/lib/module/NativePushSignal.js.map +1 -0
  21. package/lib/module/pushSignal.native.js +36 -12
  22. package/lib/module/pushSignal.native.js.map +1 -1
  23. package/lib/module/types.js +2 -0
  24. package/lib/module/types.js.map +1 -0
  25. package/lib/typescript/src/NativePushSignal.d.ts +22 -0
  26. package/lib/typescript/src/NativePushSignal.d.ts.map +1 -0
  27. package/lib/typescript/src/index.d.ts +1 -1
  28. package/lib/typescript/src/index.d.ts.map +1 -1
  29. package/lib/typescript/src/pushSignal.d.ts +1 -1
  30. package/lib/typescript/src/pushSignal.d.ts.map +1 -1
  31. package/lib/typescript/src/pushSignal.native.d.ts +1 -1
  32. package/lib/typescript/src/pushSignal.native.d.ts.map +1 -1
  33. package/lib/typescript/src/types.d.ts +22 -0
  34. package/lib/typescript/src/types.d.ts.map +1 -0
  35. package/package.json +14 -19
  36. package/src/NativePushSignal.ts +25 -0
  37. package/src/index.tsx +1 -1
  38. package/src/pushSignal.native.tsx +60 -22
  39. package/src/pushSignal.tsx +1 -1
  40. package/src/types.ts +25 -0
  41. package/android/CMakeLists.txt +0 -24
  42. package/android/src/main/cpp/cpp-adapter.cpp +0 -11
  43. package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignal.kt +0 -38
  44. package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignalPackage.kt +0 -22
  45. package/ios/PushSignal.swift +0 -29
  46. package/ios/PushSignalCenter.swift +0 -588
  47. package/lib/module/PushSignal.nitro.js +0 -4
  48. package/lib/module/PushSignal.nitro.js.map +0 -1
  49. package/lib/typescript/src/PushSignal.nitro.d.ts +0 -32
  50. package/lib/typescript/src/PushSignal.nitro.d.ts.map +0 -1
  51. package/nitro.json +0 -23
  52. package/nitrogen/generated/android/c++/JAndroidFirebaseConfig.hpp +0 -70
  53. package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.hpp +0 -128
  54. package/nitrogen/generated/android/c++/JFunc_void_PushMessage.hpp +0 -80
  55. package/nitrogen/generated/android/c++/JHybridPushSignalSpec.cpp +0 -115
  56. package/nitrogen/generated/android/c++/JHybridPushSignalSpec.hpp +0 -66
  57. package/nitrogen/generated/android/c++/JPushCredentials.hpp +0 -70
  58. package/nitrogen/generated/android/c++/JPushEnvironment.hpp +0 -58
  59. package/nitrogen/generated/android/c++/JPushMessage.hpp +0 -84
  60. package/nitrogen/generated/android/c++/JPushPlatform.hpp +0 -58
  61. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/AndroidFirebaseConfig.kt +0 -66
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.kt +0 -78
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/Func_void_PushMessage.kt +0 -78
  64. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/HybridPushSignalSpec.kt +0 -79
  65. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushCredentials.kt +0 -61
  66. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushEnvironment.kt +0 -23
  67. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushMessage.kt +0 -66
  68. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushPlatform.kt +0 -23
  69. package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/pushsignalOnLoad.kt +0 -35
  70. package/nitrogen/generated/android/pushsignal+autolinking.cmake +0 -81
  71. package/nitrogen/generated/android/pushsignal+autolinking.gradle +0 -27
  72. package/nitrogen/generated/android/pushsignalOnLoad.cpp +0 -58
  73. package/nitrogen/generated/android/pushsignalOnLoad.hpp +0 -34
  74. package/nitrogen/generated/ios/PushSignal+autolinking.rb +0 -62
  75. package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.cpp +0 -90
  76. package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.hpp +0 -345
  77. package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Umbrella.hpp +0 -63
  78. package/nitrogen/generated/ios/PushSignalAutolinking.mm +0 -33
  79. package/nitrogen/generated/ios/PushSignalAutolinking.swift +0 -26
  80. package/nitrogen/generated/ios/c++/HybridPushSignalSpecSwift.cpp +0 -11
  81. package/nitrogen/generated/ios/c++/HybridPushSignalSpecSwift.hpp +0 -120
  82. package/nitrogen/generated/ios/swift/AndroidFirebaseConfig.swift +0 -96
  83. package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.swift +0 -61
  84. package/nitrogen/generated/ios/swift/Func_void.swift +0 -46
  85. package/nitrogen/generated/ios/swift/Func_void_PushCredentials.swift +0 -46
  86. package/nitrogen/generated/ios/swift/Func_void_PushMessage.swift +0 -46
  87. package/nitrogen/generated/ios/swift/Func_void_bool.swift +0 -46
  88. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +0 -46
  89. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_bool__.swift +0 -66
  90. package/nitrogen/generated/ios/swift/HybridPushSignalSpec.swift +0 -58
  91. package/nitrogen/generated/ios/swift/HybridPushSignalSpec_cxx.swift +0 -217
  92. package/nitrogen/generated/ios/swift/PushCredentials.swift +0 -45
  93. package/nitrogen/generated/ios/swift/PushEnvironment.swift +0 -40
  94. package/nitrogen/generated/ios/swift/PushMessage.swift +0 -97
  95. package/nitrogen/generated/ios/swift/PushPlatform.swift +0 -40
  96. package/nitrogen/generated/shared/c++/AndroidFirebaseConfig.hpp +0 -96
  97. package/nitrogen/generated/shared/c++/HybridPushSignalSpec.cpp +0 -24
  98. package/nitrogen/generated/shared/c++/HybridPushSignalSpec.hpp +0 -74
  99. package/nitrogen/generated/shared/c++/PushCredentials.hpp +0 -97
  100. package/nitrogen/generated/shared/c++/PushEnvironment.hpp +0 -76
  101. package/nitrogen/generated/shared/c++/PushMessage.hpp +0 -97
  102. package/nitrogen/generated/shared/c++/PushPlatform.hpp +0 -76
  103. package/src/PushSignal.nitro.ts +0 -39
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Anton Seagull
3
+ Copyright (c) 2026 AntonSeagull
4
4
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
  of this software and associated documentation files (the "Software"), to deal
6
6
  in the Software without restriction, including without limitation the rights
@@ -13,19 +13,9 @@ Pod::Spec.new do |s|
13
13
  s.platforms = { :ios => min_ios_version_supported }
14
14
  s.source = { :git => "https://antonseagull.com.git", :tag => "#{s.version}" }
15
15
 
16
- s.source_files = [
17
- "ios/**/*.{swift}",
18
- "ios/**/*.{h,m,mm}",
19
- "cpp/**/*.{hpp,cpp}",
20
- ]
21
- s.public_header_files = "ios/**/*.h"
16
+ s.source_files = "ios/**/*.{h,m,mm,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
22
18
  s.frameworks = "UIKit", "UserNotifications"
23
19
 
24
- s.dependency 'React-jsi'
25
- s.dependency 'React-callinvoker'
26
-
27
- load 'nitrogen/generated/ios/PushSignal+autolinking.rb'
28
- add_nitrogen_files(s)
29
-
30
20
  install_modules_dependencies(s)
31
21
  end
package/README.md CHANGED
@@ -7,11 +7,9 @@ Get device credentials for your server and listen for incoming notifications or
7
7
  ## Installation
8
8
 
9
9
  ```sh
10
- npm install react-native-push-signal react-native-nitro-modules
10
+ npm install react-native-push-signal
11
11
  ```
12
12
 
13
- `react-native-nitro-modules` is required because this library uses [Nitro Modules](https://nitro.margelo.com/).
14
-
15
13
  ## Usage
16
14
 
17
15
  ```ts
@@ -44,10 +42,6 @@ const credentials = await getCredentials();
44
42
 
45
43
  const stopMessages = onMessage((message) => {
46
44
  console.log('incoming', message);
47
- if (message.data.silent === '1') {
48
- return;
49
- }
50
- return true;
51
45
  });
52
46
 
53
47
  const stopPress = onNotificationPress((message) => {
@@ -118,15 +112,13 @@ If the host app already declares its own `FirebaseMessagingService`, only one se
118
112
 
119
113
  | App state | iOS | Android (notification payload) | Android (data-only) |
120
114
  | --- | --- | --- | --- |
121
- | Foreground | `onMessage`. Banner if a listener returns `true` | `onMessage`. Banner if a listener returns `true` | `onMessage`. Tray only if a listener returns `true` and the payload has title or body |
115
+ | Foreground | `onMessage` + system banner | `onMessage` + tray (if title/body) | `onMessage` + tray (if title/body) |
122
116
  | Background / killed | System banner. Tap → `onNotificationPress` | System banner. Tap → `onNotificationPress` | No banner. `onMessage` if the process is alive |
123
117
 
124
- - `onMessage` — the push arrived while the app is in the foreground (and Android data messages while the process is alive). Return `true` to show the system banner as usual. No return, `false`, or a throw means no banner. If several listeners are registered, the banner shows when any of them returns `true`.
118
+ - `onMessage` — the push arrived while the app is in the foreground (and Android data messages while the process is alive). Listeners only receive the payload; they do not control the banner.
125
119
  - `onNotificationPress` — the user opened the notification, including a cold start.
126
120
  - On iOS, a visible push received in the background or when the app is killed is delivered on tap, not through `onMessage`. That is an OS limit.
127
121
 
128
- If `onMessage` throws or takes longer than about 2 seconds, the library does not show a banner.
129
-
130
122
  ## Web
131
123
 
132
124
  `initialize()` resolves. `getCredentials()` throws. Listeners (`onMessage`, `onNotificationPress`) are no-ops.
package/README.ru.md CHANGED
@@ -7,11 +7,9 @@
7
7
  ## Установка
8
8
 
9
9
  ```sh
10
- npm install react-native-push-signal react-native-nitro-modules
10
+ npm install react-native-push-signal
11
11
  ```
12
12
 
13
- `react-native-nitro-modules` обязателен: библиотека собрана на [Nitro Modules](https://nitro.margelo.com/).
14
-
15
13
  ## Использование
16
14
 
17
15
  ```ts
@@ -44,10 +42,6 @@ const credentials = await getCredentials();
44
42
 
45
43
  const stopMessages = onMessage((message) => {
46
44
  console.log('incoming', message);
47
- if (message.data.silent === '1') {
48
- return;
49
- }
50
- return true;
51
45
  });
52
46
 
53
47
  const stopPress = onNotificationPress((message) => {
@@ -118,15 +112,13 @@ apply plugin: "com.google.gms.google-services"
118
112
 
119
113
  | Состояние | iOS | Android (notification payload) | Android (data-only) |
120
114
  | --- | --- | --- | --- |
121
- | Foreground | `onMessage`. Баннер, если слушатель вернул `true` | `onMessage`. Баннер, если слушатель вернул `true` | `onMessage`. Tray только если слушатель вернул `true` и в payload есть title или body |
115
+ | Foreground | `onMessage` + системный баннер | `onMessage` + tray (если есть title/body) | `onMessage` + tray (если есть title/body) |
122
116
  | Background / killed | Системный баннер. Тап → `onNotificationPress` | Системный баннер. Тап → `onNotificationPress` | Баннера нет. `onMessage`, если процесс жив |
123
117
 
124
- - `onMessage` — пуш пришёл, пока приложение на переднем плане (и Android data-message, пока процесс жив). Верните `true`, чтобы показать системный баннер как обычно. Без return, `false` или ошибка — баннера нет. Если слушателей несколько, баннер показывается, когда любой вернул `true`.
118
+ - `onMessage` — пуш пришёл, пока приложение на переднем плане (и Android data-message, пока процесс жив). Слушатель только получает payload и не управляет баннером.
125
119
  - `onNotificationPress` — пользователь открыл уведомление, в том числе при холодном старте.
126
120
  - На iOS видимый пуш в фоне или при убитом приложении приходит только в тап, не в `onMessage`. Это ограничение ОС.
127
121
 
128
- Если `onMessage` бросил ошибку или не ответил примерно за 2 секунды, баннер не показывается.
129
-
130
122
  ## Web
131
123
 
132
124
  `initialize()` резолвится. `getCredentials()` бросает ошибку. Слушатели (`onMessage`, `onNotificationPress`) ничего не делают.
@@ -25,80 +25,20 @@ buildscript {
25
25
  }
26
26
  }
27
27
 
28
- def reactNativeArchitectures() {
29
- def value = rootProject.getProperties().get("reactNativeArchitectures")
30
- return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
31
- }
32
28
 
33
29
  apply plugin: "com.android.library"
34
30
  apply plugin: "kotlin-android"
35
- apply from: '../nitrogen/generated/android/pushsignal+autolinking.gradle'
36
31
 
37
32
  apply plugin: "com.facebook.react"
38
33
 
39
34
  android {
40
- namespace "com.margelo.nitro.pushsignal"
35
+ namespace "com.pushsignal"
41
36
 
42
37
  compileSdkVersion getExtOrDefault("compileSdkVersion")
43
38
 
44
39
  defaultConfig {
45
40
  minSdkVersion getExtOrDefault("minSdkVersion")
46
41
  consumerProguardFiles "consumer-rules.pro"
47
-
48
- externalNativeBuild {
49
- cmake {
50
- cppFlags "-frtti -fexceptions -Wall -fstack-protector-all"
51
- arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
52
- abiFilters (*reactNativeArchitectures())
53
-
54
- buildTypes {
55
- debug {
56
- cppFlags "-O1 -g"
57
- }
58
- release {
59
- cppFlags "-O2"
60
- }
61
- }
62
- }
63
- }
64
- }
65
-
66
- externalNativeBuild {
67
- cmake {
68
- path "CMakeLists.txt"
69
- }
70
- }
71
-
72
- packaging {
73
- resources {
74
- excludes += [
75
- "META-INF",
76
- "META-INF/**"
77
- ]
78
- }
79
-
80
- jniLibs {
81
- excludes += [
82
- "**/libc++_shared.so",
83
- "**/libfbjni.so",
84
- "**/libjsi.so",
85
- "**/libfolly_json.so",
86
- "**/libfolly_runtime.so",
87
- "**/libglog.so",
88
- "**/libhermes.so",
89
- "**/libhermes-executor-debug.so",
90
- "**/libhermes_executor.so",
91
- "**/libreactnative.so",
92
- "**/libreactnativejni.so",
93
- "**/libturbomodulejsijni.so",
94
- "**/libreact_nativemodule_core.so",
95
- "**/libjscexecutor.so"
96
- ]
97
- }
98
- }
99
-
100
- buildFeatures {
101
- prefab true
102
42
  }
103
43
 
104
44
  compileOptions {
@@ -109,7 +49,6 @@ android {
109
49
 
110
50
  dependencies {
111
51
  implementation "com.facebook.react:react-android"
112
- implementation project(":react-native-nitro-modules")
113
52
  implementation "androidx.activity:activity-ktx:1.10.1"
114
53
  implementation "androidx.core:core-ktx:1.16.0"
115
54
  implementation "com.google.firebase:firebase-messaging:24.1.2"
@@ -1,4 +1,4 @@
1
- -keep class com.margelo.nitro.pushsignal.PushSignalMessagingService { *; }
2
- -keep class com.margelo.nitro.pushsignal.PushSignalInitProvider { *; }
3
- -keep class com.margelo.nitro.pushsignal.PushSignalCenter { *; }
1
+ -keep class com.pushsignal.PushSignalMessagingService { *; }
2
+ -keep class com.pushsignal.PushSignalInitProvider { *; }
3
+ -keep class com.pushsignal.PushSignalCenter { *; }
4
4
  -keep class com.google.firebase.messaging.** { *; }
@@ -3,12 +3,12 @@
3
3
 
4
4
  <application>
5
5
  <provider
6
- android:name="com.margelo.nitro.pushsignal.PushSignalInitProvider"
6
+ android:name="com.pushsignal.PushSignalInitProvider"
7
7
  android:authorities="${applicationId}.pushsignal.init"
8
8
  android:exported="false" />
9
9
 
10
10
  <service
11
- android:name="com.margelo.nitro.pushsignal.PushSignalMessagingService"
11
+ android:name="com.pushsignal.PushSignalMessagingService"
12
12
  android:exported="false">
13
13
  <intent-filter>
14
14
  <action android:name="com.google.firebase.MESSAGING_EVENT" />
@@ -0,0 +1,15 @@
1
+ package com.pushsignal
2
+
3
+ data class PushMessage(
4
+ val id: String?,
5
+ val title: String?,
6
+ val body: String?,
7
+ val data: Map<String, String>,
8
+ )
9
+
10
+ data class AndroidFirebaseConfig(
11
+ val project_id: String?,
12
+ val mobilesdk_app_id: String?,
13
+ val current_key: String?,
14
+ val project_number: String?,
15
+ )
@@ -1,4 +1,4 @@
1
- package com.margelo.nitro.pushsignal
1
+ package com.pushsignal
2
2
 
3
3
  import android.app.Activity
4
4
  import android.app.Application
@@ -13,28 +13,25 @@ import android.os.Handler
13
13
  import android.os.Looper
14
14
  import androidx.activity.ComponentActivity
15
15
  import androidx.core.app.NotificationCompat
16
+ import com.google.android.gms.tasks.Tasks
16
17
  import com.google.firebase.FirebaseApp
17
18
  import com.google.firebase.FirebaseOptions
18
19
  import com.google.firebase.messaging.FirebaseMessaging
19
- import com.google.android.gms.tasks.Tasks
20
20
  import com.google.firebase.messaging.RemoteMessage
21
- import com.margelo.nitro.core.Promise
22
21
  import java.util.Collections
23
22
  import java.util.UUID
24
23
  import java.util.WeakHashMap
25
24
  import java.util.concurrent.CopyOnWriteArrayList
26
- import java.util.concurrent.atomic.AtomicBoolean
27
25
 
28
26
  internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
29
27
  private const val EXTRA_HANDLED = "pushsignal.handled"
30
28
  private const val CHANNEL_ID = "push_signal_default"
31
- private const val FOREGROUND_TIMEOUT_MS = 2_000L
32
29
 
33
30
  private val lock = Any()
34
31
  private val mainHandler = Handler(Looper.getMainLooper())
35
32
  @Volatile private var application: Application? = null
36
33
  @Volatile private var currentActivity: Activity? = null
37
- @Volatile private var onMessage: ((PushMessage) -> Promise<Promise<Boolean>>)? = null
34
+ @Volatile private var onMessage: ((PushMessage) -> Unit)? = null
38
35
  @Volatile private var onNotificationPress: ((PushMessage) -> Unit)? = null
39
36
  @Volatile private var pendingPress: PushMessage? = null
40
37
  private val pendingMessages = CopyOnWriteArrayList<PushMessage>()
@@ -78,23 +75,12 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
78
75
  onDone(applyFirebaseConfig(context, config))
79
76
  }
80
77
 
81
- fun setOnMessage(callback: (PushMessage) -> Promise<Promise<Boolean>>) {
78
+ fun setOnMessage(callback: (PushMessage) -> Unit) {
82
79
  onMessage = callback
83
80
  val queued = pendingMessages.toList()
84
81
  pendingMessages.clear()
85
82
  queued.forEach { message ->
86
- runOnMain {
87
- val inForeground = startedActivityCount > 0 || currentActivity != null
88
- resolveShouldShowBanner(message) { shouldShow ->
89
- if (
90
- shouldShow &&
91
- inForeground &&
92
- (!message.title.isNullOrEmpty() || !message.body.isNullOrEmpty())
93
- ) {
94
- postForegroundNotification(message)
95
- }
96
- }
97
- }
83
+ runOnMain { deliverMessage(message) }
98
84
  }
99
85
  }
100
86
 
@@ -145,69 +131,36 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
145
131
 
146
132
  fun emitMessage(remoteMessage: RemoteMessage) {
147
133
  val message = remoteMessage.toPushMessage()
148
- runOnMain {
149
- val callback = onMessage
150
- if (callback == null) {
151
- pendingMessages.add(message)
152
- return@runOnMain
153
- }
154
-
155
- val inForeground = startedActivityCount > 0 || currentActivity != null
156
- resolveShouldShowBanner(message) { shouldShow ->
157
- if (
158
- shouldShow &&
159
- inForeground &&
160
- (!message.title.isNullOrEmpty() || !message.body.isNullOrEmpty())
161
- ) {
162
- postForegroundNotification(message)
163
- }
164
- }
165
- }
166
- }
167
-
168
- private fun runOnMain(block: () -> Unit) {
169
- if (Looper.myLooper() == Looper.getMainLooper()) {
170
- block()
171
- } else {
172
- mainHandler.post(block)
173
- }
134
+ runOnMain { deliverMessage(message) }
174
135
  }
175
136
 
176
- private fun resolveShouldShowBanner(
177
- message: PushMessage,
178
- onDone: (Boolean) -> Unit
179
- ) {
137
+ private fun deliverMessage(message: PushMessage) {
180
138
  val callback = onMessage
181
139
  if (callback == null) {
182
- onDone(false)
140
+ pendingMessages.add(message)
183
141
  return
184
142
  }
185
143
 
186
- val delivered = AtomicBoolean(false)
187
- val timeout = Runnable {
188
- if (delivered.compareAndSet(false, true)) {
189
- onDone(true)
190
- }
144
+ try {
145
+ callback(message)
146
+ } catch (_: Throwable) {
147
+ // Ignore listener failures.
191
148
  }
192
- mainHandler.postDelayed(timeout, FOREGROUND_TIMEOUT_MS)
193
149
 
194
- val finish = { shouldShow: Boolean ->
195
- if (delivered.compareAndSet(false, true)) {
196
- mainHandler.removeCallbacks(timeout)
197
- onDone(shouldShow)
198
- }
150
+ val inForeground = startedActivityCount > 0 || currentActivity != null
151
+ if (
152
+ inForeground &&
153
+ (!message.title.isNullOrEmpty() || !message.body.isNullOrEmpty())
154
+ ) {
155
+ postForegroundNotification(message)
199
156
  }
157
+ }
200
158
 
201
- try {
202
- callback(message)
203
- .then { inner ->
204
- inner
205
- .then { shouldShow -> finish(shouldShow) }
206
- .catch { finish(true) }
207
- }
208
- .catch { finish(true) }
209
- } catch (_: Throwable) {
210
- finish(true)
159
+ private fun runOnMain(block: () -> Unit) {
160
+ if (Looper.myLooper() == Looper.getMainLooper()) {
161
+ block()
162
+ } else {
163
+ mainHandler.post(block)
211
164
  }
212
165
  }
213
166
 
@@ -1,4 +1,4 @@
1
- package com.margelo.nitro.pushsignal
1
+ package com.pushsignal
2
2
 
3
3
  import android.content.ContentProvider
4
4
  import android.content.ContentValues
@@ -1,4 +1,4 @@
1
- package com.margelo.nitro.pushsignal
1
+ package com.pushsignal
2
2
 
3
3
  import com.google.firebase.messaging.FirebaseMessagingService
4
4
  import com.google.firebase.messaging.RemoteMessage
@@ -0,0 +1,88 @@
1
+ package com.pushsignal
2
+
3
+ import com.facebook.react.bridge.Arguments
4
+ import com.facebook.react.bridge.Promise
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.bridge.ReadableMap
7
+ import com.facebook.react.bridge.WritableMap
8
+ import java.util.concurrent.Executors
9
+
10
+ class PushSignalModule(reactContext: ReactApplicationContext) :
11
+ NativePushSignalSpec(reactContext) {
12
+
13
+ @Volatile
14
+ private var listening = false
15
+
16
+ override fun initialize(config: ReadableMap, promise: Promise) {
17
+ val firebaseConfig = AndroidFirebaseConfig(
18
+ project_id = config.getStringOrNull("project_id"),
19
+ mobilesdk_app_id = config.getStringOrNull("mobilesdk_app_id"),
20
+ current_key = config.getStringOrNull("current_key"),
21
+ project_number = config.getStringOrNull("project_number"),
22
+ )
23
+
24
+ PushSignalCenter.attach(reactApplicationContext)
25
+ PushSignalCenter.initialize(firebaseConfig) { error ->
26
+ if (error == null) {
27
+ promise.resolve(null)
28
+ } else {
29
+ promise.reject("E_INIT", error.message, error)
30
+ }
31
+ }
32
+ }
33
+
34
+ override fun getCredentials(promise: Promise) {
35
+ executor.execute {
36
+ try {
37
+ PushSignalCenter.attach(reactApplicationContext)
38
+ val token = PushSignalCenter.fetchToken()
39
+ val result = Arguments.createMap().apply {
40
+ putString("platform", "android_os")
41
+ putString("token", token)
42
+ }
43
+ promise.resolve(result)
44
+ } catch (error: Exception) {
45
+ promise.reject("E_CREDENTIALS", error.message, error)
46
+ }
47
+ }
48
+ }
49
+
50
+ override fun startListening() {
51
+ if (listening) {
52
+ return
53
+ }
54
+ listening = true
55
+
56
+ PushSignalCenter.setOnMessage { message ->
57
+ emitOnMessage(message.toWritableMap())
58
+ }
59
+ PushSignalCenter.setOnNotificationPress { message ->
60
+ emitOnNotificationPress(message.toWritableMap())
61
+ }
62
+ }
63
+
64
+ companion object {
65
+ const val NAME = NativePushSignalSpec.NAME
66
+ private val executor = Executors.newSingleThreadExecutor()
67
+ }
68
+ }
69
+
70
+ private fun ReadableMap.getStringOrNull(key: String): String? {
71
+ if (!hasKey(key) || isNull(key)) {
72
+ return null
73
+ }
74
+ return getString(key)
75
+ }
76
+
77
+ private fun PushMessage.toWritableMap(): WritableMap {
78
+ val map = Arguments.createMap()
79
+ id?.let { map.putString("id", it) }
80
+ title?.let { map.putString("title", it) }
81
+ body?.let { map.putString("body", it) }
82
+ val dataMap = Arguments.createMap()
83
+ data.forEach { (key, value) ->
84
+ dataMap.putString(key, value)
85
+ }
86
+ map.putMap("data", dataMap)
87
+ return map
88
+ }
@@ -0,0 +1,30 @@
1
+ package com.pushsignal
2
+
3
+ import com.facebook.react.BaseReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+
9
+ class PushSignalPackage : BaseReactPackage() {
10
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
11
+ return if (name == PushSignalModule.NAME) {
12
+ PushSignalModule(reactContext)
13
+ } else {
14
+ null
15
+ }
16
+ }
17
+
18
+ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
19
+ mapOf(
20
+ PushSignalModule.NAME to ReactModuleInfo(
21
+ name = PushSignalModule.NAME,
22
+ className = PushSignalModule.NAME,
23
+ canOverrideExistingModule = false,
24
+ needsEagerInit = false,
25
+ isCxxModule = false,
26
+ isTurboModule = true
27
+ )
28
+ )
29
+ }
30
+ }
@@ -0,0 +1,4 @@
1
+ #import <PushSignalSpec/PushSignalSpec.h>
2
+
3
+ @interface PushSignal : NativePushSignalSpecBase <NativePushSignalSpec>
4
+ @end
@@ -0,0 +1,57 @@
1
+ #import "PushSignal.h"
2
+ #import "PushSignalCenter.h"
3
+
4
+ @implementation PushSignal {
5
+ BOOL _listening;
6
+ }
7
+
8
+ - (void)initialize:(NSDictionary *)config
9
+ resolve:(RCTPromiseResolveBlock)resolve
10
+ reject:(RCTPromiseRejectBlock)reject {
11
+ (void)config;
12
+ resolve(nil);
13
+ }
14
+
15
+ - (void)getCredentials:(RCTPromiseResolveBlock)resolve
16
+ reject:(RCTPromiseRejectBlock)reject {
17
+ [[PushSignalCenter shared] fetchCredentialsWithResolver:^(NSDictionary *credentials) {
18
+ resolve(credentials);
19
+ }
20
+ rejecter:^(NSError *error) {
21
+ reject(@"E_CREDENTIALS", error.localizedDescription, error);
22
+ }];
23
+ }
24
+
25
+ - (void)startListening {
26
+ if (_listening) {
27
+ return;
28
+ }
29
+ _listening = YES;
30
+
31
+ __weak PushSignal *weakSelf = self;
32
+ [[PushSignalCenter shared] setOnMessage:^(NSDictionary *message) {
33
+ PushSignal *strongSelf = weakSelf;
34
+ if (strongSelf == nil) {
35
+ return;
36
+ }
37
+ [strongSelf emitOnMessage:message];
38
+ }];
39
+ [[PushSignalCenter shared] setOnNotificationPress:^(NSDictionary *message) {
40
+ PushSignal *strongSelf = weakSelf;
41
+ if (strongSelf == nil) {
42
+ return;
43
+ }
44
+ [strongSelf emitOnNotificationPress:message];
45
+ }];
46
+ }
47
+
48
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
49
+ (const facebook::react::ObjCTurboModule::InitParams &)params {
50
+ return std::make_shared<facebook::react::NativePushSignalSpecJSI>(params);
51
+ }
52
+
53
+ + (NSString *)moduleName {
54
+ return @"PushSignal";
55
+ }
56
+
57
+ @end
@@ -0,0 +1,26 @@
1
+ #import <Foundation/Foundation.h>
2
+ #import <UserNotifications/UserNotifications.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ @interface PushSignalCenter : NSObject <UNUserNotificationCenterDelegate>
7
+
8
+ + (instancetype)shared;
9
+ + (void)installEarly;
10
+ + (void)bootstrapWithLaunchOptions:(nullable NSDictionary *)launchOptions;
11
+
12
+ - (void)install;
13
+ - (void)rememberForwardingDelegate:(nullable id<UNUserNotificationCenterDelegate>)delegate;
14
+
15
+ - (void)fetchCredentialsWithResolver:(void (^)(NSDictionary *credentials))resolve
16
+ rejecter:(void (^)(NSError *error))reject;
17
+
18
+ - (void)setOnMessage:(void (^)(NSDictionary *message))callback;
19
+ - (void)setOnNotificationPress:(void (^)(NSDictionary *message))callback;
20
+
21
+ - (void)handleDeviceToken:(NSData *)deviceToken;
22
+ - (void)handleRegistrationError:(NSError *)error;
23
+
24
+ @end
25
+
26
+ NS_ASSUME_NONNULL_END