1 /*
<lambda>null2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.core.telecom.test.ui.calling
18 
19 import androidx.compose.foundation.layout.Column
20 import androidx.compose.foundation.layout.Row
21 import androidx.compose.foundation.layout.Spacer
22 import androidx.compose.foundation.layout.fillMaxWidth
23 import androidx.compose.foundation.layout.padding
24 import androidx.compose.material3.Card
25 import androidx.compose.material3.CardDefaults
26 import androidx.compose.material3.ElevatedCard
27 import androidx.compose.material3.HorizontalDivider
28 import androidx.compose.material3.Icon
29 import androidx.compose.material3.MaterialTheme
30 import androidx.compose.material3.OutlinedCard
31 import androidx.compose.material3.Text
32 import androidx.compose.runtime.Composable
33 import androidx.compose.runtime.getValue
34 import androidx.compose.runtime.mutableStateOf
35 import androidx.compose.runtime.remember
36 import androidx.compose.runtime.rememberCoroutineScope
37 import androidx.compose.runtime.setValue
38 import androidx.compose.ui.Alignment
39 import androidx.compose.ui.Modifier
40 import androidx.compose.ui.res.painterResource
41 import androidx.compose.ui.tooling.preview.Preview
42 import androidx.compose.ui.tooling.preview.PreviewParameter
43 import androidx.compose.ui.tooling.preview.Wallpapers
44 import androidx.compose.ui.unit.dp
45 import androidx.compose.ui.window.Dialog
46 import androidx.core.telecom.test.R
47 import androidx.core.telecom.test.services.AudioRoute
48 import androidx.core.telecom.test.ui.calling.OngoingCallsViewModel.Companion.UnknownAudioUiState
49 import androidx.lifecycle.compose.collectAsStateWithLifecycle
50 import kotlinx.coroutines.launch
51 
52 /**
53  * The dialog that pops up on the screen when the user tries to change the audio route of the
54  * device.
55  */
56 @Composable
57 fun AudioRoutePickerDialog(
58     ongoingCallsViewModel: OngoingCallsViewModel,
59     onDismissDialog: () -> Unit,
60     onChangeAudioRoute: suspend (String) -> Unit
61 ) {
62     val currentAudioRoute: AudioEndpointUiState by
63         ongoingCallsViewModel
64             .streamCurrentEndpointAudioData()
65             .collectAsStateWithLifecycle(UnknownAudioUiState)
66     val availableAudioRoutes: List<AudioEndpointUiState> by
67         ongoingCallsViewModel
68             .streamAvailableEndpointAudioData()
69             .collectAsStateWithLifecycle(emptyList())
70     Dialog(onDismissRequest = onDismissDialog) {
71         Card(
72             modifier = Modifier.fillMaxWidth(),
73             colors =
74                 CardDefaults.cardColors(
75                     containerColor = MaterialTheme.colorScheme.surfaceContainerHigh
76                 )
77         ) {
78             Column(modifier = Modifier.padding(6.dp)) {
79                 Text("Current Audio Route")
80                 Spacer(modifier = Modifier.padding(vertical = 3.dp))
81                 OutlinedCard { AudioRouteContent(currentAudioRoute) }
82                 HorizontalDivider(modifier = Modifier.padding(vertical = 6.dp))
83                 Text("Available Audio Routes")
84                 val available = availableAudioRoutes.filter { it.id != currentAudioRoute.id }
85                 if (available.isEmpty()) {
86                     Text(modifier = Modifier.padding(6.dp), text = "<None Available>")
87                 } else {
88                     available.forEach { route ->
89                         ClickableAudioRouteContent(route, onChangeAudioRoute)
90                     }
91                 }
92             }
93         }
94     }
95 }
96 
97 @Preview(showBackground = true, wallpaper = Wallpapers.BLUE_DOMINATED_EXAMPLE)
98 @Composable
ClickableAudioRouteContentnull99 fun ClickableAudioRouteContent(
100     @PreviewParameter(UserPreviewEndpointProvider::class) audioRoute: AudioEndpointUiState,
101     onChangeAudioRoute: suspend (String) -> Unit = {}
102 ) {
103     val coroutineScope = rememberCoroutineScope()
<lambda>null104     var isLoading: Boolean by remember { mutableStateOf(false) }
105     ElevatedCard(
106         enabled = !isLoading,
<lambda>null107         onClick = {
108             coroutineScope.launch {
109                 isLoading = true
110                 onChangeAudioRoute(audioRoute.id)
111                 isLoading = false
112             }
113         }
<lambda>null114     ) {
115         AudioRouteContent(audioRoute)
116     }
117 }
118 
119 @Composable
AudioRouteContentnull120 fun AudioRouteContent(audioRoute: AudioEndpointUiState) {
121     Row(
122         modifier = Modifier.fillMaxWidth().padding(6.dp),
123         verticalAlignment = Alignment.CenterVertically
124     ) {
125         Icon(
126             painter = painterResource(getResourceForAudioRoute(audioRoute.audioRoute)),
127             contentDescription = "audio route details"
128         )
129         Spacer(modifier = Modifier.padding(horizontal = 6.dp))
130         Text(audioRoute.name)
131     }
132 }
133 
getResourceForAudioRoutenull134 fun getResourceForAudioRoute(audioRoute: AudioRoute): Int {
135     return when (audioRoute) {
136         AudioRoute.UNKNOWN -> R.drawable.phone_in_talk_24px
137         AudioRoute.EARPIECE -> R.drawable.phone_in_talk_24px
138         AudioRoute.SPEAKER -> R.drawable.speaker_phone_24px
139         AudioRoute.BLUETOOTH -> R.drawable.bluetooth_24px
140         AudioRoute.HEADSET -> R.drawable.headset_mic_24px
141         AudioRoute.STREAMING -> R.drawable.cast_24px
142     }
143 }
144