diff --git a/app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt b/app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt
index 1db957e09..dc1bc1339 100644
--- a/app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt
+++ b/app/src/main/java/live/hms/app2/ui/home/HomeFragment.kt
@@ -14,6 +14,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.content.edit
+import androidx.core.os.bundleOf
import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
@@ -82,10 +83,7 @@ class HomeFragment : Fragment() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_settings -> {
- findNavController().navigate(
- HomeFragmentDirections.actionHomeFragmentToSettingsFragment(SettingsMode.HOME)
- )
-
+ findNavController().navigate(HomeFragmentDirections.actionHomeFragmentToSettingsFragment())
}
R.id.action_email_logs -> {
requireContext().startActivity(
@@ -263,13 +261,13 @@ class HomeFragment : Fragment() {
private fun enableButton() {
binding.btnJoinNow.isEnabled = true
binding.btnJoinNow.background =
- ContextCompat.getDrawable(requireContext(), R.drawable.primary_blue_round_drawable)
+ ContextCompat.getDrawable(requireContext(), live.hms.roomkit.R.drawable.primary_blue_round_drawable)
}
private fun disableButton() {
binding.btnJoinNow.isEnabled = false
binding.btnJoinNow.background =
- ContextCompat.getDrawable(requireContext(), R.drawable.primary_disabled_round_drawable)
+ ContextCompat.getDrawable(requireContext(), live.hms.roomkit.R.drawable.primary_disabled_round_drawable)
}
diff --git a/app/src/main/res/drawable/primary_disabled_round_drawable.xml b/app/src/main/res/drawable/primary_disabled_round_drawable.xml
deleted file mode 100644
index f3f70896d..000000000
--- a/app/src/main/res/drawable/primary_disabled_round_drawable.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/navigation/home_nav_graph.xml b/app/src/main/res/navigation/home_nav_graph.xml
index ddcbeabb4..0ee940ab9 100644
--- a/app/src/main/res/navigation/home_nav_graph.xml
+++ b/app/src/main/res/navigation/home_nav_graph.xml
@@ -24,12 +24,6 @@
android:label="@string/settings_fragment"
tools:layout="@layout/fragment_settings">
-
-
-
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index f1652e547..072711724 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -22,5 +22,5 @@ kotlin.code.style=official
100MS_APP_VERSION_CODE=643
100MS_APP_VERSION_NAME=5.8.872
hmsRoomKitGroup=live.100ms
-HMS_ROOM_KIT_VERSION=1.1.8
+HMS_ROOM_KIT_VERSION=1.1.9
android.suppressUnsupportedCompileSdk=33
diff --git a/room-kit/build.gradle b/room-kit/build.gradle
index 345594ae5..2349ed668 100644
--- a/room-kit/build.gradle
+++ b/room-kit/build.gradle
@@ -69,7 +69,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.percentlayout:percentlayout:1.0.0'
- def hmsVersion = "2.8.5"
+ def hmsVersion = "2.8.6"
// To add dependencies of specific module
implementation "live.100ms:android-sdk:$hmsVersion"
implementation "live.100ms:video-view:$hmsVersion"
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingActivity.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingActivity.kt
index 30dfb75c7..34e5cdccd 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingActivity.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingActivity.kt
@@ -8,11 +8,9 @@ import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
-import androidx.core.os.bundleOf
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
-import androidx.navigation.findNavController
import androidx.navigation.fragment.NavHostFragment
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.DiffUtil
@@ -21,9 +19,6 @@ import live.hms.roomkit.R
import live.hms.roomkit.animation.RootViewDeferringInsetsCallback
import live.hms.roomkit.databinding.ActivityMeetingBinding
import live.hms.roomkit.ui.HMSPrebuiltOptions
-import live.hms.roomkit.ui.meeting.chat.combined.CHAT_TAB_TITLE
-import live.hms.roomkit.ui.meeting.chat.combined.ChatParticipantCombinedFragment
-import live.hms.roomkit.ui.meeting.chat.combined.OPEN_TO_PARTICIPANTS
import live.hms.roomkit.ui.notification.CardStackLayoutManager
import live.hms.roomkit.ui.notification.CardStackListener
import live.hms.roomkit.ui.notification.Direction
@@ -31,7 +26,6 @@ import live.hms.roomkit.ui.notification.HMSNotification
import live.hms.roomkit.ui.notification.HMSNotificationAdapter
import live.hms.roomkit.ui.notification.HMSNotificationDiffCallBack
import live.hms.roomkit.ui.notification.HMSNotificationType
-import live.hms.roomkit.ui.polls.display.POLL_TO_DISPLAY
import live.hms.roomkit.ui.polls.display.PollDisplayFragment
import live.hms.roomkit.ui.settings.SettingsStore
import live.hms.roomkit.util.ROOM_CODE
@@ -94,31 +88,9 @@ class MeetingActivity : AppCompatActivity() {
binding.progressBar.visibility = View.VISIBLE
- //todo show a loader UI
- meetingViewModel.initSdk(roomCode, token, hmsPrebuiltOption, object : HMSActionResultListener {
- override fun onError(error: HMSException) {
- runOnUiThread {
- Toast.makeText(this@MeetingActivity, error.message, Toast.LENGTH_SHORT).show()
- finish()
- }
- }
+ meetingViewModel.initSdk(roomCode, token, hmsPrebuiltOption, null)
- override fun onSuccess() {
- runOnUiThread {
- binding.progressBar.visibility = View.GONE
- val navHostFragment =
- supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
- val navController = navHostFragment.navController
- val topFragment = navHostFragment.childFragmentManager.fragments.firstOrNull()
- if (settingsStore?.showPreviewBeforeJoin == true && (topFragment is MeetingFragment).not()) navController?.setGraph(
- R.navigation.meeting_nav_graph, intent.extras
- )
- else navController?.setGraph(R.navigation.no_preview_nav_graph, intent.extras)
-
- initViewModels()
- }
- }
- })
+ initObservers()
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
@@ -138,7 +110,7 @@ class MeetingActivity : AppCompatActivity() {
_binding = null
}
- private fun initViewModels() {
+ private fun initObservers() {
meetingViewModel.recordingState.observe(this) {
invalidateOptionsMenu()
}
@@ -158,6 +130,25 @@ class MeetingActivity : AppCompatActivity() {
tryRemovingNotification(it)
}
+ meetingViewModel.roomLayoutLiveData.observe(this) {success ->
+ if(success) {
+ binding.progressBar.visibility = View.GONE
+ val navHostFragment =
+ supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
+ val navController = navHostFragment.navController
+ val topFragment = navHostFragment.childFragmentManager.fragments.firstOrNull()
+ navController.setGraph(
+ R.navigation.meeting_nav_graph, intent.extras
+ )
+ /*if (settingsStore?.showPreviewBeforeJoin == true && (topFragment is MeetingFragment).not()) navController?.setGraph(
+ R.navigation.meeting_nav_graph, intent.extras
+ )
+ else navController?.setGraph(R.navigation.no_preview_nav_graph, intent.extras)*/
+ } else {
+ Toast.makeText(this@MeetingActivity, "Error while Getting Room Layout Data", Toast.LENGTH_SHORT).show()
+ finish()
+ }
+ }
}
private fun triggerNotification(hmsNotification: HMSNotification) {
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingFragment.kt
index 5b129f3f1..82d984d5d 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingFragment.kt
@@ -111,7 +111,7 @@ class MeetingFragment : Fragment() {
private val chatAdapter by lazy {
ChatAdapter({ message ->
launchMessageOptionsDialog.launch(meetingViewModel,
- childFragmentManager, message) }, ::onChatClick, { MessageOptionsBottomSheet.showMessageOptions(meetingViewModel)})
+ childFragmentManager, message) }, ::onChatClick, { message -> MessageOptionsBottomSheet.showMessageOptions(meetingViewModel, message)})
}
private val chatViewModel: ChatViewModel by activityViewModels {
@@ -265,17 +265,36 @@ class MeetingFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.applyTheme()
- initObservers()
- initButtons()
- initOnBackPress()
- if (meetingViewModel.state.value is MeetingState.Disconnected) {
- // Handles configuration changes
- meetingViewModel.startMeeting()
+ if (savedInstanceState != null) {
+ // Recreated Fragment
+ meetingViewModel.roomLayoutLiveData.observe(viewLifecycleOwner) {success ->
+ if (success) {
+ meetingViewModel.state.observe(viewLifecycleOwner) { state ->
+ if (state is MeetingState.Ongoing) {
+ hideProgressBar()
+ isMeetingOngoing = true
+ meetingViewModel.state.removeObservers(viewLifecycleOwner)
+ initializeUI()
+ }
+ }
+ meetingViewModel.roomLayoutLiveData.removeObservers(viewLifecycleOwner)
+ meetingViewModel.startMeeting()
+ } else {
+ this.activity?.finish()
+ }
+ }
} else {
- //start HLS stream
+ initializeUI()
startHLSStreamingIfRequired()
}
+ }
+
+ private fun initializeUI() {
+ initButtons()
+ initObservers()
+ initOnBackPress()
+
binding.chatMessages.isHeightContrained = true
PauseChatUIUseCase().setChatPauseVisible(
binding.chatOptionsCard,
@@ -301,9 +320,12 @@ class MeetingFragment : Fragment() {
binding.chatExtra,
meetingViewModel.prebuiltInfoContainer::isChatEnabled,
meetingViewModel::availableRecipientsForChat,
- chatViewModel::currentlySelectedRbacRecipient
+ chatViewModel::currentlySelectedRbacRecipient,
+ chatViewModel.currentlySelectedRecipientRbac,
)
-
+ meetingViewModel.peerLeaveUpdate.observe(viewLifecycleOwner) {
+ chatViewModel.updatePeerLeave(it)
+ }
if(meetingViewModel.prebuiltInfoContainer.chatInitialStateOpen()) {
binding.buttonOpenChat.setIconDisabled(R.drawable.ic_chat_message)
} else {
@@ -535,12 +557,10 @@ class MeetingFragment : Fragment() {
Log.d("RecordingState", event.message)
}
is MeetingViewModel.Event.RtmpEvent -> {
- meetingViewModel.triggerErrorNotification(event.message)
- Log.d("RecordingState", event.message)
+ Log.i("RecordingState", event.message)
}
is MeetingViewModel.Event.ServerRecordEvent -> {
- meetingViewModel.triggerErrorNotification(event.message)
- Log.d("RecordingState", event.message)
+ Log.i("RecordingState", event.message)
}
is MeetingViewModel.Event.HlsEvent, is MeetingViewModel.Event.HlsRecordingEvent -> {
Log.d("RecordingState", "HlsEvent: ${event}")
@@ -865,7 +885,7 @@ class MeetingFragment : Fragment() {
)
binding.buttonRaiseHand.visibility = View.GONE
- WindowCompat.setDecorFitsSystemWindows(activity!!.window, true)
+ WindowCompat.setDecorFitsSystemWindows(requireActivity().window, true)
showSystemBars()
}
@@ -953,7 +973,7 @@ class MeetingFragment : Fragment() {
})?.start()
- val screenHeight = activity!!.window.decorView.height
+ val screenHeight = requireActivity().window.decorView.height
binding.bottomControls.animate()
?.translationY(0f)?.setDuration(300)?.setListener(object : AnimatorListener {
override fun onAnimationStart(animation: Animator) {
@@ -1001,9 +1021,9 @@ class MeetingFragment : Fragment() {
private fun hideControlBars() {
val topMenu = binding.topMenu
val bottomMenu = binding.bottomControls
- val screenHeight = activity!!.window.decorView.height
+ val screenHeight = requireActivity().window.decorView.height
controlBarsVisible = false
- topMenu?.animate()
+ topMenu.animate()
?.translationY(-(topMenu.height.toFloat()))?.setDuration(300)
?.setListener(object : AnimatorListener {
override fun onAnimationStart(animation: Animator) {
@@ -1350,53 +1370,6 @@ class MeetingFragment : Fragment() {
})
}
- fun roleChangeRemote() {
-
- val isAllowedToMuteUnmute =
- meetingViewModel.isAllowedToMutePeers() && meetingViewModel.isAllowedToAskUnmutePeers()
- var remotePeersAreMute: Boolean? = null
- if (isAllowedToMuteUnmute) {
- remotePeersAreMute = meetingViewModel.areAllRemotePeersMute()
- }
-
- val cancelRoleName = "Cancel"
- val availableRoles = meetingViewModel.getAvailableRoles().map { it.name }
- val rolesToSend = availableRoles.plus(cancelRoleName)
- binding.roleSpinner.root.initAdapters(
- rolesToSend,
- if (remotePeersAreMute == null) "Nothing to change" else if (remotePeersAreMute) "Remote Unmute Role" else "Remote Mute Role",
- object : AdapterView.OnItemSelectedListener {
- override fun onItemSelected(
- parent: AdapterView<*>?,
- view: View?,
- position: Int,
- id: Long
- ) {
- val stringRole = parent?.adapter?.getItem(position) as String
- if (remotePeersAreMute == null) {
- Toast.makeText(
- requireContext(),
- "No remote peers, or their audio tracks are absent",
- Toast.LENGTH_LONG
- ).show()
- } else {
- if (stringRole != cancelRoleName) {
- meetingViewModel.remoteMute(
- !remotePeersAreMute,
- listOf(stringRole)
- )
- }
- }
- }
-
- override fun onNothingSelected(parent: AdapterView<*>?) {
- // Nothing
- }
-
- })
- binding.roleSpinner.root.performClick()
- }
-
fun inflateExitFlow() {
if (meetingViewModel.isAllowedToEndMeeting() || (meetingViewModel.isAllowedToHlsStream() && meetingViewModel.isHlsRunning())) {
MultipleLeaveOptionBottomSheet()
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingViewModel.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingViewModel.kt
index 820ea910d..3450c88b2 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingViewModel.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingViewModel.kt
@@ -45,6 +45,7 @@ import live.hms.video.polls.models.HmsPollState
import live.hms.video.polls.models.answer.PollAnswerResponse
import live.hms.video.polls.models.question.HMSPollQuestion
import live.hms.video.polls.models.question.HMSPollQuestionType
+import live.hms.video.polls.network.PollLeaderboardResponse
import live.hms.video.sdk.*
import live.hms.video.sdk.models.*
import live.hms.video.sdk.models.enums.*
@@ -81,11 +82,13 @@ class MeetingViewModel(
HMSLogSettings(LogAlarmManager.DEFAULT_DIR_SIZE, true)
private var isPrebuiltDebug by Delegates.notNull()
val roleChange = MutableLiveData()
- private var numRoleChanges = 0
- val roleChangeSingleShot : LiveData = roleChange.map { numRoleChanges++ }
+
var roleOnJoining : HMSRole? = null
private set
+ var localPeerId : String? = null
+ private set
+
fun isLargeRoom() = hmsRoom?.isLargeRoom?:false
private val hmsTrackSettings = HMSTrackSettings.Builder()
@@ -154,11 +157,12 @@ class MeetingViewModel(
roomCode: String,
token: String,
hmsPrebuiltOptions: HMSPrebuiltOptions?,
- onHMSActionResultListener: HMSActionResultListener
+ onHMSActionResultListener: HMSActionResultListener?
) {
this.prebuiltOptions = hmsPrebuiltOptions
if (hasValidToken) {
- onHMSActionResultListener.onSuccess()
+ onHMSActionResultListener?.onSuccess()
+ roomLayoutLiveData.postValue(true)
return
}
//if empty is uses the prod token url else uses the debug token url
@@ -178,7 +182,8 @@ class MeetingViewModel(
object : HMSTokenListener {
override fun onError(error: HMSException) {
hasValidToken = false
- onHMSActionResultListener.onError(error)
+ onHMSActionResultListener?.onError(error)
+ roomLayoutLiveData.postValue(false)
}
override fun onTokenSuccess(token: String) {
@@ -186,12 +191,10 @@ class MeetingViewModel(
}
})
-
-
}
- fun joinRoomUsingToken(token: String, hmsPrebuiltOptions: HMSPrebuiltOptions?, onHMSActionResultListener: HMSActionResultListener) {
+ fun joinRoomUsingToken(token: String, hmsPrebuiltOptions: HMSPrebuiltOptions?, onHMSActionResultListener: HMSActionResultListener?) {
val initURL: String = if (hmsPrebuiltOptions?.endPoints?.containsKey("init") == true)
hmsPrebuiltOptions.endPoints["init"].orEmpty()
@@ -206,15 +209,18 @@ class MeetingViewModel(
HMSLayoutListener {
override fun onError(error: HMSException) {
Log.e(TAG, "onError: ", error)
- onHMSActionResultListener.onError(error)
+ onHMSActionResultListener?.onError(error)
+ roomLayoutLiveData.postValue(false)
}
override fun onLayoutSuccess(layoutConfig: HMSRoomLayout) {
hmsRoomLayout = layoutConfig
prebuiltInfoContainer.setParticipantLabelInfo(hmsRoomLayout)
+ Log.d("Pratim", "Setting HMS Config")
setHmsConfig(hmsPrebuiltOptions, token, initURL)
kotlin.runCatching { setTheme(layoutConfig.data?.getOrNull(0)?.themes?.getOrNull(0)?.palette!!) }
- onHMSActionResultListener.onSuccess()
+ onHMSActionResultListener?.onSuccess()
+ roomLayoutLiveData.postValue(true)
}
})
@@ -314,6 +320,7 @@ class MeetingViewModel(
val hmsRemoveNotificationEvent = MutableLiveData()
val updateGridLayoutDimensions = SingleLiveEvent()
val hmsScreenShareBottomSheetEvent = SingleLiveEvent()
+ val roomLayoutLiveData : MutableLiveData = MutableLiveData()
fun setMeetingViewMode(mode: MeetingViewMode) {
if (mode != meetingViewMode.value) {
@@ -450,6 +457,7 @@ class MeetingViewModel(
// Live data which changes on any change of peer
val peerLiveData = MutableLiveData()
val participantPeerUpdate = MutableLiveData()
+ val peerLeaveUpdate = MutableLiveData(null)
private val _peerMetadataNameUpdate = MutableLiveData>()
val peerMetadataNameUpdate: LiveData> = _peerMetadataNameUpdate
@@ -497,6 +505,7 @@ class MeetingViewModel(
}
override fun onPreview(room: HMSRoom, localTracks: Array) {
+ Log.d("Pratim", "onPreview called")
unMuteAllTracks(localTracks)
previewUpdateData.postValue(Pair(room, localTracks))
}
@@ -737,6 +746,7 @@ class MeetingViewModel(
Log.d(TAG, "SessionId is: ${room.sessionId}")
Log.d(TAG, "Room started at: ${room.startedAt}")
roleOnJoining = room.localPeer?.hmsRole
+ localPeerId = room.localPeer?.peerID
// get the hls URL from the Room, if it exists
val hlsUrl = room.hlsStreamingState.variants?.get(0)?.hlsStreamUrl
@@ -797,6 +807,7 @@ class MeetingViewModel(
peerLiveData.postValue(hmsPeer)
}
participantPeerUpdate.postValue(Unit)
+ peerLeaveUpdate.postValue(hmsPeer.peerID)
}
HMSPeerUpdate.PEER_JOINED -> {
@@ -1003,8 +1014,10 @@ class MeetingViewModel(
if(message.type != HMSMessageType.CHAT)
return
broadcastsReceived.postValue(
+
ChatMessage(
- message, false
+ message, false,
+ message.recipient.recipientPeer?.peerID == localPeerId
)
)
}
@@ -2017,6 +2030,10 @@ class MeetingViewModel(
}
})
+
+ fun fetchLeaderboard(pollId: String, completion: HmsTypedActionResultListener) {
+ localHmsInteractivityCenter.fetchLeaderboard(pollId, count = 200, completion = completion)
+ }
fun startPoll(currentList: List, pollCreationInfo: PollCreationInfo) {
// To start a poll
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MessageOptionsBottomSheet.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MessageOptionsBottomSheet.kt
index a56f8587c..28138f791 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MessageOptionsBottomSheet.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MessageOptionsBottomSheet.kt
@@ -37,8 +37,8 @@ class MessageOptionsBottomSheet(private val chatMessage: ChatMessage,
): BottomSheetDialogFragment() {
companion object {
- fun showMessageOptions(meetingViewModel: MeetingViewModel) : Boolean {
- val allowedToBlock = meetingViewModel.isAllowedToBlockFromChat()
+ fun showMessageOptions(meetingViewModel: MeetingViewModel, message: ChatMessage) : Boolean {
+ val allowedToBlock = meetingViewModel.isAllowedToBlockFromChat() && !message.isSentByMe
val allowedToPin = meetingViewModel.isAllowedToPinMessages()
val allowedToHideMessages = meetingViewModel.isAllowedToHideMessages()
return allowedToPin || allowedToBlock || allowedToHideMessages
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PauseChatUIUseCase.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PauseChatUIUseCase.kt
index a8fad9fe0..e2b08c8c9 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PauseChatUIUseCase.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PauseChatUIUseCase.kt
@@ -16,10 +16,4 @@ class PauseChatUIUseCase {
}
}
- fun observeChatPauseState(viewLifecycleOwner: LifecycleOwner, meetingViewModel: MeetingViewModel) {
- meetingViewModel.chatPauseState.observe(viewLifecycleOwner) { chatState ->
- // Set the chat as paused (can use the block UI I guess)
-
- }
- }
}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PrebuiltInfoContainer.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PrebuiltInfoContainer.kt
index 5d861f492..3c250911f 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PrebuiltInfoContainer.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/PrebuiltInfoContainer.kt
@@ -24,17 +24,17 @@ class PrebuiltInfoContainer(private val hmssdk: HMSSDK) {
fun isChatEnabled(): Boolean =
// how do we even know if it's in hls? What if they have both?
- roleMap[localPeer.hmsRole.name]?.screens?.conferencing?.hlsLiveStreaming
- ?.elements?.chat != null ||
- roleMap[localPeer.hmsRole.name]?.screens?.conferencing
- ?.default?.elements?.chat != null
+ roleMap[localPeer.hmsRole.name]?.screens?.conferencing?.hlsLiveStreaming
+ ?.elements?.chat != null ||
+ roleMap[localPeer.hmsRole.name]?.screens?.conferencing
+ ?.default?.elements?.chat != null
fun chatInitialStateOpen(): Boolean {
val isChatInitialOpen =
roleMap[localPeer.hmsRole.name]?.screens?.conferencing?.hlsLiveStreaming?.elements?.chat?.initialState == "CHAT_STATE_OPEN"
||
- roleMap[localPeer.hmsRole.name]?.screens?.conferencing
- ?.default?.elements?.chat?.initialState == "CHAT_STATE_OPEN"
+ roleMap[localPeer.hmsRole.name]?.screens?.conferencing
+ ?.default?.elements?.chat?.initialState == "CHAT_STATE_OPEN"
// Initial open is only valid for overlay chat
return isChatOverlay() && isChatInitialOpen
@@ -42,8 +42,8 @@ class PrebuiltInfoContainer(private val hmssdk: HMSSDK) {
fun isChatOverlay() =
roleMap[localPeer.hmsRole.name]?.screens?.conferencing?.hlsLiveStreaming?.elements?.chat?.overlayView == true
||
- roleMap[localPeer.hmsRole.name]?.screens?.conferencing
- ?.default?.elements?.chat?.overlayView == true
+ roleMap[localPeer.hmsRole.name]?.screens?.conferencing
+ ?.default?.elements?.chat?.overlayView == true
fun onStageExp(role : String) =
@@ -69,7 +69,8 @@ class PrebuiltInfoContainer(private val hmssdk: HMSSDK) {
Recipient.Everyone
}
else if (recipient.roles.isNotEmpty()) {
- val name = recipient.roles.first()
+ val localPeerRole = hmssdk.getLocalPeer()?.hmsRole?.name
+ val name = recipient.roles.filter { it != localPeerRole }.firstOrNull()
val role = hmssdk.getRoles().find { it.name == name }
if(role != null)
Recipient.Role(role)
@@ -111,10 +112,10 @@ class PrebuiltInfoContainer(private val hmssdk: HMSSDK) {
?.default?.elements?.chat?.realTimeControls?.canDisableChat == true
fun isAllowedToHideMessages(): Boolean =
- roleMap[localPeer.hmsRole.name]?.screens?.conferencing?.hlsLiveStreaming
- ?.elements?.chat?.realTimeControls?.canHideMessage == true ||
- roleMap[localPeer.hmsRole.name]?.screens?.conferencing
- ?.default?.elements?.chat?.realTimeControls?.canHideMessage == true
+ roleMap[localPeer.hmsRole.name]?.screens?.conferencing?.hlsLiveStreaming
+ ?.elements?.chat?.realTimeControls?.canHideMessage == true ||
+ roleMap[localPeer.hmsRole.name]?.screens?.conferencing
+ ?.default?.elements?.chat?.realTimeControls?.canHideMessage == true
fun getChatTitle(): String {
val hlsTitle = roleMap[localPeer.hmsRole.name]?.screens?.conferencing?.hlsLiveStreaming
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatAdapter.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatAdapter.kt
index 247e59cde..00fa19540 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatAdapter.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatAdapter.kt
@@ -17,7 +17,7 @@ import java.util.*
class ChatAdapter(private val openMessageOptions : (ChatMessage) -> Unit,
val onClick: () -> Unit = {},
- private val shouldShowMessageOptions : () -> Boolean
+ private val shouldShowMessageOptions : (ChatMessage) -> Boolean
) : ListAdapter(DIFFUTIL_CALLBACK) {
private val formatter = SimpleDateFormat("h:mm a", Locale.getDefault())
companion object {
@@ -54,23 +54,31 @@ class ChatAdapter(private val openMessageOptions : (ChatMessage) -> Unit,
time.text = formatter.format(Date(sentMessage.time))
}
- sentTo.visibility = if(sentMessage.sentTo == null)
- View.GONE
+ val isSentToVisible = sentMessage.toGroup != null
+ sentTo.visibility = if(isSentToVisible)
+ View.VISIBLE
else
- View.VISIBLE
-
- toGroup.visibility = if(sentMessage.toGroup == null)
View.GONE
- else
- View.VISIBLE
- sentBackground.visibility = if(sentMessage.toGroup == null && sentMessage.sentTo == null) {
+ if(isSentToVisible) {
+ val r = binding.root.resources
+ sentTo.text =
+ r.getString(R.string.chat_to_label,
+ sentMessage.toGroup,
+ if(sentMessage.isDmToMe || sentMessage.isDm)
+ r.getString(R.string.chat_to_dm_label)
+ else
+ r.getString(R.string.chat_to_group_label)
+ )
+ }
+
+ sentBackground.visibility = if(sentMessage.toGroup == null) {
View.GONE
} else
View.VISIBLE
- sentTo.text = sentMessage.sentTo
- toGroup.text = sentMessage.toGroup
- viewMore.visibility = if(shouldShowMessageOptions()) View.VISIBLE else View.GONE
+
+
+ viewMore.visibility = if(shouldShowMessageOptions(sentMessage)) View.VISIBLE else View.GONE
}
}
}
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatMessage.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatMessage.kt
index 7bb152d72..084504082 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatMessage.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatMessage.kt
@@ -3,9 +3,11 @@ package live.hms.roomkit.ui.meeting.chat
import live.hms.video.sdk.models.HMSMessage
import live.hms.video.sdk.models.enums.HMSMessageRecipientType
import live.hms.video.sdk.models.role.HMSRole
-import java.util.*
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
+import live.hms.roomkit.ui.meeting.chat.rbac.RecipientItem
+import live.hms.video.sdk.models.HMSMessageRecipient
+import live.hms.video.sdk.models.HMSPeer
const val DEFAULT_SENDER_NAME = "Participant"
@@ -17,38 +19,44 @@ data class ChatMessage constructor(
val time: Long? = null,
val message: String,
val isSentByMe: Boolean,
+ val isDmToMe : Boolean,
+ val isDm : Boolean,
var messageId : String? = null,
- val sentTo : String?,
val toGroup : String?,
val senderPeerId : String?,
val senderRoleName : String?,
- val userIdForBlockList : String?
+ val userIdForBlockList : String?,
) : Parcelable {
companion object {
- fun sendTo(message: HMSMessage) : String? = sendTo(message.recipient.recipientType,
- message.recipient.recipientRoles)
+ fun sendTo(recipient: HMSMessageRecipient, sentByMe: Boolean, sentToMe: Boolean) : String? =
+ sendTo(
+ recipient.recipientType,
+ recipient.recipientPeer,
+ recipient.recipientRoles,
+ sentToMe
+ )
- fun sendTo(recipient: HMSMessageRecipientType,
- roles : List?) : String? = when(recipient) {
+ fun sendTo(
+ recipient: HMSMessageRecipientType,
+ peer: HMSPeer?,
+ roles: List?,
+ sentToMe: Boolean
+ ) : String? = when(recipient) {
HMSMessageRecipientType.BROADCAST -> null
- HMSMessageRecipientType.PEER -> "Direct Message"
+ HMSMessageRecipientType.PEER -> if(sentToMe) "You" else peer?.name
HMSMessageRecipientType.ROLES -> roles?.firstOrNull()?.name ?: "Role"
}
-
- fun toGroup(recipient: HMSMessageRecipientType) = when(recipient) {
- HMSMessageRecipientType.PEER, HMSMessageRecipientType.BROADCAST -> null
- HMSMessageRecipientType.ROLES -> "To Group"
- }
}
- constructor(message: HMSMessage, sentByMe: Boolean) : this(
+ constructor(message: HMSMessage, sentByMe: Boolean, sentToMe : Boolean) : this(
if(sentByMe) "You" else message.sender?.name ?: DEFAULT_SENDER_NAME,
message.sender?.name ?: DEFAULT_SENDER_NAME,
message.serverReceiveTime,
message.message,
sentByMe,
+ sentToMe,
+ message.recipient.recipientType == HMSMessageRecipientType.PEER,
messageId = message.messageId,
- sentTo = sendTo(message),
- toGroup = toGroup(message.recipient.recipientType),
+ toGroup = sendTo(message.recipient, sentByMe, sentToMe),
message.sender?.peerID,
message.sender?.hmsRole?.name,
message.sender?.customerUserID
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatUseCase.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatUseCase.kt
index 2dc44a552..f0a911e46 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatUseCase.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatUseCase.kt
@@ -7,6 +7,7 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.LinearSmoothScroller
@@ -68,8 +69,8 @@ class ChatUseCase {
fun initiate(
messages: MutableLiveData>,
chatPauseState: MutableLiveData,
- roleChanged : MutableLiveData, //used to refresh options
- blockList : MutableLiveData>,
+ roleChanged: MutableLiveData, //used to refresh options
+ blockList: MutableLiveData>,
viewlifecycleOwner: LifecycleOwner,
chatAdapter: ChatAdapter,
recyclerview: SingleSideFadeRecyclerview,
@@ -83,8 +84,9 @@ class ChatUseCase {
chatPausedContainer: LinearLayoutCompat,
recipientPickerContainer: LinearLayout,
isChatEnabled: () -> Boolean,
- getAllowedRecipients : () -> AllowedToMessageParticipants?,
- currentRbac : () -> Recipient?
+ getAllowedRecipients: () -> AllowedToMessageParticipants?,
+ currentRbac: () -> Recipient?,
+ currentlySelectedRecipientRbac: LiveData
// canShowIndicator : () -> Boolean = {true}
) {
@@ -113,6 +115,10 @@ class ChatUseCase {
}
recyclerview.adapter = chatAdapter
toggleEmptyIndicator(emptyIndicator, messages.value)
+
+ currentlySelectedRecipientRbac.observe(viewlifecycleOwner) {
+ updateState()
+ }
// Chat pause observer
blockList.observe(viewlifecycleOwner) {
updateState()
@@ -206,6 +212,8 @@ class ChatUseCase {
}
ChatUiVisibilityState.RecipientSelectNeeded -> {
// Change the picker maybe?
+ bannedText.visibility = View.GONE
+ chatPausedContainer.visibility = View.GONE
}
ChatUiVisibilityState.Enabled -> {
bannedText.visibility = View.GONE
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatViewModel.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatViewModel.kt
index eefb6553b..b5cdeed39 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatViewModel.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/ChatViewModel.kt
@@ -6,7 +6,6 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
-import live.hms.roomkit.ui.meeting.chat.rbac.ChatMessageViewFilterHelper
import live.hms.video.error.HMSException
import live.hms.video.sdk.HMSMessageResultListener
import live.hms.video.sdk.HMSSDK
@@ -17,7 +16,6 @@ import live.hms.video.sdk.models.enums.HMSMessageType
import live.hms.video.sdk.models.role.HMSRole
class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
- private val chatmessageViewFilterHelper = ChatMessageViewFilterHelper()
companion object {
private const val TAG = "ChatViewModel"
@@ -33,9 +31,7 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
fun updateSelectedRecipientChatBottomSheet(recipient: Recipient?) {
// Set a filter for the messages.
- chatmessageViewFilterHelper.setFilter(recipient)
_currentlySelectedRecipient.postValue(recipient)
- messages.postValue(chatmessageViewFilterHelper.getSearchFilteredPeersIfNeeded(_messages))
}
val currentlySelectedRecipientRbac : LiveData = _currentlySelectedRecipient
@@ -46,50 +42,67 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
null -> {} // no-op if it's null
Recipient.Everyone -> broadcast(
ChatMessage(
- "You",
- hmssdk.getLocalPeer()?.name ?: DEFAULT_SENDER_NAME,
- null, // Let the server alone set the time
- messageStr,
- true,
- null,
- ChatMessage.sendTo(HMSMessageRecipientType.BROADCAST, null),
- ChatMessage.toGroup(HMSMessageRecipientType.BROADCAST),
- hmssdk.getLocalPeer()?.peerID,
- hmssdk.getLocalPeer()?.hmsRole?.name,
- hmssdk.getLocalPeer()?.customerUserID ?: ""
+ senderName = "You",
+ localSenderRealNameForPinMessage = hmssdk.getLocalPeer()?.name ?: DEFAULT_SENDER_NAME,
+ time = null, // Let the server alone set the time
+ message = messageStr,
+ isSentByMe = true,
+ isDmToMe = false,
+ isDm = false,
+ messageId = null,
+ toGroup = ChatMessage.sendTo(
+ recipient = HMSMessageRecipientType.BROADCAST,
+ peer = null,
+ roles = null,
+ false
+ ),
+ senderPeerId = hmssdk.getLocalPeer()?.peerID,
+ senderRoleName = hmssdk.getLocalPeer()?.hmsRole?.name,
+ userIdForBlockList = hmssdk.getLocalPeer()?.customerUserID ?: ""
)
)
is Recipient.Peer -> directMessage(
ChatMessage(
- "You",
- hmssdk.getLocalPeer()?.name ?: DEFAULT_SENDER_NAME,
- null, // Let the server alone set the time
- messageStr,
- true,
-
- null,
- ChatMessage.sendTo(HMSMessageRecipientType.PEER, null),
- ChatMessage.toGroup(HMSMessageRecipientType.PEER),
- hmssdk.getLocalPeer()?.peerID,
- hmssdk.getLocalPeer()?.hmsRole?.name,
- hmssdk.getLocalPeer()?.customerUserID ?: ""
+ senderName = "You",
+ localSenderRealNameForPinMessage = hmssdk.getLocalPeer()?.name ?: DEFAULT_SENDER_NAME,
+ time = null, // Let the server alone set the time
+ message = messageStr,
+ isSentByMe = true,
+ isDmToMe = false,
+ isDm = true,
+ messageId = null,
+ toGroup = ChatMessage.sendTo(
+ recipient = HMSMessageRecipientType.PEER,
+ peer = recipient.peer,
+ roles = null,
+ sentToMe = false
+ ),
+ senderPeerId = hmssdk.getLocalPeer()?.peerID,
+ senderRoleName = hmssdk.getLocalPeer()?.hmsRole?.name,
+ userIdForBlockList = hmssdk.getLocalPeer()?.customerUserID ?: ""
), recipient.peer
)
is Recipient.Role -> groupMessage(
ChatMessage(
- "You",
- hmssdk.getLocalPeer()?.name ?: DEFAULT_SENDER_NAME,
- null, // Let the server alone set the time
- messageStr,
- true,
- null,
- ChatMessage.sendTo(HMSMessageRecipientType.ROLES, listOf(recipient.role)),
- ChatMessage.toGroup(HMSMessageRecipientType.ROLES),
- hmssdk.getLocalPeer()?.peerID,
- hmssdk.getLocalPeer()?.hmsRole?.name,
- hmssdk.getLocalPeer()?.customerUserID
+ senderName = "You",
+ localSenderRealNameForPinMessage = hmssdk.getLocalPeer()?.name ?: DEFAULT_SENDER_NAME,
+ time = null, // Let the server alone set the time
+ message = messageStr,
+ isSentByMe = true,
+ isDmToMe = false,
+ isDm = false,
+ messageId = null,
+ toGroup = ChatMessage.sendTo(
+ recipient = HMSMessageRecipientType.ROLES,
+ peer = null,
+ roles = listOf(recipient.role),
+ sentToMe = false
+ ),
+ senderPeerId = hmssdk.getLocalPeer()?.peerID,
+ senderRoleName = hmssdk.getLocalPeer()?.hmsRole?.name,
+ userIdForBlockList = hmssdk.getLocalPeer()?.customerUserID
), recipient.role
)
}
@@ -108,7 +121,7 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
override fun onSuccess(hmsMessage: HMSMessage) {
// Request Successfully sent to server
MainScope().launch {
- addMessage(ChatMessage(hmsMessage, true))
+ addMessage(ChatMessage(hmsMessage, true, false))
}
}
@@ -128,7 +141,7 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
override fun onSuccess(hmsMessage: HMSMessage) {
// Request Successfully sent to server
MainScope().launch {
- addMessage(ChatMessage(hmsMessage, true))
+ addMessage(ChatMessage(hmsMessage, true, false))
}
}
@@ -147,7 +160,7 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
override fun onSuccess(hmsMessage: HMSMessage) {
// Request Successfully sent to server
MainScope().launch {
- addMessage(ChatMessage(hmsMessage, true))
+ addMessage(ChatMessage(hmsMessage, true, false))
}
}
@@ -178,7 +191,7 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
unreadMessagesCount.postValue(unreadMessagesCount.value?.plus(1))
}
_messages.add(message)
- messages.postValue(chatmessageViewFilterHelper.getSearchFilteredPeersIfNeeded(_messages))
+ messages.postValue(_messages)
}
}
@@ -201,7 +214,7 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
this.messageIdsToHide = messageIdsToHide
// Refresh the current list
_messages = _messages.filter { !messageIdsToHide.contains(it.messageId) }.toMutableList()
- messages.postValue(chatmessageViewFilterHelper.getSearchFilteredPeersIfNeeded(_messages))
+ messages.postValue(_messages)
}
// The blocklist throws away all messages from the blocked
@@ -219,7 +232,7 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
// Refresh the current list
_messages =
_messages.filter { !blockedPeerIds.contains(it.userIdForBlockList) }.toMutableList()
- messages.postValue(chatmessageViewFilterHelper.getSearchFilteredPeersIfNeeded(_messages))
+ messages.postValue(_messages)
}
}
@@ -231,4 +244,14 @@ class ChatViewModel(private val hmssdk: HMSSDK) : ViewModel() {
fun currentlySelectedRbacRecipient() : Recipient?{
return _currentlySelectedRecipient.value
}
+
+ fun updatePeerLeave(leavingPeerId : String?) {
+ if(leavingPeerId == null)
+ return
+
+ val current = _currentlySelectedRecipient.value
+ if(current is Recipient.Peer && current.peer.peerID == leavingPeerId)
+ _currentlySelectedRecipient.postValue(null)
+
+ }
}
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/Recipient.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/Recipient.kt
index 16b82bc2c..115cf18c9 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/Recipient.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/Recipient.kt
@@ -4,6 +4,9 @@ import live.hms.video.sdk.models.HMSMessageRecipient
import live.hms.video.sdk.models.HMSPeer
import live.hms.video.sdk.models.enums.HMSMessageRecipientType
import live.hms.video.sdk.models.role.HMSRole
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
sealed class Recipient {
object Everyone : Recipient() {
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/ChatRbacRecipientHandling.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/ChatRbacRecipientHandling.kt
index 62463cf9a..b9ed74025 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/ChatRbacRecipientHandling.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/ChatRbacRecipientHandling.kt
@@ -9,28 +9,34 @@ import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
import live.hms.roomkit.ui.theme.getColorOrDefault
class ChatRbacRecipientHandling {
- fun updateChipRecipientUI(sendToChipText : MaterialTextView,
- recipient: Recipient?) {
- //TODO might be able to change the UI to handle send to no one here.
- if(recipient == null)
- return
- sendToChipText.text = recipient.toString()
+ fun updateChipRecipientUI(
+ sendToChipText: MaterialTextView,
+ recipient: Recipient?
+ ) {
+
+ sendToChipText.text = recipient?.toString()
+ ?: sendToChipText.resources.getString(R.string.chat_rbac_picker_send_to)
// Set the drawable next to it
- val chevron = when(recipient) {
+ val chevron = when (recipient) {
Recipient.Everyone -> R.drawable.tiny_chip_everyone
- is Recipient.Peer,
- is Recipient.Role -> R.drawable.tiny_chip_dm
+ is Recipient.Role -> R.drawable.tiny_chip_roles
+ is Recipient.Peer -> R.drawable.tiny_chip_dm
+ null -> null
}
- sendToChipText.drawableStart = AppCompatResources.getDrawable(
- sendToChipText.context, chevron
- )?.apply {
- setTint(
- getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
- HMSPrebuiltTheme.getDefaults().onsurface_med_emp
+ sendToChipText.drawableStart = if (chevron == null) {
+ null
+ } else {
+ AppCompatResources.getDrawable(
+ sendToChipText.context, chevron
+ )?.apply {
+ setTint(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_med_emp
+ )
)
- )
+ }
}
}
}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/CombinedChatFragmentTab.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/CombinedChatFragmentTab.kt
index 2355caeea..449f6b484 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/CombinedChatFragmentTab.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/CombinedChatFragmentTab.kt
@@ -26,7 +26,7 @@ class CombinedChatFragmentTab(val dismissAllowingStateLoss: KFunction0) :
private val launchMessageOptionsDialog = LaunchMessageOptionsDialog()
private val chatAdapter by lazy { ChatAdapter({ message ->
launchMessageOptionsDialog.launch(meetingViewModel,
- childFragmentManager, message) },{}, { MessageOptionsBottomSheet.showMessageOptions(meetingViewModel)})
+ childFragmentManager, message) },{}, { message -> MessageOptionsBottomSheet.showMessageOptions(meetingViewModel, message)})
}
private val pinnedMessageUiUseCase = PinnedMessageUiUseCase()
@@ -53,18 +53,11 @@ class CombinedChatFragmentTab(val dismissAllowingStateLoss: KFunction0) :
}
- var roleChangeSingleShot = -1
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- roleChangeSingleShot = meetingViewModel.roleChangeSingleShot.value ?:0
+
binding.sendToBackground.setOnSingleClickListener {
RoleBasedChatBottomSheet.launch(childFragmentManager, chatViewModel)
}
- meetingViewModel.roleChangeSingleShot.observe(viewLifecycleOwner) {
- if(roleChangeSingleShot != it) {
- roleChangeSingleShot = it
- dismissAllowingStateLoss()
- }
- }
meetingViewModel.initPrebuiltChatMessageRecipient.observe(viewLifecycleOwner) {
chatViewModel.setInitialRecipient(it.first, it.second)
}
@@ -98,7 +91,8 @@ class CombinedChatFragmentTab(val dismissAllowingStateLoss: KFunction0) :
binding.chatExtra,
meetingViewModel.prebuiltInfoContainer::isChatEnabled,
meetingViewModel::availableRecipientsForChat,
- chatViewModel::currentlySelectedRbacRecipient
+ chatViewModel::currentlySelectedRbacRecipient,
+ chatViewModel.currentlySelectedRecipientRbac
)
meetingViewModel.broadcastsReceived.observe(viewLifecycleOwner) {
chatViewModel.receivedMessage(it)
@@ -107,6 +101,9 @@ class CombinedChatFragmentTab(val dismissAllowingStateLoss: KFunction0) :
pinnedMessageUiUseCase.messagesUpdate(pinnedMessages,
binding.pinnedMessagesDisplay)
}
+ meetingViewModel.peerLeaveUpdate.observe(viewLifecycleOwner) {
+ chatViewModel.updatePeerLeave(it)
+ }
}
}
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/LaunchMessageOptionsDialog.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/LaunchMessageOptionsDialog.kt
index 797ce0047..8a02ad694 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/LaunchMessageOptionsDialog.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/combined/LaunchMessageOptionsDialog.kt
@@ -14,10 +14,10 @@ class LaunchMessageOptionsDialog {
chatMessage: ChatMessage,
) {
// If the user can't block or pin message, hide the entire dialog.
- val allowedToBlock = meetingViewModel.isAllowedToBlockFromChat()
+ val allowedToBlock = meetingViewModel.isAllowedToBlockFromChat() && !chatMessage.isSentByMe
val allowedToPin = meetingViewModel.isAllowedToPinMessages()
val allowedToHideMessages = meetingViewModel.isAllowedToHideMessages()
- if(!MessageOptionsBottomSheet.showMessageOptions(meetingViewModel))
+ if(!MessageOptionsBottomSheet.showMessageOptions(meetingViewModel, chatMessage))
return
MessageOptionsBottomSheet(chatMessage, allowedToBlock, allowedToPin, allowedToHideMessages).apply {
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/ChatMessageViewFilterHelper.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/ChatMessageViewFilterHelper.kt
deleted file mode 100644
index 6114dfecc..000000000
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/ChatMessageViewFilterHelper.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-package live.hms.roomkit.ui.meeting.chat.rbac
-
-import live.hms.roomkit.ui.meeting.chat.ChatMessage
-import live.hms.roomkit.ui.meeting.chat.Recipient
-
-/**
- * This filter is the one which selects which peer's messages you see
- * When you select a DM vs Everyone.
- * Or a role vs Everyone.
- * If Everyone is selected that means there's no filtering.
- */
-class ChatMessageViewFilterHelper {
- private var filterRecipient : Recipient? = null
-// private var filterGroup : String? = null
- fun setFilter(recipient: Recipient?) {
- filterRecipient = recipient
- }
- private fun isSearching() = filterRecipient == Recipient.Everyone
- fun getSearchFilteredPeersIfNeeded(m : List) : List {
-
- return when(val filterTargetRecipient = filterRecipient) {
- Recipient.Everyone -> m // no change
- // Always include your own messages
- is Recipient.Peer -> m.filter {
- it.senderPeerId == filterTargetRecipient.peer.peerID || it.isSentByMe
- }
- // Always include your own messages
- is Recipient.Role -> m.filter {
- it.senderRoleName == filterTargetRecipient.role.name || it.isSentByMe
- }
- // Just receive messages even if you can't sent
- null -> m
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RecipientHeader.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RecipientHeader.kt
index 7f67d2104..c71f25463 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RecipientHeader.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RecipientHeader.kt
@@ -1,6 +1,7 @@
package live.hms.roomkit.ui.meeting.chat.rbac
import android.view.View
+import androidx.appcompat.content.res.AppCompatResources
import com.xwray.groupie.ExpandableGroup
import com.xwray.groupie.ExpandableItem
import com.xwray.groupie.viewbinding.BindableItem
@@ -8,8 +9,11 @@ import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutRoleBasedChatMessageBottomSheetItemHeaderBinding
import live.hms.roomkit.setOnSingleClickListener
import live.hms.roomkit.ui.meeting.chat.Recipient
+import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
import live.hms.roomkit.ui.theme.applyTheme
-
+import live.hms.roomkit.ui.theme.getColorOrDefault
+const val RECIPIENT_PEERS = "PARTICIPANTS"
+const val RECIPIENT_ROLES = "ROLES"
class RecipientHeader(private val recipientHeaderName: String) :
BindableItem(
recipientHeaderName.hashCode().toLong()
@@ -22,6 +26,23 @@ class RecipientHeader(private val recipientHeaderName: String) :
with(viewBinding) {
applyTheme()
name.text = recipientHeaderName
+ val headerIcon = when(recipientHeaderName) {
+ // everyone is just a recipient item not a header
+ RECIPIENT_ROLES -> R.drawable.role_rbac_icon
+ RECIPIENT_PEERS -> R.drawable.dm_rbac_icon
+ else -> R.drawable.left_arrow
+ }
+ image.setImageDrawable(
+ AppCompatResources.getDrawable(
+ viewBinding.root.context, headerIcon
+ )?.apply {
+ setTint(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_med_emp
+ )
+ )
+ })
// Don't expand/collapse right now
// root.setOnSingleClickListener {
// expandableGroup.onToggleExpanded()
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RecipientItem.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RecipientItem.kt
index f97ca1970..2c3bb3247 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RecipientItem.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RecipientItem.kt
@@ -1,12 +1,15 @@
package live.hms.roomkit.ui.meeting.chat.rbac
import android.view.View
+import androidx.appcompat.content.res.AppCompatResources
import com.xwray.groupie.viewbinding.BindableItem
import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutRoleBasedChatMessageBottomSheetItemRecipientBinding
import live.hms.roomkit.setOnSingleClickListener
import live.hms.roomkit.ui.meeting.chat.Recipient
+import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
import live.hms.roomkit.ui.theme.applyTheme
+import live.hms.roomkit.ui.theme.getColorOrDefault
class RecipientItem(private val recipient: Recipient,
private val currentSelectedRecipient: Recipient?,
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RoleBasedChatBottomSheet.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RoleBasedChatBottomSheet.kt
index e7d5f56c2..b71170f74 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RoleBasedChatBottomSheet.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/chat/rbac/RoleBasedChatBottomSheet.kt
@@ -7,6 +7,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
@@ -14,6 +15,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.xwray.groupie.ExpandableGroup
import com.xwray.groupie.Group
import com.xwray.groupie.GroupieAdapter
+import kotlinx.coroutines.launch
import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutRoleBasedChatBottomSheetSelectorBinding
import live.hms.roomkit.ui.meeting.AllowedToMessageParticipants
@@ -21,18 +23,32 @@ import live.hms.roomkit.ui.meeting.MeetingViewModel
import live.hms.roomkit.ui.meeting.MeetingViewModelFactory
import live.hms.roomkit.ui.meeting.chat.ChatViewModel
import live.hms.roomkit.ui.meeting.chat.Recipient
+import live.hms.roomkit.ui.meeting.participants.ChatRecipientSearchUseCase
import live.hms.roomkit.ui.meeting.participants.MessageHeaderItemDecoration
import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
import live.hms.roomkit.ui.theme.applyTheme
import live.hms.roomkit.ui.theme.getColorOrDefault
import live.hms.roomkit.util.viewLifecycle
import live.hms.video.sdk.HMSSDK
+import live.hms.video.signal.init.HMSRoomLayout
+import live.hms.video.sdk.models.HMSPeer
+/**
+ * The chip that lets you select who to chat with opens this.
+ * This determines what options to show based on what the role is allowed in [HMSRoomLayout].
+ * @param getSelectedRecipient the [ChatViewModel] keeps the state and knows what recipient
+ * is selected, so this fragment needs to load that info from it.
+ * @param recipientSelected if the dialog changes what recipient is selected this communicates
+ * it back to [ChatViewModel].
+ */
class RoleBasedChatBottomSheet(
private val getSelectedRecipient: () -> Recipient?,
private val recipientSelected: (Recipient) -> Unit
) : BottomSheetDialogFragment() {
+ private var initialRecipients : List = emptyList()
+ private var allowedParticipants : AllowedToMessageParticipants? = null
+ private val chatRecipientSearchUseCase : ChatRecipientSearchUseCase = ChatRecipientSearchUseCase(::updateListWithPeers)
private var binding by viewLifecycle()
private val groupieAdapter = GroupieAdapter()
@@ -80,6 +96,7 @@ class RoleBasedChatBottomSheet(
dismissAllowingStateLoss()
}
+ chatRecipientSearchUseCase.initSearchView(binding.textInputSearch, lifecycleScope)
with(binding.optionsGrid) {
adapter = groupieAdapter
layoutManager = LinearLayoutManager(context)
@@ -94,25 +111,79 @@ class RoleBasedChatBottomSheet(
)
}
+
// This would break many things if it were called when no participants were available.
// crash early to point it out.
- val allowedParticipants = meetingViewModel.availableRecipientsForChat()!!
- val initialRecipients = initialAddRecipients(allowedParticipants)
+ updateInitialRecipients()
groupieAdapter.update(initialRecipients)
- if (allowedParticipants.peers) {
- // Update all peers everytime the peers change
- meetingViewModel.participantPeerUpdate.observe(viewLifecycleOwner) {
- groupieAdapter.update(
- initialRecipients.plus(
- getUpdatedPeersGroup(
- meetingViewModel.hmsSDK, getSelectedRecipient()
- )
- )
- )
+
+ // There's no need for role change to emit the first time this runs.
+ meetingViewModel.roleChange.observe(viewLifecycleOwner) {
+ // When the role changes, the allowed participants might have changed.
+ lifecycleScope.launch {
+ updateInitialRecipients()
+ updateListWithPeers()
+ }
+ }
+ // Update all peers everytime the peers change
+ meetingViewModel.participantPeerUpdate.observe(viewLifecycleOwner) {
+ lifecycleScope.launch {
+ updateListWithPeers()
}
}
+
}
+ private suspend fun updateListWithPeers() {
+ val list = if(chatRecipientSearchUseCase.isSearching()) {
+ val filteredPeers = chatRecipientSearchUseCase
+ .getFilteredPeers(meetingViewModel.hmsSDK.getRemotePeers())
+ listOf(getUpdatedPeersGroup(
+ filteredPeers, getSelectedRecipient()
+ ))
+ } else {
+ val peers = getPeerGroup()
+ if(peers == null) {
+ initialRecipients
+ } else {
+ initialRecipients.plus(peers)
+ }
+ }
+
+ groupieAdapter.update(list)
+ // Toggle empty view
+ binding.emptyView.visibility = if (list.isEmpty())
+ View.VISIBLE
+ else
+ View.GONE
+
+ }
+
+ private fun updateInitialRecipients() {
+ allowedParticipants = meetingViewModel.availableRecipientsForChat()
+ initialRecipients = initialAddRecipients(getAllowedParticipants())
+ chatRecipientSearchUseCase.setSearchVisibility(binding.containerSearch, getAllowedParticipants())
+ }
+
+ private fun getAllowedParticipants() = allowedParticipants!!
+ private fun getInitialRecipients() = initialRecipients
+
+ private fun getPeerGroup(): ExpandableGroup? {
+ return if (getAllowedParticipants().peers) {
+ val peers = meetingViewModel.hmsSDK.getRemotePeers()
+ // Remove the "participants" option if there are no others.
+ if (peers.isEmpty())
+ null
+ else
+ getUpdatedPeersGroup(
+ peers, getSelectedRecipient()
+ )
+ } else {
+ null
+ }
+ }
+
+
private fun onRecipientSelected(recipient: Recipient) {
recipientSelected(recipient)
dismissAllowingStateLoss()
@@ -147,7 +218,7 @@ class RoleBasedChatBottomSheet(
)
}
// Separate headers and roles
- val rolesGroup = ExpandableGroup(RecipientHeader("ROLES"), true).apply {
+ val rolesGroup = ExpandableGroup(RecipientHeader(RECIPIENT_ROLES), true).apply {
addAll(rolesToAdd)
}
recipients.add(rolesGroup)
@@ -157,12 +228,12 @@ class RoleBasedChatBottomSheet(
}
private fun getUpdatedPeersGroup(
- hmsSDK: HMSSDK,
+ peers : List,
currentSelectedRecipient: Recipient?
): ExpandableGroup {
- return ExpandableGroup(RecipientHeader("PARTICIPANTS"), true).apply {
+ return ExpandableGroup(RecipientHeader(RECIPIENT_PEERS), true).apply {
addAll(
- hmsSDK.getRemotePeers().map {
+ peers.map {
RecipientItem(
Recipient.Peer(it),
currentSelectedRecipient,
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ChatRecipientSearchUseCase.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ChatRecipientSearchUseCase.kt
new file mode 100644
index 000000000..c456950d9
--- /dev/null
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ChatRecipientSearchUseCase.kt
@@ -0,0 +1,35 @@
+package live.hms.roomkit.ui.meeting.participants
+
+import android.view.View
+import android.widget.EditText
+import androidx.core.widget.addTextChangedListener
+import androidx.lifecycle.LifecycleCoroutineScope
+import com.google.android.material.card.MaterialCardView
+import com.google.android.material.textfield.TextInputEditText
+import kotlinx.coroutines.launch
+import live.hms.roomkit.ui.meeting.AllowedToMessageParticipants
+import live.hms.video.sdk.models.HMSPeer
+
+class ChatRecipientSearchUseCase(private val updateList : suspend () -> Unit) {
+ private var filterText : String? = null
+ fun isSearching() = !filterText.isNullOrEmpty()
+ fun setSearchVisibility(containerSearch : MaterialCardView,
+ allowedToMessageParticipants: AllowedToMessageParticipants) {
+ containerSearch.visibility = if(allowedToMessageParticipants.peers) View.VISIBLE else View.GONE
+ }
+ fun initSearchView(textInputSearch : EditText, scope : LifecycleCoroutineScope) {
+ textInputSearch.apply {
+ addTextChangedListener { text ->
+ scope.launch {
+ filterText = text.toString()
+ updateList()
+ }
+ }
+ }
+ }
+
+ fun getFilteredPeers(remotePeers : List) : List {
+ val filterText = filterText ?: return remotePeers
+ return remotePeers.filter { it.name.contains(filterText, ignoreCase = true) }
+ }
+}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsTabFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsTabFragment.kt
index f4372ccbb..24b339033 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsTabFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsTabFragment.kt
@@ -16,6 +16,7 @@ import live.hms.roomkit.databinding.LayoutParticipantsMergeBinding
import live.hms.roomkit.ui.meeting.MeetingState
import live.hms.roomkit.ui.meeting.MeetingViewModel
import live.hms.roomkit.ui.meeting.MeetingViewModelFactory
+import live.hms.roomkit.ui.theme.applyTheme
import live.hms.roomkit.util.viewLifecycle
class ParticipantsTabFragment(val dismissFragment: () -> Unit) : Fragment() {
@@ -45,7 +46,7 @@ class ParticipantsTabFragment(val dismissFragment: () -> Unit) : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
-// binding.applyTheme()
+ binding.applyTheme()
initViewModels()
initOnBackPress()
initViews()
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsUseCase.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsUseCase.kt
index e7253651e..723dcee16 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsUseCase.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/participants/ParticipantsUseCase.kt
@@ -1,5 +1,6 @@
package live.hms.roomkit.ui.meeting.participants
+import android.widget.EditText
import androidx.core.content.res.ResourcesCompat
import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.LifecycleCoroutineScope
@@ -108,7 +109,7 @@ class ParticipantsUseCase(val meetingViewModel: MeetingViewModel,
}
}
- fun initSearchView(textInputSearch : TextInputEditText, scope : LifecycleCoroutineScope) {
+ fun initSearchView(textInputSearch : EditText, scope : LifecycleCoroutineScope) {
textInputSearch.apply {
addTextChangedListener { text ->
scope.launch {
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionViewHolder.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionViewHolder.kt
index b86fadf25..2a873fc3a 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionViewHolder.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollQuestionViewHolder.kt
@@ -2,6 +2,7 @@ package live.hms.roomkit.ui.polls
import android.text.Editable
import android.text.TextWatcher
+import android.util.Log
import android.view.View
import android.widget.AdapterView
import android.widget.AdapterView.OnItemSelectedListener
@@ -123,11 +124,19 @@ class PollQuestionViewHolder(
it.onOptionTextChanged = { optionIndex, changedText ->
val question =
getItem(bindingAdapterPosition).currentQuestion as QuestionUi.ChoiceQuestions
- val changedList: List = question.options.toMutableList().apply {
- this[optionIndex] = changedText
+ val options = question.options
+ if(optionIndex >= options.size)
+ Log.e(TAG,"Skip invalid index change")
+ else {
+ val changedList: List = options.toMutableList().apply {
+ this[optionIndex] = changedText
+ }
+ question.options = changedList
+ validateSaveButtonEnabledState(
+ getItem(bindingAdapterPosition),
+ binding.saveButton
+ )
}
- question.options = changedList
- validateSaveButtonEnabledState(getItem(bindingAdapterPosition), binding.saveButton)
}
it.onSingleOptionSelected = { position ->
updateSelection(bindingAdapterPosition, listOf(position), null)
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollsCreationFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollsCreationFragment.kt
index 8a44b401c..767e1df30 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollsCreationFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/PollsCreationFragment.kt
@@ -16,6 +16,7 @@ import live.hms.roomkit.databinding.LayoutPollsCreationBinding
import live.hms.roomkit.ui.meeting.MeetingState
import live.hms.roomkit.ui.meeting.MeetingViewModel
import live.hms.roomkit.ui.polls.display.PollDisplayFragment
+import live.hms.roomkit.ui.polls.leaderboard.LeaderBoardBottomSheetFragment
import live.hms.roomkit.ui.polls.previous.PreviousPollsAdaptor
import live.hms.roomkit.ui.polls.previous.PreviousPollsInfo
import live.hms.roomkit.ui.theme.applyTheme
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayFragment.kt
index 16681d5ad..8a33e9553 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayFragment.kt
@@ -18,6 +18,7 @@ import kotlinx.coroutines.launch
import live.hms.roomkit.R
import live.hms.roomkit.databinding.LayoutPollsDisplayBinding
import live.hms.roomkit.ui.meeting.MeetingViewModel
+import live.hms.roomkit.ui.polls.leaderboard.LeaderBoardBottomSheetFragment
import live.hms.roomkit.ui.theme.applyTheme
import live.hms.roomkit.ui.theme.pollsStatusLiveDraftEnded
import live.hms.roomkit.util.setOnSingleClickListener
@@ -84,7 +85,7 @@ class PollDisplayFragment : BottomSheetDialogFragment() {
meetingViewModel::saveInfoMultiChoice,
meetingViewModel::saveSkipped,
meetingViewModel::endPoll
- )
+ ) { LeaderBoardBottomSheetFragment.launch(it, requireFragmentManager()) }
poll = returnedPoll
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayQuestionHolder.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayQuestionHolder.kt
index 1d3b9da39..c0ddcd06c 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayQuestionHolder.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollDisplayQuestionHolder.kt
@@ -7,9 +7,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import live.hms.roomkit.R
-import live.hms.roomkit.databinding.GoLiveBottomSheetBinding
import live.hms.roomkit.databinding.LayoutEndPollButtonBinding
-import live.hms.roomkit.databinding.LayoutLaunchPollButtonBinding
import live.hms.roomkit.databinding.LayoutPollsDisplayChoicesQuesionBinding
import live.hms.roomkit.databinding.LayoutQuizDisplayShortAnswerBinding
import live.hms.roomkit.drawableStart
@@ -38,6 +36,7 @@ class PollDisplayQuestionHolder(
val skipped : (question : HMSPollQuestion, poll : HmsPoll) -> Unit,
val endPoll : (HmsPoll) -> Unit,
val canEndPoll : Boolean,
+ val showLeaderBoard: (pollId: String) -> Unit,
) : RecyclerView.ViewHolder(binding.root) {
private val adapter = AnswerOptionsAdapter(canRoleViewVotes) { answersSelected ->
@@ -65,8 +64,9 @@ class PollDisplayQuestionHolder(
}
}
else {
+ //todd
with(binding as LayoutEndPollButtonBinding) {
- launchPollQuiz.text = "End Poll"
+ launchPollQuiz.text = if (poll.category == HmsPollCategory.QUIZ) "End Quiz" else "End Poll"
if(poll.state == HmsPollState.STARTED && canEndPoll) {
launchPollQuiz.alertButtonEnabled()
launchPollQuiz.setOnClickListener {
@@ -76,6 +76,16 @@ class PollDisplayQuestionHolder(
} else {
binding.root.visibility = View.GONE
}
+
+ if (poll.state == HmsPollState.STOPPED && poll.category == HmsPollCategory.QUIZ) {
+ binding.root.visibility = View.VISIBLE
+ launchPollQuiz.text = "View Results"
+ launchPollQuiz.buttonEnabled()
+ launchPollQuiz.setOnClickListener {
+ showLeaderBoard(poll.pollId)
+ }
+ binding.root.visibility = View.VISIBLE
+ }
}
}
}
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollsDisplayAdaptor.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollsDisplayAdaptor.kt
index 1897e3c82..02a5f7c6f 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollsDisplayAdaptor.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/display/PollsDisplayAdaptor.kt
@@ -2,12 +2,10 @@ package live.hms.roomkit.ui.polls.display
import android.view.LayoutInflater
import android.view.ViewGroup
-import androidx.core.graphics.drawable.DrawableCompat.applyTheme
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.viewbinding.ViewBinding
import live.hms.roomkit.databinding.LayoutEndPollButtonBinding
-import live.hms.roomkit.databinding.LayoutLaunchPollButtonBinding
import live.hms.roomkit.databinding.LayoutPollsDisplayChoicesQuesionBinding
import live.hms.roomkit.databinding.LayoutQuizDisplayShortAnswerBinding
import live.hms.roomkit.ui.theme.applyTheme
@@ -52,6 +50,7 @@ class PollsDisplayAdaptor(
val saveInfoMultiChoice : (question : HMSPollQuestion, List?, hmsPoll : HmsPoll) -> Boolean,
val skipped : (question : HMSPollQuestion, poll : HmsPoll) -> Unit,
val endPoll : (HmsPoll) -> Unit,
+ val showLeaderBoard : (pollId : String) -> Unit,
) : ListAdapter>(
DIFFUTIL_CALLBACK
) {
@@ -103,7 +102,7 @@ class PollsDisplayAdaptor(
EndPollViewType -> LayoutEndPollButtonBinding.inflate(LayoutInflater.from(parent.context), parent, false)
else -> null
}
- val questionHolder = PollDisplayQuestionHolder(view!!, canViewResponses(getPoll, localPeer), getPoll, ::setTextAnswer, saveInfoSingleChoice, saveInfoMultiChoice, skipped, endPoll, getPoll.createdBy?.peerID == localPeer.peerID)
+ val questionHolder = PollDisplayQuestionHolder(view!!, canViewResponses(getPoll, localPeer), getPoll, ::setTextAnswer, saveInfoSingleChoice, saveInfoMultiChoice, skipped, endPoll, getPoll.createdBy?.peerID == localPeer.peerID, showLeaderBoard)
if(viewType == HMSPollQuestionType.multiChoice.ordinal || viewType == HMSPollQuestionType.singleChoice.ordinal) {
updater.add(questionHolder)
}
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/LeaderBoardBottomSheetFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/LeaderBoardBottomSheetFragment.kt
new file mode 100644
index 000000000..62d5350ef
--- /dev/null
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/LeaderBoardBottomSheetFragment.kt
@@ -0,0 +1,209 @@
+package live.hms.roomkit.ui.polls.leaderboard
+
+import android.app.Dialog
+import android.content.res.Resources
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.FragmentManager
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.GridLayoutManager
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetDialog
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment
+import com.xwray.groupie.GroupieAdapter
+import kotlinx.coroutines.launch
+import live.hms.roomkit.R
+import live.hms.roomkit.databinding.LayoutChatParticipantCombinedBinding
+import live.hms.roomkit.databinding.LayoutQuizLeaderboardBinding
+import live.hms.roomkit.ui.meeting.InsetItemDecoration
+import live.hms.roomkit.ui.meeting.MeetingViewModel
+import live.hms.roomkit.ui.polls.display.POLL_TO_DISPLAY
+import live.hms.roomkit.ui.polls.display.PollDisplayFragment
+import live.hms.roomkit.ui.polls.leaderboard.item.ApplyRadiusatVertex
+import live.hms.roomkit.ui.polls.leaderboard.item.LeaderBoardHeader
+import live.hms.roomkit.ui.polls.leaderboard.item.LeaderBoardNameSection
+import live.hms.roomkit.ui.polls.leaderboard.item.LeaderBoardSubGrid
+import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
+import live.hms.roomkit.ui.theme.applyTheme
+import live.hms.roomkit.ui.theme.getColorOrDefault
+import live.hms.roomkit.util.contextSafe
+import live.hms.roomkit.util.viewLifecycle
+import live.hms.video.error.HMSException
+import live.hms.video.polls.models.HmsPoll
+import live.hms.video.polls.network.PollLeaderboardResponse
+import live.hms.video.sdk.HmsTypedActionResultListener
+
+
+class LeaderBoardBottomSheetFragment : BottomSheetDialogFragment() {
+
+ private var binding by viewLifecycle()
+ private val meetingViewModel: MeetingViewModel by activityViewModels()
+ var poll: HmsPoll? = null
+
+ val leaderBoardListadapter = GroupieAdapter()
+
+
+ companion object {
+ const val TAG: String = "LeaderBoardBottomSheetFragment"
+ fun launch(pollId: String, fm: FragmentManager) {
+ val args = Bundle().apply {
+ putString(POLL_TO_DISPLAY, pollId)
+ }
+
+ LeaderBoardBottomSheetFragment().apply { arguments = args }.show(
+ fm, PollDisplayFragment.TAG
+ )
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+ ): View {
+ binding = LayoutQuizLeaderboardBinding.inflate(inflater, container, false)
+ .also { it.applyTheme() }
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ dialog?.let {
+ val sheet = it as BottomSheetDialog
+ sheet.behavior.skipCollapsed = true
+ sheet.behavior.peekHeight = Resources.getSystem().displayMetrics.heightPixels
+ sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
+ }
+
+
+ lifecycleScope.launch {
+ val pollId: String =
+ (arguments?.getString(POLL_TO_DISPLAY) ?: dismissAllowingStateLoss()).toString()
+ poll = meetingViewModel.getPollForPollId(pollId)
+ leaderBoardListadapter.spanCount = 12
+
+ binding.backButton.setOnClickListener { dismissAllowingStateLoss() }
+ binding.closeBtn.setOnClickListener { dismissAllowingStateLoss() }
+ binding.leaderboardRecyclerView.apply {
+ adapter = leaderBoardListadapter
+ layoutManager = GridLayoutManager(context, leaderBoardListadapter.spanCount).apply {
+ spanSizeLookup = leaderBoardListadapter.spanSizeLookup
+ }
+ addItemDecoration(
+ InsetItemDecoration(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.backgroundDefault,
+ HMSPrebuiltTheme.getDefaults().background_default
+ ), resources.getDimension(R.dimen.twelve_dp).toInt(), "inset", "inset"
+ )
+ )
+
+ }
+
+ meetingViewModel.fetchLeaderboard(pollId,
+ object : HmsTypedActionResultListener {
+ override fun onSuccess(result: PollLeaderboardResponse) {
+ contextSafe { context, activity ->
+ activity.runOnUiThread {
+ binding.heading.text = poll?.title
+ loadList(result)
+ }
+ }
+ }
+
+ override fun onError(error: HMSException) {
+ contextSafe { _, activity ->
+ Toast.makeText(
+ activity,
+ "Error fetching leaderboard ${error.localizedMessage}",
+ Toast.LENGTH_SHORT
+ ).show()
+ dismissAllowingStateLoss()
+ }
+ }
+
+ })
+ }
+ }
+
+ fun loadList(model: PollLeaderboardResponse) {
+ leaderBoardListadapter.clear()
+
+ val isAverageTimeEmpty =
+ model.summary?.averageTime == null
+ val isAverageScoreEmpty =
+ model.summary?.averageScore == null
+ val isCorrectAnswerEmpty =
+ model.summary?.respondedCorrectlyPeersCount == null
+ val isTotalPeerCountEmpty =
+ model.summary?.totalPeersCount == null || model.summary?.totalPeersCount == 0
+
+
+ if (isAverageScoreEmpty.not() || isAverageTimeEmpty.not() || isCorrectAnswerEmpty.not() || isTotalPeerCountEmpty.not()) {
+ leaderBoardListadapter.add(LeaderBoardHeader("Participation Summary"))
+ }
+
+ if (model.summary != null) with(model.summary!!) {
+ if (isTotalPeerCountEmpty.not()) {
+ leaderBoardListadapter.add(
+ LeaderBoardSubGrid(
+ "VOTED",
+ "${(((respondedPeersCount?.toFloat()?:1f)/(totalPeersCount?.toFloat()?:1f)) * 100.0f).toInt()}% (${(respondedPeersCount ?: 0)}/${(totalPeersCount ?: 0)})"
+ )
+ )
+ }
+
+ if (isCorrectAnswerEmpty.not()) {
+ leaderBoardListadapter.add(
+ LeaderBoardSubGrid(
+ "CORRECT ANSWERS", "${(((respondedCorrectlyPeersCount?.toFloat()?:1f)/(totalPeersCount?.toFloat()?:1f)) * 100.0f).toInt()}% (${(respondedCorrectlyPeersCount ?: 0)}/${(totalPeersCount ?: 0)})"
+ )
+ )
+ }
+ if (isAverageTimeEmpty.not()) {
+ leaderBoardListadapter.add(
+ LeaderBoardSubGrid(
+ "AVG. TIME TAKEN", "${averageTime?.toInt().toString()} sec"
+ )
+ )
+ }
+
+ if (isAverageScoreEmpty.not()) {
+ leaderBoardListadapter.add(
+ LeaderBoardSubGrid(
+ "AVG. SCORE", averageScore.toString()
+ )
+ )
+ }
+ }
+
+
+ if (model.entries.isNullOrEmpty().not()) {
+ leaderBoardListadapter.add(LeaderBoardHeader("Leaderboard"))
+
+ val rankTOColorMap = mapOf(
+ "1" to "#D69516", "2" to "#3E3E3E", "3" to "#583B0F"
+ )
+ model.entries?.forEachIndexed { index, entry ->
+ leaderBoardListadapter.add(
+ LeaderBoardNameSection(
+ titleStr = entry.peer?.username.orEmpty(),
+ subtitleStr = "${entry.score}/${poll?.questions?.map { it.weight }?.toList()?.sum()?:0} points",
+ rankStr = entry.position.toString(),
+ isSelected = true,
+ timetakenStr = "${if (entry.duration == 0L) "" else entry.duration}",
+ correctAnswerStr = "${entry.correctResponses}/${poll?.questions?.size ?: 0}",
+ position = if (index == 0) ApplyRadiusatVertex.TOP
+ else if (index == model.entries?.size?.minus(1)) ApplyRadiusatVertex.BOTTOM
+ else ApplyRadiusatVertex.NONE,
+ rankBackGroundColor = rankTOColorMap.getOrDefault(entry.position.toString(), HMSPrebuiltTheme.getColours()?.secondaryDefault)
+ )
+ )
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardHeader.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardHeader.kt
new file mode 100644
index 000000000..c54a40c22
--- /dev/null
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardHeader.kt
@@ -0,0 +1,34 @@
+package live.hms.roomkit.ui.polls.leaderboard.item
+
+import android.view.View
+import com.xwray.groupie.ExpandableGroup
+import com.xwray.groupie.ExpandableItem
+import com.xwray.groupie.viewbinding.BindableItem
+import live.hms.roomkit.R
+import live.hms.roomkit.databinding.LayoutHeaderBinding
+import live.hms.roomkit.databinding.LayoutRoleBasedChatMessageBottomSheetItemHeaderBinding
+import live.hms.roomkit.ui.theme.applyTheme
+
+class LeaderBoardHeader(private val titlestr: String, private val subtitle: String = "") :
+ BindableItem() {
+
+ override fun bind(
+ viewBinding: LayoutHeaderBinding, position: Int
+ ) {
+ with(viewBinding) {
+ this.title.text = titlestr
+
+ if (subtitle.isEmpty()) this.subheading.visibility = View.GONE
+ else this.subheading.visibility = View.VISIBLE
+ this.subheading.text = subtitle
+ applyTheme()
+ }
+ }
+
+ override fun getLayout(): Int = R.layout.layout_header
+
+
+ override fun initializeViewBinding(view: View): LayoutHeaderBinding =
+ LayoutHeaderBinding.bind(view)
+
+}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardNameSection.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardNameSection.kt
new file mode 100644
index 000000000..12cdeae9c
--- /dev/null
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardNameSection.kt
@@ -0,0 +1,104 @@
+package live.hms.roomkit.ui.polls.leaderboard.item
+
+import android.view.View
+import com.xwray.groupie.viewbinding.BindableItem
+import live.hms.roomkit.R
+import live.hms.roomkit.databinding.ItemNameSectionBinding
+import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
+import live.hms.roomkit.ui.theme.applyTheme
+import live.hms.roomkit.ui.theme.getColorOrDefault
+import live.hms.roomkit.ui.theme.getShape
+import live.hms.roomkit.ui.theme.setBackgroundAndColor
+
+enum class ApplyRadiusatVertex {
+ TOP,
+ ALL_CORNERS,
+ BOTTOM,
+ NONE
+}
+class LeaderBoardNameSection(
+ private val titleStr: String,
+ private val subtitleStr: String,
+ private val rankStr: String,
+ private val timetakenStr: String? = null,
+ private val correctAnswerStr: String? = null,
+ private val isSelected: Boolean,
+ private val position: ApplyRadiusatVertex = ApplyRadiusatVertex.NONE,
+ private val rankBackGroundColor: String? = HMSPrebuiltTheme.getColours()?.secondaryDefault,
+) : BindableItem() {
+
+
+ override fun bind(viewBinding: ItemNameSectionBinding, position: Int) {
+ //themes
+ setSelectedView(isSelected, viewBinding)
+
+
+ with(viewBinding) {
+ applyTheme()
+ heading.text = titleStr
+ subtitle.text = subtitleStr
+
+ if ((rankStr == "0").not())
+ rank.text = rankStr
+ else
+ rank.text = "-"
+
+ if (timetakenStr.isNullOrEmpty().not()) {
+ timeTaken.visibility = View.VISIBLE
+ timeTaken.text = "${timetakenStr.toString()}s"
+ } else {
+ timeTaken.visibility = View.GONE
+ }
+
+ if (correctAnswerStr.isNullOrEmpty().not()) {
+ correctAnswer.visibility = View.VISIBLE
+ correctAnswer.text = correctAnswerStr.toString()
+ } else {
+ correctAnswer.visibility = View.GONE
+ }
+
+ if (rankStr == "1")
+ trophyicon.visibility = View.VISIBLE
+ else
+ trophyicon.visibility = View.GONE
+
+ rank.setBackgroundAndColor(
+ rankBackGroundColor,
+ HMSPrebuiltTheme.getDefaults().secondary_default,
+ R.drawable.circle_secondary_80
+ )
+
+
+ }
+ }
+
+ private fun setSelectedView(isSelected: Boolean, v: ItemNameSectionBinding) {
+ v.rootLayout.background = if (isSelected.not()) {
+ getShape(position).apply {
+ setTint(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.backgroundDefault,
+ HMSPrebuiltTheme.getDefaults().background_default
+ )
+ )
+ }
+ } else {
+ getShape(position).apply {
+ setTint(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.surfaceDefault,
+ HMSPrebuiltTheme.getDefaults().surface_bright,
+ )
+ )
+ }
+ }
+ }
+
+
+ override fun getLayout(): Int = R.layout.item_name_section
+
+
+
+ override fun initializeViewBinding(view: View) = ItemNameSectionBinding.bind(view)
+
+}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardSubGrid.kt b/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardSubGrid.kt
new file mode 100644
index 000000000..1bcfacd63
--- /dev/null
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/polls/leaderboard/item/LeaderBoardSubGrid.kt
@@ -0,0 +1,37 @@
+package live.hms.roomkit.ui.polls.leaderboard.item
+
+import android.view.View
+import androidx.annotation.DrawableRes
+import com.xwray.groupie.viewbinding.BindableItem
+import live.hms.roomkit.R
+import live.hms.roomkit.databinding.ItemGridOptionBinding
+import live.hms.roomkit.databinding.ItemGridSubTextBinding
+import live.hms.roomkit.ui.theme.HMSPrebuiltTheme
+import live.hms.roomkit.ui.theme.applyTheme
+import live.hms.roomkit.ui.theme.getColorOrDefault
+import live.hms.roomkit.ui.theme.getShape
+
+class LeaderBoardSubGrid(
+ private var title: String, private var subtitle: String
+) : BindableItem() {
+
+
+ override fun bind(viewBinding: ItemGridSubTextBinding, position: Int) {
+ //themes
+ viewBinding.applyTheme()
+ viewBinding.subtitle.text = subtitle
+ viewBinding.heading.text = title
+
+
+ }
+
+
+ override fun getLayout(): Int = R.layout.item_grid_sub_text
+
+ override fun getSpanSize(spanCount: Int, position: Int): Int {
+ return spanCount / 2
+ }
+
+ override fun initializeViewBinding(view: View) = ItemGridSubTextBinding.bind(view)
+
+}
\ No newline at end of file
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/settings/SettingsFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/settings/SettingsFragment.kt
index dee6fac5f..7b7ed6949 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/settings/SettingsFragment.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/settings/SettingsFragment.kt
@@ -9,7 +9,6 @@ import android.widget.AutoCompleteTextView
import androidx.appcompat.app.AlertDialog
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
-import androidx.navigation.fragment.navArgs
import com.google.android.material.switchmaterial.SwitchMaterial
import com.google.android.material.textfield.TextInputEditText
import com.google.android.material.textfield.TextInputLayout
@@ -70,7 +69,6 @@ class SettingsFragment : Fragment() {
}
private var binding by viewLifecycle()
- private val args: SettingsFragmentArgs by navArgs()
private lateinit var settings: SettingsStore
private lateinit var commitHelper: SettingsStore.MultiCommitHelper
@@ -84,7 +82,7 @@ class SettingsFragment : Fragment() {
binding = FragmentSettingsBinding.inflate(inflater, container, false)
settings = SettingsStore(requireContext())
commitHelper = settings.MultiCommitHelper()
- mode = args.mode
+ mode = SettingsMode.HOME // Do not open this in meetings.
initEditTexts()
initAutoCompleteViews()
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/settings/SettingsMode.kt b/room-kit/src/main/java/live/hms/roomkit/ui/settings/SettingsMode.kt
index dd1223ed6..c29b62d5e 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/settings/SettingsMode.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/settings/SettingsMode.kt
@@ -1,5 +1,8 @@
package live.hms.roomkit.ui.settings
+import androidx.annotation.Keep
+
+@Keep
enum class SettingsMode {
HOME,
MEETING,
diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/theme/ThemeExt.kt b/room-kit/src/main/java/live/hms/roomkit/ui/theme/ThemeExt.kt
index 96c02ce20..a7452fe3b 100644
--- a/room-kit/src/main/java/live/hms/roomkit/ui/theme/ThemeExt.kt
+++ b/room-kit/src/main/java/live/hms/roomkit/ui/theme/ThemeExt.kt
@@ -9,6 +9,7 @@ import android.graphics.drawable.shapes.RoundRectShape
import android.view.View
import android.view.ViewGroup
import android.widget.Button
+import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
@@ -37,6 +38,7 @@ import live.hms.roomkit.drawableLeft
import live.hms.roomkit.drawableStart
import live.hms.roomkit.setGradient
import live.hms.roomkit.ui.meeting.participants.EnabledMenuOptions
+import live.hms.roomkit.ui.polls.leaderboard.item.ApplyRadiusatVertex
import live.hms.roomkit.util.EmailUtils
import live.hms.roomkit.util.EmailUtils.addAlpha
import live.hms.roomkit.util.dp
@@ -1589,9 +1591,20 @@ internal fun LayoutChatParticipantCombinedBinding.applyTheme(hideParticipantTab
}
-fun getShape(): ShapeDrawable {
+fun getShape(radiusAt : ApplyRadiusatVertex = ApplyRadiusatVertex.ALL_CORNERS): ShapeDrawable {
val eightDp = 8.dp().toFloat()
- val lines = floatArrayOf(eightDp,eightDp,eightDp,eightDp,eightDp,eightDp,eightDp,eightDp,eightDp)
+
+ val lines = floatArrayOf(
+ if(radiusAt == ApplyRadiusatVertex.TOP || radiusAt == ApplyRadiusatVertex.ALL_CORNERS) eightDp else 0f,
+ if(radiusAt == ApplyRadiusatVertex.TOP || radiusAt == ApplyRadiusatVertex.ALL_CORNERS) eightDp else 0f,
+ if(radiusAt == ApplyRadiusatVertex.TOP || radiusAt == ApplyRadiusatVertex.ALL_CORNERS) eightDp else 0f,
+ if(radiusAt == ApplyRadiusatVertex.TOP || radiusAt == ApplyRadiusatVertex.ALL_CORNERS) eightDp else 0f,
+ if(radiusAt == ApplyRadiusatVertex.BOTTOM || radiusAt == ApplyRadiusatVertex.ALL_CORNERS) eightDp else 0f,
+ if(radiusAt == ApplyRadiusatVertex.BOTTOM || radiusAt == ApplyRadiusatVertex.ALL_CORNERS) eightDp else 0f,
+ if(radiusAt == ApplyRadiusatVertex.BOTTOM || radiusAt == ApplyRadiusatVertex.ALL_CORNERS) eightDp else 0f,
+ if(radiusAt == ApplyRadiusatVertex.BOTTOM || radiusAt == ApplyRadiusatVertex.ALL_CORNERS) eightDp else 0f
+ )
+
return ShapeDrawable(
RoundRectShape(
lines, null,
@@ -1665,27 +1678,30 @@ private fun configureChatControlsTheme(
)
)
- sendToBackground.strokeColor = getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.borderBright,
- HMSPrebuiltTheme.getDefaults().border_bright
- )
- sendToBackground.setBackgroundColor(
- getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.surfaceDefault,
- HMSPrebuiltTheme.getDefaults().surface_default
- )
- )
+ sendToBackground.background = getShape().apply {
+ val color = getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.primaryDefault,
+ HMSPrebuiltTheme.getDefaults().primary_default)
+ colorFilter =
+ BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, BlendModeCompat.SRC)
+ }
sendToChipText.setTextColor(
getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
- HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ HMSPrebuiltTheme.getColours()?.onPrimaryHigh,
+ HMSPrebuiltTheme.getDefaults().onprimary_high_emp
)
)
+ sendToBackground.strokeWidth = 0
+// sendToBackground.strokeColor = getColorOrDefault(
+// HMSPrebuiltTheme.getColours()?.borderBright,
+// HMSPrebuiltTheme.getDefaults().border_bright
+// )
+
sendToChipText.drawableEnd?.setTint(
getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
- HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ HMSPrebuiltTheme.getColours()?.onPrimaryHigh,
+ HMSPrebuiltTheme.getDefaults().onprimary_high_emp
)
)
}
@@ -1742,16 +1758,12 @@ internal fun ListItemChatBinding.applyTheme() {
HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
HMSPrebuiltTheme.getDefaults().onsurface_high_emp))
time.setTextColor(getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
- HMSPrebuiltTheme.getDefaults().onsurface_med_emp))
-
- toGroup.setTextColor(getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
- HMSPrebuiltTheme.getDefaults().onsurface_high_emp))
+ HMSPrebuiltTheme.getColours()?.onSurfaceLow,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp))
sentTo.setTextColor(getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
- HMSPrebuiltTheme.getDefaults().onsurface_high_emp))
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_med_emp))
}
internal fun HlsFragmentLayoutBinding.applyTheme() {
@@ -1826,8 +1838,7 @@ internal fun FragmentParticipantsBinding.applyTheme() {
}
internal fun LayoutParticipantsMergeBinding.applyTheme() {
- containerSearch.applyTheme()
- textInputSearch.applyTheme()
+ searchViewTheme(containerSearch, textInputSearch)
}
private fun backgroundShape(inset: Boolean = false, innerRadii : Float = 8.dp().toFloat()): ShapeDrawable {
val lines = floatArrayOf(
@@ -2213,6 +2224,34 @@ fun MaterialCardView.isSelectedStroke(isSelected : Boolean) {
}
+fun LayoutQuizLeaderboardBinding.applyTheme() {
+ backButton.backgroundTintList =
+ ColorStateList.valueOf(getColorOrDefault(HMSPrebuiltTheme.getColours()?.onSurfaceMedium, HMSPrebuiltTheme.getDefaults().onsurface_med_emp))
+ heading.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
+ HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ )
+ )
+ closeBtn.backgroundTintList =
+ ColorStateList.valueOf(getColorOrDefault(HMSPrebuiltTheme.getColours()?.onSurfaceMedium, HMSPrebuiltTheme.getDefaults().onsurface_med_emp))
+
+ root.setBackgroundColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.surfaceDim,
+ HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ )
+ )
+ pollsLive.setTextColor(getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
+ HMSPrebuiltTheme.getDefaults().onprimary_high_emp
+ ))
+ pollsLive.setBackgroundColor(getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.surfaceDefault,
+ HMSPrebuiltTheme.getDefaults().error_default
+ ))
+}
+
fun LayoutPollsDisplayBinding.applyTheme() {
backButton.backgroundTintList =
@@ -2237,6 +2276,106 @@ fun LayoutPollsDisplayBinding.applyTheme() {
HMSPrebuiltTheme.getColours()?.alertErrorDefault,
HMSPrebuiltTheme.getDefaults().error_default
))
+}
+
+fun LayoutHeaderBinding.applyTheme() {
+ subheading.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceLow,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp
+ )
+ )
+
+ root.setBackgroundColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.surfaceDim,
+ HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ )
+ )
+ title.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
+ HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ )
+ )
+
+}
+
+fun ItemGridSubTextBinding.applyTheme() {
+ subtitle.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp
+ )
+ )
+
+ heading.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
+ HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ )
+ )
+
+ rootLayout.background = getShape().apply {
+ setTint(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.surfaceDefault,
+ HMSPrebuiltTheme.getDefaults().surface_bright,
+ )
+ )
+ }
+
+
+}
+
+fun ItemNameSectionBinding.applyTheme() {
+
+ subtitle.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp
+ )
+ )
+
+ correctAnswer.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp
+ )
+ )
+
+ correctAnswer.drawableStart?.setTint(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp
+ )
+ )
+
+ timeTaken.drawableStart?.setTint(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp
+ )
+ )
+
+ timeTaken.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp
+ )
+ )
+
+ heading.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
+ HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ )
+ )
+
+
+
+
+
}
fun LayoutPollsDisplayChoicesQuesionBinding.applyTheme() {
@@ -2656,7 +2795,33 @@ fun BottomSheetMessageOptionsBinding.applyTheme() {
)
}
+private fun searchViewTheme(containerSearch : MaterialCardView, textInputSearch : EditText) {
+
+ textInputSearch.setTextColor(getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
+ HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ ))
+ textInputSearch.setHintTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_med_emp
+ )
+ )
+ textInputSearch.setBackgroundColor(getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.surfaceDim,
+ HMSPrebuiltTheme.getDefaults().surface_dim
+ ))
+ textInputSearch.drawableStart?.setTint(getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceMedium,
+ HMSPrebuiltTheme.getDefaults().onsurface_med_emp
+ ))
+ containerSearch.strokeWidth = 1.dp()
+ containerSearch.strokeColor = getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.borderBright,
+ HMSPrebuiltTheme.getDefaults().border_bright
+ )
+}
fun LayoutRoleBasedChatBottomSheetSelectorBinding.applyTheme() {
root.background = dialogBackground(this.root.resources)
border5.setBackgroundColor(
@@ -2665,7 +2830,13 @@ fun LayoutRoleBasedChatBottomSheetSelectorBinding.applyTheme() {
HMSPrebuiltTheme.getDefaults().border_bright
)
)
-
+ emptyView.setTextColor(
+ getColorOrDefault(
+ HMSPrebuiltTheme.getColours()?.onSurfaceLow,
+ HMSPrebuiltTheme.getDefaults().onsurface_low_emp
+ )
+ )
+ searchViewTheme(containerSearch, textInputSearch)
}
fun LayoutRoleBasedChatMessageBottomSheetItemHeaderBinding.applyTheme() {
name.setTextColor(
@@ -2678,8 +2849,8 @@ fun LayoutRoleBasedChatMessageBottomSheetItemHeaderBinding.applyTheme() {
fun LayoutRoleBasedChatMessageBottomSheetItemRecipientBinding.applyTheme() {
image.drawable.setTint(
getColorOrDefault(
- HMSPrebuiltTheme.getColours()?.onSurfaceHigh,
- HMSPrebuiltTheme.getDefaults().onsurface_high_emp
+ HMSPrebuiltTheme.getColours()?.onPrimaryMedium,
+ HMSPrebuiltTheme.getDefaults().onprimary_med_emp
)
)
tick.drawable.setTint(
diff --git a/room-kit/src/main/res/drawable/clock.xml b/room-kit/src/main/res/drawable/clock.xml
new file mode 100644
index 000000000..ecccbd005
--- /dev/null
+++ b/room-kit/src/main/res/drawable/clock.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/room-kit/src/main/res/drawable/dm_rbac_icon.xml b/room-kit/src/main/res/drawable/dm_rbac_icon.xml
new file mode 100644
index 000000000..0d7e35004
--- /dev/null
+++ b/room-kit/src/main/res/drawable/dm_rbac_icon.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/room-kit/src/main/res/drawable/everyone_rbac_icon.xml b/room-kit/src/main/res/drawable/everyone_rbac_icon.xml
index 1d3815b82..458553454 100644
--- a/room-kit/src/main/res/drawable/everyone_rbac_icon.xml
+++ b/room-kit/src/main/res/drawable/everyone_rbac_icon.xml
@@ -4,7 +4,29 @@
android:viewportWidth="20"
android:viewportHeight="20">
+
+
+
+
+
+
+
diff --git a/room-kit/src/main/res/drawable/role_rbac_icon.xml b/room-kit/src/main/res/drawable/role_rbac_icon.xml
new file mode 100644
index 000000000..e4499ed71
--- /dev/null
+++ b/room-kit/src/main/res/drawable/role_rbac_icon.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/room-kit/src/main/res/drawable/tick_check_in_circle.xml b/room-kit/src/main/res/drawable/tick_check_in_circle.xml
new file mode 100644
index 000000000..6a5cb1baf
--- /dev/null
+++ b/room-kit/src/main/res/drawable/tick_check_in_circle.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/room-kit/src/main/res/drawable/tiny_chip_dm.xml b/room-kit/src/main/res/drawable/tiny_chip_dm.xml
index e1020481e..f3086dae8 100644
--- a/room-kit/src/main/res/drawable/tiny_chip_dm.xml
+++ b/room-kit/src/main/res/drawable/tiny_chip_dm.xml
@@ -4,7 +4,7 @@
android:viewportWidth="16"
android:viewportHeight="16">
diff --git a/room-kit/src/main/res/drawable/tiny_chip_everyone.xml b/room-kit/src/main/res/drawable/tiny_chip_everyone.xml
index e52b207ce..4fb468b0c 100644
--- a/room-kit/src/main/res/drawable/tiny_chip_everyone.xml
+++ b/room-kit/src/main/res/drawable/tiny_chip_everyone.xml
@@ -4,7 +4,29 @@
android:viewportWidth="16"
android:viewportHeight="16">
+
+
+
+
+
+
+
diff --git a/room-kit/src/main/res/drawable/tiny_chip_roles.xml b/room-kit/src/main/res/drawable/tiny_chip_roles.xml
new file mode 100644
index 000000000..e3e1a8976
--- /dev/null
+++ b/room-kit/src/main/res/drawable/tiny_chip_roles.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/room-kit/src/main/res/drawable/tiny_down_chevron.xml b/room-kit/src/main/res/drawable/tiny_down_chevron.xml
index 16d1444a9..6d8d5b1e3 100644
--- a/room-kit/src/main/res/drawable/tiny_down_chevron.xml
+++ b/room-kit/src/main/res/drawable/tiny_down_chevron.xml
@@ -4,7 +4,7 @@
android:viewportWidth="12"
android:viewportHeight="12">
diff --git a/room-kit/src/main/res/layout/fragment_meeting.xml b/room-kit/src/main/res/layout/fragment_meeting.xml
index fbe711db4..85599f89a 100644
--- a/room-kit/src/main/res/layout/fragment_meeting.xml
+++ b/room-kit/src/main/res/layout/fragment_meeting.xml
@@ -356,7 +356,7 @@
android:drawableEnd="@drawable/tiny_down_chevron"
android:maxLines="1"
android:singleLine="true"
- android:text="To Group"
+ android:text="@string/chat_rbac_picker_send_to"
android:textSize="12sp"
app:fontFamily="@font/inter_regular"
tools:layout_editor_absoluteY="2dp" />
@@ -369,6 +369,7 @@
diff --git a/room-kit/src/main/res/layout/fragment_preview.xml b/room-kit/src/main/res/layout/fragment_preview.xml
index 762feff8e..14025cad3 100644
--- a/room-kit/src/main/res/layout/fragment_preview.xml
+++ b/room-kit/src/main/res/layout/fragment_preview.xml
@@ -379,6 +379,7 @@
android:layout_height="46dp"
android:elevation="8dp"
android:gravity="center"
+ android:layout_marginStart="8dp"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp"
android:visibility="invisible"
diff --git a/room-kit/src/main/res/layout/item_grid_sub_text.xml b/room-kit/src/main/res/layout/item_grid_sub_text.xml
new file mode 100644
index 000000000..56cc70a26
--- /dev/null
+++ b/room-kit/src/main/res/layout/item_grid_sub_text.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/room-kit/src/main/res/layout/item_name_section.xml b/room-kit/src/main/res/layout/item_name_section.xml
new file mode 100644
index 000000000..9f3374ac1
--- /dev/null
+++ b/room-kit/src/main/res/layout/item_name_section.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/room-kit/src/main/res/layout/layout_chat_participant_combined_tab_chat.xml b/room-kit/src/main/res/layout/layout_chat_participant_combined_tab_chat.xml
index ff88f666e..ccf2bd3fc 100644
--- a/room-kit/src/main/res/layout/layout_chat_participant_combined_tab_chat.xml
+++ b/room-kit/src/main/res/layout/layout_chat_participant_combined_tab_chat.xml
@@ -133,7 +133,7 @@
android:drawableEnd="@drawable/tiny_down_chevron"
android:maxLines="1"
android:singleLine="true"
- android:text="To Group"
+ android:text="@string/chat_rbac_picker_send_to"
android:textSize="12sp"
app:fontFamily="@font/inter_regular"
tools:layout_editor_absoluteY="2dp" />
@@ -146,6 +146,7 @@
diff --git a/room-kit/src/main/res/layout/layout_chat_send_to_chip.xml b/room-kit/src/main/res/layout/layout_chat_send_to_chip.xml
index 56968f38e..1789f5329 100644
--- a/room-kit/src/main/res/layout/layout_chat_send_to_chip.xml
+++ b/room-kit/src/main/res/layout/layout_chat_send_to_chip.xml
@@ -20,7 +20,7 @@
android:lineHeight="16px"
android:maxLines="1"
android:singleLine="true"
- android:text="To Group"
+ android:text="@string/chat_rbac_picker_send_to"
android:textSize="12sp"
app:fontFamily="@font/inter_regular"
tools:layout_editor_absoluteY="2dp" />
diff --git a/room-kit/src/main/res/layout/layout_end_poll_button.xml b/room-kit/src/main/res/layout/layout_end_poll_button.xml
index a9f2188bb..a54504df5 100644
--- a/room-kit/src/main/res/layout/layout_end_poll_button.xml
+++ b/room-kit/src/main/res/layout/layout_end_poll_button.xml
@@ -9,6 +9,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
+ android:layout_marginBottom="@dimen/spacing_d3"
android:paddingHorizontal="@dimen/spacing_d2"
android:paddingVertical="@dimen/spacing_d1"
tools:text="Launch Poll"
diff --git a/room-kit/src/main/res/layout/layout_header.xml b/room-kit/src/main/res/layout/layout_header.xml
new file mode 100644
index 000000000..468bfd317
--- /dev/null
+++ b/room-kit/src/main/res/layout/layout_header.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/room-kit/src/main/res/layout/layout_participants_merge.xml b/room-kit/src/main/res/layout/layout_participants_merge.xml
index dd7a68b6a..1d4d1c026 100644
--- a/room-kit/src/main/res/layout/layout_participants_merge.xml
+++ b/room-kit/src/main/res/layout/layout_participants_merge.xml
@@ -17,22 +17,23 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
-
+ android:layout_width="match_parent"
+ android:layout_marginTop="@dimen/spacing_d2">
-
-
+ android:inputType="textNoSuggestions"
+ android:padding="@dimen/spacing_d2" />
+
diff --git a/room-kit/src/main/res/layout/layout_polls_display.xml b/room-kit/src/main/res/layout/layout_polls_display.xml
index 73303eb10..1f4e5c730 100644
--- a/room-kit/src/main/res/layout/layout_polls_display.xml
+++ b/room-kit/src/main/res/layout/layout_polls_display.xml
@@ -19,6 +19,9 @@
android:src="@drawable/left_arrow" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/room-kit/src/main/res/layout/layout_role_based_chat_bottom_sheet_selector.xml b/room-kit/src/main/res/layout/layout_role_based_chat_bottom_sheet_selector.xml
index 6178dea63..acfcac310 100644
--- a/room-kit/src/main/res/layout/layout_role_based_chat_bottom_sheet_selector.xml
+++ b/room-kit/src/main/res/layout/layout_role_based_chat_bottom_sheet_selector.xml
@@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ xmlns:tools="http://schemas.android.com/tools"
app:cardCornerRadius="@dimen/sizeteen_dp"
android:paddingBottom="16dp"
android:id="@id/rootLayout"
@@ -47,22 +48,65 @@
-
-
+ android:layout_height="wrap_content"
+ android:layout_marginHorizontal="@dimen/spacing_d3"
+ android:layout_marginTop="@dimen/spacing_d2">
+
+
+
+
+
+
+
+
+
+
+
diff --git a/room-kit/src/main/res/layout/layout_role_based_chat_message_bottom_sheet_item_header.xml b/room-kit/src/main/res/layout/layout_role_based_chat_message_bottom_sheet_item_header.xml
index 1e7c9fe3e..9fe00e4a6 100644
--- a/room-kit/src/main/res/layout/layout_role_based_chat_message_bottom_sheet_item_header.xml
+++ b/room-kit/src/main/res/layout/layout_role_based_chat_message_bottom_sheet_item_header.xml
@@ -4,9 +4,17 @@
android:layout_height="wrap_content"
android:paddingTop="@dimen/spacing_d2"
android:paddingHorizontal="@dimen/spacing_d2"
+ android:gravity="center_vertical"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal">
+
+
-
-
-
-
-
-
+ />
-
@@ -93,19 +90,6 @@
-
-
-
-
-
-
-
@@ -74,19 +71,6 @@
-
-
-
-
-
-
Block from Chat
Chat Paused
+ to %1$s %2$s
+ (Group)
+ (DM)
+ You
+ Choose a Recipient
+ No Recipients Yet
\ No newline at end of file
diff --git a/room-kit/src/main/res/values/themes.xml b/room-kit/src/main/res/values/themes.xml
index 11e804051..a49d7b2a1 100644
--- a/room-kit/src/main/res/values/themes.xml
+++ b/room-kit/src/main/res/values/themes.xml
@@ -56,6 +56,7 @@