正在显示
4 个修改的文件
包含
184 行增加
和
128 行删除
| @@ -72,6 +72,9 @@ class CallViewModel( | @@ -72,6 +72,9 @@ class CallViewModel( | ||
| 72 | private val mutableDataReceived = MutableSharedFlow<String>() | 72 | private val mutableDataReceived = MutableSharedFlow<String>() |
| 73 | val dataReceived = mutableDataReceived | 73 | val dataReceived = mutableDataReceived |
| 74 | 74 | ||
| 75 | + private val mutablePermissionAllowed = MutableStateFlow(true) | ||
| 76 | + val permissionAllowed = mutablePermissionAllowed.hide() | ||
| 77 | + | ||
| 75 | init { | 78 | init { |
| 76 | viewModelScope.launch { | 79 | viewModelScope.launch { |
| 77 | 80 | ||
| @@ -238,6 +241,11 @@ class CallViewModel( | @@ -238,6 +241,11 @@ class CallViewModel( | ||
| 238 | room.value?.localParticipant?.publishData(message.toByteArray(Charsets.UTF_8)) | 241 | room.value?.localParticipant?.publishData(message.toByteArray(Charsets.UTF_8)) |
| 239 | } | 242 | } |
| 240 | } | 243 | } |
| 244 | + | ||
| 245 | + fun toggleSubscriptionPermissions() { | ||
| 246 | + mutablePermissionAllowed.value = !mutablePermissionAllowed.value | ||
| 247 | + room.value?.localParticipant?.setTrackSubscriptionPermissions(mutablePermissionAllowed.value) | ||
| 248 | + } | ||
| 241 | } | 249 | } |
| 242 | 250 | ||
| 243 | private fun <T> LiveData<T>.hide(): LiveData<T> = this | 251 | private fun <T> LiveData<T>.hide(): LiveData<T> = this |
| 1 | +<!-- drawable/account_cancel.xml --> | ||
| 2 | +<vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:height="24dp" | ||
| 4 | + android:width="24dp" | ||
| 5 | + android:viewportWidth="24" | ||
| 6 | + android:viewportHeight="24"> | ||
| 7 | + <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" /> | ||
| 8 | +</vector> |
| 1 | +<!-- drawable/account_cancel_outline.xml --> | ||
| 2 | +<vector xmlns:android="http://schemas.android.com/apk/res/android" | ||
| 3 | + android:height="24dp" | ||
| 4 | + android:width="24dp" | ||
| 5 | + android:viewportWidth="24" | ||
| 6 | + android:viewportHeight="24"> | ||
| 7 | + <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" /> | ||
| 8 | +</vector> |
| @@ -96,6 +96,7 @@ class CallActivity : AppCompatActivity() { | @@ -96,6 +96,7 @@ class CallActivity : AppCompatActivity() { | ||
| 96 | val videoEnabled by viewModel.cameraEnabled.observeAsState(true) | 96 | val videoEnabled by viewModel.cameraEnabled.observeAsState(true) |
| 97 | val flipButtonEnabled by viewModel.flipButtonVideoEnabled.observeAsState(true) | 97 | val flipButtonEnabled by viewModel.flipButtonVideoEnabled.observeAsState(true) |
| 98 | val screencastEnabled by viewModel.screenshareEnabled.observeAsState(false) | 98 | val screencastEnabled by viewModel.screenshareEnabled.observeAsState(false) |
| 99 | + val permissionAllowed by viewModel.permissionAllowed.collectAsState() | ||
| 99 | Content( | 100 | Content( |
| 100 | room, | 101 | room, |
| 101 | participants, | 102 | participants, |
| @@ -105,6 +106,7 @@ class CallActivity : AppCompatActivity() { | @@ -105,6 +106,7 @@ class CallActivity : AppCompatActivity() { | ||
| 105 | videoEnabled, | 106 | videoEnabled, |
| 106 | flipButtonEnabled, | 107 | flipButtonEnabled, |
| 107 | screencastEnabled, | 108 | screencastEnabled, |
| 109 | + permissionAllowed = permissionAllowed, | ||
| 108 | onExitClick = { finish() }, | 110 | onExitClick = { finish() }, |
| 109 | onSendMessage = { viewModel.sendData(it) } | 111 | onSendMessage = { viewModel.sendData(it) } |
| 110 | ) | 112 | ) |
| @@ -149,6 +151,7 @@ class CallActivity : AppCompatActivity() { | @@ -149,6 +151,7 @@ class CallActivity : AppCompatActivity() { | ||
| 149 | videoEnabled: Boolean = true, | 151 | videoEnabled: Boolean = true, |
| 150 | flipButtonEnabled: Boolean = true, | 152 | flipButtonEnabled: Boolean = true, |
| 151 | screencastEnabled: Boolean = false, | 153 | screencastEnabled: Boolean = false, |
| 154 | + permissionAllowed: Boolean = true, | ||
| 152 | onExitClick: () -> Unit = {}, | 155 | onExitClick: () -> Unit = {}, |
| 153 | error: Throwable? = null, | 156 | error: Throwable? = null, |
| 154 | onSnackbarDismiss: () -> Unit = {}, | 157 | onSnackbarDismiss: () -> Unit = {}, |
| @@ -210,7 +213,7 @@ class CallActivity : AppCompatActivity() { | @@ -210,7 +213,7 @@ class CallActivity : AppCompatActivity() { | ||
| 210 | } | 213 | } |
| 211 | 214 | ||
| 212 | // Control bar for any switches such as mic/camera enable/disable. | 215 | // Control bar for any switches such as mic/camera enable/disable. |
| 213 | - Row( | 216 | + Column( |
| 214 | modifier = Modifier | 217 | modifier = Modifier |
| 215 | .padding(top = 10.dp, bottom = 20.dp) | 218 | .padding(top = 10.dp, bottom = 20.dp) |
| 216 | .fillMaxWidth() | 219 | .fillMaxWidth() |
| @@ -219,141 +222,170 @@ class CallActivity : AppCompatActivity() { | @@ -219,141 +222,170 @@ class CallActivity : AppCompatActivity() { | ||
| 219 | width = Dimension.fillToConstraints | 222 | width = Dimension.fillToConstraints |
| 220 | height = Dimension.wrapContent | 223 | height = Dimension.wrapContent |
| 221 | }, | 224 | }, |
| 222 | - horizontalArrangement = Arrangement.SpaceEvenly, | ||
| 223 | - verticalAlignment = Alignment.Bottom, | 225 | + verticalArrangement = Arrangement.SpaceEvenly, |
| 226 | + horizontalAlignment = Alignment.CenterHorizontally | ||
| 224 | ) { | 227 | ) { |
| 228 | + | ||
| 225 | val controlSize = 40.dp | 229 | val controlSize = 40.dp |
| 226 | val controlPadding = 4.dp | 230 | val controlPadding = 4.dp |
| 227 | - Surface( | ||
| 228 | - onClick = { viewModel.setMicEnabled(!micEnabled) }, | ||
| 229 | - indication = rememberRipple(false), | ||
| 230 | - modifier = Modifier | ||
| 231 | - .size(controlSize) | ||
| 232 | - .padding(controlPadding) | ||
| 233 | - ) { | ||
| 234 | - val resource = | ||
| 235 | - if (micEnabled) R.drawable.outline_mic_24 else R.drawable.outline_mic_off_24 | ||
| 236 | - Icon( | ||
| 237 | - painterResource(id = resource), | ||
| 238 | - contentDescription = "Mic", | ||
| 239 | - tint = Color.White, | ||
| 240 | - ) | ||
| 241 | - } | ||
| 242 | - Surface( | ||
| 243 | - onClick = { viewModel.setCameraEnabled(!videoEnabled) }, | ||
| 244 | - indication = rememberRipple(false), | ||
| 245 | - modifier = Modifier | ||
| 246 | - .size(controlSize) | ||
| 247 | - .padding(controlPadding) | ||
| 248 | - ) { | ||
| 249 | - val resource = | ||
| 250 | - if (videoEnabled) R.drawable.outline_videocam_24 else R.drawable.outline_videocam_off_24 | ||
| 251 | - Icon( | ||
| 252 | - painterResource(id = resource), | ||
| 253 | - contentDescription = "Video", | ||
| 254 | - tint = Color.White, | ||
| 255 | - ) | ||
| 256 | - } | ||
| 257 | - Surface( | ||
| 258 | - onClick = { viewModel.flipCamera() }, | ||
| 259 | - indication = rememberRipple(false), | ||
| 260 | - modifier = Modifier | ||
| 261 | - .size(controlSize) | ||
| 262 | - .padding(controlPadding) | ||
| 263 | - ) { | ||
| 264 | - Icon( | ||
| 265 | - painterResource(id = R.drawable.outline_flip_camera_android_24), | ||
| 266 | - contentDescription = "Flip Camera", | ||
| 267 | - tint = Color.White, | ||
| 268 | - ) | ||
| 269 | - } | ||
| 270 | - Surface( | ||
| 271 | - onClick = { | ||
| 272 | - if (!screencastEnabled) { | ||
| 273 | - requestMediaProjection() | ||
| 274 | - } else { | ||
| 275 | - viewModel.stopScreenCapture() | ||
| 276 | - } | ||
| 277 | - }, | ||
| 278 | - indication = rememberRipple(false), | ||
| 279 | - modifier = Modifier | ||
| 280 | - .size(controlSize) | ||
| 281 | - .padding(controlPadding) | 231 | + Row( |
| 232 | + horizontalArrangement = Arrangement.SpaceEvenly, | ||
| 233 | + verticalAlignment = Alignment.Bottom, | ||
| 282 | ) { | 234 | ) { |
| 283 | - val resource = | ||
| 284 | - if (screencastEnabled) R.drawable.baseline_cast_connected_24 else R.drawable.baseline_cast_24 | ||
| 285 | - Icon( | ||
| 286 | - painterResource(id = resource), | ||
| 287 | - contentDescription = "Flip Camera", | ||
| 288 | - tint = Color.White, | ||
| 289 | - ) | ||
| 290 | - } | 235 | + Surface( |
| 236 | + onClick = { viewModel.setMicEnabled(!micEnabled) }, | ||
| 237 | + indication = rememberRipple(false), | ||
| 238 | + modifier = Modifier | ||
| 239 | + .size(controlSize) | ||
| 240 | + .padding(controlPadding) | ||
| 241 | + ) { | ||
| 242 | + val resource = | ||
| 243 | + if (micEnabled) R.drawable.outline_mic_24 else R.drawable.outline_mic_off_24 | ||
| 244 | + Icon( | ||
| 245 | + painterResource(id = resource), | ||
| 246 | + contentDescription = "Mic", | ||
| 247 | + tint = Color.White, | ||
| 248 | + ) | ||
| 249 | + } | ||
| 250 | + Surface( | ||
| 251 | + onClick = { viewModel.setCameraEnabled(!videoEnabled) }, | ||
| 252 | + indication = rememberRipple(false), | ||
| 253 | + modifier = Modifier | ||
| 254 | + .size(controlSize) | ||
| 255 | + .padding(controlPadding) | ||
| 256 | + ) { | ||
| 257 | + val resource = | ||
| 258 | + if (videoEnabled) R.drawable.outline_videocam_24 else R.drawable.outline_videocam_off_24 | ||
| 259 | + Icon( | ||
| 260 | + painterResource(id = resource), | ||
| 261 | + contentDescription = "Video", | ||
| 262 | + tint = Color.White, | ||
| 263 | + ) | ||
| 264 | + } | ||
| 265 | + Surface( | ||
| 266 | + onClick = { viewModel.flipCamera() }, | ||
| 267 | + indication = rememberRipple(false), | ||
| 268 | + modifier = Modifier | ||
| 269 | + .size(controlSize) | ||
| 270 | + .padding(controlPadding) | ||
| 271 | + ) { | ||
| 272 | + Icon( | ||
| 273 | + painterResource(id = R.drawable.outline_flip_camera_android_24), | ||
| 274 | + contentDescription = "Flip Camera", | ||
| 275 | + tint = Color.White, | ||
| 276 | + ) | ||
| 277 | + } | ||
| 278 | + Surface( | ||
| 279 | + onClick = { | ||
| 280 | + if (!screencastEnabled) { | ||
| 281 | + requestMediaProjection() | ||
| 282 | + } else { | ||
| 283 | + viewModel.stopScreenCapture() | ||
| 284 | + } | ||
| 285 | + }, | ||
| 286 | + indication = rememberRipple(false), | ||
| 287 | + modifier = Modifier | ||
| 288 | + .size(controlSize) | ||
| 289 | + .padding(controlPadding) | ||
| 290 | + ) { | ||
| 291 | + val resource = | ||
| 292 | + if (screencastEnabled) R.drawable.baseline_cast_connected_24 else R.drawable.baseline_cast_24 | ||
| 293 | + Icon( | ||
| 294 | + painterResource(id = resource), | ||
| 295 | + contentDescription = "Flip Camera", | ||
| 296 | + tint = Color.White, | ||
| 297 | + ) | ||
| 298 | + } | ||
| 291 | 299 | ||
| 292 | - var showMessageDialog by remember { mutableStateOf(false) } | ||
| 293 | - var messageToSend by remember { mutableStateOf("") } | ||
| 294 | - Surface( | ||
| 295 | - onClick = { showMessageDialog = true }, | ||
| 296 | - indication = rememberRipple(false), | ||
| 297 | - modifier = Modifier | ||
| 298 | - .size(controlSize) | ||
| 299 | - .padding(controlPadding) | ||
| 300 | - ) { | ||
| 301 | - Icon( | ||
| 302 | - painterResource(id = R.drawable.baseline_chat_24), | ||
| 303 | - contentDescription = "Send Message", | ||
| 304 | - tint = Color.White, | ||
| 305 | - ) | ||
| 306 | - } | 300 | + var showMessageDialog by remember { mutableStateOf(false) } |
| 301 | + var messageToSend by remember { mutableStateOf("") } | ||
| 302 | + Surface( | ||
| 303 | + onClick = { showMessageDialog = true }, | ||
| 304 | + indication = rememberRipple(false), | ||
| 305 | + modifier = Modifier | ||
| 306 | + .size(controlSize) | ||
| 307 | + .padding(controlPadding) | ||
| 308 | + ) { | ||
| 309 | + Icon( | ||
| 310 | + painterResource(id = R.drawable.baseline_chat_24), | ||
| 311 | + contentDescription = "Send Message", | ||
| 312 | + tint = Color.White, | ||
| 313 | + ) | ||
| 314 | + } | ||
| 307 | 315 | ||
| 308 | - if (showMessageDialog) { | ||
| 309 | - AlertDialog( | ||
| 310 | - onDismissRequest = { | ||
| 311 | - showMessageDialog = false | ||
| 312 | - messageToSend = "" | ||
| 313 | - }, | ||
| 314 | - title = { | ||
| 315 | - Text(text = "Send Message") | ||
| 316 | - }, | ||
| 317 | - text = { | ||
| 318 | - OutlinedTextField( | ||
| 319 | - value = messageToSend, | ||
| 320 | - onValueChange = { messageToSend = it }, | ||
| 321 | - label = { Text("Message") }, | ||
| 322 | - modifier = Modifier.fillMaxWidth(), | ||
| 323 | - ) | ||
| 324 | - }, | ||
| 325 | - confirmButton = { | ||
| 326 | - Button( | ||
| 327 | - onClick = { | ||
| 328 | - onSendMessage(messageToSend) | ||
| 329 | - showMessageDialog = false | ||
| 330 | - messageToSend = "" | ||
| 331 | - } | ||
| 332 | - ) { Text("Send") } | ||
| 333 | - }, | ||
| 334 | - dismissButton = { | ||
| 335 | - Button( | ||
| 336 | - onClick = { | ||
| 337 | - showMessageDialog = false | ||
| 338 | - messageToSend = "" | ||
| 339 | - } | ||
| 340 | - ) { Text("Cancel") } | ||
| 341 | - }, | ||
| 342 | - backgroundColor = Color.Black, | ||
| 343 | - ) | 316 | + if (showMessageDialog) { |
| 317 | + AlertDialog( | ||
| 318 | + onDismissRequest = { | ||
| 319 | + showMessageDialog = false | ||
| 320 | + messageToSend = "" | ||
| 321 | + }, | ||
| 322 | + title = { | ||
| 323 | + Text(text = "Send Message") | ||
| 324 | + }, | ||
| 325 | + text = { | ||
| 326 | + OutlinedTextField( | ||
| 327 | + value = messageToSend, | ||
| 328 | + onValueChange = { messageToSend = it }, | ||
| 329 | + label = { Text("Message") }, | ||
| 330 | + modifier = Modifier.fillMaxWidth(), | ||
| 331 | + ) | ||
| 332 | + }, | ||
| 333 | + confirmButton = { | ||
| 334 | + Button( | ||
| 335 | + onClick = { | ||
| 336 | + onSendMessage(messageToSend) | ||
| 337 | + showMessageDialog = false | ||
| 338 | + messageToSend = "" | ||
| 339 | + } | ||
| 340 | + ) { Text("Send") } | ||
| 341 | + }, | ||
| 342 | + dismissButton = { | ||
| 343 | + Button( | ||
| 344 | + onClick = { | ||
| 345 | + showMessageDialog = false | ||
| 346 | + messageToSend = "" | ||
| 347 | + } | ||
| 348 | + ) { Text("Cancel") } | ||
| 349 | + }, | ||
| 350 | + backgroundColor = Color.Black, | ||
| 351 | + ) | ||
| 352 | + } | ||
| 353 | + Surface( | ||
| 354 | + onClick = { onExitClick() }, | ||
| 355 | + indication = rememberRipple(false), | ||
| 356 | + modifier = Modifier | ||
| 357 | + .size(controlSize) | ||
| 358 | + .padding(controlPadding) | ||
| 359 | + ) { | ||
| 360 | + Icon( | ||
| 361 | + painterResource(id = R.drawable.ic_baseline_cancel_24), | ||
| 362 | + contentDescription = "Flip Camera", | ||
| 363 | + tint = Color.White, | ||
| 364 | + ) | ||
| 365 | + } | ||
| 344 | } | 366 | } |
| 345 | - Surface( | ||
| 346 | - onClick = { onExitClick() }, | ||
| 347 | - indication = rememberRipple(false), | ||
| 348 | - modifier = Modifier | ||
| 349 | - .size(controlSize) | ||
| 350 | - .padding(controlPadding) | 367 | + |
| 368 | + Spacer(modifier = Modifier.height(10.dp)) | ||
| 369 | + | ||
| 370 | + Row( | ||
| 371 | + horizontalArrangement = Arrangement.SpaceEvenly, | ||
| 372 | + verticalAlignment = Alignment.Bottom, | ||
| 351 | ) { | 373 | ) { |
| 352 | - Icon( | ||
| 353 | - painterResource(id = R.drawable.ic_baseline_cancel_24), | ||
| 354 | - contentDescription = "Flip Camera", | ||
| 355 | - tint = Color.White, | ||
| 356 | - ) | 374 | + Surface( |
| 375 | + onClick = { viewModel.toggleSubscriptionPermissions() }, | ||
| 376 | + indication = rememberRipple(false), | ||
| 377 | + modifier = Modifier | ||
| 378 | + .size(controlSize) | ||
| 379 | + .padding(controlPadding) | ||
| 380 | + ) { | ||
| 381 | + val resource = | ||
| 382 | + if (permissionAllowed) R.drawable.account_cancel_outline else R.drawable.account_cancel | ||
| 383 | + Icon( | ||
| 384 | + painterResource(id = resource), | ||
| 385 | + contentDescription = "Permissions", | ||
| 386 | + tint = Color.White, | ||
| 387 | + ) | ||
| 388 | + } | ||
| 357 | } | 389 | } |
| 358 | } | 390 | } |
| 359 | 391 |
-
请 注册 或 登录 后发表评论