Remove Int as id for LexiconItem

This commit is contained in:
Thomas Andres Gomez 2023-11-12 18:30:27 +01:00
parent 003390e844
commit 3880807372
11 changed files with 73 additions and 55 deletions

View file

@ -5,8 +5,7 @@ import androidx.compose.runtime.Stable
@Stable @Stable
data class Lexicon( data class Lexicon(
val id: Int, val id: String,
val sheetIndex: Int,
val name: String, val name: String,
val diminutive: String?, val diminutive: String?,
val gender: Gender, val gender: Gender,

View file

@ -12,7 +12,7 @@ class LexiconParser @Inject constructor(
) { ) {
@Throws(IncompatibleSheetStructure::class) @Throws(IncompatibleSheetStructure::class)
fun parse(sheet: ValueRange): List<Lexicon> = parserScope { fun parse(sheet: ValueRange): List<Lexicon> = parserScope {
var id = 0 val ids = hashMapOf<String, Int>()
val lexicons = mutableListOf<Lexicon>() val lexicons = mutableListOf<Lexicon>()
sheet.forEachRowIndexed { index, row -> sheet.forEachRowIndexed { index, row ->
@ -22,9 +22,9 @@ class LexiconParser @Inject constructor(
else -> { else -> {
val name = row.parse(column = NAME) val name = row.parse(column = NAME)
if (name != null) { if (name != null) {
ids[name] = ids.getOrDefault(name, 0) + 1
val lexicon = Lexicon( val lexicon = Lexicon(
id = id++, id = "$name-${ids[name]}",
sheetIndex = index,
name = name, name = name,
diminutive = row.parse(column = SHORT), diminutive = row.parse(column = SHORT),
gender = genderParser.parse(row.parse(column = GENDER)), gender = genderParser.parse(row.parse(column = GENDER)),

View file

@ -22,7 +22,11 @@ class LexiconRepository @Inject constructor(
var lastSuccessFullUpdate: Update = Update.INITIAL var lastSuccessFullUpdate: Update = Update.INITIAL
private set private set
fun findId(name: String?): Int? { fun find(id: String?): Lexicon? {
return id?.let { _data.value.firstOrNull { item -> item.id == it } }
}
fun findId(name: String?): String? {
return name?.let { _data.value.firstOrNull { item -> item.name == it }?.id } return name?.let { _data.value.firstOrNull { item -> item.name == it }?.id }
} }

View file

@ -33,7 +33,7 @@ val LEXICON_DETAIL_ROUTE = ROUTE +
@Stable @Stable
@Immutable @Immutable
data class LexiconDetailArgument( data class LexiconDetailArgument(
val id: Int, val id: String,
val highlight: String?, val highlight: String?,
val race: Lexicon.Race, val race: Lexicon.Race,
val highlightRace: Boolean, val highlightRace: Boolean,
@ -61,7 +61,7 @@ fun NavGraphBuilder.composableLexiconDetail() {
route = LEXICON_DETAIL_ROUTE, route = LEXICON_DETAIL_ROUTE,
arguments = listOf( arguments = listOf(
navArgument(name = ARG_ID) { navArgument(name = ARG_ID) {
type = NavType.IntType type = NavType.StringType
}, },
navArgument(name = ARG_HIGHLIGHT) { navArgument(name = ARG_HIGHLIGHT) {
type = NavType.StringType type = NavType.StringType
@ -87,7 +87,7 @@ fun NavGraphBuilder.composableLexiconDetail() {
} }
fun NavHostController.navigateToLexiconDetail( fun NavHostController.navigateToLexiconDetail(
id: Int, id: String,
highlight: String? = null, highlight: String? = null,
race: Lexicon.Race? = null, race: Lexicon.Race? = null,
gender: Lexicon.Gender? = null, gender: Lexicon.Gender? = null,

View file

@ -106,6 +106,7 @@ data class AnnotatedLexiconDetailUio(
@Stable @Stable
fun LexiconDetailUio.annotate(): AnnotatedLexiconDetailUio { fun LexiconDetailUio.annotate(): AnnotatedLexiconDetailUio {
val colorScheme = MaterialTheme.colorScheme val colorScheme = MaterialTheme.colorScheme
val typography = MaterialTheme.lexicon.typography
val highlight = remember { SpanStyle(color = colorScheme.primary) } val highlight = remember { SpanStyle(color = colorScheme.primary) }
val trimmedSearch = remember(search) { search.searchCriterion() } val trimmedSearch = remember(search) { search.searchCriterion() }
val highlightRegex = remember(search) { trimmedSearch.highlightRegex } val highlightRegex = remember(search) { trimmedSearch.highlightRegex }
@ -117,10 +118,16 @@ fun LexiconDetailUio.annotate(): AnnotatedLexiconDetailUio {
portrait = portrait, portrait = portrait,
name = AnnotatedString( name = AnnotatedString(
text = name, text = name,
spanStyles = highlightRegex?.annotatedSpan( spanStyles = (highlightRegex?.annotatedSpan(
input = name, input = name,
spanStyle = highlight, spanStyle = highlight,
) ?: emptyList() ) ?: emptyList()) + listOf(
AnnotatedString.Range(
item = typography.headlineSmallDropCap,
start = 0,
end = 1,
)
)
), ),
diminutive = diminutive?.let { diminutive = diminutive?.let {
highlightRegex.annotatedString(input = it, spanStyle = highlight) highlightRegex.annotatedString(input = it, spanStyle = highlight)
@ -165,7 +172,9 @@ fun LexiconDetailScreen(
) { ) {
val screen = LocalScreenNavHost.current val screen = LocalScreenNavHost.current
Surface { Surface(
modifier = Modifier.fillMaxSize(),
) {
LexiconDetailContent( LexiconDetailContent(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
item = viewModel.character, item = viewModel.character,
@ -186,7 +195,7 @@ fun LexiconDetailScreen(
private fun LexiconDetailContent( private fun LexiconDetailContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
state: ScrollState = rememberScrollState(), state: ScrollState = rememberScrollState(),
item: State<LexiconDetailUio>, item: State<LexiconDetailUio?>,
haveCharacterSheet: State<Boolean>, haveCharacterSheet: State<Boolean>,
onBack: () -> Unit, onBack: () -> Unit,
onCharacterSheet: (String) -> Unit, onCharacterSheet: (String) -> Unit,
@ -194,9 +203,9 @@ private fun LexiconDetailContent(
) { ) {
val colorScheme = MaterialTheme.colorScheme val colorScheme = MaterialTheme.colorScheme
val typography = MaterialTheme.typography val typography = MaterialTheme.typography
val annotatedItem = item.value.annotate() val annotatedItem = item.value?.annotate()
val backgroundUri = remember(annotatedItem) { val backgroundUri = remember(annotatedItem) {
annotatedItem.portrait.firstOrNull() annotatedItem?.portrait?.firstOrNull()
} }
Scaffold( Scaffold(
@ -215,7 +224,7 @@ private fun LexiconDetailContent(
}, },
actions = { actions = {
AnimatedVisibility(visible = haveCharacterSheet.value) { AnimatedVisibility(visible = haveCharacterSheet.value) {
IconButton(onClick = { onCharacterSheet(item.value.name) }) { IconButton(onClick = { item.value?.name?.let(onCharacterSheet) }) {
Icon( Icon(
painter = painterResource(id = R.drawable.ic_d20_24), painter = painterResource(id = R.drawable.ic_d20_24),
contentDescription = null contentDescription = null
@ -257,14 +266,14 @@ private fun LexiconDetailContent(
modifier = Modifier.padding(horizontal = 16.dp), modifier = Modifier.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp) horizontalArrangement = Arrangement.spacedBy(4.dp)
) { ) {
annotatedItem.name.let { annotatedItem?.name?.let {
Text( Text(
modifier = Modifier.alignByBaseline(), modifier = Modifier.alignByBaseline(),
style = typography.headlineSmall, style = typography.headlineSmall,
text = it, text = it,
) )
} }
annotatedItem.diminutive?.let { annotatedItem?.diminutive?.let {
Text( Text(
modifier = Modifier.alignByBaseline(), modifier = Modifier.alignByBaseline(),
style = typography.labelMedium, style = typography.labelMedium,
@ -278,23 +287,27 @@ private fun LexiconDetailContent(
modifier = Modifier.padding(horizontal = 16.dp), modifier = Modifier.padding(horizontal = 16.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp) horizontalArrangement = Arrangement.spacedBy(4.dp)
) { ) {
Text( annotatedItem?.gender?.let {
style = typography.labelMedium, Text(
fontStyle = FontStyle.Italic, style = typography.labelMedium,
text = annotatedItem.gender, fontStyle = FontStyle.Italic,
) text = it,
Text( )
style = typography.labelMedium, }
fontStyle = FontStyle.Italic, annotatedItem?.race?.let {
text = annotatedItem.race, Text(
) style = typography.labelMedium,
fontStyle = FontStyle.Italic,
text = it,
)
}
} }
if (annotatedItem.status != null || annotatedItem.location != null) { if (annotatedItem?.status != null || annotatedItem?.location != null) {
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
} }
annotatedItem.status?.let { annotatedItem?.status?.let {
Row( Row(
modifier = Modifier.padding(start = 16.dp, end = 16.dp), modifier = Modifier.padding(start = 16.dp, end = 16.dp),
horizontalArrangement = Arrangement.spacedBy(space = 4.dp), horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
@ -320,7 +333,7 @@ private fun LexiconDetailContent(
} }
} }
annotatedItem.location?.let { annotatedItem?.location?.let {
Row( Row(
modifier = Modifier.padding(start = 16.dp, end = 16.dp), modifier = Modifier.padding(start = 16.dp, end = 16.dp),
horizontalArrangement = Arrangement.spacedBy(space = 4.dp), horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
@ -346,7 +359,7 @@ private fun LexiconDetailContent(
} }
} }
annotatedItem.description?.let { annotatedItem?.description?.let {
Text( Text(
modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp), modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp),
style = typography.titleMedium, style = typography.titleMedium,
@ -366,7 +379,7 @@ private fun LexiconDetailContent(
) )
} }
annotatedItem.history?.let { annotatedItem?.history?.let {
Text( Text(
modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp), modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp),
style = typography.titleMedium, style = typography.titleMedium,
@ -379,7 +392,7 @@ private fun LexiconDetailContent(
) )
} }
if (annotatedItem.portrait.isNotEmpty()) { if (annotatedItem?.portrait?.isNotEmpty() == true) {
val maxSize = rememberPortraitWidth() val maxSize = rememberPortraitWidth()
Text( Text(
modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp), modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp),
@ -407,7 +420,7 @@ private fun LexiconDetailContent(
} }
} }
annotatedItem.tags?.let { annotatedItem?.tags?.let {
Text( Text(
modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp), modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp),
style = typography.labelSmall, style = typography.labelSmall,
@ -454,7 +467,7 @@ private fun LexiconDetailPreview() {
description = "Brulkhai, ou plus simplement Bru, est solidement bâti. Elle mesure 192 cm pour 110 kg de muscles lorsquelle est en bonne santé. Elle a les cheveux châtains, les yeux noisettes et la peau couleur gris-vert typique de son espèce. Dun tempérament taciturne, elle parle peu et de façon concise. Elle est parfois brutale, aussi bien physiquement que verbalement, Elle ne prend cependant aucun plaisir à malmener ceux quelle considère plus faibles quelle. Dune 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 dun manque déducation et dune capacité limitée à gérer ses émotions quà une débilité congénitale. Elle voue à la force un culte car cest par son expression quelle se sent vraiment vivante et éprouve de grandes difficultés vis à vis de ceux quelle nomme foshnu (bébé, chouineur en commun).", description = "Brulkhai, ou plus simplement Bru, est solidement bâti. Elle mesure 192 cm pour 110 kg de muscles lorsquelle est en bonne santé. Elle a les cheveux châtains, les yeux noisettes et la peau couleur gris-vert typique de son espèce. Dun tempérament taciturne, elle parle peu et de façon concise. Elle est parfois brutale, aussi bien physiquement que verbalement, Elle ne prend cependant aucun plaisir à malmener ceux quelle considère plus faibles quelle. Dune 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 dun manque déducation et dune capacité limitée à gérer ses émotions quà une débilité congénitale. Elle voue à la force un culte car cest par son expression quelle se sent vraiment vivante et éprouve de grandes difficultés vis à vis de ceux quelle nomme foshnu (bébé, chouineur en commun).",
history = null, history = null,
tags = "protagoniste, brute", tags = "protagoniste, brute",
search = null, search = "Bru",
highlightGender = true, highlightGender = true,
highlightRace = true, highlightRace = true,
) )

View file

@ -16,15 +16,17 @@ class LexiconDetailViewModel @Inject constructor(
lexiconRepository: LexiconRepository, lexiconRepository: LexiconRepository,
characterSheetRepository: CharacterSheetRepository, characterSheetRepository: CharacterSheetRepository,
) : ViewModel() { ) : ViewModel() {
val character: State<LexiconDetailUio>
val haveCharacterSheet: State<Boolean> val haveCharacterSheet: State<Boolean>
private val _character = mutableStateOf<LexiconDetailUio?>(null)
val character: State<LexiconDetailUio?> get() = _character
init { init {
val argument = savedStateHandle.lexiconDetailArgument val argument = savedStateHandle.lexiconDetailArgument
val source = lexiconRepository.data.value[argument.id] val source = lexiconRepository.find(id = argument.id)
character = mutableStateOf( if (source != null) {
LexiconDetailUio( _character.value = LexiconDetailUio(
name = source.name, name = source.name,
diminutive = source.diminutive?.let { "./ $it" }, diminutive = source.diminutive?.let { "./ $it" },
gender = source.gender, gender = source.gender,
@ -39,10 +41,10 @@ class LexiconDetailViewModel @Inject constructor(
highlightGender = argument.highlightGender && argument.gender == source.gender, highlightGender = argument.highlightGender && argument.gender == source.gender,
highlightRace = argument.highlightRace && argument.race == source.race, highlightRace = argument.highlightRace && argument.race == source.race,
) )
) }
haveCharacterSheet = mutableStateOf( haveCharacterSheet = mutableStateOf(
characterSheetRepository.find(source.name) != null characterSheetRepository.find(name = source?.name) != null
) )
} }
} }

View file

@ -34,7 +34,7 @@ import com.pixelized.rplexicon.utilitary.extentions.placeholder
@Stable @Stable
data class LexiconItemUio( data class LexiconItemUio(
val id: Int, val id: String,
val name: String, val name: String,
val diminutive: String?, val diminutive: String?,
@StringRes val gender: Int, @StringRes val gender: Int,
@ -45,7 +45,7 @@ data class LexiconItemUio(
companion object { companion object {
@Stable @Stable
fun preview( fun preview(
id: Int = 0, id: String = "Brulkhai-1",
name: String = "Brulkhai", name: String = "Brulkhai",
diminutive: String? = null, diminutive: String? = null,
@StringRes gender: Int = R.string.gender_female_short, @StringRes gender: Int = R.string.gender_female_short,

View file

@ -207,7 +207,7 @@ private fun LexiconScreenContentPreview() {
mutableStateOf( mutableStateOf(
listOf( listOf(
LexiconItemUio( LexiconItemUio(
id = 0, id = "Brulkhai-1",
name = "Brulkhai", name = "Brulkhai",
diminutive = "Bru", diminutive = "Bru",
gender = R.string.gender_female_short, gender = R.string.gender_female_short,

View file

@ -43,7 +43,7 @@ import com.pixelized.rplexicon.utilitary.extentions.searchCriterion
@Stable @Stable
class SearchItemUio( class SearchItemUio(
val id: Int, val id: String,
val name: String, val name: String,
val diminutive: String?, val diminutive: String?,
val gender: Lexicon.Gender, val gender: Lexicon.Gender,
@ -59,7 +59,7 @@ class SearchItemUio(
) { ) {
companion object { companion object {
fun preview( fun preview(
id: Int = 0, id: String = "Brulkhai-1",
name: String = "Brulkhai", name: String = "Brulkhai",
diminutive: String? = "Bru", diminutive: String? = "Bru",
gender: Lexicon.Gender = Lexicon.Gender.FEMALE, gender: Lexicon.Gender = Lexicon.Gender.FEMALE,
@ -93,7 +93,7 @@ class SearchItemUio(
@Stable @Stable
class AnnotatedSearchItemUio( class AnnotatedSearchItemUio(
val id: Int, val id: String,
val name: AnnotatedString, val name: AnnotatedString,
val diminutive: AnnotatedString?, val diminutive: AnnotatedString?,
val gender: AnnotatedString, val gender: AnnotatedString,

View file

@ -218,35 +218,35 @@ private fun SearchScreenContentPreview() {
mutableStateOf( mutableStateOf(
listOf( listOf(
SearchItemUio.preview( SearchItemUio.preview(
id = 0, id = "Brulkhai-1",
name = "Brulkhai", name = "Brulkhai",
diminutive = "Bru", diminutive = "Bru",
gender = Lexicon.Gender.FEMALE, gender = Lexicon.Gender.FEMALE,
race = Lexicon.Race.HALF_ORC, race = Lexicon.Race.HALF_ORC,
), ),
SearchItemUio.preview( SearchItemUio.preview(
id = 1, id = "Léandre-1",
name = "Léandre", name = "Léandre",
diminutive = null, diminutive = null,
gender = Lexicon.Gender.MALE, gender = Lexicon.Gender.MALE,
race = Lexicon.Race.HUMAN, race = Lexicon.Race.HUMAN,
), ),
SearchItemUio.preview( SearchItemUio.preview(
id = 2, id = "Nélia-1",
name = "Nélia", name = "Nélia",
diminutive = null, diminutive = null,
gender = Lexicon.Gender.FEMALE, gender = Lexicon.Gender.FEMALE,
race = Lexicon.Race.ELF, race = Lexicon.Race.ELF,
), ),
SearchItemUio.preview( SearchItemUio.preview(
id = 3, id = "Tigrane-1",
name = "Tigrane", name = "Tigrane",
diminutive = null, diminutive = null,
gender = Lexicon.Gender.MALE, gender = Lexicon.Gender.MALE,
race = Lexicon.Race.TIEFLING, race = Lexicon.Race.TIEFLING,
), ),
SearchItemUio.preview( SearchItemUio.preview(
id = 4, id = "Unathana-1",
name = "Unathana", name = "Unathana",
diminutive = "Una", diminutive = "Una",
gender = Lexicon.Gender.FEMALE, gender = Lexicon.Gender.FEMALE,

View file

@ -71,7 +71,7 @@ data class QuestDetailUio(
@Stable @Stable
data class QuestStep( data class QuestStep(
val subtitle: String? = null, val subtitle: String? = null,
val giverId: Int? = null, val giverId: String? = null,
val giver: String? = null, val giver: String? = null,
val placeId: String? = null, val placeId: String? = null,
val place: String? = null, val place: String? = null,
@ -112,7 +112,7 @@ private fun QuestDetailContent(
state: ScrollState = rememberScrollState(), state: ScrollState = rememberScrollState(),
item: State<QuestDetailUio>, item: State<QuestDetailUio>,
onBack: () -> Unit, onBack: () -> Unit,
onGiver: (Int) -> Unit, onGiver: (String) -> Unit,
onLocation: (String) -> Unit, onLocation: (String) -> Unit,
onImage: (Uri) -> Unit, onImage: (Uri) -> Unit,
) { ) {