mirror of
https://github.com/Myzel394/Alibi.git
synced 2025-06-19 07:15:25 +02:00
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:
parent
0a626e5f66
commit
671c8da56a
@ -11,6 +11,7 @@ import app.myzel394.alibi.helpers.AudioBatchesFolder
|
|||||||
import app.myzel394.alibi.helpers.VideoBatchesFolder
|
import app.myzel394.alibi.helpers.VideoBatchesFolder
|
||||||
import app.myzel394.alibi.ui.RECORDER_MEDIA_SELECTED_VALUE
|
import app.myzel394.alibi.ui.RECORDER_MEDIA_SELECTED_VALUE
|
||||||
import app.myzel394.alibi.ui.SUPPORTS_SCOPED_STORAGE
|
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 app.myzel394.alibi.ui.utils.PermissionHelper
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
@ -102,6 +103,16 @@ data class AppSettings(
|
|||||||
return copy(appLockSettings = appLockSettings)
|
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.
|
// If the object is present, biometric authentication is enabled.
|
||||||
// To disable biometric authentication, set the instance to null.
|
// To disable biometric authentication, set the instance to null.
|
||||||
fun isAppLockEnabled() = appLockSettings != null
|
fun isAppLockEnabled() = appLockSettings != null
|
||||||
|
@ -22,6 +22,7 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
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.dataStore
|
||||||
import app.myzel394.alibi.ui.components.RecorderScreen.atoms.RealtimeAudioVisualizer
|
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.MicrophoneStatus
|
||||||
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingControl
|
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingControl
|
||||||
@ -39,8 +40,6 @@ fun AudioRecordingStatus(
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val configuration = LocalConfiguration.current.orientation
|
val configuration = LocalConfiguration.current.orientation
|
||||||
|
|
||||||
val scope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
var now by remember { mutableStateOf(LocalDateTime.now()) }
|
var now by remember { mutableStateOf(LocalDateTime.now()) }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
@ -90,34 +89,7 @@ fun AudioRecordingStatus(
|
|||||||
MicrophoneStatus(audioRecorder)
|
MicrophoneStatus(audioRecorder)
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordingControl(
|
_PrimitiveControls(audioRecorder)
|
||||||
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)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +110,19 @@ fun AudioRecordingStatus(
|
|||||||
|
|
||||||
HorizontalDivider()
|
HorizontalDivider()
|
||||||
|
|
||||||
|
_PrimitiveControls(audioRecorder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun _PrimitiveControls(audioRecorder: AudioRecorderModel) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
val dataStore = context.dataStore
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
RecordingControl(
|
RecordingControl(
|
||||||
isPaused = audioRecorder.isPaused,
|
isPaused = audioRecorder.isPaused,
|
||||||
recordingTime = audioRecorder.recordingTime,
|
recordingTime = audioRecorder.recordingTime,
|
||||||
@ -160,11 +145,19 @@ fun AudioRecordingStatus(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSave = {
|
onSave = {
|
||||||
audioRecorder.onRecordingSave(false)
|
scope.launch {
|
||||||
|
audioRecorder.stopRecording(context)
|
||||||
|
|
||||||
|
dataStore.updateData {
|
||||||
|
it.saveLastRecording(audioRecorder as RecorderModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
audioRecorder.onRecordingSave()
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
audioRecorder.destroyService(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -30,7 +30,6 @@ import app.myzel394.alibi.ui.models.AudioRecorderModel
|
|||||||
import app.myzel394.alibi.ui.models.BaseRecorderModel
|
import app.myzel394.alibi.ui.models.BaseRecorderModel
|
||||||
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
||||||
import app.myzel394.alibi.ui.utils.rememberFileSaverDialog
|
import app.myzel394.alibi.ui.utils.rememberFileSaverDialog
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
@ -224,26 +223,15 @@ fun RecorderEventsHandler(
|
|||||||
|
|
||||||
// Register audio recorder events
|
// Register audio recorder events
|
||||||
DisposableEffect(key1 = audioRecorder, key2 = settings) {
|
DisposableEffect(key1 = audioRecorder, key2 = settings) {
|
||||||
audioRecorder.onRecordingSave = { justSave ->
|
audioRecorder.onRecordingSave = {
|
||||||
val completer = CompletableDeferred<Unit>()
|
// 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 {
|
scope.launch {
|
||||||
if (justSave) {
|
|
||||||
saveRecording(audioRecorder as RecorderModel)
|
saveRecording(audioRecorder as RecorderModel)
|
||||||
} else {
|
|
||||||
audioRecorder.stopRecording(context)
|
|
||||||
|
|
||||||
saveAsLastRecording(audioRecorder as RecorderModel)
|
|
||||||
|
|
||||||
saveRecording(audioRecorder)
|
|
||||||
|
|
||||||
audioRecorder.destroyService(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
completer.complete(Unit)
|
|
||||||
}
|
|
||||||
|
|
||||||
completer
|
|
||||||
}
|
}
|
||||||
audioRecorder.onRecordingStart = {
|
audioRecorder.onRecordingStart = {
|
||||||
snackbarHostState.currentSnackbarData?.dismiss()
|
snackbarHostState.currentSnackbarData?.dismiss()
|
||||||
@ -278,26 +266,15 @@ fun RecorderEventsHandler(
|
|||||||
|
|
||||||
// Register video recorder events
|
// Register video recorder events
|
||||||
DisposableEffect(key1 = videoRecorder, key2 = settings) {
|
DisposableEffect(key1 = videoRecorder, key2 = settings) {
|
||||||
videoRecorder.onRecordingSave = { justSave ->
|
videoRecorder.onRecordingSave = {
|
||||||
val completer = CompletableDeferred<Unit>()
|
// 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 {
|
scope.launch {
|
||||||
if (justSave) {
|
|
||||||
saveRecording(videoRecorder as RecorderModel)
|
saveRecording(videoRecorder as RecorderModel)
|
||||||
} else {
|
|
||||||
videoRecorder.stopRecording(context)
|
|
||||||
|
|
||||||
saveAsLastRecording(videoRecorder as RecorderModel)
|
|
||||||
|
|
||||||
saveRecording(videoRecorder)
|
|
||||||
|
|
||||||
videoRecorder.destroyService(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
completer.complete(Unit)
|
|
||||||
}
|
|
||||||
|
|
||||||
completer
|
|
||||||
}
|
}
|
||||||
videoRecorder.onRecordingStart = {
|
videoRecorder.onRecordingStart = {
|
||||||
snackbarHostState.currentSnackbarData?.dismiss()
|
snackbarHostState.currentSnackbarData?.dismiss()
|
||||||
|
@ -32,6 +32,7 @@ import androidx.compose.ui.platform.LocalDensity
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
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.ui.components.RecorderScreen.atoms.TorchStatus
|
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.RecordingControl
|
||||||
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingStatus
|
import app.myzel394.alibi.ui.components.RecorderScreen.molecules.RecordingStatus
|
||||||
@ -189,6 +190,7 @@ fun _VideoRecordingStatus(videoRecorder: VideoRecorderModel) {
|
|||||||
@Composable
|
@Composable
|
||||||
fun _PrimitiveControls(videoRecorder: VideoRecorderModel) {
|
fun _PrimitiveControls(videoRecorder: VideoRecorderModel) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val dataStore = context.dataStore
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
RecordingControl(
|
RecordingControl(
|
||||||
@ -218,7 +220,19 @@ fun _PrimitiveControls(videoRecorder: VideoRecorderModel) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSave = {
|
onSave = {
|
||||||
videoRecorder.onRecordingSave(false)
|
scope.launch {
|
||||||
|
videoRecorder.stopRecording(context)
|
||||||
|
|
||||||
|
dataStore.updateData {
|
||||||
|
it.saveLastRecording(videoRecorder as RecorderModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
videoRecorder.onRecordingSave()
|
||||||
|
|
||||||
|
runCatching {
|
||||||
|
videoRecorder.destroyService(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import app.myzel394.alibi.helpers.BatchesFolder
|
|||||||
import app.myzel394.alibi.services.IntervalRecorderService
|
import app.myzel394.alibi.services.IntervalRecorderService
|
||||||
import app.myzel394.alibi.services.RecorderNotificationHelper
|
import app.myzel394.alibi.services.RecorderNotificationHelper
|
||||||
import app.myzel394.alibi.services.RecorderService
|
import app.myzel394.alibi.services.RecorderService
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
abstract class BaseRecorderModel<I, B : BatchesFolder, T : IntervalRecorderService<I, B>> :
|
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,
|
// 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
|
// 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")
|
throw NotImplementedError("onRecordingSave not implemented")
|
||||||
}
|
}
|
||||||
var onRecordingStart: () -> Unit = {}
|
var onRecordingStart: () -> Unit = {}
|
||||||
|
@ -16,22 +16,26 @@ import androidx.compose.material3.SnackbarHostState
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.runtime.Composable
|
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.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
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.R
|
||||||
import app.myzel394.alibi.dataStore
|
import app.myzel394.alibi.dataStore
|
||||||
import app.myzel394.alibi.db.AppSettings
|
import app.myzel394.alibi.db.AppSettings
|
||||||
import app.myzel394.alibi.db.RecordingInformation
|
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.RecorderEventsHandler
|
||||||
|
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.StartRecording
|
||||||
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.VideoRecordingStatus
|
import app.myzel394.alibi.ui.components.RecorderScreen.organisms.VideoRecordingStatus
|
||||||
import app.myzel394.alibi.ui.models.AudioRecorderModel
|
import app.myzel394.alibi.ui.models.AudioRecorderModel
|
||||||
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
import app.myzel394.alibi.ui.models.VideoRecorderModel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
@ -43,6 +47,7 @@ fun RecorderScreen(
|
|||||||
) {
|
) {
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
RecorderEventsHandler(
|
RecorderEventsHandler(
|
||||||
settings = settings,
|
settings = settings,
|
||||||
@ -112,12 +117,14 @@ fun RecorderScreen(
|
|||||||
videoRecorder = videoRecorder,
|
videoRecorder = videoRecorder,
|
||||||
appSettings = appSettings,
|
appSettings = appSettings,
|
||||||
onSaveLastRecording = {
|
onSaveLastRecording = {
|
||||||
|
scope.launch {
|
||||||
when (settings.lastRecording!!.type) {
|
when (settings.lastRecording!!.type) {
|
||||||
RecordingInformation.Type.AUDIO ->
|
RecordingInformation.Type.AUDIO ->
|
||||||
audioRecorder.onRecordingSave(true)
|
audioRecorder.onRecordingSave()
|
||||||
|
|
||||||
RecordingInformation.Type.VIDEO ->
|
RecordingInformation.Type.VIDEO ->
|
||||||
videoRecorder.onRecordingSave(true)
|
videoRecorder.onRecordingSave()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showAudioRecorder = topBarVisible,
|
showAudioRecorder = topBarVisible,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user