Compare commits
4
Commits
1.6.0
..
586852073e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
586852073e | ||
|
|
10a7ff06c1 | ||
|
|
ec28d63656 | ||
|
|
c9b4a958bf |
No files matched your search
@@ -14,6 +14,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.luminance
|
import androidx.compose.ui.graphics.luminance
|
||||||
import androidx.compose.ui.layout.onSizeChanged
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -21,9 +22,12 @@ import androidx.compose.ui.semantics.semantics
|
|||||||
import androidx.compose.ui.semantics.testTagsAsResourceId
|
import androidx.compose.ui.semantics.testTagsAsResourceId
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
import androidx.compose.ui.text.SpanStyle
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.style.LineHeightStyle
|
import androidx.compose.ui.text.style.BaselineShift
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.Density
|
||||||
|
import androidx.compose.ui.unit.isUnspecified
|
||||||
import androidx.compose.ui.unit.IntSize
|
import androidx.compose.ui.unit.IntSize
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.example.research.R
|
import com.example.research.R
|
||||||
@@ -56,8 +60,17 @@ fun ArticleRoute(
|
|||||||
private const val MERGED_BLOCK_MAX_CHARS = 1500
|
private const val MERGED_BLOCK_MAX_CHARS = 1500
|
||||||
private const val MERGED_BLOCK_MAX_ITEMS = 12
|
private const val MERGED_BLOCK_MAX_ITEMS = 12
|
||||||
|
|
||||||
private fun mergeDslBlocks(blocks: List<DslBlock>): List<DslBlock> {
|
private fun mergeDslBlocks(
|
||||||
|
blocks: List<DslBlock>,
|
||||||
|
density: Density,
|
||||||
|
baseStyle: TextStyle,
|
||||||
|
): List<DslBlock> {
|
||||||
if (blocks.size <= MERGED_BLOCK_MAX_ITEMS) return blocks
|
if (blocks.size <= MERGED_BLOCK_MAX_ITEMS) return blocks
|
||||||
|
val gapShift = with(density) {
|
||||||
|
val fontPx =
|
||||||
|
if (baseStyle.fontSize.isUnspecified) 0f else baseStyle.fontSize.toPx()
|
||||||
|
if (fontPx > 0f) 8.dp.toPx() / (0.534f * fontPx) else 0.94f
|
||||||
|
}
|
||||||
val merged = ArrayList<DslBlock>(blocks.size / 4)
|
val merged = ArrayList<DslBlock>(blocks.size / 4)
|
||||||
var i = 0
|
var i = 0
|
||||||
while (i < blocks.size) {
|
while (i < blocks.size) {
|
||||||
@@ -80,6 +93,15 @@ private fun mergeDslBlocks(blocks: List<DslBlock>): List<DslBlock> {
|
|||||||
val more = j + 1 < blocks.size &&
|
val more = j + 1 < blocks.size &&
|
||||||
(j + 1 - i) < MERGED_BLOCK_MAX_ITEMS &&
|
(j + 1 - i) < MERGED_BLOCK_MAX_ITEMS &&
|
||||||
builder.length < MERGED_BLOCK_MAX_CHARS
|
builder.length < MERGED_BLOCK_MAX_CHARS
|
||||||
|
if (more && !blocks[j + 1].continuesPrevious) {
|
||||||
|
val shiftPos = builder.length
|
||||||
|
builder.append('')
|
||||||
|
builder.addStyle(
|
||||||
|
SpanStyle(baselineShift = BaselineShift(-gapShift)),
|
||||||
|
shiftPos,
|
||||||
|
shiftPos + 1
|
||||||
|
)
|
||||||
|
}
|
||||||
if (more) {
|
if (more) {
|
||||||
builder.append('\n')
|
builder.append('\n')
|
||||||
}
|
}
|
||||||
@@ -116,11 +138,7 @@ fun ArticleContent(
|
|||||||
is ArticleState.Success -> {
|
is ArticleState.Success -> {
|
||||||
val articleSaveKey = "${articleState.dictionaryPath}:${articleState.title}"
|
val articleSaveKey = "${articleState.dictionaryPath}:${articleState.title}"
|
||||||
val baseTextStyle = MaterialTheme.typography.bodyLarge.copy(
|
val baseTextStyle = MaterialTheme.typography.bodyLarge.copy(
|
||||||
color = MaterialTheme.colorScheme.onSurface,
|
color = MaterialTheme.colorScheme.onSurface
|
||||||
lineHeightStyle = LineHeightStyle(
|
|
||||||
alignment = LineHeightStyle.Alignment.Proportional,
|
|
||||||
trim = LineHeightStyle.Trim.Both,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
val indentStep = 16.dp
|
val indentStep = 16.dp
|
||||||
|
|
||||||
@@ -180,14 +198,16 @@ fun ArticleContent(
|
|||||||
val isHeavyArticle =
|
val isHeavyArticle =
|
||||||
articleState.dslContent.size > HEAVY_ARTICLE_BLOCK_COUNT
|
articleState.dslContent.size > HEAVY_ARTICLE_BLOCK_COUNT
|
||||||
|
|
||||||
|
val density = LocalDensity.current
|
||||||
val darkTheme = MaterialTheme.colorScheme.background.luminance() < 0.5f
|
val darkTheme = MaterialTheme.colorScheme.background.luminance() < 0.5f
|
||||||
val displayBlocks = remember(
|
val displayBlocks = remember(
|
||||||
articleState.dslContent,
|
articleState.dslContent,
|
||||||
|
density,
|
||||||
baseTextStyle,
|
baseTextStyle,
|
||||||
darkTheme
|
darkTheme
|
||||||
) {
|
) {
|
||||||
val merged =
|
val merged =
|
||||||
mergeDslBlocks(articleState.dslContent)
|
mergeDslBlocks(articleState.dslContent, density, baseTextStyle)
|
||||||
if (darkTheme) {
|
if (darkTheme) {
|
||||||
merged.map {
|
merged.map {
|
||||||
it.copy(text = DslAnnotatedParser.remapForDarkTheme(it.text))
|
it.copy(text = DslAnnotatedParser.remapForDarkTheme(it.text))
|
||||||
@@ -213,24 +233,32 @@ fun ArticleContent(
|
|||||||
},
|
},
|
||||||
contentType = { _, _ -> "article_block" }
|
contentType = { _, _ -> "article_block" }
|
||||||
) { index, block ->
|
) { index, block ->
|
||||||
Box(
|
val followedByContinuation =
|
||||||
modifier = Modifier
|
displayBlocks.getOrNull(index + 1)?.continuesPrevious == true
|
||||||
.padding(start = Spacing.contentStart + indentStep * block.indent)
|
val textContent = @Composable {
|
||||||
) {
|
Box(
|
||||||
ArticleLinkText(
|
|
||||||
block = block,
|
|
||||||
linksEnabled = true,
|
|
||||||
preferDirectHitTesting = isHeavyArticle,
|
|
||||||
style = baseTextStyle,
|
|
||||||
onRefClick = refClickHandler,
|
|
||||||
onTextLayout = {},
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.testTag("article_block_$index")
|
.padding(
|
||||||
.semantics {
|
start = Spacing.contentStart + indentStep * block.indent
|
||||||
testTagsAsResourceId = true
|
)
|
||||||
}
|
.padding(bottom = if (followedByContinuation) 0.dp else 8.dp)
|
||||||
)
|
) {
|
||||||
|
ArticleLinkText(
|
||||||
|
block = block,
|
||||||
|
linksEnabled = true,
|
||||||
|
preferDirectHitTesting = isHeavyArticle,
|
||||||
|
style = baseTextStyle,
|
||||||
|
onRefClick = refClickHandler,
|
||||||
|
onTextLayout = {},
|
||||||
|
modifier = Modifier
|
||||||
|
.testTag("article_block_$index")
|
||||||
|
.semantics {
|
||||||
|
testTagsAsResourceId = true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
textContent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ aboutlibraries = "15.2.0"
|
|||||||
activity_compose = "1.13.0"
|
activity_compose = "1.13.0"
|
||||||
agp = "9.4.1"
|
agp = "9.4.1"
|
||||||
compose_bom = "2026.09.00"
|
compose_bom = "2026.09.00"
|
||||||
core = "1.19.1"
|
core = "1.19.0"
|
||||||
datastore_preferences = "1.2.1"
|
datastore_preferences = "1.2.1"
|
||||||
documentfile = "1.1.0"
|
documentfile = "1.1.0"
|
||||||
kotlin = "2.4.20"
|
kotlin = "2.4.20"
|
||||||
|
|||||||
Reference in new issue
Block a user