Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/mtsdk 318 poc cards and carousels #274

Open
wants to merge 2 commits into
base: feature/MTSDK-76-Cards-and-Carousels
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ enum class Command(val description: String) {
OKTA_SIGN_IN_WITH_PKCE("oktaSignInWithPKCE"),
SEND("send <msg>"),
SEND_QUICK_REPLY("sendQuickReply <quickReply>"),
TYPING("typing")
TYPING("typing"),
SEND_CARD_REPLY("sendCardReply <card> <action>")
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package com.genesys.cloud.messenger.androidcomposeprototype.ui.testbed

import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.genesys.cloud.messenger.androidcomposeprototype.BuildConfig
import com.genesys.cloud.messenger.transport.core.Action
import com.genesys.cloud.messenger.transport.core.Attachment.State.Detached
import com.genesys.cloud.messenger.transport.core.ButtonResponse
import com.genesys.cloud.messenger.transport.core.Card
import com.genesys.cloud.messenger.transport.core.Configuration
import com.genesys.cloud.messenger.transport.core.CorrectiveAction
import com.genesys.cloud.messenger.transport.core.ErrorCode
import com.genesys.cloud.messenger.transport.core.Message
import com.genesys.cloud.messenger.transport.core.FileAttachmentProfile
import com.genesys.cloud.messenger.transport.core.MessageEvent
import com.genesys.cloud.messenger.transport.core.MessageEvent.AttachmentUpdated
Expand Down Expand Up @@ -41,6 +47,7 @@ class TestBedViewModel : ViewModel(), CoroutineScope {
private lateinit var client: MessagingClient
private val attachedIds = mutableListOf<String>()


var command: String by mutableStateOf("")
private set
var commandWaiting: Boolean by mutableStateOf(false)
Expand All @@ -56,6 +63,7 @@ class TestBedViewModel : ViewModel(), CoroutineScope {
var authState: AuthState by mutableStateOf(AuthState.NoAuth)
private set
private var pkceEnabled by mutableStateOf(false)
private var cards: Map<String, Card> = emptyMap()

var authCode: String = ""
set(value) {
Expand All @@ -73,6 +81,7 @@ class TestBedViewModel : ViewModel(), CoroutineScope {
private lateinit var onOktaSingIn: (url: String) -> Unit
private val quickRepliesMap = mutableMapOf<String, ButtonResponse>()
private lateinit var selectFile: (fileAttachmentProfile: FileAttachmentProfile) -> Unit
private val carouselMap = mutableMapOf<String, Message.Card>()

fun init(
context: Context,
Expand Down Expand Up @@ -101,7 +110,7 @@ class TestBedViewModel : ViewModel(), CoroutineScope {
)
}
}
messageListener = { onMessage(it) }
messageListener = { onMessage(it, context) }
eventListener = { onEvent(it) }
clientState = client.currentState
}
Expand Down Expand Up @@ -153,13 +162,41 @@ class TestBedViewModel : ViewModel(), CoroutineScope {
"refreshAttachment" -> doRefreshAttachmentUrl(input)
"savedFileName" -> doChangeFileName(input)
"fileAttachmentProfile" -> doFileAttachmentProfile()
"sendCardReply" -> doSendCardReply(input)
else -> {
Log.e(TAG, "Invalid command")
commandWaiting = false
}
}
}

private fun doSendCardReply(input: String) {
commandWaiting = false
val components = input.split(" ", limit = 2)
val card = components.firstOrNull()
val inputAction = components.getOrNull(1) ?: ""
carouselMap[card]?.actions?.forEach {
if (it.type == "Link") {
openExternalLink(it.url, DefaultVault.context!!)
}
return
}
carouselMap[card]?.let {
it.actions.forEach { action ->
if (action.text == inputAction) {
client.sendQuickReply(
ButtonResponse(
text = action.text ?: "",
payload = action.payload ?: "",
//type = action.type
type = "Button"
)
)
}
}
}
}

private fun doOktaSignIn(withPKCE: Boolean) {
pkceEnabled = withPKCE
onOktaSingIn(buildOktaAuthorizeUrl())
Expand Down Expand Up @@ -388,7 +425,34 @@ class TestBedViewModel : ViewModel(), CoroutineScope {
commandWaiting = false
}

private fun onMessage(event: MessageEvent) {
// private fun handleCardAction(context: Context, actions: List<Action>) {
// val buttonResponses = actions.map { action ->
// if (action.type == "Postback") {
// ButtonResponse(
// text = action.text,
// payload = action.payload!!,
// type = action.type
// )
//
// }
//
// }
// quickRepliesMap.putAll(buttonResponses.associateBy { it.text })
//
// }

private fun openExternalLink(url: String?, context: Context) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
Log.e(TAG, "No activity found to handle URL: $url", e)
}

}

private fun onMessage(event: MessageEvent, context: Context) {
val eventMessage = when (event) {
is MessageEvent.MessageUpdated -> "MessageUpdated: ${event.message}"
is MessageEvent.MessageInserted -> "MessageInserted: ${event.message}"
Expand All @@ -403,13 +467,16 @@ class TestBedViewModel : ViewModel(), CoroutineScope {
else -> event.attachment.toString()
}
}

is MessageEvent.QuickReplyReceived -> event.message.run {
quickRepliesMap.clear()
quickRepliesMap.putAll(quickReplies.associateBy { it.text })
"QuickReplyReceived: text: $text | quick reply options: $quickReplies"
}

is MessageEvent.CarouselMessageReceived -> {
carouselMap.clear()
carouselMap.putAll(event.message.cards.associateBy { it.title })
"CarouselMessageReceived | cards options: $carouselMap"
}
else -> event.toString()
}
onSocketMessageReceived(eventMessage)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.genesys.cloud.messenger.transport.core

import kotlinx.serialization.Serializable


@Serializable
data class Action(
val payload: String? = null,
val text: String,
val type: String,
val url: String? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.genesys.cloud.messenger.transport.core

import kotlinx.serialization.Serializable


@Serializable
data class Card(
val actions: List<Action> = emptyList(),
val defaultAction: DefaultAction,
val description: String,
val image: String,
val title: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.genesys.cloud.messenger.transport.core

import kotlinx.serialization.Serializable


@Serializable
data class Cards(
val body: Action,
val `class`: String,
val code: Int,
val type: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.genesys.cloud.messenger.transport.core

import kotlinx.serialization.Serializable


@Serializable
data class Carousel(
val cards: List<Card>
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.genesys.cloud.messenger.transport.core

import kotlinx.serialization.Serializable


@Serializable
data class DefaultAction(
val type: String,
val url: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ data class Message(
val attachments: Map<String, Attachment> = emptyMap(),
val events: List<Event> = emptyList(),
val quickReplies: List<ButtonResponse> = emptyList(),
val cards: List<Card> = emptyList(),
val from: Participant = Participant(
originatingEntity = Participant.OriginatingEntity.Human
),
Expand All @@ -48,6 +49,8 @@ data class Message(
Text,
Event,
QuickReply,
Card,
Carousel,
Unknown,
}

Expand Down Expand Up @@ -103,11 +106,15 @@ data class Message(
val contentType: Type,
val attachment: Attachment? = null,
val buttonResponse: ButtonResponse? = null,
val card: Card? = null,
val carousel: Carousel? = null,
) {
@Serializable
enum class Type {
Attachment,
ButtonResponse,
Card,
Carousel,
}
}

Expand Down Expand Up @@ -138,4 +145,25 @@ data class Message(
Unknown,
}
}

@Serializable
data class Card(
val title: String,
val description: String,
val imageUrl: String,
val actions: List<Action>
) {
@Serializable
data class Action(
val type: String,
val text: String? = null,
val url: String? = null,
val payload: String? = null,
)
}

@Serializable
data class Carousel(
val cards: List<Card>
)
}
Loading