diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/StorePath.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/StorePath.kt index e36ed75..1d56535 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/StorePath.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/StorePath.kt @@ -1,27 +1,37 @@ package com.pixelized.desktop.lwa.repository -fun operatingSystem( - name: String = System.getProperty("os.name") -): OperatingSystem { - return when { - name.contains(other = "win", ignoreCase = true) -> OperatingSystem.Windows - name.contains(other = "mac", ignoreCase = true) -> OperatingSystem.Macintosh - else -> error("Unsupported operating system: $name") - } -} - enum class OperatingSystem( - val home: String, + val home: String = System.getProperty("user.home"), ) { - Windows(home = System.getProperty("user.home")), - Macintosh(home = System.getProperty("user.home")), + Windows, + 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") + } + } + } } fun storePath( - operatingSystem: OperatingSystem = operatingSystem() + os: OperatingSystem = OperatingSystem.current, ): String { - return when (operatingSystem) { - OperatingSystem.Windows -> "${operatingSystem.home}\\AppData\\Roaming\\Pixelized\\" - OperatingSystem.Macintosh -> "${operatingSystem.home}/Library/Pixelized/" + return when (os) { + OperatingSystem.Windows -> "${os.home}\\AppData\\Roaming\\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/" } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt index 69cef43..16cf6ef 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt @@ -52,23 +52,11 @@ class CharacterSheetRepository( } fun save(characterSheet: CharacterSheet) { - val savedSheets = store.load().toMutableList() - 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) + store.save(sheet = characterSheet) } fun delete(id: String) { - val savedSheets = store.load().toMutableList() - savedSheets.removeIf { it.id == id } - store.save(sheets = savedSheets) + store.delete(id = id) } fun setDiminishedForCharacter(id: String, diminished: Int) { diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt index 29b9856..47d2dd6 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt @@ -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.CharacterSheetJson -import com.pixelized.desktop.lwa.repository.storePath +import com.pixelized.desktop.lwa.repository.characterStorePath import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.serialization.encodeToString @@ -12,8 +12,7 @@ import java.io.File 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 characterDirectory = File(characterStorePath()).also { it.mkdirs() } private val flow = MutableStateFlow(value = load()) fun characterSheetFlow(): StateFlow> = flow @@ -23,23 +22,49 @@ class CharacterSheetStore( FileWriteException::class, JsonConversionException::class, ) - fun save(sheets: List) { + fun save(sheet: CharacterSheet) { + // convert the character sheet into json format. val json = try { - sheets - .map(factory::convertToJson) - .let(Json::encodeToString) + factory.convertToJson(sheet = sheet).let(Json::encodeToString) } catch (exception: Exception) { throw JsonConversionException(root = exception) } + // write the character file. try { - files.writeText( + val file = characterSheetFile(id = sheet.id) + file.writeText( text = json, charset = Charsets.UTF_8, ) } catch (exception: 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( @@ -48,25 +73,33 @@ class CharacterSheetStore( JsonConversionException::class, ) fun load(): List { - val json = try { - files.readText(charset = Charsets.UTF_8) - } catch (exception: Exception) { - throw FileReadException(root = exception) - } - return if (json.isBlank()) { - emptyList() - } else { - try { - val sheets = Json.decodeFromString>(json) - sheets.map { factory.convertFromJson(it) } - } catch (exception: Exception) { - throw JsonConversionException(root = exception) + return characterDirectory + .listFiles() + ?.mapNotNull { file -> + val json = try { + file.readText(charset = Charsets.UTF_8) + } catch (exception: Exception) { + throw FileReadException(root = exception) + } + // Guard, if the json is blank no character have been save, ignore this file. + if (json.isBlank()) { + return@mapNotNull null + } + try { + val sheet = Json.decodeFromString(json) + factory.convertFromJson(sheet) + } catch (exception: Exception) { + throw JsonConversionException(root = exception) + } } - } + ?.sortedBy { + it.name + } + ?: emptyList() } - companion object { - private const val NAME = "characters_sheet.json" + private fun characterSheetFile(id: String): File { + return File("${characterStorePath()}${id}.json") } sealed class CharacterSheetStoreException(root: Exception) : Exception(root) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt index 0365ee6..86a84c0 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt @@ -69,8 +69,8 @@ data class CharacterSheetEditPageUio( val charisma: SimpleFieldUio, val movement: SimpleFieldUio, val maxHp: SimpleFieldUio, - val currentHp: SimpleFieldUio, val maxPp: SimpleFieldUio, + val currentHp: SimpleFieldUio, val currentPp: SimpleFieldUio, val damageBonus: SimpleFieldUio, val armor: SimpleFieldUio, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/common/SkillFieldFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/common/SkillFieldFactory.kt index 7878d40..0d8b8c3 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/common/SkillFieldFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/common/SkillFieldFactory.kt @@ -34,7 +34,7 @@ class SkillFieldFactory { return SkillFieldUio( id = id, label = createWrapper( - label = mutableStateOf(labelValue), + label = mutableStateOf(label), value = labelValue, ), base = createWrapper( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPageViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPageViewModel.kt index 23391e8..8e1c3f7 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPageViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPageViewModel.kt @@ -7,7 +7,6 @@ import androidx.lifecycle.ViewModel import com.lordcodes.turtle.shellRun import com.pixelized.desktop.lwa.repository.OperatingSystem 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.utils.extention.collectAsState @@ -28,17 +27,12 @@ class MainPageViewModel( } } - fun openSaveDirectory() { - when (val os = operatingSystem()) { - OperatingSystem.Windows -> shellRun( - "explorer.exe", - listOf(storePath(operatingSystem = os)) - ) - - OperatingSystem.Macintosh -> shellRun( - "open", - listOf(storePath(operatingSystem = os)) - ) + fun openSaveDirectory( + os: OperatingSystem = OperatingSystem.current + ) { + when (os) { + OperatingSystem.Windows -> shellRun("explorer.exe", listOf(storePath(os = os))) + OperatingSystem.Macintosh -> shellRun("open", listOf(storePath(os = os))) } } } \ No newline at end of file diff --git a/output.zip b/output.zip deleted file mode 100644 index 3ba14d4..0000000 Binary files a/output.zip and /dev/null differ