Skip to content

Commit 62b1cea

Browse files
authored
Merge pull request #204 from mikepenz/feature/refactor_markdown_image
Refactor `MarkdownImage` and `InlineImage` handling
2 parents 53efcb3 + a90b495 commit 62b1cea

File tree

4 files changed

+79
-43
lines changed

4 files changed

+79
-43
lines changed

multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/compose/elements/MarkdownImage.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ fun MarkdownImage(content: String, node: ASTNode) {
1717
Image(
1818
painter = imageData.painter,
1919
contentDescription = imageData.contentDescription,
20+
modifier = imageData.modifier,
2021
alignment = imageData.alignment,
21-
modifier = imageData.modifier
22+
contentScale = imageData.contentScale,
23+
alpha = imageData.alpha,
24+
colorFilter = imageData.colorFilter
2225
)
2326
}
2427
}

multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/compose/elements/MarkdownText.kt

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import androidx.compose.foundation.gestures.awaitEachGesture
66
import androidx.compose.foundation.gestures.awaitFirstDown
77
import androidx.compose.foundation.gestures.waitForUpOrCancellation
88
import androidx.compose.foundation.text.InlineTextContent
9-
import androidx.compose.runtime.Composable
10-
import androidx.compose.runtime.LaunchedEffect
11-
import androidx.compose.runtime.mutableStateOf
12-
import androidx.compose.runtime.remember
9+
import androidx.compose.runtime.*
1310
import androidx.compose.ui.Modifier
1411
import androidx.compose.ui.input.pointer.pointerInput
1512
import androidx.compose.ui.layout.onPlaced
1613
import androidx.compose.ui.platform.LocalUriHandler
17-
import androidx.compose.ui.text.*
14+
import androidx.compose.ui.text.AnnotatedString
15+
import androidx.compose.ui.text.Placeholder
16+
import androidx.compose.ui.text.TextLayoutResult
17+
import androidx.compose.ui.text.TextStyle
1818
import androidx.compose.ui.unit.sp
1919
import com.mikepenz.markdown.compose.*
2020
import com.mikepenz.markdown.compose.elements.material.MarkdownBasicText
@@ -110,6 +110,16 @@ fun MarkdownText(
110110
}
111111
} else modifier
112112

113+
114+
val transformer = LocalImageTransformer.current
115+
val placeholderState by derivedStateOf {
116+
transformer.placeholderConfig(
117+
imageState.density,
118+
imageState.containerSize,
119+
imageState.intrinsicImageSize
120+
)
121+
}
122+
113123
MarkdownBasicText(
114124
text = content,
115125
modifier = textModifier
@@ -123,31 +133,30 @@ fun MarkdownText(
123133
color = LocalMarkdownColors.current.text,
124134
inlineContent = mapOf(MARKDOWN_TAG_IMAGE_URL to InlineTextContent(
125135
Placeholder(
126-
width = imageState.imageSize.width.sp,
127-
height = imageState.imageSize.height.sp,
128-
placeholderVerticalAlign = PlaceholderVerticalAlign.Bottom
136+
width = placeholderState.size.width.sp,
137+
height = placeholderState.size.height.sp,
138+
placeholderVerticalAlign = placeholderState.verticalAlign
129139
)
130140
) { link ->
131-
val transformer = LocalImageTransformer.current
132-
133141
transformer.transform(link)?.let { imageData ->
134142
val intrinsicSize = transformer.intrinsicSize(imageData.painter)
135-
136143
LaunchedEffect(intrinsicSize) {
137144
imageState.setImageSize(intrinsicSize)
138145
}
139-
140146
Image(
141147
painter = imageData.painter,
142148
contentDescription = imageData.contentDescription,
149+
modifier = imageData.modifier,
143150
alignment = imageData.alignment,
144-
modifier = imageData.modifier
151+
contentScale = imageData.contentScale,
152+
alpha = imageData.alpha,
153+
colorFilter = imageData.colorFilter
145154
)
146155
}
147156
}),
148157
onTextLayout = {
149158
layoutResult.value = it
150-
onTextLayout?.invoke(it)
159+
onTextLayout.invoke(it)
151160
}
152161
)
153162
}

multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/ImageTransformer.kt

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,64 @@ import androidx.compose.runtime.Immutable
66
import androidx.compose.ui.Alignment
77
import androidx.compose.ui.Modifier
88
import androidx.compose.ui.geometry.Size
9+
import androidx.compose.ui.geometry.isUnspecified
10+
import androidx.compose.ui.graphics.ColorFilter
11+
import androidx.compose.ui.graphics.DefaultAlpha
912
import androidx.compose.ui.graphics.painter.Painter
13+
import androidx.compose.ui.layout.ContentScale
14+
import androidx.compose.ui.text.PlaceholderVerticalAlign
15+
import androidx.compose.ui.unit.Density
1016

1117
interface ImageTransformer {
18+
/**
19+
* Will retrieve the [ImageData] from an image link/url
20+
*/
1221
@Composable
1322
fun transform(link: String): ImageData?
1423

24+
/**
25+
* Returns the detected intrinsic size of the painter
26+
*/
1527
@Composable
1628
fun intrinsicSize(painter: Painter): Size {
1729
return painter.intrinsicSize
1830
}
31+
32+
/**
33+
* The expected placeholderSize. Note: The same size is shared for all inline images within a single MarkdownText item.
34+
*/
35+
fun placeholderConfig(density: Density, containerSize: Size, intrinsicImageSize: Size): PlaceholderConfig {
36+
return PlaceholderConfig(with(density) {
37+
if (containerSize.isUnspecified) {
38+
Size(180f, 180f)
39+
} else if (intrinsicImageSize.isUnspecified) {
40+
Size(containerSize.width.toSp().value, 180f)
41+
} else {
42+
val width = minOf(intrinsicImageSize.width, containerSize.width)
43+
val height = if (intrinsicImageSize.width < containerSize.width) {
44+
intrinsicImageSize.height
45+
} else {
46+
(intrinsicImageSize.height * containerSize.width) / intrinsicImageSize.width
47+
}
48+
Size(width.toSp().value, height.toSp().value)
49+
}
50+
})
51+
}
1952
}
2053

54+
@Immutable
55+
data class PlaceholderConfig(
56+
val size: Size,
57+
val verticalAlign: PlaceholderVerticalAlign = PlaceholderVerticalAlign.Bottom,
58+
)
59+
2160
@Immutable
2261
data class ImageData(
2362
val painter: Painter,
63+
val modifier: Modifier = Modifier.fillMaxWidth(),
2464
val contentDescription: String? = "Image",
2565
val alignment: Alignment = Alignment.CenterStart,
26-
val modifier: Modifier = Modifier.fillMaxWidth()
66+
val contentScale: ContentScale = ContentScale.Fit,
67+
val alpha: Float = DefaultAlpha,
68+
val colorFilter: ColorFilter? = null,
2769
)

multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/model/MarkdownImageState.kt

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,27 @@ package com.mikepenz.markdown.model
22

33
import androidx.compose.runtime.*
44
import androidx.compose.ui.geometry.Size
5-
import androidx.compose.ui.geometry.isUnspecified
65
import androidx.compose.ui.platform.LocalDensity
76
import androidx.compose.ui.unit.Density
87
import androidx.compose.ui.unit.IntSize
98
import androidx.compose.ui.unit.toSize
109

1110
internal interface MarkdownImageState {
12-
val imageSize: Size
11+
val density: Density
12+
val containerSize: Size
13+
val intrinsicImageSize: Size
1314
fun setContainerSize(intSize: IntSize)
1415
fun setImageSize(size: Size)
1516
}
1617

17-
internal class MarkdownImageStateImpl(private val density: Density) : MarkdownImageState {
18-
19-
private var parentSize by mutableStateOf(Size.Unspecified)
20-
21-
private var intrinsicImageSize by mutableStateOf(Size.Unspecified)
22-
23-
override val imageSize by derivedStateOf {
24-
with(density) {
25-
if (parentSize.isUnspecified) {
26-
Size(180f, 180f)
27-
} else if (intrinsicImageSize.isUnspecified) {
28-
Size(parentSize.width.toSp().value, 180f)
29-
} else {
30-
val width = minOf(intrinsicImageSize.width, parentSize.width)
31-
32-
val height = if (intrinsicImageSize.width < parentSize.width) {
33-
intrinsicImageSize.height
34-
} else {
35-
(intrinsicImageSize.height * parentSize.width) / intrinsicImageSize.width
36-
}
37-
Size(width.toSp().value, height.toSp().value)
38-
}
39-
}
40-
}
18+
internal class MarkdownImageStateImpl(override val density: Density) : MarkdownImageState {
19+
20+
override var containerSize by mutableStateOf(Size.Unspecified)
21+
22+
override var intrinsicImageSize by mutableStateOf(Size.Unspecified)
4123

4224
override fun setContainerSize(intSize: IntSize) {
43-
parentSize = intSize.toSize()
25+
containerSize = intSize.toSize()
4426
}
4527

4628
override fun setImageSize(size: Size) {

0 commit comments

Comments
 (0)