From ef4c5a592c29fa8a871e0553249b8d3e795de5d3 Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Tue, 21 Apr 2026 03:15:32 +0200 Subject: [PATCH] Use forwardingPainter to add colour to placeholder graphics --- .../widgets/coil/forwardingPainter.kt | 60 +++++++++++++++++++ .../composable/widgets/feed/EventListView.kt | 3 + .../widgets/profile/ProfileAvatar.kt | 18 +++++- 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/coil/forwardingPainter.kt diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/coil/forwardingPainter.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/coil/forwardingPainter.kt new file mode 100644 index 00000000..4616a28e --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/coil/forwardingPainter.kt @@ -0,0 +1,60 @@ +package ac.aux.compose.ui.composable.widgets.coil + +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.DefaultAlpha +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.painter.Painter + +/** + * https://gist.github.com/colinrtwhite/c2966e0b8584b4cdf0a5b05786b20ae1 + */ +fun forwardingPainter( + painter: Painter, + alpha: Float = DefaultAlpha, + colorFilter: ColorFilter? = null, + onDraw: DrawScope.(ForwardingDrawInfo) -> Unit = DefaultOnDraw, +): Painter = ForwardingPainter(painter, alpha, colorFilter, onDraw) + +data class ForwardingDrawInfo( + val painter: Painter, + val alpha: Float, + val colorFilter: ColorFilter?, +) + +private class ForwardingPainter( + private val painter: Painter, + private var alpha: Float, + private var colorFilter: ColorFilter?, + private val onDraw: DrawScope.(ForwardingDrawInfo) -> Unit, +) : Painter() { + + private var info = newInfo() + + override val intrinsicSize get() = painter.intrinsicSize + + override fun applyAlpha(alpha: Float): Boolean { + if (alpha != DefaultAlpha) { + this.alpha = alpha + this.info = newInfo() + } + return true + } + + override fun applyColorFilter(colorFilter: ColorFilter?): Boolean { + if (colorFilter != null) { + this.colorFilter = colorFilter + this.info = newInfo() + } + return true + } + + override fun DrawScope.onDraw() = onDraw(info) + + private fun newInfo() = ForwardingDrawInfo(painter, alpha, colorFilter) +} + +private val DefaultOnDraw: DrawScope.(ForwardingDrawInfo) -> Unit = { info -> + with(info.painter) { + draw(size, info.alpha, info.colorFilter) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/feed/EventListView.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/feed/EventListView.kt index 15810d0d..4f41760e 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/feed/EventListView.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/feed/EventListView.kt @@ -30,6 +30,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.BiasAbsoluteAlignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -130,6 +131,7 @@ private fun TextNoteFeedItem( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically ) { + // TODO: If we don't have the name of the author being replied too we shouldn't show this.. Text( "In reply to ", style = MaterialTheme.typography.labelSmall @@ -146,6 +148,7 @@ private fun TextNoteFeedItem( ) } } + ElevatedCard( modifier = Modifier.padding( horizontal = 10.dp diff --git a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/profile/ProfileAvatar.kt b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/profile/ProfileAvatar.kt index 8a1ffc32..931206fd 100644 --- a/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/profile/ProfileAvatar.kt +++ b/composeApp/src/commonMain/kotlin/ac/aux/compose/ui/composable/widgets/profile/ProfileAvatar.kt @@ -1,6 +1,7 @@ package ac.aux.compose.ui.composable.widgets.profile import ac.aux.compose.database.model.Profile +import ac.aux.compose.ui.composable.widgets.coil.forwardingPainter import ac.aux.compose.ui.theme.AuxTheme import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -16,6 +17,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.tooling.preview.Preview @@ -44,9 +46,19 @@ fun ProfileAvatar(publicKey: String, profile: Profile?) { ) } else { // Load image... - val placeHolderGraphic = rememberVectorPainter(Icons.Default.Face5) - val fallbackGraphic = rememberVectorPainter(Icons.Default.Face5) - val errorGraphic = rememberVectorPainter(Icons.Default.FaceRetouchingOff) + val placeHolderGraphic = forwardingPainter( + painter = rememberVectorPainter(Icons.Default.Face5), + colorFilter = ColorFilter.tint(tintColor) + ) + + val fallbackGraphic = forwardingPainter( + painter = rememberVectorPainter(Icons.Default.Face5), + colorFilter = ColorFilter.tint(tintColor) + ) + val errorGraphic = forwardingPainter( + painter = rememberVectorPainter(Icons.Default.FaceRetouchingOff), + colorFilter = ColorFilter.tint(tintColor) + ) AsyncImage( model = profile.picture,