Skip to content

Commit 06b8f2f

Browse files
authored
Change public API: rename onTransformInterval callback, add support for SpannableString (#35)
2 parents fa1ea5b + c4c786a commit 06b8f2f

File tree

8 files changed

+49
-31
lines changed

8 files changed

+49
-31
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ private inline fun getPrivacyPolicyAnnotatedString(
137137
privacyPolicy: String,
138138
crossinline onPrivacyPolicyClick: () -> Unit,
139139
) = intervalAnnotatedString(privacyPolicy)
140-
.asAnnotatedString { id, startsAt, length ->
140+
.asAnnotatedString { id, startsAt, endsAt ->
141141
if (id == PRIVACY_POLICY_LINK_INTERVAL_ID) {
142142
addLink(
143143
clickable =
@@ -154,7 +154,7 @@ private inline fun getPrivacyPolicyAnnotatedString(
154154
linkInteractionListener = { onPrivacyPolicyClick() },
155155
),
156156
start = startsAt,
157-
end = startsAt + length,
157+
end = endsAt,
158158
)
159159
}
160160
}

app/src/main/java/com/justeattakeaway/intervalannotatedstring/sampleapp/compose/CareersPromotionCard.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ fun CareersPromotionCard(
5959
)
6060
Text(
6161
text = intervalAnnotatedString(R.string.careers_promotion_card_text)
62-
.asAnnotatedString { id, startsAt, length ->
63-
val endsAt = startsAt + length
64-
62+
.asAnnotatedString { id, startsAt, endsAt ->
6563
if (id == URL_ANNOTATION_ID) {
6664
addLink(
6765
clickable = LinkAnnotation.Clickable(

app/src/main/java/com/justeattakeaway/intervalannotatedstring/sampleapp/compose/Playground.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,7 @@ private fun buildAnnotatedStringPreview(
113113

114114
return try {
115115
val annotatedString = IntervalAnnotatedString(text)
116-
.asAnnotatedString { id, startsAt, length ->
117-
val endsAt = startsAt + length
118-
116+
.asAnnotatedString { id, startsAt, endsAt ->
119117
if (!coloursLookup.containsKey(id)) {
120118
coloursLookup[id] = Color(
121119
Random.nextInt(256),

app/src/main/java/com/justeattakeaway/intervalannotatedstring/sampleapp/compose/SamplesContent.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,7 @@ private fun SampleContentItemRenderingStringViewer(
177177
) {
178178
Text(
179179
text = intervalAnnotatedString(rawText)
180-
.asAnnotatedString { id, startsAt, length ->
181-
val endsAt = startsAt + length
182-
180+
.asAnnotatedString { id, startsAt, endsAt ->
183181
val annotation = annotationsLookup[id]
184182
when (annotation) {
185183
is SpanStyle ->

intervalannotatedstring/api/intervalannotatedstring.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public final class com/justeattakeaway/intervalannotatedstring/IntervalAnnotated
6161

6262
public final class com/justeattakeaway/intervalannotatedstring/IntervalAnnotatedStringExtsKt {
6363
public static final fun asAnnotatedString-QpJNx2M (Ljava/lang/String;Lkotlin/jvm/functions/Function4;)Landroidx/compose/ui/text/AnnotatedString;
64+
public static final fun asSpannableString-QpJNx2M (Ljava/lang/String;Lkotlin/jvm/functions/Function4;)Landroid/text/SpannableString;
6465
}
6566

6667
public final class com/justeattakeaway/intervalannotatedstring/IntervalAnnotatedStringFactoryKt {

intervalannotatedstring/src/main/java/com/justeattakeaway/intervalannotatedstring/IntervalAnnotatedString.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import com.justeattakeaway.intervalannotatedstring.InlineIntervalSyntaxParser.No
1111
typealias OnTransformText<T> = (text: String) -> T
1212

1313
/**
14-
* Applies interval transformation on the target rendering string implementation.
14+
* Applies interval transformation on the target rendering string implementation at
15+
* inclusive startsAt and exclusive endsAt bounds.
1516
*/
16-
typealias OnTransformInterval<T> = T.(id: String, startsAt: Int, length: Int) -> Unit
17+
typealias OnApplyIntervalTransformation<T> = T.(id: String, startsAt: Int, endsAt: Int) -> Unit
1718

1819
/**
1920
* Primary class for working with interval annotated strings.
@@ -26,14 +27,14 @@ value class IntervalAnnotatedString(
2627
/**
2728
* Performs a transformation of raw text (with embedded intervals metadata) to the target rendering string
2829
* implementation. Can be used to transform the string to an instance of
29-
* [androidx.compose.ui.text.AnnotatedString] or [com.jet.pie2.utils.StyledString].
30+
* [androidx.compose.ui.text.AnnotatedString] or [android.text.SpannableString].
3031
*
3132
* @param T The target type for the transformed string. This is typically a class
3233
* designed to represent a rendering text, such as
33-
* [androidx.compose.ui.text.AnnotatedString] or [com.jet.pie2.utils.StyledString].
34+
* [androidx.compose.ui.text.AnnotatedString] or [android.text.SpannableString].
3435
* The chosen type [T] should generally be constructible from a plain string (via [onTransformText]) and
3536
* should allow for range-based modifications, styling, or annotations
36-
* (via [onTransformInterval]) to be useful with this transformation.
37+
* (via [onApplyIntervalTransformation]) to be useful with this transformation.
3738
*
3839
* @throws NoIdException if the id subsection is empty
3940
* @throws EmptyInlineTextException if the raw text within the interval annotated string area is empty
@@ -43,12 +44,16 @@ value class IntervalAnnotatedString(
4344
@Throws(NoIdException::class, EmptyInlineTextException::class)
4445
inline fun <T> transform(
4546
onTransformText: OnTransformText<T>,
46-
onTransformInterval: OnTransformInterval<T>,
47+
onApplyIntervalTransformation: OnApplyIntervalTransformation<T>,
4748
): T {
4849
val (clearedText, intervals) = InlineIntervalSyntaxParser.parseMetadata(rawString)
4950
val outResult = onTransformText(clearedText)
5051
for (interval in intervals) {
51-
outResult.onTransformInterval(interval.id, interval.startsAt, interval.length)
52+
outResult.onApplyIntervalTransformation(
53+
interval.id,
54+
interval.startsAt,
55+
interval.startsAt + interval.length, // endsAt
56+
)
5257
}
5358
return outResult
5459
}
Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,31 @@
11
package com.justeattakeaway.intervalannotatedstring
22

3+
import android.text.SpannableString
34
import androidx.annotation.AnyThread
45
import androidx.annotation.CheckResult
56
import androidx.compose.ui.text.AnnotatedString
67
import com.justeattakeaway.intervalannotatedstring.InlineIntervalSyntaxParser.EmptyInlineTextException
78
import com.justeattakeaway.intervalannotatedstring.InlineIntervalSyntaxParser.NoIdException
89

910
/**
10-
* Converts an interval annotated string instance to AnnotatedString.
11+
* Converts an interval annotated string instance to [SpannableString].
12+
*
13+
* @see IntervalAnnotatedString
14+
* @see SpannableString
15+
*/
16+
@AnyThread
17+
@CheckResult
18+
@Throws(NoIdException::class, EmptyInlineTextException::class)
19+
inline fun IntervalAnnotatedString.asSpannableString(
20+
onAddIntervalStyle: OnApplyIntervalTransformation<SpannableString>
21+
): SpannableString =
22+
transform(
23+
onTransformText = { SpannableString(it) },
24+
onApplyIntervalTransformation = onAddIntervalStyle,
25+
)
26+
27+
/**
28+
* Converts an interval annotated string instance to [AnnotatedString].
1129
*
1230
* @see IntervalAnnotatedString
1331
* @see AnnotatedString
@@ -16,9 +34,9 @@ import com.justeattakeaway.intervalannotatedstring.InlineIntervalSyntaxParser.No
1634
@CheckResult
1735
@Throws(NoIdException::class, EmptyInlineTextException::class)
1836
inline fun IntervalAnnotatedString.asAnnotatedString(
19-
onAddIntervalStyle: OnTransformInterval<AnnotatedString.Builder>
37+
onAddIntervalStyle: OnApplyIntervalTransformation<AnnotatedString.Builder>
2038
): AnnotatedString =
2139
transform(
2240
onTransformText = { AnnotatedString.Builder(it) },
23-
onTransformInterval = onAddIntervalStyle,
41+
onApplyIntervalTransformation = onAddIntervalStyle,
2442
).toAnnotatedString()

intervalannotatedstring/src/test/java/com/justeattakeaway/intervalannotatedstring/IntervalAnnotatedStringTest.kt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ typealias TestRenderingString = String
1717
@RunWith(JUnit4::class)
1818
class IntervalAnnotatedStringTest {
1919
private val onTransformText = mockk<OnTransformText<TestRenderingString>>()
20-
private val onTransformInterval = mockk<OnTransformInterval<TestRenderingString>>()
20+
private val onApplyIntervalTransformation = mockk<OnApplyIntervalTransformation<TestRenderingString>>()
2121

2222
@Before
2323
fun setUp() {
2424
mockkObject(InlineIntervalSyntaxParser)
2525

2626
every { onTransformText.invoke(any()) } returns TEST_RENDERING_STRING
27-
every { onTransformInterval.invoke(any(), any(), any(), any()) } returns Unit
27+
every { onApplyIntervalTransformation.invoke(any(), any(), any(), any()) } returns Unit
2828
}
2929

3030
@SuppressLint("CheckResult")
@@ -39,7 +39,7 @@ class IntervalAnnotatedStringTest {
3939
)
4040

4141
// When
42-
text.transform(onTransformText, onTransformInterval)
42+
text.transform(onTransformText, onApplyIntervalTransformation)
4343

4444
// Then
4545
verify(exactly = 1) { onTransformText.invoke(eq(TEST_INTERVAL_CLEARED_STRING)) }
@@ -57,27 +57,27 @@ class IntervalAnnotatedStringTest {
5757
)
5858

5959
// When
60-
text.transform(onTransformText, onTransformInterval)
60+
text.transform(onTransformText, onApplyIntervalTransformation)
6161

6262
// Then
6363
verify {
64-
onTransformInterval.invoke(
64+
onApplyIntervalTransformation.invoke(
6565
eq(TEST_RENDERING_STRING),
6666
eq(TEST_INTERVAL_1.id),
6767
eq(TEST_INTERVAL_1.startsAt),
68-
eq(TEST_INTERVAL_1.length),
68+
eq(TEST_INTERVAL_1.startsAt + TEST_INTERVAL_1.length),
6969
)
70-
onTransformInterval.invoke(
70+
onApplyIntervalTransformation.invoke(
7171
eq(TEST_RENDERING_STRING),
7272
eq(TEST_INTERVAL_2.id),
7373
eq(TEST_INTERVAL_2.startsAt),
74-
eq(TEST_INTERVAL_2.length),
74+
eq(TEST_INTERVAL_2.startsAt + TEST_INTERVAL_2.length),
7575
)
76-
onTransformInterval.invoke(
76+
onApplyIntervalTransformation.invoke(
7777
eq(TEST_RENDERING_STRING),
7878
eq(TEST_INTERVAL_3.id),
7979
eq(TEST_INTERVAL_3.startsAt),
80-
eq(TEST_INTERVAL_3.length),
80+
eq(TEST_INTERVAL_3.startsAt + TEST_INTERVAL_3.length),
8181
)
8282
}
8383
}

0 commit comments

Comments
 (0)