mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
@@ -54,6 +54,11 @@ When working with the mobile app:
|
|||||||
- `GlobalScope.launch { }` for fire-and-forget background operations on iOS
|
- `GlobalScope.launch { }` for fire-and-forget background operations on iOS
|
||||||
- Platform-specific logging with `ru.fromchat.core.Logger`
|
- Platform-specific logging with `ru.fromchat.core.Logger`
|
||||||
|
|
||||||
|
## Modifier.conditional
|
||||||
|
- Use `Modifier.conditional` when you need to apply different modifiers based on a condition.
|
||||||
|
- Both `if` and `else` closures are `@Composable` and receive the current Modifier; they return a Modifier to be appended.
|
||||||
|
- Source: `utils/shared/.../Compose.kt` — uses `composed { }`; when true applies `if`, when false applies `else` (default `{ Modifier }`).
|
||||||
|
|
||||||
## C Interop Gotchas
|
## C Interop Gotchas
|
||||||
- NSDictionaryAsKMap (Kotlin's internal NSDictionary wrapper) ≠ NSDictionary (Foundation object)
|
- NSDictionaryAsKMap (Kotlin's internal NSDictionary wrapper) ≠ NSDictionary (Foundation object)
|
||||||
- Security framework expects strict CFDictionaryRef types, not NSDictionary toll-free bridging
|
- Security framework expects strict CFDictionaryRef types, not NSDictionary toll-free bridging
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import androidx.compose.ui.layout.ContentScale
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil3.compose.AsyncImage
|
import coil3.compose.AsyncImage
|
||||||
import coil3.compose.rememberAsyncImagePainter
|
import coil3.compose.rememberAsyncImagePainter
|
||||||
|
import com.pr0gramm3r101.utils.conditional
|
||||||
import com.pr0gramm3r101.utils.crypto.Base64
|
import com.pr0gramm3r101.utils.crypto.Base64
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@@ -64,24 +65,33 @@ fun AttachmentPreview(
|
|||||||
fileAspectRatio: Float? = null,
|
fileAspectRatio: Float? = null,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val isImage = file?.let { isImageFilename(it.name) } ?: pendingFileUri?.let {
|
val isImage = when {
|
||||||
it.contains("image", ignoreCase = true) || it.endsWith(".jpg", true) ||
|
file != null -> isImageFilename(file.name)
|
||||||
it.endsWith(".png", true) || it.endsWith(".jpeg", true) ||
|
pendingFileUri != null -> {
|
||||||
it.endsWith(".gif", true) || it.endsWith(".webp", true)
|
isImageFilename(
|
||||||
} ?: false
|
pendingFileUri
|
||||||
|
.substringAfterLast('/')
|
||||||
|
.substringBefore('?')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
val baseModifier = modifier
|
|
||||||
.then(
|
|
||||||
if (fileAspectRatio != null && fileAspectRatio > 0f) {
|
|
||||||
Modifier.aspectRatio(fileAspectRatio).sizeIn(maxWidth = IMAGE_SIZE, maxHeight = IMAGE_SIZE)
|
|
||||||
} else {
|
|
||||||
Modifier.size(IMAGE_SIZE)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.clip(RoundedCornerShape(IMAGE_RADIUS))
|
|
||||||
.background(MaterialTheme.colorScheme.surfaceVariant)
|
|
||||||
Box(
|
Box(
|
||||||
modifier = baseModifier,
|
modifier = modifier
|
||||||
|
.conditional(
|
||||||
|
fileAspectRatio != null && fileAspectRatio > 0f,
|
||||||
|
`if` = {
|
||||||
|
Modifier
|
||||||
|
.aspectRatio(fileAspectRatio!!)
|
||||||
|
.sizeIn(maxWidth = IMAGE_SIZE, maxHeight = IMAGE_SIZE)
|
||||||
|
},
|
||||||
|
`else` = {
|
||||||
|
Modifier.size(IMAGE_SIZE)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.clip(RoundedCornerShape(IMAGE_RADIUS))
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceVariant),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
when {
|
when {
|
||||||
|
|||||||
Reference in New Issue
Block a user