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.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth 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.foundation.lazy.LazyColumn
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import app.myzel394.alibi.R 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.MicrophoneSelectionButton
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneTypeInfo import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneTypeInfo
import app.myzel394.alibi.ui.models.AudioRecorderModel import app.myzel394.alibi.ui.models.AudioRecorderModel
@ -37,15 +43,26 @@ import app.myzel394.alibi.ui.utils.MicrophoneInfo
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MicrophoneSelection( fun MicrophoneSelection(
microphones: List<MicrophoneInfo>, audioRecorder: AudioRecorderModel
selectedMicrophone: MicrophoneInfo?,
onSelect: (MicrophoneInfo?) -> Unit,
) { ) {
val context = LocalContext.current
var showSelection by rememberSaveable { var showSelection by rememberSaveable {
mutableStateOf(false) mutableStateOf(false)
} }
val sheetState = rememberModalBottomSheetState() 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) { if (showSelection) {
ModalBottomSheet( ModalBottomSheet(
onDismissRequest = { onDismissRequest = {
@ -73,26 +90,64 @@ fun MicrophoneSelection(
) { ) {
item { item {
MicrophoneSelectionButton( MicrophoneSelectionButton(
selected = selectedMicrophone == null, selected = audioRecorder.selectedMicrophone == null,
onSelect = { onSelect = {
onSelect(null) audioRecorder.changeMicrophone(null)
showSelection = false showSelection = false
} }
) )
} }
items(microphones.size) { items(visibleMicrophones.size) {
val microphone = microphones[it] val microphone = visibleMicrophones[it]
MicrophoneSelectionButton( MicrophoneSelectionButton(
microphone = microphone, microphone = microphone,
selected = selectedMicrophone == microphone, selected = audioRecorder.selectedMicrophone == microphone,
onSelect = { onSelect = {
onSelect(microphone) audioRecorder.changeMicrophone(microphone)
showSelection = false 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,6 +156,7 @@ fun MicrophoneSelection(
Box {} Box {}
} }
if (visibleMicrophones.isNotEmpty() || (settings.audioRecorderSettings.showAllMicrophones && hiddenMicrophones.isNotEmpty())) {
Button( Button(
onClick = { onClick = {
showSelection = true showSelection = true
@ -108,16 +164,17 @@ fun MicrophoneSelection(
colors = ButtonDefaults.textButtonColors(), colors = ButtonDefaults.textButtonColors(),
) { ) {
MicrophoneTypeInfo( MicrophoneTypeInfo(
type = selectedMicrophone?.type type = audioRecorder.selectedMicrophone?.type
?: MicrophoneInfo.MicrophoneType.PHONE, ?: MicrophoneInfo.MicrophoneType.PHONE,
modifier = Modifier.size(ButtonDefaults.IconSize), modifier = Modifier.size(ButtonDefaults.IconSize),
) )
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing)) Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
Text( Text(
text = selectedMicrophone.let { text = audioRecorder.selectedMicrophone.let {
it?.name it?.name
?: stringResource(R.string.ui_audioRecorder_info_microphone_deviceMicrophone) ?: 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.RecordingTime
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.SaveButton 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.MicrophoneSelection
import app.myzel394.alibi.ui.components.AudioRecorder.molecules.MicrophoneStatus
import app.myzel394.alibi.ui.effects.rememberPrevious import app.myzel394.alibi.ui.effects.rememberPrevious
import app.myzel394.alibi.ui.models.AudioRecorderModel import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.utils.KeepScreenOn import app.myzel394.alibi.ui.utils.KeepScreenOn
@ -141,60 +142,6 @@ fun RecordingStatus(
} }
} }
val dataStore = LocalContext.current.dataStore MicrophoneStatus(audioRecorder)
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 {}
}
} }
} }

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_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_title">Show hidden microphones</string>
<string name="ui_settings_option_showAllMicrophones_description">Show all microphones, including internal ones</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> </resources>