Change the character sheet save system to use separate files for sheets
This commit is contained in:
parent
de13bf2c74
commit
4606122264
7 changed files with 95 additions and 70 deletions
|
|
@ -1,27 +1,37 @@
|
||||||
package com.pixelized.desktop.lwa.repository
|
package com.pixelized.desktop.lwa.repository
|
||||||
|
|
||||||
fun operatingSystem(
|
enum class OperatingSystem(
|
||||||
name: String = System.getProperty("os.name")
|
val home: String = System.getProperty("user.home"),
|
||||||
): OperatingSystem {
|
) {
|
||||||
return when {
|
Windows,
|
||||||
name.contains(other = "win", ignoreCase = true) -> OperatingSystem.Windows
|
Macintosh;
|
||||||
name.contains(other = "mac", ignoreCase = true) -> OperatingSystem.Macintosh
|
|
||||||
|
companion object {
|
||||||
|
val current: OperatingSystem = run {
|
||||||
|
val name = System.getProperty("os.name")
|
||||||
|
when {
|
||||||
|
name.contains(other = "win", ignoreCase = true) -> Windows
|
||||||
|
name.contains(other = "mac", ignoreCase = true) -> Macintosh
|
||||||
else -> error("Unsupported operating system: $name")
|
else -> error("Unsupported operating system: $name")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
enum class OperatingSystem(
|
|
||||||
val home: String,
|
|
||||||
) {
|
|
||||||
Windows(home = System.getProperty("user.home")),
|
|
||||||
Macintosh(home = System.getProperty("user.home")),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun storePath(
|
fun storePath(
|
||||||
operatingSystem: OperatingSystem = operatingSystem()
|
os: OperatingSystem = OperatingSystem.current,
|
||||||
): String {
|
): String {
|
||||||
return when (operatingSystem) {
|
return when (os) {
|
||||||
OperatingSystem.Windows -> "${operatingSystem.home}\\AppData\\Roaming\\Pixelized\\"
|
OperatingSystem.Windows -> "${os.home}\\AppData\\Roaming\\Pixelized\\"
|
||||||
OperatingSystem.Macintosh -> "${operatingSystem.home}/Library/Pixelized/"
|
OperatingSystem.Macintosh -> "${os.home}/Library/Pixelized/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun characterStorePath(
|
||||||
|
os: OperatingSystem = OperatingSystem.current,
|
||||||
|
): String {
|
||||||
|
return when (os) {
|
||||||
|
OperatingSystem.Windows -> "${storePath(os = os)}characters\\"
|
||||||
|
OperatingSystem.Macintosh -> "${storePath(os = os)}characters/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,23 +52,11 @@ class CharacterSheetRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save(characterSheet: CharacterSheet) {
|
fun save(characterSheet: CharacterSheet) {
|
||||||
val savedSheets = store.load().toMutableList()
|
store.save(sheet = characterSheet)
|
||||||
val savedIndex = savedSheets.indexOfFirst { it.id == characterSheet.id }
|
|
||||||
if (savedIndex >= 0) {
|
|
||||||
// this sheet is already saved. update it
|
|
||||||
savedSheets[savedIndex] = characterSheet
|
|
||||||
} else {
|
|
||||||
// add the character sheet to the list.
|
|
||||||
savedSheets.add(characterSheet)
|
|
||||||
}
|
|
||||||
// save the list of characters sheet.
|
|
||||||
store.save(sheets = savedSheets)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun delete(id: String) {
|
fun delete(id: String) {
|
||||||
val savedSheets = store.load().toMutableList()
|
store.delete(id = id)
|
||||||
savedSheets.removeIf { it.id == id }
|
|
||||||
store.save(sheets = savedSheets)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDiminishedForCharacter(id: String, diminished: Int) {
|
fun setDiminishedForCharacter(id: String, diminished: Int) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,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.CharacterSheet
|
||||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJson
|
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJson
|
||||||
import com.pixelized.desktop.lwa.repository.storePath
|
import com.pixelized.desktop.lwa.repository.characterStorePath
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
|
|
@ -12,8 +12,7 @@ import java.io.File
|
||||||
class CharacterSheetStore(
|
class CharacterSheetStore(
|
||||||
private val factory: CharacterSheetJsonFactory,
|
private val factory: CharacterSheetJsonFactory,
|
||||||
) {
|
) {
|
||||||
private val root = File(storePath()).also { it.mkdirs() }
|
private val characterDirectory = File(characterStorePath()).also { it.mkdirs() }
|
||||||
private val files = File(root, NAME).also { it.createNewFile() }
|
|
||||||
private val flow = MutableStateFlow(value = load())
|
private val flow = MutableStateFlow(value = load())
|
||||||
|
|
||||||
fun characterSheetFlow(): StateFlow<List<CharacterSheet>> = flow
|
fun characterSheetFlow(): StateFlow<List<CharacterSheet>> = flow
|
||||||
|
|
@ -23,23 +22,49 @@ class CharacterSheetStore(
|
||||||
FileWriteException::class,
|
FileWriteException::class,
|
||||||
JsonConversionException::class,
|
JsonConversionException::class,
|
||||||
)
|
)
|
||||||
fun save(sheets: List<CharacterSheet>) {
|
fun save(sheet: CharacterSheet) {
|
||||||
|
// convert the character sheet into json format.
|
||||||
val json = try {
|
val json = try {
|
||||||
sheets
|
factory.convertToJson(sheet = sheet).let(Json::encodeToString)
|
||||||
.map(factory::convertToJson)
|
|
||||||
.let(Json::encodeToString)
|
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw JsonConversionException(root = exception)
|
throw JsonConversionException(root = exception)
|
||||||
}
|
}
|
||||||
|
// write the character file.
|
||||||
try {
|
try {
|
||||||
files.writeText(
|
val file = characterSheetFile(id = sheet.id)
|
||||||
|
file.writeText(
|
||||||
text = json,
|
text = json,
|
||||||
charset = Charsets.UTF_8,
|
charset = Charsets.UTF_8,
|
||||||
)
|
)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw FileWriteException(root = exception)
|
throw FileWriteException(root = exception)
|
||||||
}
|
}
|
||||||
flow.value = sheets
|
// Update the dataflow.
|
||||||
|
flow.value = flow.value
|
||||||
|
.toMutableList()
|
||||||
|
.also { data ->
|
||||||
|
val index = data.indexOfFirst { it.id == sheet.id }
|
||||||
|
if (index >= 0) {
|
||||||
|
data[index] = sheet
|
||||||
|
} else {
|
||||||
|
data.add(sheet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sortedBy {
|
||||||
|
it.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun delete(id: String): Boolean {
|
||||||
|
val file = characterSheetFile(id = id)
|
||||||
|
flow.value = flow.value.toMutableList()
|
||||||
|
.also { data ->
|
||||||
|
data.removeIf { it.id == id }
|
||||||
|
}
|
||||||
|
.sortedBy {
|
||||||
|
it.name
|
||||||
|
}
|
||||||
|
return file.delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Throws(
|
@Throws(
|
||||||
|
|
@ -48,25 +73,33 @@ class CharacterSheetStore(
|
||||||
JsonConversionException::class,
|
JsonConversionException::class,
|
||||||
)
|
)
|
||||||
fun load(): List<CharacterSheet> {
|
fun load(): List<CharacterSheet> {
|
||||||
|
return characterDirectory
|
||||||
|
.listFiles()
|
||||||
|
?.mapNotNull { file ->
|
||||||
val json = try {
|
val json = try {
|
||||||
files.readText(charset = Charsets.UTF_8)
|
file.readText(charset = Charsets.UTF_8)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw FileReadException(root = exception)
|
throw FileReadException(root = exception)
|
||||||
}
|
}
|
||||||
return if (json.isBlank()) {
|
// Guard, if the json is blank no character have been save, ignore this file.
|
||||||
emptyList()
|
if (json.isBlank()) {
|
||||||
} else {
|
return@mapNotNull null
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
val sheets = Json.decodeFromString<List<CharacterSheetJson>>(json)
|
val sheet = Json.decodeFromString<CharacterSheetJson>(json)
|
||||||
sheets.map { factory.convertFromJson(it) }
|
factory.convertFromJson(sheet)
|
||||||
} catch (exception: Exception) {
|
} catch (exception: Exception) {
|
||||||
throw JsonConversionException(root = exception)
|
throw JsonConversionException(root = exception)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
?.sortedBy {
|
||||||
|
it.name
|
||||||
|
}
|
||||||
|
?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
private fun characterSheetFile(id: String): File {
|
||||||
private const val NAME = "characters_sheet.json"
|
return File("${characterStorePath()}${id}.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class CharacterSheetStoreException(root: Exception) : Exception(root)
|
sealed class CharacterSheetStoreException(root: Exception) : Exception(root)
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,8 @@ data class CharacterSheetEditPageUio(
|
||||||
val charisma: SimpleFieldUio,
|
val charisma: SimpleFieldUio,
|
||||||
val movement: SimpleFieldUio,
|
val movement: SimpleFieldUio,
|
||||||
val maxHp: SimpleFieldUio,
|
val maxHp: SimpleFieldUio,
|
||||||
val currentHp: SimpleFieldUio,
|
|
||||||
val maxPp: SimpleFieldUio,
|
val maxPp: SimpleFieldUio,
|
||||||
|
val currentHp: SimpleFieldUio,
|
||||||
val currentPp: SimpleFieldUio,
|
val currentPp: SimpleFieldUio,
|
||||||
val damageBonus: SimpleFieldUio,
|
val damageBonus: SimpleFieldUio,
|
||||||
val armor: SimpleFieldUio,
|
val armor: SimpleFieldUio,
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class SkillFieldFactory {
|
||||||
return SkillFieldUio(
|
return SkillFieldUio(
|
||||||
id = id,
|
id = id,
|
||||||
label = createWrapper(
|
label = createWrapper(
|
||||||
label = mutableStateOf(labelValue),
|
label = mutableStateOf(label),
|
||||||
value = labelValue,
|
value = labelValue,
|
||||||
),
|
),
|
||||||
base = createWrapper(
|
base = createWrapper(
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import androidx.lifecycle.ViewModel
|
||||||
import com.lordcodes.turtle.shellRun
|
import com.lordcodes.turtle.shellRun
|
||||||
import com.pixelized.desktop.lwa.repository.OperatingSystem
|
import com.pixelized.desktop.lwa.repository.OperatingSystem
|
||||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||||
import com.pixelized.desktop.lwa.repository.operatingSystem
|
|
||||||
import com.pixelized.desktop.lwa.repository.storePath
|
import com.pixelized.desktop.lwa.repository.storePath
|
||||||
import com.pixelized.desktop.lwa.utils.extention.collectAsState
|
import com.pixelized.desktop.lwa.utils.extention.collectAsState
|
||||||
|
|
||||||
|
|
@ -28,17 +27,12 @@ class MainPageViewModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openSaveDirectory() {
|
fun openSaveDirectory(
|
||||||
when (val os = operatingSystem()) {
|
os: OperatingSystem = OperatingSystem.current
|
||||||
OperatingSystem.Windows -> shellRun(
|
) {
|
||||||
"explorer.exe",
|
when (os) {
|
||||||
listOf(storePath(operatingSystem = os))
|
OperatingSystem.Windows -> shellRun("explorer.exe", listOf(storePath(os = os)))
|
||||||
)
|
OperatingSystem.Macintosh -> shellRun("open", listOf(storePath(os = os)))
|
||||||
|
|
||||||
OperatingSystem.Macintosh -> shellRun(
|
|
||||||
"open",
|
|
||||||
listOf(storePath(operatingSystem = os))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BIN
output.zip
BIN
output.zip
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue