react-native-mehery-event-sender 0.0.2 → 0.0.5
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/README.md +63 -8
- package/android/build.gradle +30 -1
- package/android/gradle.properties +7 -1
- package/android/src/main/AndroidManifest.xml +11 -1
- package/android/src/main/java/com/meheryeventsender/CustomNotificationService.kt +199 -0
- package/android/src/main/java/com/meheryeventsender/LiveActivityModule.kt +32 -0
- package/android/src/main/java/com/meheryeventsender/LiveActivityUtils.kt +56 -0
- package/android/src/main/java/com/meheryeventsender/MeheryEventSenderPackage.kt +3 -1
- package/android/src/main/java/com/meheryeventsender/MyFirebaseMessagingService.kt +137 -0
- package/android/src/main/res/drawable/notification_bg.xml +5 -0
- package/android/src/main/res/layout/custom_notification_layout.xml +84 -0
- package/android/src/main/res/mipmap/ic_launcher.png +0 -0
- package/lib/module/components/BannerPoll.js +64 -0
- package/lib/module/components/BannerPoll.js.map +1 -0
- package/lib/module/components/BannerScreen.js +44 -0
- package/lib/module/components/BannerScreen.js.map +1 -0
- package/lib/module/components/BottomSheetPoll.js +162 -0
- package/lib/module/components/BottomSheetPoll.js.map +1 -0
- package/lib/module/components/CustomBanner.js +51 -0
- package/lib/module/components/CustomBanner.js.map +1 -0
- package/lib/module/components/FloaterPoll.js +113 -0
- package/lib/module/components/FloaterPoll.js.map +1 -0
- package/lib/module/components/PipPoll.js +169 -0
- package/lib/module/components/PipPoll.js.map +1 -0
- package/lib/module/components/PollOverlay.js +157 -0
- package/lib/module/components/PollOverlay.js.map +1 -0
- package/lib/module/components/RenderInlinePoll.js +178 -0
- package/lib/module/components/RenderInlinePoll.js.map +1 -0
- package/lib/module/components/RoadblockPoll.js +130 -0
- package/lib/module/components/RoadblockPoll.js.map +1 -0
- package/lib/module/components/TooltipEmitter.js +8 -0
- package/lib/module/components/TooltipEmitter.js.map +1 -0
- package/lib/module/components/TooltipPoll.js +84 -0
- package/lib/module/components/TooltipPoll.js.map +1 -0
- package/lib/module/components/TooltipPollContainer.js +99 -0
- package/lib/module/components/TooltipPollContainer.js.map +1 -0
- package/lib/module/components/TooltipPollManager.js +11 -0
- package/lib/module/components/TooltipPollManager.js.map +1 -0
- package/lib/module/events/custom/CustomEvents.js +263 -0
- package/lib/module/events/custom/CustomEvents.js.map +1 -0
- package/lib/module/events/default/DefaultEvents.js +46 -0
- package/lib/module/events/default/DefaultEvents.js.map +1 -0
- package/lib/module/firebase/Fb.js +146 -0
- package/lib/module/firebase/Fb.js.map +1 -0
- package/lib/module/firebase/IosAPNS.js +100 -0
- package/lib/module/firebase/IosAPNS.js.map +1 -0
- package/lib/module/index.js +156 -101
- package/lib/module/index.js.map +1 -1
- package/lib/module/native/LiveActivity.js +20 -0
- package/lib/module/native/LiveActivity.js.map +1 -0
- package/lib/module/native/MeheryEventSenderView.js +12 -0
- package/lib/module/native/MeheryEventSenderView.js.map +1 -0
- package/lib/module/socket/SocketManager.js +77 -0
- package/lib/module/socket/SocketManager.js.map +1 -0
- package/lib/module/socket/WebSock.js +63 -0
- package/lib/module/socket/WebSock.js.map +1 -0
- package/lib/module/types/react-native-push-notification.d.js +2 -0
- package/lib/module/types/react-native-push-notification.d.js.map +1 -0
- package/lib/module/utils/device.js +30 -0
- package/lib/module/utils/device.js.map +1 -0
- package/lib/module/utils/user.js +106 -0
- package/lib/module/utils/user.js.map +1 -0
- package/lib/typescript/src/components/BannerPoll.d.ts +2 -0
- package/lib/typescript/src/components/BannerPoll.d.ts.map +1 -0
- package/lib/typescript/src/components/BannerScreen.d.ts +3 -0
- package/lib/typescript/src/components/BannerScreen.d.ts.map +1 -0
- package/lib/typescript/src/components/BottomSheetPoll.d.ts +8 -0
- package/lib/typescript/src/components/BottomSheetPoll.d.ts.map +1 -0
- package/lib/typescript/src/components/CustomBanner.d.ts +10 -0
- package/lib/typescript/src/components/CustomBanner.d.ts.map +1 -0
- package/lib/typescript/src/components/FloaterPoll.d.ts +10 -0
- package/lib/typescript/src/components/FloaterPoll.d.ts.map +1 -0
- package/lib/typescript/src/components/PipPoll.d.ts +8 -0
- package/lib/typescript/src/components/PipPoll.d.ts.map +1 -0
- package/lib/typescript/src/components/PollOverlay.d.ts +5 -0
- package/lib/typescript/src/components/PollOverlay.d.ts.map +1 -0
- package/lib/typescript/src/components/RenderInlinePoll.d.ts +5 -0
- package/lib/typescript/src/components/RenderInlinePoll.d.ts.map +1 -0
- package/lib/typescript/src/components/RoadblockPoll.d.ts +2 -0
- package/lib/typescript/src/components/RoadblockPoll.d.ts.map +1 -0
- package/lib/typescript/src/components/TooltipEmitter.d.ts +7 -0
- package/lib/typescript/src/components/TooltipEmitter.d.ts.map +1 -0
- package/lib/typescript/src/components/TooltipPoll.d.ts +27 -0
- package/lib/typescript/src/components/TooltipPoll.d.ts.map +1 -0
- package/lib/typescript/src/components/TooltipPollContainer.d.ts +7 -0
- package/lib/typescript/src/components/TooltipPollContainer.d.ts.map +1 -0
- package/lib/typescript/src/components/TooltipPollManager.d.ts +2 -0
- package/lib/typescript/src/components/TooltipPollManager.d.ts.map +1 -0
- package/lib/typescript/src/events/custom/CustomEvents.d.ts +11 -0
- package/lib/typescript/src/events/custom/CustomEvents.d.ts.map +1 -0
- package/lib/typescript/src/events/default/DefaultEvents.d.ts +3 -0
- package/lib/typescript/src/events/default/DefaultEvents.d.ts.map +1 -0
- package/lib/typescript/src/firebase/Fb.d.ts +18 -0
- package/lib/typescript/src/firebase/Fb.d.ts.map +1 -0
- package/lib/typescript/src/firebase/IosAPNS.d.ts +6 -0
- package/lib/typescript/src/firebase/IosAPNS.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +12 -21
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/native/LiveActivity.d.ts +2 -0
- package/lib/typescript/src/native/LiveActivity.d.ts.map +1 -0
- package/lib/typescript/src/native/MeheryEventSenderView.d.ts +8 -0
- package/lib/typescript/src/native/MeheryEventSenderView.d.ts.map +1 -0
- package/lib/typescript/src/socket/SocketManager.d.ts +13 -0
- package/lib/typescript/src/socket/SocketManager.d.ts.map +1 -0
- package/lib/typescript/src/socket/WebSock.d.ts +4 -0
- package/lib/typescript/src/socket/WebSock.d.ts.map +1 -0
- package/lib/typescript/src/utils/device.d.ts +2 -0
- package/lib/typescript/src/utils/device.d.ts.map +1 -0
- package/lib/typescript/src/utils/user.d.ts +9 -0
- package/lib/typescript/src/utils/user.d.ts.map +1 -0
- package/package.json +15 -3
- package/src/components/BannerPoll.tsx +67 -0
- package/src/components/BannerScreen.tsx +49 -0
- package/src/components/BottomSheetPoll.tsx +182 -0
- package/src/components/CustomBanner.tsx +48 -0
- package/src/components/FloaterPoll.tsx +116 -0
- package/src/components/PipPoll.tsx +166 -0
- package/src/components/PollOverlay.tsx +187 -0
- package/src/components/RenderInlinePoll.tsx +229 -0
- package/src/components/RoadblockPoll.tsx +133 -0
- package/src/components/TooltipEmitter.ts +12 -0
- package/src/components/TooltipPoll.tsx +127 -0
- package/src/components/TooltipPollContainer.tsx +105 -0
- package/src/components/TooltipPollManager.tsx +6 -0
- package/src/events/custom/CustomEvents.tsx +260 -0
- package/src/events/default/DefaultEvents.ts +52 -0
- package/src/firebase/Fb.ts +178 -0
- package/src/firebase/IosAPNS.ts +136 -0
- package/src/index.tsx +186 -128
- package/src/native/LiveActivity.ts +20 -0
- package/src/native/MeheryEventSenderView.ts +22 -0
- package/src/socket/SocketManager.ts +92 -0
- package/src/socket/WebSock.ts +71 -0
- package/src/types/react-native-push-notification.d.ts +4 -0
- package/src/utils/device.ts +31 -0
- package/src/utils/user.ts +129 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# react-native-mehery-event-sender
|
|
2
2
|
|
|
3
|
-
A React Native SDK
|
|
3
|
+
A lightweight React Native SDK to support push notifications, custom in-app messages (popup, banner, PiP), event tracking, and session handling for your apps.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,27 +8,82 @@ A React Native SDK for event tracking that works with both Expo Go and bare Reac
|
|
|
8
8
|
npm install react-native-mehery-event-sender
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
11
|
+
## 🚀 Initialization
|
|
12
12
|
|
|
13
|
+
Initialize the SDK in your App.tsx
|
|
13
14
|
|
|
14
15
|
```js
|
|
15
|
-
import {
|
|
16
|
+
import { initSdk } from 'react-native-mehery-event-sender';
|
|
16
17
|
|
|
17
18
|
// ...
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
initSdk(
|
|
21
|
+
(context = this),
|
|
22
|
+
(identifier = 'demo_1754408042569'),
|
|
23
|
+
(sandbox = true)
|
|
24
|
+
);
|
|
20
25
|
```
|
|
21
26
|
|
|
27
|
+
To login the user:
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
```js
|
|
30
|
+
import { onUserLogin } from 'react-native-mehery-event-sender';
|
|
31
|
+
|
|
32
|
+
// ...
|
|
33
|
+
|
|
34
|
+
OnUserLogin('user_id');
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 🎯 Event Tracking
|
|
38
|
+
|
|
39
|
+
To track user actions or custom events:
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
import { sendCustomEvent } from 'react-native-mehery-event-sender';
|
|
43
|
+
|
|
44
|
+
// ...
|
|
45
|
+
// Send a simple event
|
|
46
|
+
sendCustomEvent('login_clicked', { userId: '12345' });
|
|
47
|
+
|
|
48
|
+
// Send an event with multiple properties
|
|
49
|
+
sendCustomEvent('purchase_made', {
|
|
50
|
+
itemId: '987',
|
|
51
|
+
amount: 299,
|
|
52
|
+
currency: 'USD',
|
|
53
|
+
});
|
|
54
|
+
```
|
|
24
55
|
|
|
25
|
-
|
|
56
|
+
## 🔔 Notification Handling
|
|
26
57
|
|
|
27
|
-
|
|
58
|
+
The SDK auto-registers FCM token and handles push notifications. Ensure you have Firebase configured.
|
|
59
|
+
|
|
60
|
+
## In-App Notifications
|
|
61
|
+
|
|
62
|
+
The SDK handles: -- Popup full-screen . -- Banner with inline dismiss. -- PiP small floating view with expand logic to popup.
|
|
63
|
+
No integration required from your side. The SDK renders them when triggered.
|
|
64
|
+
|
|
65
|
+
## 📄 ProGuard
|
|
66
|
+
|
|
67
|
+
-keep class com.mehery.pushapp.\*_ { _; }
|
|
68
|
+
|
|
69
|
+
## 🏷️ Versions
|
|
70
|
+
|
|
71
|
+
Latest Version: 0.0.5 Hosted on npm.
|
|
72
|
+
|
|
73
|
+
## 💬 Support
|
|
74
|
+
|
|
75
|
+
Raise issues or feature requests in GitHub Issues
|
|
76
|
+
|
|
77
|
+
<!-- ## Contributing
|
|
78
|
+
|
|
79
|
+
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. -->
|
|
80
|
+
|
|
81
|
+
<!-- ## License
|
|
28
82
|
|
|
29
83
|
MIT
|
|
30
84
|
|
|
31
85
|
---
|
|
32
86
|
|
|
33
|
-
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
|
87
|
+
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) -->
|
|
88
|
+
|
|
34
89
|
# react-native-mehery-event-sender
|
package/android/build.gradle
CHANGED
|
@@ -15,6 +15,21 @@ buildscript {
|
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
allprojects {
|
|
19
|
+
configurations.all {
|
|
20
|
+
resolutionStrategy {
|
|
21
|
+
force 'androidx.core:core:1.13.1'
|
|
22
|
+
force 'androidx.appcompat:appcompat:1.6.1'
|
|
23
|
+
|
|
24
|
+
// Exclude support libraries
|
|
25
|
+
exclude group: 'com.android.support', module: 'support-compat'
|
|
26
|
+
exclude group: 'com.android.support', module: 'support-core-utils'
|
|
27
|
+
exclude group: 'com.android.support', module: 'support-core-ui'
|
|
28
|
+
exclude group: 'com.android.support', module: 'support-fragment'
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
|
|
19
34
|
apply plugin: "com.android.library"
|
|
20
35
|
apply plugin: "kotlin-android"
|
|
@@ -40,6 +55,16 @@ android {
|
|
|
40
55
|
sourceSets {
|
|
41
56
|
main {
|
|
42
57
|
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
58
|
+
res.srcDirs = ['src/main/res'] // 👈 Add this line
|
|
59
|
+
main.java.srcDirs += 'src/main/java'
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
sourceSets {
|
|
66
|
+
main {
|
|
67
|
+
res.srcDirs = ['src/main/res']
|
|
43
68
|
}
|
|
44
69
|
}
|
|
45
70
|
}
|
|
@@ -65,8 +90,10 @@ android {
|
|
|
65
90
|
sourceCompatibility JavaVersion.VERSION_1_8
|
|
66
91
|
targetCompatibility JavaVersion.VERSION_1_8
|
|
67
92
|
}
|
|
93
|
+
|
|
68
94
|
}
|
|
69
95
|
|
|
96
|
+
|
|
70
97
|
repositories {
|
|
71
98
|
mavenCentral()
|
|
72
99
|
google()
|
|
@@ -75,7 +102,9 @@ repositories {
|
|
|
75
102
|
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
76
103
|
|
|
77
104
|
dependencies {
|
|
78
|
-
implementation "com.facebook.react:react-android"
|
|
105
|
+
implementation "com.facebook.react:react-android:0.80.0"
|
|
106
|
+
implementation 'com.google.firebase:firebase-messaging:24.0.0'
|
|
107
|
+
|
|
79
108
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
80
109
|
}
|
|
81
110
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
MeheryEventSender_kotlinVersion=2.0.21
|
|
2
2
|
MeheryEventSender_minSdkVersion=24
|
|
3
|
-
MeheryEventSender_targetSdkVersion=
|
|
3
|
+
MeheryEventSender_targetSdkVersion=35
|
|
4
4
|
MeheryEventSender_compileSdkVersion=35
|
|
5
5
|
MeheryEventSender_ndkVersion=27.1.12297006
|
|
6
|
+
android.useAndroidX=true
|
|
7
|
+
android.enableJetifier=true
|
|
8
|
+
|
|
9
|
+
# Increase heap size for Jetifier and Kotlin
|
|
10
|
+
org.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8
|
|
11
|
+
kotlin.daemon.jvmargs=-Xmx2048m
|
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
-
|
|
2
|
+
package="com.meheryeventsender">
|
|
3
|
+
|
|
4
|
+
<application>
|
|
5
|
+
<service
|
|
6
|
+
android:name="com.meheryeventsender.MyFirebaseMessagingService"
|
|
7
|
+
android:exported="false">
|
|
8
|
+
<intent-filter>
|
|
9
|
+
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
10
|
+
</intent-filter>
|
|
11
|
+
</service>
|
|
12
|
+
</application>
|
|
3
13
|
</manifest>
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
package com.meheryeventsender
|
|
2
|
+
|
|
3
|
+
import android.app.PendingIntent
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.graphics.*
|
|
6
|
+
import android.widget.RemoteViews
|
|
7
|
+
import androidx.core.app.NotificationCompat
|
|
8
|
+
import java.io.InputStream
|
|
9
|
+
import java.net.HttpURLConnection
|
|
10
|
+
import java.net.URL
|
|
11
|
+
import android.os.Handler
|
|
12
|
+
import android.os.Looper
|
|
13
|
+
import android.app.NotificationManager
|
|
14
|
+
import android.graphics.drawable.GradientDrawable
|
|
15
|
+
import com.meheryeventsender.R
|
|
16
|
+
|
|
17
|
+
class CustomNotificationService(private val context: Context) {
|
|
18
|
+
|
|
19
|
+
fun createCustomNotification(
|
|
20
|
+
channelId: String,
|
|
21
|
+
title: String,
|
|
22
|
+
message: String,
|
|
23
|
+
tapText: String,
|
|
24
|
+
progress: Int,
|
|
25
|
+
titleColor: String,
|
|
26
|
+
messageColor: String,
|
|
27
|
+
tapTextColor: String,
|
|
28
|
+
progressColor: String,
|
|
29
|
+
backgroundColor: String,
|
|
30
|
+
imageUrl: String,
|
|
31
|
+
bg_color_gradient: String,
|
|
32
|
+
bg_color_gradient_dir: String,
|
|
33
|
+
align: String,
|
|
34
|
+
notificationId: Int
|
|
35
|
+
): NotificationCompat.Builder {
|
|
36
|
+
val customView = RemoteViews(context.packageName, R.layout.custom_notification_layout)
|
|
37
|
+
|
|
38
|
+
// 🔵 Apply background (solid or gradient)
|
|
39
|
+
try {
|
|
40
|
+
if (bg_color_gradient.isNotEmpty() && bg_color_gradient_dir.isNotEmpty()) {
|
|
41
|
+
val startColor = Color.parseColor(backgroundColor)
|
|
42
|
+
val endColor = Color.parseColor(bg_color_gradient)
|
|
43
|
+
val isHorizontal = bg_color_gradient_dir.equals("horizontal", ignoreCase = true)
|
|
44
|
+
|
|
45
|
+
val gradientBitmap = createGradientBitmap(startColor, endColor, isHorizontal)
|
|
46
|
+
customView.setImageViewBitmap(R.id.root_background, gradientBitmap)
|
|
47
|
+
} else {
|
|
48
|
+
val solidBitmap = createSolidColorBitmap(Color.parseColor(backgroundColor))
|
|
49
|
+
customView.setImageViewBitmap(R.id.root_background, solidBitmap)
|
|
50
|
+
}
|
|
51
|
+
} catch (e: Exception) {
|
|
52
|
+
e.printStackTrace()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
customView.setTextViewText(R.id.title, title)
|
|
56
|
+
customView.setTextViewText(R.id.message, message)
|
|
57
|
+
customView.setTextViewText(R.id.tap_text, tapText)
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
customView.setTextColor(R.id.title, Color.parseColor(titleColor))
|
|
61
|
+
customView.setTextColor(R.id.message, Color.parseColor(messageColor))
|
|
62
|
+
customView.setTextColor(R.id.tap_text, Color.parseColor(tapTextColor))
|
|
63
|
+
} catch (e: Exception) {
|
|
64
|
+
e.printStackTrace()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
customView.setProgressBar(R.id.progress_bar, 100, progress, false)
|
|
68
|
+
customView.setImageViewResource(R.id.icon, R.mipmap.ic_launcher)
|
|
69
|
+
|
|
70
|
+
// NOTE: Removed setLayoutDirection calls here because RemoteViews does not support them.
|
|
71
|
+
// Handle layoutDirection in your XML layouts with android:layoutDirection attribute if needed.
|
|
72
|
+
|
|
73
|
+
val builder = NotificationCompat.Builder(context, channelId)
|
|
74
|
+
.setSmallIcon(R.mipmap.ic_launcher)
|
|
75
|
+
.setCustomContentView(customView)
|
|
76
|
+
.setCustomBigContentView(customView)
|
|
77
|
+
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
|
|
78
|
+
.setPriority(NotificationCompat.PRIORITY_MAX)
|
|
79
|
+
.setOngoing(true)
|
|
80
|
+
.setAutoCancel(false)
|
|
81
|
+
.setContentTitle(title)
|
|
82
|
+
.setContentText(message)
|
|
83
|
+
.setSubText(tapText)
|
|
84
|
+
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
85
|
+
|
|
86
|
+
val intent = context.packageManager.getLaunchIntentForPackage(context.packageName)
|
|
87
|
+
val pendingIntent = PendingIntent.getActivity(
|
|
88
|
+
context, 0, intent,
|
|
89
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
90
|
+
)
|
|
91
|
+
builder.setContentIntent(pendingIntent)
|
|
92
|
+
|
|
93
|
+
if (imageUrl.isNotEmpty()) {
|
|
94
|
+
downloadImage(imageUrl) { bitmap ->
|
|
95
|
+
if (bitmap != null) {
|
|
96
|
+
val updatedView = RemoteViews(context.packageName, R.layout.custom_notification_layout)
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
val bgBitmap = if (bg_color_gradient.isNotEmpty() && bg_color_gradient_dir.isNotEmpty()) {
|
|
100
|
+
val startColor = Color.parseColor(backgroundColor)
|
|
101
|
+
val endColor = Color.parseColor(bg_color_gradient)
|
|
102
|
+
val isHorizontal = bg_color_gradient_dir.equals("horizontal", ignoreCase = true)
|
|
103
|
+
createGradientBitmap(startColor, endColor, isHorizontal)
|
|
104
|
+
} else {
|
|
105
|
+
createSolidColorBitmap(Color.parseColor(backgroundColor))
|
|
106
|
+
}
|
|
107
|
+
updatedView.setImageViewBitmap(R.id.root_background, bgBitmap)
|
|
108
|
+
} catch (_: Exception) {}
|
|
109
|
+
|
|
110
|
+
updatedView.setTextViewText(R.id.title, title)
|
|
111
|
+
updatedView.setTextViewText(R.id.message, message)
|
|
112
|
+
updatedView.setTextViewText(R.id.tap_text, tapText)
|
|
113
|
+
updatedView.setTextColor(R.id.title, Color.parseColor(titleColor))
|
|
114
|
+
updatedView.setTextColor(R.id.message, Color.parseColor(messageColor))
|
|
115
|
+
updatedView.setTextColor(R.id.tap_text, Color.parseColor(tapTextColor))
|
|
116
|
+
updatedView.setProgressBar(R.id.progress_bar, 100, progress, false)
|
|
117
|
+
updatedView.setImageViewBitmap(R.id.icon, bitmap)
|
|
118
|
+
|
|
119
|
+
// Removed setLayoutDirection here as well.
|
|
120
|
+
|
|
121
|
+
val updatedBuilder = NotificationCompat.Builder(context, channelId)
|
|
122
|
+
.setSmallIcon(R.mipmap.ic_launcher)
|
|
123
|
+
.setCustomContentView(updatedView)
|
|
124
|
+
.setCustomBigContentView(updatedView)
|
|
125
|
+
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
|
|
126
|
+
.setPriority(NotificationCompat.PRIORITY_MAX)
|
|
127
|
+
.setOngoing(true)
|
|
128
|
+
.setAutoCancel(false)
|
|
129
|
+
.setContentTitle(title)
|
|
130
|
+
.setContentText(message)
|
|
131
|
+
.setSubText(tapText)
|
|
132
|
+
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
133
|
+
.setContentIntent(pendingIntent)
|
|
134
|
+
println("NotifID 3")
|
|
135
|
+
println(notificationId)
|
|
136
|
+
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
137
|
+
manager.notify(notificationId, updatedBuilder.build())
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return builder
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
fun createGradientBitmap(
|
|
146
|
+
startColor: Int,
|
|
147
|
+
endColor: Int,
|
|
148
|
+
isHorizontal: Boolean,
|
|
149
|
+
width: Int = 1080,
|
|
150
|
+
height: Int = 300
|
|
151
|
+
): Bitmap {
|
|
152
|
+
val orientation = if (isHorizontal) GradientDrawable.Orientation.LEFT_RIGHT
|
|
153
|
+
else GradientDrawable.Orientation.TOP_BOTTOM
|
|
154
|
+
|
|
155
|
+
val gradient = GradientDrawable(orientation, intArrayOf(startColor, endColor))
|
|
156
|
+
gradient.setBounds(0, 0, width, height)
|
|
157
|
+
|
|
158
|
+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
159
|
+
val canvas = Canvas(bitmap)
|
|
160
|
+
gradient.draw(canvas)
|
|
161
|
+
return bitmap
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
fun createSolidColorBitmap(color: Int, width: Int = 1080, height: Int = 300): Bitmap {
|
|
165
|
+
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
|
166
|
+
bitmap.eraseColor(color)
|
|
167
|
+
return bitmap
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
fun downloadImage(urlString: String, onResult: (Bitmap?) -> Unit) {
|
|
171
|
+
val cleanUrl = if (urlString.startsWith("@")) urlString.substring(1) else urlString
|
|
172
|
+
Thread {
|
|
173
|
+
var bitmap: Bitmap? = null
|
|
174
|
+
try {
|
|
175
|
+
val url = URL(cleanUrl)
|
|
176
|
+
val connection = url.openConnection() as HttpURLConnection
|
|
177
|
+
connection.doInput = true
|
|
178
|
+
connection.connectTimeout = 15000
|
|
179
|
+
connection.readTimeout = 15000
|
|
180
|
+
connection.connect()
|
|
181
|
+
if (connection.responseCode == 200) {
|
|
182
|
+
val input: InputStream = connection.inputStream
|
|
183
|
+
bitmap = BitmapFactory.decodeStream(input)
|
|
184
|
+
}
|
|
185
|
+
} catch (e: Exception) {
|
|
186
|
+
e.printStackTrace()
|
|
187
|
+
}
|
|
188
|
+
Handler(Looper.getMainLooper()).post {
|
|
189
|
+
onResult(bitmap)
|
|
190
|
+
}
|
|
191
|
+
}.start()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
fun testImageLoading(imageUrl: String, callback: (Boolean) -> Unit) {
|
|
195
|
+
downloadImage(imageUrl) { bitmap ->
|
|
196
|
+
callback(bitmap != null)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package com.meheryeventsender
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.*
|
|
4
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
5
|
+
|
|
6
|
+
@ReactModule(name = LiveActivityModule.NAME)
|
|
7
|
+
class LiveActivityModule(private val reactContext: ReactApplicationContext) :
|
|
8
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
9
|
+
|
|
10
|
+
companion object {
|
|
11
|
+
const val NAME = "LiveActivityModule"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun getName(): String = NAME
|
|
15
|
+
|
|
16
|
+
@ReactMethod
|
|
17
|
+
fun triggerLiveActivity(dataMap: ReadableMap) {
|
|
18
|
+
val data = mutableMapOf<String, String>()
|
|
19
|
+
val iterator = dataMap.keySetIterator()
|
|
20
|
+
|
|
21
|
+
while (iterator.hasNextKey()) {
|
|
22
|
+
val key = iterator.nextKey()
|
|
23
|
+
val value = dataMap.getString(key)
|
|
24
|
+
if (value != null) {
|
|
25
|
+
data[key] = value
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ✅ Call the shared utility instead of private method
|
|
30
|
+
LiveActivityUtils.handleLiveActivityNotification(reactContext, data)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package com.meheryeventsender
|
|
2
|
+
|
|
3
|
+
import android.app.NotificationManager
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.os.Build
|
|
6
|
+
import android.util.Log
|
|
7
|
+
import android.app.NotificationChannel
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
object LiveActivityUtils {
|
|
11
|
+
|
|
12
|
+
fun handleLiveActivityNotification(context: Context, data: Map<String, String>) {
|
|
13
|
+
try {
|
|
14
|
+
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
15
|
+
|
|
16
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
17
|
+
val channelId = "live_activity_channel"
|
|
18
|
+
val channelName = "Live Activity Notifications"
|
|
19
|
+
val channel = NotificationChannel(
|
|
20
|
+
channelId,
|
|
21
|
+
channelName,
|
|
22
|
+
NotificationManager.IMPORTANCE_HIGH
|
|
23
|
+
)
|
|
24
|
+
notificationManager.createNotificationChannel(channel)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
val customService = CustomNotificationService(context)
|
|
28
|
+
|
|
29
|
+
val notificationId = (data["activity_id"] ?: "activity_${System.currentTimeMillis()}").hashCode()
|
|
30
|
+
|
|
31
|
+
val notification = customService.createCustomNotification(
|
|
32
|
+
channelId = "live_activity_channel",
|
|
33
|
+
title = data["message1"] ?: "",
|
|
34
|
+
message = data["message2"] ?: "",
|
|
35
|
+
tapText = data["message3"] ?: "",
|
|
36
|
+
progress = ((data["progressPercent"]?.toDoubleOrNull() ?: 0.0) * 100).toInt(),
|
|
37
|
+
titleColor = data["message1FontColorHex"] ?: "#FF0000",
|
|
38
|
+
messageColor = data["message2FontColorHex"] ?: "#000000",
|
|
39
|
+
tapTextColor = data["message3FontColorHex"] ?: "#CCCCCC",
|
|
40
|
+
progressColor = data["progressColorHex"] ?: "#00FF00",
|
|
41
|
+
backgroundColor = data["backgroundColorHex"] ?: "#FFFFFF",
|
|
42
|
+
imageUrl = data["imageUrl"] ?: "",
|
|
43
|
+
bg_color_gradient = data["bg_color_gradient"] ?: "",
|
|
44
|
+
bg_color_gradient_dir = data["bg_color_gradient_dir"] ?: "",
|
|
45
|
+
align = data["align"] ?: "",
|
|
46
|
+
notificationId = notificationId
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
Log.d("LiveActivityUtils", "Notifying with ID: $notificationId")
|
|
50
|
+
notificationManager.notify(notificationId, notification.build())
|
|
51
|
+
|
|
52
|
+
} catch (e: Exception) {
|
|
53
|
+
Log.e("LiveActivityUtils", "Live activity error: ${e.message}", e)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -8,7 +8,9 @@ import com.facebook.react.uimanager.ViewManager
|
|
|
8
8
|
|
|
9
9
|
class MeheryEventSenderPackage : ReactPackage {
|
|
10
10
|
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
11
|
-
|
|
11
|
+
return listOf(
|
|
12
|
+
LiveActivityModule(reactContext)
|
|
13
|
+
)
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
package com.meheryeventsender
|
|
2
|
+
import com.meheryeventsender.CustomNotificationService
|
|
3
|
+
|
|
4
|
+
import com.meheryeventsender.R
|
|
5
|
+
|
|
6
|
+
import android.app.NotificationChannel
|
|
7
|
+
import android.app.NotificationManager
|
|
8
|
+
import android.content.Context
|
|
9
|
+
import android.os.Build
|
|
10
|
+
import android.app.PendingIntent
|
|
11
|
+
import android.content.BroadcastReceiver
|
|
12
|
+
import android.content.Intent
|
|
13
|
+
import android.util.Log
|
|
14
|
+
import com.google.firebase.messaging.FirebaseMessagingService
|
|
15
|
+
import com.google.firebase.messaging.RemoteMessage
|
|
16
|
+
import androidx.core.app.NotificationCompat
|
|
17
|
+
|
|
18
|
+
class MyFirebaseMessagingService : FirebaseMessagingService() {
|
|
19
|
+
private val TAG = "MyFirebaseMessagingService"
|
|
20
|
+
override fun onMessageReceived(remoteMessage: RemoteMessage) {
|
|
21
|
+
Log.d(TAG, "From: ${remoteMessage.from}")
|
|
22
|
+
|
|
23
|
+
// Check if message contains a data payload
|
|
24
|
+
if (remoteMessage.data.isNotEmpty()) {
|
|
25
|
+
Log.d(TAG, "Message data payload: ${remoteMessage.data}")
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Check if this is a live activity notification
|
|
29
|
+
if (remoteMessage.data.containsKey("message1") &&
|
|
30
|
+
remoteMessage.data.containsKey("message2") &&
|
|
31
|
+
remoteMessage.data.containsKey("message3")) {
|
|
32
|
+
|
|
33
|
+
handleLiveActivityNotification(remoteMessage.data)
|
|
34
|
+
} else {
|
|
35
|
+
val title = remoteMessage.data["title"] ?: "Notification"
|
|
36
|
+
val message = remoteMessage.data["body"] ?: "You have a new message"
|
|
37
|
+
val title1 = remoteMessage.data["title1"]
|
|
38
|
+
val url1 = remoteMessage.data["url1"]
|
|
39
|
+
val title2 = remoteMessage.data["title2"]
|
|
40
|
+
val url2 = remoteMessage.data["url2"]
|
|
41
|
+
|
|
42
|
+
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
43
|
+
val channelId = "default_channel_id"
|
|
44
|
+
val channelName = "Default Channel"
|
|
45
|
+
|
|
46
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
47
|
+
val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
|
|
48
|
+
notificationManager.createNotificationChannel(channel)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
val builder = NotificationCompat.Builder(this, channelId)
|
|
54
|
+
.setSmallIcon(R.mipmap.ic_launcher)
|
|
55
|
+
.setContentTitle(title)
|
|
56
|
+
.setContentText(message)
|
|
57
|
+
.setAutoCancel(true)
|
|
58
|
+
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
|
59
|
+
|
|
60
|
+
if (!title1.isNullOrBlank() && !url1.isNullOrBlank()) {
|
|
61
|
+
val intent1 = createUrlIntent(this, url1)
|
|
62
|
+
builder.addAction(0, title1, intent1)
|
|
63
|
+
}
|
|
64
|
+
if (!title2.isNullOrBlank() && !url2.isNullOrBlank()) {
|
|
65
|
+
val intent2 = createUrlIntent(this, url2)
|
|
66
|
+
builder.addAction(0, title2, intent2)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
notificationManager.notify(System.currentTimeMillis().toInt(), builder.build())
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
} catch (e: Exception) {
|
|
74
|
+
Log.e(TAG, "Error handling FCM message", e)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
private fun createUrlIntent(context: Context, url: String): PendingIntent {
|
|
79
|
+
val intent = Intent(Intent.ACTION_VIEW).apply {
|
|
80
|
+
data = android.net.Uri.parse(url)
|
|
81
|
+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
82
|
+
}
|
|
83
|
+
return PendingIntent.getActivity(
|
|
84
|
+
context,
|
|
85
|
+
url.hashCode(), // unique requestCode
|
|
86
|
+
intent,
|
|
87
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private fun handleLiveActivityNotification(data: Map<String, String>) {
|
|
92
|
+
try {
|
|
93
|
+
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
94
|
+
|
|
95
|
+
// ✅ Create the "live_activity_channel" if not already created
|
|
96
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
97
|
+
val channelId = "live_activity_channel"
|
|
98
|
+
val channelName = "Live Activity Notifications"
|
|
99
|
+
val channel = NotificationChannel(
|
|
100
|
+
channelId,
|
|
101
|
+
channelName,
|
|
102
|
+
NotificationManager.IMPORTANCE_HIGH
|
|
103
|
+
)
|
|
104
|
+
notificationManager.createNotificationChannel(channel)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
val customService = CustomNotificationService(this)
|
|
108
|
+
|
|
109
|
+
val notificationId = (data["activity_id"] ?: "activity_${System.currentTimeMillis()}").hashCode()
|
|
110
|
+
|
|
111
|
+
val notification = customService.createCustomNotification(
|
|
112
|
+
channelId = "live_activity_channel",
|
|
113
|
+
title = data["message1"] ?: "",
|
|
114
|
+
message = data["message2"] ?: "",
|
|
115
|
+
tapText = data["message3"] ?: "",
|
|
116
|
+
progress = ((data["progressPercent"]?.toDoubleOrNull() ?: 0.0) * 100).toInt(),
|
|
117
|
+
titleColor = data["message1FontColorHex"] ?: "#FF0000",
|
|
118
|
+
messageColor = data["message2FontColorHex"] ?: "#000000",
|
|
119
|
+
tapTextColor = data["message3FontColorHex"] ?: "#CCCCCC",
|
|
120
|
+
progressColor = data["progressColorHex"] ?: "#00FF00",
|
|
121
|
+
backgroundColor = data["backgroundColorHex"] ?: "#FFFFFF",
|
|
122
|
+
imageUrl = data["imageUrl"] ?: "",
|
|
123
|
+
bg_color_gradient = data["bg_color_gradient"] ?: "",
|
|
124
|
+
bg_color_gradient_dir = data["bg_color_gradient_dir"] ?: "",
|
|
125
|
+
align = data["align"] ?: "",
|
|
126
|
+
notificationId = notificationId
|
|
127
|
+
)
|
|
128
|
+
println("NotifID 2")
|
|
129
|
+
println(notificationId)
|
|
130
|
+
notificationManager.notify(notificationId, notification.build())
|
|
131
|
+
|
|
132
|
+
} catch (e: Exception) {
|
|
133
|
+
Log.e("MySdk", "Live activity error: ${e.message}", e)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|