mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-03-18 05:41:56 +01:00
Add camera button in the stories screen
This commit is contained in:
parent
2e110422c8
commit
1e3104d489
@ -21,11 +21,9 @@
|
||||
package com.vitorpamplona.amethyst.ui.actions
|
||||
|
||||
import android.Manifest
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.util.Log
|
||||
import android.util.Size
|
||||
import android.widget.Toast
|
||||
@ -123,7 +121,6 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
@ -189,11 +186,7 @@ import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.receiveAsFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.lang.Math.round
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, FlowPreview::class)
|
||||
@Composable
|
||||
@ -645,23 +638,6 @@ private fun BottomRowActions(postViewModel: NewPostViewModel) {
|
||||
}
|
||||
}
|
||||
|
||||
fun getPhotoUri(context: Context): Uri {
|
||||
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
|
||||
val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
|
||||
return File
|
||||
.createTempFile(
|
||||
"JPEG_${timeStamp}_",
|
||||
".jpg",
|
||||
storageDir,
|
||||
).let {
|
||||
FileProvider.getUriForFile(
|
||||
context,
|
||||
"${context.packageName}.provider",
|
||||
it,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
fun TakePictureButton(onPictureTaken: (Uri) -> Unit) {
|
||||
|
@ -20,8 +20,10 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.actions
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
import androidx.compose.animation.core.animateFloat
|
||||
@ -52,6 +54,7 @@ import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.FileProvider
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
@ -60,6 +63,10 @@ import com.vitorpamplona.amethyst.ui.GetMediaActivityResultContract
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@ -125,6 +132,23 @@ private fun UploadBoxButton(
|
||||
}
|
||||
}
|
||||
|
||||
fun getPhotoUri(context: Context): Uri {
|
||||
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
|
||||
val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
|
||||
return File
|
||||
.createTempFile(
|
||||
"JPEG_${timeStamp}_",
|
||||
".jpg",
|
||||
storageDir,
|
||||
).let {
|
||||
FileProvider.getUriForFile(
|
||||
context,
|
||||
"${context.packageName}.provider",
|
||||
it,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val DefaultAnimationColors =
|
||||
listOf(
|
||||
Color(0xFF5851D8),
|
||||
|
@ -23,11 +23,19 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.video
|
||||
import android.Manifest
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AddPhotoAlternate
|
||||
import androidx.compose.material.icons.filled.CameraAlt
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
@ -45,6 +53,7 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
@ -57,6 +66,7 @@ import com.vitorpamplona.amethyst.R
|
||||
import com.vitorpamplona.amethyst.ui.actions.GallerySelect
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewMediaModel
|
||||
import com.vitorpamplona.amethyst.ui.actions.NewMediaView
|
||||
import com.vitorpamplona.amethyst.ui.actions.getPhotoUri
|
||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
@ -73,7 +83,15 @@ fun NewImageButton(
|
||||
nav: INav,
|
||||
navScrollToTop: () -> Unit,
|
||||
) {
|
||||
var wantsToPost by remember { mutableStateOf(false) }
|
||||
val context = LocalContext.current
|
||||
|
||||
var isOpen by remember { mutableStateOf(false) }
|
||||
|
||||
var wantsToPostFromGallery by remember { mutableStateOf(false) }
|
||||
|
||||
var wantsToPostFromCamera by remember { mutableStateOf(false) }
|
||||
|
||||
var cameraUri by remember { mutableStateOf<Uri?>(null) }
|
||||
|
||||
var pickedURI by remember { mutableStateOf<Uri?>(null) }
|
||||
|
||||
@ -87,7 +105,46 @@ fun NewImageButton(
|
||||
}
|
||||
}
|
||||
|
||||
if (wantsToPost) {
|
||||
if (wantsToPostFromCamera) {
|
||||
val launcher =
|
||||
rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.TakePicture(),
|
||||
) { success ->
|
||||
if (success) {
|
||||
cameraUri?.let {
|
||||
pickedURI = it
|
||||
}
|
||||
}
|
||||
cameraUri = null
|
||||
wantsToPostFromCamera = false
|
||||
}
|
||||
|
||||
val cameraPermissionState =
|
||||
rememberPermissionState(
|
||||
Manifest.permission.CAMERA,
|
||||
onPermissionResult = {
|
||||
if (it) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
cameraUri = getPhotoUri(context)
|
||||
cameraUri?.let { launcher.launch(it) }
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
if (cameraPermissionState.status.isGranted) {
|
||||
LaunchedEffect(key1 = accountViewModel) {
|
||||
launch(Dispatchers.IO) {
|
||||
cameraUri = getPhotoUri(context)
|
||||
cameraUri?.let { launcher.launch(it) }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LaunchedEffect(key1 = accountViewModel) { cameraPermissionState.launchPermissionRequest() }
|
||||
}
|
||||
}
|
||||
|
||||
if (wantsToPostFromGallery) {
|
||||
val cameraPermissionState =
|
||||
rememberPermissionState(
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
@ -102,7 +159,7 @@ fun NewImageButton(
|
||||
if (showGallerySelect) {
|
||||
GallerySelect(
|
||||
onImageUri = { uri ->
|
||||
wantsToPost = false
|
||||
wantsToPostFromGallery = false
|
||||
showGallerySelect = false
|
||||
pickedURI = uri
|
||||
},
|
||||
@ -128,18 +185,62 @@ fun NewImageButton(
|
||||
if (postViewModel.isUploadingImage) {
|
||||
ShowProgress(postViewModel)
|
||||
} else {
|
||||
FloatingActionButton(
|
||||
onClick = { wantsToPost = true },
|
||||
modifier = Size55Modifier,
|
||||
shape = CircleShape,
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_compose),
|
||||
contentDescription = stringRes(id = R.string.new_short),
|
||||
modifier = Modifier.size(26.dp),
|
||||
tint = Color.White,
|
||||
)
|
||||
Column {
|
||||
if (isOpen) {
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
wantsToPostFromCamera = true
|
||||
isOpen = false
|
||||
},
|
||||
modifier = Size55Modifier,
|
||||
shape = CircleShape,
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.CameraAlt,
|
||||
contentDescription = stringRes(id = R.string.upload_image),
|
||||
modifier = Modifier.size(26.dp),
|
||||
tint = Color.White,
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
wantsToPostFromGallery = true
|
||||
isOpen = false
|
||||
},
|
||||
modifier = Size55Modifier,
|
||||
shape = CircleShape,
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AddPhotoAlternate,
|
||||
contentDescription = stringRes(id = R.string.upload_image),
|
||||
modifier = Modifier.size(26.dp),
|
||||
tint = Color.White,
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
}
|
||||
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
isOpen = !isOpen
|
||||
},
|
||||
modifier = Size55Modifier,
|
||||
shape = CircleShape,
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_compose),
|
||||
contentDescription = stringRes(id = R.string.new_short),
|
||||
modifier = Modifier.size(26.dp),
|
||||
tint = Color.White,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user