mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-04-09 04:18:11 +02:00
Add a button to take a picture from camera
This commit is contained in:
parent
f89c1ff391
commit
a03e02bfeb
@ -299,5 +299,12 @@ dependencies {
|
||||
debugImplementation platform(libs.androidx.compose.bom)
|
||||
debugImplementation libs.androidx.ui.tooling
|
||||
debugImplementation libs.androidx.ui.test.manifest
|
||||
|
||||
def camerax_version = "1.3.4"
|
||||
implementation "androidx.camera:camera-core:$camerax_version"
|
||||
implementation "androidx.camera:camera-camera2:$camerax_version"
|
||||
implementation "androidx.camera:camera-lifecycle:$camerax_version"
|
||||
implementation "androidx.camera:camera-view:$camerax_version"
|
||||
implementation "androidx.camera:camera-extensions:$camerax_version"
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,9 @@
|
||||
<!-- To connect with relays -->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
|
||||
<!-- To take pictures -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<!-- To Upload media (newer devices) -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
|
||||
@ -121,6 +124,16 @@
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.provider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -24,9 +24,12 @@ import android.Manifest
|
||||
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
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.border
|
||||
@ -56,6 +59,7 @@ import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Bolt
|
||||
import androidx.compose.material.icons.filled.CameraAlt
|
||||
import androidx.compose.material.icons.filled.CurrencyBitcoin
|
||||
import androidx.compose.material.icons.filled.LocationOff
|
||||
import androidx.compose.material.icons.filled.LocationOn
|
||||
@ -117,6 +121,8 @@ 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
|
||||
import coil.compose.AsyncImage
|
||||
@ -180,7 +186,11 @@ 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
|
||||
@ -195,6 +205,7 @@ fun NewPostView(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: (String) -> Unit,
|
||||
) {
|
||||
val lifecycleOwner = LocalLifecycleOwner.current
|
||||
val postViewModel: NewPostViewModel = viewModel()
|
||||
postViewModel.wantsDirectMessage = enableMessageInterface
|
||||
|
||||
@ -204,6 +215,9 @@ fun NewPostView(
|
||||
val scope = rememberCoroutineScope()
|
||||
var showRelaysDialog by remember { mutableStateOf(false) }
|
||||
var relayList = remember { accountViewModel.account.activeWriteRelays().toImmutableList() }
|
||||
var showCamera by remember {
|
||||
mutableStateOf(true)
|
||||
}
|
||||
|
||||
LaunchedEffect(key1 = postViewModel.draftTag) {
|
||||
launch(Dispatchers.IO) {
|
||||
@ -561,7 +575,6 @@ fun NewPostView(
|
||||
@Composable
|
||||
private fun BottomRowActions(postViewModel: NewPostViewModel) {
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
Row(
|
||||
modifier =
|
||||
Modifier
|
||||
@ -578,6 +591,12 @@ private fun BottomRowActions(postViewModel: NewPostViewModel) {
|
||||
postViewModel.selectImage(it)
|
||||
}
|
||||
|
||||
TakePictureButton(
|
||||
onPictureTaken = {
|
||||
postViewModel.selectImage(it)
|
||||
},
|
||||
)
|
||||
|
||||
if (postViewModel.canUsePoll) {
|
||||
// These should be hashtag recommendations the user selects in the future.
|
||||
// val hashtag = stringRes(R.string.poll_hashtag)
|
||||
@ -623,6 +642,64 @@ private fun BottomRowActions(postViewModel: NewPostViewModel) {
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
fun TakePictureButton(onPictureTaken: (Uri) -> Unit) {
|
||||
var imageUri by remember { mutableStateOf<Uri?>(null) }
|
||||
val launcher =
|
||||
rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.TakePicture(),
|
||||
) { success ->
|
||||
if (success) {
|
||||
imageUri?.let {
|
||||
onPictureTaken(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
val context = LocalContext.current
|
||||
val cameraPermissionState =
|
||||
rememberPermissionState(
|
||||
Manifest.permission.CAMERA,
|
||||
)
|
||||
|
||||
Box {
|
||||
IconButton(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
onClick = {
|
||||
if (cameraPermissionState.status.isGranted) {
|
||||
val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
|
||||
val storageDir: File? = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
|
||||
File
|
||||
.createTempFile(
|
||||
"JPEG_${timeStamp}_",
|
||||
".jpg",
|
||||
storageDir,
|
||||
).apply {
|
||||
imageUri =
|
||||
FileProvider.getUriForFile(
|
||||
context,
|
||||
"${context.packageName}.provider",
|
||||
this,
|
||||
)
|
||||
}
|
||||
imageUri?.let {
|
||||
launcher.launch(it)
|
||||
}
|
||||
} else {
|
||||
cameraPermissionState.launchPermissionRequest()
|
||||
}
|
||||
},
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.CameraAlt,
|
||||
contentDescription = stringRes(id = R.string.upload_image),
|
||||
modifier = Modifier.height(25.dp),
|
||||
tint = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PollField(postViewModel: NewPostViewModel) {
|
||||
val optionsList = postViewModel.pollOptions
|
||||
|
6
amethyst/src/main/res/xml/file_paths.xml
Normal file
6
amethyst/src/main/res/xml/file_paths.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths>
|
||||
<external-path
|
||||
name="external_files"
|
||||
path="." />
|
||||
</paths>
|
Loading…
x
Reference in New Issue
Block a user