diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ClosedCaptionsForEveryone.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ClosedCaptionsForEveryone.kt index b53470a8b..21cd8f8e2 100644 --- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ClosedCaptionsForEveryone.kt +++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/ClosedCaptionsForEveryone.kt @@ -129,16 +129,16 @@ fun EnableCaptionsDisplay(onEnableForEveryoneClicked : () -> Unit, .wrapContentHeight() .background( color = Variables.SurfaceDim, - shape = RoundedCornerShape(topStart = Variables.Spacing2, topEnd = Variables.Spacing2) + shape = RoundedCornerShape(topStart = Variables.Spacing4, topEnd = Variables.Spacing4) ) .padding( - start = Variables.Spacing3, - end = Variables.Spacing3, - top = Variables.Spacing3, - bottom = Variables.Spacing4 + start = Variables.Spacing6, + end = Variables.Spacing6, + top = Variables.Spacing6, + bottom = Variables.Spacing8 ) , - verticalArrangement = Arrangement.spacedBy(Variables.Spacing2, Alignment.Top), + verticalArrangement = Arrangement.spacedBy(Variables.Spacing4, Alignment.Top), horizontalAlignment = Alignment.CenterHorizontally, ) { Row( diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingEndedFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingEndedFragment.kt new file mode 100644 index 000000000..02069a046 --- /dev/null +++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/MeetingEndedFragment.kt @@ -0,0 +1,1175 @@ +package live.hms.roomkit.ui.meeting + +import android.content.Context +import android.graphics.drawable.BitmapDrawable +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.animation.AccelerateDecelerateInterpolator +import android.widget.ImageView +import android.widget.TextView +import androidx.activity.OnBackPressedCallback +import androidx.appcompat.app.AlertDialog +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.absoluteOffset +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Divider +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.SheetValue +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.HorizontalAlignmentLine +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.TextUnit +import androidx.compose.ui.unit.TextUnitType +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.content.ContextCompat +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsAnimationCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.forEach +import androidx.core.view.marginBottom +import androidx.core.widget.doOnTextChanged +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Observer +import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController +import com.bumptech.glide.Glide +import kotlinx.coroutines.launch +import live.hms.roomkit.R +import live.hms.roomkit.animation.ControlFocusInsetsAnimationCallback +import live.hms.roomkit.animation.TranslateDeferringInsetsAnimationCallback +import live.hms.roomkit.databinding.FragmentMeetingEndedBinding +import live.hms.roomkit.databinding.FragmentPreviewBinding +import live.hms.roomkit.drawableStart +import live.hms.roomkit.helpers.NetworkQualityHelper +import live.hms.roomkit.hideKeyboard +import live.hms.roomkit.initAnimState +import live.hms.roomkit.setDrawables +import live.hms.roomkit.startBounceAnimationUpwards +import live.hms.roomkit.ui.meeting.compose.Variables +import live.hms.roomkit.ui.meeting.participants.ParticipantsAdapter +import live.hms.roomkit.ui.meeting.participants.ParticipantsDialog +import live.hms.roomkit.ui.settings.SettingsStore +import live.hms.roomkit.ui.theme.applyTheme +import live.hms.roomkit.ui.theme.buttonDisabled +import live.hms.roomkit.ui.theme.buttonEnabled +import live.hms.roomkit.ui.theme.getCurrentRoleData +import live.hms.roomkit.ui.theme.getPreviewLayout +import live.hms.roomkit.ui.theme.setIconDisabled +import live.hms.roomkit.ui.theme.setIconEnabled +import live.hms.roomkit.util.NameUtils +import live.hms.roomkit.util.contextSafe +import live.hms.roomkit.util.openShareIntent +import live.hms.roomkit.util.setCameraGestureListener +import live.hms.roomkit.util.setOnSingleClickListener +import live.hms.roomkit.util.switchCamera +import live.hms.roomkit.util.viewLifecycle +import live.hms.video.audio.HMSAudioManager +import live.hms.video.error.HMSException +import live.hms.video.media.tracks.HMSLocalAudioTrack +import live.hms.video.media.tracks.HMSLocalVideoTrack +import live.hms.video.sdk.models.HMSLocalPeer +import live.hms.video.sdk.models.HMSPeer +import live.hms.video.sdk.models.HMSRoom +import live.hms.video.sdk.models.enums.HMSPeerUpdate +import live.hms.video.sdk.models.enums.HMSRecordingState +import live.hms.video.sdk.models.enums.HMSStreamingState +import live.hms.video.sdk.models.role.PublishParams +import live.hms.videoview.VideoViewStateChangeListener + + +class MeetingEndedFragment : Fragment() { + + companion object { + private const val TAG = "MeetingEndedFragment" + } + + private var binding by viewLifecycle() + + private lateinit var settings: SettingsStore + + private val meetingViewModel: MeetingViewModel by activityViewModels { + MeetingViewModelFactory( + requireActivity().application + ) + } + + private var alertDialog: AlertDialog? = null + + private var track: MeetingTrack? = null + + private var isViewVisible = false + + private var participantsDialog: ParticipantsDialog? = null + private var participantsDialogAdapter: ParticipantsAdapter? = null + + private var setTextOnce = false + private var isPreviewLoaded = false + private var nameEditText: String? = null + private var isBeamRunning = false + private var isFirstRender : Boolean = true + private var startHlsStream : Boolean = false + + // var showBottomSheet by remember { mutableStateOf(false) } + + +// private fun updateJoinButtonTextIfHlsIsEnabled(roleName: String?): Boolean { +// val hlsJoinButtonFromLayoutConfig = meetingViewModel.getHmsRoomLayout() +// ?.getPreviewLayout(roleName)?.default?.elements?.joinForm?.joinBtnType == "JOIN_BTN_TYPE_JOIN_AND_GO_LIVE" +// +// if (isBeamRunning.not() && hlsJoinButtonFromLayoutConfig) { +// if (binding.buttonJoinMeeting.drawableStart == null) { +// binding.buttonJoinMeeting.setDrawables( +// start = ContextCompat.getDrawable( +// requireContext(), R.drawable.ic_live +// ) +// ) +// } +// binding.buttonJoinMeeting.text = "Go Live" +// startHlsStream = true +// return true +// } else { +// binding.buttonJoinMeeting.text = "Join Now" +// binding.buttonJoinMeeting.setDrawables( +// start = null ) +// +// startHlsStream = false +// return false +// } +// +// } + + override fun onResume() { + super.onResume() + isViewVisible = true +// bindVideo() + } + + override fun onPause() { + super.onPause() + isViewVisible = false +// unbindVideo() + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } + +// private fun bindVideo(isFirstRender: Boolean = false) { +// if (track?.video?.isMute == false) { +// track?.video?.let { +// binding.previewView.addTrack(it) +// binding.previewView.setCameraGestureListener(it, { +// activity?.openShareIntent(it) +// }, {}) +// } +// if (isFirstRender) { +// binding.previewView.initAnimState(alphaOnly = true) +// binding.previewView.visibility = View.VISIBLE +// binding.previewView.addVideoViewStateChangeListener(object : VideoViewStateChangeListener { +// override fun onFirstFrameRendered() { +// super.onFirstFrameRendered() +// contextSafe { context, activity -> +// activity.runOnUiThread { +// if (isFirstRender) { +// viewLifecycleOwner.lifecycleScope.launch { +// binding?.previewGradient?.startBounceAnimationUpwards(animationDuration = 650, interpolator = AccelerateDecelerateInterpolator()) +// binding?.previewView?.startBounceAnimationUpwards() +// } +// } +// } +// } +// } +// }) +// } else { +// binding.previewView.visibility = View.VISIBLE +// } +// +// } else { +// binding.previewView.visibility = View.GONE +// } +// +// } + +// private fun unbindVideo() { +// binding.previewView.visibility = View.GONE +// binding.previewView.removeTrack() +// } + +// private fun enableDisableJoinNowButton() { +// if (isPreviewLoaded && nameEditText.isNullOrEmpty().not()) { +// binding.buttonJoinMeeting.buttonEnabled() +// } else { +// binding.buttonJoinMeeting.buttonDisabled() +// } +// } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + +// binding.applyTheme() // TODO: apply theme? + + addComposable(binding.composeView) + +// initIntroAnimation() + initOnBackPress() +// initButtons() +// initObservers() + + _showBottomSheet.value = true + + if (savedInstanceState != null) { + // Recreated Fragment +// meetingViewModel.roomLayoutLiveData.observe(viewLifecycleOwner) {success -> +// if (success) { +// meetingViewModel.roomLayoutLiveData.removeObservers(viewLifecycleOwner) +// initUI() +// meetingViewModel.startPreview() +// enableDisableJoinNowButton() +// +// } else { +// this.activity?.finish() +// } +// } + } else { +// initUI() +// meetingViewModel.startPreview() +// enableDisableJoinNowButton() + } + + + } + + var _showBottomSheet = mutableStateOf(false) + + data class Rating(val label: String, val value: Int, val emoji: String) + + @OptIn(ExperimentalMaterial3Api::class) + private fun addComposable(composeView: ComposeView) = composeView.apply { + + + setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) + setContent { + val sheetState = rememberModalBottomSheetState(confirmValueChange = { it != SheetValue.Hidden }, skipPartiallyExpanded = true) + val scope = rememberCoroutineScope() + var showBottomSheet by remember { _showBottomSheet } + var selectedRating by remember { mutableStateOf(null) } + + val ratings = listOf( + Rating( + label = "Awful", + value = 1, + emoji = "😔" + ), + Rating( + label = "Bad", + value = 2, + emoji = "☹️" + ), + Rating( + label = "Fair", + value = 3, + emoji = "🙂" + ), + Rating( + label = "Good", + value = 4, + emoji = "😄" + ), + Rating( + label = "Great", + value = 5, + emoji = "🤩" + ), + ) + + Box(modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .background(color = Variables.BackgroundDim) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Image( + painter = painterResource(id = R.drawable.ic_hand_golden), + contentDescription = "Golden color hand indicating hello", + modifier = Modifier + .width(width = 60.dp) + .height(height = 60.dp) + .padding(bottom = Variables.Spacing4) + ) + Text( + text = "You left the meeting", // or, Session ended + fontFamily = FontFamily(Font((R.font.inter_semibold))), + fontWeight = FontWeight(600), + fontSize = 24.sp, + lineHeight = 32.sp, + color = Variables.OnSurfaceHigh, + modifier = Modifier.padding(bottom = Variables.Spacing1) + ) + Text( + text = "Have a nice day!", + fontFamily = FontFamily(Font((R.font.inter_regular))), + fontWeight = FontWeight(400), + fontSize = 16.sp, + lineHeight = 24.sp, + color = Variables.OnSurfaceMedium, + modifier = Modifier.padding(bottom = Variables.Spacing10 + Variables.Spacing2) + ) + Text( + text = "Left by mistake?", // or, Ended by mistake? + fontFamily = FontFamily(Font((R.font.inter_regular))), + fontWeight = FontWeight(400), + fontSize = 14.sp, + lineHeight = 20.sp, + color = Variables.OnSurfaceMedium, + modifier = Modifier.padding(bottom = Variables.Spacing4) + ) + Button( + onClick = { + //your onclick code + }, + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors(containerColor = Variables.PrimaryDefault), + contentPadding = PaddingValues(horizontal = Variables.Spacing4, vertical = Variables.Spacing3) + ) { + Image( + painter = painterResource(id = R.drawable.ic_leave), + contentDescription = "Leave Icon", + modifier = Modifier + .width(width = 24.dp) + .height(height = 24.dp) + .padding(end = Variables.Spacing2) + ) + Text( + text = "Rejoin", + fontFamily = FontFamily(Font((R.font.inter_semibold))), + fontWeight = FontWeight(600), + fontSize = 16.sp, + lineHeight = 24.sp, + color = Variables.OnPrimaryHigh, + ) // or, Restart + } + } + + Button( + onClick = { /*TODO*/ }, + modifier = Modifier + .width(width = 40.dp) + .height(height = 40.dp) + .align(alignment = Alignment.TopEnd) + .absoluteOffset(x = (-16).dp, y = 8.dp), + shape = RoundedCornerShape(20.dp) + ) { + Image( + painter = painterResource(id = R.drawable.close_icon), + contentDescription = "Close", + modifier = Modifier + .width(width = 24.dp) + .height(height = 24.dp), + contentScale = ContentScale.Inside + ) + } + + if (showBottomSheet) { + ModalBottomSheet( + onDismissRequest = { + showBottomSheet = false + }, + dragHandle = null, + sheetState = sheetState, + shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), + windowInsets = WindowInsets(bottom = 0.dp, left = 0.dp, right = 0.dp, top = 0.dp), + containerColor = Variables.SurfaceDim + ) { + Column ( + modifier = Modifier + .padding(Variables.Spacing6) + .padding( + bottom = if (selectedRating != null) { + 0.dp + } else { + Variables.Spacing6 + } + ) + ) { + Row ( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = Variables.Spacing6) + ) { + Column { + Text( + text = "How was your experience?", + fontWeight = FontWeight(600), + fontFamily = FontFamily(Font(R.font.inter_semibold)), + fontSize = 20.sp, + lineHeight = 24.sp, + color = Variables.OnSurfaceHigh, + modifier = Modifier.padding(bottom = Variables.Spacing1) + ) + Text( + text = "Your answers help us improve the quality.", + fontWeight = FontWeight(400), + fontFamily = FontFamily(Font(R.font.inter_regular)), + fontSize = 14.sp, + lineHeight = 20.sp, + color = Variables.OnSurfaceMedium, + ) + } + Button( + onClick = { showBottomSheet = false }, + modifier = Modifier + .width(width = 40.dp) + .height(height = 40.dp), +// .align(alignment = Alignment.TopEnd) +// .absoluteOffset(x = (-16).dp, y = 8.dp), +// shape = RoundedCornerShape(20.dp) + ) { + Image( + painter = painterResource(id = R.drawable.close_icon), + contentDescription = "Close", + modifier = Modifier + .width(width = 24.dp) + .height(height = 24.dp), + contentScale = ContentScale.Inside + ) + } + } + Row (horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) { + ratings.forEach { + Button( + onClick = { + selectedRating = it.value + }, + contentPadding = PaddingValues(0.dp), + shape = RectangleShape, + colors = ButtonDefaults.buttonColors(containerColor = Color.Transparent) + ) { + Column (horizontalAlignment = Alignment.CenterHorizontally) { + Text( + text = it.emoji, + fontFamily = FontFamily(Font(R.font.inter_semibold)), + fontWeight = FontWeight(600), + color = Color.White, + fontSize = 32.sp, + lineHeight = 32.sp, + modifier = Modifier + .padding(bottom = Variables.Spacing2) + .alpha( + if (selectedRating != null && it.value != selectedRating) { + 0.4F + } else { + 1F + } + ) + ) + Text( + text = it.label, + fontFamily = FontFamily(Font( + if (selectedRating != null && it.value == selectedRating) { + R.font.inter_semibold + } else { + R.font.inter_regular + } + )), + fontWeight = FontWeight(if (selectedRating != null && it.value == selectedRating) { + 600 + } else { + 400 + }), + color = if (selectedRating != null) { + if (it.value == selectedRating) { + Variables.OnSurfaceHigh + } else { + Variables.OnSurfaceLow + } + } else { + Variables.OnSurfaceMedium + }, + fontSize = 14.sp, + lineHeight = 20.sp, + ) + } + } + } + } + } + if (selectedRating != null) { + Divider(color = Variables.BorderDefault, thickness = 1.dp, modifier = Modifier.padding(bottom = Variables.Spacing6)) +// TODO: Below content needs to come from Layout Config + Column (modifier = Modifier.padding(horizontal = Variables.Spacing4).padding(bottom = Variables.Spacing6)) { + Text( + text = "What went wrong?", + fontFamily = FontFamily(Font(R.font.inter_semibold)), + fontWeight = FontWeight(600), + fontSize = 14.sp, + lineHeight = 20.sp, + color = Variables.OnSurfaceHigh, + modifier = Modifier.padding(bottom = Variables.Spacing3) + ) + } + Column (modifier = Modifier.padding(horizontal = Variables.Spacing4).padding(bottom = Variables.Spacing6)) { + Text( + text = "Additional comments (optional)", + fontFamily = FontFamily(Font(R.font.inter_regular)), + fontWeight = FontWeight(400), + fontSize = 14.sp, + lineHeight = 20.sp, + color = Variables.OnSurfaceHigh, + modifier = Modifier.padding(bottom = Variables.Spacing2) + ) + TextField( + value = "", + onValueChange = { /***/ }, + label = { Text("Tell us more...") } + ) + } + Button( + onClick = { + //your onclick code + }, + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors(containerColor = Variables.PrimaryDefault), + contentPadding = PaddingValues(horizontal = Variables.Spacing4, vertical = Variables.Spacing3), + modifier = Modifier.padding(horizontal = Variables.Spacing4).fillMaxWidth() + ) { + Text( + text = "Submit Feedback", + fontFamily = FontFamily(Font((R.font.inter_semibold))), + fontWeight = FontWeight(600), + fontSize = 16.sp, + lineHeight = 24.sp, + color = Variables.OnPrimaryHigh, + ) + } + Spacer(modifier = Modifier.height(Variables.Spacing10)) + } + } + } + } + } + } + +// fun initUI() { +// binding.applyTheme() +// with(binding.editTextName) { +// isEnabled = !meetingViewModel.disableNameEdit() +// if(!isEnabled) { +// binding.editContainerName.isHintEnabled = false +// } else { +// hint = "Enter Name…" +// } +// } +// requireActivity().invalidateOptionsMenu() +// setHasOptionsMenu(true) +// settings = SettingsStore(requireContext()) +// startFixedIntroAnimation() +// setupKeyboardAnimation() +// } + +// private fun startFixedIntroAnimation() { +// var animationOffset = 350 +// binding.apply { +// previewBottomBar.startBounceAnimationUpwards(animationOffset) +// animationOffset += 50 +// editContainerName.startBounceAnimationUpwards(animationOffset) +// buttonJoinMeeting.startBounceAnimationUpwards(animationOffset) +// } +// } + +// private fun initIntroAnimation() { +// with(binding) { +// previewBottomBar.initAnimState() +// buttonToggleAudio.initAnimState(littleLessTranslate = true) +// buttonToggleVideo.initAnimState(littleLessTranslate = true) +// buttonSwitchCamera.initAnimState(littleLessTranslate = true) +// buttonNetworkQuality.initAnimState(littleLessTranslate = true) +// iconOutputDevice.initAnimState(littleLessTranslate = true) +// editContainerName.initAnimState() +// buttonJoinMeeting.initAnimState() +// hlsSession.initAnimState(isUpwardsAnimation = false) +// iconParticipants.initAnimState(isUpwardsAnimation = false) +// previewGradient.initAnimState(alphaOnly = true) +// descriptionTv.initAnimState(alphaOnly = true) +// logoIv.initAnimState(alphaOnly = true) +// nameTv.initAnimState(alphaOnly = true) +// +// +// } +// } + +// private fun setupUI(roleName: String) { +// // don't allow editing the name if there's supposed to be a fixed one +// +// var introAnimationOffset = 450 +// if (meetingViewModel.getHmsRoomLayout() +// ?.getPreviewLayout(roleName)?.default?.elements?.previewHeader?.title.isNullOrEmpty() +// ) { +// binding.nameTv.visibility = View.GONE +// } else { +// binding.nameTv.text = meetingViewModel.getHmsRoomLayout() +// ?.getPreviewLayout(roleName)?.default?.elements?.previewHeader?.title +// binding.nameTv.startBounceAnimationUpwards() +// } +// +// if (meetingViewModel.getHmsRoomLayout() +// ?.getPreviewLayout(roleName)?.default?.elements?.previewHeader?.subTitle.isNullOrEmpty() +// ) { +// binding.descriptionTv.visibility = View.GONE +// } else { +// binding.descriptionTv.text = meetingViewModel.getHmsRoomLayout() +// ?.getPreviewLayout(roleName)?.default?.elements?.previewHeader?.subTitle +// binding.descriptionTv.startBounceAnimationUpwards() +// } +// +// if (meetingViewModel.getHmsRoomLayout()?.getCurrentRoleData(roleName)?.logo?.url.isNullOrEmpty()) { +// binding.logoIv.visibility = View.INVISIBLE +// } else { +// binding.logoIv.visibility = View.VISIBLE +// Glide.with(this) +// .load(meetingViewModel.getHmsRoomLayout()?.getCurrentRoleData(roleName)?.logo?.url) +// .into(binding.logoIv); +// introAnimationOffset += 50 +// binding.logoIv.startBounceAnimationUpwards() +// +// } +// } + +// private fun setupKeyboardAnimation() { +// +// ViewCompat.setWindowInsetsAnimationCallback( +// binding.previewBottomBar, TranslateDeferringInsetsAnimationCallback( +// view = binding.previewBottomBar, +// persistentInsetTypes = WindowInsetsCompat.Type.systemBars(), +// deferredInsetTypes = WindowInsetsCompat.Type.ime(), +// // We explicitly allow dispatch to continue down to binding.messageHolder's +// // child views, so that step 2.5 below receives the call +// dispatchMode = WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE +// ) +// ) +// +// val movableOnKeybaordOpen = arrayOf(binding.buttonNetworkQuality) +// movableOnKeybaordOpen.forEach { +// ViewCompat.setWindowInsetsAnimationCallback( +// it, TranslateDeferringInsetsAnimationCallback( +// view = it, +// persistentInsetTypes = WindowInsetsCompat.Type.systemBars(), +// deferredInsetTypes = WindowInsetsCompat.Type.ime() +// ) +// ) +// +// } +// +// ViewCompat.setWindowInsetsAnimationCallback( +// binding.editTextName, ControlFocusInsetsAnimationCallback(binding.editTextName) +// ) +// } + + override fun onAttach(context: Context) { + super.onAttach(context) + +// setupParticipantsDialog() + } + + +// private fun setupParticipantsDialog() { +// participantsDialog = ParticipantsDialog() +// participantsDialogAdapter = participantsDialog?.adapter +// } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? + ): View { + binding = FragmentMeetingEndedBinding.inflate(inflater, container, false) + return binding.root + } + +// private fun initButtons() { +// +// binding.closeBtn.setOnSingleClickListener(300L) { +// contextSafe { context, activity -> +// meetingViewModel.leaveMeeting() +// goToHomePage() +// } +// } +// updateActionVolumeMenuIcon(meetingViewModel.getAudioOutputRouteType()) +// meetingViewModel.hmsSDK.setAudioDeviceChangeListener(object : +// HMSAudioManager.AudioManagerDeviceChangeListener { +// override fun onAudioDeviceChanged( +// p0: HMSAudioManager.AudioDevice, +// p1: Set +// ) { +// meetingViewModel.updateAudioDeviceChange(p0) +// } +// +// +// override fun onError(p0: HMSException) { +// } +// }) +// +// meetingViewModel.audioDeviceChange.observe(viewLifecycleOwner, Observer{ +// updateActionVolumeMenuIcon(it) +// }) +// +// binding.iconNoiseCancellation.setOnSingleClickListener(200L) { +// meetingViewModel.clickNcPreview() +// updateNoiseCancellationIcon() +// } +// +// binding.iconOutputDevice.setOnSingleClickListener(200L) { +// Log.v(TAG, "iconOutputDevice.onClick()") +// +// AudioOutputSwitchBottomSheet { audioDevice, isMuted -> +// if (isMuted) +// updateActionVolumeMenuIcon() +// }.show( +// childFragmentManager, MeetingFragment.AudioSwitchBottomSheetTAG +// ) +// } +// +// binding.buttonSwitchCamera.setOnSingleClickListener(200L) { +// if (it.isEnabled) track?.video.switchCamera() +// } +// +// +// binding.buttonToggleVideo.apply { +// setOnSingleClickListener(200L) { +// Log.v(TAG, "buttonToggleVideo.onClick()") +// +// (track?.video as HMSLocalVideoTrack?)?.let { +// if (it.isMute) { +// // Un-mute this track +// it.setMute(false) +// if (isViewVisible) { +// bindVideo() +// } +// binding.buttonSwitchCamera.alpha = 1f +// binding.buttonSwitchCamera.isEnabled = true +// binding.buttonToggleVideo.setIconEnabled(R.drawable.avd_video_off_to_on) +//// +// } else { +// // Mute this track +// it.setMute(true) +// if (isViewVisible) { +// unbindVideo() +// } +// binding.buttonSwitchCamera.alpha = 0.5f +// binding.buttonSwitchCamera.isEnabled = false +// binding.buttonToggleVideo.setIconDisabled(R.drawable.avd_video_on_to_off) +// } +// } +// +// } +// } +// +// binding.buttonToggleAudio.apply { +// setOnSingleClickListener(200L) { +// Log.v(TAG, "buttonToggleAudio.onClick()") +// +// (track?.audio as HMSLocalAudioTrack?)?.let { +// it.setMute(!it.isMute) +// +// if (it.isMute) { +// binding.buttonToggleAudio.setIconDisabled(R.drawable.avd_mic_on_to_off) +// } else { +// binding.buttonToggleAudio.setIconEnabled(R.drawable.avd_mic_off_to_on) +// } +// } +// } +// } +// +// binding.buttonJoinMeeting.apply { +// setOnSingleClickListener(200L) { +// Log.v(TAG, "buttonJoinMeeting.onClick()") +// if (this.isEnabled) { +// hideKeyboard() +// +// meetingViewModel.updateNameInPreview( +// binding.editTextName.text.toString().trim() +// ) +// +// //start meeting +// if (meetingViewModel.state.value is MeetingState.Disconnected) { +// meetingViewModel.startMeeting() +// } +// } +// } +// } +// } + +// private fun enableJoinLoader() { +// binding.joinLoader.visibility = View.VISIBLE +//// binding.editContainerName.isEnabled = false +// // binding.editTextName.isEnabled = false +// } + +// private fun disableJoinLoader() { +// binding.joinLoader.visibility = View.INVISIBLE +// // binding.editContainerName.isEnabled = true +// // binding.editTextName.isEnabled = true +// } + + // INTERESTING + private fun navigateToMeeting() { + findNavController().navigate( + PreviewFragmentDirections.actionPreviewFragmentToMeetingFragment(startHlsStream = startHlsStream) + ) + } + +// private fun updateActionVolumeMenuIcon( +// audioOutputType: HMSAudioManager.AudioDevice? = null +// ) { +// binding.iconOutputDevice.visibility = View.VISIBLE +// binding.iconOutputDevice.apply { +// when (audioOutputType) { +// HMSAudioManager.AudioDevice.EARPIECE -> { +// setIconEnabled(R.drawable.phone) +// } +// +// HMSAudioManager.AudioDevice.SPEAKER_PHONE -> { +// setIconEnabled(R.drawable.ic_icon_speaker) +// } +// +// HMSAudioManager.AudioDevice.AUTOMATIC -> { +// setIconEnabled(R.drawable.ic_icon_speaker) +// } +// +// HMSAudioManager.AudioDevice.BLUETOOTH -> { +// setIconEnabled(R.drawable.bt) +// } +// +// HMSAudioManager.AudioDevice.WIRED_HEADSET -> { +// setIconEnabled(R.drawable.wired) +// } +// +// else -> { +// setIconEnabled(R.drawable.ic_volume_off_24) +// } +// } +// } +// } + +// private fun updateNoiseCancellationIcon() { +// with(binding.iconNoiseCancellation) { +// if(meetingViewModel.noiseCancellationInPreviewUseCase.isEnabled()) { +// setIconDisabled(R.drawable.reduce_noise_session_option) +// } else +// { +// setIconEnabled(R.drawable.reduce_noise_session_option) +// } +// +// val existingVisibility = visibility +// visibility = if(meetingViewModel.displayNoiseCancellationButton()) View.VISIBLE else View.GONE +// if(existingVisibility == View.GONE && visibility == View.VISIBLE) { +// startBounceAnimationUpwards() +// } +// } +// } +// private fun updateActionVolumeMenuIcon() { +// binding.iconOutputDevice.visibility = View.VISIBLE +// binding.iconOutputDevice.apply { +// if (meetingViewModel.isPeerAudioEnabled()) { +// setIconEnabled(R.drawable.ic_icon_speaker) +// } else { +// setIconDisabled(R.drawable.ic_volume_off_24) +// } +// } +// } + + + private fun goToHomePage() { + requireActivity().finish() + } + +// private fun initObservers() { +// +// meetingViewModel.state.observe(viewLifecycleOwner) { +// when (it) { +// is MeetingState.Connecting, is MeetingState.Reconnecting, is MeetingState.Joining, is MeetingState.PublishingMedia -> { +// enableJoinLoader() +// } +// +// is MeetingState.Failure -> { +// disableJoinLoader() +// it.exceptions.forEach { exception -> +// meetingViewModel.triggerErrorNotification(exception.message, isDismissible = false) +// } +// } +// +// is MeetingState.ForceLeave -> { +// meetingViewModel.leaveMeeting() +// goToHomePage() +// } +// +// is MeetingState.Ongoing, is MeetingState.Reconnected -> { +// disableJoinLoader() +// navigateToMeeting() +// } +// +// else -> { +// +// } +// } +// } +// +// meetingViewModel.previewRoomStateLiveData.observe(viewLifecycleOwner) { +// if (it.second.peerCount != null) { +// binding.iconParticipants.visibility = View.VISIBLE +// binding.participantCountText.text = it.second.peerCount.formatNames().orEmpty() +// binding.iconParticipants.startBounceAnimationUpwards() +// } +// isBeamRunning = it.second.hlsStreamingState.state == HMSStreamingState.STARTED || +// it.second.rtmpHMSRtmpStreamingState.state == HMSStreamingState.STARTED || +// it.second.browserRecordingState.state == HMSRecordingState.STARTED +// updateJoinButtonTextIfHlsIsEnabled(it?.second?.localPeer?.hmsRole?.name) +// +// val isLiveWithHLSOrRTMP = it.second.hlsStreamingState.state == HMSStreamingState.STARTED || +// it.second.rtmpHMSRtmpStreamingState.state == HMSStreamingState.STARTED +// if (isLiveWithHLSOrRTMP) { +// binding.liveHlsGroup.visibility = View.VISIBLE +// binding.hlsSession.startBounceAnimationUpwards() +// } else { +// binding.liveHlsGroup.visibility = View.GONE +// } +// } +// +// meetingViewModel.previewErrorLiveData.observe(viewLifecycleOwner) { error -> +// if (error.isTerminal) { +// isPreviewLoaded = false +// meetingViewModel.triggerErrorNotification(error.message, isDismissible = false) +// } else { +// meetingViewModel.triggerErrorNotification(error.message) +// } +// } +// +// meetingViewModel.previewPeerLiveData.observe(viewLifecycleOwner) { (type, peer) -> +// when (type) { +// HMSPeerUpdate.PEER_JOINED -> { +// participantsDialogAdapter?.insertItem(peer) +// } +// +// HMSPeerUpdate.PEER_LEFT -> { +// participantsDialogAdapter?.removeItem(peer) +// } +// +// HMSPeerUpdate.NETWORK_QUALITY_UPDATED -> { +// peer.networkQuality?.downlinkQuality?.let { +// binding.networkQuality.visibility = View.VISIBLE +// updateNetworkQualityView(it, requireContext(), binding.networkQuality) +// } +// } +// +// else -> Unit +// } +// } +// +// meetingViewModel.previewUpdateLiveData.observe(viewLifecycleOwner, +// Observer { (room, localTracks) -> +// +// if (setTextOnce.not()) { +// setupUI(room.localPeer?.hmsRole?.name.orEmpty()) +// binding.nameInitials.visibility = View.VISIBLE +// binding.nameInitials.text = NameUtils.getInitials(room.localPeer!!.name) +// binding.editTextName.setText( +// room.localPeer?.name.orEmpty(), TextView.BufferType.EDITABLE +// ) +// nameEditText = room.localPeer?.name.orEmpty() +// enableDisableJoinNowButton() +// setTextOnce = true +// } +// isPreviewLoaded = true +// enableDisableJoinNowButton() +// +// updateUiBasedOnPublishParams(room.localPeer?.hmsRole?.publishParams) +// track = MeetingTrack(room.localPeer!!, null, null) +// localTracks.forEach { +// when (it) { +// is HMSLocalAudioTrack -> { +// track?.audio = it +// } +// +// is HMSLocalVideoTrack -> { +// track?.video = it +// +// if (isViewVisible) { +// bindVideo(isFirstRender = isFirstRender) +// } +// isFirstRender = false +// } +// } +// } +// +// binding.editTextName.doOnTextChanged { text, start, before, count -> +// if (text.isNullOrEmpty().not()) { +// val intitals = kotlin.runCatching { NameUtils.getInitials(text.toString()) } +// binding.nameInitials.text = intitals.getOrNull().orEmpty() +// binding.noNameIv.visibility = View.GONE +// } else { +// binding.nameInitials.text = "" +// binding.noNameIv.visibility = View.VISIBLE +// } +// nameEditText = text.toString() +// enableDisableJoinNowButton() +// } +// +// // Disable buttons +// track?.video?.let { +// binding.buttonToggleVideo.apply { +// isEnabled = (track?.video != null) +// +// if (it.isMute) { +// binding.buttonSwitchCamera.alpha = 0.5f +// binding.buttonSwitchCamera.isEnabled = false +// setIconDisabled(R.drawable.avd_video_on_to_off) +// } else { +// binding.buttonSwitchCamera.alpha = 1f +// binding.buttonSwitchCamera.isEnabled = true +// setIconEnabled(R.drawable.avd_video_off_to_on) +// } +// } +// } +// +// updateNoiseCancellationIcon() +// if (settings.lastUsedMeetingUrl.contains("/streaming/").not()) { +// +// updateJoinButtonTextIfHlsIsEnabled(room.localPeer?.hmsRole?.name) +// enableDisableJoinNowButton() +// binding.buttonJoinMeeting.visibility = View.VISIBLE +// +// } else { +// updateActionVolumeMenuIcon() +// binding.buttonJoinMeeting.visibility = View.VISIBLE +// } +// +// track?.audio?.let { +// binding.buttonToggleAudio.apply { +// isEnabled = (track?.audio != null) +// +// if (it.isMute) { +// binding.buttonToggleAudio.setIconDisabled(R.drawable.avd_mic_on_to_off) +// } else { +// binding.buttonToggleAudio.setIconEnabled(R.drawable.avd_mic_off_to_on) +// } +// } +// } +// }) +// +// } + +// private fun updateUiBasedOnPublishParams(publishParams: PublishParams?) { +// if (publishParams == null) return +// +// if (publishParams.allowed.contains("audio")) { +// binding.buttonToggleAudio.visibility = View.VISIBLE +// updateNoiseCancellationIcon() +// binding.buttonToggleAudio.startBounceAnimationUpwards() +// binding.iconOutputDevice.startBounceAnimationUpwards() +// } else { +// binding.buttonToggleAudio.visibility = View.GONE +// } +// +// if (publishParams.allowed.contains("video")) { +// binding.buttonToggleVideo.visibility = View.VISIBLE +// binding.buttonSwitchCamera.visibility = View.VISIBLE +// +// binding.buttonToggleVideo.startBounceAnimationUpwards() +// binding.buttonSwitchCamera.startBounceAnimationUpwards() +// +// binding.videoCardContainer.visibility = View.VISIBLE +// } else { +// binding.topMarging.setGuidelinePercent(0.35f) +// binding.buttonToggleVideo.visibility = View.GONE +// binding.buttonSwitchCamera.visibility = View.GONE +// binding.videoCardContainer.visibility = View.GONE +// binding.iconNoiseCancellation.visibility = View.GONE +// } +// } + +// private fun updateNetworkQualityView( +// downlinkScore: Int, context: Context, imageView: ImageView +// ) { +// NetworkQualityHelper.getNetworkResource(downlinkScore, context = requireContext()) +// .let { drawable -> +// imageView.setImageDrawable(drawable) +// if (drawable == null) { +// imageView.visibility = View.GONE +// binding.buttonNetworkQuality.visibility = View.GONE +// } else { +// imageView.visibility = View.VISIBLE +// binding.buttonNetworkQuality.visibility = View.VISIBLE +// binding.buttonNetworkQuality.startBounceAnimationUpwards() +// } +// } +// } + +// private fun getRemotePeers(hmsRoom: HMSRoom): ArrayList { +// val previewPeerList = arrayListOf() +// hmsRoom.peerList.forEach { +// if (it !is HMSLocalPeer) { +// previewPeerList.add(it) +// } +// } +// return previewPeerList +// } + + // INTERESTING + private fun initOnBackPress() { + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, + object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { +// meetingViewModel.leaveMeeting() + goToHomePage() + } + }) + } +} 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 e24a2b1f8..ffaaa3541 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 @@ -419,7 +419,11 @@ class MeetingFragment : Fragment() { } } - requireActivity().finish() + // Navigate to Meeting Feedback Fragment + findNavController().navigate( + MeetingFragmentDirections.actionMeetingFragmentToMeetingEndedFragment() + ) +// requireActivity().finish() } private fun updateRecordingViews(state: HMSRecordingState) { @@ -1530,7 +1534,7 @@ fun Caption(subtitles : AnnotatedString) { Box(modifier = Modifier) { Text( text = subtitles, -// modifier = Modifier.padding(Variables.Spacing1), +// modifier = Modifier.padding(Variables.Spacing2), style = TextStyle( fontSize = 14.sp, lineHeight = 20.sp, diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/HlsFragment.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/HlsFragment.kt index 6f867c41d..436f7db9a 100644 --- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/HlsFragment.kt +++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/activespeaker/HlsFragment.kt @@ -134,9 +134,9 @@ import live.hms.roomkit.ui.meeting.chat.rbac.RoleBasedChatBottomSheet import live.hms.roomkit.ui.meeting.compose.Variables import live.hms.roomkit.ui.meeting.compose.Variables.Companion.OnSurfaceHigh import live.hms.roomkit.ui.meeting.compose.Variables.Companion.PrimaryDefault -import live.hms.roomkit.ui.meeting.compose.Variables.Companion.Spacing0 import live.hms.roomkit.ui.meeting.compose.Variables.Companion.Spacing1 import live.hms.roomkit.ui.meeting.compose.Variables.Companion.Spacing2 +import live.hms.roomkit.ui.meeting.compose.Variables.Companion.Spacing4 import live.hms.roomkit.ui.polls.leaderboard.millisToText import live.hms.roomkit.ui.theme.applyTheme import live.hms.roomkit.util.contextSafe @@ -569,7 +569,7 @@ fun ChatHeader( fun getTimeDisplayNum(startedMillis: Long): String = millisToText(startedMillis, false, "s") - val contentPadding = Modifier.padding(Spacing2) + val contentPadding = Modifier.padding(Spacing4) var chatHeaderModifier = Modifier .fillMaxWidth() if(showExpandedView) { @@ -578,7 +578,7 @@ fun ChatHeader( Column { Column(modifier = chatHeaderModifier) { if (showExpandedView) { - Row(modifier = Modifier.padding(Spacing2)) { + Row(modifier = Modifier.padding(Spacing4)) { Text( "About Session", fontSize = 16.sp, @@ -603,7 +603,7 @@ fun ChatHeader( .height(1.dp) .fillMaxWidth() ) - // Spacer(modifier = Modifier.height(Spacing2)) + // Spacer(modifier = Modifier.height(Spacing4)) } Row( modifier = contentPadding, @@ -672,7 +672,7 @@ fun ChatHeader( if(showExpandedView && description != null) { Text( modifier = Modifier - .padding(horizontal = Spacing2) + .padding(horizontal = Spacing4) .verticalScroll(rememberScrollState()), text = description, fontSize = 14.sp, @@ -737,7 +737,7 @@ fun ChatHeaderExpandedPreview() { fun Chat(messages: List) { LazyColumn( modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(Spacing1), + verticalArrangement = Arrangement.spacedBy(Spacing2), horizontalAlignment = Alignment.Start, ) { items(messages) { @@ -826,7 +826,7 @@ fun GoLiveText(isLive : Boolean, behindBy: String, goLiveClicked : () -> Unit) { contentDescription = "Gray", modifier = Modifier // Margin right - .padding(end = Spacing1) + .padding(end = Spacing2) ) Text( text = if(isLive) "LIVE" else "GO LIVE", @@ -845,7 +845,7 @@ fun GoLiveText(isLive : Boolean, behindBy: String, goLiveClicked : () -> Unit) { text = behindBy, modifier = Modifier .clickable { goLiveClicked() } - .padding(start = Spacing1), + .padding(start = Spacing2), style = TextStyle( fontSize = 16.sp, lineHeight = 24.sp, @@ -1004,12 +1004,12 @@ fun HlsComposable( val subtitles by hlsViewModel.currentSubtitles.observeAsState() if(!subtitles.isNullOrEmpty()) { Box(modifier = Modifier - .padding(horizontal = Spacing0) + .padding(horizontal = Spacing1) .padding(bottom = 32.dp)) { Surface(color = Color.Black) { Text( text = subtitles ?: "", - modifier = Modifier.padding(Spacing1), + modifier = Modifier.padding(Spacing2), style = TextStyle( fontSize = 11.sp, lineHeight = 13.sp, @@ -1041,7 +1041,7 @@ fun HlsComposable( // There's one column, with two rows. // A spacer puts a gap between items on any one row. - Column(Modifier.padding(Spacing1)) { + Column(Modifier.padding(Spacing2)) { // Top Row Row { @@ -1050,11 +1050,11 @@ fun HlsComposable( if(!chatOpen) { HlsChatIcon(isChatEnabled, unreadMessagesCount, chatIconClicked) } if(areCaptionsSupported) { - Spacer(modifier = Modifier.padding(start = Spacing2)) + Spacer(modifier = Modifier.padding(start = Spacing4)) closedCaptionsButton() } - Spacer(modifier = Modifier.padding(start = Spacing2)) + Spacer(modifier = Modifier.padding(start = Spacing4)) SettingsButton(settingsButtonTapped) } @@ -1084,7 +1084,7 @@ fun HlsComposable( if (!isChatEnabled) { Box(modifier = Modifier .fillMaxSize() - .padding(vertical = Spacing0), + .padding(vertical = Spacing1), contentAlignment = Alignment.BottomCenter) { Row(horizontalArrangement = Arrangement.spacedBy(12.dp), ) { @@ -1116,7 +1116,7 @@ fun DvrControls(modifier: Modifier, player: HmsHlsPlayer, playPauseButton : @Com Spacer(Modifier.weight(1f)) AndroidView(modifier = Modifier .wrapContentSize() - .padding(top = Spacing1), factory = { + .padding(top = Spacing2), factory = { (LayoutInflater.from(it) .inflate(R.layout.player_controls, null) as PlayerControlView) .apply { @@ -1181,8 +1181,8 @@ fun CloseButton(onCloseButtonClicked: () -> Unit) { contentScale = ContentScale.None, modifier = Modifier .clickable { onCloseButtonClicked() } - .padding(Spacing0) .padding(Spacing1) + .padding(Spacing2) ) } diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/bottomsheets/EndCallBottomSheet.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/bottomsheets/EndCallBottomSheet.kt index f05d41cfb..864fc3c9a 100644 --- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/bottomsheets/EndCallBottomSheet.kt +++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/bottomsheets/EndCallBottomSheet.kt @@ -61,6 +61,7 @@ class EndCallBottomSheet : BottomSheetDialogFragment() { if (canEndRoom) { meetingViewModel.stopHls() meetingViewModel.endRoom(false) + dismissAllowingStateLoss() } else { meetingViewModel.stopHls() dismissAllowingStateLoss() diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/bottomsheets/LeaveCallBottomSheet.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/bottomsheets/LeaveCallBottomSheet.kt index 04dd55093..b364349c7 100644 --- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/bottomsheets/LeaveCallBottomSheet.kt +++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/bottomsheets/LeaveCallBottomSheet.kt @@ -63,6 +63,7 @@ class LeaveCallBottomSheet : BottomSheetDialogFragment() { meetingViewModel.stopHls() } meetingViewModel.leaveMeeting() + dismissAllowingStateLoss() } diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/compose/Variables.kt b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/compose/Variables.kt index 2d539fd26..07d4406d0 100644 --- a/room-kit/src/main/java/live/hms/roomkit/ui/meeting/compose/Variables.kt +++ b/room-kit/src/main/java/live/hms/roomkit/ui/meeting/compose/Variables.kt @@ -8,12 +8,16 @@ import live.hms.roomkit.ui.theme.getColorOrDefault class Variables { companion object { - val Spacing3: Dp = 24.dp - val Spacing4: Dp = 32.dp - val Spacing2 = 16.dp - val Spacing1 = 8.dp - val Spacing0 = 4.dp - val TwelveDp = 12.dp + val Spacing1 = 4.dp + val Spacing2 = 8.dp + val Spacing3 = 12.dp + val Spacing4 = 16.dp + val Spacing5 = 20.dp + val Spacing6 = 24.dp + val Spacing7 = 28.dp + val Spacing8 = 32.dp + val Spacing9 = 36.dp + val Spacing10 = 40.dp val PrimaryDefault : Color = Color(getColorOrDefault( HMSPrebuiltTheme.getColours()?.primaryDefault, HMSPrebuiltTheme.getDefaults().primary_default)) @@ -52,10 +56,18 @@ class Variables { HMSPrebuiltTheme.getColours()?.onSurfaceMedium, HMSPrebuiltTheme.getDefaults().onsurface_med_emp )) + val OnSurfaceLow = Color(getColorOrDefault( + HMSPrebuiltTheme.getColours()?.onSurfaceLow, + HMSPrebuiltTheme.getDefaults().onsurface_low_emp + )) val BorderBright = Color(getColorOrDefault( HMSPrebuiltTheme.getColours()?.borderBright, HMSPrebuiltTheme.getDefaults().border_bright )) + val BorderDefault = Color(getColorOrDefault( + HMSPrebuiltTheme.getColours()?.borderDefault, + HMSPrebuiltTheme.getDefaults().border_default + )) val BackgroundDim = Color(getColorOrDefault( HMSPrebuiltTheme.getColours()?.backgroundDim, diff --git a/room-kit/src/main/java/live/hms/roomkit/ui/theme/DefaultDarkThemeColours.kt b/room-kit/src/main/java/live/hms/roomkit/ui/theme/DefaultDarkThemeColours.kt index 2fb9a5647..a08d5aef3 100644 --- a/room-kit/src/main/java/live/hms/roomkit/ui/theme/DefaultDarkThemeColours.kt +++ b/room-kit/src/main/java/live/hms/roomkit/ui/theme/DefaultDarkThemeColours.kt @@ -29,6 +29,7 @@ data class DefaultDarkThemeColours( @SerializedName("error_default") val error_default: String = "#C74E5B", @SerializedName("error_container") val error_container: String = "#FFB2B6", @SerializedName("background_default") val background_default: String = "#0B0E15", - @SerializedName("border_bright") val border_bright: String = "#272A31" + @SerializedName("border_bright") val border_bright: String = "#272A31", + @SerializedName("border_default") val border_default: String = "#1D1F27" ) diff --git a/room-kit/src/main/res/layout/fragment_meeting_ended.xml b/room-kit/src/main/res/layout/fragment_meeting_ended.xml new file mode 100644 index 000000000..05a06c28b --- /dev/null +++ b/room-kit/src/main/res/layout/fragment_meeting_ended.xml @@ -0,0 +1,468 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/room-kit/src/main/res/navigation/meeting_nav_graph.xml b/room-kit/src/main/res/navigation/meeting_nav_graph.xml index 279fe601e..c9108f5da 100644 --- a/room-kit/src/main/res/navigation/meeting_nav_graph.xml +++ b/room-kit/src/main/res/navigation/meeting_nav_graph.xml @@ -66,8 +66,19 @@ + + + +