mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-23 16:36:22 +02:00
@@ -218,7 +218,9 @@ fun NewPostView(onClose: () -> Unit, baseReplyTo: Note? = null, quote: Note? = n
|
|||||||
|
|
||||||
Row(modifier = Modifier.fillMaxWidth()) {
|
Row(modifier = Modifier.fillMaxWidth()) {
|
||||||
UploadFromGallery(
|
UploadFromGallery(
|
||||||
isUploading = postViewModel.isUploadingImage
|
isUploading = postViewModel.isUploadingImage,
|
||||||
|
tint = MaterialTheme.colors.primary,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp)
|
||||||
) {
|
) {
|
||||||
postViewModel.upload(it, context)
|
postViewModel.upload(it, context)
|
||||||
}
|
}
|
||||||
|
@@ -4,23 +4,38 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.compose.animation.core.LinearEasing
|
||||||
|
import androidx.compose.animation.core.animateFloat
|
||||||
|
import androidx.compose.animation.core.infiniteRepeatable
|
||||||
|
import androidx.compose.animation.core.rememberInfiniteTransition
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.*
|
import androidx.compose.material.*
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.AddPhotoAlternate
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.draw.rotate
|
||||||
|
import androidx.compose.ui.graphics.Brush
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
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
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
@OptIn(ExperimentalPermissionsApi::class)
|
@OptIn(ExperimentalPermissionsApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun UploadFromGallery(
|
fun UploadFromGallery(
|
||||||
isUploading: Boolean,
|
isUploading: Boolean,
|
||||||
|
tint: Color,
|
||||||
|
modifier: Modifier,
|
||||||
onImageChosen: (Uri) -> Unit
|
onImageChosen: (Uri) -> Unit
|
||||||
) {
|
) {
|
||||||
val cameraPermissionState =
|
val cameraPermissionState =
|
||||||
@@ -43,13 +58,13 @@ fun UploadFromGallery(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
}
|
||||||
UploadBoxButton(isUploading) {
|
|
||||||
showGallerySelect = true
|
UploadBoxButton(isUploading, tint, modifier) {
|
||||||
}
|
showGallerySelect = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UploadBoxButton(isUploading) {
|
UploadBoxButton(isUploading, tint, modifier) {
|
||||||
cameraPermissionState.launchPermissionRequest()
|
cameraPermissionState.launchPermissionRequest()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,50 +73,96 @@ fun UploadFromGallery(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun UploadBoxButton(
|
private fun UploadBoxButton(
|
||||||
isUploading: Boolean,
|
isUploading: Boolean,
|
||||||
|
tint: Color,
|
||||||
|
modifier: Modifier,
|
||||||
onClick: () -> Unit
|
onClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
Box() {
|
Box() {
|
||||||
TextButton(
|
IconButton(
|
||||||
modifier = Modifier
|
modifier = modifier.align(Alignment.Center),
|
||||||
.align(Alignment.TopCenter),
|
|
||||||
enabled = !isUploading,
|
enabled = !isUploading,
|
||||||
onClick = {
|
onClick = {
|
||||||
onClick()
|
onClick()
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Icon(
|
|
||||||
painter = painterResource(id = R.drawable.ic_add_photo),
|
|
||||||
contentDescription = stringResource(id = R.string.upload_image),
|
|
||||||
modifier = Modifier
|
|
||||||
.height(20.dp)
|
|
||||||
.padding(end = 8.dp),
|
|
||||||
tint = MaterialTheme.colors.primary
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!isUploading) {
|
if (!isUploading) {
|
||||||
Text(stringResource(R.string.upload_image))
|
Icon(
|
||||||
|
imageVector = Icons.Default.AddPhotoAlternate,
|
||||||
|
contentDescription = stringResource(id = R.string.upload_image),
|
||||||
|
modifier = Modifier.height(25.dp),
|
||||||
|
tint = tint
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Text(stringResource(R.string.uploading))
|
LoadingAnimation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LoadingAnimation(
|
||||||
|
indicatorSize: Dp = 20.dp,
|
||||||
|
circleColors: List<Color> = listOf(
|
||||||
|
Color(0xFF5851D8),
|
||||||
|
Color(0xFF833AB4),
|
||||||
|
Color(0xFFC13584),
|
||||||
|
Color(0xFFE1306C),
|
||||||
|
Color(0xFFFD1D1D),
|
||||||
|
Color(0xFFF56040),
|
||||||
|
Color(0xFFF77737),
|
||||||
|
Color(0xFFFCAF45),
|
||||||
|
Color(0xFFFFDC80),
|
||||||
|
Color(0xFF5851D8)
|
||||||
|
),
|
||||||
|
animationDuration: Int = 1000
|
||||||
|
) {
|
||||||
|
val infiniteTransition = rememberInfiniteTransition()
|
||||||
|
|
||||||
|
val rotateAnimation by infiniteTransition.animateFloat(
|
||||||
|
initialValue = 0f,
|
||||||
|
targetValue = 360f,
|
||||||
|
animationSpec = infiniteRepeatable(
|
||||||
|
animation = tween(
|
||||||
|
durationMillis = animationDuration,
|
||||||
|
easing = LinearEasing
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier
|
||||||
|
.size(size = indicatorSize)
|
||||||
|
.rotate(degrees = rotateAnimation)
|
||||||
|
.border(
|
||||||
|
width = 4.dp,
|
||||||
|
brush = Brush.sweepGradient(circleColors),
|
||||||
|
shape = CircleShape
|
||||||
|
),
|
||||||
|
progress = 1f,
|
||||||
|
strokeWidth = 1.dp,
|
||||||
|
color = MaterialTheme.colors.background // Set background color
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun GallerySelect(
|
fun GallerySelect(
|
||||||
onImageUri: (Uri?) -> Unit = { }
|
onImageUri: (Uri?) -> Unit = { }
|
||||||
) {
|
) {
|
||||||
|
var hasLaunched by remember { mutableStateOf(AtomicBoolean(false)) }
|
||||||
val launcher = rememberLauncherForActivityResult(
|
val launcher = rememberLauncherForActivityResult(
|
||||||
contract = ActivityResultContracts.GetContent(),
|
contract = ActivityResultContracts.GetContent(),
|
||||||
onResult = { uri: Uri? ->
|
onResult = { uri: Uri? ->
|
||||||
onImageUri(uri)
|
onImageUri(uri)
|
||||||
|
hasLaunched.set(false)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LaunchGallery() {
|
fun LaunchGallery() {
|
||||||
SideEffect {
|
SideEffect {
|
||||||
launcher.launch("image/*")
|
if (!hasLaunched.getAndSet(true)) {
|
||||||
|
launcher.launch("image/*")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -178,13 +178,6 @@ fun ChannelScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(modifier = Modifier.fillMaxWidth()) {
|
|
||||||
UploadFromGallery(
|
|
||||||
isUploading = channelScreenModel.isUploadingImage
|
|
||||||
) {
|
|
||||||
channelScreenModel.upload(it, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// LAST ROW
|
// LAST ROW
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(start = 10.dp, end = 10.dp, bottom = 10.dp, top = 5.dp).fillMaxWidth(),
|
modifier = Modifier.padding(start = 10.dp, end = 10.dp, bottom = 10.dp, top = 5.dp).fillMaxWidth(),
|
||||||
@@ -220,6 +213,15 @@ fun ChannelScreen(
|
|||||||
modifier = Modifier.padding(end = 10.dp)
|
modifier = Modifier.padding(end = 10.dp)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
leadingIcon = {
|
||||||
|
UploadFromGallery(
|
||||||
|
isUploading = channelScreenModel.isUploadingImage,
|
||||||
|
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
|
modifier = Modifier.padding(start = 5.dp)
|
||||||
|
) {
|
||||||
|
channelScreenModel.upload(it, context)
|
||||||
|
}
|
||||||
|
},
|
||||||
colors = TextFieldDefaults.textFieldColors(
|
colors = TextFieldDefaults.textFieldColors(
|
||||||
focusedIndicatorColor = Color.Transparent,
|
focusedIndicatorColor = Color.Transparent,
|
||||||
unfocusedIndicatorColor = Color.Transparent
|
unfocusedIndicatorColor = Color.Transparent
|
||||||
|
@@ -156,13 +156,6 @@ fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navContr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(modifier = Modifier.fillMaxWidth()) {
|
|
||||||
UploadFromGallery(
|
|
||||||
isUploading = chatRoomScreenModel.isUploadingImage
|
|
||||||
) {
|
|
||||||
chatRoomScreenModel.upload(it, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// LAST ROW
|
// LAST ROW
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(start = 10.dp, end = 10.dp, bottom = 10.dp, top = 5.dp)
|
modifier = Modifier.padding(start = 10.dp, end = 10.dp, bottom = 10.dp, top = 5.dp)
|
||||||
@@ -193,10 +186,19 @@ fun ChatroomScreen(userId: String?, accountViewModel: AccountViewModel, navContr
|
|||||||
replyTo.value = null
|
replyTo.value = null
|
||||||
feedViewModel.refresh() // Don't wait a full second before updating
|
feedViewModel.refresh() // Don't wait a full second before updating
|
||||||
},
|
},
|
||||||
isActive = chatRoomScreenModel.message.text.isNotBlank() && !chatRoomScreenModel.isUploadingImage,
|
isActive = chatRoomScreenModel.message.text.isNotBlank() && !chatRoomScreenModel.isUploadingImage,
|
||||||
modifier = Modifier.padding(end = 10.dp),
|
modifier = Modifier.padding(end = 10.dp)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
leadingIcon = {
|
||||||
|
UploadFromGallery(
|
||||||
|
isUploading = chatRoomScreenModel.isUploadingImage,
|
||||||
|
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f),
|
||||||
|
modifier = Modifier.padding(start = 5.dp)
|
||||||
|
) {
|
||||||
|
chatRoomScreenModel.upload(it, context)
|
||||||
|
}
|
||||||
|
},
|
||||||
colors = TextFieldDefaults.textFieldColors(
|
colors = TextFieldDefaults.textFieldColors(
|
||||||
focusedIndicatorColor = Color.Transparent,
|
focusedIndicatorColor = Color.Transparent,
|
||||||
unfocusedIndicatorColor = Color.Transparent
|
unfocusedIndicatorColor = Color.Transparent
|
||||||
|
Reference in New Issue
Block a user