Add version to the charactersheet savable.
This commit is contained in:
parent
c7fe440f8f
commit
52f7f8333b
13 changed files with 211 additions and 134 deletions
|
|
@ -1,13 +1,14 @@
|
|||
package com.pixelized.desktop.lwa
|
||||
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetJsonFactory
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetStore
|
||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||
import com.pixelized.desktop.lwa.repository.roll.RollHistoryRepository
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetFactory
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetViewModel
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditViewModel
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditFactory
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditViewModel
|
||||
import com.pixelized.desktop.lwa.screen.main.MainPageViewModel
|
||||
import com.pixelized.desktop.lwa.screen.network.NetworkFactory
|
||||
import com.pixelized.desktop.lwa.screen.network.NetworkViewModel
|
||||
|
|
@ -37,6 +38,7 @@ val factoryDependencies
|
|||
get() = module {
|
||||
factoryOf(::CharacterSheetFactory)
|
||||
factoryOf(::CharacterSheetEditFactory)
|
||||
factoryOf(::CharacterSheetJsonFactory)
|
||||
factoryOf(::NetworkFactory)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.pixelized.desktop.lwa.business
|
||||
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
|
||||
object RollUseCase {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
package com.pixelized.desktop.lwa.composable.overlay
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.blur
|
||||
import androidx.compose.ui.draw.drawWithContent
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
|
||||
@Stable
|
||||
data class BlurOverlayTransitionUio(
|
||||
val blur: State<Dp>,
|
||||
val background: State<Color>,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun BlurOverlay(
|
||||
viewModel: BlurOverlayViewModel = viewModel { BlurOverlayViewModel() },
|
||||
overlay: @Composable BoxScope.() -> Unit,
|
||||
content: @Composable BoxScope.() -> Unit,
|
||||
) {
|
||||
val transition = viewModel.transition
|
||||
Box {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.blur(radius = transition.blur.value)
|
||||
.drawWithContent {
|
||||
drawContent()
|
||||
drawRect(color = transition.background.value)
|
||||
},
|
||||
content = content,
|
||||
)
|
||||
|
||||
AnimatedContent(
|
||||
targetState = viewModel.overlay.value,
|
||||
transitionSpec = {
|
||||
val enter = fadeIn() + slideInVertically { 64 }
|
||||
val exit = fadeOut() + slideOutVertically { 64 }
|
||||
enter togetherWith exit
|
||||
},
|
||||
) { roll ->
|
||||
when (roll) {
|
||||
true -> Box(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
content = overlay,
|
||||
)
|
||||
|
||||
else -> Box(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
package com.pixelized.desktop.lwa.composable.overlay
|
||||
|
||||
import androidx.compose.animation.animateColor
|
||||
import androidx.compose.animation.core.animateDp
|
||||
import androidx.compose.animation.core.updateTransition
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class BlurOverlayViewModel : ViewModel() {
|
||||
private val _overlay = mutableStateOf(false)
|
||||
val overlay: State<Boolean>
|
||||
get() = _overlay
|
||||
|
||||
val transition: BlurOverlayTransitionUio
|
||||
@Composable
|
||||
get() {
|
||||
val transition = updateTransition(_overlay.value)
|
||||
val blur = transition.animateDp {
|
||||
when (it) {
|
||||
true -> 8.dp
|
||||
else -> 0.dp
|
||||
}
|
||||
}
|
||||
val background = transition.animateColor {
|
||||
when (it) {
|
||||
true -> Color.Black.copy(alpha = 0.6f)
|
||||
else -> Color.Black.copy(alpha = 0f)
|
||||
}
|
||||
}
|
||||
return remember {
|
||||
BlurOverlayTransitionUio(
|
||||
blur = blur,
|
||||
background = background,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun show() {
|
||||
_overlay.value = true
|
||||
}
|
||||
|
||||
fun hide() {
|
||||
_overlay.value = false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet
|
||||
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJson
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJsonV1
|
||||
|
||||
class CharacterSheetJsonFactory {
|
||||
|
||||
fun convertLastJsonVersion(
|
||||
sheet: CharacterSheet,
|
||||
): CharacterSheetJson {
|
||||
val json = CharacterSheetJsonV1(
|
||||
id = sheet.id,
|
||||
name = sheet.name,
|
||||
strength = sheet.strength,
|
||||
dexterity = sheet.dexterity,
|
||||
constitution = sheet.constitution,
|
||||
height = sheet.height,
|
||||
intelligence = sheet.intelligence,
|
||||
power = sheet.power,
|
||||
charisma = sheet.charisma,
|
||||
movement = sheet.movement,
|
||||
currentHp = sheet.currentHp,
|
||||
maxHp = sheet.maxHp,
|
||||
currentPP = sheet.currentPP,
|
||||
maxPP = sheet.maxPP,
|
||||
damageBonus = sheet.damageBonus,
|
||||
armor = sheet.armor,
|
||||
skills = sheet.skills.map {
|
||||
CharacterSheetJsonV1.Skill(
|
||||
label = it.label,
|
||||
value = it.value,
|
||||
used = it.used,
|
||||
)
|
||||
},
|
||||
occupations = sheet.occupations.map {
|
||||
CharacterSheetJsonV1.Skill(
|
||||
label = it.label,
|
||||
value = it.value,
|
||||
used = it.used,
|
||||
)
|
||||
},
|
||||
magics = sheet.magics.map {
|
||||
CharacterSheetJsonV1.Skill(
|
||||
label = it.label,
|
||||
value = it.value,
|
||||
used = it.used,
|
||||
)
|
||||
},
|
||||
rolls = sheet.rolls.map {
|
||||
CharacterSheetJsonV1.Roll(
|
||||
label = it.label,
|
||||
roll = it.roll,
|
||||
)
|
||||
},
|
||||
)
|
||||
return json
|
||||
}
|
||||
|
||||
fun convertFromJson(
|
||||
json: CharacterSheetJson,
|
||||
): CharacterSheet {
|
||||
return when (json) {
|
||||
is CharacterSheetJsonV1 -> convertFromV1(json = json)
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertFromV1(
|
||||
json: CharacterSheetJsonV1,
|
||||
): CharacterSheet {
|
||||
val sheet = CharacterSheet(
|
||||
id = json.id,
|
||||
name = json.name,
|
||||
strength = json.strength,
|
||||
dexterity = json.dexterity,
|
||||
constitution = json.constitution,
|
||||
height = json.height,
|
||||
intelligence = json.intelligence,
|
||||
power = json.power,
|
||||
charisma = json.charisma,
|
||||
movement = json.movement,
|
||||
currentHp = json.currentHp,
|
||||
maxHp = json.maxHp,
|
||||
currentPP = json.currentPP,
|
||||
maxPP = json.maxPP,
|
||||
damageBonus = json.damageBonus,
|
||||
armor = json.armor,
|
||||
skills = json.skills.map {
|
||||
CharacterSheet.Skill(
|
||||
label = it.label,
|
||||
value = it.value,
|
||||
used = it.used,
|
||||
)
|
||||
},
|
||||
occupations = json.occupations.map {
|
||||
CharacterSheet.Skill(
|
||||
label = it.label,
|
||||
value = it.value,
|
||||
used = it.used,
|
||||
)
|
||||
},
|
||||
magics = json.magics.map {
|
||||
CharacterSheet.Skill(
|
||||
label = it.label,
|
||||
value = it.value,
|
||||
used = it.used,
|
||||
)
|
||||
},
|
||||
rolls = json.rolls.map {
|
||||
CharacterSheet.Roll(
|
||||
label = it.label,
|
||||
roll = it.roll,
|
||||
)
|
||||
},
|
||||
)
|
||||
return sheet
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet
|
||||
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -13,7 +14,7 @@ class CharacterSheetRepository(
|
|||
) {
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
||||
private val sheets = store.loadFlow()
|
||||
private val sheets = store.characterSheetFlow()
|
||||
.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.Eagerly,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet
|
||||
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJson
|
||||
import com.pixelized.desktop.lwa.repository.storePath
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
|
@ -7,11 +9,15 @@ import kotlinx.serialization.encodeToString
|
|||
import kotlinx.serialization.json.Json
|
||||
import java.io.File
|
||||
|
||||
class CharacterSheetStore {
|
||||
class CharacterSheetStore(
|
||||
private val factory: CharacterSheetJsonFactory,
|
||||
) {
|
||||
private val root = File(storePath()).also { it.mkdirs() }
|
||||
private val files = File(root, NAME).also { it.createNewFile() }
|
||||
private val flow = MutableStateFlow(value = load())
|
||||
|
||||
fun characterSheetFlow(): StateFlow<List<CharacterSheet>> = flow
|
||||
|
||||
@Throws(
|
||||
CharacterSheetStoreException::class,
|
||||
FileWriteException::class,
|
||||
|
|
@ -19,7 +25,9 @@ class CharacterSheetStore {
|
|||
)
|
||||
fun save(sheets: List<CharacterSheet>) {
|
||||
val json = try {
|
||||
Json.encodeToString(sheets)
|
||||
sheets
|
||||
.map(factory::convertLastJsonVersion)
|
||||
.let(Json::encodeToString)
|
||||
} catch (exception: Exception) {
|
||||
throw JsonConversionException(root = exception)
|
||||
}
|
||||
|
|
@ -49,15 +57,14 @@ class CharacterSheetStore {
|
|||
emptyList()
|
||||
} else {
|
||||
try {
|
||||
Json.decodeFromString<List<CharacterSheet>>(json)
|
||||
val sheets = Json.decodeFromString<List<CharacterSheetJson>>(json)
|
||||
sheets.map { factory.convertFromJson(it) }
|
||||
} catch (exception: Exception) {
|
||||
throw JsonConversionException(root = exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun loadFlow(): StateFlow<List<CharacterSheet>> = flow
|
||||
|
||||
companion object {
|
||||
private const val NAME = "characters_sheet.json"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet
|
||||
package com.pixelized.desktop.lwa.repository.characterSheet.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CharacterSheet(
|
||||
val id: String,
|
||||
val name: String,
|
||||
|
|
@ -31,14 +28,12 @@ data class CharacterSheet(
|
|||
// attack
|
||||
val rolls: List<Roll>,
|
||||
) {
|
||||
@Serializable
|
||||
data class Skill(
|
||||
val label: String,
|
||||
val value: Int,
|
||||
val used: Boolean,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Roll(
|
||||
val label: String,
|
||||
val roll: String,
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
sealed interface CharacterSheetJson
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CharacterSheetJsonV1(
|
||||
val id: String,
|
||||
val name: String,
|
||||
// characteristics
|
||||
val strength: Int,
|
||||
val dexterity: Int,
|
||||
val constitution: Int,
|
||||
val height: Int,
|
||||
val intelligence: Int,
|
||||
val power: Int,
|
||||
val charisma: Int,
|
||||
// sub characteristics
|
||||
val movement: Int,
|
||||
val currentHp: Int,
|
||||
val maxHp: Int,
|
||||
val currentPP: Int,
|
||||
val maxPP: Int,
|
||||
val damageBonus: String,
|
||||
val armor: Int,
|
||||
// skills
|
||||
val skills: List<Skill>,
|
||||
// occupations
|
||||
val occupations: List<Skill>,
|
||||
// magic skill
|
||||
val magics: List<Skill>,
|
||||
// attack
|
||||
val rolls: List<Roll>,
|
||||
) : CharacterSheetJson {
|
||||
@Serializable
|
||||
data class Skill(
|
||||
val label: String,
|
||||
val value: Int,
|
||||
val used: Boolean,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Roll(
|
||||
val label: String,
|
||||
val roll: String,
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val COMBAT = "Bagarre"
|
||||
const val DODGE = "Esquive"
|
||||
const val GRAB = "Saisie"
|
||||
const val THROW = "Lancer"
|
||||
const val ATHLETICS = "Athlétisme"
|
||||
const val ACROBATICS = "Acrobatie"
|
||||
const val PERCEPTION = "Perception"
|
||||
const val SEARCH = "Recherche"
|
||||
const val EMPATHY = "Empathie"
|
||||
const val PERSUASION = "Persuasion"
|
||||
const val INTIMIDATION = "Intimidation"
|
||||
const val SPIEL = "Baratin"
|
||||
const val BARGAIN = "Marchandage"
|
||||
const val DISCRETION = "Discrétion"
|
||||
const val SLEIGHT_OF_HAND = "Escamotage"
|
||||
const val AID = "Premiers soins"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package com.pixelized.desktop.lwa.screen.characterSheet.detail
|
||||
|
||||
import com.pixelized.desktop.lwa.composable.tooltip.TooltipUio
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Node
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.pixelized.desktop.lwa.screen.characterSheet.edit
|
|||
|
||||
import com.pixelized.desktop.lwa.business.DamageBonusUseCase.bonusDamage
|
||||
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase.normalize
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditPageUio.SkillGroup
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import androidx.lifecycle.ViewModel
|
||||
import com.pixelized.desktop.lwa.business.RollUseCase
|
||||
import com.pixelized.desktop.lwa.business.SkillStepUseCase
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.desktop.lwa.repository.roll.RollHistoryRepository
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue