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.
Files changed (136) hide show
  1. package/README.md +63 -8
  2. package/android/build.gradle +30 -1
  3. package/android/gradle.properties +7 -1
  4. package/android/src/main/AndroidManifest.xml +11 -1
  5. package/android/src/main/java/com/meheryeventsender/CustomNotificationService.kt +199 -0
  6. package/android/src/main/java/com/meheryeventsender/LiveActivityModule.kt +32 -0
  7. package/android/src/main/java/com/meheryeventsender/LiveActivityUtils.kt +56 -0
  8. package/android/src/main/java/com/meheryeventsender/MeheryEventSenderPackage.kt +3 -1
  9. package/android/src/main/java/com/meheryeventsender/MyFirebaseMessagingService.kt +137 -0
  10. package/android/src/main/res/drawable/notification_bg.xml +5 -0
  11. package/android/src/main/res/layout/custom_notification_layout.xml +84 -0
  12. package/android/src/main/res/mipmap/ic_launcher.png +0 -0
  13. package/lib/module/components/BannerPoll.js +64 -0
  14. package/lib/module/components/BannerPoll.js.map +1 -0
  15. package/lib/module/components/BannerScreen.js +44 -0
  16. package/lib/module/components/BannerScreen.js.map +1 -0
  17. package/lib/module/components/BottomSheetPoll.js +162 -0
  18. package/lib/module/components/BottomSheetPoll.js.map +1 -0
  19. package/lib/module/components/CustomBanner.js +51 -0
  20. package/lib/module/components/CustomBanner.js.map +1 -0
  21. package/lib/module/components/FloaterPoll.js +113 -0
  22. package/lib/module/components/FloaterPoll.js.map +1 -0
  23. package/lib/module/components/PipPoll.js +169 -0
  24. package/lib/module/components/PipPoll.js.map +1 -0
  25. package/lib/module/components/PollOverlay.js +157 -0
  26. package/lib/module/components/PollOverlay.js.map +1 -0
  27. package/lib/module/components/RenderInlinePoll.js +178 -0
  28. package/lib/module/components/RenderInlinePoll.js.map +1 -0
  29. package/lib/module/components/RoadblockPoll.js +130 -0
  30. package/lib/module/components/RoadblockPoll.js.map +1 -0
  31. package/lib/module/components/TooltipEmitter.js +8 -0
  32. package/lib/module/components/TooltipEmitter.js.map +1 -0
  33. package/lib/module/components/TooltipPoll.js +84 -0
  34. package/lib/module/components/TooltipPoll.js.map +1 -0
  35. package/lib/module/components/TooltipPollContainer.js +99 -0
  36. package/lib/module/components/TooltipPollContainer.js.map +1 -0
  37. package/lib/module/components/TooltipPollManager.js +11 -0
  38. package/lib/module/components/TooltipPollManager.js.map +1 -0
  39. package/lib/module/events/custom/CustomEvents.js +263 -0
  40. package/lib/module/events/custom/CustomEvents.js.map +1 -0
  41. package/lib/module/events/default/DefaultEvents.js +46 -0
  42. package/lib/module/events/default/DefaultEvents.js.map +1 -0
  43. package/lib/module/firebase/Fb.js +146 -0
  44. package/lib/module/firebase/Fb.js.map +1 -0
  45. package/lib/module/firebase/IosAPNS.js +100 -0
  46. package/lib/module/firebase/IosAPNS.js.map +1 -0
  47. package/lib/module/index.js +156 -101
  48. package/lib/module/index.js.map +1 -1
  49. package/lib/module/native/LiveActivity.js +20 -0
  50. package/lib/module/native/LiveActivity.js.map +1 -0
  51. package/lib/module/native/MeheryEventSenderView.js +12 -0
  52. package/lib/module/native/MeheryEventSenderView.js.map +1 -0
  53. package/lib/module/socket/SocketManager.js +77 -0
  54. package/lib/module/socket/SocketManager.js.map +1 -0
  55. package/lib/module/socket/WebSock.js +63 -0
  56. package/lib/module/socket/WebSock.js.map +1 -0
  57. package/lib/module/types/react-native-push-notification.d.js +2 -0
  58. package/lib/module/types/react-native-push-notification.d.js.map +1 -0
  59. package/lib/module/utils/device.js +30 -0
  60. package/lib/module/utils/device.js.map +1 -0
  61. package/lib/module/utils/user.js +106 -0
  62. package/lib/module/utils/user.js.map +1 -0
  63. package/lib/typescript/src/components/BannerPoll.d.ts +2 -0
  64. package/lib/typescript/src/components/BannerPoll.d.ts.map +1 -0
  65. package/lib/typescript/src/components/BannerScreen.d.ts +3 -0
  66. package/lib/typescript/src/components/BannerScreen.d.ts.map +1 -0
  67. package/lib/typescript/src/components/BottomSheetPoll.d.ts +8 -0
  68. package/lib/typescript/src/components/BottomSheetPoll.d.ts.map +1 -0
  69. package/lib/typescript/src/components/CustomBanner.d.ts +10 -0
  70. package/lib/typescript/src/components/CustomBanner.d.ts.map +1 -0
  71. package/lib/typescript/src/components/FloaterPoll.d.ts +10 -0
  72. package/lib/typescript/src/components/FloaterPoll.d.ts.map +1 -0
  73. package/lib/typescript/src/components/PipPoll.d.ts +8 -0
  74. package/lib/typescript/src/components/PipPoll.d.ts.map +1 -0
  75. package/lib/typescript/src/components/PollOverlay.d.ts +5 -0
  76. package/lib/typescript/src/components/PollOverlay.d.ts.map +1 -0
  77. package/lib/typescript/src/components/RenderInlinePoll.d.ts +5 -0
  78. package/lib/typescript/src/components/RenderInlinePoll.d.ts.map +1 -0
  79. package/lib/typescript/src/components/RoadblockPoll.d.ts +2 -0
  80. package/lib/typescript/src/components/RoadblockPoll.d.ts.map +1 -0
  81. package/lib/typescript/src/components/TooltipEmitter.d.ts +7 -0
  82. package/lib/typescript/src/components/TooltipEmitter.d.ts.map +1 -0
  83. package/lib/typescript/src/components/TooltipPoll.d.ts +27 -0
  84. package/lib/typescript/src/components/TooltipPoll.d.ts.map +1 -0
  85. package/lib/typescript/src/components/TooltipPollContainer.d.ts +7 -0
  86. package/lib/typescript/src/components/TooltipPollContainer.d.ts.map +1 -0
  87. package/lib/typescript/src/components/TooltipPollManager.d.ts +2 -0
  88. package/lib/typescript/src/components/TooltipPollManager.d.ts.map +1 -0
  89. package/lib/typescript/src/events/custom/CustomEvents.d.ts +11 -0
  90. package/lib/typescript/src/events/custom/CustomEvents.d.ts.map +1 -0
  91. package/lib/typescript/src/events/default/DefaultEvents.d.ts +3 -0
  92. package/lib/typescript/src/events/default/DefaultEvents.d.ts.map +1 -0
  93. package/lib/typescript/src/firebase/Fb.d.ts +18 -0
  94. package/lib/typescript/src/firebase/Fb.d.ts.map +1 -0
  95. package/lib/typescript/src/firebase/IosAPNS.d.ts +6 -0
  96. package/lib/typescript/src/firebase/IosAPNS.d.ts.map +1 -0
  97. package/lib/typescript/src/index.d.ts +12 -21
  98. package/lib/typescript/src/index.d.ts.map +1 -1
  99. package/lib/typescript/src/native/LiveActivity.d.ts +2 -0
  100. package/lib/typescript/src/native/LiveActivity.d.ts.map +1 -0
  101. package/lib/typescript/src/native/MeheryEventSenderView.d.ts +8 -0
  102. package/lib/typescript/src/native/MeheryEventSenderView.d.ts.map +1 -0
  103. package/lib/typescript/src/socket/SocketManager.d.ts +13 -0
  104. package/lib/typescript/src/socket/SocketManager.d.ts.map +1 -0
  105. package/lib/typescript/src/socket/WebSock.d.ts +4 -0
  106. package/lib/typescript/src/socket/WebSock.d.ts.map +1 -0
  107. package/lib/typescript/src/utils/device.d.ts +2 -0
  108. package/lib/typescript/src/utils/device.d.ts.map +1 -0
  109. package/lib/typescript/src/utils/user.d.ts +9 -0
  110. package/lib/typescript/src/utils/user.d.ts.map +1 -0
  111. package/package.json +15 -3
  112. package/src/components/BannerPoll.tsx +67 -0
  113. package/src/components/BannerScreen.tsx +49 -0
  114. package/src/components/BottomSheetPoll.tsx +182 -0
  115. package/src/components/CustomBanner.tsx +48 -0
  116. package/src/components/FloaterPoll.tsx +116 -0
  117. package/src/components/PipPoll.tsx +166 -0
  118. package/src/components/PollOverlay.tsx +187 -0
  119. package/src/components/RenderInlinePoll.tsx +229 -0
  120. package/src/components/RoadblockPoll.tsx +133 -0
  121. package/src/components/TooltipEmitter.ts +12 -0
  122. package/src/components/TooltipPoll.tsx +127 -0
  123. package/src/components/TooltipPollContainer.tsx +105 -0
  124. package/src/components/TooltipPollManager.tsx +6 -0
  125. package/src/events/custom/CustomEvents.tsx +260 -0
  126. package/src/events/default/DefaultEvents.ts +52 -0
  127. package/src/firebase/Fb.ts +178 -0
  128. package/src/firebase/IosAPNS.ts +136 -0
  129. package/src/index.tsx +186 -128
  130. package/src/native/LiveActivity.ts +20 -0
  131. package/src/native/MeheryEventSenderView.ts +22 -0
  132. package/src/socket/SocketManager.ts +92 -0
  133. package/src/socket/WebSock.ts +71 -0
  134. package/src/types/react-native-push-notification.d.ts +4 -0
  135. package/src/utils/device.ts +31 -0
  136. 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 for event tracking that works with both Expo Go and bare React Native applications
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
- ## Usage
11
+ ## 🚀 Initialization
12
12
 
13
+ Initialize the SDK in your App.tsx
13
14
 
14
15
  ```js
15
- import { MeheryEventSenderView } from "react-native-mehery-event-sender";
16
+ import { initSdk } from 'react-native-mehery-event-sender';
16
17
 
17
18
  // ...
18
19
 
19
- <MeheryEventSenderView color="tomato" />
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
- ## Contributing
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
- See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
56
+ ## 🔔 Notification Handling
26
57
 
27
- ## License
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
@@ -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=34
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
- package="com.meheryeventsender">
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
- return emptyList()
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
+
@@ -0,0 +1,5 @@
1
+
2
+ <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
3
+ <solid android:color="#333333" />
4
+ <corners android:radius="8dp" />
5
+ </shape>