From d89d1b5049b23535fcb4f26585132581dbab34d0 Mon Sep 17 00:00:00 2001 From: Subhadip Mondal <159517480+subhadipverloop@users.noreply.github.com> Date: Tue, 12 May 2026 19:51:32 +0530 Subject: [PATCH 1/3] onRoomReady/onChatStarted callback support Handling onChatStarted/onRoomReady Functionlity of livechat v2 android methods - setChatStartedListener setRoomReadyListner --- app/src/main/java/io/verloop/TestActivity.kt | 18 +++++++++++-- .../verloop/sdk/LiveChatRoomReadyListner.kt | 5 ++++ .../io/verloop/sdk/LiveChatStartedListener.kt | 5 ++++ sdk/src/main/java/io/verloop/sdk/Verloop.kt | 8 ++++++ .../main/java/io/verloop/sdk/VerloopConfig.kt | 21 ++++++++++++++++ .../java/io/verloop/sdk/ui/VerloopFragment.kt | 25 +++++++++++++++++++ .../io/verloop/sdk/viewmodel/MainViewModel.kt | 8 ++++++ 7 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 sdk/src/main/java/io/verloop/sdk/LiveChatRoomReadyListner.kt create mode 100644 sdk/src/main/java/io/verloop/sdk/LiveChatStartedListener.kt diff --git a/app/src/main/java/io/verloop/TestActivity.kt b/app/src/main/java/io/verloop/TestActivity.kt index 0d00ca5..4a00332 100644 --- a/app/src/main/java/io/verloop/TestActivity.kt +++ b/app/src/main/java/io/verloop/TestActivity.kt @@ -24,6 +24,16 @@ class TestActivity : AppCompatActivity() { var verloop: Verloop? = null var verloop2: Verloop? = null + + private val chatStarted: () -> Unit = { + Log.i(TAG, "Chat Started") + Toast.makeText(applicationContext, "Chat Started", Toast.LENGTH_SHORT).show() + } + + private val roomReady: () -> Unit = { + Log.i(TAG, "Room Ready") + Toast.makeText(applicationContext, "Room Ready", Toast.LENGTH_SHORT).show() + } var headerConfig: HeaderConfig? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -149,7 +159,7 @@ class TestActivity : AppCompatActivity() { .closeExistingChat(checkCloseExistingChat.isChecked) .openMenuWidgetOnStart(openMenuWidgetOnStart.isChecked) .overrideHeaderLayout(false) - .allowFileDownload(true) + .allowFileDownload(false) .headerConfig(headerConfig) .fields(customFields).build() @@ -171,6 +181,7 @@ class TestActivity : AppCompatActivity() { verloopConfig?.setButtonClickListener(object : LiveChatButtonClickListener { override fun buttonClicked(title: String?, type: String?, payload: String?) { if (type == "web_url"){ + Log.d("URL",payload.toString()) try { val jsonPayload = JSONObject(payload) val url = jsonPayload.optString("url") @@ -190,6 +201,8 @@ class TestActivity : AppCompatActivity() { } } }) + verloopConfig?.setChatStartedListener(chatStarted) + verloopConfig?.setRoomReadyListner(roomReady) verloop = Verloop(this, verloopConfig!!) verloop?.showChat() } catch (e: VerloopException) { @@ -273,4 +286,5 @@ class TestActivity : AppCompatActivity() { } } } -} \ No newline at end of file +} + diff --git a/sdk/src/main/java/io/verloop/sdk/LiveChatRoomReadyListner.kt b/sdk/src/main/java/io/verloop/sdk/LiveChatRoomReadyListner.kt new file mode 100644 index 0000000..1879bce --- /dev/null +++ b/sdk/src/main/java/io/verloop/sdk/LiveChatRoomReadyListner.kt @@ -0,0 +1,5 @@ +package io.verloop.sdk + +fun interface LiveChatRoomReadyListner { + fun onRoomReady() +} \ No newline at end of file diff --git a/sdk/src/main/java/io/verloop/sdk/LiveChatStartedListener.kt b/sdk/src/main/java/io/verloop/sdk/LiveChatStartedListener.kt new file mode 100644 index 0000000..fd93d89 --- /dev/null +++ b/sdk/src/main/java/io/verloop/sdk/LiveChatStartedListener.kt @@ -0,0 +1,5 @@ +package io.verloop.sdk + +fun interface LiveChatStartedListener { + fun onChatStarted() +} \ No newline at end of file diff --git a/sdk/src/main/java/io/verloop/sdk/Verloop.kt b/sdk/src/main/java/io/verloop/sdk/Verloop.kt index dcbe3ee..bc1d7d9 100644 --- a/sdk/src/main/java/io/verloop/sdk/Verloop.kt +++ b/sdk/src/main/java/io/verloop/sdk/Verloop.kt @@ -167,5 +167,13 @@ class Verloop(val context: Context, var verloopConfig: VerloopConfig) { fun onLogEvent(logEvent: LogEvent) { config.logEventListener?.logEvent(logEvent) } + + fun onChatStarted() { + config.chatStartedListenerImpl?.onChatStarted() + } + + fun onRoomReady() { + config.roomReadyListenerImpl?.onRoomReady() + } } } \ No newline at end of file diff --git a/sdk/src/main/java/io/verloop/sdk/VerloopConfig.kt b/sdk/src/main/java/io/verloop/sdk/VerloopConfig.kt index 7fff503..bf91bfa 100644 --- a/sdk/src/main/java/io/verloop/sdk/VerloopConfig.kt +++ b/sdk/src/main/java/io/verloop/sdk/VerloopConfig.kt @@ -29,6 +29,11 @@ data class VerloopConfig private constructor( var logLevel: LogLevel = LogLevel.WARNING var buttonOnClickListener: LiveChatButtonClickListener? = null + + var chatStartedListenerImpl: LiveChatStartedListener? = null + + var roomReadyListenerImpl: LiveChatRoomReadyListner? = null + var chatUrlClickListener: LiveChatUrlClickListener? = null var logEventListener: LiveLogEventListener? = null @@ -75,6 +80,22 @@ data class VerloopConfig private constructor( this.buttonOnClickListener = buttonOnClickListener } + /** + * Callback for chat started + * @param chatStartedListener + */ + fun setChatStartedListener(listener: LiveChatStartedListener) { + this.chatStartedListenerImpl = listener // ← uses new name + } + + /** + * Callback for chat started + * @param roomReadyListenerImpl + */ + fun setRoomReadyListner(listener: LiveChatRoomReadyListner) { + this.roomReadyListenerImpl = listener // ← uses new name + } + /** * Callback for url click event from within the chat * @param urlClickListener diff --git a/sdk/src/main/java/io/verloop/sdk/ui/VerloopFragment.kt b/sdk/src/main/java/io/verloop/sdk/ui/VerloopFragment.kt index 64c6f25..d337833 100644 --- a/sdk/src/main/java/io/verloop/sdk/ui/VerloopFragment.kt +++ b/sdk/src/main/java/io/verloop/sdk/ui/VerloopFragment.kt @@ -543,6 +543,8 @@ class VerloopFragment : Fragment() { ready() } else if (params.getString("fn").equals("roomReady")) { roomReady() + }else if (params.getString("fn").equals("callback")) { + handleCallback(params.optJSONArray("args")) } } @@ -574,6 +576,29 @@ class VerloopFragment : Fragment() { } } + private fun handleCallback(args: org.json.JSONArray?) { + val eventName = args?.optString(0) ?: return + when (eventName) { + "chat-started" -> callChatStarted() + "room-ready" -> callRoomReady() + // room-ready, chat-ended, etc. — add later as needed + } + } + + private fun callChatStarted(){ + logEvent(LogLevel.INFO, "ChatStarted", null) + Handler(Looper.getMainLooper()).post { + viewModel?.chatStarted() + } + } + + private fun callRoomReady(){ + logEvent(LogLevel.INFO, "Room Ready", null) + Handler(Looper.getMainLooper()).post { + viewModel?.roomReady() + } + } + private fun logEvent(level: LogLevel, message: String, params: JSONObject?) { if (config?.logLevel?.ordinal!! >= level.ordinal) { viewModel?.logEvent(LogEvent(level.name, message, params)) diff --git a/sdk/src/main/java/io/verloop/sdk/viewmodel/MainViewModel.kt b/sdk/src/main/java/io/verloop/sdk/viewmodel/MainViewModel.kt index b9dedb5..1633105 100644 --- a/sdk/src/main/java/io/verloop/sdk/viewmodel/MainViewModel.kt +++ b/sdk/src/main/java/io/verloop/sdk/viewmodel/MainViewModel.kt @@ -28,6 +28,14 @@ class MainViewModel(var configKey: String?, var repository: VerloopRepository) : } } + fun chatStarted() { + Verloop.eventListeners[configKey]?.onChatStarted() + } + + fun roomReady() { + Verloop.eventListeners[configKey]?.onRoomReady() + } + fun urlClicked(json: String) { configKey.let { Verloop.eventListeners[configKey]?.onURLClick(json) From 6de5a0d49ab281e7d1d748377bf4f6dd91059086 Mon Sep 17 00:00:00 2001 From: Subhadip Mondal <159517480+subhadipverloop@users.noreply.github.com> Date: Wed, 13 May 2026 15:16:02 +0530 Subject: [PATCH 2/3] return roomId in callback --- app/src/main/java/io/verloop/TestActivity.kt | 8 ++++---- .../io/verloop/sdk/LiveChatRoomReadyListner.kt | 3 ++- .../java/io/verloop/sdk/LiveChatStartedListener.kt | 2 +- sdk/src/main/java/io/verloop/sdk/Verloop.kt | 8 ++++---- .../main/java/io/verloop/sdk/ui/VerloopFragment.kt | 14 ++++++++------ .../java/io/verloop/sdk/viewmodel/MainViewModel.kt | 8 ++++---- 6 files changed, 23 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/io/verloop/TestActivity.kt b/app/src/main/java/io/verloop/TestActivity.kt index 4a00332..787956c 100644 --- a/app/src/main/java/io/verloop/TestActivity.kt +++ b/app/src/main/java/io/verloop/TestActivity.kt @@ -25,13 +25,13 @@ class TestActivity : AppCompatActivity() { var verloop: Verloop? = null var verloop2: Verloop? = null - private val chatStarted: () -> Unit = { - Log.i(TAG, "Chat Started") + private val chatStarted: (String?) -> Unit = { roomId -> + Log.i(TAG, "Chat Started - roomId $roomId") Toast.makeText(applicationContext, "Chat Started", Toast.LENGTH_SHORT).show() } - private val roomReady: () -> Unit = { - Log.i(TAG, "Room Ready") + private val roomReady: (String?) -> Unit = { roomId -> + Log.i(TAG, "Room Ready - roomId $roomId") Toast.makeText(applicationContext, "Room Ready", Toast.LENGTH_SHORT).show() } var headerConfig: HeaderConfig? = null diff --git a/sdk/src/main/java/io/verloop/sdk/LiveChatRoomReadyListner.kt b/sdk/src/main/java/io/verloop/sdk/LiveChatRoomReadyListner.kt index 1879bce..d91f53f 100644 --- a/sdk/src/main/java/io/verloop/sdk/LiveChatRoomReadyListner.kt +++ b/sdk/src/main/java/io/verloop/sdk/LiveChatRoomReadyListner.kt @@ -1,5 +1,6 @@ package io.verloop.sdk + fun interface LiveChatRoomReadyListner { - fun onRoomReady() + fun onRoomReady(roomId: String?) } \ No newline at end of file diff --git a/sdk/src/main/java/io/verloop/sdk/LiveChatStartedListener.kt b/sdk/src/main/java/io/verloop/sdk/LiveChatStartedListener.kt index fd93d89..722a481 100644 --- a/sdk/src/main/java/io/verloop/sdk/LiveChatStartedListener.kt +++ b/sdk/src/main/java/io/verloop/sdk/LiveChatStartedListener.kt @@ -1,5 +1,5 @@ package io.verloop.sdk fun interface LiveChatStartedListener { - fun onChatStarted() + fun onChatStarted(roomId: String?) } \ No newline at end of file diff --git a/sdk/src/main/java/io/verloop/sdk/Verloop.kt b/sdk/src/main/java/io/verloop/sdk/Verloop.kt index bc1d7d9..ab3ab95 100644 --- a/sdk/src/main/java/io/verloop/sdk/Verloop.kt +++ b/sdk/src/main/java/io/verloop/sdk/Verloop.kt @@ -168,12 +168,12 @@ class Verloop(val context: Context, var verloopConfig: VerloopConfig) { config.logEventListener?.logEvent(logEvent) } - fun onChatStarted() { - config.chatStartedListenerImpl?.onChatStarted() + fun onChatStarted(roomId: String?) { + config.chatStartedListenerImpl?.onChatStarted(roomId) } - fun onRoomReady() { - config.roomReadyListenerImpl?.onRoomReady() + fun onRoomReady(roomId: String?) { + config.roomReadyListenerImpl?.onRoomReady(roomId) } } } \ No newline at end of file diff --git a/sdk/src/main/java/io/verloop/sdk/ui/VerloopFragment.kt b/sdk/src/main/java/io/verloop/sdk/ui/VerloopFragment.kt index d337833..fc825ff 100644 --- a/sdk/src/main/java/io/verloop/sdk/ui/VerloopFragment.kt +++ b/sdk/src/main/java/io/verloop/sdk/ui/VerloopFragment.kt @@ -578,24 +578,26 @@ class VerloopFragment : Fragment() { private fun handleCallback(args: org.json.JSONArray?) { val eventName = args?.optString(0) ?: return + val payload = args.optJSONObject(1) + val roomId = payload?.optString("roomId", null) when (eventName) { - "chat-started" -> callChatStarted() - "room-ready" -> callRoomReady() + "chat-started" -> callChatStarted(roomId) + "room-ready" -> callRoomReady(roomId) // room-ready, chat-ended, etc. — add later as needed } } - private fun callChatStarted(){ + private fun callChatStarted(roomId: String?){ logEvent(LogLevel.INFO, "ChatStarted", null) Handler(Looper.getMainLooper()).post { - viewModel?.chatStarted() + viewModel?.chatStarted(roomId) } } - private fun callRoomReady(){ + private fun callRoomReady(roomId: String?){ logEvent(LogLevel.INFO, "Room Ready", null) Handler(Looper.getMainLooper()).post { - viewModel?.roomReady() + viewModel?.roomReady(roomId) } } diff --git a/sdk/src/main/java/io/verloop/sdk/viewmodel/MainViewModel.kt b/sdk/src/main/java/io/verloop/sdk/viewmodel/MainViewModel.kt index 1633105..abd7d7b 100644 --- a/sdk/src/main/java/io/verloop/sdk/viewmodel/MainViewModel.kt +++ b/sdk/src/main/java/io/verloop/sdk/viewmodel/MainViewModel.kt @@ -28,12 +28,12 @@ class MainViewModel(var configKey: String?, var repository: VerloopRepository) : } } - fun chatStarted() { - Verloop.eventListeners[configKey]?.onChatStarted() + fun chatStarted(roomId: String?) { + Verloop.eventListeners[configKey]?.onChatStarted(roomId) } - fun roomReady() { - Verloop.eventListeners[configKey]?.onRoomReady() + fun roomReady(roomId: String?) { + Verloop.eventListeners[configKey]?.onRoomReady(roomId) } fun urlClicked(json: String) { From 7379eca8b5be52db1d0c9320b2511a62d857102c Mon Sep 17 00:00:00 2001 From: Subhadip Mondal <159517480+subhadipverloop@users.noreply.github.com> Date: Thu, 14 May 2026 12:27:17 +0530 Subject: [PATCH 3/3] update: readme.md & typo on method name type on setRoomReadyListener updated readme.md --- .idea/misc.xml | 12 ++++++---- Readme.md | 18 ++++++++++----- app/src/main/java/io/verloop/TestActivity.kt | 22 +++++++++---------- .../main/java/io/verloop/sdk/VerloopConfig.kt | 2 +- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 8af4157..362a8f0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - + - + diff --git a/Readme.md b/Readme.md index f576e7a..9df4826 100644 --- a/Readme.md +++ b/Readme.md @@ -247,12 +247,20 @@ click listeners can be added using: `overrideUrlClick`: keep it as true if you want to handle the url internally in your app. Else keep it false if you want to open a browser when url is clicked. -```kotlin -config?.setUrlClickListener(object : LiveChatUrlClickListener { - override fun buttonClicked(url: String?) { - // Add the app logic for url click +### Chat Started Listener + +Receive a callback when a new chat conversation has been started for the user. +This fires once the chat has been initiated and the backend has assigned a +`roomId` for the conversation. Use it to log analytics, persist the room +reference, or trigger any in-app behaviour that depends on a chat being live. + + ```kotlin + config?.setChatStartedListener(object : LiveChatStartedListener { + override fun onChatStarted(roomId: String?) { + // A new chat has started — `roomId` identifies this conversation + // Log.d("Chat Started","roomId = $roomId") } -}, overrideUrlClick) +}) ``` # User session management diff --git a/app/src/main/java/io/verloop/TestActivity.kt b/app/src/main/java/io/verloop/TestActivity.kt index 787956c..eb90469 100644 --- a/app/src/main/java/io/verloop/TestActivity.kt +++ b/app/src/main/java/io/verloop/TestActivity.kt @@ -17,6 +17,7 @@ import io.verloop.sdk.utils.NetworkUtils import org.json.JSONException import org.json.JSONObject import android.net.Uri +import kotlin.math.log class TestActivity : AppCompatActivity() { @@ -25,15 +26,6 @@ class TestActivity : AppCompatActivity() { var verloop: Verloop? = null var verloop2: Verloop? = null - private val chatStarted: (String?) -> Unit = { roomId -> - Log.i(TAG, "Chat Started - roomId $roomId") - Toast.makeText(applicationContext, "Chat Started", Toast.LENGTH_SHORT).show() - } - - private val roomReady: (String?) -> Unit = { roomId -> - Log.i(TAG, "Room Ready - roomId $roomId") - Toast.makeText(applicationContext, "Room Ready", Toast.LENGTH_SHORT).show() - } var headerConfig: HeaderConfig? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -201,8 +193,16 @@ class TestActivity : AppCompatActivity() { } } }) - verloopConfig?.setChatStartedListener(chatStarted) - verloopConfig?.setRoomReadyListner(roomReady) + verloopConfig?.setChatStartedListener(object : LiveChatStartedListener{ + override fun onChatStarted(roomId: String?) { + Log.d("Chat Started"," roomId = $roomId") + } + }) + verloopConfig?.setRoomReadyListener(object : LiveChatRoomReadyListner{ + override fun onRoomReady(roomId: String?) { + Log.d("Room Ready","roomId = $roomId") + } + }) verloop = Verloop(this, verloopConfig!!) verloop?.showChat() } catch (e: VerloopException) { diff --git a/sdk/src/main/java/io/verloop/sdk/VerloopConfig.kt b/sdk/src/main/java/io/verloop/sdk/VerloopConfig.kt index bf91bfa..44a5762 100644 --- a/sdk/src/main/java/io/verloop/sdk/VerloopConfig.kt +++ b/sdk/src/main/java/io/verloop/sdk/VerloopConfig.kt @@ -92,7 +92,7 @@ data class VerloopConfig private constructor( * Callback for chat started * @param roomReadyListenerImpl */ - fun setRoomReadyListner(listener: LiveChatRoomReadyListner) { + fun setRoomReadyListener(listener: LiveChatRoomReadyListner) { this.roomReadyListenerImpl = listener // ← uses new name }