Skip to content

Commit 970009c

Browse files
committed
Deduplicate compendium chooser
1 parent fb6e39c commit 970009c

File tree

22 files changed

+127
-542
lines changed

22 files changed

+127
-542
lines changed
Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package cz.frantisekmasa.wfrp_master.common.character.religion.blessings.dialog
1+
package cz.frantisekmasa.wfrp_master.common.character
22

33
import androidx.compose.foundation.clickable
44
import androidx.compose.foundation.layout.Box
@@ -21,8 +21,9 @@ import androidx.compose.runtime.remember
2121
import androidx.compose.runtime.rememberCoroutineScope
2222
import androidx.compose.runtime.setValue
2323
import androidx.compose.ui.Modifier
24-
import cz.frantisekmasa.wfrp_master.common.character.religion.blessings.BlessingsScreenModel
25-
import cz.frantisekmasa.wfrp_master.common.core.domain.religion.Blessing
24+
import cz.frantisekmasa.wfrp_master.common.core.CharacterItemScreenModel
25+
import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterItem
26+
import cz.frantisekmasa.wfrp_master.common.core.domain.compendium.CompendiumItem
2627
import cz.frantisekmasa.wfrp_master.common.core.shared.IO
2728
import cz.frantisekmasa.wfrp_master.common.core.shared.Resources
2829
import cz.frantisekmasa.wfrp_master.common.core.ui.buttons.CloseButton
@@ -37,62 +38,60 @@ import kotlinx.coroutines.launch
3738

3839

3940
@Composable
40-
internal fun CompendiumBlessingChooser(
41-
screenModel: BlessingsScreenModel,
42-
onComplete: () -> Unit,
43-
onCustomBlessingRequest: () -> Unit,
41+
internal fun <A : CharacterItem, B : CompendiumItem<B>> CompendiumItemChooser(
42+
title: String,
43+
icon: @Composable (B) -> Resources.Drawable,
44+
screenModel: CharacterItemScreenModel<A, B>,
45+
onSelect: suspend (B) -> Unit,
46+
onCustomItemRequest: () -> Unit,
4447
onDismissRequest: () -> Unit,
48+
customItemButtonText: String,
49+
emptyUiIcon: Resources.Drawable,
4550
) {
46-
val strings = LocalStrings.current.blessings
47-
4851
Scaffold(
4952
topBar = {
5053
TopAppBar(
5154
navigationIcon = { CloseButton(onDismissRequest) },
52-
title = { Text(strings.titleChooseCompendiumBlessing) },
55+
title = { Text(title) },
5356
)
5457
}
5558
) {
56-
val compendiumBlessings = screenModel.notUsedItemsFromCompendium.collectWithLifecycle(null).value
57-
val totalCompendiumBlessingCount = screenModel.compendiumItemsCount.collectWithLifecycle(null).value
59+
val compendiumItems =
60+
screenModel.notUsedItemsFromCompendium.collectWithLifecycle(null).value
61+
val totalCompendiumItemCount =
62+
screenModel.compendiumItemsCount.collectWithLifecycle(null).value
5863
var saving by remember { mutableStateOf(false) }
5964

60-
if (compendiumBlessings == null || totalCompendiumBlessingCount == null || saving) {
65+
if (compendiumItems == null || totalCompendiumItemCount == null || saving) {
6166
FullScreenProgress()
6267
return@Scaffold
6368
}
6469

6570
Column(Modifier.fillMaxSize()) {
6671
Box(Modifier.weight(1f)) {
67-
if (compendiumBlessings.isEmpty()) {
72+
if (compendiumItems.isEmpty()) {
6873
EmptyUI(
69-
icon = Resources.Drawable.Blessing,
70-
text = strings.messages.noBlessingsInCompendium,
71-
subText = if (totalCompendiumBlessingCount == 0)
72-
strings.messages.noBlessingsInCompendiumSubtextPlayer
74+
icon = emptyUiIcon,
75+
text = LocalStrings.current.compendium.messages.noItems,
76+
subText = if (totalCompendiumItemCount == 0)
77+
LocalStrings.current.compendium.messages.noItemsInCompendiumSubtextPlayer
7378
else null,
7479
)
7580
} else {
7681
val coroutineScope = rememberCoroutineScope()
7782

7883
LazyColumn(contentPadding = PaddingValues(Spacing.bodyPadding)) {
79-
items(compendiumBlessings, key = { it.id }) { blessing ->
84+
items(compendiumItems, key = { it.id }) { item ->
8085
ListItem(
8186
modifier = Modifier.clickable(
8287
onClick = {
8388
saving = false
8489

85-
coroutineScope.launch(Dispatchers.IO) {
86-
screenModel.saveItem(
87-
Blessing.fromCompendium(blessing)
88-
)
89-
90-
onComplete()
91-
}
90+
coroutineScope.launch(Dispatchers.IO) { onSelect(item) }
9291
}
9392
),
94-
icon = { ItemIcon(Resources.Drawable.Blessing, ItemIcon.Size.Small) },
95-
text = { Text(blessing.name) }
93+
icon = { ItemIcon(icon(item), ItemIcon.Size.Small) },
94+
text = { Text(item.name) }
9695
)
9796
}
9897
}
@@ -103,9 +102,9 @@ internal fun CompendiumBlessingChooser(
103102
modifier = Modifier
104103
.fillMaxWidth()
105104
.padding(Spacing.bodyPadding),
106-
onClick = onCustomBlessingRequest,
105+
onClick = onCustomItemRequest,
107106
) {
108-
Text(strings.buttonAddNonCompendium)
107+
Text(customItemButtonText)
109108
}
110109
}
111110
}

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/religion/blessings/dialog/AddBlessingDialog.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ import androidx.compose.runtime.getValue
55
import androidx.compose.runtime.mutableStateOf
66
import androidx.compose.runtime.saveable.rememberSaveable
77
import androidx.compose.runtime.setValue
8+
import cz.frantisekmasa.wfrp_master.common.character.CompendiumItemChooser
89
import cz.frantisekmasa.wfrp_master.common.character.religion.blessings.BlessingsScreenModel
10+
import cz.frantisekmasa.wfrp_master.common.core.domain.religion.Blessing
911
import cz.frantisekmasa.wfrp_master.common.core.shared.Parcelable
1012
import cz.frantisekmasa.wfrp_master.common.core.shared.Parcelize
13+
import cz.frantisekmasa.wfrp_master.common.core.shared.Resources
1114
import cz.frantisekmasa.wfrp_master.common.core.ui.dialogs.FullScreenDialog
15+
import cz.frantisekmasa.wfrp_master.common.localization.LocalStrings
1216

1317

1418
@Composable
@@ -26,13 +30,17 @@ internal fun AddBlessingDialog(screenModel: BlessingsScreenModel, onDismissReque
2630
) {
2731
when (state) {
2832
ChoosingCompendiumMiracle ->
29-
CompendiumBlessingChooser(
33+
CompendiumItemChooser(
3034
screenModel = screenModel,
31-
onComplete = onDismissRequest,
32-
onCustomBlessingRequest = { state = FillingInCustomMiracle },
35+
title = LocalStrings.current.blessings.titleChooseCompendiumBlessing,
3336
onDismissRequest = onDismissRequest,
37+
icon = { Resources.Drawable.Blessing },
38+
onSelect = { screenModel.saveItem(Blessing.fromCompendium(it)) },
39+
onCustomItemRequest = { state = FillingInCustomBlessing },
40+
customItemButtonText = LocalStrings.current.blessings.buttonAddNonCompendium,
41+
emptyUiIcon = Resources.Drawable.Blessing,
3442
)
35-
is FillingInCustomMiracle -> NonCompendiumBlessingForm(
43+
is FillingInCustomBlessing -> NonCompendiumBlessingForm(
3644
screenModel = screenModel,
3745
existingBlessing = null,
3846
onDismissRequest = onDismissRequest,
@@ -47,4 +55,4 @@ private sealed class AddMiracleDialogState : Parcelable
4755
private object ChoosingCompendiumMiracle : AddMiracleDialogState()
4856

4957
@Parcelize
50-
private object FillingInCustomMiracle : AddMiracleDialogState()
58+
private object FillingInCustomBlessing : AddMiracleDialogState()

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/religion/miracles/dialog/AddMiracleDialog.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ import androidx.compose.runtime.getValue
55
import androidx.compose.runtime.mutableStateOf
66
import androidx.compose.runtime.saveable.rememberSaveable
77
import androidx.compose.runtime.setValue
8+
import cz.frantisekmasa.wfrp_master.common.character.CompendiumItemChooser
89
import cz.frantisekmasa.wfrp_master.common.character.religion.miracles.MiraclesScreenModel
10+
import cz.frantisekmasa.wfrp_master.common.core.domain.religion.Miracle
911
import cz.frantisekmasa.wfrp_master.common.core.shared.Parcelable
1012
import cz.frantisekmasa.wfrp_master.common.core.shared.Parcelize
13+
import cz.frantisekmasa.wfrp_master.common.core.shared.Resources
1114
import cz.frantisekmasa.wfrp_master.common.core.ui.dialogs.FullScreenDialog
15+
import cz.frantisekmasa.wfrp_master.common.localization.LocalStrings
1216

1317
@Composable
1418
internal fun AddMiracleDialog(screenModel: MiraclesScreenModel, onDismissRequest: () -> Unit) {
@@ -25,11 +29,15 @@ internal fun AddMiracleDialog(screenModel: MiraclesScreenModel, onDismissRequest
2529
) {
2630
when (state) {
2731
ChoosingCompendiumMiracle ->
28-
CompendiumMiracleChooser(
32+
CompendiumItemChooser(
2933
screenModel = screenModel,
30-
onComplete = onDismissRequest,
31-
onCustomMiracleRequest = { state = FillingInCustomMiracle },
34+
title = LocalStrings.current.miracles.titleChooseCompendiumMiracle,
3235
onDismissRequest = onDismissRequest,
36+
icon = { Resources.Drawable.Miracle },
37+
onSelect = { screenModel.saveItem(Miracle.fromCompendium(it)) },
38+
onCustomItemRequest = { state = FillingInCustomMiracle },
39+
customItemButtonText = LocalStrings.current.miracles.buttonAddNonCompendium,
40+
emptyUiIcon = Resources.Drawable.Miracle,
3341
)
3442
is FillingInCustomMiracle -> NonCompendiumMiracleForm(
3543
screenModel = screenModel,

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/religion/miracles/dialog/CompendiumMiracleChooser.kt

Lines changed: 0 additions & 113 deletions
This file was deleted.

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/skills/SkillsCard.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ internal fun SkillsCard(
3434
skillsScreenModel: SkillsScreenModel,
3535
onRemove: (Skill) -> Unit,
3636
) {
37-
val skills = skillsScreenModel.skills.collectWithLifecycle(null).value ?: return
37+
val skills = skillsScreenModel.items.collectWithLifecycle(null).value ?: return
3838
val characteristics = characterScreenModel.character
3939
.collectWithLifecycle(null).value?.characteristics ?: return
4040

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/skills/SkillsScreenModel.kt

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,22 @@
11
package cz.frantisekmasa.wfrp_master.common.character.skills
22

3-
import cafe.adriel.voyager.core.model.ScreenModel
43
import cafe.adriel.voyager.core.model.coroutineScope
54
import com.benasher44.uuid.Uuid
5+
import cz.frantisekmasa.wfrp_master.common.core.CharacterItemScreenModel
66
import cz.frantisekmasa.wfrp_master.common.core.domain.compendium.Compendium
77
import cz.frantisekmasa.wfrp_master.common.core.domain.identifiers.CharacterId
88
import cz.frantisekmasa.wfrp_master.common.core.domain.skills.Skill
99
import cz.frantisekmasa.wfrp_master.common.core.domain.skills.SkillRepository
1010
import cz.frantisekmasa.wfrp_master.common.core.shared.IO
1111
import kotlinx.coroutines.Dispatchers
12-
import kotlinx.coroutines.flow.Flow
13-
import kotlinx.coroutines.flow.combineTransform
14-
import kotlinx.coroutines.flow.map
1512
import kotlinx.coroutines.launch
1613
import cz.frantisekmasa.wfrp_master.common.compendium.domain.Skill as CompendiumSkill
1714

1815
class SkillsScreenModel(
1916
private val characterId: CharacterId,
2017
private val skillRepository: SkillRepository,
2118
private val compendium: Compendium<CompendiumSkill>
22-
) : ScreenModel {
23-
val skills: Flow<List<Skill>> = skillRepository.findAllForCharacter(characterId)
24-
25-
val compendiumSkillsCount: Flow<Int> by lazy {
26-
compendiumSkills.map { it.size }
27-
}
28-
val notUsedSkillsFromCompendium: Flow<List<CompendiumSkill>> by lazy {
29-
compendiumSkills.combineTransform(skills) { compendiumSkills, characterSkills ->
30-
val skillsUsedByCharacter = characterSkills.mapNotNull { it.compendiumId }.toSet()
31-
32-
emit(compendiumSkills.filter { !skillsUsedByCharacter.contains(it.id) })
33-
}
34-
}
35-
36-
private val compendiumSkills by lazy { compendium.liveForParty(characterId.partyId) }
37-
19+
) : CharacterItemScreenModel<Skill, CompendiumSkill>(characterId, skillRepository, compendium) {
3820
suspend fun saveSkill(skill: Skill) = skillRepository.save(characterId, skill)
3921

4022
suspend fun saveCompendiumSkill(skillId: Uuid, compendiumSkillId: Uuid, advances: Int) {

common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/skills/dialog/AddSkillDialog.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ import androidx.compose.runtime.mutableStateOf
66
import androidx.compose.runtime.saveable.rememberSaveable
77
import androidx.compose.runtime.setValue
88
import com.benasher44.uuid.Uuid
9+
import cz.frantisekmasa.wfrp_master.common.character.CompendiumItemChooser
910
import cz.frantisekmasa.wfrp_master.common.character.skills.SkillsScreenModel
1011
import cz.frantisekmasa.wfrp_master.common.core.shared.Parcelable
1112
import cz.frantisekmasa.wfrp_master.common.core.shared.Parcelize
13+
import cz.frantisekmasa.wfrp_master.common.core.shared.Resources
1214
import cz.frantisekmasa.wfrp_master.common.core.ui.dialogs.FullScreenDialog
15+
import cz.frantisekmasa.wfrp_master.common.localization.LocalStrings
1316

1417
@Composable
1518
fun AddSkillDialog(screenModel: SkillsScreenModel, onDismissRequest: () -> Unit) {
@@ -26,11 +29,15 @@ fun AddSkillDialog(screenModel: SkillsScreenModel, onDismissRequest: () -> Unit)
2629
) {
2730
when (val currentState = state) {
2831
ChoosingCompendiumSkill ->
29-
CompendiumSkillChooser(
32+
CompendiumItemChooser(
3033
screenModel = screenModel,
31-
onSkillSelected = { state = FillingInAdvances(it.id, it.advanced) },
32-
onCustomSkillRequest = { state = FillingInCustomSkill },
34+
title = LocalStrings.current.skills.titleChooseCompendiumSkill,
3335
onDismissRequest = onDismissRequest,
36+
icon = { it.characteristic.getIcon() },
37+
onSelect = { state = FillingInAdvances(it.id, it.advanced) },
38+
onCustomItemRequest = { state = FillingInCustomSkill },
39+
customItemButtonText = LocalStrings.current.skills.buttonAddNonCompendium,
40+
emptyUiIcon = Resources.Drawable.Skill,
3441
)
3542
is FillingInAdvances ->
3643
AdvancesForm(

0 commit comments

Comments
 (0)