From 0de415fba034ff9800a288d45dde28667682fc4c Mon Sep 17 00:00:00 2001 From: polina Date: Thu, 29 May 2025 11:29:34 +0200 Subject: [PATCH 1/2] all working --- .../create/presentation/ui/CreateScreen.kt | 56 ++++++++++++++++--- .../presentation/viewmodel/CanvasViewModel.kt | 18 ++++++ 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/codekotliners/memify/features/create/presentation/ui/CreateScreen.kt b/app/src/main/java/com/codekotliners/memify/features/create/presentation/ui/CreateScreen.kt index c9019d2a..b721364b 100644 --- a/app/src/main/java/com/codekotliners/memify/features/create/presentation/ui/CreateScreen.kt +++ b/app/src/main/java/com/codekotliners/memify/features/create/presentation/ui/CreateScreen.kt @@ -1,6 +1,9 @@ package com.codekotliners.memify.features.create.presentation.ui +import android.app.Activity import android.content.Intent +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -25,6 +28,7 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material.icons.filled.KeyboardArrowUp import androidx.compose.material.icons.filled.MoreVert @@ -33,6 +37,7 @@ import androidx.compose.material3.BottomSheetScaffoldState import androidx.compose.material3.CenterAlignedTopAppBar import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme @@ -106,11 +111,22 @@ fun CreateScreen( viewModelViewer: ImageViewerViewModel = hiltViewModel(), ) { val isPublishing by viewModelViewer.isPublishing.collectAsState() + val context = LocalContext.current + val galleryLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult() + ) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val uri = result.data?.data + viewModel.handleImageSelection(uri) + } + } + LaunchedEffect(Unit) { + viewModel.imagePickerLauncher.value = galleryLauncher + } LaunchedEffect(imageUrl) { viewModel.imageUrl = imageUrl } - val bottomSheetState = rememberStandardBottomSheetState( initialValue = SheetValue.Expanded, @@ -134,6 +150,7 @@ fun CreateScreen( PublishingLoadCircle(isPublishing) } } + } @Composable @@ -357,6 +374,20 @@ private fun CreateScreenContent(innerPadding: PaddingValues, viewModel: CanvasVi InteractiveCanvas(viewModel, graphicsLayer) } } + Box( + modifier = Modifier + .fillMaxSize() + .padding(bottom = 80.dp, end = 16.dp), + contentAlignment = Alignment.BottomEnd + ) { + FloatingActionButton( + onClick = { viewModel.pickImageFromGallery() }, + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary + ) { + Icon(Icons.Default.Add, contentDescription = "Add from gallery") + } + } } @OptIn(ExperimentalMaterial3Api::class) @@ -387,14 +418,23 @@ fun BottomSheetHandle(bottomSheetState: SheetState) { @Composable private fun InteractiveCanvas(viewModel: CanvasViewModel, graphicsLayer: GraphicsLayer) { val context = LocalContext.current - val painter = - rememberAsyncImagePainter( - model = - ImageRequest - .Builder(context) + val painter = rememberAsyncImagePainter( + model = when { + viewModel.imageUrl?.startsWith("content://") == true -> { + // Handle content URI (from gallery) + ImageRequest.Builder(context) .data(viewModel.imageUrl) - .build(), - ) + .build() + } + !viewModel.imageUrl.isNullOrEmpty() -> { + // Handle network URL + ImageRequest.Builder(context) + .data(viewModel.imageUrl) + .build() + } + else -> null + } + ) // Получаем размеры изображения после загрузки LaunchedEffect(painter.state) { diff --git a/app/src/main/java/com/codekotliners/memify/features/create/presentation/viewmodel/CanvasViewModel.kt b/app/src/main/java/com/codekotliners/memify/features/create/presentation/viewmodel/CanvasViewModel.kt index ea2e226e..35bf85e1 100644 --- a/app/src/main/java/com/codekotliners/memify/features/create/presentation/viewmodel/CanvasViewModel.kt +++ b/app/src/main/java/com/codekotliners/memify/features/create/presentation/viewmodel/CanvasViewModel.kt @@ -1,5 +1,9 @@ package com.codekotliners.memify.features.create.presentation.viewmodel +import android.content.Intent +import android.net.Uri +import android.provider.MediaStore +import androidx.activity.result.ActivityResultLauncher import androidx.compose.runtime.MutableState import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue @@ -52,6 +56,8 @@ open class CanvasViewModel @Inject constructor() : ViewModel() { var showRadialMenu by mutableStateOf(false) var radialMenuPosition by mutableStateOf(Offset.Zero) + val imagePickerLauncher = mutableStateOf?>(null) + fun addPointToCurrentLine(point: Offset) { currentLine.add(point) } @@ -135,4 +141,16 @@ open class CanvasViewModel @Inject constructor() : ViewModel() { canvasElements[index] = element.copy(position = newPosition) } } + fun pickImageFromGallery() { + val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI).apply { + type = "image/*" + } + imagePickerLauncher.value?.launch(intent) + } + + fun handleImageSelection(uri: Uri?) { + uri?.let { + imageUrl = it.toString() + } + } } From 0a17b73ff7c665794e0ce4f7b23f0919ce233e6e Mon Sep 17 00:00:00 2001 From: polina Date: Thu, 29 May 2025 11:33:25 +0200 Subject: [PATCH 2/2] all working --- .../create/presentation/ui/CreateScreen.kt | 65 ++++++++++--------- .../presentation/viewmodel/CanvasViewModel.kt | 8 ++- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/codekotliners/memify/features/create/presentation/ui/CreateScreen.kt b/app/src/main/java/com/codekotliners/memify/features/create/presentation/ui/CreateScreen.kt index b721364b..a0106933 100644 --- a/app/src/main/java/com/codekotliners/memify/features/create/presentation/ui/CreateScreen.kt +++ b/app/src/main/java/com/codekotliners/memify/features/create/presentation/ui/CreateScreen.kt @@ -113,14 +113,15 @@ fun CreateScreen( val isPublishing by viewModelViewer.isPublishing.collectAsState() val context = LocalContext.current - val galleryLauncher = rememberLauncherForActivityResult( - contract = ActivityResultContracts.StartActivityForResult() - ) { result -> - if (result.resultCode == Activity.RESULT_OK) { - val uri = result.data?.data - viewModel.handleImageSelection(uri) + val galleryLauncher = + rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult(), + ) { result -> + if (result.resultCode == Activity.RESULT_OK) { + val uri = result.data?.data + viewModel.handleImageSelection(uri) + } } - } LaunchedEffect(Unit) { viewModel.imagePickerLauncher.value = galleryLauncher } @@ -150,7 +151,6 @@ fun CreateScreen( PublishingLoadCircle(isPublishing) } } - } @Composable @@ -375,15 +375,16 @@ private fun CreateScreenContent(innerPadding: PaddingValues, viewModel: CanvasVi } } Box( - modifier = Modifier - .fillMaxSize() - .padding(bottom = 80.dp, end = 16.dp), - contentAlignment = Alignment.BottomEnd + modifier = + Modifier + .fillMaxSize() + .padding(bottom = 80.dp, end = 16.dp), + contentAlignment = Alignment.BottomEnd, ) { FloatingActionButton( onClick = { viewModel.pickImageFromGallery() }, containerColor = MaterialTheme.colorScheme.primary, - contentColor = MaterialTheme.colorScheme.onPrimary + contentColor = MaterialTheme.colorScheme.onPrimary, ) { Icon(Icons.Default.Add, contentDescription = "Add from gallery") } @@ -418,23 +419,27 @@ fun BottomSheetHandle(bottomSheetState: SheetState) { @Composable private fun InteractiveCanvas(viewModel: CanvasViewModel, graphicsLayer: GraphicsLayer) { val context = LocalContext.current - val painter = rememberAsyncImagePainter( - model = when { - viewModel.imageUrl?.startsWith("content://") == true -> { - // Handle content URI (from gallery) - ImageRequest.Builder(context) - .data(viewModel.imageUrl) - .build() - } - !viewModel.imageUrl.isNullOrEmpty() -> { - // Handle network URL - ImageRequest.Builder(context) - .data(viewModel.imageUrl) - .build() - } - else -> null - } - ) + val painter = + rememberAsyncImagePainter( + model = + when { + viewModel.imageUrl?.startsWith("content://") == true -> { + // Handle content URI (from gallery) + ImageRequest + .Builder(context) + .data(viewModel.imageUrl) + .build() + } + !viewModel.imageUrl.isNullOrEmpty() -> { + // Handle network URL + ImageRequest + .Builder(context) + .data(viewModel.imageUrl) + .build() + } + else -> null + }, + ) // Получаем размеры изображения после загрузки LaunchedEffect(painter.state) { diff --git a/app/src/main/java/com/codekotliners/memify/features/create/presentation/viewmodel/CanvasViewModel.kt b/app/src/main/java/com/codekotliners/memify/features/create/presentation/viewmodel/CanvasViewModel.kt index 35bf85e1..f828c634 100644 --- a/app/src/main/java/com/codekotliners/memify/features/create/presentation/viewmodel/CanvasViewModel.kt +++ b/app/src/main/java/com/codekotliners/memify/features/create/presentation/viewmodel/CanvasViewModel.kt @@ -141,10 +141,12 @@ open class CanvasViewModel @Inject constructor() : ViewModel() { canvasElements[index] = element.copy(position = newPosition) } } + fun pickImageFromGallery() { - val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI).apply { - type = "image/*" - } + val intent = + Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI).apply { + type = "image/*" + } imagePickerLauncher.value?.launch(intent) }