mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-03-17 21:31:57 +01:00
Merge branch 'main' into refactor-media-compressor
This commit is contained in:
commit
ce0c7c842d
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@
|
||||
/.idea/ktfmt.xml
|
||||
/.idea/studiobot.xml
|
||||
/.idea/other.xml
|
||||
/.idea/runConfigurations.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
@ -89,6 +91,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
|
||||
@ -146,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
|
||||
|
||||
@ -1325,23 +1329,52 @@ fun ReactionChoicePopup(
|
||||
.collectAsStateWithLifecycle()
|
||||
val toRemove = remember { baseNote.reactedBy(accountViewModel.userProfile()).toImmutableSet() }
|
||||
|
||||
// Define animation specs
|
||||
val animationDuration = 250
|
||||
val fadeAnimationSpec = tween<Float>(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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1503,58 +1536,87 @@ fun ZapAmountChoicePopup(
|
||||
|
||||
val yOffset = with(LocalDensity.current) { -popupYOffset.toPx().toInt() }
|
||||
|
||||
// Define animation specs
|
||||
val animationDuration = 250
|
||||
val fadeAnimationSpec = tween<Float>(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() },
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
@ -36,7 +36,7 @@ markdown = "077a2cde64"
|
||||
media3 = "1.4.1"
|
||||
mockk = "1.13.12"
|
||||
kotlinx-coroutines-test = "1.9.0-RC.2"
|
||||
navigationCompose = "2.8.1"
|
||||
navigationCompose = "2.8.2"
|
||||
okhttp = "5.0.0-alpha.14"
|
||||
runner = "1.6.2"
|
||||
rfc3986 = "0.1.0"
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user