Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reworked PickImage() composable #877

Merged
merged 10 commits into from
Jun 25, 2023
74 changes: 25 additions & 49 deletions app/src/main/java/com/jerboa/ui/components/common/PictrsImage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,26 @@ package com.jerboa.ui.components.common

import BlurTransformation
import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
Expand All @@ -40,14 +33,12 @@ import coil.compose.AsyncImage
import coil.request.ImageRequest
import com.jerboa.R
import com.jerboa.datatypes.sampleCommunity
import com.jerboa.decodeUriToBitmap
import com.jerboa.pictrsImageThumbnail
import com.jerboa.ui.theme.ICON_SIZE
import com.jerboa.ui.theme.ICON_THUMBNAIL_SIZE
import com.jerboa.ui.theme.LARGER_ICON_SIZE
import com.jerboa.ui.theme.LARGER_ICON_THUMBNAIL_SIZE
import com.jerboa.ui.theme.MAX_IMAGE_SIZE
import com.jerboa.ui.theme.SMALL_PADDING
import com.jerboa.ui.theme.THUMBNAIL_SIZE
import com.jerboa.ui.theme.muted

Expand Down Expand Up @@ -206,63 +197,48 @@ fun PictrsBannerImage(
}

@Composable
fun PickImage(
fun ColumnScope.PickImage(
modifier: Modifier = Modifier,
onPickedImage: (image: Uri) -> Unit,
image: Uri? = null,
showImage: Boolean = true,
sharedImage: Uri? = null,
isUploadingImage: Boolean = false,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
) {
val ctx = LocalContext.current
var imageUri by remember {
mutableStateOf<Uri?>(null)
}
val bitmap = remember {
mutableStateOf<Bitmap?>(null)
fun initiateUpload(uri: Uri) {
Log.d("jerboa", "Uploading image...")
Log.d("jerboa", uri.toString())
onPickedImage(uri)
}

if (image != null) {
LaunchedEffect(image) {
imageUri = image
bitmap.value = decodeUriToBitmap(ctx, imageUri!!)
Log.d("jerboa", "Uploading image...")
Log.d("jerboa", imageUri.toString())
onPickedImage(image)
if (sharedImage != null) {
LaunchedEffect(sharedImage) {
initiateUpload(sharedImage)
}
}

val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.GetContent(),
) { uri ->
uri?.let {
imageUri = it
bitmap.value = decodeUriToBitmap(ctx, it)
Log.d("jerboa", "Uploading image...")
Log.d("jerboa", imageUri.toString())
onPickedImage(it)
initiateUpload(it)
}
}
Column(
modifier = modifier,
horizontalAlignment = horizontalAlignment,
) {
OutlinedButton(onClick = {

OutlinedButton(
modifier = modifier.align(horizontalAlignment),
onClick = {
launcher.launch("image/*")
}) {
},
) {
if (isUploadingImage) {
CircularProgressIndicator(
modifier = Modifier.size(ButtonDefaults.IconSize),
)
} else {
Text(
text = stringResource(R.string.pictrs_image_upload_image),
color = MaterialTheme.colorScheme.onBackground.muted,
)
}

if (showImage) {
Spacer(modifier = Modifier.height(SMALL_PADDING))
bitmap.value?.let { btm ->
Image(
bitmap = btm.asImageBitmap(),
contentDescription = stringResource(R.string.pickImage_imagePreview),
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ import com.jerboa.R
import com.jerboa.datatypes.sampleCommunity
import com.jerboa.datatypes.types.Community
import com.jerboa.db.Account
import com.jerboa.isImage
import com.jerboa.ui.components.common.CircularIcon
import com.jerboa.ui.components.common.MarkdownTextField
import com.jerboa.ui.components.common.PickImage
import com.jerboa.ui.components.common.PictrsUrlImage
import com.jerboa.ui.theme.ICON_SIZE
import com.jerboa.ui.theme.MEDIUM_PADDING
import com.jerboa.ui.theme.THUMBNAIL_SIZE
Expand Down Expand Up @@ -108,8 +110,9 @@ fun CreateEditPostBody(
url: String,
urlField: InputField,
onUrlChange: (url: String) -> Unit,
selectedImage: Uri? = null,
sharedImage: Uri? = null,
onImagePicked: (image: Uri) -> Unit,
isUploadingImage: Boolean = false,
isNsfw: Boolean,
onIsNsfwChange: (isNsfw: Boolean) -> Unit,
suggestedTitle: String? = null,
Expand Down Expand Up @@ -175,15 +178,22 @@ fun CreateEditPostBody(
}

/**
* Pick and upload an image, show a preview
* Pick and upload an image, show a preview if possible
*/
PickImage(
onPickedImage = onImagePicked,
image = selectedImage,
sharedImage = sharedImage,
horizontalAlignment = Alignment.End,
modifier = Modifier.fillMaxWidth(),
isUploadingImage = isUploadingImage,
)

if (isImage(url)) {
PictrsUrlImage(
url = url,
nsfw = false,
)
}

/**
* Markdown field for post body
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ fun CreatePostActivity(
),
)
}
var isUploadingImage by rememberSaveable { mutableStateOf(false) }

val nameField = validatePostName(name)
val urlField = validateUrl(url)
Expand Down Expand Up @@ -98,11 +99,11 @@ fun CreatePostActivity(
Surface(color = MaterialTheme.colorScheme.background) {
Scaffold(
topBar = {
val loading = when (createPostViewModel.createPostRes) {
ApiState.Loading -> true
else -> false
}
Column {
val loading = when (createPostViewModel.createPostRes) {
ApiState.Loading -> true
else -> false
}
CreateEditPostHeader(
navController = navController,
formValid = formValid,
Expand All @@ -124,7 +125,6 @@ fun CreatePostActivity(
},
title = stringResource(R.string.create_post_create_post),
)

if (loading) {
LoadingBar()
}
Expand Down Expand Up @@ -152,14 +152,17 @@ fun CreatePostActivity(
},
suggestedTitle = suggestedTitle,
suggestedTitleLoading = suggestedTitleLoading,
selectedImage = initialImage,
sharedImage = initialImage,
isUploadingImage = isUploadingImage,
onImagePicked = { uri ->
if (uri != Uri.EMPTY) {
val imageIs = imageInputStreamFromUri(ctx, uri)
scope.launch {
isUploadingImage = true
account?.also { acct ->
url = uploadPictrsImage(acct, imageIs, ctx).orEmpty()
}
isUploadingImage = false
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ fun PostEditActivity(
),
)
}
var isUploadingImage by rememberSaveable { mutableStateOf(false) }

val nameField = validatePostName(name)
val urlField = validateUrl(url)
Expand Down Expand Up @@ -116,11 +117,14 @@ fun PostEditActivity(
onImagePicked = { uri ->
val imageIs = imageInputStreamFromUri(ctx, uri)
scope.launch {
isUploadingImage = true
account?.also { acct ->
url = uploadPictrsImage(acct, imageIs, ctx).orEmpty()
}
isUploadingImage = false
}
},
isUploadingImage = isUploadingImage,
account = account,
padding = padding,
isNsfw = isNsfw,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ fun SettingsForm(
show_scores = showScores.value,
discussion_languages = null,
)
var isUploadingAvatar by rememberSaveable { mutableStateOf(false) }
var isUploadingBanner by rememberSaveable { mutableStateOf(false) }

Column(
modifier = Modifier
.padding(padding)
Expand Down Expand Up @@ -188,12 +191,17 @@ fun SettingsForm(
LargerCircularIcon(icon = avatar)
}
} else {
PickImage(onPickedImage = { uri ->
val imageIs = imageInputStreamFromUri(ctx, uri)
scope.launch {
avatar = uploadPictrsImage(account, imageIs, ctx).orEmpty()
}
}, showImage = false)
PickImage(
isUploadingImage = isUploadingAvatar,
onPickedImage = { uri ->
val imageIs = imageInputStreamFromUri(ctx, uri)
scope.launch {
isUploadingAvatar = true
avatar = uploadPictrsImage(account, imageIs, ctx).orEmpty()
isUploadingAvatar = false
}
},
)
}
}
Column(modifier = Modifier.padding(MEDIUM_PADDING)) {
Expand All @@ -203,12 +211,17 @@ fun SettingsForm(
PictrsBannerImage(url = banner)
}
} else {
PickImage(onPickedImage = { uri ->
val imageIs = imageInputStreamFromUri(ctx, uri)
scope.launch {
banner = uploadPictrsImage(account, imageIs, ctx).orEmpty()
}
}, showImage = false)
PickImage(
isUploadingImage = isUploadingBanner,
onPickedImage = { uri ->
val imageIs = imageInputStreamFromUri(ctx, uri)
scope.launch {
isUploadingBanner = true
banner = uploadPictrsImage(account, imageIs, ctx).orEmpty()
isUploadingBanner = false
}
},
)
}
}
SettingsListDropdown(
Expand Down