diff --git a/app/src/main/java/com/pixelized/rplexicon/data/model/Lexicon.kt b/app/src/main/java/com/pixelized/rplexicon/data/model/Lexicon.kt index ceb391f..e6fe81d 100644 --- a/app/src/main/java/com/pixelized/rplexicon/data/model/Lexicon.kt +++ b/app/src/main/java/com/pixelized/rplexicon/data/model/Lexicon.kt @@ -5,8 +5,7 @@ import androidx.compose.runtime.Stable @Stable data class Lexicon( - val id: Int, - val sheetIndex: Int, + val id: String, val name: String, val diminutive: String?, val gender: Gender, diff --git a/app/src/main/java/com/pixelized/rplexicon/data/parser/LexiconParser.kt b/app/src/main/java/com/pixelized/rplexicon/data/parser/LexiconParser.kt index 0d6bca9..beae0af 100644 --- a/app/src/main/java/com/pixelized/rplexicon/data/parser/LexiconParser.kt +++ b/app/src/main/java/com/pixelized/rplexicon/data/parser/LexiconParser.kt @@ -12,7 +12,7 @@ class LexiconParser @Inject constructor( ) { @Throws(IncompatibleSheetStructure::class) fun parse(sheet: ValueRange): List = parserScope { - var id = 0 + val ids = hashMapOf() val lexicons = mutableListOf() sheet.forEachRowIndexed { index, row -> @@ -22,9 +22,9 @@ class LexiconParser @Inject constructor( else -> { val name = row.parse(column = NAME) if (name != null) { + ids[name] = ids.getOrDefault(name, 0) + 1 val lexicon = Lexicon( - id = id++, - sheetIndex = index, + id = "$name-${ids[name]}", name = name, diminutive = row.parse(column = SHORT), gender = genderParser.parse(row.parse(column = GENDER)), diff --git a/app/src/main/java/com/pixelized/rplexicon/data/repository/lexicon/LexiconRepository.kt b/app/src/main/java/com/pixelized/rplexicon/data/repository/lexicon/LexiconRepository.kt index cf31045..0a93bea 100644 --- a/app/src/main/java/com/pixelized/rplexicon/data/repository/lexicon/LexiconRepository.kt +++ b/app/src/main/java/com/pixelized/rplexicon/data/repository/lexicon/LexiconRepository.kt @@ -22,7 +22,11 @@ class LexiconRepository @Inject constructor( var lastSuccessFullUpdate: Update = Update.INITIAL 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 } } diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/navigation/screens/ComposableLexiconDetail.kt b/app/src/main/java/com/pixelized/rplexicon/ui/navigation/screens/ComposableLexiconDetail.kt index 921afd6..bd7db88 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/navigation/screens/ComposableLexiconDetail.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/navigation/screens/ComposableLexiconDetail.kt @@ -33,7 +33,7 @@ val LEXICON_DETAIL_ROUTE = ROUTE + @Stable @Immutable data class LexiconDetailArgument( - val id: Int, + val id: String, val highlight: String?, val race: Lexicon.Race, val highlightRace: Boolean, @@ -61,7 +61,7 @@ fun NavGraphBuilder.composableLexiconDetail() { route = LEXICON_DETAIL_ROUTE, arguments = listOf( navArgument(name = ARG_ID) { - type = NavType.IntType + type = NavType.StringType }, navArgument(name = ARG_HIGHLIGHT) { type = NavType.StringType @@ -87,7 +87,7 @@ fun NavGraphBuilder.composableLexiconDetail() { } fun NavHostController.navigateToLexiconDetail( - id: Int, + id: String, highlight: String? = null, race: Lexicon.Race? = null, gender: Lexicon.Gender? = null, diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailScreen.kt index b9a36f8..af75e88 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailScreen.kt @@ -106,6 +106,7 @@ data class AnnotatedLexiconDetailUio( @Stable fun LexiconDetailUio.annotate(): AnnotatedLexiconDetailUio { val colorScheme = MaterialTheme.colorScheme + val typography = MaterialTheme.lexicon.typography val highlight = remember { SpanStyle(color = colorScheme.primary) } val trimmedSearch = remember(search) { search.searchCriterion() } val highlightRegex = remember(search) { trimmedSearch.highlightRegex } @@ -117,10 +118,16 @@ fun LexiconDetailUio.annotate(): AnnotatedLexiconDetailUio { portrait = portrait, name = AnnotatedString( text = name, - spanStyles = highlightRegex?.annotatedSpan( + spanStyles = (highlightRegex?.annotatedSpan( input = name, spanStyle = highlight, - ) ?: emptyList() + ) ?: emptyList()) + listOf( + AnnotatedString.Range( + item = typography.headlineSmallDropCap, + start = 0, + end = 1, + ) + ) ), diminutive = diminutive?.let { highlightRegex.annotatedString(input = it, spanStyle = highlight) @@ -165,7 +172,9 @@ fun LexiconDetailScreen( ) { val screen = LocalScreenNavHost.current - Surface { + Surface( + modifier = Modifier.fillMaxSize(), + ) { LexiconDetailContent( modifier = Modifier.fillMaxSize(), item = viewModel.character, @@ -186,7 +195,7 @@ fun LexiconDetailScreen( private fun LexiconDetailContent( modifier: Modifier = Modifier, state: ScrollState = rememberScrollState(), - item: State, + item: State, haveCharacterSheet: State, onBack: () -> Unit, onCharacterSheet: (String) -> Unit, @@ -194,9 +203,9 @@ private fun LexiconDetailContent( ) { val colorScheme = MaterialTheme.colorScheme val typography = MaterialTheme.typography - val annotatedItem = item.value.annotate() + val annotatedItem = item.value?.annotate() val backgroundUri = remember(annotatedItem) { - annotatedItem.portrait.firstOrNull() + annotatedItem?.portrait?.firstOrNull() } Scaffold( @@ -215,7 +224,7 @@ private fun LexiconDetailContent( }, actions = { AnimatedVisibility(visible = haveCharacterSheet.value) { - IconButton(onClick = { onCharacterSheet(item.value.name) }) { + IconButton(onClick = { item.value?.name?.let(onCharacterSheet) }) { Icon( painter = painterResource(id = R.drawable.ic_d20_24), contentDescription = null @@ -257,14 +266,14 @@ private fun LexiconDetailContent( modifier = Modifier.padding(horizontal = 16.dp), horizontalArrangement = Arrangement.spacedBy(4.dp) ) { - annotatedItem.name.let { + annotatedItem?.name?.let { Text( modifier = Modifier.alignByBaseline(), style = typography.headlineSmall, text = it, ) } - annotatedItem.diminutive?.let { + annotatedItem?.diminutive?.let { Text( modifier = Modifier.alignByBaseline(), style = typography.labelMedium, @@ -278,23 +287,27 @@ private fun LexiconDetailContent( modifier = Modifier.padding(horizontal = 16.dp), horizontalArrangement = Arrangement.spacedBy(4.dp) ) { - Text( - style = typography.labelMedium, - fontStyle = FontStyle.Italic, - text = annotatedItem.gender, - ) - Text( - style = typography.labelMedium, - fontStyle = FontStyle.Italic, - text = annotatedItem.race, - ) + annotatedItem?.gender?.let { + Text( + style = typography.labelMedium, + fontStyle = FontStyle.Italic, + text = it, + ) + } + annotatedItem?.race?.let { + 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)) } - annotatedItem.status?.let { + annotatedItem?.status?.let { Row( modifier = Modifier.padding(start = 16.dp, end = 16.dp), horizontalArrangement = Arrangement.spacedBy(space = 4.dp), @@ -320,7 +333,7 @@ private fun LexiconDetailContent( } } - annotatedItem.location?.let { + annotatedItem?.location?.let { Row( modifier = Modifier.padding(start = 16.dp, end = 16.dp), horizontalArrangement = Arrangement.spacedBy(space = 4.dp), @@ -346,7 +359,7 @@ private fun LexiconDetailContent( } } - annotatedItem.description?.let { + annotatedItem?.description?.let { Text( modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp), style = typography.titleMedium, @@ -366,7 +379,7 @@ private fun LexiconDetailContent( ) } - annotatedItem.history?.let { + annotatedItem?.history?.let { Text( modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp), style = typography.titleMedium, @@ -379,7 +392,7 @@ private fun LexiconDetailContent( ) } - if (annotatedItem.portrait.isNotEmpty()) { + if (annotatedItem?.portrait?.isNotEmpty() == true) { val maxSize = rememberPortraitWidth() Text( 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( modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp), 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 lorsqu’elle est en bonne santé. Elle a les cheveux châtains, les yeux noisettes et la peau couleur gris-vert typique de son espèce. D’un 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 qu’elle considère plus faibles qu’elle. 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. 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 = null, tags = "protagoniste, brute", - search = null, + search = "Bru", highlightGender = true, highlightRace = true, ) diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailViewModel.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailViewModel.kt index 86a203d..b20c2c9 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailViewModel.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailViewModel.kt @@ -16,15 +16,17 @@ class LexiconDetailViewModel @Inject constructor( lexiconRepository: LexiconRepository, characterSheetRepository: CharacterSheetRepository, ) : ViewModel() { - val character: State val haveCharacterSheet: State + private val _character = mutableStateOf(null) + val character: State get() = _character + init { val argument = savedStateHandle.lexiconDetailArgument - val source = lexiconRepository.data.value[argument.id] + val source = lexiconRepository.find(id = argument.id) - character = mutableStateOf( - LexiconDetailUio( + if (source != null) { + _character.value = LexiconDetailUio( name = source.name, diminutive = source.diminutive?.let { "./ $it" }, gender = source.gender, @@ -39,10 +41,10 @@ class LexiconDetailViewModel @Inject constructor( highlightGender = argument.highlightGender && argument.gender == source.gender, highlightRace = argument.highlightRace && argument.race == source.race, ) - ) + } haveCharacterSheet = mutableStateOf( - characterSheetRepository.find(source.name) != null + characterSheetRepository.find(name = source?.name) != null ) } } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/list/LexiconItem.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/list/LexiconItem.kt index 6d191b8..bb2b458 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/list/LexiconItem.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/list/LexiconItem.kt @@ -34,7 +34,7 @@ import com.pixelized.rplexicon.utilitary.extentions.placeholder @Stable data class LexiconItemUio( - val id: Int, + val id: String, val name: String, val diminutive: String?, @StringRes val gender: Int, @@ -45,7 +45,7 @@ data class LexiconItemUio( companion object { @Stable fun preview( - id: Int = 0, + id: String = "Brulkhai-1", name: String = "Brulkhai", diminutive: String? = null, @StringRes gender: Int = R.string.gender_female_short, diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/list/LexiconScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/list/LexiconScreen.kt index 4f00823..fca9e51 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/list/LexiconScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/list/LexiconScreen.kt @@ -207,7 +207,7 @@ private fun LexiconScreenContentPreview() { mutableStateOf( listOf( LexiconItemUio( - id = 0, + id = "Brulkhai-1", name = "Brulkhai", diminutive = "Bru", gender = R.string.gender_female_short, diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/search/SearchItem.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/search/SearchItem.kt index 905286a..7a4fcb2 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/search/SearchItem.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/search/SearchItem.kt @@ -43,7 +43,7 @@ import com.pixelized.rplexicon.utilitary.extentions.searchCriterion @Stable class SearchItemUio( - val id: Int, + val id: String, val name: String, val diminutive: String?, val gender: Lexicon.Gender, @@ -59,7 +59,7 @@ class SearchItemUio( ) { companion object { fun preview( - id: Int = 0, + id: String = "Brulkhai-1", name: String = "Brulkhai", diminutive: String? = "Bru", gender: Lexicon.Gender = Lexicon.Gender.FEMALE, @@ -93,7 +93,7 @@ class SearchItemUio( @Stable class AnnotatedSearchItemUio( - val id: Int, + val id: String, val name: AnnotatedString, val diminutive: AnnotatedString?, val gender: AnnotatedString, diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/search/SearchScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/search/SearchScreen.kt index 2d4a9d4..171aad0 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/search/SearchScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/search/SearchScreen.kt @@ -218,35 +218,35 @@ private fun SearchScreenContentPreview() { mutableStateOf( listOf( SearchItemUio.preview( - id = 0, + id = "Brulkhai-1", name = "Brulkhai", diminutive = "Bru", gender = Lexicon.Gender.FEMALE, race = Lexicon.Race.HALF_ORC, ), SearchItemUio.preview( - id = 1, + id = "Léandre-1", name = "Léandre", diminutive = null, gender = Lexicon.Gender.MALE, race = Lexicon.Race.HUMAN, ), SearchItemUio.preview( - id = 2, + id = "Nélia-1", name = "Nélia", diminutive = null, gender = Lexicon.Gender.FEMALE, race = Lexicon.Race.ELF, ), SearchItemUio.preview( - id = 3, + id = "Tigrane-1", name = "Tigrane", diminutive = null, gender = Lexicon.Gender.MALE, race = Lexicon.Race.TIEFLING, ), SearchItemUio.preview( - id = 4, + id = "Unathana-1", name = "Unathana", diminutive = "Una", gender = Lexicon.Gender.FEMALE, diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/quest/detail/QuestDetailScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/quest/detail/QuestDetailScreen.kt index 1b70b79..5bd1d92 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/quest/detail/QuestDetailScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/quest/detail/QuestDetailScreen.kt @@ -71,7 +71,7 @@ data class QuestDetailUio( @Stable data class QuestStep( val subtitle: String? = null, - val giverId: Int? = null, + val giverId: String? = null, val giver: String? = null, val placeId: String? = null, val place: String? = null, @@ -112,7 +112,7 @@ private fun QuestDetailContent( state: ScrollState = rememberScrollState(), item: State, onBack: () -> Unit, - onGiver: (Int) -> Unit, + onGiver: (String) -> Unit, onLocation: (String) -> Unit, onImage: (Uri) -> Unit, ) {