mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-19 07:15:25 +02:00
feat: Add MicrophoneDisconnectedDialog
This commit is contained in:
parent
78453f1c4d
commit
07757f34bb
@ -0,0 +1,62 @@
|
|||||||
|
package app.myzel394.alibi.ui.components.AudioRecorder.atoms
|
||||||
|
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.MicOff
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.contentDescription
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import app.myzel394.alibi.R
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun MicrophoneDisconnectedDialog(
|
||||||
|
microphoneName: String,
|
||||||
|
onClose: () -> Unit,
|
||||||
|
) {
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onClose,
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
stringResource(
|
||||||
|
R.string.ui_audioRecorder_error_microphoneDisconnected_title,
|
||||||
|
),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text(
|
||||||
|
stringResource(
|
||||||
|
R.string.ui_audioRecorder_error_microphoneDisconnected_message,
|
||||||
|
microphoneName,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
icon = {
|
||||||
|
Icon(
|
||||||
|
Icons.Default.MicOff,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
val label = stringResource(R.string.dialog_close_neutral_label)
|
||||||
|
|
||||||
|
Button(
|
||||||
|
modifier = Modifier
|
||||||
|
.semantics {
|
||||||
|
contentDescription = label
|
||||||
|
},
|
||||||
|
onClick = onClose,
|
||||||
|
) {
|
||||||
|
Text(label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
@ -24,11 +24,13 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.DeleteButton
|
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.DeleteButton
|
||||||
|
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.MicrophoneDisconnectedDialog
|
||||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.PauseResumeButton
|
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.PauseResumeButton
|
||||||
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.RealtimeAudioVisualizer
|
import app.myzel394.alibi.ui.components.AudioRecorder.atoms.RealtimeAudioVisualizer
|
||||||
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.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
|
||||||
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
import app.myzel394.alibi.ui.utils.MicrophoneInfo
|
||||||
@ -137,19 +139,41 @@ fun RecordingStatus(
|
|||||||
|
|
||||||
|
|
||||||
val microphones = MicrophoneInfo.fetchDeviceMicrophones(context)
|
val microphones = MicrophoneInfo.fetchDeviceMicrophones(context)
|
||||||
|
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) {
|
||||||
|
println(microphoneStatus)
|
||||||
|
println(previousStatus)
|
||||||
|
if (microphoneStatus != previousStatus && showMicrophoneStatusDialog == null && previousStatus != null) {
|
||||||
|
showMicrophoneStatusDialog = microphoneStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showMicrophoneStatusDialog == AudioRecorderModel.MicrophoneConnectivityStatus.DISCONNECTED) {
|
||||||
|
MicrophoneDisconnectedDialog(
|
||||||
|
onClose = {
|
||||||
|
showMicrophoneStatusDialog = null
|
||||||
|
},
|
||||||
|
microphoneName = audioRecorder.selectedMicrophone?.name ?: "",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (microphones.isNotEmpty()) {
|
if (microphones.isNotEmpty()) {
|
||||||
MicrophoneSelection(
|
MicrophoneSelection(
|
||||||
microphones = microphones,
|
microphones = microphones,
|
||||||
selectedMicrophone = audioRecorder.selectedMicrophone,
|
selectedMicrophone = audioRecorder.selectedMicrophone,
|
||||||
onSelect = {
|
onSelect = audioRecorder::changeMicrophone,
|
||||||
audioRecorder.changeMicrophone(it)
|
|
||||||
|
|
||||||
if (!audioRecorder.isPaused) {
|
|
||||||
audioRecorder.recorderService!!.startNewCycle()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
Box {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package app.myzel394.alibi.ui.effects
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a dummy MutableState that does not cause render when setting it
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
private fun <T> rememberRef(): MutableState<T?> {
|
||||||
|
// for some reason it always recreated the value with vararg keys,
|
||||||
|
// leaving out the keys as a parameter for remember for now
|
||||||
|
return remember() {
|
||||||
|
object : MutableState<T?> {
|
||||||
|
override var value: T? = null
|
||||||
|
|
||||||
|
override fun component1(): T? = value
|
||||||
|
|
||||||
|
override fun component2(): (T?) -> Unit = { value = it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun <T> rememberPrevious(
|
||||||
|
current: T,
|
||||||
|
shouldUpdate: (prev: T?, curr: T) -> Boolean = { a: T?, b: T -> a != b },
|
||||||
|
): T? {
|
||||||
|
val ref = rememberRef<T>()
|
||||||
|
|
||||||
|
// launched after render, so the current render will have the old value anyway
|
||||||
|
SideEffect {
|
||||||
|
if (shouldUpdate(ref.value, current)) {
|
||||||
|
ref.value = current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref.value
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user