From 7326d6be93ffd8c197d42347ec2311368505ac52 Mon Sep 17 00:00:00 2001 From: KotlinGeekDev Date: Sat, 5 Oct 2024 17:06:36 +0100 Subject: [PATCH 1/7] Rotation:actually rotate if the device orientation is not locked. --- .../ui/components/ZoomableContentView.kt | 9 ++++--- .../ui/components/util/DeviceUtils.kt | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt index 13ca3741d..457d072b0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt @@ -126,6 +126,7 @@ fun ZoomableContentView( val isLandscapeMode = DeviceUtils.isLandscapeMetric(LocalContext.current) val isFoldableOrLarge = DeviceUtils.windowIsLarge(windowSize = currentWindowSize, isInLandscapeMode = isLandscapeMode) + val isOrientationLocked = DeviceUtils.screenOrientationIsLocked(LocalContext.current) val contentScale = if (isFiniteHeight) { @@ -160,9 +161,9 @@ fun ZoomableContentView( nostrUriCallback = content.uri, onDialog = { dialogOpen = true - // if (!isFoldableOrLarge) { - // DeviceUtils.changeDeviceOrientation(isLandscapeMode, activity) - // } + if (!isFoldableOrLarge && !isOrientationLocked) { + DeviceUtils.changeDeviceOrientation(isLandscapeMode, activity) + } }, accountViewModel = accountViewModel, ) @@ -200,7 +201,7 @@ fun ZoomableContentView( images, onDismiss = { dialogOpen = false - // if (!isFoldableOrLarge) DeviceUtils.changeDeviceOrientation(isLandscapeMode, activity) + if (!isFoldableOrLarge && !isOrientationLocked) DeviceUtils.changeDeviceOrientation(isLandscapeMode, activity) }, accountViewModel, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/util/DeviceUtils.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/util/DeviceUtils.kt index 575058939..3e3f3d11c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/util/DeviceUtils.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/util/DeviceUtils.kt @@ -23,6 +23,8 @@ package com.vitorpamplona.amethyst.ui.components.util import android.app.Activity import android.content.Context import android.content.pm.ActivityInfo +import android.content.pm.PackageManager +import android.provider.Settings import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.window.core.layout.WindowHeightSizeClass @@ -38,6 +40,31 @@ object DeviceUtils { */ fun isLandscapeMetric(context: Context): Boolean = context.resources.displayMetrics.heightPixels < context.resources.displayMetrics.widthPixels + /** + * Checks if the device's orientation is set to locked. + * + * Credits: NewPipe devs + */ + fun screenOrientationIsLocked(context: Context): Boolean { + // 1: Screen orientation changes using accelerometer + // 0: Screen orientation is locked + // if the accelerometer sensor is missing completely, assume locked orientation + return ( + Settings.System.getInt( + context.contentResolver, + Settings.System.ACCELEROMETER_ROTATION, + 0, + ) == 0 || + !context.packageManager.hasSystemFeature(PackageManager.FEATURE_SENSOR_ACCELEROMETER) + ) + } + + /** + * Changes the device's orientation. This works even if the device's orientation + * is set to locked. + * Thus, to prevent unwanted behaviour, + * it's use can be guarded by conditions such as [screenOrientationIsLocked]. + */ fun changeDeviceOrientation( isInLandscape: Boolean, currentActivity: Activity, From baa9ee05626a645d1ea060e78e9231c2624bd666 Mon Sep 17 00:00:00 2001 From: greenart7c3 Date: Mon, 7 Oct 2024 08:50:06 -0300 Subject: [PATCH 2/7] Support for login with hex key when using amber --- .../amethyst/ui/screen/AccountStateViewModel.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt index 8df699705..0c9538c81 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountStateViewModel.kt @@ -109,7 +109,12 @@ class AccountStateViewModel : ViewModel() { is Nip19Bech32.NEmbed -> null is Nip19Bech32.NRelay -> null is Nip19Bech32.NAddress -> null - else -> null + else -> + try { + if (loginWithExternalSigner) Hex.decode(key) else null + } catch (e: Exception) { + null + } } if (loginWithExternalSigner && pubKeyParsed == null) { From 54d52e0b779de1b8a6f403f2339a65e64847d2a5 Mon Sep 17 00:00:00 2001 From: Giovanni Gatti <156141003+geovnn@users.noreply.github.com> Date: Mon, 7 Oct 2024 17:38:05 +0200 Subject: [PATCH 3/7] Prevent clicks outside reaction and zap popups --- .../java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index 45fc0e3a5..facfb3f56 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -89,6 +89,7 @@ import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.window.Popup +import androidx.compose.ui.window.PopupProperties import androidx.core.content.ContextCompat import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData @@ -1329,6 +1330,7 @@ fun ReactionChoicePopup( alignment = Alignment.BottomCenter, offset = IntOffset(0, iconSizePx), onDismissRequest = { onDismiss() }, + properties = PopupProperties(focusable = true), ) { ReactionChoicePopupContent( reactions, @@ -1507,6 +1509,7 @@ fun ZapAmountChoicePopup( alignment = Alignment.BottomCenter, offset = IntOffset(0, yOffset), onDismissRequest = { onDismiss() }, + properties = PopupProperties(focusable = true), ) { FlowRow(horizontalArrangement = Arrangement.Center) { zapAmountChoices.forEach { amountInSats -> From 0551b82bd91b720cfc108def82215132f35c9782 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 7 Oct 2024 17:02:09 -0400 Subject: [PATCH 4/7] Updates AGP and compose, fragment, navigation, benchmarking and firebase libraries. --- .gitignore | 1 + gradle/libs.versions.toml | 14 +++++++------- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 23b285a78..e5303fd75 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ /.idea/ktfmt.xml /.idea/studiobot.xml /.idea/other.xml +/.idea/runConfigurations.xml .DS_Store /build /captures diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1768d5ee9..524165d1f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] accompanistAdaptive = "0.34.0" activityCompose = "1.9.2" -agp = "8.6.1" +agp = "8.7.0" android-compileSdk = "34" android-minSdk = "26" android-targetSdk = "34" @@ -9,16 +9,16 @@ androidKotlinGeohash = "1.0" androidxJunit = "1.2.1" appcompat = "1.7.0" audiowaveform = "1.1.1" -benchmark = "1.3.1" -benchmarkJunit4 = "1.3.1" +benchmark = "1.3.2" +benchmarkJunit4 = "1.3.2" biometricKtx = "1.2.0-alpha05" blurhash = "1.0.0" coil = "2.7.0" -composeBom = "2024.09.02" +composeBom = "2024.09.03" coreKtx = "1.13.1" espressoCore = "3.6.1" -firebaseBom = "33.3.0" -fragmentKtx = "1.8.3" +firebaseBom = "33.4.0" +fragmentKtx = "1.8.4" gms = "4.4.2" jacksonModuleKotlin = "2.17.2" jna = "5.14.0" @@ -35,7 +35,7 @@ lightcompressor = "1.3.2" markdown = "077a2cde64" media3 = "1.4.1" mockk = "1.13.12" -navigationCompose = "2.8.1" +navigationCompose = "2.8.2" okhttp = "5.0.0-alpha.14" runner = "1.6.2" rfc3986 = "0.1.0" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 859969a3f..358e7f41b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Jan 04 09:23:50 EST 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME From a7343d5b5477ae16dd38f5c49cbfe042b8244b9d Mon Sep 17 00:00:00 2001 From: Giovanni Gatti <156141003+geovnn@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:06:29 +0200 Subject: [PATCH 5/7] Add animation to zap and reaction popups --- .../amethyst/ui/note/ReactionsRow.kt | 179 ++++++++++++------ 1 file changed, 119 insertions(+), 60 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt index facfb3f56..bb7bbfe20 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/ReactionsRow.kt @@ -24,8 +24,10 @@ import android.content.Context import android.content.Intent import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.ContentTransform import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.MutableTransitionState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn @@ -147,6 +149,7 @@ import kotlinx.collections.immutable.persistentSetOf import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableSet import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlin.math.roundToInt @@ -1326,24 +1329,52 @@ fun ReactionChoicePopup( .collectAsStateWithLifecycle() val toRemove = remember { baseNote.reactedBy(accountViewModel.userProfile()).toImmutableSet() } + // Define animation specs + val animationDuration = 250 + val fadeAnimationSpec = tween(durationMillis = animationDuration) + + // Prevent multiple calls to onDismiss() + var dismissed by remember { mutableStateOf(false) } + + val visibilityState = remember { MutableTransitionState(false).apply { targetState = true } } + LaunchedEffect(visibilityState.targetState) { + if (!visibilityState.targetState && !dismissed) { + delay(animationDuration.toLong()) + dismissed = true + onDismiss() + } + } + Popup( alignment = Alignment.BottomCenter, offset = IntOffset(0, iconSizePx), - onDismissRequest = { onDismiss() }, + onDismissRequest = { visibilityState.targetState = false }, properties = PopupProperties(focusable = true), ) { - ReactionChoicePopupContent( - reactions, - toRemove = toRemove, - onClick = { reactionType -> - accountViewModel.reactToOrDelete( - baseNote, - reactionType, - ) - onDismiss() - }, - onChangeAmount, - ) + AnimatedVisibility( + visibleState = visibilityState, + enter = + slideInVertically( + initialOffsetY = { it / 2 }, + ) + fadeIn(animationSpec = fadeAnimationSpec), + exit = + slideOutVertically( + targetOffsetY = { it / 2 }, + ) + fadeOut(animationSpec = fadeAnimationSpec), + ) { + ReactionChoicePopupContent( + reactions, + toRemove = toRemove, + onClick = { reactionType -> + accountViewModel.reactToOrDelete( + baseNote, + reactionType, + ) + visibilityState.targetState = false + }, + onChangeAmount, + ) + } } } @@ -1505,59 +1536,87 @@ fun ZapAmountChoicePopup( val yOffset = with(LocalDensity.current) { -popupYOffset.toPx().toInt() } + // Define animation specs + val animationDuration = 250 + val fadeAnimationSpec = tween(durationMillis = animationDuration) + + // Prevent multiple calls to onDismiss() + var dismissed by remember { mutableStateOf(false) } + + val visibilityState = remember { MutableTransitionState(false).apply { targetState = true } } + LaunchedEffect(visibilityState.targetState) { + if (!visibilityState.targetState && !dismissed) { + delay(animationDuration.toLong()) + dismissed = true + onDismiss() + } + } + Popup( alignment = Alignment.BottomCenter, offset = IntOffset(0, yOffset), - onDismissRequest = { onDismiss() }, + onDismissRequest = { visibilityState.targetState = false }, properties = PopupProperties(focusable = true), ) { - FlowRow(horizontalArrangement = Arrangement.Center) { - zapAmountChoices.forEach { amountInSats -> - Button( - modifier = Modifier.padding(horizontal = 3.dp), - onClick = { - accountViewModel.zap( - baseNote, - amountInSats * 1000, - null, - zapMessage, - context, - true, - onError, - onProgress, - onPayViaIntent, - ) - onDismiss() - }, - shape = ButtonBorder, - colors = - ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary, - ), - ) { - Text( - "⚡ ${showAmount(amountInSats.toBigDecimal().setScale(1))}", - color = Color.White, - textAlign = TextAlign.Center, - modifier = - Modifier.combinedClickable( - onClick = { - accountViewModel.zap( - baseNote, - amountInSats * 1000, - null, - zapMessage, - context, - true, - onError, - onProgress, - onPayViaIntent, - ) - onDismiss() - }, - onLongClick = { onChangeAmount() }, + AnimatedVisibility( + visibleState = visibilityState, + enter = + slideInVertically( + initialOffsetY = { it / 2 }, + ) + fadeIn(animationSpec = fadeAnimationSpec), + exit = + slideOutVertically( + targetOffsetY = { it / 2 }, + ) + fadeOut(animationSpec = fadeAnimationSpec), + ) { + FlowRow(horizontalArrangement = Arrangement.Center) { + zapAmountChoices.forEach { amountInSats -> + Button( + modifier = Modifier.padding(horizontal = 3.dp), + onClick = { + accountViewModel.zap( + baseNote, + amountInSats * 1000, + null, + zapMessage, + context, + true, + onError, + onProgress, + onPayViaIntent, + ) + visibilityState.targetState = false + }, + shape = ButtonBorder, + colors = + ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary, ), - ) + ) { + Text( + "⚡ ${showAmount(amountInSats.toBigDecimal().setScale(1))}", + color = Color.White, + textAlign = TextAlign.Center, + modifier = + Modifier.combinedClickable( + onClick = { + accountViewModel.zap( + baseNote, + amountInSats * 1000, + null, + zapMessage, + context, + true, + onError, + onProgress, + onPayViaIntent, + ) + visibilityState.targetState = false + }, + onLongClick = { onChangeAmount() }, + ), + ) + } } } } From 9340c440f5f45f68484dc9b6e4d82a27260d2e11 Mon Sep 17 00:00:00 2001 From: Giovanni Gatti <156141003+geovnn@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:54:42 +0200 Subject: [PATCH 6/7] Add animation to FABs --- .../loggedIn/chatrooms/ChannelFabColumn.kt | 96 ++++++++------ .../screen/loggedIn/video/NewImageButton.kt | 118 +++++++++++------- 2 files changed, 133 insertions(+), 81 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chatrooms/ChannelFabColumn.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chatrooms/ChannelFabColumn.kt index 5cdc10772..6f0934618 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chatrooms/ChannelFabColumn.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chatrooms/ChannelFabColumn.kt @@ -20,6 +20,12 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.chatrooms +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.height @@ -38,6 +44,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.R @@ -76,46 +83,56 @@ fun ChannelFabColumn( } Column { - if (isOpen) { - FloatingActionButton( - onClick = { - wantsToSendNewMessage = true - isOpen = false - }, - modifier = Size55Modifier, - shape = CircleShape, - containerColor = MaterialTheme.colorScheme.primary, - ) { - Text( - text = stringRes(R.string.messages_new_message), - color = Color.White, - textAlign = TextAlign.Center, - fontSize = Font12SP, - ) + AnimatedVisibility( + visible = isOpen, + enter = slideInVertically(initialOffsetY = { it / 2 }) + fadeIn(), + exit = slideOutVertically(targetOffsetY = { it / 2 }) + fadeOut(), + ) { + Column { + FloatingActionButton( + onClick = { + wantsToSendNewMessage = true + isOpen = false + }, + modifier = Size55Modifier, + shape = CircleShape, + containerColor = MaterialTheme.colorScheme.primary, + ) { + Text( + text = stringRes(R.string.messages_new_message), + color = Color.White, + textAlign = TextAlign.Center, + fontSize = Font12SP, + ) + } + + Spacer(modifier = Modifier.height(20.dp)) + + FloatingActionButton( + onClick = { + wantsToCreateChannel = true + isOpen = false + }, + modifier = Size55Modifier, + shape = CircleShape, + containerColor = MaterialTheme.colorScheme.primary, + ) { + Text( + text = stringRes(R.string.messages_create_public_chat), + color = Color.White, + textAlign = TextAlign.Center, + fontSize = Font12SP, + ) + } + + Spacer(modifier = Modifier.height(20.dp)) } - - Spacer(modifier = Modifier.height(20.dp)) - - FloatingActionButton( - onClick = { - wantsToCreateChannel = true - isOpen = false - }, - modifier = Size55Modifier, - shape = CircleShape, - containerColor = MaterialTheme.colorScheme.primary, - ) { - Text( - text = stringRes(R.string.messages_create_public_chat), - color = Color.White, - textAlign = TextAlign.Center, - fontSize = Font12SP, - ) - } - - Spacer(modifier = Modifier.height(20.dp)) } + val rotationDegree by animateFloatAsState( + targetValue = if (isOpen) 45f else 0f, + ) + FloatingActionButton( onClick = { isOpen = !isOpen }, modifier = Size55Modifier, @@ -125,7 +142,10 @@ fun ChannelFabColumn( Icon( imageVector = Icons.Outlined.Add, contentDescription = stringRes(R.string.messages_create_public_private_chat_description), - modifier = Modifier.size(26.dp), + modifier = + Modifier.size(26.dp).graphicsLayer { + rotationZ = rotationDegree + }, tint = Color.White, ) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/NewImageButton.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/NewImageButton.kt index 60110f49a..7d6e960c3 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/NewImageButton.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/NewImageButton.kt @@ -25,7 +25,12 @@ import android.net.Uri import android.os.Build import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -36,6 +41,7 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.AddPhotoAlternate import androidx.compose.material.icons.filled.CameraAlt +import androidx.compose.material.icons.outlined.Close import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon @@ -186,44 +192,51 @@ fun NewImageButton( ShowProgress(postViewModel) } else { Column { - if (isOpen) { - FloatingActionButton( - onClick = { - wantsToPostFromCamera = true - isOpen = false - }, - modifier = Size55Modifier, - shape = CircleShape, - containerColor = MaterialTheme.colorScheme.primary, - ) { - Icon( - imageVector = Icons.Default.CameraAlt, - contentDescription = stringRes(id = R.string.upload_image), - modifier = Modifier.size(26.dp), - tint = Color.White, - ) +// if (isOpen) { + AnimatedVisibility( + visible = isOpen, + enter = slideInVertically(initialOffsetY = { it / 2 }) + fadeIn(), + exit = slideOutVertically(targetOffsetY = { it / 2 }) + fadeOut(), + ) { + Column { + FloatingActionButton( + onClick = { + wantsToPostFromCamera = true + isOpen = false + }, + modifier = Size55Modifier, + shape = CircleShape, + containerColor = MaterialTheme.colorScheme.primary, + ) { + Icon( + imageVector = Icons.Default.CameraAlt, + contentDescription = stringRes(id = R.string.upload_image), + modifier = Modifier.size(26.dp), + tint = Color.White, + ) + } + + Spacer(modifier = Modifier.height(20.dp)) + + FloatingActionButton( + onClick = { + wantsToPostFromGallery = true + isOpen = false + }, + modifier = Size55Modifier, + shape = CircleShape, + containerColor = MaterialTheme.colorScheme.primary, + ) { + Icon( + imageVector = Icons.Default.AddPhotoAlternate, + contentDescription = stringRes(id = R.string.upload_image), + modifier = Modifier.size(26.dp), + tint = Color.White, + ) + } + + Spacer(modifier = Modifier.height(20.dp)) } - - Spacer(modifier = Modifier.height(20.dp)) - - FloatingActionButton( - onClick = { - wantsToPostFromGallery = true - isOpen = false - }, - modifier = Size55Modifier, - shape = CircleShape, - containerColor = MaterialTheme.colorScheme.primary, - ) { - Icon( - imageVector = Icons.Default.AddPhotoAlternate, - contentDescription = stringRes(id = R.string.upload_image), - modifier = Modifier.size(26.dp), - tint = Color.White, - ) - } - - Spacer(modifier = Modifier.height(20.dp)) } FloatingActionButton( @@ -234,12 +247,31 @@ fun NewImageButton( shape = CircleShape, containerColor = MaterialTheme.colorScheme.primary, ) { - Icon( - painter = painterResource(R.drawable.ic_compose), - contentDescription = stringRes(id = R.string.new_short), - modifier = Modifier.size(26.dp), - tint = Color.White, - ) + AnimatedVisibility( + visible = isOpen, + enter = fadeIn(), + exit = fadeOut(), + ) { + Icon( + imageVector = Icons.Outlined.Close, + contentDescription = stringRes(id = R.string.new_short), + modifier = Modifier.size(26.dp), + tint = Color.White, + ) + } + + AnimatedVisibility( + visible = !isOpen, + enter = fadeIn(), + exit = fadeOut(), + ) { + Icon( + painter = painterResource(R.drawable.ic_compose), + contentDescription = stringRes(id = R.string.new_short), + modifier = Modifier.size(26.dp), + tint = Color.White, + ) + } } } } From a3166f4ff3341e097271570ad68ef9bd4429e144 Mon Sep 17 00:00:00 2001 From: Giovanni Gatti <156141003+geovnn@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:13:47 +0200 Subject: [PATCH 7/7] Add animation to notification chart --- .../loggedIn/notifications/NotificationSummaryView.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/NotificationSummaryView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/NotificationSummaryView.kt index 9e434a3c0..7e16002b2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/NotificationSummaryView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/notifications/NotificationSummaryView.kt @@ -20,6 +20,11 @@ */ package com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding @@ -73,7 +78,11 @@ fun SummaryBar(state: NotificationSummaryState) { UserReactionsRow(state) { showChart = !showChart } - if (showChart) { + AnimatedVisibility( + visible = showChart, + enter = slideInVertically() + expandVertically(), + exit = slideOutVertically() + shrinkVertically(), + ) { val lineChartCount = lineChart( lines =