diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 00000000..7643783a
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 00000000..79ee123c
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9a9d8839..1d69610d 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -97,6 +97,7 @@ dependencies {
// Lifecycle
implementation(libs.androidx.lifecycle.viewmodel.compose)
+ implementation(libs.androidx.lifecycle.runtime.compose)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.lifecycle.livedata.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
@@ -127,6 +128,14 @@ dependencies {
implementation(libs.zoomable)
implementation(libs.zoomable.image.coil)
+
+ // CameraX
+ implementation(libs.camera.core)
+ implementation(libs.camera.camera2)
+ implementation(libs.camera.lifecycle)
+ implementation(libs.camera.extensions)
+ implementation(libs.camera.video)
+ implementation(libs.camera.view)
}
ktlint {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8e85acf3..df16769f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,6 +2,11 @@
+
+
+
photoUri = uris
}
+ val controller = remember {
+ LifecycleCameraController(context).apply {
+ setEnabledUseCases(CameraController.IMAGE_CAPTURE)
+ }
+ }
val permissionState = rememberPermissionState(
permission = Manifest.permission.RECORD_AUDIO
)
+ val camPermissionState = rememberPermissionState(
+ permission = Manifest.permission.CAMERA
+ )
+
// add note
if (isNew) {
SideEffect {
permissionState.launchPermissionRequest()
}
+ if ((permissionState.status.isGranted || !permissionState.status.isGranted) && !camPermissionState.status.isGranted) {
+ SideEffect {
+ camPermissionState.launchPermissionRequest()
+ }
+ }
}
val speechRecognizerLauncher = rememberLauncherForActivityResult(contract = SpeechRecognizerContract(), onResult = {
it?.let {
@@ -236,6 +275,18 @@ fun AddEditScreen(
.navigationBarsPadding()
.padding(16.dp)
) {
+ BottomSheetOptions(
+ text = stringResource(R.string.take_image),
+ icon = painterResource(id = R.drawable.camera_icon),
+ onClick = {
+ if (camPermissionState.status.isGranted) {
+ openCameraBottomSheet = true
+ } else {
+ camPermissionState.launchPermissionRequest()
+ }
+ showSheet = false
+ }
+ )
BottomSheetOptions(
text = stringResource(R.string.add_image),
icon = painterResource(id = R.drawable.gallery_icon),
@@ -345,7 +396,6 @@ fun AddEditScreen(
}
}
}
-
TextField(
modifier = Modifier.fillMaxWidth(), value = title, onValueChange = { newTitle ->
if (isNew) {
@@ -430,7 +480,6 @@ fun AddEditScreen(
}
}
}
-
TextDialog(
title = stringResource(R.string.are_you_sure),
description = stringResource(R.string.the_text_change_will_not_be_saved),
@@ -441,4 +490,84 @@ fun AddEditScreen(
cancelDialogState.value = false
}
)
+
+ if (openCameraBottomSheet) {
+ BottomSheetScaffold(scaffoldState = scaffoldState, sheetPeekHeight = 0.dp, sheetContent = {}) {
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(it)
+ ) {
+ CameraPreview(controller = controller, modifier = Modifier.fillMaxSize())
+
+ IconButton(onClick = {
+ openCameraBottomSheet = false
+ }, modifier = Modifier.offset(16.dp, 16.dp)) {
+ Icon(imageVector = Icons.Filled.ArrowBack, contentDescription = "navigate back")
+ }
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .align(Alignment.BottomCenter)
+ .padding(16.dp), horizontalArrangement = Arrangement.SpaceAround
+ ) {
+ IconButton(onClick = {
+ controller.cameraSelector =
+ if (controller.cameraSelector == CameraSelector.DEFAULT_BACK_CAMERA) {
+ CameraSelector.DEFAULT_FRONT_CAMERA
+ } else {
+ CameraSelector.DEFAULT_BACK_CAMERA
+ }
+ }) {
+ Icon(imageVector = Icons.Filled.Cameraswitch, contentDescription = "camera Switch")
+ }
+ IconButton(onClick = {
+ takePhoto(controller, context, onPhotoCaptured = { receviedUri ->
+ receviedUri?.let {
+ photoUri += it
+ }
+ })
+ }) {
+ Icon(imageVector = Icons.Filled.PhotoCamera, contentDescription = "Click To Capture")
+ }
+ }
+ }
+ }
+ }
+}
+
+fun takePhoto(controller: LifecycleCameraController, context: Context, onPhotoCaptured: (Uri?) -> Unit) {
+ controller.takePicture(ContextCompat.getMainExecutor(context), object : OnImageCapturedCallback() {
+ override fun onCaptureSuccess(image: ImageProxy) {
+ super.onCaptureSuccess(image)
+ val matrix = Matrix().apply {
+ postRotate(image.imageInfo.rotationDegrees.toFloat())
+ if (controller.cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA) {
+ postScale(-1f, 1f)
+ }
+ }
+ val bitmap = Bitmap.createBitmap(image.toBitmap(), 0, 0, image.width, image.height, matrix, true)
+ Toast.makeText(context, "Photo Attached Successfully", Toast.LENGTH_SHORT).show()
+ onPhotoCaptured(bitmap.toUri(context = context))
+ }
+
+ override fun onError(exception: ImageCaptureException) {
+ super.onError(exception)
+ Toast.makeText(context, "Something Went Wrong ! Try Again", Toast.LENGTH_SHORT).show()
+ }
+ })
+}
+
+fun Bitmap.toUri(context: Context, format: Bitmap.CompressFormat = Bitmap.CompressFormat.JPEG): Uri? {
+ val bytes = ByteArrayOutputStream()
+ compress(format, 100, bytes)
+ val path = MediaStore.Images.Media.insertImage(
+ context.contentResolver,
+ this,
+ "${System.currentTimeMillis()}",
+ null
+ )
+ return Uri.parse(path)
}
+
+
diff --git a/app/src/main/java/com/aritra/notify/ui/screens/notes/addEditScreen/AddEditViewModel.kt b/app/src/main/java/com/aritra/notify/ui/screens/notes/addEditScreen/AddEditViewModel.kt
index 095461aa..0ebc2b40 100644
--- a/app/src/main/java/com/aritra/notify/ui/screens/notes/addEditScreen/AddEditViewModel.kt
+++ b/app/src/main/java/com/aritra/notify/ui/screens/notes/addEditScreen/AddEditViewModel.kt
@@ -1,6 +1,7 @@
package com.aritra.notify.ui.screens.notes.addEditScreen
import android.app.Application
+import android.graphics.Bitmap
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
@@ -11,6 +12,9 @@ import com.aritra.notify.domain.usecase.SaveSelectedImageUseCase
import com.aritra.notify.utils.toFile
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -147,7 +151,7 @@ class AddEditViewModel @Inject constructor(
_noteModel.postValue(noteModel.value?.copy(note = description))
}
- /* fun updateImage(imageList: List) {
- _noteModel.postValue(noteModel.value?.copy(image = imageList))
- }*/
+ /* fun updateImage(imageList: List) {
+ _noteModel.postValue(noteModel.value?.copy(image = imageList))
+ }*/
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2b4a25bd..6bb573bc 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -41,9 +41,11 @@
Rate us on Google Play
https://play.google.com/store/apps/details?id=com.aritra.notify
Image
+ No Clicked Photos
Clear Image
Speech to Text
Add image
+ Capture a Photo
Add Box
notify
Request permission
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 4f763b60..2b149690 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -33,6 +33,7 @@ devtools-ksp = "1.9.0-1.0.12"
zoomable = "0.6.2"
zoomableImageCoil = "0.6.2"
ktlint = "11.6.0"
+camerax_version = "1.4.0-alpha01"
[libraries]
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" }
@@ -58,6 +59,7 @@ androidx-lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensi
androidx-lifecycle-livedata-ktx = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "lifecycleVersion" }
androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle-runtime-ktx" }
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycleVersion" }
+androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleVersion" }
androidx-lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycleVersion" }
androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended", version.ref = "materialIconsExtended" }
androidx-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
@@ -77,6 +79,14 @@ hilt-compiler = { module = "com.google.dagger:hilt-compiler", version.ref = "hil
junit = { module = "junit:junit", version.ref = "junit" }
zoomable = { module = "me.saket.telephoto:zoomable", version.ref = "zoomable" }
zoomable-image-coil = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "zoomableImageCoil" }
+camera-core = { module = "androidx.camera:camera-core", version.ref = "camerax_version" }
+camera-camera2 = { module = "androidx.camera:camera-camera2", version.ref = "camerax_version" }
+camera-lifecycle = { module = "androidx.camera:camera-lifecycle", version.ref = "camerax_version" }
+camera-video = { module = "androidx.camera:camera-video", version.ref = "camerax_version" }
+camera-mlkit-vision = { module = "androidx.camera:camera-mlkit-vision", version.ref = "camerax_version" }
+camera-view = { module = "androidx.camera:camera-view", version.ref = "camerax_version" }
+camera-extensions = { module = "androidx.camera:camera-extensions", version.ref = "camerax_version" }
+
[plugins]
android-application = { id = "com.android.application", version.ref = "android-application" }
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 83085218..a45b7ac1 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,4 +1,4 @@
-#Tue Jun 27 10:53:54 IST 2023
+#Tue Oct 10 18:09:43 PKT 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip