Merge pull request #1043 from greenart7c3/camera
Take pictures with camera
This commit is contained in:
@@ -302,5 +302,11 @@ dependencies {
|
|||||||
debugImplementation platform(libs.androidx.compose.bom)
|
debugImplementation platform(libs.androidx.compose.bom)
|
||||||
debugImplementation libs.androidx.ui.tooling
|
debugImplementation libs.androidx.ui.tooling
|
||||||
debugImplementation libs.androidx.ui.test.manifest
|
debugImplementation libs.androidx.ui.test.manifest
|
||||||
|
|
||||||
|
implementation libs.androidx.camera.core
|
||||||
|
implementation libs.androidx.camera.camera2
|
||||||
|
implementation libs.androidx.camera.lifecycle
|
||||||
|
implementation libs.androidx.camera.view
|
||||||
|
implementation libs.androidx.camera.extensions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
<!-- To connect with relays -->
|
<!-- To connect with relays -->
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
|
|
||||||
|
<!-- To take pictures -->
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
<!-- To Upload media (newer devices) -->
|
<!-- To Upload media (newer devices) -->
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
|
||||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
|
||||||
@@ -121,6 +124,16 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</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>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -27,6 +27,8 @@ import android.os.Build
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
@@ -56,6 +58,7 @@ import androidx.compose.foundation.text.KeyboardOptions
|
|||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Bolt
|
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.CurrencyBitcoin
|
||||||
import androidx.compose.material.icons.filled.LocationOff
|
import androidx.compose.material.icons.filled.LocationOff
|
||||||
import androidx.compose.material.icons.filled.LocationOn
|
import androidx.compose.material.icons.filled.LocationOn
|
||||||
@@ -118,6 +121,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
|
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
@@ -197,6 +201,7 @@ fun NewPostView(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: INav,
|
nav: INav,
|
||||||
) {
|
) {
|
||||||
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
val postViewModel: NewPostViewModel = viewModel()
|
val postViewModel: NewPostViewModel = viewModel()
|
||||||
postViewModel.wantsDirectMessage = enableMessageInterface
|
postViewModel.wantsDirectMessage = enableMessageInterface
|
||||||
|
|
||||||
@@ -206,6 +211,9 @@ fun NewPostView(
|
|||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
var showRelaysDialog by remember { mutableStateOf(false) }
|
var showRelaysDialog by remember { mutableStateOf(false) }
|
||||||
var relayList = remember { accountViewModel.account.activeWriteRelays().toImmutableList() }
|
var relayList = remember { accountViewModel.account.activeWriteRelays().toImmutableList() }
|
||||||
|
var showCamera by remember {
|
||||||
|
mutableStateOf(true)
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(key1 = postViewModel.draftTag) {
|
LaunchedEffect(key1 = postViewModel.draftTag) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
@@ -563,7 +571,6 @@ fun NewPostView(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun BottomRowActions(postViewModel: NewPostViewModel) {
|
private fun BottomRowActions(postViewModel: NewPostViewModel) {
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
@@ -580,6 +587,12 @@ private fun BottomRowActions(postViewModel: NewPostViewModel) {
|
|||||||
postViewModel.selectImage(it)
|
postViewModel.selectImage(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TakePictureButton(
|
||||||
|
onPictureTaken = {
|
||||||
|
postViewModel.selectImage(it)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
if (postViewModel.canUsePoll) {
|
if (postViewModel.canUsePoll) {
|
||||||
// These should be hashtag recommendations the user selects in the future.
|
// These should be hashtag recommendations the user selects in the future.
|
||||||
// val hashtag = stringRes(R.string.poll_hashtag)
|
// val hashtag = stringRes(R.string.poll_hashtag)
|
||||||
@@ -625,6 +638,59 @@ private fun BottomRowActions(postViewModel: NewPostViewModel) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
|
@Composable
|
||||||
|
fun TakePictureButton(onPictureTaken: (Uri) -> Unit) {
|
||||||
|
var imageUri by remember { mutableStateOf<Uri?>(null) }
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
val launcher =
|
||||||
|
rememberLauncherForActivityResult(
|
||||||
|
contract = ActivityResultContracts.TakePicture(),
|
||||||
|
) { success ->
|
||||||
|
if (success) {
|
||||||
|
imageUri?.let {
|
||||||
|
onPictureTaken(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val context = LocalContext.current
|
||||||
|
val cameraPermissionState =
|
||||||
|
rememberPermissionState(
|
||||||
|
Manifest.permission.CAMERA,
|
||||||
|
onPermissionResult = {
|
||||||
|
if (it) {
|
||||||
|
scope.launch(Dispatchers.IO) {
|
||||||
|
imageUri = getPhotoUri(context)
|
||||||
|
imageUri?.let { uri -> launcher.launch(uri) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Box {
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.align(Alignment.Center),
|
||||||
|
onClick = {
|
||||||
|
if (cameraPermissionState.status.isGranted) {
|
||||||
|
scope.launch(Dispatchers.IO) {
|
||||||
|
imageUri = getPhotoUri(context)
|
||||||
|
imageUri?.let { uri -> launcher.launch(uri) }
|
||||||
|
}
|
||||||
|
} 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
|
@Composable
|
||||||
private fun PollField(postViewModel: NewPostViewModel) {
|
private fun PollField(postViewModel: NewPostViewModel) {
|
||||||
val optionsList = postViewModel.pollOptions
|
val optionsList = postViewModel.pollOptions
|
||||||
|
|||||||
@@ -20,8 +20,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.vitorpamplona.amethyst.ui.actions
|
package com.vitorpamplona.amethyst.ui.actions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.compose.animation.core.LinearEasing
|
import androidx.compose.animation.core.LinearEasing
|
||||||
import androidx.compose.animation.core.animateFloat
|
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.graphics.Color
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
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.ExperimentalPermissionsApi
|
||||||
import com.google.accompanist.permissions.isGranted
|
import com.google.accompanist.permissions.isGranted
|
||||||
import com.google.accompanist.permissions.rememberPermissionState
|
import com.google.accompanist.permissions.rememberPermissionState
|
||||||
@@ -60,6 +63,10 @@ import com.vitorpamplona.amethyst.ui.GetMediaActivityResultContract
|
|||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
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
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
@OptIn(ExperimentalPermissionsApi::class)
|
@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 =
|
val DefaultAnimationColors =
|
||||||
listOf(
|
listOf(
|
||||||
Color(0xFF5851D8),
|
Color(0xFF5851D8),
|
||||||
|
|||||||
+116
-15
@@ -23,11 +23,19 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.video
|
|||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Box
|
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.layout.size
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
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.CircularProgressIndicator
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -45,6 +53,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
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.GallerySelect
|
||||||
import com.vitorpamplona.amethyst.ui.actions.NewMediaModel
|
import com.vitorpamplona.amethyst.ui.actions.NewMediaModel
|
||||||
import com.vitorpamplona.amethyst.ui.actions.NewMediaView
|
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.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
@@ -73,7 +83,15 @@ fun NewImageButton(
|
|||||||
nav: INav,
|
nav: INav,
|
||||||
navScrollToTop: () -> Unit,
|
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) }
|
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 =
|
val cameraPermissionState =
|
||||||
rememberPermissionState(
|
rememberPermissionState(
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
@@ -102,7 +159,7 @@ fun NewImageButton(
|
|||||||
if (showGallerySelect) {
|
if (showGallerySelect) {
|
||||||
GallerySelect(
|
GallerySelect(
|
||||||
onImageUri = { uri ->
|
onImageUri = { uri ->
|
||||||
wantsToPost = false
|
wantsToPostFromGallery = false
|
||||||
showGallerySelect = false
|
showGallerySelect = false
|
||||||
pickedURI = uri
|
pickedURI = uri
|
||||||
},
|
},
|
||||||
@@ -128,18 +185,62 @@ fun NewImageButton(
|
|||||||
if (postViewModel.isUploadingImage) {
|
if (postViewModel.isUploadingImage) {
|
||||||
ShowProgress(postViewModel)
|
ShowProgress(postViewModel)
|
||||||
} else {
|
} else {
|
||||||
FloatingActionButton(
|
Column {
|
||||||
onClick = { wantsToPost = true },
|
if (isOpen) {
|
||||||
modifier = Size55Modifier,
|
FloatingActionButton(
|
||||||
shape = CircleShape,
|
onClick = {
|
||||||
containerColor = MaterialTheme.colorScheme.primary,
|
wantsToPostFromCamera = true
|
||||||
) {
|
isOpen = false
|
||||||
Icon(
|
},
|
||||||
painter = painterResource(R.drawable.ic_compose),
|
modifier = Size55Modifier,
|
||||||
contentDescription = stringRes(id = R.string.new_short),
|
shape = CircleShape,
|
||||||
modifier = Modifier.size(26.dp),
|
containerColor = MaterialTheme.colorScheme.primary,
|
||||||
tint = Color.White,
|
) {
|
||||||
)
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths>
|
||||||
|
<external-path
|
||||||
|
name="external_files"
|
||||||
|
path="." />
|
||||||
|
</paths>
|
||||||
@@ -52,6 +52,7 @@ zoomable = "1.6.2"
|
|||||||
zxing = "3.5.3"
|
zxing = "3.5.3"
|
||||||
zxingAndroidEmbedded = "4.3.0"
|
zxingAndroidEmbedded = "4.3.0"
|
||||||
windowCoreAndroid = "1.3.0"
|
windowCoreAndroid = "1.3.0"
|
||||||
|
androidxCamera = "1.3.4"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
abedElazizShe-image-compressor = { group = "com.github.AbedElazizShe", name = "LightCompressor", version.ref = "lightcompressor" }
|
abedElazizShe-image-compressor = { group = "com.github.AbedElazizShe", name = "LightCompressor", version.ref = "lightcompressor" }
|
||||||
@@ -61,6 +62,11 @@ androidx-activity-compose = { group = "androidx.activity", name = "activity-comp
|
|||||||
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||||
androidx-benchmark-junit4 = { group = "androidx.benchmark", name = "benchmark-junit4", version.ref = "benchmarkJunit4" }
|
androidx-benchmark-junit4 = { group = "androidx.benchmark", name = "benchmark-junit4", version.ref = "benchmarkJunit4" }
|
||||||
androidx-biometric-ktx = { group = "androidx.biometric", name = "biometric-ktx", version.ref = "biometricKtx" }
|
androidx-biometric-ktx = { group = "androidx.biometric", name = "biometric-ktx", version.ref = "biometricKtx" }
|
||||||
|
androidx-camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "androidxCamera" }
|
||||||
|
androidx-camera-core = { module = "androidx.camera:camera-core", version.ref = "androidxCamera" }
|
||||||
|
androidx-camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "androidxCamera" }
|
||||||
|
androidx-camera-view = { module = "androidx.camera:camera-view", version.ref = "androidxCamera" }
|
||||||
|
androidx-camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "androidxCamera" }
|
||||||
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||||
@@ -136,4 +142,4 @@ googleServices = { id = "com.google.gms.google-services", version.ref = "gms" }
|
|||||||
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
jetbrainsKotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
jetbrainsKotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
jetbrainsComposeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
jetbrainsComposeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||||
serialization = { id = 'org.jetbrains.kotlin.plugin.serialization', version.ref = 'kotlinxSerializationPlugin' }
|
serialization = { id = 'org.jetbrains.kotlin.plugin.serialization', version.ref = 'kotlinxSerializationPlugin' }
|
||||||
|
|||||||
Reference in New Issue
Block a user