refactor: Move recording save stuff out to audio and video recording statuses component

Signed-off-by: Myzel394 <50424412+Myzel394@users.noreply.github.com>
This commit is contained in:
Myzel394 2024-03-16 17:28:45 +01:00
parent 0a626e5f66
commit 671c8da56a
No known key found for this signature in database
GPG Key ID: DEC4AAB876F73185
6 changed files with 107 additions and 105 deletions

View File

@ -11,6 +11,7 @@ import app.myzel394.alibi.helpers.AudioBatchesFolder
import app.myzel394.alibi.helpers.VideoBatchesFolder
import app.myzel394.alibi.ui.RECORDER_MEDIA_SELECTED_VALUE
import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.RecorderModel
import app.myzel394.alibi.ui.utils.PermissionHelper
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
@ -102,6 +103,16 @@ data class AppSettings(
return copy(appLockSettings = appLockSettings)
}
fun saveLastRecording(recorder: RecorderModel): AppSettings {
return if (deleteRecordingsImmediately) {
this
} else {
setLastRecording(
recorder.recorderService!!.getRecordingInformation()
)
}
}
// If the object is present, biometric authentication is enabled.
// To disable biometric authentication, set the instance to null.
fun isAppLockEnabled() = appLockSettings != null

View File

@ -22,6 +22,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.RealtimeAudioVisualizer
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.MicrophoneStatus
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingControl
@ -39,8 +40,6 @@ fun AudioRecordingStatus(
val context = LocalContext.current
val configuration = LocalConfiguration.current.orientation
val scope = rememberCoroutineScope()
var now by remember { mutableStateOf(LocalDateTime.now()) }
LaunchedEffect(Unit) {
@ -90,34 +89,7 @@ fun AudioRecordingStatus(
MicrophoneStatus(audioRecorder)
}
RecordingControl(
modifier = Modifier
.weight(1f)
.fillMaxWidth(),
isPaused = audioRecorder.isPaused,
recordingTime = audioRecorder.recordingTime,
onDelete = {
scope.launch {
runCatching {
audioRecorder.stopRecording(context)
}
runCatching {
audioRecorder.destroyService(context)
}
audioRecorder.batchesFolder!!.deleteRecordings()
}
},
onPauseResume = {
if (audioRecorder.isPaused) {
audioRecorder.resumeRecording()
} else {
audioRecorder.pauseRecording()
}
},
onSave = {
audioRecorder.onRecordingSave(false)
}
)
_PrimitiveControls(audioRecorder)
}
}
@ -138,33 +110,54 @@ fun AudioRecordingStatus(
HorizontalDivider()
RecordingControl(
isPaused = audioRecorder.isPaused,
recordingTime = audioRecorder.recordingTime,
onDelete = {
scope.launch {
runCatching {
audioRecorder.stopRecording(context)
}
runCatching {
audioRecorder.destroyService(context)
}
audioRecorder.batchesFolder!!.deleteRecordings()
}
},
onPauseResume = {
if (audioRecorder.isPaused) {
audioRecorder.resumeRecording()
} else {
audioRecorder.pauseRecording()
}
},
onSave = {
audioRecorder.onRecordingSave(false)
}
)
_PrimitiveControls(audioRecorder)
}
}
}
}
}
@Composable
fun _PrimitiveControls(audioRecorder: AudioRecorderModel) {
val context = LocalContext.current
val dataStore = context.dataStore
val scope = rememberCoroutineScope()
RecordingControl(
isPaused = audioRecorder.isPaused,
recordingTime = audioRecorder.recordingTime,
onDelete = {
scope.launch {
runCatching {
audioRecorder.stopRecording(context)
}
runCatching {
audioRecorder.destroyService(context)
}
audioRecorder.batchesFolder!!.deleteRecordings()
}
},
onPauseResume = {
if (audioRecorder.isPaused) {
audioRecorder.resumeRecording()
} else {
audioRecorder.pauseRecording()
}
},
onSave = {
scope.launch {
audioRecorder.stopRecording(context)
dataStore.updateData {
it.saveLastRecording(audioRecorder as RecorderModel)
}
audioRecorder.onRecordingSave()
runCatching {
audioRecorder.destroyService(context)
}
}
}
)
}

View File

@ -30,7 +30,6 @@ import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.models.BaseRecorderModel
import app.myzel394.alibi.ui.models.VideoRecorderModel
import app.myzel394.alibi.ui.utils.rememberFileSaverDialog
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
@ -224,26 +223,15 @@ fun RecorderEventsHandler(
// Register audio recorder events
DisposableEffect(key1 = audioRecorder, key2 = settings) {
audioRecorder.onRecordingSave = { justSave ->
val completer = CompletableDeferred<Unit>()
audioRecorder.onRecordingSave = {
// We create our own coroutine because we show our own dialog and we want to
// keep saving until it's finished.
// So it's smarter to take things into our own hands and use our local coroutine,
// instead of hoping that the coroutine from where this will be called will be alive
// until the end of the saving process
scope.launch {
if (justSave) {
saveRecording(audioRecorder as RecorderModel)
} else {
audioRecorder.stopRecording(context)
saveAsLastRecording(audioRecorder as RecorderModel)
saveRecording(audioRecorder)
audioRecorder.destroyService(context)
}
completer.complete(Unit)
saveRecording(audioRecorder as RecorderModel)
}
completer
}
audioRecorder.onRecordingStart = {
snackbarHostState.currentSnackbarData?.dismiss()
@ -278,26 +266,15 @@ fun RecorderEventsHandler(
// Register video recorder events
DisposableEffect(key1 = videoRecorder, key2 = settings) {
videoRecorder.onRecordingSave = { justSave ->
val completer = CompletableDeferred<Unit>()
videoRecorder.onRecordingSave = {
// We create our own coroutine because we show our own dialog and we want to
// keep saving until it's finished.
// So it's smarter to take things into our own hands and use our local coroutine,
// instead of hoping that the coroutine from where this will be called will be alive
// until the end of the saving process
scope.launch {
if (justSave) {
saveRecording(videoRecorder as RecorderModel)
} else {
videoRecorder.stopRecording(context)
saveAsLastRecording(videoRecorder as RecorderModel)
saveRecording(videoRecorder)
videoRecorder.destroyService(context)
}
completer.complete(Unit)
saveRecording(videoRecorder as RecorderModel)
}
completer
}
videoRecorder.onRecordingStart = {
snackbarHostState.currentSnackbarData?.dismiss()

View File

@ -32,6 +32,7 @@ import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.TorchStatus
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingControl
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingStatus
@ -189,6 +190,7 @@ fun _VideoRecordingStatus(videoRecorder: VideoRecorderModel) {
@Composable
fun _PrimitiveControls(videoRecorder: VideoRecorderModel) {
val context = LocalContext.current
val dataStore = context.dataStore
val scope = rememberCoroutineScope()
RecordingControl(
@ -218,7 +220,19 @@ fun _PrimitiveControls(videoRecorder: VideoRecorderModel) {
}
},
onSave = {
videoRecorder.onRecordingSave(false)
scope.launch {
videoRecorder.stopRecording(context)
dataStore.updateData {
it.saveLastRecording(videoRecorder as RecorderModel)
}
videoRecorder.onRecordingSave()
runCatching {
videoRecorder.destroyService(context)
}
}
}
)
}

View File

@ -17,7 +17,7 @@ import app.myzel394.alibi.helpers.BatchesFolder
import app.myzel394.alibi.services.IntervalRecorderService
import app.myzel394.alibi.services.RecorderNotificationHelper
import app.myzel394.alibi.services.RecorderService
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Job
import kotlinx.serialization.json.Json
abstract class BaseRecorderModel<I, B : BatchesFolder, T : IntervalRecorderService<I, B>> :
@ -46,7 +46,7 @@ abstract class BaseRecorderModel<I, B : BatchesFolder, T : IntervalRecorderServi
// If `isSavingAsOldRecording` is true, the user is saving an old recording,
// thus the service is not running and thus doesn't need to be stopped or destroyed
var onRecordingSave: (isSavingAsOldRecording: Boolean) -> CompletableDeferred<Unit> = {
var onRecordingSave: () -> Job = {
throw NotImplementedError("onRecordingSave not implemented")
}
var onRecordingStart: () -> Unit = {}

View File

@ -16,22 +16,26 @@ import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavController
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.AudioRecordingStatus
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.StartRecording
import app.myzel394.alibi.ui.enums.Screen
import app.myzel394.alibi.R
import app.myzel394.alibi.dataStore
import app.myzel394.alibi.db.AppSettings
import app.myzel394.alibi.db.RecordingInformation
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.AudioRecordingStatus
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.RecorderEventsHandler
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.StartRecording
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.VideoRecordingStatus
import app.myzel394.alibi.ui.models.AudioRecorderModel
import app.myzel394.alibi.ui.models.VideoRecorderModel
import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -43,6 +47,7 @@ fun RecorderScreen(
) {
val snackbarHostState = remember { SnackbarHostState() }
val context = LocalContext.current
val scope = rememberCoroutineScope()
RecorderEventsHandler(
settings = settings,
@ -112,12 +117,14 @@ fun RecorderScreen(
videoRecorder = videoRecorder,
appSettings = appSettings,
onSaveLastRecording = {
when (settings.lastRecording!!.type) {
RecordingInformation.Type.AUDIO ->
audioRecorder.onRecordingSave(true)
scope.launch {
when (settings.lastRecording!!.type) {
RecordingInformation.Type.AUDIO ->
audioRecorder.onRecordingSave()
RecordingInformation.Type.VIDEO ->
videoRecorder.onRecordingSave(true)
RecordingInformation.Type.VIDEO ->
videoRecorder.onRecordingSave()
}
}
},
showAudioRecorder = topBarVisible,