@@ -25,6 +25,30 @@ import android.widget.Toast
25
25
import androidx.activity.OnBackPressedCallback
26
26
import androidx.activity.result.contract.ActivityResultContracts
27
27
import androidx.appcompat.app.AlertDialog
28
+ import androidx.compose.foundation.background
29
+ import androidx.compose.foundation.layout.Arrangement
30
+ import androidx.compose.foundation.layout.Box
31
+ import androidx.compose.foundation.layout.Column
32
+ import androidx.compose.foundation.layout.fillMaxWidth
33
+ import androidx.compose.foundation.layout.padding
34
+ import androidx.compose.foundation.layout.requiredHeightIn
35
+ import androidx.compose.foundation.rememberScrollState
36
+ import androidx.compose.foundation.verticalScroll
37
+ import androidx.compose.material3.Text
38
+ import androidx.compose.runtime.Composable
39
+ import androidx.compose.runtime.LaunchedEffect
40
+ import androidx.compose.runtime.getValue
41
+ import androidx.compose.runtime.livedata.observeAsState
42
+ import androidx.compose.ui.Modifier
43
+ import androidx.compose.ui.draw.clip
44
+ import androidx.compose.ui.graphics.toArgb
45
+ import androidx.compose.ui.platform.ComposeView
46
+ import androidx.compose.ui.platform.ViewCompositionStrategy
47
+ import androidx.compose.ui.text.AnnotatedString
48
+ import androidx.compose.ui.text.TextStyle
49
+ import androidx.compose.ui.tooling.preview.Preview
50
+ import androidx.compose.ui.unit.dp
51
+ import androidx.compose.ui.unit.sp
28
52
import androidx.core.os.bundleOf
29
53
import androidx.core.view.*
30
54
import androidx.fragment.app.Fragment
@@ -64,6 +88,8 @@ import live.hms.roomkit.ui.meeting.chat.combined.OPEN_TO_PARTICIPANTS
64
88
import live.hms.roomkit.ui.meeting.chat.combined.PinnedMessageUiUseCase
65
89
import live.hms.roomkit.ui.meeting.chat.rbac.RoleBasedChatBottomSheet
66
90
import live.hms.roomkit.ui.meeting.commons.VideoGridBaseFragment
91
+ import live.hms.roomkit.ui.meeting.compose.Variables
92
+ import live.hms.roomkit.ui.meeting.participants.DIRECTLY_OPENED
67
93
import live.hms.roomkit.ui.meeting.participants.ParticipantsFragment
68
94
import live.hms.roomkit.ui.meeting.pinnedvideo.PinnedVideoFragment
69
95
import live.hms.roomkit.ui.meeting.videogrid.VideoGridFragment
@@ -260,6 +286,7 @@ class MeetingFragment : Fragment() {
260
286
override fun onViewCreated (view : View , savedInstanceState : Bundle ? ) {
261
287
super .onViewCreated(view, savedInstanceState)
262
288
binding.applyTheme()
289
+ addComposable(binding.composeView)
263
290
264
291
if (savedInstanceState != null ) {
265
292
// Recreated Fragment
@@ -303,6 +330,21 @@ class MeetingFragment : Fragment() {
303
330
}
304
331
}
305
332
333
+ private fun addComposable (composeView : ComposeView ) = composeView.apply {
334
+ setViewCompositionStrategy(ViewCompositionStrategy .DisposeOnViewTreeLifecycleDestroyed )
335
+ setContent {
336
+ val captionsEnabled by meetingViewModel.areCaptionsEnabledByUser.observeAsState(false )
337
+ val subtitles by meetingViewModel.captions.observeAsState()
338
+ val topBottom by meetingViewModel.transcriptionsPosition.observeAsState()
339
+ if ( ! subtitles.isNullOrEmpty() && captionsEnabled) {
340
+ Column (modifier = Modifier .padding(start = 8 .dp, top = 8 .dp, end = 8 .dp, bottom = 16 .dp),
341
+ verticalArrangement = if (topBottom == MeetingViewModel .TranscriptionsPosition .TOP ) Arrangement .Top else Arrangement .Bottom ) {
342
+ Captions (subtitles)
343
+ }
344
+ }
345
+ }
346
+ }
347
+
306
348
private fun initializeUI () {
307
349
initButtons()
308
350
initObservers()
@@ -348,10 +390,16 @@ class MeetingFragment : Fragment() {
348
390
meetingViewModel.peerLeaveUpdate.observe(viewLifecycleOwner) {
349
391
chatViewModel.updatePeerLeave(it)
350
392
}
351
- if (meetingViewModel.prebuiltInfoContainer.chatInitialStateOpen()) {
393
+ chatButtonEnabled(meetingViewModel.prebuiltInfoContainer.chatInitialStateOpen())
394
+ }
395
+
396
+ private fun chatButtonEnabled (enable : Boolean ) {
397
+ if (enable) {
352
398
binding.buttonOpenChat.setIconDisabled(R .drawable.ic_chat_message)
399
+ meetingViewModel.transcriptionsPosition.postValue(MeetingViewModel .TranscriptionsPosition .TOP )
353
400
} else {
354
401
binding.buttonOpenChat.setIconEnabled(R .drawable.ic_chat_message)
402
+ meetingViewModel.transcriptionsPosition.postValue(MeetingViewModel .TranscriptionsPosition .BOTTOM )
355
403
}
356
404
}
357
405
@@ -865,11 +913,7 @@ class MeetingFragment : Fragment() {
865
913
} else {
866
914
binding.messageMenu.visibility = View .GONE
867
915
}
868
- if (meetingViewModel.prebuiltInfoContainer.chatInitialStateOpen()) {
869
- binding.buttonOpenChat.setIconDisabled(R .drawable.ic_chat_message)
870
- } else {
871
- binding.buttonOpenChat.setIconEnabled(R .drawable.ic_chat_message)
872
- }
916
+ chatButtonEnabled(meetingViewModel.prebuiltInfoContainer.chatInitialStateOpen())
873
917
}
874
918
var controlBarsVisible = true
875
919
private fun setupConfiguration (mode : MeetingViewMode ) {
@@ -981,6 +1025,8 @@ class MeetingFragment : Fragment() {
981
1025
982
1026
private fun showControlBars (shouldHideAfterDelay : Boolean ) {
983
1027
controlBarsVisible = true
1028
+ binding.bottomControls.maxHeight = Int .MAX_VALUE
1029
+
984
1030
binding.topMenu.animate()
985
1031
?.translationY(0f )?.setDuration(300 )?.setListener(object : AnimatorListener {
986
1032
override fun onAnimationStart (animation : Animator ) {
@@ -1089,7 +1135,8 @@ class MeetingFragment : Fragment() {
1089
1135
}
1090
1136
1091
1137
override fun onAnimationEnd (animation : Animator ) {
1092
- bottomMenu.visibility = View .GONE
1138
+ bottomMenu.visibility = View .INVISIBLE
1139
+ bottomMenu.maxHeight = 0
1093
1140
controlBarsVisible = false
1094
1141
}
1095
1142
@@ -1155,15 +1202,21 @@ class MeetingFragment : Fragment() {
1155
1202
onScreenShareClicked = { startOrStopScreenShare() },
1156
1203
onBRBClicked = { meetingViewModel.toggleBRB() },
1157
1204
onPeerListClicked = {
1205
+ meetingViewModel.tempHideCaptions()
1158
1206
if ( meetingViewModel.prebuiltInfoContainer.isChatOverlay() ||
1159
1207
! meetingViewModel.prebuiltInfoContainer.isChatEnabled()
1160
1208
) {
1161
1209
if (isOverlayChatVisible()){
1162
1210
toggleChatVisibility()
1163
1211
}
1212
+ val args = Bundle ()
1213
+ .apply {
1214
+ putBoolean(DIRECTLY_OPENED , true )
1215
+ }
1216
+
1164
1217
childFragmentManager
1165
1218
.beginTransaction()
1166
- .add(R .id.fragment_container, ParticipantsFragment ())
1219
+ .add(R .id.fragment_container, ParticipantsFragment (). apply { arguments = args } )
1167
1220
.commit()
1168
1221
} else {
1169
1222
val args = Bundle ()
@@ -1220,6 +1273,7 @@ class MeetingFragment : Fragment() {
1220
1273
{
1221
1274
findNavController().navigate(MeetingFragmentDirections .actionMeetingFragmentToPollsCreationFragment())
1222
1275
})
1276
+ meetingViewModel.tempHideCaptions()
1223
1277
settingsBottomSheet.show(
1224
1278
requireActivity().supportFragmentManager,
1225
1279
" settingsBottomSheet"
@@ -1360,12 +1414,7 @@ class MeetingFragment : Fragment() {
1360
1414
}
1361
1415
}
1362
1416
1363
- if (binding.chatView.visibility == View .VISIBLE ) {
1364
-
1365
- binding.buttonOpenChat.setIconDisabled(R .drawable.ic_chat_message)
1366
- } else {
1367
- binding.buttonOpenChat.setIconEnabled(R .drawable.ic_chat_message)
1368
- }
1417
+ chatButtonEnabled(binding.chatView.visibility == View .VISIBLE )
1369
1418
}
1370
1419
1371
1420
private fun startOrStopScreenShare () {
@@ -1439,4 +1488,51 @@ class MeetingFragment : Fragment() {
1439
1488
LeaveCallBottomSheet ().show(parentFragmentManager, null )
1440
1489
}
1441
1490
}
1491
+ }
1492
+
1493
+ @Preview
1494
+ @Composable
1495
+ fun DisplayCaptions () {
1496
+ Captions (subtitles = listOf (TranscriptViewHolder (" Cat" , " Dinner time" , peerId = " a" ),
1497
+ TranscriptViewHolder (" Dog" ," Time for a walk" , peerId = " b" )))
1498
+ }
1499
+
1500
+ @Composable
1501
+ fun Captions (subtitles : List <TranscriptViewHolder >? ) {
1502
+ val scrollState = rememberScrollState()
1503
+ LaunchedEffect (subtitles) {
1504
+ scrollState.scrollTo(scrollState.maxValue)
1505
+ }
1506
+
1507
+ Column (
1508
+ Modifier
1509
+ .background(color = androidx.compose.ui.graphics.Color (Variables .BackgroundDim .toArgb()))
1510
+ .fillMaxWidth()
1511
+ .requiredHeightIn(
1512
+ min = 27 .dp,
1513
+ max = 110 .dp
1514
+ )
1515
+ .verticalScroll(scrollState)
1516
+ .padding(12 .dp),
1517
+ ) {
1518
+ subtitles?.forEach {
1519
+ Caption (it.getSubtitle())
1520
+ }
1521
+ }
1522
+
1523
+ }
1524
+ @Composable
1525
+ fun Caption (subtitles : AnnotatedString ) {
1526
+ Box (modifier = Modifier ) {
1527
+ Text (
1528
+ text = subtitles,
1529
+ // modifier = Modifier.padding(Variables.Spacing1),
1530
+ style = TextStyle (
1531
+ fontSize = 14 .sp,
1532
+ lineHeight = 20 .sp,
1533
+ color = androidx.compose.ui.graphics.Color .White ,
1534
+ letterSpacing = 0.25 .sp,
1535
+ )
1536
+ )
1537
+ }
1442
1538
}
0 commit comments