diff --git a/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt b/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt index ac48807..a025dca 100644 --- a/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt +++ b/app/src/main/java/app/myzel394/alibi/helpers/BatchesFolder.kt @@ -7,12 +7,15 @@ import android.content.Context import android.database.Cursor import android.net.Uri import android.os.Build +import android.os.storage.StorageManager import android.provider.MediaStore import android.provider.MediaStore.Video.Media import android.util.Log import androidx.annotation.RequiresApi +import androidx.core.net.toFile import androidx.core.net.toUri import androidx.documentfile.provider.DocumentFile +import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.ui.MEDIA_RECORDINGS_PREFIX import app.myzel394.alibi.ui.RECORDER_INTERNAL_SELECTED_VALUE import app.myzel394.alibi.ui.RECORDER_MEDIA_SELECTED_VALUE @@ -519,10 +522,32 @@ abstract class BatchesFolder( return uri!! } + fun getAvailableBytes(): Long { + val storageManager = context.getSystemService(StorageManager::class.java) ?: return -1 + val file = when (type) { + BatchType.INTERNAL -> context.filesDir + BatchType.CUSTOM -> customFolder!!.uri.toFile() + BatchType.MEDIA -> scopedMediaContentUri.toFile() + } + + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + storageManager.getAllocatableBytes(storageManager.getUuidForPath(file)) + } else { + file.usableSpace; + } + } + enum class BatchType { INTERNAL, CUSTOM, MEDIA, } + + companion object { + fun requiredBytesForOneMinuteOfRecording(appSettings: AppSettings): Long { + // 300 MiB sounds like a good default + return 300 * 1024 * 1024 + } + } } diff --git a/app/src/main/java/app/myzel394/alibi/helpers/VideoBatchesFolder.kt b/app/src/main/java/app/myzel394/alibi/helpers/VideoBatchesFolder.kt index 22f0201..e143681 100644 --- a/app/src/main/java/app/myzel394/alibi/helpers/VideoBatchesFolder.kt +++ b/app/src/main/java/app/myzel394/alibi/helpers/VideoBatchesFolder.kt @@ -135,7 +135,8 @@ class VideoBatchesFolder( fun viaMediaFolder(context: Context) = VideoBatchesFolder(context, BatchType.MEDIA) - fun importFromFolder(folder: String, context: Context) = when (folder) { + fun importFromFolder(folder: String?, context: Context) = when (folder) { + null -> viaInternalFolder(context) RECORDER_INTERNAL_SELECTED_VALUE -> viaInternalFolder(context) RECORDER_MEDIA_SELECTED_VALUE -> viaMediaFolder(context) else -> viaCustomFolder( diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/LowStorageInfo.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/LowStorageInfo.kt new file mode 100644 index 0000000..9ee6dac --- /dev/null +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/atoms/LowStorageInfo.kt @@ -0,0 +1,41 @@ +package app.myzel394.alibi.ui.components.RecorderScreen.atoms + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import app.myzel394.alibi.R +import app.myzel394.alibi.db.AppSettings +import app.myzel394.alibi.helpers.BatchesFolder +import app.myzel394.alibi.helpers.VideoBatchesFolder +import app.myzel394.alibi.ui.components.atoms.MessageBox +import app.myzel394.alibi.ui.components.atoms.MessageType + +@Composable +fun LowStorageInfo( + appSettings: AppSettings, +) { + val context = LocalContext.current + val availableBytes = + VideoBatchesFolder.importFromFolder(appSettings.saveFolder, context).getAvailableBytes() + + val bytesPerMinute = BatchesFolder.requiredBytesForOneMinuteOfRecording(appSettings) + val requiredBytes = appSettings.maxDuration / 1000 / 60 * bytesPerMinute + + // Allow for a 10% margin of error + val isLowOnStorage = availableBytes < requiredBytes * 1.1 + println("LowStorageInfo: availableBytes: $availableBytes, requiredBytes: $requiredBytes, isLowOnStorage: $isLowOnStorage") + + if (isLowOnStorage) + Box( + modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp) + ) { + MessageBox( + type = MessageType.WARNING, + message = stringResource(R.string.ui_recorder_lowOnStorage_hint), + ) + } +} diff --git a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/StartRecording.kt b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/StartRecording.kt index 0ea2ddc..f59ad8e 100644 --- a/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/StartRecording.kt +++ b/app/src/main/java/app/myzel394/alibi/ui/components/RecorderScreen/organisms/StartRecording.kt @@ -44,6 +44,7 @@ import app.myzel394.alibi.R import app.myzel394.alibi.db.AppSettings import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_MAX_WIDTH import app.myzel394.alibi.ui.BIG_PRIMARY_BUTTON_SIZE +import app.myzel394.alibi.ui.components.RecorderScreen.atoms.LowStorageInfo import app.myzel394.alibi.ui.components.RecorderScreen.molecules.AudioRecordingStart import app.myzel394.alibi.ui.components.RecorderScreen.molecules.QuickMaxDurationSelector import app.myzel394.alibi.ui.components.RecorderScreen.molecules.VideoRecordingStart @@ -212,5 +213,7 @@ fun StartRecording( } } } + + LowStorageInfo(appSettings = appSettings) } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0e30de6..e826fa3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -193,4 +193,5 @@ Back Save now? You can save the current ongoing recording by pressing and holding down on the save button. The recording will continue in the background. + You are low on storage. Alibi may not function properly. Please free up some space. \ No newline at end of file