davidliu

permissions toggle

... ... @@ -72,6 +72,9 @@ class CallViewModel(
private val mutableDataReceived = MutableSharedFlow<String>()
val dataReceived = mutableDataReceived
private val mutablePermissionAllowed = MutableStateFlow(true)
val permissionAllowed = mutablePermissionAllowed.hide()
init {
viewModelScope.launch {
... ... @@ -238,6 +241,11 @@ class CallViewModel(
room.value?.localParticipant?.publishData(message.toByteArray(Charsets.UTF_8))
}
}
fun toggleSubscriptionPermissions() {
mutablePermissionAllowed.value = !mutablePermissionAllowed.value
room.value?.localParticipant?.setTrackSubscriptionPermissions(mutablePermissionAllowed.value)
}
}
private fun <T> LiveData<T>.hide(): LiveData<T> = this
... ...
<!-- drawable/account_cancel.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M10 4A4 4 0 0 0 6 8A4 4 0 0 0 10 12A4 4 0 0 0 14 8A4 4 0 0 0 10 4M17.5 13C15 13 13 15 13 17.5C13 20 15 22 17.5 22C20 22 22 20 22 17.5C22 15 20 13 17.5 13M10 14C5.58 14 2 15.79 2 18V20H11.5A6.5 6.5 0 0 1 11 17.5A6.5 6.5 0 0 1 11.95 14.14C11.32 14.06 10.68 14 10 14M17.5 14.5C19.16 14.5 20.5 15.84 20.5 17.5C20.5 18.06 20.35 18.58 20.08 19L16 14.92C16.42 14.65 16.94 14.5 17.5 14.5M14.92 16L19 20.08C18.58 20.35 18.06 20.5 17.5 20.5C15.84 20.5 14.5 19.16 14.5 17.5C14.5 16.94 14.65 16.42 14.92 16Z" />
</vector>
\ No newline at end of file
... ...
<!-- drawable/account_cancel_outline.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M10 4A4 4 0 0 0 6 8A4 4 0 0 0 10 12A4 4 0 0 0 14 8A4 4 0 0 0 10 4M10 6A2 2 0 0 1 12 8A2 2 0 0 1 10 10A2 2 0 0 1 8 8A2 2 0 0 1 10 6M10 13C7.33 13 2 14.33 2 17V20H11.5A6.5 6.5 0 0 1 11.03 18.1H3.9V17C3.9 16.36 7.03 14.9 10 14.9C10.5 14.9 11 14.95 11.5 15.03A6.5 6.5 0 0 1 12.55 13.29C11.61 13.1 10.71 13 10 13M17.5 13C15 13 13 15 13 17.5C13 20 15 22 17.5 22C20 22 22 20 22 17.5C22 15 20 13 17.5 13M17.5 14.5C19.16 14.5 20.5 15.84 20.5 17.5C20.5 18.06 20.35 18.58 20.08 19L16 14.92C16.42 14.65 16.94 14.5 17.5 14.5M14.92 16L19 20.08C18.58 20.35 18.06 20.5 17.5 20.5C15.84 20.5 14.5 19.16 14.5 17.5C14.5 16.94 14.65 16.42 14.92 16Z" />
</vector>
\ No newline at end of file
... ...
... ... @@ -96,6 +96,7 @@ class CallActivity : AppCompatActivity() {
val videoEnabled by viewModel.cameraEnabled.observeAsState(true)
val flipButtonEnabled by viewModel.flipButtonVideoEnabled.observeAsState(true)
val screencastEnabled by viewModel.screenshareEnabled.observeAsState(false)
val permissionAllowed by viewModel.permissionAllowed.collectAsState()
Content(
room,
participants,
... ... @@ -105,6 +106,7 @@ class CallActivity : AppCompatActivity() {
videoEnabled,
flipButtonEnabled,
screencastEnabled,
permissionAllowed = permissionAllowed,
onExitClick = { finish() },
onSendMessage = { viewModel.sendData(it) }
)
... ... @@ -149,6 +151,7 @@ class CallActivity : AppCompatActivity() {
videoEnabled: Boolean = true,
flipButtonEnabled: Boolean = true,
screencastEnabled: Boolean = false,
permissionAllowed: Boolean = true,
onExitClick: () -> Unit = {},
error: Throwable? = null,
onSnackbarDismiss: () -> Unit = {},
... ... @@ -210,7 +213,7 @@ class CallActivity : AppCompatActivity() {
}
// Control bar for any switches such as mic/camera enable/disable.
Row(
Column(
modifier = Modifier
.padding(top = 10.dp, bottom = 20.dp)
.fillMaxWidth()
... ... @@ -219,141 +222,170 @@ class CallActivity : AppCompatActivity() {
width = Dimension.fillToConstraints
height = Dimension.wrapContent
},
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.Bottom,
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally
) {
val controlSize = 40.dp
val controlPadding = 4.dp
Surface(
onClick = { viewModel.setMicEnabled(!micEnabled) },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
val resource =
if (micEnabled) R.drawable.outline_mic_24 else R.drawable.outline_mic_off_24
Icon(
painterResource(id = resource),
contentDescription = "Mic",
tint = Color.White,
)
}
Surface(
onClick = { viewModel.setCameraEnabled(!videoEnabled) },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
val resource =
if (videoEnabled) R.drawable.outline_videocam_24 else R.drawable.outline_videocam_off_24
Icon(
painterResource(id = resource),
contentDescription = "Video",
tint = Color.White,
)
}
Surface(
onClick = { viewModel.flipCamera() },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
Icon(
painterResource(id = R.drawable.outline_flip_camera_android_24),
contentDescription = "Flip Camera",
tint = Color.White,
)
}
Surface(
onClick = {
if (!screencastEnabled) {
requestMediaProjection()
} else {
viewModel.stopScreenCapture()
}
},
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.Bottom,
) {
val resource =
if (screencastEnabled) R.drawable.baseline_cast_connected_24 else R.drawable.baseline_cast_24
Icon(
painterResource(id = resource),
contentDescription = "Flip Camera",
tint = Color.White,
)
}
Surface(
onClick = { viewModel.setMicEnabled(!micEnabled) },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
val resource =
if (micEnabled) R.drawable.outline_mic_24 else R.drawable.outline_mic_off_24
Icon(
painterResource(id = resource),
contentDescription = "Mic",
tint = Color.White,
)
}
Surface(
onClick = { viewModel.setCameraEnabled(!videoEnabled) },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
val resource =
if (videoEnabled) R.drawable.outline_videocam_24 else R.drawable.outline_videocam_off_24
Icon(
painterResource(id = resource),
contentDescription = "Video",
tint = Color.White,
)
}
Surface(
onClick = { viewModel.flipCamera() },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
Icon(
painterResource(id = R.drawable.outline_flip_camera_android_24),
contentDescription = "Flip Camera",
tint = Color.White,
)
}
Surface(
onClick = {
if (!screencastEnabled) {
requestMediaProjection()
} else {
viewModel.stopScreenCapture()
}
},
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
val resource =
if (screencastEnabled) R.drawable.baseline_cast_connected_24 else R.drawable.baseline_cast_24
Icon(
painterResource(id = resource),
contentDescription = "Flip Camera",
tint = Color.White,
)
}
var showMessageDialog by remember { mutableStateOf(false) }
var messageToSend by remember { mutableStateOf("") }
Surface(
onClick = { showMessageDialog = true },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
Icon(
painterResource(id = R.drawable.baseline_chat_24),
contentDescription = "Send Message",
tint = Color.White,
)
}
var showMessageDialog by remember { mutableStateOf(false) }
var messageToSend by remember { mutableStateOf("") }
Surface(
onClick = { showMessageDialog = true },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
Icon(
painterResource(id = R.drawable.baseline_chat_24),
contentDescription = "Send Message",
tint = Color.White,
)
}
if (showMessageDialog) {
AlertDialog(
onDismissRequest = {
showMessageDialog = false
messageToSend = ""
},
title = {
Text(text = "Send Message")
},
text = {
OutlinedTextField(
value = messageToSend,
onValueChange = { messageToSend = it },
label = { Text("Message") },
modifier = Modifier.fillMaxWidth(),
)
},
confirmButton = {
Button(
onClick = {
onSendMessage(messageToSend)
showMessageDialog = false
messageToSend = ""
}
) { Text("Send") }
},
dismissButton = {
Button(
onClick = {
showMessageDialog = false
messageToSend = ""
}
) { Text("Cancel") }
},
backgroundColor = Color.Black,
)
if (showMessageDialog) {
AlertDialog(
onDismissRequest = {
showMessageDialog = false
messageToSend = ""
},
title = {
Text(text = "Send Message")
},
text = {
OutlinedTextField(
value = messageToSend,
onValueChange = { messageToSend = it },
label = { Text("Message") },
modifier = Modifier.fillMaxWidth(),
)
},
confirmButton = {
Button(
onClick = {
onSendMessage(messageToSend)
showMessageDialog = false
messageToSend = ""
}
) { Text("Send") }
},
dismissButton = {
Button(
onClick = {
showMessageDialog = false
messageToSend = ""
}
) { Text("Cancel") }
},
backgroundColor = Color.Black,
)
}
Surface(
onClick = { onExitClick() },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
Icon(
painterResource(id = R.drawable.ic_baseline_cancel_24),
contentDescription = "Flip Camera",
tint = Color.White,
)
}
}
Surface(
onClick = { onExitClick() },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
Spacer(modifier = Modifier.height(10.dp))
Row(
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.Bottom,
) {
Icon(
painterResource(id = R.drawable.ic_baseline_cancel_24),
contentDescription = "Flip Camera",
tint = Color.White,
)
Surface(
onClick = { viewModel.toggleSubscriptionPermissions() },
indication = rememberRipple(false),
modifier = Modifier
.size(controlSize)
.padding(controlPadding)
) {
val resource =
if (permissionAllowed) R.drawable.account_cancel_outline else R.drawable.account_cancel
Icon(
painterResource(id = resource),
contentDescription = "Permissions",
tint = Color.White,
)
}
}
}
... ...