react-native-mytatva-rn-sdk 1.2.97 → 1.2.99
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/android/src/main/java/com/mytatvarnsdk/CgmTrackyLibModule.kt +25 -0
- package/android/src/main/java/com/mytatvarnsdk/activity/ConnectSensorActivity.kt +164 -18
- package/android/src/main/java/com/mytatvarnsdk/activity/HelpActivity.kt +3 -9
- package/android/src/main/java/com/mytatvarnsdk/activity/PermissionActivity.kt +8 -16
- package/android/src/main/java/com/mytatvarnsdk/activity/PlaceSensorActivity.kt +12 -13
- package/android/src/main/java/com/mytatvarnsdk/activity/PlaceTransmitterActivity.kt +12 -13
- package/android/src/main/java/com/mytatvarnsdk/activity/SearchTransmitterActivity.kt +9 -14
- package/android/src/main/java/com/mytatvarnsdk/activity/SensorConnectSuccessActivity.kt +12 -16
- package/android/src/main/java/com/mytatvarnsdk/activity/StartCGMActivity.kt +9 -15
- package/android/src/main/java/com/mytatvarnsdk/activity/VideoActivity.kt +96 -50
- package/android/src/main/java/com/mytatvarnsdk/network/AuthenticateSDKService.kt +50 -0
- package/android/src/main/java/com/mytatvarnsdk/utils/CustomerSupportConfig.kt +137 -0
- package/android/src/main/java/com/mytatvarnsdk/utils/ToolbarSupportHelper.kt +83 -0
- package/android/src/main/res/layout/activity_connect_sensor.xml +117 -2
- package/ios/Custom/CustomTopUIView.swift +25 -0
- package/ios/Database/KLTBluetoothManager.m +69 -14
- package/ios/MyReactNativeBridge.m +4 -0
- package/ios/Support/API.swift +117 -18
- package/ios/Support/CustomTopViewSupportHelper.swift +55 -0
- package/ios/Support/CustomerSupportConfig.swift +169 -0
- package/ios/Support/Global.swift +2 -2
- package/ios/Support/GlobalYouTubePlayerView.swift +102 -11
- package/ios/TableViewCell/ImageTVC/ImageTVC.swift +147 -15
- package/ios/ViewControllers/AttachTransmitterViewController.swift +16 -21
- package/ios/ViewControllers/ChatWithExpertViewController.swift +1 -7
- package/ios/ViewControllers/ConnectToSensorViewController.swift +213 -34
- package/ios/ViewControllers/ConnectToTransmitterViewController.swift +16 -21
- package/ios/ViewControllers/ProvidePermissionViewController.swift +16 -21
- package/ios/ViewControllers/PutOnTheSensorViewController.swift +16 -21
- package/ios/ViewControllers/StartConnectionViewController.swift +18 -25
- package/ios/ViewModel/FinalViewModel.swift +2 -2
- package/package.json +1 -1
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
package com.mytatvarnsdk.activity
|
|
2
2
|
|
|
3
|
+
import android.annotation.SuppressLint
|
|
3
4
|
import android.os.Bundle
|
|
4
5
|
import android.view.View
|
|
6
|
+
import android.webkit.WebChromeClient
|
|
7
|
+
import android.webkit.WebView
|
|
8
|
+
import android.webkit.WebViewClient
|
|
5
9
|
import androidx.activity.OnBackPressedCallback
|
|
6
10
|
import androidx.activity.enableEdgeToEdge
|
|
7
11
|
import androidx.appcompat.app.AppCompatActivity
|
|
12
|
+
import androidx.constraintlayout.widget.ConstraintLayout
|
|
8
13
|
import androidx.core.view.ViewCompat
|
|
9
14
|
import androidx.core.view.WindowInsetsCompat
|
|
10
15
|
import com.mytatvarnsdk.R
|
|
11
16
|
import com.mytatvarnsdk.databinding.ActivityVideoBinding
|
|
12
|
-
import com.
|
|
13
|
-
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.AbstractYouTubePlayerListener
|
|
14
|
-
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.listeners.FullscreenListener
|
|
15
|
-
import com.pierfrancescosoffritti.androidyoutubeplayer.core.player.options.IFramePlayerOptions
|
|
17
|
+
import com.mytatvarnsdk.utils.CustomerSupportConfig
|
|
16
18
|
|
|
17
19
|
class VideoActivity : AppCompatActivity() {
|
|
18
20
|
private lateinit var binding: ActivityVideoBinding
|
|
19
|
-
private var
|
|
20
|
-
private lateinit var youTubePlayer: YouTubePlayer
|
|
21
|
+
private var webView: WebView? = null
|
|
21
22
|
private var videoId = ""
|
|
22
23
|
|
|
23
24
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
@@ -34,66 +35,111 @@ class VideoActivity : AppCompatActivity() {
|
|
|
34
35
|
init()
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
@SuppressLint("SetJavaScriptEnabled")
|
|
37
39
|
private fun init() {
|
|
38
|
-
videoId = intent.getStringExtra("VideoId")
|
|
40
|
+
videoId = resolveVideoId(intent.getStringExtra("VideoId"))
|
|
39
41
|
|
|
40
42
|
onBackPressedDispatcher.addCallback(onBackPressedCallback)
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
.fullscreen(1)
|
|
45
|
-
.build()
|
|
46
|
-
binding.youtubePlayerView.enableAutomaticInitialization = false
|
|
44
|
+
binding.youtubePlayerView.visibility = View.GONE
|
|
45
|
+
binding.fullScreenViewContainer.visibility = View.GONE
|
|
47
46
|
|
|
48
47
|
binding.ivClose.setOnClickListener {
|
|
49
|
-
|
|
48
|
+
finish()
|
|
50
49
|
}
|
|
51
50
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
51
|
+
val playerWebView = WebView(this)
|
|
52
|
+
webView = playerWebView
|
|
53
|
+
playerWebView.settings.apply {
|
|
54
|
+
javaScriptEnabled = true
|
|
55
|
+
domStorageEnabled = true
|
|
56
|
+
mediaPlaybackRequiresUserGesture = false
|
|
57
|
+
}
|
|
58
|
+
playerWebView.webViewClient = WebViewClient()
|
|
59
|
+
playerWebView.webChromeClient = WebChromeClient()
|
|
60
|
+
|
|
61
|
+
val layoutParams = ConstraintLayout.LayoutParams(
|
|
62
|
+
ConstraintLayout.LayoutParams.MATCH_PARENT,
|
|
63
|
+
ConstraintLayout.LayoutParams.MATCH_CONSTRAINT
|
|
64
|
+
).apply {
|
|
65
|
+
topToBottom = R.id.ivClose
|
|
66
|
+
bottomToBottom = R.id.main
|
|
67
|
+
startToStart = R.id.main
|
|
68
|
+
endToEnd = R.id.main
|
|
69
|
+
}
|
|
70
|
+
(binding.root as ConstraintLayout).addView(playerWebView, layoutParams)
|
|
71
|
+
binding.ivClose.bringToFront()
|
|
72
|
+
binding.ivClose.elevation = 12f
|
|
73
|
+
|
|
74
|
+
val html = buildYouTubeEmbedHtml(videoId)
|
|
75
|
+
// Base URL + referrer meta are required by YouTube (errors 152-4 / 153).
|
|
76
|
+
playerWebView.loadDataWithBaseURL(
|
|
77
|
+
EMBED_BASE_URL,
|
|
78
|
+
html,
|
|
79
|
+
"text/html",
|
|
80
|
+
"UTF-8",
|
|
81
|
+
null
|
|
82
|
+
)
|
|
83
|
+
}
|
|
79
84
|
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
private fun resolveVideoId(raw: String?): String {
|
|
86
|
+
val value = raw?.trim().orEmpty()
|
|
87
|
+
if (value.isEmpty() || value == "null") {
|
|
88
|
+
return CustomerSupportConfig.DEFAULT_DEMO_VIDEO_ID
|
|
89
|
+
}
|
|
90
|
+
return CustomerSupportConfig.extractYouTubeVideoId(value) ?: value
|
|
91
|
+
}
|
|
82
92
|
|
|
83
|
-
|
|
93
|
+
private fun buildYouTubeEmbedHtml(videoId: String): String {
|
|
94
|
+
return """
|
|
95
|
+
<!DOCTYPE html>
|
|
96
|
+
<html>
|
|
97
|
+
<head>
|
|
98
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
99
|
+
<meta name="referrer" content="strict-origin-when-cross-origin">
|
|
100
|
+
<style>
|
|
101
|
+
html, body { margin: 0; padding: 0; background: #000; height: 100%; }
|
|
102
|
+
.video-container { position: relative; width: 100%; height: 100%; }
|
|
103
|
+
iframe {
|
|
104
|
+
position: absolute;
|
|
105
|
+
top: 0;
|
|
106
|
+
left: 0;
|
|
107
|
+
width: 100%;
|
|
108
|
+
height: 100%;
|
|
109
|
+
border: 0;
|
|
110
|
+
}
|
|
111
|
+
</style>
|
|
112
|
+
</head>
|
|
113
|
+
<body>
|
|
114
|
+
<div class="video-container">
|
|
115
|
+
<iframe
|
|
116
|
+
src="https://www.youtube-nocookie.com/embed/$videoId?playsinline=1&rel=0&modestbranding=1"
|
|
117
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
118
|
+
allowfullscreen
|
|
119
|
+
referrerpolicy="strict-origin-when-cross-origin">
|
|
120
|
+
</iframe>
|
|
121
|
+
</div>
|
|
122
|
+
</body>
|
|
123
|
+
</html>
|
|
124
|
+
""".trimIndent()
|
|
84
125
|
}
|
|
85
126
|
|
|
86
127
|
private val onBackPressedCallback = object : OnBackPressedCallback(true) {
|
|
87
128
|
override fun handleOnBackPressed() {
|
|
88
|
-
|
|
129
|
+
finish()
|
|
89
130
|
}
|
|
90
131
|
}
|
|
91
132
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
finish()
|
|
133
|
+
override fun onDestroy() {
|
|
134
|
+
webView?.apply {
|
|
135
|
+
stopLoading()
|
|
136
|
+
destroy()
|
|
97
137
|
}
|
|
138
|
+
webView = null
|
|
139
|
+
super.onDestroy()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
companion object {
|
|
143
|
+
private const val EMBED_BASE_URL = "https://www.mytatva.in/"
|
|
98
144
|
}
|
|
99
|
-
}
|
|
145
|
+
}
|
|
@@ -260,6 +260,56 @@ class AuthenticateSDKService(val scope: CoroutineScope) {
|
|
|
260
260
|
}
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
+
fun fetchCustomerSupportDetails(
|
|
264
|
+
environment: TATVA_ENVIRONMENT,
|
|
265
|
+
token: String,
|
|
266
|
+
onSuccess: (String) -> Unit = {},
|
|
267
|
+
onFailure: () -> Unit = {}
|
|
268
|
+
) {
|
|
269
|
+
scope.launch {
|
|
270
|
+
try {
|
|
271
|
+
val apiServiceInterface = RetrofitInstance.getRetroInstance().create(
|
|
272
|
+
ApiServiceInterface::class.java
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
val encryptionKey = getEncryptionKey(
|
|
276
|
+
env = TATVA_ENVIRONMENT.PROD,
|
|
277
|
+
prodEncKey = PROD_ENC_KEY,
|
|
278
|
+
stagEncKey = STAGE_ENC_KEY
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
val encryptionIv = getEncryptionIv(
|
|
282
|
+
env = TATVA_ENVIRONMENT.PROD, prodEncIv = PROD_ENC_IV, stagEncIv = STAGE_ENC_IV
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
val headers = mapOf(
|
|
286
|
+
"api-key" to if (environment == TATVA_ENVIRONMENT.PROD) PROD_API_KEY else STAGE_API_KEY,
|
|
287
|
+
"token" to token
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
val baseUrl = if (environment == TATVA_ENVIRONMENT.PROD) PROD_BASE_URL else STAGE_BASE_URL
|
|
291
|
+
val url = "$baseUrl/helper/customer_support_details"
|
|
292
|
+
|
|
293
|
+
Log.d("API Response", "Customer Support Details URL: $url")
|
|
294
|
+
|
|
295
|
+
val response = apiServiceInterface.getCgmStatus(url, headers).string()
|
|
296
|
+
|
|
297
|
+
val decryptedResponse = getDecryptedData(
|
|
298
|
+
cipherText = response.toString(),
|
|
299
|
+
encryptionKey = encryptionKey,
|
|
300
|
+
encryptionIv = encryptionIv
|
|
301
|
+
) ?: response.toString()
|
|
302
|
+
|
|
303
|
+
Log.d("API Response", "Customer Support Details Response: $decryptedResponse")
|
|
304
|
+
onSuccess(decryptedResponse)
|
|
305
|
+
} catch (e: Exception) {
|
|
306
|
+
Log.d("API Response", "Customer Support Details Exception: ${e.message}")
|
|
307
|
+
e.printStackTrace()
|
|
308
|
+
onFailure()
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
263
313
|
fun verifyDevice(
|
|
264
314
|
environment: TATVA_ENVIRONMENT,
|
|
265
315
|
token: String,
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
package com.mytatvarnsdk.utils
|
|
2
|
+
|
|
3
|
+
import android.os.Handler
|
|
4
|
+
import android.os.Looper
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import org.json.JSONObject
|
|
7
|
+
import java.util.concurrent.CopyOnWriteArraySet
|
|
8
|
+
|
|
9
|
+
object CustomerSupportConfig {
|
|
10
|
+
private const val TAG = "CustomerSupportConfig"
|
|
11
|
+
|
|
12
|
+
const val DEFAULT_WHATSAPP_NUMBER = "918511975757"
|
|
13
|
+
const val DEFAULT_DEMO_VIDEO_ID = "65vl2aE1K_I"
|
|
14
|
+
const val DEFAULT_DEMO_VIDEO_URL =
|
|
15
|
+
"https://www.youtube.com/embed/65vl2aE1K_I"
|
|
16
|
+
|
|
17
|
+
private val mainHandler = Handler(Looper.getMainLooper())
|
|
18
|
+
private val updateListeners = CopyOnWriteArraySet<() -> Unit>()
|
|
19
|
+
|
|
20
|
+
@Volatile
|
|
21
|
+
var isLoaded: Boolean = false
|
|
22
|
+
|
|
23
|
+
@Volatile
|
|
24
|
+
var isShowWhatsapp: Boolean = false
|
|
25
|
+
|
|
26
|
+
@Volatile
|
|
27
|
+
var whatsAppNumber: String = DEFAULT_WHATSAPP_NUMBER
|
|
28
|
+
|
|
29
|
+
@Volatile
|
|
30
|
+
var watchCGMDemoUrl: String = DEFAULT_DEMO_VIDEO_URL
|
|
31
|
+
|
|
32
|
+
fun addUpdateListener(listener: () -> Unit) {
|
|
33
|
+
updateListeners.add(listener)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fun removeUpdateListener(listener: () -> Unit) {
|
|
37
|
+
updateListeners.remove(listener)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fun applyFailureDefaults() {
|
|
41
|
+
isShowWhatsapp = true
|
|
42
|
+
whatsAppNumber = DEFAULT_WHATSAPP_NUMBER
|
|
43
|
+
watchCGMDemoUrl = DEFAULT_DEMO_VIDEO_URL
|
|
44
|
+
isLoaded = true
|
|
45
|
+
Log.d(
|
|
46
|
+
TAG,
|
|
47
|
+
"Failure defaults applied | showWhatsapp=$isShowWhatsapp | demoUrl=$watchCGMDemoUrl"
|
|
48
|
+
)
|
|
49
|
+
notifyConfigUpdated()
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fun updateFromResponse(response: String) {
|
|
53
|
+
try {
|
|
54
|
+
val json = JSONObject(response)
|
|
55
|
+
if (json.optInt("code", 0) != 1) {
|
|
56
|
+
Log.w(TAG, "Customer support API returned non-success code, using failure defaults")
|
|
57
|
+
applyFailureDefaults()
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
val data = json.optJSONObject("data")
|
|
62
|
+
if (data == null) {
|
|
63
|
+
Log.w(TAG, "Customer support API missing data, using failure defaults")
|
|
64
|
+
applyFailureDefaults()
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
isShowWhatsapp = parseBoolean(data, "isShowWhatsapp")
|
|
69
|
+
whatsAppNumber = data.optString("whatsAppNumber", "").trim()
|
|
70
|
+
.ifEmpty { DEFAULT_WHATSAPP_NUMBER }
|
|
71
|
+
watchCGMDemoUrl = data.optString("watchCGMDemoUrl", "").trim()
|
|
72
|
+
.ifEmpty { DEFAULT_DEMO_VIDEO_URL }
|
|
73
|
+
isLoaded = true
|
|
74
|
+
|
|
75
|
+
Log.d(
|
|
76
|
+
TAG,
|
|
77
|
+
"Customer support loaded | showWhatsapp=$isShowWhatsapp | demoUrl=$watchCGMDemoUrl"
|
|
78
|
+
)
|
|
79
|
+
notifyConfigUpdated()
|
|
80
|
+
} catch (e: Exception) {
|
|
81
|
+
Log.w(TAG, "Failed to parse customer support response: ${e.message}, using failure defaults")
|
|
82
|
+
applyFailureDefaults()
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private fun notifyConfigUpdated() {
|
|
87
|
+
mainHandler.post {
|
|
88
|
+
updateListeners.forEach { listener ->
|
|
89
|
+
try {
|
|
90
|
+
listener.invoke()
|
|
91
|
+
} catch (e: Exception) {
|
|
92
|
+
Log.w(TAG, "Customer support listener failed: ${e.message}")
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
fun effectiveWhatsAppNumber(): String =
|
|
99
|
+
whatsAppNumber.ifEmpty { DEFAULT_WHATSAPP_NUMBER }
|
|
100
|
+
|
|
101
|
+
fun shouldShowWhatsapp(): Boolean =
|
|
102
|
+
isLoaded && isShowWhatsapp && effectiveWhatsAppNumber().isNotEmpty()
|
|
103
|
+
|
|
104
|
+
fun getDemoVideoId(isForReconnect: Boolean): String {
|
|
105
|
+
val url = watchCGMDemoUrl.ifEmpty { DEFAULT_DEMO_VIDEO_URL }
|
|
106
|
+
extractYouTubeVideoId(url)?.let { return it }
|
|
107
|
+
return DEFAULT_DEMO_VIDEO_ID
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fun getDemoVideoUrl(isForReconnect: Boolean): String =
|
|
111
|
+
watchCGMDemoUrl.ifEmpty { DEFAULT_DEMO_VIDEO_URL }
|
|
112
|
+
|
|
113
|
+
fun extractYouTubeVideoId(url: String): String? {
|
|
114
|
+
val trimmed = url.trim()
|
|
115
|
+
if (trimmed.isEmpty()) return null
|
|
116
|
+
|
|
117
|
+
val patterns = listOf(
|
|
118
|
+
Regex("(?:embed/|/v/|watch\\?v=|youtu\\.be/)([\\w-]{11})"),
|
|
119
|
+
Regex("^([\\w-]{11})$")
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
for (pattern in patterns) {
|
|
123
|
+
pattern.find(trimmed)?.groupValues?.getOrNull(1)?.let { return it }
|
|
124
|
+
}
|
|
125
|
+
return null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private fun parseBoolean(json: JSONObject, key: String): Boolean {
|
|
129
|
+
if (!json.has(key)) return false
|
|
130
|
+
return when (val value = json.get(key)) {
|
|
131
|
+
is Boolean -> value
|
|
132
|
+
is Int -> value == 1
|
|
133
|
+
is String -> value.equals("true", ignoreCase = true) || value == "1"
|
|
134
|
+
else -> false
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
package com.mytatvarnsdk.utils
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.net.Uri
|
|
6
|
+
import android.view.View
|
|
7
|
+
import android.widget.Toast
|
|
8
|
+
import androidx.appcompat.app.AppCompatActivity
|
|
9
|
+
import androidx.lifecycle.DefaultLifecycleObserver
|
|
10
|
+
import androidx.lifecycle.LifecycleOwner
|
|
11
|
+
import com.mytatvarnsdk.activity.VideoActivity
|
|
12
|
+
|
|
13
|
+
object ToolbarSupportHelper {
|
|
14
|
+
|
|
15
|
+
fun configureWhatsappButton(
|
|
16
|
+
context: Context,
|
|
17
|
+
btnWhatsapp: View,
|
|
18
|
+
onClickAnalytics: (() -> Unit)? = null
|
|
19
|
+
) {
|
|
20
|
+
if (CustomerSupportConfig.shouldShowWhatsapp()) {
|
|
21
|
+
btnWhatsapp.visibility = View.VISIBLE
|
|
22
|
+
btnWhatsapp.setOnClickListener {
|
|
23
|
+
onClickAnalytics?.invoke()
|
|
24
|
+
openWhatsApp(context, CustomerSupportConfig.effectiveWhatsAppNumber())
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
btnWhatsapp.visibility = View.GONE
|
|
28
|
+
btnWhatsapp.setOnClickListener(null)
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fun bindWhatsappButton(
|
|
33
|
+
activity: AppCompatActivity,
|
|
34
|
+
btnWhatsapp: View,
|
|
35
|
+
onClickAnalytics: (() -> Unit)? = null
|
|
36
|
+
) {
|
|
37
|
+
btnWhatsapp.setOnClickListener(null)
|
|
38
|
+
val refresh: () -> Unit = {
|
|
39
|
+
configureWhatsappButton(activity, btnWhatsapp, onClickAnalytics)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
refresh()
|
|
43
|
+
CustomerSupportConfig.addUpdateListener(refresh)
|
|
44
|
+
|
|
45
|
+
activity.lifecycle.addObserver(object : DefaultLifecycleObserver {
|
|
46
|
+
override fun onDestroy(owner: LifecycleOwner) {
|
|
47
|
+
CustomerSupportConfig.removeUpdateListener(refresh)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fun configureWatchDemoButton(
|
|
53
|
+
context: Context,
|
|
54
|
+
btnWatchDemo: View,
|
|
55
|
+
isForReconnect: Boolean,
|
|
56
|
+
onClickAnalytics: (() -> Unit)? = null
|
|
57
|
+
) {
|
|
58
|
+
btnWatchDemo.setOnClickListener {
|
|
59
|
+
onClickAnalytics?.invoke()
|
|
60
|
+
val intent = Intent(context, VideoActivity::class.java)
|
|
61
|
+
val videoId = CustomerSupportConfig.getDemoVideoId(isForReconnect)
|
|
62
|
+
intent.putExtra("VideoId", videoId)
|
|
63
|
+
context.startActivity(intent)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fun openWhatsApp(context: Context, number: String) {
|
|
68
|
+
val cleanedNumber = number.replace(Regex("[^0-9]"), "")
|
|
69
|
+
if (cleanedNumber.isEmpty()) {
|
|
70
|
+
Toast.makeText(context, "WhatsApp number unavailable", Toast.LENGTH_SHORT).show()
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
val waUri = Uri.parse("https://wa.me/$cleanedNumber")
|
|
75
|
+
val intent = Intent(Intent.ACTION_VIEW, waUri)
|
|
76
|
+
try {
|
|
77
|
+
context.startActivity(intent)
|
|
78
|
+
} catch (e: Exception) {
|
|
79
|
+
e.printStackTrace()
|
|
80
|
+
Toast.makeText(context, "Error opening WhatsApp", Toast.LENGTH_SHORT).show()
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -246,7 +246,11 @@
|
|
|
246
246
|
app:layout_constraintStart_toStartOf="parent"
|
|
247
247
|
app:layout_constraintTop_toBottomOf="@id/transmitterImages">
|
|
248
248
|
|
|
249
|
-
|
|
249
|
+
<LinearLayout
|
|
250
|
+
android:layout_width="match_parent"
|
|
251
|
+
android:layout_height="wrap_content"
|
|
252
|
+
android:orientation="vertical">
|
|
253
|
+
|
|
250
254
|
<androidx.constraintlayout.widget.ConstraintLayout
|
|
251
255
|
android:id="@+id/clPermission"
|
|
252
256
|
android:layout_width="match_parent"
|
|
@@ -289,7 +293,6 @@
|
|
|
289
293
|
app:layout_constraintTop_toBottomOf="@+id/tvDesc"
|
|
290
294
|
app:layout_constraintVertical_chainStyle="packed" />
|
|
291
295
|
|
|
292
|
-
|
|
293
296
|
<androidx.appcompat.widget.AppCompatImageView
|
|
294
297
|
android:id="@+id/ivProceedArrow"
|
|
295
298
|
android:layout_width="18dp"
|
|
@@ -303,9 +306,121 @@
|
|
|
303
306
|
app:layout_constraintTop_toTopOf="@+id/tvPermission"
|
|
304
307
|
app:tint="@color/color_green" />
|
|
305
308
|
|
|
309
|
+
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
310
|
+
|
|
311
|
+
<androidx.constraintlayout.widget.ConstraintLayout
|
|
312
|
+
android:id="@+id/clManualInput"
|
|
313
|
+
android:layout_width="match_parent"
|
|
314
|
+
android:layout_height="wrap_content"
|
|
315
|
+
android:layout_marginTop="12dp"
|
|
316
|
+
android:background="@drawable/bg_dark_black"
|
|
317
|
+
android:paddingHorizontal="20dp"
|
|
318
|
+
android:paddingVertical="20dp"
|
|
319
|
+
android:visibility="gone">
|
|
320
|
+
|
|
321
|
+
<EditText
|
|
322
|
+
android:id="@+id/etSensorId"
|
|
323
|
+
android:layout_width="0dp"
|
|
324
|
+
android:layout_height="52dp"
|
|
325
|
+
android:background="@drawable/bg_white_corner_10"
|
|
326
|
+
android:fontFamily="@font/roboto_regular"
|
|
327
|
+
android:hint="Enter Sensor ID"
|
|
328
|
+
android:importantForAutofill="no"
|
|
329
|
+
android:inputType="textCapCharacters"
|
|
330
|
+
android:paddingHorizontal="14dp"
|
|
331
|
+
android:textColor="#101828"
|
|
332
|
+
android:textColorHint="#98A2B3"
|
|
333
|
+
android:textSize="14sp"
|
|
334
|
+
app:layout_constraintEnd_toEndOf="parent"
|
|
335
|
+
app:layout_constraintStart_toStartOf="parent"
|
|
336
|
+
app:layout_constraintTop_toTopOf="parent" />
|
|
337
|
+
|
|
338
|
+
<androidx.cardview.widget.CardView
|
|
339
|
+
android:id="@+id/btnConnectManual"
|
|
340
|
+
android:layout_width="0dp"
|
|
341
|
+
android:layout_height="54dp"
|
|
342
|
+
android:layout_marginTop="12dp"
|
|
343
|
+
app:cardBackgroundColor="#2A805A"
|
|
344
|
+
app:cardCornerRadius="12dp"
|
|
345
|
+
app:cardElevation="0dp"
|
|
346
|
+
app:layout_constraintEnd_toEndOf="parent"
|
|
347
|
+
app:layout_constraintStart_toStartOf="parent"
|
|
348
|
+
app:layout_constraintTop_toBottomOf="@+id/etSensorId">
|
|
349
|
+
|
|
350
|
+
<androidx.constraintlayout.widget.ConstraintLayout
|
|
351
|
+
android:layout_width="match_parent"
|
|
352
|
+
android:layout_height="match_parent"
|
|
353
|
+
android:background="@drawable/bg_green_border_20">
|
|
354
|
+
|
|
355
|
+
<TextView
|
|
356
|
+
android:id="@+id/tvConnectManual"
|
|
357
|
+
android:layout_width="wrap_content"
|
|
358
|
+
android:layout_height="wrap_content"
|
|
359
|
+
android:fontFamily="@font/roboto_semibold"
|
|
360
|
+
android:text="Connect"
|
|
361
|
+
android:textColor="#FFFFFF"
|
|
362
|
+
android:textSize="16sp"
|
|
363
|
+
app:layout_constraintBottom_toBottomOf="parent"
|
|
364
|
+
app:layout_constraintEnd_toEndOf="parent"
|
|
365
|
+
app:layout_constraintStart_toStartOf="parent"
|
|
366
|
+
app:layout_constraintTop_toTopOf="parent" />
|
|
367
|
+
|
|
368
|
+
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
369
|
+
|
|
370
|
+
</androidx.cardview.widget.CardView>
|
|
371
|
+
|
|
372
|
+
<TextView
|
|
373
|
+
android:id="@+id/tvManualEntryHint"
|
|
374
|
+
android:layout_width="0dp"
|
|
375
|
+
android:layout_height="wrap_content"
|
|
376
|
+
android:layout_marginTop="10dp"
|
|
377
|
+
android:fontFamily="@font/roboto_regular"
|
|
378
|
+
android:gravity="center"
|
|
379
|
+
android:text="Scan the QR with mobile camera to get a sensor ID."
|
|
380
|
+
android:textAlignment="center"
|
|
381
|
+
android:textColor="#98A2B3"
|
|
382
|
+
android:textSize="12sp"
|
|
383
|
+
app:layout_constraintBottom_toBottomOf="parent"
|
|
384
|
+
app:layout_constraintEnd_toEndOf="parent"
|
|
385
|
+
app:layout_constraintStart_toStartOf="parent"
|
|
386
|
+
app:layout_constraintTop_toBottomOf="@+id/btnConnectManual" />
|
|
306
387
|
|
|
307
388
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
308
389
|
|
|
390
|
+
<LinearLayout
|
|
391
|
+
android:id="@+id/clManualEntry"
|
|
392
|
+
android:layout_width="match_parent"
|
|
393
|
+
android:layout_height="wrap_content"
|
|
394
|
+
android:layout_marginTop="12dp"
|
|
395
|
+
android:background="@drawable/bg_manual_entry_bar"
|
|
396
|
+
android:gravity="center"
|
|
397
|
+
android:orientation="horizontal"
|
|
398
|
+
android:paddingHorizontal="16dp"
|
|
399
|
+
android:paddingVertical="14dp">
|
|
400
|
+
|
|
401
|
+
<TextView
|
|
402
|
+
android:id="@+id/tvCantScanQr"
|
|
403
|
+
android:layout_width="wrap_content"
|
|
404
|
+
android:layout_height="wrap_content"
|
|
405
|
+
android:fontFamily="@font/roboto_regular"
|
|
406
|
+
android:text="@string/txt_cant_scan_sensor_qr"
|
|
407
|
+
android:textColor="#2D3282"
|
|
408
|
+
android:textSize="14sp" />
|
|
409
|
+
|
|
410
|
+
<TextView
|
|
411
|
+
android:id="@+id/tvEnterIdManually"
|
|
412
|
+
android:layout_width="wrap_content"
|
|
413
|
+
android:layout_height="wrap_content"
|
|
414
|
+
android:layout_marginStart="4dp"
|
|
415
|
+
android:fontFamily="@font/roboto_bold"
|
|
416
|
+
android:text="@string/txt_enter_id_manually"
|
|
417
|
+
android:textColor="@color/color_green"
|
|
418
|
+
android:textSize="14sp" />
|
|
419
|
+
|
|
420
|
+
</LinearLayout>
|
|
421
|
+
|
|
422
|
+
</LinearLayout>
|
|
423
|
+
|
|
309
424
|
</FrameLayout>
|
|
310
425
|
|
|
311
426
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@@ -48,6 +48,8 @@ class CustomTopUIView: UIView {
|
|
|
48
48
|
var onWhatsAppTapped: (() -> Void)?
|
|
49
49
|
var onCloseTapped: (() -> Void)?
|
|
50
50
|
|
|
51
|
+
private var customerSupportConfigObserver: NSObjectProtocol?
|
|
52
|
+
|
|
51
53
|
|
|
52
54
|
// For Interface Builder
|
|
53
55
|
override init(frame: CGRect) {
|
|
@@ -124,6 +126,21 @@ class CustomTopUIView: UIView {
|
|
|
124
126
|
whatsappButton.addTarget(self, action: #selector(whatsappButtonTapped), for: .touchUpInside)
|
|
125
127
|
closeButton.addTarget(self, action: #selector(closeButtonTapped), for: .touchUpInside)
|
|
126
128
|
|
|
129
|
+
customerSupportConfigObserver = NotificationCenter.default.addObserver(
|
|
130
|
+
forName: .customerSupportConfigDidUpdate,
|
|
131
|
+
object: nil,
|
|
132
|
+
queue: .main
|
|
133
|
+
) { [weak self] _ in
|
|
134
|
+
self?.refreshWhatsappVisibility()
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
refreshWhatsappVisibility()
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
deinit {
|
|
142
|
+
if let customerSupportConfigObserver {
|
|
143
|
+
NotificationCenter.default.removeObserver(customerSupportConfigObserver)
|
|
127
144
|
}
|
|
128
145
|
}
|
|
129
146
|
|
|
@@ -131,6 +148,14 @@ class CustomTopUIView: UIView {
|
|
|
131
148
|
demoButton.isHidden = true
|
|
132
149
|
whatsappButton.isHidden = true
|
|
133
150
|
}
|
|
151
|
+
|
|
152
|
+
func setWhatsappVisible(_ isVisible: Bool) {
|
|
153
|
+
whatsappButton.isHidden = !isVisible
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
func refreshWhatsappVisibility() {
|
|
157
|
+
setWhatsappVisible(CustomerSupportConfig.shared.shouldShowWhatsapp())
|
|
158
|
+
}
|
|
134
159
|
|
|
135
160
|
@objc private func demoButtonTapped() {
|
|
136
161
|
onDemoTapped?()
|