mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-04-08 11:58:03 +02:00
Faster Expandable Text calculator.
This commit is contained in:
parent
b13b832696
commit
845c99b798
@ -64,7 +64,7 @@ fun ExpandableRichTextViewer(
|
||||
) {
|
||||
var showFullText by remember { mutableStateOf(false) }
|
||||
|
||||
val whereToCut = remember(content) { ExpandableTextParser().computeWhereToCutIfPostIsTooLong(content) }
|
||||
val whereToCut = remember(content) { ExpandableTextParser.computeWhereToCutIfPostIsTooLong(content) }
|
||||
|
||||
val text by
|
||||
remember(content) {
|
||||
|
@ -24,6 +24,7 @@ import androidx.benchmark.junit4.BenchmarkRule
|
||||
import androidx.benchmark.junit4.measureRepeated
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.vitorpamplona.amethyst.commons.ExpandableTextParser
|
||||
import com.vitorpamplona.amethyst.commons.nthIndexOf
|
||||
import junit.framework.TestCase
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@ -38,18 +39,38 @@ class ExpandableViewComputationBenchmark {
|
||||
fun computeTestCase1() {
|
||||
benchmarkRule.measureRepeated {
|
||||
TestCase.assertEquals(
|
||||
294,
|
||||
ExpandableTextParser().computeWhereToCutIfPostIsTooLong(testCase1),
|
||||
293,
|
||||
testCase1.nthIndexOf('\n', 10),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun computeTestCase2() {
|
||||
benchmarkRule.measureRepeated {
|
||||
TestCase.assertEquals(
|
||||
423,
|
||||
testCase2.nthIndexOf('\n', 10),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun computeTestCase1All() {
|
||||
benchmarkRule.measureRepeated {
|
||||
TestCase.assertEquals(
|
||||
293,
|
||||
ExpandableTextParser.computeWhereToCutIfPostIsTooLong(testCase1),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun computeTestCase2All() {
|
||||
benchmarkRule.measureRepeated {
|
||||
TestCase.assertEquals(
|
||||
355,
|
||||
ExpandableTextParser().computeWhereToCutIfPostIsTooLong(testCase2),
|
||||
ExpandableTextParser.computeWhereToCutIfPostIsTooLong(testCase2),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -22,31 +22,35 @@ package com.vitorpamplona.amethyst.commons
|
||||
|
||||
class ExpandableTextParser {
|
||||
companion object {
|
||||
const val SHORT_TEXT_LENGTH = 350
|
||||
const val SHORTEN_AFTER_LINES = 10
|
||||
}
|
||||
private const val SHORT_TEXT_LENGTH = 350
|
||||
private const val SHORTEN_AFTER_LINES = 10
|
||||
|
||||
fun computeWhereToCutIfPostIsTooLong(content: String): Int {
|
||||
// Cuts the text in the first space or new line after SHORT_TEXT_LENGTH characters
|
||||
val firstSpaceAfterCut =
|
||||
content.indexOf(' ', SHORT_TEXT_LENGTH).let { if (it < 0) content.length else it }
|
||||
val firstNewLineAfterCut =
|
||||
content.indexOf('\n', SHORT_TEXT_LENGTH).let { if (it < 0) content.length else it }
|
||||
fun computeWhereToCutIfPostIsTooLong(content: String): Int {
|
||||
// Cuts the text in the first space or new line after SHORT_TEXT_LENGTH characters
|
||||
val firstSpaceAfterCut =
|
||||
content.indexOf(' ', SHORT_TEXT_LENGTH).let { if (it < 0) content.length else it }
|
||||
val firstNewLineAfterCut =
|
||||
content.indexOf('\n', SHORT_TEXT_LENGTH).let { if (it < 0) content.length else it }
|
||||
val firstLineAfterLineLimits =
|
||||
content.nthIndexOf('\n', SHORTEN_AFTER_LINES).let { if (it < 0) content.length else it }
|
||||
|
||||
// or after SHORTEN_AFTER_LINES lines
|
||||
val numberOfLines = content.count { it == '\n' }
|
||||
|
||||
var charactersInLines = minOf(firstSpaceAfterCut, firstNewLineAfterCut)
|
||||
|
||||
if (numberOfLines > SHORTEN_AFTER_LINES) {
|
||||
val shortContent = content.lines().take(SHORTEN_AFTER_LINES)
|
||||
charactersInLines = 0
|
||||
for (line in shortContent) {
|
||||
// +1 because new line character is omitted from .lines
|
||||
charactersInLines += (line.length + 1)
|
||||
}
|
||||
return minOf(firstSpaceAfterCut, firstNewLineAfterCut, firstLineAfterLineLimits)
|
||||
}
|
||||
|
||||
return minOf(firstSpaceAfterCut, firstNewLineAfterCut, charactersInLines)
|
||||
}
|
||||
}
|
||||
|
||||
fun String.nthIndexOf(
|
||||
ch: Char,
|
||||
N: Int,
|
||||
): Int {
|
||||
var occur = N
|
||||
var pos = -1
|
||||
|
||||
while (occur > 0) {
|
||||
// calling the native function multiple times is faster than looping just once
|
||||
pos = indexOf(ch, pos + 1)
|
||||
occur--
|
||||
}
|
||||
|
||||
return if (occur == 0) pos else -1
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user