Add Status & Location to the Lexicon Detail & Search
This commit is contained in:
parent
418224a482
commit
c2e642292a
13 changed files with 218 additions and 40 deletions
|
|
@ -28,13 +28,15 @@ class LexiconParser @Inject constructor(
|
|||
|
||||
row is List<*> -> {
|
||||
val name = row.getOrNull(sheetStructure.name) as? String
|
||||
val diminutive = row.getOrNull(sheetStructure.diminutive) as? String?
|
||||
val gender = row.getOrNull(sheetStructure.gender) as? String?
|
||||
val race = row.getOrNull(sheetStructure.race) as? String?
|
||||
val portrait = row.getOrNull(sheetStructure.portrait) as? String?
|
||||
val description = row.getOrNull(sheetStructure.description) as? String?
|
||||
val history = row.getOrNull(sheetStructure.history) as? String?
|
||||
val tags = row.getOrNull(sheetStructure.tags) as? String?
|
||||
val diminutive = row.getOrNull(sheetStructure.diminutive) as? String
|
||||
val gender = row.getOrNull(sheetStructure.gender) as? String
|
||||
val race = row.getOrNull(sheetStructure.race) as? String
|
||||
val portrait = row.getOrNull(sheetStructure.portrait) as? String
|
||||
val status = row.getOrNull(sheetStructure.status) as? String
|
||||
val location = row.getOrNull(sheetStructure.location) as? String
|
||||
val description = row.getOrNull(sheetStructure.description) as? String
|
||||
val history = row.getOrNull(sheetStructure.history) as? String
|
||||
val tags = row.getOrNull(sheetStructure.tags) as? String
|
||||
|
||||
if (name != null) {
|
||||
Lexicon(
|
||||
|
|
@ -45,6 +47,8 @@ class LexiconParser @Inject constructor(
|
|||
gender = genderParser.parse(gender),
|
||||
race = raceParser.parser(race),
|
||||
portrait = portraitParser.parse(portrait),
|
||||
status = status?.takeIf { it.isNotBlank() },
|
||||
location = location?.takeIf { it.isNotBlank() },
|
||||
description = description?.takeIf { it.isNotBlank() },
|
||||
history = history?.takeIf { it.isNotBlank() },
|
||||
tags = tags?.takeIf { it.isNotBlank() },
|
||||
|
|
@ -63,10 +67,12 @@ class LexiconParser @Inject constructor(
|
|||
private val Map<String, Int>.diminutive: Int get() = getValue(COLUMNS[1])
|
||||
private val Map<String, Int>.gender: Int get() = getValue(COLUMNS[2])
|
||||
private val Map<String, Int>.race: Int get() = getValue(COLUMNS[3])
|
||||
private val Map<String, Int>.portrait: Int get() = getValue(COLUMNS[4])
|
||||
private val Map<String, Int>.description: Int get() = getValue(COLUMNS[5])
|
||||
private val Map<String, Int>.history: Int get() = getValue(COLUMNS[6])
|
||||
private val Map<String, Int>.tags: Int get() = getValue(COLUMNS[7])
|
||||
private val Map<String, Int>.status: Int get() = getValue(COLUMNS[4])
|
||||
private val Map<String, Int>.location: Int get() = getValue(COLUMNS[5])
|
||||
private val Map<String, Int>.portrait: Int get() = getValue(COLUMNS[6])
|
||||
private val Map<String, Int>.description: Int get() = getValue(COLUMNS[7])
|
||||
private val Map<String, Int>.history: Int get() = getValue(COLUMNS[8])
|
||||
private val Map<String, Int>.tags: Int get() = getValue(COLUMNS[9])
|
||||
|
||||
companion object {
|
||||
private val COLUMNS = listOf(
|
||||
|
|
@ -74,6 +80,8 @@ class LexiconParser @Inject constructor(
|
|||
"Diminutif",
|
||||
"Sexe",
|
||||
"Race",
|
||||
"Statut",
|
||||
"Localisation",
|
||||
"Portrait",
|
||||
"Description",
|
||||
"Histoire",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ data class Lexicon(
|
|||
val diminutive: String?,
|
||||
val gender: Gender,
|
||||
val race: Race,
|
||||
val status: String?,
|
||||
val location: String?,
|
||||
val portrait: List<Uri>,
|
||||
val description: String?,
|
||||
val history: String?,
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
|
|
@ -45,6 +47,7 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -70,6 +73,8 @@ data class LexiconDetailUio(
|
|||
val diminutive: String?,
|
||||
val gender: Lexicon.Gender,
|
||||
val race: Lexicon.Race,
|
||||
val status: String?,
|
||||
val location: String?,
|
||||
val portrait: List<Uri>,
|
||||
val description: String?,
|
||||
val history: String?,
|
||||
|
|
@ -86,6 +91,8 @@ data class AnnotatedLexiconDetailUio(
|
|||
val gender: AnnotatedString,
|
||||
val race: AnnotatedString,
|
||||
val portrait: List<Uri>,
|
||||
val status: AnnotatedString?,
|
||||
val location: AnnotatedString?,
|
||||
val description: AnnotatedString?,
|
||||
val history: AnnotatedString?,
|
||||
val tags: AnnotatedString?
|
||||
|
|
@ -130,6 +137,12 @@ fun LexiconDetailUio.annotate(): AnnotatedLexiconDetailUio {
|
|||
description = description?.let { description ->
|
||||
highlightRegex.annotatedString(input = description, spanStyle = highlight)
|
||||
},
|
||||
status = status?.let { status ->
|
||||
highlightRegex.annotatedString(input = status, spanStyle = highlight)
|
||||
},
|
||||
location = location?.let { location ->
|
||||
highlightRegex.annotatedString(input = location, spanStyle = highlight)
|
||||
},
|
||||
history = history?.let { history ->
|
||||
highlightRegex.annotatedString(input = history, spanStyle = highlight)
|
||||
},
|
||||
|
|
@ -170,6 +183,9 @@ private fun LexiconDetailContent(
|
|||
val colorScheme = MaterialTheme.colorScheme
|
||||
val typography = MaterialTheme.typography
|
||||
val annotatedItem = item.value.annotate()
|
||||
val backgroundUri = remember(annotatedItem) {
|
||||
annotatedItem.portrait.firstOrNull()
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
modifier = modifier,
|
||||
|
|
@ -203,7 +219,7 @@ private fun LexiconDetailContent(
|
|||
Surface(
|
||||
modifier = Modifier.padding(paddingValues = paddingValues),
|
||||
) {
|
||||
annotatedItem.portrait.firstOrNull()?.let { uri ->
|
||||
backgroundUri?.let { uri ->
|
||||
BackgroundImage(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -216,7 +232,10 @@ private fun LexiconDetailContent(
|
|||
modifier = Modifier
|
||||
.verticalScroll(state)
|
||||
.padding(
|
||||
top = MaterialTheme.lexicon.dimens.detailPadding,
|
||||
top = when (backgroundUri) {
|
||||
null -> 16.dp
|
||||
else -> MaterialTheme.lexicon.dimens.detailPadding
|
||||
},
|
||||
bottom = 16.dp,
|
||||
),
|
||||
verticalArrangement = Arrangement.spacedBy(space = 4.dp),
|
||||
|
|
@ -258,6 +277,62 @@ private fun LexiconDetailContent(
|
|||
)
|
||||
}
|
||||
|
||||
if (annotatedItem.status != null || annotatedItem.location != null) {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
annotatedItem.status?.let {
|
||||
Row(
|
||||
modifier = Modifier.padding(start = 16.dp, end = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = typography.bodyMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(id = R.string.detail_status),
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = remember {
|
||||
typography.bodyMedium.copy(
|
||||
shadow = Shadow(
|
||||
color = colorScheme.surface.copy(alpha = 0.5f),
|
||||
offset = Offset(x = 1f, y = 1f),
|
||||
)
|
||||
)
|
||||
},
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
annotatedItem.location?.let {
|
||||
Row(
|
||||
modifier = Modifier.padding(start = 16.dp, end = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = typography.bodyMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(id = R.string.detail_location),
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = remember {
|
||||
typography.bodyMedium.copy(
|
||||
shadow = Shadow(
|
||||
color = colorScheme.surface.copy(alpha = 0.5f),
|
||||
offset = Offset(x = 1f, y = 1f),
|
||||
)
|
||||
)
|
||||
},
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
annotatedItem.description?.let {
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp),
|
||||
|
|
@ -359,6 +434,8 @@ private fun LexiconDetailPreview() {
|
|||
diminutive = "./ Bru",
|
||||
gender = Lexicon.Gender.FEMALE,
|
||||
race = Lexicon.Race.HALF_ORC,
|
||||
status = "Vivante",
|
||||
location = "Manoir Durst",
|
||||
portrait = listOf(
|
||||
Uri.parse("https://cdnb.artstation.com/p/assets/images/images/003/024/889/large/bayard-wu-0716.jpg?1468642855"),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ class LexiconDetailViewModel @Inject constructor(
|
|||
gender = source.gender,
|
||||
race = source.race,
|
||||
portrait = source.portrait,
|
||||
status = source.status,
|
||||
location = source.location,
|
||||
description = source.description,
|
||||
history = source.history,
|
||||
tags = source.tags,
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ private fun LexiconScreenContent(
|
|||
state = lazyColumnState,
|
||||
contentPadding = MaterialTheme.lexicon.dimens.itemListPadding,
|
||||
) {
|
||||
items(count = 6) {
|
||||
items(count = 16) {
|
||||
LexiconItem(
|
||||
modifier = Modifier.cell(),
|
||||
item = LexiconItemUio.preview(placeholder = true),
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import com.pixelized.rplexicon.utilitary.extentions.annotatedString
|
|||
import com.pixelized.rplexicon.utilitary.extentions.finderRegex
|
||||
import com.pixelized.rplexicon.utilitary.extentions.foldAll
|
||||
import com.pixelized.rplexicon.utilitary.extentions.highlightRegex
|
||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||
|
||||
@Stable
|
||||
class SearchItemUio(
|
||||
|
|
@ -46,6 +47,8 @@ class SearchItemUio(
|
|||
val diminutive: String?,
|
||||
val gender: Lexicon.Gender,
|
||||
val race: Lexicon.Race,
|
||||
val status: String?,
|
||||
val location: String?,
|
||||
val description: String?,
|
||||
val history: String?,
|
||||
val tags: String?,
|
||||
|
|
@ -64,7 +67,7 @@ class SearchItemUio(
|
|||
"D’une nature simple et honnête, elle ne mâche pas ses mots et ne dissimule généralement pas ses pensées. Son intelligence modeste est plus le reflet d’un manque d’éducation et d’une capacité limitée à gérer ses émotions qu’à une débilité congénitale.\n" +
|
||||
"Elle voue à la force un culte car c’est par son expression qu’elle se sent vraiment vivante et éprouve de grandes difficultés vis à vis de ceux qu’elle nomme foshnu (bébé, chouineur en commun).",
|
||||
history: String? = null,
|
||||
search: String = "",
|
||||
search: String = " ",
|
||||
highlightGender: Boolean = false,
|
||||
highlightRace: Boolean = false,
|
||||
): SearchItemUio {
|
||||
|
|
@ -74,6 +77,8 @@ class SearchItemUio(
|
|||
diminutive = diminutive,
|
||||
gender = gender,
|
||||
race = race,
|
||||
status = null,
|
||||
location = null,
|
||||
description = description,
|
||||
history = history,
|
||||
tags = null,
|
||||
|
|
@ -92,6 +97,8 @@ class AnnotatedSearchItemUio(
|
|||
val diminutive: AnnotatedString?,
|
||||
val gender: AnnotatedString,
|
||||
val race: AnnotatedString,
|
||||
val status: AnnotatedString?,
|
||||
val location: AnnotatedString?,
|
||||
val description: AnnotatedString?,
|
||||
val history: AnnotatedString?,
|
||||
val tags: AnnotatedString?,
|
||||
|
|
@ -102,7 +109,9 @@ class AnnotatedSearchItemUio(
|
|||
private fun SearchItemUio.annotate(): AnnotatedSearchItemUio {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val highlight = remember { SpanStyle(color = colorScheme.primary) }
|
||||
val trimmedSearch = remember(search) { search.trim() }
|
||||
val trimmedSearch = remember(search) {
|
||||
search.split(" ").mapNotNull { it.trim().takeIf { trim -> trim.isNotEmpty() } }
|
||||
}
|
||||
val highlightRegex = remember(search) { trimmedSearch.highlightRegex }
|
||||
val finderRegex = remember(search) { trimmedSearch.finderRegex }
|
||||
val gender = stringResource(id = gender, short = true)
|
||||
|
|
@ -140,6 +149,12 @@ private fun SearchItemUio.annotate(): AnnotatedSearchItemUio {
|
|||
}
|
||||
)
|
||||
},
|
||||
status = finderRegex?.foldAll(status)?.let { status ->
|
||||
highlightRegex?.annotatedString(status, spanStyle = highlight)
|
||||
},
|
||||
location = finderRegex?.foldAll(location)?.let { location ->
|
||||
highlightRegex?.annotatedString(location, spanStyle = highlight)
|
||||
},
|
||||
description = finderRegex?.foldAll(description)?.let { description ->
|
||||
highlightRegex?.annotatedString(description, spanStyle = highlight)
|
||||
},
|
||||
|
|
@ -160,7 +175,7 @@ fun SearchItem(
|
|||
item: SearchItemUio,
|
||||
) {
|
||||
val typography = MaterialTheme.typography
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val colorScheme = MaterialTheme.lexicon.colorScheme
|
||||
val annotatedItem = item.annotate()
|
||||
|
||||
Box(
|
||||
|
|
@ -179,7 +194,8 @@ fun SearchItem(
|
|||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = remember { typography.bodyLarge.copy(fontWeight = FontWeight.Bold) },
|
||||
style = typography.bodyLarge,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
text = annotatedItem.name,
|
||||
)
|
||||
|
|
@ -199,13 +215,15 @@ fun SearchItem(
|
|||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = remember { typography.labelMedium.copy(fontStyle = FontStyle.Italic) },
|
||||
style = typography.labelMedium,
|
||||
fontStyle = FontStyle.Italic,
|
||||
maxLines = 1,
|
||||
text = annotatedItem.gender
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = remember { typography.labelMedium.copy(fontStyle = FontStyle.Italic) },
|
||||
style = typography.labelMedium,
|
||||
fontStyle = FontStyle.Italic,
|
||||
maxLines = 1,
|
||||
text = annotatedItem.race
|
||||
)
|
||||
|
|
@ -214,7 +232,7 @@ fun SearchItem(
|
|||
Column(
|
||||
modifier = Modifier.drawBehind {
|
||||
drawLine(
|
||||
color = colorScheme.primary,
|
||||
color = colorScheme.base.primary,
|
||||
start = Offset(0f, 0f),
|
||||
end = Offset(0f, size.height),
|
||||
strokeWidth = 2.dp.toPx()
|
||||
|
|
@ -222,16 +240,52 @@ fun SearchItem(
|
|||
},
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
annotatedItem.status?.let {
|
||||
Row(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
style = typography.labelSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(id = R.string.search_item_status),
|
||||
)
|
||||
Text(
|
||||
style = typography.labelSmall,
|
||||
fontStyle = FontStyle.Italic,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
annotatedItem.location?.let {
|
||||
Row(
|
||||
modifier = Modifier.padding(start = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
style = typography.labelSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(id = R.string.search_item_location),
|
||||
)
|
||||
Text(
|
||||
style = typography.labelSmall,
|
||||
fontStyle = FontStyle.Italic,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
annotatedItem.description?.let {
|
||||
Column(
|
||||
modifier = Modifier.padding(start = 8.dp)
|
||||
) {
|
||||
Text(
|
||||
style = remember { typography.labelSmall.copy(fontWeight = FontWeight.Bold) },
|
||||
style = typography.labelSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(id = R.string.search_item_description),
|
||||
)
|
||||
Text(
|
||||
style = typography.labelSmall,
|
||||
fontStyle = FontStyle.Italic,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
|
|
@ -241,11 +295,13 @@ fun SearchItem(
|
|||
modifier = Modifier.padding(start = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
style = remember { typography.labelSmall.copy(fontWeight = FontWeight.Bold) },
|
||||
style = typography.labelSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(id = R.string.search_item_history),
|
||||
)
|
||||
Text(
|
||||
style = typography.labelSmall,
|
||||
fontStyle = FontStyle.Italic,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
|
|
@ -255,11 +311,13 @@ fun SearchItem(
|
|||
modifier = Modifier.padding(start = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
style = remember { typography.labelSmall.copy(fontWeight = FontWeight.Bold) },
|
||||
style = typography.labelSmall,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = stringResource(id = R.string.search_item_tags),
|
||||
)
|
||||
Text(
|
||||
style = typography.labelSmall,
|
||||
fontStyle = FontStyle.Italic,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,15 +52,19 @@ class SearchViewModel @Inject constructor(
|
|||
data.filter { item ->
|
||||
val gender = _gender.value?.let { it == item.gender }
|
||||
val race = _race.value?.let { it == item.race }
|
||||
val search = _search.value.takeIf { it.isNotEmpty() }?.trim()?.let { search ->
|
||||
val name = item.name.contains(search, true)
|
||||
val diminutive = item.diminutive?.contains(search, true) == true
|
||||
val description = item.description?.contains(search, true) == true
|
||||
val history = item.history?.contains(search, true) == true
|
||||
val tag = item.tags?.contains(search, true) == true
|
||||
name || diminutive || description || history || tag
|
||||
val search = _search.value.split(" ").mapNotNull {
|
||||
it.takeIf { it.isNotEmpty() }?.trim()?.let { search ->
|
||||
val name = item.name.contains(search, true)
|
||||
val diminutive = item.diminutive?.contains(search, true) == true
|
||||
val status = item.status?.contains(search, true) == true
|
||||
val location = item.location?.contains(search, true) == true
|
||||
val description = item.description?.contains(search, true) == true
|
||||
val history = item.history?.contains(search, true) == true
|
||||
val tag = item.tags?.contains(search, true) == true
|
||||
name || diminutive || status || location || description || history || tag
|
||||
}
|
||||
}
|
||||
(gender == null || gender) && (race == null || race) && (search == null || search)
|
||||
(gender == null || gender) && (race == null || race) && (search.all { it })
|
||||
}.map {
|
||||
it.toSearchUio()
|
||||
}.sortedBy {
|
||||
|
|
@ -78,6 +82,8 @@ class SearchViewModel @Inject constructor(
|
|||
diminutive = diminutive?.takeIf { it.isNotBlank() }?.let { "./ $it" },
|
||||
gender = this.gender,
|
||||
race = this.race,
|
||||
status = this.status,
|
||||
location = this.location,
|
||||
description = this.description,
|
||||
history = this.history,
|
||||
search = search,
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ fun LocationScreen(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterialApi::class)
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun LocationContent(
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ fun QuestListScreen(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterialApi::class)
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun QuestListContent(
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -103,7 +103,7 @@ private fun QuestListContent(
|
|||
state = lazyColumnState,
|
||||
contentPadding = MaterialTheme.lexicon.dimens.itemListPadding,
|
||||
) {
|
||||
items(count = 2) {
|
||||
items(count = 4) {
|
||||
QuestItem(
|
||||
modifier = Modifier.cell(),
|
||||
item = QuestItemUio.preview(placeHolder = true),
|
||||
|
|
|
|||
|
|
@ -11,14 +11,20 @@ fun Regex?.foldAll(
|
|||
this?.findAll(it, startIndex)?.fold("") { acc, item ->
|
||||
val dummy = acc + when {
|
||||
previous == null && item.range.first == 0 -> item.value
|
||||
previous == null && item.range.first != 0 -> "...${item.value}"
|
||||
previous == null && item.range.first != 0 -> "... ${item.value}"
|
||||
item.range.first <= (previous?.range?.last ?: 0) + 1 -> item.value
|
||||
else -> " ... ${item.value}"
|
||||
}
|
||||
previous = item
|
||||
dummy
|
||||
}
|
||||
}?.takeIf { it.isNotEmpty() }?.let { "$it..." }
|
||||
}?.takeIf { it.isNotEmpty() }?.let {
|
||||
if (it.length == input.length) {
|
||||
it
|
||||
} else {
|
||||
"$it..."
|
||||
}
|
||||
}
|
||||
|
||||
fun Regex?.annotatedSpan(
|
||||
input: String,
|
||||
|
|
|
|||
|
|
@ -22,14 +22,25 @@ val String?.highlightRegex: Regex?
|
|||
}
|
||||
|
||||
@Stable
|
||||
val String?.finderRegex: Regex?
|
||||
get() = this?.takeIf { it.isNotEmpty() }?.let {
|
||||
val List<String>.highlightRegex: Regex?
|
||||
get() = if (isNotEmpty()) {
|
||||
Regex(
|
||||
pattern = "\\w*.{0,30}${Regex.escape(it)}\\w*.{0,30}\\w*",
|
||||
pattern = joinToString(separator = "|") { "(${Regex.escape(it)})" },
|
||||
option = RegexOption.IGNORE_CASE,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
@Stable
|
||||
val List<String>.finderRegex: Regex?
|
||||
get() = if (isNotEmpty()) {
|
||||
Regex(
|
||||
pattern = joinToString(separator = "|") { "(\\w*.{0,30}${Regex.escape(it)}\\w*.{0,30}\\w*)" },
|
||||
option = RegexOption.IGNORE_CASE,
|
||||
)
|
||||
} else null
|
||||
|
||||
fun String?.toUriOrNull(): Uri? = try {
|
||||
this?.takeIf { it.isNotBlank() }?.toUri()
|
||||
} catch (_: Exception) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue