From a66f001033c3b7c6336957d88e4b60bf2c0cb4fa Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Wed, 29 Mar 2023 17:22:05 -0400 Subject: [PATCH] Adds Image Upload on Profile Edit pages. --- .../ui/actions/NewUserMetadataView.kt | 25 +++++++++ .../ui/actions/NewUserMetadataViewModel.kt | 56 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataView.kt index 3a683ec89..130c20f83 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataView.kt @@ -1,5 +1,6 @@ package com.vitorpamplona.amethyst.ui.actions +import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -18,6 +19,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.unit.dp @@ -30,9 +32,14 @@ import com.vitorpamplona.amethyst.model.Account @Composable fun NewUserMetadataView(onClose: () -> Unit, account: Account) { val postViewModel: NewUserMetadataViewModel = viewModel() + val context = LocalContext.current LaunchedEffect(Unit) { postViewModel.load(account) + + postViewModel.imageUploadingError.collect { error -> + Toast.makeText(context, error, Toast.LENGTH_SHORT).show() + } } Dialog( @@ -141,6 +148,15 @@ fun NewUserMetadataView(onClose: () -> Unit, account: Account) { color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) ) }, + leadingIcon = { + UploadFromGallery( + isUploading = postViewModel.isUploadingImageForPicture, + tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f), + modifier = Modifier.padding(start = 5.dp) + ) { + postViewModel.uploadForPicture(it, context) + } + }, singleLine = true ) @@ -157,6 +173,15 @@ fun NewUserMetadataView(onClose: () -> Unit, account: Account) { color = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) ) }, + leadingIcon = { + UploadFromGallery( + isUploading = postViewModel.isUploadingImageForBanner, + tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f), + modifier = Modifier.padding(start = 5.dp) + ) { + postViewModel.uploadForBanner(it, context) + } + }, singleLine = true ) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt index 0b8e272ff..e6a9bf2e0 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/NewUserMetadataViewModel.kt @@ -1,13 +1,20 @@ package com.vitorpamplona.amethyst.ui.actions +import android.content.Context +import android.net.Uri +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.node.ObjectNode import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.service.model.GitHubIdentity import com.vitorpamplona.amethyst.service.model.MastodonIdentity import com.vitorpamplona.amethyst.service.model.TwitterIdentity +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.launch import java.io.ByteArrayInputStream import java.io.StringWriter @@ -30,6 +37,10 @@ class NewUserMetadataViewModel : ViewModel() { val github = mutableStateOf("") val mastodon = mutableStateOf("") + var isUploadingImageForPicture by mutableStateOf(false) + var isUploadingImageForBanner by mutableStateOf(false) + val imageUploadingError = MutableSharedFlow() + fun load(account: Account) { this.account = account @@ -127,4 +138,49 @@ class NewUserMetadataViewModel : ViewModel() { github.value = "" mastodon.value = "" } + + fun uploadForPicture(uri: Uri, context: Context) { + upload( + uri, + context, + onUploading = { + isUploadingImageForPicture = it + }, + onUploaded = { + picture.value = it + } + ) + } + + fun uploadForBanner(uri: Uri, context: Context) { + upload( + uri, + context, + onUploading = { + isUploadingImageForBanner = it + }, + onUploaded = { + banner.value = it + } + ) + } + + fun upload(it: Uri, context: Context, onUploading: (Boolean) -> Unit, onUploaded: (String) -> Unit) { + onUploading(true) + + ImageUploader.uploadImage( + uri = it, + contentResolver = context.contentResolver, + onSuccess = { imageUrl -> + onUploading(false) + onUploaded(imageUrl) + }, + onError = { + onUploading(false) + viewModelScope.launch { + imageUploadingError.emit("Failed to upload the image / video") + } + } + ) + } }