diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/AsyncImageProxy.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/AsyncImageProxy.kt
index 456e7e327..8e4dbcd33 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/AsyncImageProxy.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/AsyncImageProxy.kt
@@ -1,11 +1,6 @@
package com.vitorpamplona.amethyst.ui.components
-import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
-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.graphics.ColorFilter
@@ -31,50 +26,6 @@ data class ResizeImage(val url: String?, val size: Dp) {
}
}
-@Composable fun AsyncUserImageProxy(
- pubkeyHex: String,
- model: ResizeImage,
- contentDescription: String?,
- modifier: Modifier = Modifier,
- alignment: Alignment = Alignment.Center,
- contentScale: ContentScale = ContentScale.Fit,
- alpha: Float = DefaultAlpha,
- colorFilter: ColorFilter? = null,
- filterQuality: FilterQuality = DrawScope.DefaultFilterQuality
-) {
- var loading by remember { mutableStateOf(false) }
- var error by remember { mutableStateOf(false) }
-
- Box() {
- AsyncImage(
- model = model.proxyUrl(),
- contentDescription = contentDescription,
- modifier = modifier,
- onLoading = { loading = true },
- onSuccess = { loading = false; error = false },
- onError = { loading = false; error = true },
- alignment = alignment,
- contentScale = contentScale,
- alpha = alpha,
- colorFilter = colorFilter,
- filterQuality = filterQuality
- )
-
- if (model.url == null || loading || error) {
- RoboHashAsyncImage(
- message = pubkeyHex,
- contentDescription = contentDescription,
- modifier = modifier,
- alignment = alignment,
- contentScale = contentScale,
- alpha = alpha,
- colorFilter = colorFilter,
- filterQuality = filterQuality
- )
- }
- }
-}
-
@Composable
fun AsyncImageProxy(
model: ResizeImage,
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RoboHashAsyncImage.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/Robohash.kt
similarity index 98%
rename from app/src/main/java/com/vitorpamplona/amethyst/ui/components/RoboHashAsyncImage.kt
rename to app/src/main/java/com/vitorpamplona/amethyst/ui/components/Robohash.kt
index 4e2dd9a11..e3f9a2f97 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RoboHashAsyncImage.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/Robohash.kt
@@ -1,335 +1,299 @@
-package com.vitorpamplona.amethyst.ui.components
-
-import android.content.Context
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.ColorFilter
-import androidx.compose.ui.graphics.DefaultAlpha
-import androidx.compose.ui.graphics.FilterQuality
-import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.toArgb
-import androidx.compose.ui.layout.ContentScale
-import androidx.compose.ui.platform.LocalContext
-import coil.compose.AsyncImage
-import coil.compose.AsyncImagePainter
-import coil.request.ImageRequest
-import java.nio.ByteBuffer
-import java.security.MessageDigest
-
-private fun toHex(color: Color): String {
- val argb = color.toArgb()
- val rgb = argb and 0x00FFFFFF // Mask out the alpha channel
- return String.format("#%06X", rgb)
-}
-
-private val sha256: MessageDigest = MessageDigest.getInstance("SHA-256")
-
-private fun byteMod(byte: Byte, modulo: Int): Int {
- val ub = byte.toUByte().toInt()
- return ub % modulo
-}
-
-private fun bytesToRGB(b1: Byte, b2: Byte, b3: Byte): Color {
- return Color(b1.toUByte().toInt(), b2.toUByte().toInt(), b3.toUByte().toInt())
-}
-
-fun generateRoboHashSvg(msg: String): String {
- val hash = sha256.digest(msg.toByteArray())
- val hashHex = hash.joinToString(separator = "") { b -> "%02x".format(b) }
- val bgColor1 = bytesToRGB(hash[0], hash[1], hash[2])
- val bgColor2 = bytesToRGB(hash[3], hash[4], hash[5])
- val fgColor = bytesToRGB(hash[6], hash[7], hash[8])
- val bgIndex = byteMod(hash[9], 8)
- val bodyIndex = byteMod(hash[10], 10)
- val faceIndex = byteMod(hash[11], 10)
- val eyesIndex = byteMod(hash[12], 10)
- val mouthIndex = byteMod(hash[13], 10)
- val accIndex = byteMod(hash[14], 10)
- val background = backgrounds[bgIndex]
- val body = bodies[bodyIndex]
- val face = faces[faceIndex]
- val eye = eyes[eyesIndex]
- val mouth = mouths[mouthIndex]
- val accessory = accessories[accIndex]
-
- return """
-
- """.trimIndent()
-}
-
-fun roboHashImageRequest(context: Context, message: String): ImageRequest {
- return ImageRequest
- .Builder(context)
- .data(
- ByteBuffer.wrap(
- generateRoboHashSvg(message).toByteArray()
- )
- )
- .build()
-}
-
-@Composable
-fun RoboHashAsyncImage(
- message: String,
- modifier: Modifier = Modifier,
- contentDescription: String? = null,
- transform: (AsyncImagePainter.State) -> AsyncImagePainter.State = AsyncImagePainter.DefaultTransform,
- onState: ((AsyncImagePainter.State) -> Unit)? = null,
- alignment: Alignment = Alignment.Center,
- contentScale: ContentScale = ContentScale.Fit,
- alpha: Float = DefaultAlpha,
- colorFilter: ColorFilter? = null,
- filterQuality: FilterQuality = DrawScope.DefaultFilterQuality
-) {
- AsyncImage(
- model = roboHashImageRequest(LocalContext.current, message),
- contentDescription = contentDescription,
- modifier = modifier,
- transform = transform,
- onState = onState,
- alignment = alignment,
- contentScale = contentScale,
- alpha = alpha,
- colorFilter = colorFilter,
- filterQuality = filterQuality
- )
-}
-
-private data class Part(val style: String, val paths: String)
-
-private val backgrounds: List = listOf(
- """""",
- """""",
- """""",
- """""",
- """""",
- """""",
- """""",
- """"""
-)
-
-private val accessories: List = listOf(
- Part(
- """.cls-00-2{fill:none;}.cls-00-2,.cls-00-3,.cls-00-4{stroke:#000;}.cls-00-2,.cls-00-3{stroke-linecap:round;stroke-linejoin:round;}.cls-00-3{fill-opacity:0.4;stroke-width:0.75px;}.cls-00-4{fill-opacity:0.2;stroke-miterlimit:10;stroke-width:0.5px;}""",
- """"""
- ),
- Part(
- """.cls-01-2{fill:#fff;fill-opacity:0.2;}.cls-01-3,.cls-01-4{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-01-4{stroke-width:0.75px;}""",
- """"""
- ),
- Part(
- """.cls-02-2{fill:#be1e2d;}.cls-02-11,.cls-02-2,.cls-02-5,.cls-02-6,.cls-02-7,.cls-02-9{stroke:#000;}.cls-02-11,.cls-02-2,.cls-02-5,.cls-02-9{stroke-miterlimit:10;}.cls-02-3{fill:#561317;}.cls-02-4{fill:#ed293b;}.cls-02-11,.cls-02-5,.cls-02-7{fill:none;}.cls-02-5,.cls-02-6{stroke-width:0.75px;}.cls-02-6{fill:#fff;}.cls-02-6,.cls-02-8{fill-opacity:0.2;}.cls-02-6,.cls-02-7{stroke-linecap:round;stroke-linejoin:round;}.cls-02-9{fill:#e6e7e8;}.cls-02-10{fill:#d0d2d3;}""",
- """"""
- ),
- Part(
- """.cls-03-2,.cls-03-3,.cls-03-8{fill:#fff;}.cls-03-2,.cls-03-3,.cls-03-7{fill-opacity:0.2;}.cls-03-2,.cls-03-4,.cls-03-5{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-03-2{stroke-width:0.75px;}.cls-03-4{fill:none;}.cls-03-5{fill:#ec1c24;}.cls-03-6{fill-opacity:0.1;}.cls-03-8{fill-opacity:0.4;}""",
- """"""
- ),
- Part(
- """.cls-04-2,.cls-04-3{fill:none;stroke-linecap:round;stroke-linejoin:round;}.cls-04-2,.cls-04-3,.cls-04-5{stroke:#000;}.cls-04-3,.cls-04-5{stroke-width:0.75px;}.cls-04-4,.cls-04-6{fill:#fff;}.cls-04-4{fill-opacity:0.4;}.cls-04-5{fill:#ec1c24;stroke-miterlimit:10;}.cls-04-6,.cls-04-7{fill-opacity:0.2;}""",
- """"""
- ),
- Part(
- """.cls-05-2{fill:#fff;fill-opacity:0.4;}.cls-05-2,.cls-05-3{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-05-3{fill:none;stroke-width:0.75px;}""",
- """"""
- ),
- Part(
- """.cls-06-2,.cls-06-4{fill-opacity:0.2;}.cls-06-3,.cls-06-6{fill:none;}.cls-06-3,.cls-06-5,.cls-06-6{stroke:#000;}.cls-06-3,.cls-06-5{stroke-miterlimit:10;}.cls-06-4{fill:#fff;}.cls-06-5{fill:#ec1c24;stroke-width:0.75px;}.cls-06-6{stroke-linecap:round;stroke-linejoin:round;}""",
- """"""
- ),
- Part(
- """.cls-07-10,.cls-07-2,.cls-07-4,.cls-07-8,.cls-07-9{fill:none;}.cls-07-10,.cls-07-2,.cls-07-3,.cls-07-4,.cls-07-5,.cls-07-6,.cls-07-8,.cls-07-9{stroke:#000;}.cls-07-2,.cls-07-3,.cls-07-4,.cls-07-5,.cls-07-6,.cls-07-8{stroke-linecap:round;}.cls-07-2,.cls-07-3,.cls-07-4,.cls-07-5,.cls-07-6,.cls-07-8,.cls-07-9{stroke-linejoin:round;}.cls-07-3,.cls-07-5{fill:#fff;}.cls-07-3,.cls-07-5,.cls-07-6,.cls-07-7{fill-opacity:0.2;}.cls-07-3,.cls-07-4{stroke-width:0.75px;}.cls-07-10,.cls-07-8,.cls-07-9{stroke-width:1.5px;}.cls-07-10{stroke-miterlimit:10;}""",
- """"""
- ),
- Part(
- """.cls-08-2{fill:none;}.cls-08-2,.cls-08-3,.cls-08-5,.cls-08-6,.cls-08-7{stroke:#000;stroke-miterlimit:10;}.cls-08-3,.cls-08-4{fill:#fff;}.cls-08-3,.cls-08-4,.cls-08-8{fill-opacity:0.2;}.cls-08-5{fill:#716558;}.cls-08-6{fill:#9a8479;}.cls-08-7{fill:#c1b49a;}""",
- """"""
- ),
- Part(
- """.cls-09-2{fill:none;}.cls-09-2,.cls-09-4{stroke:#000;stroke-miterlimit:10;}.cls-09-3,.cls-09-4{fill:#fff;}.cls-09-3{fill-opacity:0.2;}.cls-09-5{fill:#d0d2d3;}.cls-09-6{fill-opacity:0.4;}""",
- """"""
- )
-)
-
-private val bodies: List = listOf(
- Part(
- """.cls-10-2{fill:#fff;fill-opacity:0.4;}.cls-10-3,.cls-10-5,.cls-10-7{fill:none;}.cls-10-3,.cls-10-4,.cls-10-5,.cls-10-6,.cls-10-7,.cls-10-8{stroke:#000;stroke-miterlimit:10;}.cls-10-3{stroke-width:1.2px;}.cls-10-4,.cls-10-6,.cls-10-9{fill-opacity:0.2;}.cls-10-5{stroke-width:1.25px;}.cls-10-6{stroke-width:0.75px;}.cls-10-8{fill:#6d6e70;}""",
- """"""
- ),
- Part(
- """.cls-11-2{fill:#fff;}.cls-11-2,.cls-11-6{fill-opacity:0.2;}.cls-11-3{fill:none;}.cls-11-3,.cls-11-4{stroke:#000;stroke-miterlimit:10;}.cls-11-4{fill:#6d6e70;}.cls-11-5{opacity:0.2;}""",
- """"""
- ),
- Part(
- """.cls-12-2{fill:#fff;fill-opacity:0.4;}.cls-12-3,.cls-12-7{fill:none;}.cls-12-3,.cls-12-5,.cls-12-6,.cls-12-7{stroke:#000;}.cls-12-3,.cls-12-5,.cls-12-6{stroke-miterlimit:10;}.cls-12-4,.cls-12-6{fill-opacity:0.2;}.cls-12-5{fill:#6d6e70;}.cls-12-7{stroke-linecap:round;stroke-linejoin:round;}""",
- """"""
- ),
- Part(
- """.cls-13-2{fill:none;}.cls-13-2,.cls-13-5{stroke:#000;stroke-miterlimit:10;}.cls-13-3{fill:#fff;fill-opacity:0.4;}.cls-13-4{fill-opacity:0.2;}.cls-13-5{fill:#6d6e70;}""",
- """"""
- ),
- Part(
- """.cls-14-2{fill:none;}.cls-14-2,.cls-14-4{stroke:#000;stroke-miterlimit:10;}.cls-14-3,.cls-14-6{fill-opacity:0.2;}.cls-14-4{fill:#6d6e70;}.cls-14-5,.cls-14-6{fill:#fff;}.cls-14-5{fill-opacity:0.4;}""",
- """"""
- ),
- Part(
- """.cls-15-2{fill:#fff;}.cls-15-2,.cls-15-4{fill-opacity:0.2;}.cls-15-2,.cls-15-3,.cls-15-5{stroke:#000;stroke-miterlimit:10;}.cls-15-3{fill:none;}.cls-15-5{fill:#6d6e70;}""",
- """"""
- ),
- Part(
- """.cls-16-2,.cls-16-5{fill:none;}.cls-16-2,.cls-16-5,.cls-16-6,.cls-16-7,.cls-16-8,.cls-16-9{stroke:#000;}.cls-16-2{stroke-linecap:round;stroke-linejoin:round;}.cls-16-3,.cls-16-6,.cls-16-7{fill-opacity:0.2;}.cls-16-4,.cls-16-6{fill:#fff;}.cls-16-4{fill-opacity:0.4;}.cls-16-5,.cls-16-6,.cls-16-7,.cls-16-8,.cls-16-9{stroke-miterlimit:10;}.cls-16-8{fill:#f9ec31;}.cls-16-9{fill:#6d6e70;}""",
- """"""
- ),
- Part(
- """.cls-17-2{fill:#020202;}.cls-17-2,.cls-17-4,.cls-17-6,.cls-17-7{fill-opacity:0.4;}.cls-17-3{fill-opacity:0.2;}.cls-17-4,.cls-17-6{fill:#fff;}.cls-17-4,.cls-17-5,.cls-17-8{stroke:#000;stroke-miterlimit:10;}.cls-17-5{fill:none;}.cls-17-8{fill:#6d6e70;}""",
- """"""
- ),
- Part(
- """.cls-fill-2,.cls-18-3,.cls-18-5,.cls-18-6{stroke:#000;stroke-miterlimit:10;}.cls-18-3{fill:none;}.cls-18-4{fill:#fff;}.cls-18-4,.cls-18-5{fill-opacity:0.4;}.cls-18-6{fill:#6d6e70;}.cls-18-7{opacity:0.2;}.cls-18-8{fill-opacity:0.2;}""",
- """"""
- ),
- Part(
- """.cls-19-2{fill-opacity:0.6;}.cls-19-11,.cls-19-13,.cls-19-14,.cls-19-2,.cls-19-3,.cls-19-4,.cls-19-6,.cls-19-8{stroke:#000;}.cls-19-11,.cls-19-13,.cls-19-2,.cls-19-4,.cls-19-6,.cls-19-8{stroke-miterlimit:10;}.cls-19-11,.cls-19-14,.cls-19-3,.cls-19-8{fill:none;}.cls-19-14,.cls-19-3{stroke-linecap:round;stroke-linejoin:round;}.cls-19-10,.cls-19-12,.cls-19-4,.cls-19-5{fill:#fff;}.cls-19-12,.cls-19-4{fill-opacity:0.2;}.cls-19-4{stroke-opacity:0;}.cls-19-5{fill-opacity:0.1;}.cls-19-6{fill:#6d6e70;}.cls-19-7{fill:#58595b;}.cls-19-13,.cls-19-9{fill-opacity:0.4;}.cls-19-10{fill-opacity:0.5;}.cls-19-11,.cls-19-14{stroke-width:0.75px;}""",
- """"""
- )
-)
-
-private val eyes: List = listOf(
- Part(
- """.cls-20-2{fill-opacity:0.4;}.cls-20-2,.cls-20-3{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-20-3{fill:#461917;stroke-width:0.5px;}""",
- """"""
- ),
- Part(
- """.cls-21-2{fill-opacity:0.2;}.cls-21-2,.cls-21-3,.cls-21-4,.cls-21-5{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-21-2,.cls-21-4,.cls-21-5{stroke-width:0.5px;}.cls-21-3,.cls-21-4{fill-opacity:0.4;}.cls-21-5{fill:#461917;}.cls-21-6{fill:#faaf40;}""",
- """"""
- ),
- Part(
- """.cls-22-2{opacity:0.4;}.cls-22-3{fill:#461917;}.cls-22-3,.cls-22-4,.cls-22-5{stroke:#000;}.cls-22-3,.cls-22-5{stroke-linecap:round;stroke-linejoin:round;}.cls-22-3,.cls-22-4{stroke-width:0.5px;}.cls-22-4{fill:#ec1c24;stroke-miterlimit:10;}.cls-22-5{fill:none;stroke-width:0.75px;}""",
- """"""
- ),
- Part(
- """.cls-23-2,.cls-23-3{fill:#fff;}.cls-23-2{fill-opacity:0.4;}.cls-23-3{fill-opacity:0.2;}.cls-23-3,.cls-23-4,.cls-23-5{stroke:#000;stroke-miterlimit:10;}.cls-23-4{fill:none;}.cls-23-4,.cls-23-5{stroke-width:0.75px;}.cls-23-5{fill:red;}""",
- """"""
- ),
- Part(
- """.cls-24-2{fill-opacity:0.4;stroke-miterlimit:10;}.cls-24-2,.cls-24-3,.cls-24-5{stroke:#000;}.cls-24-2,.cls-24-5{stroke-width:0.75px;}.cls-24-3,.cls-24-5{fill:#461917;stroke-linecap:round;stroke-linejoin:round;}.cls-24-3{stroke-width:0.5px;}.cls-24-4{fill:#ec1c24;}""",
- """"""
- ),
- Part(
- """.cls-25-2{fill-opacity:0.55;stroke-miterlimit:10;stroke-width:0.75px;}.cls-25-2,.cls-25-3{stroke:#000;}.cls-25-3{fill:#461917;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5px;}.cls-25-4{fill:#ec1c24;}""",
- """"""
- ),
- Part(
- """.cls-26-2{fill-opacity:0.6;}.cls-26-2,.cls-26-3,.cls-26-4,.cls-26-5,.cls-26-6{stroke:#000;}.cls-26-2,.cls-26-3,.cls-26-4,.cls-26-6{stroke-linecap:round;stroke-linejoin:round;}.cls-26-3{fill:#461917;}.cls-26-3,.cls-26-4,.cls-26-5{stroke-width:0.5px;}.cls-26-4,.cls-26-5{fill:#f9ec31;}.cls-26-5{stroke-miterlimit:10;}.cls-26-6{fill:none;}""",
- """"""
- ),
- Part(
- """.cls-27-2{fill-opacity:0.4;stroke-miterlimit:10;}.cls-27-2,.cls-27-3,.cls-27-4{stroke:#000;}.cls-27-3,.cls-27-4{fill:#461917;stroke-linecap:round;stroke-linejoin:round;}.cls-27-3{stroke-width:0.5px;}.cls-27-4{stroke-width:0.75px;}""",
- """"""
- ),
- Part(
- """.cls-28-2{fill:none;}.cls-28-2,.cls-28-3,.cls-28-4,.cls-28-6{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-28-2,.cls-28-4,.cls-28-6{stroke-width:0.75px;}.cls-28-3{fill:#461917;stroke-width:0.5px;}.cls-28-4{fill-opacity:0.4;}.cls-28-5{fill:#fff100;}.cls-28-6{fill:#fff;fill-opacity:0.2;}""",
- """"""
- ),
- Part(
- """.cls-29-2{fill:#fff;}.cls-29-2,.cls-29-4{fill-opacity:0.4;}.cls-29-3{fill:none;}.cls-29-3,.cls-29-4{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-29-4{stroke-width:0.75px;}""",
- """"""
- )
-)
-
-private val faces: List = listOf(
- Part(
- """.cls-30-2{fill:#fff;fill-opacity:0.4;}.cls-30-3,.cls-30-4{fill:none;}.cls-30-3,.cls-30-4,.cls-30-6{stroke:#000;}.cls-30-3,.cls-30-6{stroke-linecap:round;stroke-linejoin:round;}.cls-30-4{stroke-miterlimit:10;}.cls-30-5,.cls-30-6{fill-opacity:0.2;}.cls-30-6{stroke-width:0.75px;}""",
- """"""
- ),
- Part(
- """.cls-31-2,.cls-31-4{fill-opacity:0.2;}.cls-31-3{fill:none;}.cls-31-3,.cls-31-4{stroke:#000;stroke-miterlimit:10;}.cls-31-4,.cls-31-5{fill:#fff;}.cls-31-4{stroke-width:0.75px;}.cls-31-5{fill-opacity:0.4;}""",
- """"""
- ),
- Part(
- """.cls-32-2{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-32-3{fill-opacity:0.2;}.cls-32-4{fill:#fff;fill-opacity:0.4;}""",
- """"""
- ),
- Part(
- """.cls-33-2{fill-opacity:0.2;}.cls-33-3{fill:#fff;fill-opacity:0.4;}.cls-33-4{fill:none;stroke:#000;stroke-miterlimit:10;}""",
- """"""
- ),
- Part(
- """.cls-34-2,.cls-34-3{fill:#fff;}.cls-34-2{fill-opacity:0.4;}.cls-34-3,.cls-34-5{fill-opacity:0.2;}.cls-34-3,.cls-34-4{stroke:#000;stroke-miterlimit:10;}.cls-34-4{fill:none;}""",
- """"""
- ),
- Part(
- """.cls-35-2{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-35-3{fill-opacity:0.2;}.cls-35-4{fill:#fff;fill-opacity:0.4;}""",
- """"""
- ),
- Part(
- """.cls-36-2,.cls-36-6{fill:#fff;}.cls-36-2{fill-opacity:0.4;}.cls-36-3,.cls-36-4{fill:none;stroke:#000;stroke-miterlimit:10;}.cls-36-3{stroke-width:2px;}.cls-36-5,.cls-36-6{fill-opacity:0.2;}""",
- """"""
- ),
- Part(
- """.cls-37-2{fill:#fff;fill-opacity:0.4;}.cls-37-3{fill:none;}.cls-37-3,.cls-37-4{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-37-4{fill-opacity:0.2;}""",
- """"""
- ),
- Part(
- """.cls-38-2{fill:none;stroke:#000;stroke-miterlimit:10;}.cls-38-3,.cls-38-6{fill:#fff;}.cls-38-3,.cls-38-4{fill-opacity:0.2;}.cls-38-5{fill-opacity:0.1;}.cls-38-6{fill-opacity:0.4;}""",
- """"""
- ),
- Part(
- """.cls-39-2{fill:#fff;fill-opacity:0.4;}.cls-39-3{fill:none;}.cls-39-3,.cls-39-4{stroke:#000;stroke-miterlimit:10;}.cls-39-4{fill-opacity:0.2;stroke-width:0.75px;}""",
- """"""
- )
-)
-
-private val mouths: List = listOf(
- Part(
- """.cls-40-2{fill-opacity:0.4;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}""",
- """"""
- ),
- Part(
- """.cls-41-2,.cls-41-4{fill:none;}.cls-41-2,.cls-41-3,.cls-41-4{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-41-3{fill-opacity:0.4;}.cls-41-3,.cls-41-4{stroke-width:0.75px;}""",
- """"""
- ),
- Part(
- """.cls-42-2{fill-opacity:0.4;}.cls-42-2,.cls-42-5,.cls-42-6{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-42-3{fill:#ee4036;}.cls-42-4{fill:#f05a28;}.cls-42-5{fill:#faaf40;stroke-width:0.75px;}.cls-42-6{fill:none;}""",
- """"""
- ),
- Part(
- """.cls-43-2{fill:#f9ec31;}.cls-43-3{fill:#faaf40;}.cls-43-4,.cls-43-6{fill:none;}.cls-43-4,.cls-43-5,.cls-43-6{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-43-5{fill-opacity:0.4;}.cls-43-5,.cls-43-6{stroke-width:0.75px;}""",
- """"""
- ),
- Part(
- """.cls-44-2{fill:none;}.cls-44-2,.cls-44-5{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-44-3{opacity:0.4;}.cls-44-4{fill:#461917;}.cls-44-5{fill-opacity:0.4;stroke-width:0.75px;}""",
- """"""
- ),
- Part(
- """.cls-45-2{fill-opacity:0.4;stroke-miterlimit:10;}.cls-45-2,.cls-45-3{stroke:#000;}.cls-45-3{fill:#461917;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5px;}""",
- """"""
- ),
- Part(
- """.cls-46-2{fill-opacity:0.4;}.cls-46-3{fill:none;}.cls-46-3,.cls-46-4{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-46-4{fill:#461917;stroke-width:0.5px;}""",
- """"""
- ),
- Part(
- """.cls-47-2{fill-opacity:0.4;}.cls-47-2,.cls-47-3,.cls-47-4,.cls-47-5{stroke:#000;stroke-miterlimit:10;}.cls-47-3{fill:#f6921e;}.cls-47-4{fill:#f9ec31;stroke-width:0.75px;}.cls-47-5{fill:none;}""",
- """"""
- ),
- Part(
- """.cls-48-2{opacity:0.4;}.cls-48-3,.cls-48-4,.cls-48-5{fill:none;}.cls-48-3,.cls-48-4,.cls-48-5,.cls-48-6,.cls-48-7,.cls-48-8{stroke:#000;}.cls-48-3,.cls-48-5,.cls-48-7{stroke-miterlimit:10;}.cls-48-4,.cls-48-6,.cls-48-8{stroke-linecap:round;stroke-linejoin:round;}.cls-48-4,.cls-48-5{stroke-width:0.5px;}.cls-48-6{fill:#f6921e;stroke-width:1.2px;}.cls-48-7{fill:#f9ec31;}.cls-48-7,.cls-48-8{stroke-width:0.75px;}.cls-48-8{fill:#f05a27;}""",
- """"""
- ),
- Part(
- """.cls-49-2{fill:none;}.cls-49-2,.cls-49-3,.cls-49-5{stroke:#000;}.cls-49-2,.cls-49-3{stroke-linecap:round;stroke-linejoin:round;}.cls-49-3{opacity:0.1;}.cls-49-4{opacity:0.4;}.cls-49-5{fill-opacity:0.4;stroke-miterlimit:10;stroke-width:0.75px;}""",
- """"""
- )
-)
+package com.vitorpamplona.amethyst.ui.components
+
+import android.content.Context
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import coil.request.ImageRequest
+import java.nio.ByteBuffer
+import java.security.MessageDigest
+
+private fun toHex(color: Color): String {
+ val argb = color.toArgb()
+ val rgb = argb and 0x00FFFFFF // Mask out the alpha channel
+ return String.format("#%06X", rgb)
+}
+
+private val sha256: MessageDigest = MessageDigest.getInstance("SHA-256")
+
+private fun byteMod(byte: Byte, modulo: Int): Int {
+ val ub = byte.toUByte().toInt()
+ return ub % modulo
+}
+
+private fun bytesToRGB(b1: Byte, b2: Byte, b3: Byte): Color {
+ return Color(b1.toUByte().toInt(), b2.toUByte().toInt(), b3.toUByte().toInt())
+}
+
+private fun svgString(msg: String): String {
+ val hash = sha256.digest(msg.toByteArray())
+ val hashHex = hash.joinToString(separator = "") { b -> "%02x".format(b) }
+ val bgColor1 = bytesToRGB(hash[0], hash[1], hash[2])
+ val bgColor2 = bytesToRGB(hash[3], hash[4], hash[5])
+ val fgColor = bytesToRGB(hash[6], hash[7], hash[8])
+ val bgIndex = byteMod(hash[9], 8)
+ val bodyIndex = byteMod(hash[10], 10)
+ val faceIndex = byteMod(hash[11], 10)
+ val eyesIndex = byteMod(hash[12], 10)
+ val mouthIndex = byteMod(hash[13], 10)
+ val accIndex = byteMod(hash[14], 10)
+ val background = backgrounds[bgIndex]
+ val body = bodies[bodyIndex]
+ val face = faces[faceIndex]
+ val eye = eyes[eyesIndex]
+ val mouth = mouths[mouthIndex]
+ val accessory = accessories[accIndex]
+
+ return """
+
+ """.trimIndent()
+}
+
+object Robohash {
+ fun imageRequest(context: Context, message: String): ImageRequest {
+ return ImageRequest
+ .Builder(context)
+ .data(
+ ByteBuffer.wrap(
+ svgString(message).toByteArray()
+ )
+ )
+ .build()
+ }
+}
+
+private data class Part(val style: String, val paths: String)
+
+private val backgrounds: List = listOf(
+ """""",
+ """""",
+ """""",
+ """""",
+ """""",
+ """""",
+ """""",
+ """"""
+)
+
+private val accessories: List = listOf(
+ Part(
+ """.cls-00-2{fill:none;}.cls-00-2,.cls-00-3,.cls-00-4{stroke:#000;}.cls-00-2,.cls-00-3{stroke-linecap:round;stroke-linejoin:round;}.cls-00-3{fill-opacity:0.4;stroke-width:0.75px;}.cls-00-4{fill-opacity:0.2;stroke-miterlimit:10;stroke-width:0.5px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-01-2{fill:#fff;fill-opacity:0.2;}.cls-01-3,.cls-01-4{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-01-4{stroke-width:0.75px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-02-2{fill:#be1e2d;}.cls-02-11,.cls-02-2,.cls-02-5,.cls-02-6,.cls-02-7,.cls-02-9{stroke:#000;}.cls-02-11,.cls-02-2,.cls-02-5,.cls-02-9{stroke-miterlimit:10;}.cls-02-3{fill:#561317;}.cls-02-4{fill:#ed293b;}.cls-02-11,.cls-02-5,.cls-02-7{fill:none;}.cls-02-5,.cls-02-6{stroke-width:0.75px;}.cls-02-6{fill:#fff;}.cls-02-6,.cls-02-8{fill-opacity:0.2;}.cls-02-6,.cls-02-7{stroke-linecap:round;stroke-linejoin:round;}.cls-02-9{fill:#e6e7e8;}.cls-02-10{fill:#d0d2d3;}""",
+ """"""
+ ),
+ Part(
+ """.cls-03-2,.cls-03-3,.cls-03-8{fill:#fff;}.cls-03-2,.cls-03-3,.cls-03-7{fill-opacity:0.2;}.cls-03-2,.cls-03-4,.cls-03-5{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-03-2{stroke-width:0.75px;}.cls-03-4{fill:none;}.cls-03-5{fill:#ec1c24;}.cls-03-6{fill-opacity:0.1;}.cls-03-8{fill-opacity:0.4;}""",
+ """"""
+ ),
+ Part(
+ """.cls-04-2,.cls-04-3{fill:none;stroke-linecap:round;stroke-linejoin:round;}.cls-04-2,.cls-04-3,.cls-04-5{stroke:#000;}.cls-04-3,.cls-04-5{stroke-width:0.75px;}.cls-04-4,.cls-04-6{fill:#fff;}.cls-04-4{fill-opacity:0.4;}.cls-04-5{fill:#ec1c24;stroke-miterlimit:10;}.cls-04-6,.cls-04-7{fill-opacity:0.2;}""",
+ """"""
+ ),
+ Part(
+ """.cls-05-2{fill:#fff;fill-opacity:0.4;}.cls-05-2,.cls-05-3{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-05-3{fill:none;stroke-width:0.75px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-06-2,.cls-06-4{fill-opacity:0.2;}.cls-06-3,.cls-06-6{fill:none;}.cls-06-3,.cls-06-5,.cls-06-6{stroke:#000;}.cls-06-3,.cls-06-5{stroke-miterlimit:10;}.cls-06-4{fill:#fff;}.cls-06-5{fill:#ec1c24;stroke-width:0.75px;}.cls-06-6{stroke-linecap:round;stroke-linejoin:round;}""",
+ """"""
+ ),
+ Part(
+ """.cls-07-10,.cls-07-2,.cls-07-4,.cls-07-8,.cls-07-9{fill:none;}.cls-07-10,.cls-07-2,.cls-07-3,.cls-07-4,.cls-07-5,.cls-07-6,.cls-07-8,.cls-07-9{stroke:#000;}.cls-07-2,.cls-07-3,.cls-07-4,.cls-07-5,.cls-07-6,.cls-07-8{stroke-linecap:round;}.cls-07-2,.cls-07-3,.cls-07-4,.cls-07-5,.cls-07-6,.cls-07-8,.cls-07-9{stroke-linejoin:round;}.cls-07-3,.cls-07-5{fill:#fff;}.cls-07-3,.cls-07-5,.cls-07-6,.cls-07-7{fill-opacity:0.2;}.cls-07-3,.cls-07-4{stroke-width:0.75px;}.cls-07-10,.cls-07-8,.cls-07-9{stroke-width:1.5px;}.cls-07-10{stroke-miterlimit:10;}""",
+ """"""
+ ),
+ Part(
+ """.cls-08-2{fill:none;}.cls-08-2,.cls-08-3,.cls-08-5,.cls-08-6,.cls-08-7{stroke:#000;stroke-miterlimit:10;}.cls-08-3,.cls-08-4{fill:#fff;}.cls-08-3,.cls-08-4,.cls-08-8{fill-opacity:0.2;}.cls-08-5{fill:#716558;}.cls-08-6{fill:#9a8479;}.cls-08-7{fill:#c1b49a;}""",
+ """"""
+ ),
+ Part(
+ """.cls-09-2{fill:none;}.cls-09-2,.cls-09-4{stroke:#000;stroke-miterlimit:10;}.cls-09-3,.cls-09-4{fill:#fff;}.cls-09-3{fill-opacity:0.2;}.cls-09-5{fill:#d0d2d3;}.cls-09-6{fill-opacity:0.4;}""",
+ """"""
+ )
+)
+
+private val bodies: List = listOf(
+ Part(
+ """.cls-10-2{fill:#fff;fill-opacity:0.4;}.cls-10-3,.cls-10-5,.cls-10-7{fill:none;}.cls-10-3,.cls-10-4,.cls-10-5,.cls-10-6,.cls-10-7,.cls-10-8{stroke:#000;stroke-miterlimit:10;}.cls-10-3{stroke-width:1.2px;}.cls-10-4,.cls-10-6,.cls-10-9{fill-opacity:0.2;}.cls-10-5{stroke-width:1.25px;}.cls-10-6{stroke-width:0.75px;}.cls-10-8{fill:#6d6e70;}""",
+ """"""
+ ),
+ Part(
+ """.cls-11-2{fill:#fff;}.cls-11-2,.cls-11-6{fill-opacity:0.2;}.cls-11-3{fill:none;}.cls-11-3,.cls-11-4{stroke:#000;stroke-miterlimit:10;}.cls-11-4{fill:#6d6e70;}.cls-11-5{opacity:0.2;}""",
+ """"""
+ ),
+ Part(
+ """.cls-12-2{fill:#fff;fill-opacity:0.4;}.cls-12-3,.cls-12-7{fill:none;}.cls-12-3,.cls-12-5,.cls-12-6,.cls-12-7{stroke:#000;}.cls-12-3,.cls-12-5,.cls-12-6{stroke-miterlimit:10;}.cls-12-4,.cls-12-6{fill-opacity:0.2;}.cls-12-5{fill:#6d6e70;}.cls-12-7{stroke-linecap:round;stroke-linejoin:round;}""",
+ """"""
+ ),
+ Part(
+ """.cls-13-2{fill:none;}.cls-13-2,.cls-13-5{stroke:#000;stroke-miterlimit:10;}.cls-13-3{fill:#fff;fill-opacity:0.4;}.cls-13-4{fill-opacity:0.2;}.cls-13-5{fill:#6d6e70;}""",
+ """"""
+ ),
+ Part(
+ """.cls-14-2{fill:none;}.cls-14-2,.cls-14-4{stroke:#000;stroke-miterlimit:10;}.cls-14-3,.cls-14-6{fill-opacity:0.2;}.cls-14-4{fill:#6d6e70;}.cls-14-5,.cls-14-6{fill:#fff;}.cls-14-5{fill-opacity:0.4;}""",
+ """"""
+ ),
+ Part(
+ """.cls-15-2{fill:#fff;}.cls-15-2,.cls-15-4{fill-opacity:0.2;}.cls-15-2,.cls-15-3,.cls-15-5{stroke:#000;stroke-miterlimit:10;}.cls-15-3{fill:none;}.cls-15-5{fill:#6d6e70;}""",
+ """"""
+ ),
+ Part(
+ """.cls-16-2,.cls-16-5{fill:none;}.cls-16-2,.cls-16-5,.cls-16-6,.cls-16-7,.cls-16-8,.cls-16-9{stroke:#000;}.cls-16-2{stroke-linecap:round;stroke-linejoin:round;}.cls-16-3,.cls-16-6,.cls-16-7{fill-opacity:0.2;}.cls-16-4,.cls-16-6{fill:#fff;}.cls-16-4{fill-opacity:0.4;}.cls-16-5,.cls-16-6,.cls-16-7,.cls-16-8,.cls-16-9{stroke-miterlimit:10;}.cls-16-8{fill:#f9ec31;}.cls-16-9{fill:#6d6e70;}""",
+ """"""
+ ),
+ Part(
+ """.cls-17-2{fill:#020202;}.cls-17-2,.cls-17-4,.cls-17-6,.cls-17-7{fill-opacity:0.4;}.cls-17-3{fill-opacity:0.2;}.cls-17-4,.cls-17-6{fill:#fff;}.cls-17-4,.cls-17-5,.cls-17-8{stroke:#000;stroke-miterlimit:10;}.cls-17-5{fill:none;}.cls-17-8{fill:#6d6e70;}""",
+ """"""
+ ),
+ Part(
+ """.cls-fill-2,.cls-18-3,.cls-18-5,.cls-18-6{stroke:#000;stroke-miterlimit:10;}.cls-18-3{fill:none;}.cls-18-4{fill:#fff;}.cls-18-4,.cls-18-5{fill-opacity:0.4;}.cls-18-6{fill:#6d6e70;}.cls-18-7{opacity:0.2;}.cls-18-8{fill-opacity:0.2;}""",
+ """"""
+ ),
+ Part(
+ """.cls-19-2{fill-opacity:0.6;}.cls-19-11,.cls-19-13,.cls-19-14,.cls-19-2,.cls-19-3,.cls-19-4,.cls-19-6,.cls-19-8{stroke:#000;}.cls-19-11,.cls-19-13,.cls-19-2,.cls-19-4,.cls-19-6,.cls-19-8{stroke-miterlimit:10;}.cls-19-11,.cls-19-14,.cls-19-3,.cls-19-8{fill:none;}.cls-19-14,.cls-19-3{stroke-linecap:round;stroke-linejoin:round;}.cls-19-10,.cls-19-12,.cls-19-4,.cls-19-5{fill:#fff;}.cls-19-12,.cls-19-4{fill-opacity:0.2;}.cls-19-4{stroke-opacity:0;}.cls-19-5{fill-opacity:0.1;}.cls-19-6{fill:#6d6e70;}.cls-19-7{fill:#58595b;}.cls-19-13,.cls-19-9{fill-opacity:0.4;}.cls-19-10{fill-opacity:0.5;}.cls-19-11,.cls-19-14{stroke-width:0.75px;}""",
+ """"""
+ )
+)
+
+private val eyes: List = listOf(
+ Part(
+ """.cls-20-2{fill-opacity:0.4;}.cls-20-2,.cls-20-3{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-20-3{fill:#461917;stroke-width:0.5px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-21-2{fill-opacity:0.2;}.cls-21-2,.cls-21-3,.cls-21-4,.cls-21-5{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-21-2,.cls-21-4,.cls-21-5{stroke-width:0.5px;}.cls-21-3,.cls-21-4{fill-opacity:0.4;}.cls-21-5{fill:#461917;}.cls-21-6{fill:#faaf40;}""",
+ """"""
+ ),
+ Part(
+ """.cls-22-2{opacity:0.4;}.cls-22-3{fill:#461917;}.cls-22-3,.cls-22-4,.cls-22-5{stroke:#000;}.cls-22-3,.cls-22-5{stroke-linecap:round;stroke-linejoin:round;}.cls-22-3,.cls-22-4{stroke-width:0.5px;}.cls-22-4{fill:#ec1c24;stroke-miterlimit:10;}.cls-22-5{fill:none;stroke-width:0.75px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-23-2,.cls-23-3{fill:#fff;}.cls-23-2{fill-opacity:0.4;}.cls-23-3{fill-opacity:0.2;}.cls-23-3,.cls-23-4,.cls-23-5{stroke:#000;stroke-miterlimit:10;}.cls-23-4{fill:none;}.cls-23-4,.cls-23-5{stroke-width:0.75px;}.cls-23-5{fill:red;}""",
+ """"""
+ ),
+ Part(
+ """.cls-24-2{fill-opacity:0.4;stroke-miterlimit:10;}.cls-24-2,.cls-24-3,.cls-24-5{stroke:#000;}.cls-24-2,.cls-24-5{stroke-width:0.75px;}.cls-24-3,.cls-24-5{fill:#461917;stroke-linecap:round;stroke-linejoin:round;}.cls-24-3{stroke-width:0.5px;}.cls-24-4{fill:#ec1c24;}""",
+ """"""
+ ),
+ Part(
+ """.cls-25-2{fill-opacity:0.55;stroke-miterlimit:10;stroke-width:0.75px;}.cls-25-2,.cls-25-3{stroke:#000;}.cls-25-3{fill:#461917;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5px;}.cls-25-4{fill:#ec1c24;}""",
+ """"""
+ ),
+ Part(
+ """.cls-26-2{fill-opacity:0.6;}.cls-26-2,.cls-26-3,.cls-26-4,.cls-26-5,.cls-26-6{stroke:#000;}.cls-26-2,.cls-26-3,.cls-26-4,.cls-26-6{stroke-linecap:round;stroke-linejoin:round;}.cls-26-3{fill:#461917;}.cls-26-3,.cls-26-4,.cls-26-5{stroke-width:0.5px;}.cls-26-4,.cls-26-5{fill:#f9ec31;}.cls-26-5{stroke-miterlimit:10;}.cls-26-6{fill:none;}""",
+ """"""
+ ),
+ Part(
+ """.cls-27-2{fill-opacity:0.4;stroke-miterlimit:10;}.cls-27-2,.cls-27-3,.cls-27-4{stroke:#000;}.cls-27-3,.cls-27-4{fill:#461917;stroke-linecap:round;stroke-linejoin:round;}.cls-27-3{stroke-width:0.5px;}.cls-27-4{stroke-width:0.75px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-28-2{fill:none;}.cls-28-2,.cls-28-3,.cls-28-4,.cls-28-6{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-28-2,.cls-28-4,.cls-28-6{stroke-width:0.75px;}.cls-28-3{fill:#461917;stroke-width:0.5px;}.cls-28-4{fill-opacity:0.4;}.cls-28-5{fill:#fff100;}.cls-28-6{fill:#fff;fill-opacity:0.2;}""",
+ """"""
+ ),
+ Part(
+ """.cls-29-2{fill:#fff;}.cls-29-2,.cls-29-4{fill-opacity:0.4;}.cls-29-3{fill:none;}.cls-29-3,.cls-29-4{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-29-4{stroke-width:0.75px;}""",
+ """"""
+ )
+)
+
+private val faces: List = listOf(
+ Part(
+ """.cls-30-2{fill:#fff;fill-opacity:0.4;}.cls-30-3,.cls-30-4{fill:none;}.cls-30-3,.cls-30-4,.cls-30-6{stroke:#000;}.cls-30-3,.cls-30-6{stroke-linecap:round;stroke-linejoin:round;}.cls-30-4{stroke-miterlimit:10;}.cls-30-5,.cls-30-6{fill-opacity:0.2;}.cls-30-6{stroke-width:0.75px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-31-2,.cls-31-4{fill-opacity:0.2;}.cls-31-3{fill:none;}.cls-31-3,.cls-31-4{stroke:#000;stroke-miterlimit:10;}.cls-31-4,.cls-31-5{fill:#fff;}.cls-31-4{stroke-width:0.75px;}.cls-31-5{fill-opacity:0.4;}""",
+ """"""
+ ),
+ Part(
+ """.cls-32-2{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-32-3{fill-opacity:0.2;}.cls-32-4{fill:#fff;fill-opacity:0.4;}""",
+ """"""
+ ),
+ Part(
+ """.cls-33-2{fill-opacity:0.2;}.cls-33-3{fill:#fff;fill-opacity:0.4;}.cls-33-4{fill:none;stroke:#000;stroke-miterlimit:10;}""",
+ """"""
+ ),
+ Part(
+ """.cls-34-2,.cls-34-3{fill:#fff;}.cls-34-2{fill-opacity:0.4;}.cls-34-3,.cls-34-5{fill-opacity:0.2;}.cls-34-3,.cls-34-4{stroke:#000;stroke-miterlimit:10;}.cls-34-4{fill:none;}""",
+ """"""
+ ),
+ Part(
+ """.cls-35-2{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-35-3{fill-opacity:0.2;}.cls-35-4{fill:#fff;fill-opacity:0.4;}""",
+ """"""
+ ),
+ Part(
+ """.cls-36-2,.cls-36-6{fill:#fff;}.cls-36-2{fill-opacity:0.4;}.cls-36-3,.cls-36-4{fill:none;stroke:#000;stroke-miterlimit:10;}.cls-36-3{stroke-width:2px;}.cls-36-5,.cls-36-6{fill-opacity:0.2;}""",
+ """"""
+ ),
+ Part(
+ """.cls-37-2{fill:#fff;fill-opacity:0.4;}.cls-37-3{fill:none;}.cls-37-3,.cls-37-4{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-37-4{fill-opacity:0.2;}""",
+ """"""
+ ),
+ Part(
+ """.cls-38-2{fill:none;stroke:#000;stroke-miterlimit:10;}.cls-38-3,.cls-38-6{fill:#fff;}.cls-38-3,.cls-38-4{fill-opacity:0.2;}.cls-38-5{fill-opacity:0.1;}.cls-38-6{fill-opacity:0.4;}""",
+ """"""
+ ),
+ Part(
+ """.cls-39-2{fill:#fff;fill-opacity:0.4;}.cls-39-3{fill:none;}.cls-39-3,.cls-39-4{stroke:#000;stroke-miterlimit:10;}.cls-39-4{fill-opacity:0.2;stroke-width:0.75px;}""",
+ """"""
+ )
+)
+
+private val mouths: List = listOf(
+ Part(
+ """.cls-40-2{fill-opacity:0.4;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}""",
+ """"""
+ ),
+ Part(
+ """.cls-41-2,.cls-41-4{fill:none;}.cls-41-2,.cls-41-3,.cls-41-4{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-41-3{fill-opacity:0.4;}.cls-41-3,.cls-41-4{stroke-width:0.75px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-42-2{fill-opacity:0.4;}.cls-42-2,.cls-42-5,.cls-42-6{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-42-3{fill:#ee4036;}.cls-42-4{fill:#f05a28;}.cls-42-5{fill:#faaf40;stroke-width:0.75px;}.cls-42-6{fill:none;}""",
+ """"""
+ ),
+ Part(
+ """.cls-43-2{fill:#f9ec31;}.cls-43-3{fill:#faaf40;}.cls-43-4,.cls-43-6{fill:none;}.cls-43-4,.cls-43-5,.cls-43-6{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-43-5{fill-opacity:0.4;}.cls-43-5,.cls-43-6{stroke-width:0.75px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-44-2{fill:none;}.cls-44-2,.cls-44-5{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-44-3{opacity:0.4;}.cls-44-4{fill:#461917;}.cls-44-5{fill-opacity:0.4;stroke-width:0.75px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-45-2{fill-opacity:0.4;stroke-miterlimit:10;}.cls-45-2,.cls-45-3{stroke:#000;}.cls-45-3{fill:#461917;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.5px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-46-2{fill-opacity:0.4;}.cls-46-3{fill:none;}.cls-46-3,.cls-46-4{stroke:#000;stroke-linecap:round;stroke-linejoin:round;}.cls-46-4{fill:#461917;stroke-width:0.5px;}""",
+ """"""
+ ),
+ Part(
+ """.cls-47-2{fill-opacity:0.4;}.cls-47-2,.cls-47-3,.cls-47-4,.cls-47-5{stroke:#000;stroke-miterlimit:10;}.cls-47-3{fill:#f6921e;}.cls-47-4{fill:#f9ec31;stroke-width:0.75px;}.cls-47-5{fill:none;}""",
+ """"""
+ ),
+ Part(
+ """.cls-48-2{opacity:0.4;}.cls-48-3,.cls-48-4,.cls-48-5{fill:none;}.cls-48-3,.cls-48-4,.cls-48-5,.cls-48-6,.cls-48-7,.cls-48-8{stroke:#000;}.cls-48-3,.cls-48-5,.cls-48-7{stroke-miterlimit:10;}.cls-48-4,.cls-48-6,.cls-48-8{stroke-linecap:round;stroke-linejoin:round;}.cls-48-4,.cls-48-5{stroke-width:0.5px;}.cls-48-6{fill:#f6921e;stroke-width:1.2px;}.cls-48-7{fill:#f9ec31;}.cls-48-7,.cls-48-8{stroke-width:0.75px;}.cls-48-8{fill:#f05a27;}""",
+ """"""
+ ),
+ Part(
+ """.cls-49-2{fill:none;}.cls-49-2,.cls-49-3,.cls-49-5{stroke:#000;}.cls-49-2,.cls-49-3{stroke-linecap:round;stroke-linejoin:round;}.cls-49-3{opacity:0.1;}.cls-49-4{opacity:0.4;}.cls-49-5{fill-opacity:0.4;stroke-miterlimit:10;stroke-width:0.75px;}""",
+ """"""
+ )
+)
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RobohashAsyncImage.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RobohashAsyncImage.kt
new file mode 100644
index 000000000..7523dff6e
--- /dev/null
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/RobohashAsyncImage.kt
@@ -0,0 +1,128 @@
+package com.vitorpamplona.amethyst.ui.components
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+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.graphics.ColorFilter
+import androidx.compose.ui.graphics.DefaultAlpha
+import androidx.compose.ui.graphics.FilterQuality
+import androidx.compose.ui.graphics.drawscope.DrawScope
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import coil.compose.AsyncImage
+import coil.compose.AsyncImagePainter
+
+@Composable
+fun RobohashAsyncImage(
+ robot: String,
+ modifier: Modifier = Modifier,
+ contentDescription: String? = null,
+ transform: (AsyncImagePainter.State) -> AsyncImagePainter.State = AsyncImagePainter.DefaultTransform,
+ onState: ((AsyncImagePainter.State) -> Unit)? = null,
+ alignment: Alignment = Alignment.Center,
+ contentScale: ContentScale = ContentScale.Fit,
+ alpha: Float = DefaultAlpha,
+ colorFilter: ColorFilter? = null,
+ filterQuality: FilterQuality = DrawScope.DefaultFilterQuality
+) {
+ AsyncImage(
+ model = Robohash.imageRequest(LocalContext.current, robot),
+ contentDescription = contentDescription,
+ modifier = modifier,
+ transform = transform,
+ onState = onState,
+ alignment = alignment,
+ contentScale = contentScale,
+ alpha = alpha,
+ colorFilter = colorFilter,
+ filterQuality = filterQuality
+ )
+}
+
+@Composable
+fun RobohashFallbackAsyncImage(
+ robot: String = "aaaa",
+ model: Any?,
+ contentDescription: String?,
+ modifier: Modifier = Modifier,
+ alignment: Alignment = Alignment.Center,
+ contentScale: ContentScale = ContentScale.Fit,
+ alpha: Float = DefaultAlpha,
+ colorFilter: ColorFilter? = null,
+ filterQuality: FilterQuality = DrawScope.DefaultFilterQuality
+) {
+ var loading by remember { mutableStateOf(false) }
+ var error by remember { mutableStateOf(false) }
+
+ Box {
+ AsyncImage(
+ model = model,
+ contentDescription = contentDescription,
+ modifier = modifier,
+ onLoading = { loading = true },
+ onSuccess = { loading = false; error = false },
+ onError = { error = true },
+ alignment = alignment,
+ contentScale = contentScale,
+ alpha = alpha,
+ colorFilter = colorFilter,
+ filterQuality = filterQuality
+ )
+
+ if (loading || error) {
+ RobohashAsyncImage(
+ robot = robot,
+ contentDescription = contentDescription,
+ modifier = modifier,
+ alignment = alignment,
+ contentScale = contentScale,
+ alpha = alpha,
+ colorFilter = colorFilter,
+ filterQuality = filterQuality
+ )
+ }
+ }
+}
+
+@Composable
+fun RobohashAsyncImageProxy(
+ robot: String,
+ model: ResizeImage,
+ contentDescription: String?,
+ modifier: Modifier = Modifier,
+ alignment: Alignment = Alignment.Center,
+ contentScale: ContentScale = ContentScale.Fit,
+ alpha: Float = DefaultAlpha,
+ colorFilter: ColorFilter? = null,
+ filterQuality: FilterQuality = DrawScope.DefaultFilterQuality
+) {
+ if (model.url == null) {
+ RobohashAsyncImage(
+ robot = robot,
+ contentDescription = contentDescription,
+ modifier = modifier,
+ alignment = alignment,
+ contentScale = contentScale,
+ alpha = alpha,
+ colorFilter = colorFilter,
+ filterQuality = filterQuality
+ )
+ } else {
+ RobohashFallbackAsyncImage(
+ robot = robot,
+ model = model.proxyUrl(),
+ contentDescription = contentDescription,
+ modifier = modifier,
+ alignment = alignment,
+ contentScale = contentScale,
+ alpha = alpha,
+ colorFilter = colorFilter,
+ filterQuality = filterQuality
+ )
+ }
+}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt
index 991c8e8dc..eed7bfd60 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppTopBar.kt
@@ -57,8 +57,8 @@ import com.vitorpamplona.amethyst.service.NostrUserProfileDataSource
import com.vitorpamplona.amethyst.service.relays.Client
import com.vitorpamplona.amethyst.service.relays.RelayPool
import com.vitorpamplona.amethyst.ui.actions.NewRelayListView
-import com.vitorpamplona.amethyst.ui.components.AsyncUserImageProxy
import com.vitorpamplona.amethyst.ui.components.ResizeImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
import com.vitorpamplona.amethyst.ui.screen.RelayPoolViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import kotlinx.coroutines.launch
@@ -195,12 +195,9 @@ fun MainTopBar(scaffoldState: ScaffoldState, accountViewModel: AccountViewModel)
},
modifier = Modifier
) {
- AsyncUserImageProxy(
- pubkeyHex = accountUser.pubkeyHex,
+ RobohashAsyncImageProxy(
+ robot = accountUser.pubkeyHex,
model = ResizeImage(accountUser.profilePicture(), 34.dp),
-// placeholder = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
-// fallback = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
-// error = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
contentDescription = stringResource(id = R.string.profile_image),
modifier = Modifier
.width(34.dp)
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt
index b6ad544ef..aa337915d 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/DrawerContent.kt
@@ -49,8 +49,8 @@ import com.vitorpamplona.amethyst.BuildConfig
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.User
-import com.vitorpamplona.amethyst.ui.components.AsyncUserImageProxy
import com.vitorpamplona.amethyst.ui.components.ResizeImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountBackupDialog
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import kotlinx.coroutines.launch
@@ -135,13 +135,10 @@ fun ProfileContent(baseAccountUser: User, modifier: Modifier = Modifier, scaffol
}
Column(modifier = modifier) {
- AsyncUserImageProxy(
- pubkeyHex = accountUser.pubkeyHex,
+ RobohashAsyncImageProxy(
+ robot = accountUser.pubkeyHex,
model = ResizeImage(accountUser.profilePicture(), 100.dp),
contentDescription = stringResource(id = R.string.profile_image),
-// placeholder = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
-// fallback = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
-// error = BitmapPainter(RoboHashCache.get(ctx, accountUser.pubkeyHex)),
modifier = Modifier
.width(100.dp)
.height(100.dp)
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt
index c0dd8c182..023d9cedd 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomCompose.kt
@@ -27,8 +27,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.painter.BitmapPainter
-import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
@@ -43,12 +41,11 @@ import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.vitorpamplona.amethyst.NotificationCache
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
-import com.vitorpamplona.amethyst.ui.components.AsyncImageProxy
import com.vitorpamplona.amethyst.ui.components.ResizeImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -98,13 +95,8 @@ fun ChatroomCompose(
}
ChannelName(
+ channelIdHex = channel.idHex,
channelPicture = channel.profilePicture(),
- channelPicturePlaceholder = BitmapPainter(
- RoboHashCache.get(
- context,
- channel.idHex
- )
- ),
channelTitle = {
Text(
text = buildAnnotatedString {
@@ -183,8 +175,8 @@ fun ChatroomCompose(
@Composable
fun ChannelName(
+ channelIdHex: String,
channelPicture: String?,
- channelPicturePlaceholder: Painter?,
channelTitle: @Composable (Modifier) -> Unit,
channelLastTime: Long?,
channelLastContent: String?,
@@ -193,11 +185,9 @@ fun ChannelName(
) {
ChannelName(
channelPicture = {
- AsyncImageProxy(
+ RobohashAsyncImageProxy(
+ robot = channelIdHex,
model = ResizeImage(channelPicture, 55.dp),
- placeholder = channelPicturePlaceholder,
- fallback = channelPicturePlaceholder,
- error = channelPicturePlaceholder,
contentDescription = stringResource(R.string.channel_image),
modifier = Modifier
.width(55.dp)
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt
index b00a1d192..0c7a730bb 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/ChatroomMessageCompose.kt
@@ -40,7 +40,6 @@ import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ColorMatrix
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
@@ -51,17 +50,16 @@ import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
-import coil.compose.AsyncImage
import com.google.accompanist.flowlayout.FlowRow
import com.vitorpamplona.amethyst.NotificationCache
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.model.ChannelCreateEvent
import com.vitorpamplona.amethyst.service.model.ChannelMessageEvent
import com.vitorpamplona.amethyst.service.model.ChannelMetadataEvent
-import com.vitorpamplona.amethyst.ui.components.AsyncUserImageProxy
import com.vitorpamplona.amethyst.ui.components.ResizeImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
+import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.components.TranslateableRichTextViewer
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import kotlinx.coroutines.Dispatchers
@@ -149,12 +147,14 @@ fun ChatroomMessageCompose(
val modif = if (innerQuote) {
Modifier.padding(top = 10.dp, end = 5.dp)
} else {
- Modifier.fillMaxWidth(1f).padding(
- start = 12.dp,
- end = 12.dp,
- top = 5.dp,
- bottom = 5.dp
- )
+ Modifier
+ .fillMaxWidth(1f)
+ .padding(
+ start = 12.dp,
+ end = 12.dp,
+ top = 5.dp,
+ bottom = 5.dp
+ )
}
Row(
@@ -182,9 +182,11 @@ fun ChatroomMessageCompose(
var bubbleSize by remember { mutableStateOf(IntSize.Zero) }
Column(
- modifier = Modifier.padding(start = 10.dp, end = 5.dp, bottom = 5.dp).onSizeChanged {
- bubbleSize = it
- }
+ modifier = Modifier
+ .padding(start = 10.dp, end = 5.dp, bottom = 5.dp)
+ .onSizeChanged {
+ bubbleSize = it
+ }
) {
val authorState by note.author!!.live().metadata.observeAsState()
val author = authorState?.user!!
@@ -195,12 +197,9 @@ fun ChatroomMessageCompose(
horizontalArrangement = alignment,
modifier = Modifier.padding(top = 5.dp)
) {
- AsyncUserImageProxy(
- pubkeyHex = author.pubkeyHex,
+ RobohashAsyncImageProxy(
+ robot = author.pubkeyHex,
model = ResizeImage(author.profilePicture(), 25.dp),
-// placeholder = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)),
-// fallback = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)),
-// error = BitmapPainter(RoboHashCache.get(context, author.pubkeyHex)),
contentDescription = stringResource(id = R.string.profile_image),
modifier = Modifier
.width(25.dp)
@@ -308,11 +307,16 @@ fun ChatroomMessageCompose(
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
- modifier = Modifier.padding(top = 5.dp).then(
- with(LocalDensity.current) {
- Modifier.widthIn(bubbleSize.width.toDp(), availableBubbleSize.width.toDp())
- }
- )
+ modifier = Modifier
+ .padding(top = 5.dp)
+ .then(
+ with(LocalDensity.current) {
+ Modifier.widthIn(
+ bubbleSize.width.toDp(),
+ availableBubbleSize.width.toDp()
+ )
+ }
+ )
) {
Row() {
Text(
@@ -366,18 +370,16 @@ private fun RelayBadges(baseNote: Note) {
.size(15.dp)
.padding(1.dp)
) {
- AsyncImage(
+ RobohashFallbackAsyncImage(
+ robot = "https://$url/favicon.ico",
model = "https://$url/favicon.ico",
- placeholder = BitmapPainter(RoboHashCache.get(ctx, url)),
- fallback = BitmapPainter(RoboHashCache.get(ctx, url)),
- error = BitmapPainter(RoboHashCache.get(ctx, url)),
contentDescription = stringResource(id = R.string.relay_icon),
colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) }),
modifier = Modifier
.fillMaxSize(1f)
.clip(shape = CircleShape)
.background(MaterialTheme.colors.background)
- .clickable(onClick = { uri.openUri("https://" + url) })
+ .clickable(onClick = { uri.openUri("https://$url") })
)
}
}
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt
index 078389a62..24dced5f6 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt
@@ -19,7 +19,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ColorMatrix
import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
@@ -38,7 +37,6 @@ import coil.compose.AsyncImage
import com.google.accompanist.flowlayout.FlowRow
import com.vitorpamplona.amethyst.NotificationCache
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
@@ -53,9 +51,11 @@ import com.vitorpamplona.amethyst.service.model.ReactionEvent
import com.vitorpamplona.amethyst.service.model.ReportEvent
import com.vitorpamplona.amethyst.service.model.RepostEvent
import com.vitorpamplona.amethyst.service.model.TextNoteEvent
-import com.vitorpamplona.amethyst.ui.components.AsyncUserImageProxy
import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status
import com.vitorpamplona.amethyst.ui.components.ResizeImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
+import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.components.TranslateableRichTextViewer
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.ChannelHeader
@@ -217,12 +217,9 @@ fun NoteCompose(
.height(30.dp)
.align(Alignment.BottomEnd)
) {
- AsyncUserImageProxy(
- pubkeyHex = channel.idHex,
+ RobohashAsyncImageProxy(
+ robot = channel.idHex,
model = ResizeImage(channel.profilePicture(), 30.dp),
-// placeholder = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
-// fallback = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
-// error = BitmapPainter(RoboHashCache.get(context, channel.idHex)),
contentDescription = stringResource(R.string.group_picture),
modifier = Modifier
.width(30.dp)
@@ -603,11 +600,9 @@ private fun RelayBadges(baseNote: Note) {
.size(15.dp)
.padding(1.dp)
) {
- AsyncImage(
+ RobohashFallbackAsyncImage(
+ robot = "https://$url/favicon.ico",
model = "https://$url/favicon.ico",
- placeholder = BitmapPainter(RoboHashCache.get(ctx, url)),
- fallback = BitmapPainter(RoboHashCache.get(ctx, url)),
- error = BitmapPainter(RoboHashCache.get(ctx, url)),
contentDescription = stringResource(R.string.relay_icon),
colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0f) }),
modifier = Modifier
@@ -677,8 +672,8 @@ fun NoteAuthorPicture(
.height(size)
) {
if (author == null) {
- Image(
- painter = BitmapPainter(RoboHashCache.get(ctx, "ohnothisauthorisnotfound")),
+ RobohashAsyncImage(
+ robot = "authornotfound",
contentDescription = stringResource(R.string.unknown_author),
modifier = pictureModifier
.fillMaxSize(1f)
@@ -724,8 +719,8 @@ fun UserPicture(
.width(size)
.height(size)
) {
- AsyncUserImageProxy(
- pubkeyHex = user.pubkeyHex,
+ RobohashAsyncImageProxy(
+ robot = user.pubkeyHex,
model = ResizeImage(user.profilePicture(), size),
contentDescription = stringResource(id = R.string.profile_image),
modifier = pictureModifier
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt
index 0dd85989b..5d54cbdc5 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChannelScreen.kt
@@ -66,8 +66,8 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.NostrChannelDataSource
import com.vitorpamplona.amethyst.ui.actions.NewChannelView
import com.vitorpamplona.amethyst.ui.actions.PostButton
-import com.vitorpamplona.amethyst.ui.components.AsyncUserImageProxy
import com.vitorpamplona.amethyst.ui.components.ResizeImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
import com.vitorpamplona.amethyst.ui.dal.ChannelFeedFilter
import com.vitorpamplona.amethyst.ui.navigation.Route
import com.vitorpamplona.amethyst.ui.note.ChatroomMessageCompose
@@ -226,8 +226,8 @@ fun ChannelHeader(baseChannel: Channel, account: Account, navController: NavCont
Column() {
Column(modifier = Modifier.padding(12.dp)) {
Row(verticalAlignment = Alignment.CenterVertically) {
- AsyncUserImageProxy(
- pubkeyHex = channel.idHex,
+ RobohashAsyncImageProxy(
+ robot = channel.idHex,
model = ResizeImage(channel.profilePicture(), 35.dp),
contentDescription = context.getString(R.string.profile_image),
modifier = Modifier
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt
index 6d1775651..e566bb055 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomScreen.kt
@@ -52,9 +52,9 @@ import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.model.User
import com.vitorpamplona.amethyst.service.NostrChatroomDataSource
import com.vitorpamplona.amethyst.ui.actions.PostButton
-import com.vitorpamplona.amethyst.ui.components.AsyncUserImageProxy
import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status
import com.vitorpamplona.amethyst.ui.components.ResizeImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImageProxy
import com.vitorpamplona.amethyst.ui.dal.ChatroomFeedFilter
import com.vitorpamplona.amethyst.ui.note.ChatroomMessageCompose
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
@@ -211,12 +211,9 @@ fun ChatroomHeader(baseUser: User, accountViewModel: AccountViewModel, navContro
val authorState by baseUser.live().metadata.observeAsState()
val author = authorState?.user!!
- AsyncUserImageProxy(
- pubkeyHex = author.pubkeyHex,
+ RobohashAsyncImageProxy(
+ robot = author.pubkeyHex,
model = ResizeImage(author.profilePicture(), 35.dp),
-// placeholder = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)),
-// fallback = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)),
-// error = BitmapPainter(RoboHashCache.get(ctx, author.pubkeyHex)),
contentDescription = stringResource(id = R.string.profile_image),
modifier = Modifier
.width(35.dp)
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt
index 198b6c5ca..cc7cf9e55 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt
@@ -21,7 +21,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
@@ -51,7 +50,6 @@ import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.pagerTabIndicatorOffset
import com.google.accompanist.pager.rememberPagerState
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
@@ -65,6 +63,8 @@ import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView
import com.vitorpamplona.amethyst.ui.components.DisplayNip05ProfileStatus
import com.vitorpamplona.amethyst.ui.components.InvoiceRequest
import com.vitorpamplona.amethyst.ui.components.ResizeImage
+import com.vitorpamplona.amethyst.ui.components.RobohashAsyncImage
+import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage
import com.vitorpamplona.amethyst.ui.components.ZoomableImageDialog
import com.vitorpamplona.amethyst.ui.dal.UserProfileConversationsFeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileFollowersFeedFilter
@@ -432,13 +432,17 @@ private fun DrawAdditionalInfo(baseUser: User, account: Account, navController:
)
IconButton(
- modifier = Modifier.size(30.dp).padding(start = 5.dp),
+ modifier = Modifier
+ .size(30.dp)
+ .padding(start = 5.dp),
onClick = { clipboardManager.setText(AnnotatedString(user.pubkeyNpub())); }
) {
Icon(
imageVector = Icons.Default.ContentCopy,
null,
- modifier = Modifier.padding(end = 5.dp).size(15.dp),
+ modifier = Modifier
+ .padding(end = 5.dp)
+ .size(15.dp),
tint = MaterialTheme.colors.onSurface.copy(alpha = 0.32f)
)
}
@@ -580,20 +584,18 @@ fun BadgeThumb(
.height(size)
) {
if (image == null) {
- Image(
- painter = BitmapPainter(RoboHashCache.get(ctx, "ohnothisauthorisnotfound")),
+ RobohashAsyncImage(
+ robot = "authornotfound",
contentDescription = stringResource(R.string.unknown_author),
modifier = pictureModifier
.fillMaxSize(1f)
.background(MaterialTheme.colors.background)
)
} else {
- AsyncImage(
+ RobohashFallbackAsyncImage(
+ robot = note.idHex,
model = image,
contentDescription = stringResource(id = R.string.profile_image),
- placeholder = BitmapPainter(RoboHashCache.get(ctx, note.idHex)),
- fallback = BitmapPainter(RoboHashCache.get(ctx, note.idHex)),
- error = BitmapPainter(RoboHashCache.get(ctx, note.idHex)),
modifier = pictureModifier
.fillMaxSize(1f)
.clip(shape = CircleShape)
diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt
index f55a5f3a8..1707582bc 100644
--- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt
+++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/SearchScreen.kt
@@ -36,7 +36,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.painterResource
@@ -49,7 +48,6 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.navigation.NavController
import com.vitorpamplona.amethyst.R
-import com.vitorpamplona.amethyst.RoboHashCache
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.Channel
import com.vitorpamplona.amethyst.model.LocalCache
@@ -245,8 +243,8 @@ private fun SearchBar(accountViewModel: AccountViewModel, navController: NavCont
itemsIndexed(searchResultsChannels.value, key = { _, item -> "c" + item.idHex }) { index, item ->
ChannelName(
+ channelIdHex = item.idHex,
channelPicture = item.profilePicture(),
- channelPicturePlaceholder = BitmapPainter(RoboHashCache.get(ctx, item.idHex)),
channelTitle = {
Text(
"${item.info.name}",