Add take video functionality

Add take video button to new post screen
I18N
This commit is contained in:
davotoula
2025-08-29 09:13:26 +01:00
parent df85c3969c
commit f83166e576
3 changed files with 105 additions and 0 deletions

View File

@@ -29,6 +29,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.height
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CameraAlt
import androidx.compose.material.icons.filled.Videocam
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
@@ -152,3 +153,99 @@ fun getPhotoUri(context: Context): Uri {
)
}
}
@Composable
fun TakeVideoButton(onVideoTaken: (ImmutableList<SelectedMedia>) -> Unit) {
var showCamera by remember { mutableStateOf(false) }
if (showCamera) {
TakeVideo(
onVideoTaken = { uri ->
showCamera = false
if (uri.isNotEmpty()) {
onVideoTaken(uri)
}
},
)
}
VideoButton { showCamera = true }
}
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun TakeVideo(onVideoTaken: (ImmutableList<SelectedMedia>) -> Unit) {
val context = LocalContext.current
var videoUri by remember { mutableStateOf<Uri?>(null) }
val scope = rememberCoroutineScope()
val launcher =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.CaptureVideo(),
) { success ->
if (success) {
videoUri?.let {
onVideoTaken(persistentListOf(SelectedMedia(it, "video/mp4")))
}
} else {
onVideoTaken(persistentListOf())
}
videoUri = null
}
val cameraPermissionState =
rememberPermissionState(
Manifest.permission.CAMERA,
onPermissionResult = {
if (it) {
scope.launch(Dispatchers.IO) {
videoUri = getVideoUri(context)
videoUri?.let { launcher.launch(it) }
}
}
},
)
if (cameraPermissionState.status.isGranted) {
LaunchedEffect(key1 = Unit) {
launch(Dispatchers.IO) {
videoUri = getVideoUri(context)
videoUri?.let { launcher.launch(it) }
}
}
} else {
LaunchedEffect(key1 = Unit) {
cameraPermissionState.launchPermissionRequest()
}
}
}
@Composable
fun VideoButton(onClick: () -> Unit) {
IconButton(
onClick = onClick,
) {
Icon(
imageVector = Icons.Default.Videocam,
contentDescription = stringRes(id = R.string.record_a_video),
modifier = Modifier.height(22.dp),
tint = MaterialTheme.colorScheme.onBackground,
)
}
}
fun getVideoUri(context: Context): Uri {
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_MOVIES)
return File
.createTempFile(
"MP4_${timeStamp}_",
".mp4",
storageDir,
).let {
FileProvider.getUriForFile(
context,
"${context.packageName}.provider",
it,
)
}
}

View File

@@ -60,6 +60,7 @@ import com.vitorpamplona.amethyst.ui.actions.mediaServers.ServerType
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectFromGallery
import com.vitorpamplona.amethyst.ui.actions.uploads.SelectedMedia
import com.vitorpamplona.amethyst.ui.actions.uploads.TakePictureButton
import com.vitorpamplona.amethyst.ui.actions.uploads.TakeVideoButton
import com.vitorpamplona.amethyst.ui.components.getActivity
import com.vitorpamplona.amethyst.ui.navigation.navs.Nav
import com.vitorpamplona.amethyst.ui.navigation.topbars.PostingTopBar
@@ -431,6 +432,12 @@ private fun BottomRowActions(postViewModel: ShortNotePostViewModel) {
},
)
TakeVideoButton(
onVideoTaken = {
postViewModel.selectImage(it)
},
)
if (postViewModel.canUsePoll) {
// These should be hashtag recommendations the user selects in the future.
// val hashtag = stringRes(R.string.poll_hashtag)

View File

@@ -160,6 +160,7 @@
<string name="failed_to_save_the_video">Failed to save the video</string>
<string name="upload_image">Upload Image</string>
<string name="take_a_picture">Take a picture</string>
<string name="record_a_video">Record a video</string>
<string name="record_a_message">Record a message</string>
<string name="record_a_message_title">Record a message</string>
<string name="record_a_message_description">Click and hold to record a message</string>