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.
- package/LICENSE +1 -1
- package/PushSignal.podspec +2 -12
- package/README.md +3 -11
- package/README.ru.md +3 -11
- package/android/build.gradle +1 -62
- package/android/consumer-rules.pro +3 -3
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/pushsignal/PushModels.kt +15 -0
- package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalCenter.kt +24 -71
- package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalInitProvider.kt +1 -1
- package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalMessagingService.kt +1 -1
- package/android/src/main/java/com/pushsignal/PushSignalModule.kt +88 -0
- package/android/src/main/java/com/pushsignal/PushSignalPackage.kt +30 -0
- package/ios/PushSignal.h +4 -0
- package/ios/PushSignal.mm +57 -0
- package/ios/PushSignalCenter.h +26 -0
- package/ios/PushSignalCenter.m +608 -0
- package/ios/PushSignalLaunchStore.m +6 -9
- package/lib/module/NativePushSignal.js +5 -0
- package/lib/module/NativePushSignal.js.map +1 -0
- package/lib/module/pushSignal.native.js +36 -12
- package/lib/module/pushSignal.native.js.map +1 -1
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/src/NativePushSignal.d.ts +22 -0
- package/lib/typescript/src/NativePushSignal.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/pushSignal.d.ts +1 -1
- package/lib/typescript/src/pushSignal.d.ts.map +1 -1
- package/lib/typescript/src/pushSignal.native.d.ts +1 -1
- package/lib/typescript/src/pushSignal.native.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +22 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +14 -19
- package/src/NativePushSignal.ts +25 -0
- package/src/index.tsx +1 -1
- package/src/pushSignal.native.tsx +60 -22
- package/src/pushSignal.tsx +1 -1
- package/src/types.ts +25 -0
- package/android/CMakeLists.txt +0 -24
- package/android/src/main/cpp/cpp-adapter.cpp +0 -11
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignal.kt +0 -38
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignalPackage.kt +0 -22
- package/ios/PushSignal.swift +0 -29
- package/ios/PushSignalCenter.swift +0 -588
- package/lib/module/PushSignal.nitro.js +0 -4
- package/lib/module/PushSignal.nitro.js.map +0 -1
- package/lib/typescript/src/PushSignal.nitro.d.ts +0 -32
- package/lib/typescript/src/PushSignal.nitro.d.ts.map +0 -1
- package/nitro.json +0 -23
- package/nitrogen/generated/android/c++/JAndroidFirebaseConfig.hpp +0 -70
- package/nitrogen/generated/android/c++/JFunc_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.hpp +0 -128
- package/nitrogen/generated/android/c++/JFunc_void_PushMessage.hpp +0 -80
- package/nitrogen/generated/android/c++/JHybridPushSignalSpec.cpp +0 -115
- package/nitrogen/generated/android/c++/JHybridPushSignalSpec.hpp +0 -66
- package/nitrogen/generated/android/c++/JPushCredentials.hpp +0 -70
- package/nitrogen/generated/android/c++/JPushEnvironment.hpp +0 -58
- package/nitrogen/generated/android/c++/JPushMessage.hpp +0 -84
- package/nitrogen/generated/android/c++/JPushPlatform.hpp +0 -58
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/AndroidFirebaseConfig.kt +0 -66
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.kt +0 -78
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/Func_void_PushMessage.kt +0 -78
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/HybridPushSignalSpec.kt +0 -79
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushCredentials.kt +0 -61
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushEnvironment.kt +0 -23
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushMessage.kt +0 -66
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushPlatform.kt +0 -23
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/pushsignalOnLoad.kt +0 -35
- package/nitrogen/generated/android/pushsignal+autolinking.cmake +0 -81
- package/nitrogen/generated/android/pushsignal+autolinking.gradle +0 -27
- package/nitrogen/generated/android/pushsignalOnLoad.cpp +0 -58
- package/nitrogen/generated/android/pushsignalOnLoad.hpp +0 -34
- package/nitrogen/generated/ios/PushSignal+autolinking.rb +0 -62
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.cpp +0 -90
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.hpp +0 -345
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Umbrella.hpp +0 -63
- package/nitrogen/generated/ios/PushSignalAutolinking.mm +0 -33
- package/nitrogen/generated/ios/PushSignalAutolinking.swift +0 -26
- package/nitrogen/generated/ios/c++/HybridPushSignalSpecSwift.cpp +0 -11
- package/nitrogen/generated/ios/c++/HybridPushSignalSpecSwift.hpp +0 -120
- package/nitrogen/generated/ios/swift/AndroidFirebaseConfig.swift +0 -96
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_bool_____PushMessage.swift +0 -61
- package/nitrogen/generated/ios/swift/Func_void.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_PushCredentials.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_PushMessage.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +0 -46
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_bool__.swift +0 -66
- package/nitrogen/generated/ios/swift/HybridPushSignalSpec.swift +0 -58
- package/nitrogen/generated/ios/swift/HybridPushSignalSpec_cxx.swift +0 -217
- package/nitrogen/generated/ios/swift/PushCredentials.swift +0 -45
- package/nitrogen/generated/ios/swift/PushEnvironment.swift +0 -40
- package/nitrogen/generated/ios/swift/PushMessage.swift +0 -97
- package/nitrogen/generated/ios/swift/PushPlatform.swift +0 -40
- package/nitrogen/generated/shared/c++/AndroidFirebaseConfig.hpp +0 -96
- package/nitrogen/generated/shared/c++/HybridPushSignalSpec.cpp +0 -24
- package/nitrogen/generated/shared/c++/HybridPushSignalSpec.hpp +0 -74
- package/nitrogen/generated/shared/c++/PushCredentials.hpp +0 -97
- package/nitrogen/generated/shared/c++/PushEnvironment.hpp +0 -76
- package/nitrogen/generated/shared/c++/PushMessage.hpp +0 -97
- package/nitrogen/generated/shared/c++/PushPlatform.hpp +0 -76
- package/src/PushSignal.nitro.ts +0 -39
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026
|
|
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
|
package/PushSignal.podspec
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
|
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).
|
|
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
|
|
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
|
|
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, пока процесс жив).
|
|
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`) ничего не делают.
|
package/android/build.gradle
CHANGED
|
@@ -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.
|
|
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.
|
|
2
|
-
-keep class com.
|
|
3
|
-
-keep class com.
|
|
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.
|
|
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.
|
|
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
|
+
)
|
package/android/src/main/java/com/{margelo/nitro/pushsignal → pushsignal}/PushSignalCenter.kt
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
package com.
|
|
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) ->
|
|
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) ->
|
|
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
|
|
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
|
-
|
|
140
|
+
pendingMessages.add(message)
|
|
183
141
|
return
|
|
184
142
|
}
|
|
185
143
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
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
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
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
|
|
|
@@ -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
|
+
}
|
package/ios/PushSignal.h
ADDED
|
@@ -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
|