refactor: Move microphone related stuff to MicrophoneStatus

This commit is contained in:
Myzel394 2023-10-22 00:23:02 +02:00
parent 38df00898d
commit 76e10a1512
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
4 changed files with 148 additions and 82 deletions

View File

@ -3,6 +3,7 @@ package app.myzel394.alibi.ui.components.AudioRecorder.molecules
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@ -13,22 +14,27 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneSelectionButton
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneTypeInfo
import app.myzel394.alibi.ui.models.AudioRecorderModel
@ -37,15 +43,26 @@ import app.myzel394.alibi.ui.utils.MicrophoneInfo
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MicrophoneSelection(
microphones: List<MicrophoneInfo>,
selectedMicrophone: MicrophoneInfo?,
onSelect: (MicrophoneInfo?) -> Unit,
audioRecorder: AudioRecorderModel
) {
val context = LocalContext.current
var showSelection by rememberSaveable {
mutableStateOf(false)
}
val sheetState = rememberModalBottomSheetState()
val allMicrophones = MicrophoneInfo.fetchDeviceMicrophones(context)
val visibleMicrophones = MicrophoneInfo.filterMicrophones(allMicrophones)
val hiddenMicrophones = allMicrophones - visibleMicrophones.toSet()
val dataStore = LocalContext.current.dataStore
val settings = dataStore
.data
.collectAsState(initial = AppSettings.getDefaultInstance())
.value
if (showSelection) {
ModalBottomSheet(
onDismissRequest = {
@ -73,26 +90,64 @@ fun MicrophoneSelection(
) {
item {
MicrophoneSelectionButton(
selected = selectedMicrophone == null,
selected = audioRecorder.selectedMicrophone == null,
onSelect = {
onSelect(null)
audioRecorder.changeMicrophone(null)
showSelection = false
}
)
}
items(microphones.size) {
val microphone = microphones[it]
items(visibleMicrophones.size) {
val microphone = visibleMicrophones[it]
MicrophoneSelectionButton(
microphone = microphone,
selected = selectedMicrophone == microphone,
selected = audioRecorder.selectedMicrophone == microphone,
onSelect = {
onSelect(microphone)
audioRecorder.changeMicrophone(microphone)
showSelection = false
}
)
}
if (settings.audioRecorderSettings.showAllMicrophones) {
item {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.padding(vertical = 32.dp),
) {
Divider(
modifier = Modifier
.weight(1f)
)
Text(
stringResource(R.string.ui_audioRecorder_info_microphone_hiddenMicrophones),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.tertiary,
textAlign = TextAlign.Center,
)
Divider(
modifier = Modifier
.weight(1f),
)
}
}
items(hiddenMicrophones.size) {
val microphone = hiddenMicrophones[it]
MicrophoneSelectionButton(
microphone = microphone,
selected = audioRecorder.selectedMicrophone == microphone,
onSelect = {
audioRecorder.changeMicrophone(microphone)
showSelection = false
}
)
}
}
}
}
}
@ -101,23 +156,25 @@ fun MicrophoneSelection(
Box {}
}
Button(
onClick = {
showSelection = true
},
colors = ButtonDefaults.textButtonColors(),
) {
MicrophoneTypeInfo(
type = selectedMicrophone?.type
?: MicrophoneInfo.MicrophoneType.PHONE,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
Text(
text = selectedMicrophone.let {
it?.name
?: stringResource(R.string.ui_audioRecorder_info_microphone_deviceMicrophone)
}
)
if (visibleMicrophones.isNotEmpty() || (settings.audioRecorderSettings.showAllMicrophones && hiddenMicrophones.isNotEmpty())) {
Button(
onClick = {
showSelection = true
},
colors = ButtonDefaults.textButtonColors(),
) {
MicrophoneTypeInfo(
type = audioRecorder.selectedMicrophone?.type
?: MicrophoneInfo.MicrophoneType.PHONE,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
Text(
text = audioRecorder.selectedMicrophone.let {
it?.name
?: stringResource(R.string.ui_audioRecorder_info_microphone_deviceMicrophone)
}
)
}
}
}

View File

@ -0,0 +1,61 @@
package app.myzel394.alibi.ui.components.AudioRecorder.molecules
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneDisconnectedDialog
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneReconnectedDialog
import app.myzel394.alibi.ui.effects.rememberPrevious
import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.utils.MicrophoneInfo
@Composable
fun MicrophoneStatus(
audioRecorder: AudioRecorderModel,
) {
val microphoneStatus = audioRecorder.microphoneStatus
val previousStatus = rememberPrevious(microphoneStatus)
var showMicrophoneStatusDialog by remember {
// null = no dialog
// `MicrophoneConnectivityStatus.CONNECTED` = Reconnected dialog
// `MicrophoneConnectivityStatus.DISCONNECTED` = Disconnected dialog
mutableStateOf<AudioRecorderModel.MicrophoneConnectivityStatus?>(null)
}
LaunchedEffect(microphoneStatus) {
if (microphoneStatus != previousStatus && showMicrophoneStatusDialog == null && previousStatus != null) {
showMicrophoneStatusDialog = microphoneStatus
}
}
if (showMicrophoneStatusDialog == AudioRecorderModel.MicrophoneConnectivityStatus.DISCONNECTED) {
MicrophoneDisconnectedDialog(
onClose = {
showMicrophoneStatusDialog = null
},
microphoneName = audioRecorder.selectedMicrophone?.name ?: "",
)
}
if (showMicrophoneStatusDialog == AudioRecorderModel.MicrophoneConnectivityStatus.CONNECTED) {
MicrophoneReconnectedDialog(
onClose = {
showMicrophoneStatusDialog = null
},
microphoneName = audioRecorder.selectedMicrophone?.name ?: "",
)
}
MicrophoneSelection(
audioRecorder = audioRecorder,
)
}

View File

@ -34,6 +34,7 @@ import app.myzel394.alibi.ui.components.AudioRecorder.atoms.RealtimeAudioVisuali
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.RecordingTime
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.SaveButton
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.MicrophoneSelection
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.MicrophoneStatus
import app.myzel394.alibi.ui.effects.rememberPrevious
import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.utils.KeepScreenOn
@ -141,60 +142,6 @@ fun RecordingStatus(
}
}
val dataStore = LocalContext.current.dataStore
val settings = dataStore
.data
.collectAsState(initial = AppSettings.getDefaultInstance())
.value
val microphones = MicrophoneInfo.fetchDeviceMicrophones(context).let {
if (settings.audioRecorderSettings.showAllMicrophones) {
it
} else {
MicrophoneInfo.filterMicrophones(it)
}
}
val microphoneStatus = audioRecorder.microphoneStatus
val previousStatus = rememberPrevious(microphoneStatus)
var showMicrophoneStatusDialog by remember {
// null = no dialog
// `MicrophoneConnectivityStatus.CONNECTED` = Reconnected dialog
// `MicrophoneConnectivityStatus.DISCONNECTED` = Disconnected dialog
mutableStateOf<AudioRecorderModel.MicrophoneConnectivityStatus?>(null)
}
LaunchedEffect(microphoneStatus) {
if (microphoneStatus != previousStatus && showMicrophoneStatusDialog == null && previousStatus != null) {
showMicrophoneStatusDialog = microphoneStatus
}
}
if (showMicrophoneStatusDialog == AudioRecorderModel.MicrophoneConnectivityStatus.DISCONNECTED) {
MicrophoneDisconnectedDialog(
onClose = {
showMicrophoneStatusDialog = null
},
microphoneName = audioRecorder.selectedMicrophone?.name ?: "",
)
}
if (showMicrophoneStatusDialog == AudioRecorderModel.MicrophoneConnectivityStatus.CONNECTED) {
MicrophoneReconnectedDialog(
onClose = {
showMicrophoneStatusDialog = null
},
microphoneName = audioRecorder.selectedMicrophone?.name ?: "",
)
}
if (microphones.isNotEmpty()) {
MicrophoneSelection(
microphones = microphones,
selectedMicrophone = audioRecorder.selectedMicrophone,
onSelect = audioRecorder::changeMicrophone,
)
} else {
Box {}
}
MicrophoneStatus(audioRecorder)
}
}

View File

@ -71,4 +71,5 @@
<string name="ui_audioRecorder_error_microphoneReconnected_message"><xliff:g name="name">%s</xliff:g> reconnected! Alibi automatically changed the microphone input to it.</string>
<string name="ui_settings_option_showAllMicrophones_title">Show hidden microphones</string>
<string name="ui_settings_option_showAllMicrophones_description">Show all microphones, including internal ones</string>
<string name="ui_audioRecorder_info_microphone_hiddenMicrophones">Hidden Microphones</string>
</resources>