mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-19 07:15:25 +02:00
refactor: Move microphone related stuff to MicrophoneStatus
This commit is contained in:
parent
38df00898d
commit
76e10a1512
@ -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,23 +156,25 @@ fun MicrophoneSelection(
|
|||||||
Box {}
|
Box {}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(
|
if (visibleMicrophones.isNotEmpty() || (settings.audioRecorderSettings.showAllMicrophones && hiddenMicrophones.isNotEmpty())) {
|
||||||
onClick = {
|
Button(
|
||||||
showSelection = true
|
onClick = {
|
||||||
},
|
showSelection = true
|
||||||
colors = ButtonDefaults.textButtonColors(),
|
},
|
||||||
) {
|
colors = ButtonDefaults.textButtonColors(),
|
||||||
MicrophoneTypeInfo(
|
) {
|
||||||
type = selectedMicrophone?.type
|
MicrophoneTypeInfo(
|
||||||
?: MicrophoneInfo.MicrophoneType.PHONE,
|
type = audioRecorder.selectedMicrophone?.type
|
||||||
modifier = Modifier.size(ButtonDefaults.IconSize),
|
?: MicrophoneInfo.MicrophoneType.PHONE,
|
||||||
)
|
modifier = Modifier.size(ButtonDefaults.IconSize),
|
||||||
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
|
)
|
||||||
Text(
|
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
|
||||||
text = selectedMicrophone.let {
|
Text(
|
||||||
it?.name
|
text = audioRecorder.selectedMicrophone.let {
|
||||||
?: stringResource(R.string.ui_audioRecorder_info_microphone_deviceMicrophone)
|
it?.name
|
||||||
}
|
?: stringResource(R.string.ui_audioRecorder_info_microphone_deviceMicrophone)
|
||||||
)
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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,
|
||||||
|
)
|
||||||
|
}
|
@ -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 {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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>
|
Loading…
x
Reference in New Issue
Block a user