Client : Error management

This commit is contained in:
Thomas Andres Gomez 2025-04-01 16:01:43 +02:00
parent d806048510
commit 1ebb7c1400
48 changed files with 630 additions and 473 deletions

View file

@ -1,5 +1,8 @@
package com.pixelized.desktop.lwa
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.MaterialTheme
@ -10,11 +13,13 @@ import androidx.compose.material.SnackbarDefaults
import androidx.compose.material.SnackbarDuration
import androidx.compose.material.SnackbarHost
import androidx.compose.material.SnackbarHostState
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
@ -146,7 +151,7 @@ private fun MainWindowScreen(
}
LwaScaffold(
modifier = Modifier.fillMaxSize(),
modifier = Modifier.fillMaxSize()
) {
MainNavHost()

View file

@ -6,6 +6,7 @@ import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import com.pixelized.desktop.lwa.repository.tag.TagRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.distinctUntilChanged
@ -19,6 +20,7 @@ class DataSyncViewModel(
private val characterRepository: CharacterSheetRepository,
private val alterationRepository: AlterationRepository,
private val campaignRepository: CampaignRepository,
private val tagRepository: TagRepository,
private val settingsRepository: SettingsRepository,
private val networkRepository: NetworkRepository,
) : ViewModel() {
@ -40,10 +42,10 @@ class DataSyncViewModel(
networkRepository.status
.filter { status -> status == NetworkRepository.Status.CONNECTED }
.onEach {
tagRepository.updateAlterationTags()
alterationRepository.updateAlterations()
alterationRepository.updateTags()
tagRepository.updateCharacterTags()
characterRepository.updateCharacterPreviews()
characterRepository.updateTags()
campaignRepository.updateCampaign()
}
.launchIn(this)
@ -54,9 +56,8 @@ class DataSyncViewModel(
.distinctUntilChanged()
.onEach { instances ->
instances.forEach { characterSheetId ->
characterRepository.characterDetail(
characterRepository.updateCharacterSheet(
characterSheetId = characterSheetId,
forceUpdate = true,
)
}
}

View file

@ -13,6 +13,8 @@ import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsFactory
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsStore
import com.pixelized.desktop.lwa.repository.tag.TagRepository
import com.pixelized.desktop.lwa.repository.tag.TagStore
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogFactory
import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogFactory
@ -37,9 +39,9 @@ import com.pixelized.desktop.lwa.ui.screen.characterSheet.edit.common.SkillField
import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.edit.GMAlterationEditFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.edit.GMAlterationEditViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.list.GMAlterationFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.list.GMAlterationViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.edit.GMAlterationEditViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.list.GMCharacterFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.list.GMCharacterViewModel
import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagFactory
@ -100,6 +102,7 @@ val storeDependencies
singleOf(::SettingsStore)
singleOf(::AlterationStore)
singleOf(::CampaignStore)
singleOf(::TagStore)
}
val repositoryDependencies
@ -110,6 +113,7 @@ val repositoryDependencies
singleOf(::SettingsRepository)
singleOf(::AlterationRepository)
singleOf(::CampaignRepository)
singleOf(::TagRepository)
}
val factoryDependencies

View file

@ -5,83 +5,89 @@ import com.pixelized.shared.lwa.model.campaign.CampaignJson
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson
import com.pixelized.shared.lwa.model.tag.TagJson
import com.pixelized.shared.lwa.protocol.rest.CharacterPreviewJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
interface LwaClient {
// Alteration
suspend fun alterations(): List<AlterationJson>
suspend fun getAlterations(): APIResponse<List<AlterationJson>>
suspend fun alterations(
suspend fun getAlteration(
alterationId: String,
): AlterationJson?
): APIResponse<AlterationJson?>
suspend fun updateAlteration(
alterationJson: AlterationJson
)
suspend fun putAlteration(
alterationJson: AlterationJson,
create: Boolean,
): APIResponse<Unit>
suspend fun deleteAlteration(
alterationId: String,
)
): APIResponse<Unit>
suspend fun alterationTags(): List<TagJson>
suspend fun getAlterationTags(): APIResponse<List<TagJson>>
// Campaign
suspend fun campaign(): CampaignJson
suspend fun getCampaign(): APIResponse<CampaignJson>
suspend fun campaignAddCharacter(
suspend fun putCampaignCharacter(
characterSheetId: String,
)
): APIResponse<Unit>
suspend fun campaignRemoveCharacter(
suspend fun removeCampaignCharacter(
characterSheetId: String,
)
): APIResponse<Unit>
suspend fun campaignAddNpc(
suspend fun putCampaignNpc(
characterSheetId: String,
)
): APIResponse<Unit>
suspend fun campaignRemoveNpc(
suspend fun removeCampaignNpc(
characterSheetId: String,
)
): APIResponse<Unit>
// Character
suspend fun characters(): List<CharacterPreviewJson>
suspend fun getCharacters(): APIResponse<List<CharacterPreviewJson>>
suspend fun characterTags(): List<TagJson>
suspend fun getCharacterTags(): APIResponse<List<TagJson>>
suspend fun character(
suspend fun getCharacter(
characterSheetId: String,
): CharacterSheetJson
): APIResponse<CharacterSheetJson>
suspend fun updateCharacter(
suspend fun putCharacter(
sheet: CharacterSheetJson,
)
): APIResponse<Unit>
suspend fun updateCharacterDamage(
suspend fun putCharacterDamage(
characterSheetId: String,
damage: Int,
)
): APIResponse<Unit>
suspend fun updateCharacterFatigue(
suspend fun putCharacterFatigue(
characterSheetId: String,
fatigue: Int,
)
): APIResponse<Unit>
suspend fun updateCharacterDiminished(
suspend fun putCharacterDiminished(
characterSheetId: String,
diminished: Int,
)
): APIResponse<Unit>
suspend fun updateCharacterAlteration(
suspend fun putCharacterAlteration(
characterSheetId: String,
alterationId: Int,
active: Boolean,
)
): APIResponse<Unit>
suspend fun deleteCharacterSheet(
characterSheetId: String,
)
): APIResponse<Unit>
companion object {
fun error(error: APIResponse<*>): Nothing = throw LwaNetworkException(error)
}
}

View file

@ -5,6 +5,7 @@ import com.pixelized.shared.lwa.model.alteration.AlterationJson
import com.pixelized.shared.lwa.model.campaign.CampaignJson
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson
import com.pixelized.shared.lwa.model.tag.TagJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.rest.CharacterPreviewJson
import io.ktor.client.HttpClient
import io.ktor.client.call.body
@ -21,114 +22,134 @@ class LwaClientImpl(
) : LwaClient {
private val root = setting.settings().network.root
override suspend fun alterations(): List<AlterationJson> = client
@Throws
override suspend fun getAlterations(): APIResponse<List<AlterationJson>> = client
.get("$root/alteration/all")
.body()
override suspend fun alterations(
@Throws
override suspend fun getAlteration(
alterationId: String,
): AlterationJson? = client
): APIResponse<AlterationJson?> = client
.get("$root/alteration/detail?alterationId=$alterationId")
.body()
override suspend fun updateAlteration(
alterationJson: AlterationJson
@Throws
override suspend fun putAlteration(
alterationJson: AlterationJson,
create: Boolean,
) = client
.put("$root/alteration/update") {
.put("$root/alteration/update?create=$create") {
contentType(ContentType.Application.Json)
setBody(alterationJson)
}
.body<Unit>()
.body<APIResponse<Unit>>()
@Throws
override suspend fun deleteAlteration(alterationId: String) = client
.delete("$root/alteration/delete?alterationId=$alterationId")
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun alterationTags(): List<TagJson> = client
@Throws
override suspend fun getAlterationTags(): APIResponse<List<TagJson>> = client
.get("$root/alteration/tags")
.body()
override suspend fun campaign(): CampaignJson = client
@Throws
override suspend fun getCampaign(): APIResponse<CampaignJson> = client
.get("$root/campaign")
.body()
override suspend fun campaignAddCharacter(
@Throws
override suspend fun putCampaignCharacter(
characterSheetId: String,
) = client
.put("$root/campaign/character/add?characterSheetId=$characterSheetId")
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun campaignRemoveCharacter(
@Throws
override suspend fun removeCampaignCharacter(
characterSheetId: String,
) = client
.delete("$root/campaign/character/delete?characterSheetId=$characterSheetId")
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun campaignAddNpc(
@Throws
override suspend fun putCampaignNpc(
characterSheetId: String,
) = client
.put("$root/campaign/npc/add?characterSheetId=$characterSheetId")
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun campaignRemoveNpc(
@Throws
override suspend fun removeCampaignNpc(
characterSheetId: String,
) = client
.delete("$root/campaign/npc/delete?characterSheetId=$characterSheetId")
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun characters(): List<CharacterPreviewJson> = client
@Throws
override suspend fun getCharacters(): APIResponse<List<CharacterPreviewJson>> = client
.get("$root/character/all")
.body()
override suspend fun characterTags(): List<TagJson> = client
@Throws
override suspend fun getCharacterTags(): APIResponse<List<TagJson>> = client
.get("$root/character/tags")
.body()
override suspend fun character(
@Throws
override suspend fun getCharacter(
characterSheetId: String,
): CharacterSheetJson = client
): APIResponse<CharacterSheetJson> = client
.get("$root/character/detail?characterSheetId=$characterSheetId")
.body()
override suspend fun updateCharacter(
@Throws
override suspend fun putCharacter(
sheet: CharacterSheetJson,
) = client
.put("$root/character/update/sheet") {
contentType(ContentType.Application.Json)
setBody(sheet)
}
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun updateCharacterDamage(
@Throws
override suspend fun putCharacterDamage(
characterSheetId: String,
damage: Int,
) = client
.put("$root/character/update/damage?characterSheetId=$characterSheetId&damage=$damage")
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun updateCharacterFatigue(
@Throws
override suspend fun putCharacterFatigue(
characterSheetId: String,
fatigue: Int,
) = client
.put("$root/character/update/fatigue?characterSheetId=$characterSheetId&fatigue=$fatigue")
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun updateCharacterDiminished(
@Throws
override suspend fun putCharacterDiminished(
characterSheetId: String,
diminished: Int,
) = client
.put("$root/character/update/diminished?characterSheetId=$characterSheetId&diminished=$diminished")
.body<Unit>()
.body<APIResponse<Unit>>()
override suspend fun updateCharacterAlteration(
@Throws
override suspend fun putCharacterAlteration(
characterSheetId: String,
alterationId: Int,
active: Boolean,
) = client
.put("$root/character/update/alteration?characterSheetId=$characterSheetId&alterationId=$alterationId&active=$active")
.body<Unit>()
.body<APIResponse<Unit>>()
@Throws
override suspend fun deleteCharacterSheet(characterSheetId: String) = client
.delete("$root/character/delete?characterSheetId=$characterSheetId")
.body<Unit>()
.body<APIResponse<Unit>>()
}

View file

@ -0,0 +1,13 @@
package com.pixelized.desktop.lwa.network
import com.pixelized.shared.lwa.protocol.rest.APIResponse
class LwaNetworkException(
val status: Int,
message: String,
) : Exception(message) {
constructor(error: APIResponse<*>) : this(
status = error.status,
message = error.message ?: "An unknown error occurred"
)
}

View file

@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.stateIn
class AlterationRepository(
private val alterationStore: AlterationStore,
campaignRepository: CampaignRepository,
characterRepository: CharacterSheetRepository,
) {
@ -26,8 +27,6 @@ class AlterationRepository(
val alterationFlow get() = alterationStore.alterationsFlow
val tagsFlow get() = alterationStore.tagsFlow
/**
* This flow transform the campaign instance (player + npc) into a
* Map<CharacterSheetId, List<AlterationId>>.
@ -66,11 +65,7 @@ class AlterationRepository(
)
suspend fun updateAlterations() {
alterationStore.updateAlterations()
}
suspend fun updateTags() {
alterationStore.updateTags()
alterationStore.updateAlterationsFlow()
}
fun alteration(
@ -91,10 +86,15 @@ class AlterationRepository(
return activeAlterationMapFlow.map { it[characterSheetId] ?: emptyMap() }
}
@Throws
suspend fun updateAlteration(
alteration: Alteration
alteration: Alteration,
create: Boolean,
) {
alterationStore.putAlteration(alteration)
alterationStore.putAlteration(
alteration = alteration,
create = create,
)
}
suspend fun deleteAlteration(

View file

@ -4,8 +4,6 @@ import com.pixelized.desktop.lwa.network.LwaClient
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.shared.lwa.model.alteration.Alteration
import com.pixelized.shared.lwa.model.alteration.AlterationJsonFactory
import com.pixelized.shared.lwa.model.tag.Tag
import com.pixelized.shared.lwa.model.tag.TagJsonFactory
import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
import kotlinx.coroutines.CoroutineScope
@ -18,22 +16,14 @@ import kotlinx.coroutines.launch
class AlterationStore(
private val networkRepository: NetworkRepository,
private val alterationFactory: AlterationJsonFactory,
private val tagFactory: TagJsonFactory,
private val factory: AlterationJsonFactory,
private val client: LwaClient,
) {
private val _alterationsFlow = MutableStateFlow<Map<String, Alteration>>(emptyMap())
val alterationsFlow: StateFlow<Map<String, Alteration>> = _alterationsFlow
private val _tagsFlow = MutableStateFlow<Map<String, Tag>>(emptyMap())
val tagsFlow: StateFlow<Map<String, Tag>> = _tagsFlow
init {
val scope = CoroutineScope(Dispatchers.IO + Job())
scope.launch {
updateAlterations()
updateTags()
}
// data update through WebSocket.
scope.launch {
networkRepository.data.collect(::handleMessage)
@ -44,19 +34,11 @@ class AlterationStore(
return alterationsFlow.value.values
}
fun tags(): Collection<Tag> {
return tagsFlow.value.values
}
fun alteration(alterationId: String): Alteration? {
return alterationsFlow.value[alterationId]
}
fun tag(tagId: String): Tag? {
return tagsFlow.value[tagId]
}
suspend fun updateAlterations() {
suspend fun updateAlterationsFlow() {
_alterationsFlow.value = try {
getAlteration()
} catch (exception: Exception) {
@ -65,7 +47,7 @@ class AlterationStore(
}
}
suspend fun updateAlteration(
private suspend fun updateAlterationFlow(
alterationId: String,
) {
val alteration = try {
@ -74,9 +56,9 @@ class AlterationStore(
println(exception.message) // TODO proper exception handling
null
}
// guard case if getAlteration failed
if (alteration == null) return
// update the flow with the alteration.
_alterationsFlow.update { alterations ->
alterations.toMutableMap().also {
it[alterationId] = alteration
@ -84,60 +66,59 @@ class AlterationStore(
}
}
suspend fun updateTags() {
_tagsFlow.value = try {
getAlterationTag()
} catch (exception: Exception) {
println(exception.message) // TODO proper exception handling
emptyMap()
}
}
@Throws
private suspend fun getAlteration(): Map<String, Alteration> {
val request = client.alterations()
val data = request.map { alterationFactory.convertFromJson(json = it) }
return data.associateBy { it.id }
val request = client.getAlterations()
return when (request.success) {
true -> request.data
?.map { factory.convertFromJson(json = it) }
?.associateBy { it.id }
?: emptyMap()
else -> LwaClient.error(error = request)
}
}
@Throws
private suspend fun getAlteration(
alterationId: String,
): Alteration? {
val request = client.alterations(alterationId = alterationId)
return request?.let { alterationFactory.convertFromJson(json = it) }
val request = client.getAlteration(alterationId = alterationId)
return when (request.success) {
true -> request.data?.let { factory.convertFromJson(json = it) }
else -> LwaClient.error(error = request)
}
@Throws
private suspend fun getAlterationTag(): Map<String, Tag> {
val request = client.alterationTags()
val data = request.map { tagFactory.convertFromJson(json = it) }
return data.associateBy { it.id }
}
@Throws
suspend fun putAlteration(
alteration: Alteration,
create: Boolean,
) {
client.updateAlteration(
alterationJson = alterationFactory.convertToJson(data = alteration)
val request = client.putAlteration(
alterationJson = factory.convertToJson(data = alteration),
create = create,
)
if (request.success.not()) {
LwaClient.error(error = request)
}
}
@Throws
suspend fun deleteAlteration(
alterationId: String
alterationId: String,
) {
client.deleteAlteration(
alterationId = alterationId
)
val request = client.deleteAlteration(alterationId = alterationId)
if (request.success.not()) {
LwaClient.error(error = request)
}
}
// region: WebSocket & data update.
private suspend fun handleMessage(message: SocketMessage) {
when (message) {
is ApiSynchronisation.AlterationUpdate -> updateAlteration(
is ApiSynchronisation.AlterationUpdate -> updateAlterationFlow(
alterationId = message.alterationId,
)

View file

@ -3,33 +3,45 @@ package com.pixelized.desktop.lwa.repository.campaign
class CampaignRepository(
private val store: CampaignStore,
) {
val campaignFlow get() = store.campaignFlow
val campaignFlow = store.campaignFlow()
suspend fun updateCampaign() {
store.campaign(update = true)
store.updateCampaignFlow()
}
@Throws
suspend fun addCharacter(
characterSheetId: String,
) = store.addCharacter(
characterSheetId = characterSheetId,
)
suspend fun removeCharacter(
characterSheetId: String,
) = store.removeCharacter(
characterSheetId = characterSheetId,
)
suspend fun addNpc(
characterSheetId: String,
) = store.addNpc(
characterSheetId = characterSheetId,
)
suspend fun removeNpc(
characterSheetId: String,
) = store.removeNpc(
) {
store.addCharacter(
characterSheetId = characterSheetId,
)
}
@Throws
suspend fun removeCharacter(
characterSheetId: String,
) {
store.removeCharacter(
characterSheetId = characterSheetId,
)
}
@Throws
suspend fun addNpc(
characterSheetId: String,
) {
store.addNpc(
characterSheetId = characterSheetId,
)
}
@Throws
suspend fun removeNpc(
characterSheetId: String,
) {
store.removeNpc(
characterSheetId = characterSheetId,
)
}
}

View file

@ -19,81 +19,76 @@ class CampaignStore(
private val client: LwaClient,
private val network: NetworkRepository,
private val factory: CampaignJsonFactory,
) {
private val _campaignFlow = MutableStateFlow(value = Campaign.empty())
val campaignFlow: StateFlow<Campaign> get() = _campaignFlow
private val campaignFlow = MutableStateFlow(value = Campaign.empty())
init {
val scope = CoroutineScope(Dispatchers.IO + Job())
scope.launch {
campaign(update = true)
}
scope.launch {
network.data.collect(::handleMessage)
}
}
suspend fun campaign(update: Boolean): Campaign {
val campaign = _campaignFlow.value
if (update || campaign == Campaign.empty()) {
val data = try {
val request = client.campaign()
factory.convertFromJson(json = request)
fun campaignFlow(): StateFlow<Campaign> = campaignFlow
suspend fun updateCampaignFlow() {
campaignFlow.value = try {
getCampaign()
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
println(exception.message) // TODO proper exception handling
Campaign.empty()
}
return _campaignFlow.update(data)
}
return campaign
}
@Throws
suspend fun addCharacter(
characterSheetId: String,
) {
try {
client.campaignAddCharacter(
characterSheetId = characterSheetId
)
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
val request = client.putCampaignCharacter(characterSheetId = characterSheetId)
if (request.success.not()) {
LwaClient.error(error = request)
}
}
@Throws
suspend fun removeCharacter(
characterSheetId: String,
) {
try {
client.campaignRemoveCharacter(
characterSheetId = characterSheetId,
)
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
val request = client.removeCampaignCharacter(characterSheetId = characterSheetId)
if (request.success.not()) {
LwaClient.error(error = request)
}
}
@Throws
suspend fun addNpc(
characterSheetId: String,
) {
try {
client.campaignAddNpc(
characterSheetId = characterSheetId
)
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
val request = client.putCampaignNpc(characterSheetId = characterSheetId)
if (request.success.not()) {
LwaClient.error(error = request)
}
}
@Throws
suspend fun removeNpc(
characterSheetId: String,
) {
try {
client.campaignRemoveNpc(
characterSheetId = characterSheetId,
)
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
val request = client.removeCampaignNpc(characterSheetId = characterSheetId)
if (request.success.not()) {
LwaClient.error(error = request)
}
}
@Throws
private suspend fun getCampaign(): Campaign {
val request = client.getCampaign()
return when (request.success) {
true -> request.data
?.let { factory.convertFromJson(json = it) }
?: Campaign.empty()
else -> LwaClient.error(error = request)
}
}
@ -103,7 +98,7 @@ class CampaignStore(
when (message) {
is CampaignEvent -> {
when (message) {
is CampaignEvent.CharacterAdded -> _campaignFlow.update { campaign ->
is CampaignEvent.CharacterAdded -> campaignFlow.update { campaign ->
campaign.copy(
characters = campaign.characters.toMutableSet().also {
it.add(message.characterSheetId)
@ -111,7 +106,7 @@ class CampaignStore(
)
}
is CampaignEvent.CharacterRemoved -> _campaignFlow.update { campaign ->
is CampaignEvent.CharacterRemoved -> campaignFlow.update { campaign ->
campaign.copy(
characters = campaign.characters.toMutableSet().also {
it.remove(message.characterSheetId)
@ -119,7 +114,7 @@ class CampaignStore(
)
}
is CampaignEvent.NpcAdded -> _campaignFlow.update { campaign ->
is CampaignEvent.NpcAdded -> campaignFlow.update { campaign ->
campaign.copy(
npcs = campaign.npcs.toMutableSet().also {
it.add(message.characterSheetId)
@ -127,7 +122,7 @@ class CampaignStore(
)
}
is CampaignEvent.NpcRemoved -> _campaignFlow.update { campaign ->
is CampaignEvent.NpcRemoved -> campaignFlow.update { campaign ->
campaign.copy(
npcs = campaign.npcs.toMutableSet().also {
it.remove(message.characterSheetId)
@ -135,7 +130,7 @@ class CampaignStore(
)
}
is CampaignEvent.UpdateScene -> _campaignFlow.update { campaign ->
is CampaignEvent.UpdateScene -> campaignFlow.update { campaign ->
campaign.copy(
scene = Campaign.Scene(name = message.name)
)
@ -145,17 +140,17 @@ class CampaignStore(
is GameMasterEvent -> when (message) {
is GameMasterEvent.ToggleNpc -> {
_campaignFlow.value = _campaignFlow.value.copy(
options = _campaignFlow.value.options.copy(
showNpcs = _campaignFlow.value.options.showNpcs.not()
campaignFlow.value = campaignFlow.value.copy(
options = campaignFlow.value.options.copy(
showNpcs = campaignFlow.value.options.showNpcs.not()
)
)
}
is GameMasterEvent.TogglePlayer -> {
_campaignFlow.value = _campaignFlow.value.copy(
options = _campaignFlow.value.options.copy(
showParty = _campaignFlow.value.options.showParty.not()
campaignFlow.value = campaignFlow.value.copy(
options = campaignFlow.value.options.copy(
showParty = campaignFlow.value.options.showParty.not()
)
)
}
@ -168,9 +163,4 @@ class CampaignStore(
}
// endregion
private fun MutableStateFlow<Campaign>.update(campaign: Campaign): Campaign {
value = campaign
return campaign
}
}

View file

@ -18,46 +18,27 @@ class CharacterSheetRepository(
val characterSheetPreviewFlow get() = store.previewFlow
val characterDetailFlow get() = store.detailFlow
val tagsFlow get() = store.tagsFlow
suspend fun updateCharacterPreviews() {
store.updateCharactersPreview()
store.updateCharactersPreviewFlow()
}
suspend fun updateTags() {
store.updateTags()
suspend fun updateCharacterSheet(characterSheetId: String) {
store.updateCharacterSheetDetailFlow(characterSheetId = characterSheetId)
}
fun characterPreview(characterId: String?): CharacterSheetPreview? {
return characterSheetPreviewFlow.value.firstOrNull { it.characterSheetId == characterId }
}
suspend fun characterDetail(
fun characterDetail(
characterSheetId: String?,
forceUpdate: Boolean = false,
): CharacterSheet? {
return try {
characterSheetId?.let {
store.getCharacterSheet(
characterSheetId = it,
forceUpdate = forceUpdate
)
}
} catch (exception: Exception) {
null
}
return store.detailFlow.value[characterSheetId]
}
fun characterDetailFlow(
characterSheetId: String?,
): StateFlow<CharacterSheet?> {
val initial = store.detailFlow.value[characterSheetId]
if (initial == null) {
scope.launch { characterDetail(characterSheetId = characterSheetId) }
}
return store.detailFlow
.map { sheets ->
sheets[characterSheetId]
@ -65,16 +46,18 @@ class CharacterSheetRepository(
.stateIn(
scope = scope,
started = SharingStarted.Eagerly,
initialValue = initial,
initialValue = store.detailFlow.value[characterSheetId],
)
}
@Throws
suspend fun updateCharacter(
sheet: CharacterSheet,
) {
store.updateCharacterSheet(sheet = sheet)
}
@Throws
suspend fun deleteCharacter(
characterSheetId: String,
) {

View file

@ -6,12 +6,9 @@ import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetPreview
import com.pixelized.shared.lwa.model.characterSheet.factory.CharacterSheetJsonFactory
import com.pixelized.shared.lwa.model.tag.Tag
import com.pixelized.shared.lwa.model.tag.TagJsonFactory
import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent
import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
import com.pixelized.shared.lwa.usecase.CharacterSheetUseCase
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@ -25,7 +22,6 @@ class CharacterSheetStore(
private val client: LwaClient,
private val network: NetworkRepository,
private val factory: CharacterSheetJsonFactory,
private val tagFactory: TagJsonFactory,
) {
private val _previewFlow = MutableStateFlow<List<CharacterSheetPreview>>(value = emptyList())
val previewFlow: StateFlow<List<CharacterSheetPreview>> get() = _previewFlow
@ -33,16 +29,8 @@ class CharacterSheetStore(
private val _detailFlow = MutableStateFlow<Map<String, CharacterSheet>>(value = emptyMap())
val detailFlow: StateFlow<Map<String, CharacterSheet>> get() = _detailFlow
private val _tagsFlow = MutableStateFlow<Map<String, Tag>>(emptyMap())
val tagsFlow: StateFlow<Map<String, Tag>> = _tagsFlow
init {
val scope = CoroutineScope(Dispatchers.IO + Job())
// initial data loading.
scope.launch {
updateCharactersPreview()
updateTags()
}
// data update through WebSocket.
scope.launch {
network.data.collect(::handleMessage)
@ -51,71 +39,75 @@ class CharacterSheetStore(
// region Rest
suspend fun updateCharactersPreview(): List<CharacterSheetPreview> {
val request = try {
client.characters()
suspend fun updateCharactersPreviewFlow() {
_previewFlow.value = try {
getCharacters()
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
println(exception.message) // TODO proper exception handling
emptyList()
}
val characters = request.map {
factory.convertFromJson(it)
}
return _previewFlow.update(characters)
}
suspend fun updateTags(): Map<String, Tag> {
val request = try {
client.characterTags()
suspend fun updateCharacterSheetDetailFlow(
characterSheetId: String,
) {
val characterSheet = try {
getCharacterSheet(characterSheetId = characterSheetId)
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
emptyList()
println(exception.message) // TODO proper exception handling
null
}
if (characterSheet == null) return
_detailFlow.update { data ->
data.toMutableMap().also {
it[characterSheetId] = characterSheet
}
}
val tags = request.map {
tagFactory.convertFromJson(json = it)
}.associateBy { it.id }
_tagsFlow.value = tags
return tags
}
@Throws
suspend fun getCharacters(): List<CharacterSheetPreview> {
val request = client.getCharacters()
return when (request.success) {
true -> request.data
?.map { factory.convertFromJson(it) }
?: emptyList()
else -> LwaClient.error(error = request)
}
}
@Throws
suspend fun getCharacterSheet(
characterSheetId: String,
forceUpdate: Boolean = false,
): CharacterSheet? {
val character = _detailFlow.value[characterSheetId]
if (forceUpdate || character == null) {
try {
val request = client.character(characterSheetId = characterSheetId)
val data = factory.convertFromJson(json = request)
return _detailFlow.update(data)
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
return null
): CharacterSheet {
val request = client.getCharacter(characterSheetId = characterSheetId)
return when (request.success) {
true -> request.data!!.let { factory.convertFromJson(json = it) }
else -> LwaClient.error(error = request)
}
}
return character
}
// TODO check crash
@Throws
suspend fun updateCharacterSheet(
sheet: CharacterSheet,
) {
val json = factory.convertToJson(sheet = sheet)
try {
client.updateCharacter(sheet = json)
} catch (exception: Exception) {
println(exception) // TODO
val request = client.putCharacter(sheet = json)
if (request.success) {
LwaClient.error(error = request)
}
_detailFlow.update(sheet = sheet)
}
// TODO check crash
@Throws
suspend fun deleteCharacterSheet(
characterSheetId: String,
) {
try {
client.deleteCharacterSheet(characterSheetId = characterSheetId)
} catch (exception: Exception) {
println(exception) // TODO
val request = client.deleteCharacterSheet(characterSheetId = characterSheetId)
if (request.success) {
LwaClient.error(error = request)
}
}
@ -124,14 +116,14 @@ class CharacterSheetStore(
private suspend fun handleMessage(message: SocketMessage) {
when (message) {
is ApiSynchronisation -> when (message) {
is ApiSynchronisation -> try {
when (message) {
is ApiSynchronisation.CharacterSheetUpdate -> {
getCharacterSheet(
characterSheetId = message.characterSheetId,
forceUpdate = true,
_detailFlow.update(
sheet = getCharacterSheet(characterSheetId = message.characterSheetId)
)
if (_previewFlow.value.firstOrNull { it.characterSheetId == message.characterSheetId } == null) {
updateCharactersPreview()
_previewFlow.value = getCharacters()
}
}
@ -151,6 +143,9 @@ class CharacterSheetStore(
is ApiSynchronisation.AlterationUpdate -> Unit
is ApiSynchronisation.AlterationDelete -> Unit
}
} catch (exception: Exception) {
println(exception.message) // TODO proper exception handling
}
is CharacterSheetEvent -> when (message) {
is CharacterSheetEvent.UpdateAlteration -> updateAlterations(
@ -190,7 +185,7 @@ class CharacterSheetStore(
skillId: String,
used: Boolean,
) {
val sheet = getCharacterSheet(characterSheetId = characterSheetId) ?: return
val sheet = getCharacterSheet(characterSheetId = characterSheetId)
val character = sheet.copy(
commonSkills = sheet.commonSkills.map { skill ->
skill.takeIf { skill.id == skillId }?.copy(used = used) ?: skill
@ -211,7 +206,7 @@ class CharacterSheetStore(
active: Boolean,
) {
if (alterationStore.alteration(alterationId = alterationId) == null) return
val sheet = getCharacterSheet(characterSheetId = characterSheetId) ?: return
val sheet = getCharacterSheet(characterSheetId = characterSheetId)
val containAlteration = sheet.alterations.contains(alterationId)
@ -233,7 +228,7 @@ class CharacterSheetStore(
characterSheetId: String,
damage: Int,
) {
val sheet = getCharacterSheet(characterSheetId = characterSheetId) ?: return
val sheet = getCharacterSheet(characterSheetId = characterSheetId)
_detailFlow.update(sheet.copy(damage = damage))
}
@ -241,7 +236,7 @@ class CharacterSheetStore(
characterSheetId: String,
diminished: Int,
) {
val sheet = getCharacterSheet(characterSheetId = characterSheetId) ?: return
val sheet = getCharacterSheet(characterSheetId = characterSheetId)
_detailFlow.update(sheet.copy(diminished = diminished))
}
@ -249,18 +244,12 @@ class CharacterSheetStore(
characterSheetId: String,
fatigue: Int,
) {
val sheet = getCharacterSheet(characterSheetId = characterSheetId) ?: return
val sheet = getCharacterSheet(characterSheetId = characterSheetId)
_detailFlow.update(sheet.copy(fatigue = fatigue))
}
// endregion
private fun MutableStateFlow<List<CharacterSheetPreview>>.update(
previews: List<CharacterSheetPreview>,
): List<CharacterSheetPreview> {
value = previews
return previews
}
private fun MutableStateFlow<Map<String, CharacterSheet>>.update(
sheet: CharacterSheet,

View file

@ -0,0 +1,16 @@
package com.pixelized.desktop.lwa.repository.tag
import com.pixelized.shared.lwa.model.tag.Tag
import kotlinx.coroutines.flow.StateFlow
class TagRepository(
private val store: TagStore,
) {
suspend fun updateCharacterTags() = store.updateCharacterTagsFlow()
suspend fun updateAlterationTags() = store.updateAlterationTagsFlow()
fun charactersTagFlow(): StateFlow<Map<String, Tag>> = store.charactersTagFlow()
fun alterationsTagFlow(): StateFlow<Map<String, Tag>> = store.alterationsTagFlow()
}

View file

@ -0,0 +1,79 @@
package com.pixelized.desktop.lwa.repository.tag
import com.pixelized.desktop.lwa.network.LwaClient
import com.pixelized.shared.lwa.model.tag.Tag
import com.pixelized.shared.lwa.model.tag.TagJsonFactory
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
class TagStore(
private val factory: TagJsonFactory,
private val client: LwaClient,
) {
private val characterTagsFlow = MutableStateFlow<Map<String, Tag>>(emptyMap())
private val alterationTagsFlow = MutableStateFlow<Map<String, Tag>>(emptyMap())
fun charactersTagFlow(): StateFlow<Map<String, Tag>> = characterTagsFlow
fun characters(): Collection<Tag> {
return characterTagsFlow.value.values
}
fun character(tagId: String): Tag? {
return characterTagsFlow.value[tagId]
}
fun alterationsTagFlow(): StateFlow<Map<String, Tag>> = alterationTagsFlow
fun alterations(): Collection<Tag> {
return alterationTagsFlow.value.values
}
fun alteration(tagId: String): Tag? {
return alterationTagsFlow.value[tagId]
}
suspend fun updateCharacterTagsFlow() {
characterTagsFlow.value = try {
getCharacterTag()
} catch (exception: Exception) {
println(exception.message) // TODO proper exception handling
emptyMap()
}
}
suspend fun updateAlterationTagsFlow() {
alterationTagsFlow.value = try {
getAlterationTag()
} catch (exception: Exception) {
println(exception.message) // TODO proper exception handling
emptyMap()
}
}
@Throws
private suspend fun getCharacterTag(): Map<String, Tag> {
val request = client.getCharacterTags()
return when (request.success) {
true -> request.data
?.map { factory.convertFromJson(json = it) }
?.associateBy { it.id }
?: emptyMap()
else -> LwaClient.error(error = request)
}
}
@Throws
private suspend fun getAlterationTag(): Map<String, Tag> {
val request = client.getAlterationTags()
return when (request.success) {
true -> request.data
?.map { factory.convertFromJson(json = it) }
?.associateBy { it.id }
?: emptyMap()
else -> LwaClient.error(error = request)
}
}
}

View file

@ -24,7 +24,7 @@ class ErrorSnackUio(
}
@Composable
fun ErrorSnack(
fun ErrorSnackHandler(
snack: SnackbarHostState = LocalErrorSnackHost.current,
error: SharedFlow<ErrorSnackUio>,
) {

View file

@ -43,7 +43,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.LocalSnackHost
import com.pixelized.desktop.lwa.ui.composable.blur.BlurContent
import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnack
import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackHandler
import com.pixelized.desktop.lwa.ui.theme.lwa
import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res
@ -148,7 +148,7 @@ fun NetworkDialog(
}
}
ErrorSnack(
ErrorSnackHandler(
error = viewModel.networkError,
)
}

View file

@ -35,6 +35,7 @@ import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.type
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackHandler
import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextField
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio
@ -109,6 +110,10 @@ fun GMAlterationEditPage(
}
}
ErrorSnackHandler(
error = viewModel.error,
)
AlterationEditKeyHandler(
onDismissRequest = {
screen.popBackStack()

View file

@ -4,8 +4,11 @@ import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackUio
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.gamemaster.GMAlterationEditDestination
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@ -20,6 +23,9 @@ class GMAlterationEditViewModel(
private val _form = MutableStateFlow<GMAlterationEditPageUio?>(null)
val form: StateFlow<GMAlterationEditPageUio?> get() = _form
private val _error = MutableSharedFlow<ErrorSnackUio>()
val error: SharedFlow<ErrorSnackUio> get() = _error
init {
viewModelScope.launch {
_form.value = factory.createForm(
@ -30,14 +36,22 @@ class GMAlterationEditViewModel(
suspend fun save() {
val edited = factory.createAlteration(form = form.value)
val actual = alterationRepository.alterationFlow.value[edited?.id]
// TODO if argument.id == null et actual?.id != null on créer et on écrase existant !!!
if (edited == null) return
if (edited != null)
alterationRepository.updateAlteration(edited)
try {
if (argument.id == null && actual?.id != null) {
error("Id already taken by an another alteration")
}
alterationRepository.updateAlteration(
alteration = edited,
create = argument.id == null,
)
} catch (exception: Exception) {
val message = ErrorSnackUio.from(exception = exception)
_error.emit(message)
}
}
suspend fun addField() {

View file

@ -3,6 +3,7 @@ package com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.list
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
import com.pixelized.desktop.lwa.repository.tag.TagRepository
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio
import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagFactory
import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagUio
@ -22,6 +23,7 @@ import org.jetbrains.compose.resources.getString
class GMAlterationViewModel(
private val alterationRepository: AlterationRepository,
alterationFactory: GMAlterationFactory,
tagRepository: TagRepository,
tagFactory: GMTagFactory,
) : ViewModel() {
@ -38,7 +40,7 @@ class GMAlterationViewModel(
)
val tags: StateFlow<List<GMTagUio>> = combine(
alterationRepository.tagsFlow,
tagRepository.alterationsTagFlow(),
selectedTagId,
) { tags, selectedTagId ->
tagFactory.convertToGMTagItemUio(
@ -53,7 +55,7 @@ class GMAlterationViewModel(
val alterations: StateFlow<List<GMAlterationUio>> = combine(
alterationRepository.alterationFlow,
alterationRepository.tagsFlow,
tagRepository.alterationsTagFlow(),
filter.valueFlow.map { it.unAccent() },
selectedTagId,
) { alterations, tags, unAccentFilter, selectedTagId ->

View file

@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
import com.pixelized.desktop.lwa.repository.tag.TagRepository
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio
import com.pixelized.desktop.lwa.ui.screen.gamemaster.character.list.GMCharacterItemUio.Action
import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagFactory
@ -27,6 +28,7 @@ class GMCharacterViewModel(
private val networkRepository: NetworkRepository,
private val campaignRepository: CampaignRepository,
characterSheetRepository: CharacterSheetRepository,
tagRepository: TagRepository,
private val factory: GMCharacterFactory,
private val tagFactory: GMTagFactory,
) : ViewModel() {
@ -44,7 +46,7 @@ class GMCharacterViewModel(
)
val tags = combine(
characterSheetRepository.tagsFlow,
tagRepository.charactersTagFlow(),
selectedTagId,
) { tags, selectedTagId ->
tagFactory.convertToGMTagItemUio(

View file

@ -39,7 +39,7 @@ class AlterationStore(
alterationFlow.value = try {
load()
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
println(exception.message) // TODO proper exception handling
emptyList()
}
}

View file

@ -38,7 +38,7 @@ class CampaignStore(
campaignFlow.value = try {
load()
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
println(exception.message) // TODO proper exception handling
Campaign.empty()
}
}

View file

@ -38,7 +38,7 @@ class CharacterSheetStore(
characterSheetsFlow.value = try {
load()
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
println(exception.message) // TODO proper exception handling
emptyList()
}
}

View file

@ -49,7 +49,7 @@ class TagStore(
flow.value = try {
file.readTags().associateBy { it.id }
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
println(exception.message) // TODO proper exception handling
emptyMap()
}
}

View file

@ -24,7 +24,7 @@ class Engine(
try {
unSafeHandle(message)
} catch (exception: Exception) {
println(exception) // TODO proper exception handling
println(exception.message) // TODO proper exception handling
}
}

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.alteration
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.alterationId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -19,7 +19,7 @@ fun Engine.deleteAlteration(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses.
call.respond(
message = ResultJson.Success(),
message = APIResponse.success(),
)
webSocket.emit(
value = ApiSynchronisation.AlterationDelete(
@ -29,15 +29,15 @@ fun Engine.deleteAlteration(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -2,7 +2,7 @@ package com.pixelized.server.lwa.server.rest.alteration
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.alterationId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -17,12 +17,14 @@ fun Engine.getAlteration(): suspend RoutingContext.() -> Unit {
?: error("Alteration with id:$alterationId not found.")
// send it back to the user.
call.respond(
message = alteration,
message = APIResponse.success(
data = alteration
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -1,7 +1,7 @@
package com.pixelized.server.lwa.server.rest.alteration
import com.pixelized.server.lwa.server.Engine
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -9,12 +9,14 @@ fun Engine.getAlterationTags(): suspend RoutingContext.() -> Unit {
return {
try {
call.respond(
message = alterationService.tags(),
message = APIResponse.success(
data = alterationService.tags(),
),
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -1,7 +1,7 @@
package com.pixelized.server.lwa.server.rest.alteration
import com.pixelized.server.lwa.server.Engine
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -9,12 +9,14 @@ fun Engine.getAlterations(): suspend RoutingContext.() -> Unit {
return {
try {
call.respond(
message = alterationService.alterations(),
message = APIResponse.success(
data = alterationService.alterations(),
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -4,7 +4,7 @@ import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.create
import com.pixelized.shared.lwa.model.alteration.AlterationJson
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
import io.ktor.server.request.receive
import io.ktor.server.response.respond
@ -21,7 +21,7 @@ fun Engine.putAlteration(): suspend RoutingContext.() -> Unit {
create = create,
)
call.respond(
message = ResultJson.Success(),
message = APIResponse.success(),
)
webSocket.emit(
value = ApiSynchronisation.AlterationUpdate(
@ -31,15 +31,15 @@ fun Engine.putAlteration(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.campaign
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -19,7 +19,7 @@ fun Engine.removeCampaignCharacter(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses
call.respond(
message = ResultJson.Success(),
message = APIResponse.success(),
)
webSocket.emit(
value = CampaignEvent.CharacterRemoved(
@ -29,15 +29,15 @@ fun Engine.removeCampaignCharacter(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.campaign
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -19,7 +19,7 @@ fun Engine.removeCampaignNpc(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses
call.respond(
message = ResultJson.Success(),
message = APIResponse.success(),
)
webSocket.emit(
value = CampaignEvent.NpcRemoved(
@ -29,15 +29,15 @@ fun Engine.removeCampaignNpc(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -1,7 +1,7 @@
package com.pixelized.server.lwa.server.rest.campaign
import com.pixelized.server.lwa.server.Engine
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -9,12 +9,14 @@ fun Engine.getCampaign(): suspend RoutingContext.() -> Unit {
return {
try {
call.respond(
message = campaignService.campaignJson(),
message = APIResponse.success(
data = campaignService.campaignJson(),
),
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.campaign
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -19,7 +19,7 @@ fun Engine.putCampaignCharacter(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses.
call.respond(
message = ResultJson.Success(),
message = APIResponse.success(),
)
webSocket.emit(
value = CampaignEvent.CharacterAdded(
@ -29,15 +29,15 @@ fun Engine.putCampaignCharacter(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.campaign
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -19,7 +19,7 @@ fun Engine.putCampaignNpc(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses.
call.respond(
message = ResultJson.Success(),
message = APIResponse.success(),
)
webSocket.emit(
value = CampaignEvent.NpcAdded(
@ -29,15 +29,15 @@ fun Engine.putCampaignNpc(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.campaign
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.shared.lwa.model.campaign.CampaignJsonV2
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent
import io.ktor.server.request.receive
import io.ktor.server.response.respond
@ -17,10 +17,12 @@ fun Engine.putCampaignScene(): suspend RoutingContext.() -> Unit {
// convert the scene into the a usable data model.
val scene = campaignJsonFactory.convertFromJson(json = form)
// update the campaign.
campaignService.setScene(scene = scene)
campaignService.setScene(
scene = scene,
)
// API & WebSocket responses
call.respond(
message = ResultJson.Success(),
message = APIResponse.success(),
)
webSocket.emit(
value = CampaignEvent.UpdateScene(
@ -30,15 +32,15 @@ fun Engine.putCampaignScene(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.character
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -19,7 +19,7 @@ fun Engine.deleteCharacter(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses.
call.respond(
message = ResultJson.Success()
message = APIResponse.success()
)
webSocket.emit(
value = ApiSynchronisation.CharacterSheetDelete(
@ -29,15 +29,15 @@ fun Engine.deleteCharacter(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.character
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -18,19 +18,21 @@ fun Engine.getCharacter(): suspend RoutingContext.() -> Unit {
?: error("CharacterSheet with id:$characterSheetId not found.")
// send it back to the user.
call.respond(
message = characterSheet,
message = APIResponse.success(
data = characterSheet,
),
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -1,7 +1,7 @@
package com.pixelized.server.lwa.server.rest.character
import com.pixelized.server.lwa.server.Engine
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -9,12 +9,14 @@ fun Engine.getCharacterTags(): suspend RoutingContext.() -> Unit {
return {
try {
call.respond(
message = characterService.tags(),
message = APIResponse.success(
data = characterService.tags(),
),
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -1,7 +1,7 @@
package com.pixelized.server.lwa.server.rest.character
import com.pixelized.server.lwa.server.Engine
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -9,12 +9,14 @@ fun Engine.getCharacters(): suspend RoutingContext.() -> Unit {
return {
try {
call.respond(
message = characterService.charactersJson(),
message = APIResponse.success(
data = characterService.charactersJson(),
),
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -4,7 +4,7 @@ import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.create
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheetJson
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
import io.ktor.server.request.receive
import io.ktor.server.response.respond
@ -20,7 +20,7 @@ fun Engine.putCharacter(): suspend RoutingContext.() -> Unit {
create = create,
)
call.respond(
message = ResultJson.Success()
message = APIResponse.success()
)
webSocket.emit(
value = ApiSynchronisation.CharacterSheetUpdate(
@ -30,15 +30,15 @@ fun Engine.putCharacter(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -5,7 +5,7 @@ import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.active
import com.pixelized.server.lwa.utils.extentions.alterationId
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -25,7 +25,7 @@ fun Engine.putCharacterAlteration(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses.
call.respond(
message = ResultJson.Success()
message = APIResponse.success()
)
webSocket.emit(
value = CharacterSheetEvent.UpdateAlteration(
@ -37,15 +37,15 @@ fun Engine.putCharacterAlteration(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.character
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -16,7 +16,7 @@ fun Engine.putCharacterDamage(): suspend RoutingContext.() -> Unit {
val damage = call.queryParameters["damage"]?.toIntOrNull()
?: throw MissingParameterException(
name = "damage",
errorCode = ResultJson.Error.MISSING_DAMAGE
errorCode = APIResponse.MISSING_DAMAGE
)
// fetch the character sheet
val characterSheet = characterService.character(characterSheetId)
@ -28,7 +28,7 @@ fun Engine.putCharacterDamage(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses.
call.respond(
message = ResultJson.Success()
message = APIResponse.success()
)
webSocket.emit(
value = CharacterSheetEvent.UpdateDamage(
@ -40,15 +40,15 @@ fun Engine.putCharacterDamage(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.character
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -16,7 +16,7 @@ fun Engine.putCharacterDiminished(): suspend RoutingContext.() -> Unit {
val diminished = call.queryParameters["diminished"]?.toIntOrNull()
?: throw MissingParameterException(
name = "diminished",
errorCode = ResultJson.Error.MISSING_DIMINISHED
errorCode = APIResponse.MISSING_DIMINISHED
)
// Update the character damage
characterService.updateDiminished(
@ -25,7 +25,7 @@ fun Engine.putCharacterDiminished(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses.
call.respond(
message = ResultJson.Success()
message = APIResponse.success()
)
webSocket.emit(
value = CharacterSheetEvent.UpdateDiminished(
@ -36,15 +36,15 @@ fun Engine.putCharacterDiminished(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -3,7 +3,7 @@ package com.pixelized.server.lwa.server.rest.character
import com.pixelized.server.lwa.server.Engine
import com.pixelized.server.lwa.utils.extentions.MissingParameterException
import com.pixelized.server.lwa.utils.extentions.characterSheetId
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent
import io.ktor.server.response.respond
import io.ktor.server.routing.RoutingContext
@ -16,7 +16,7 @@ fun Engine.putCharacterFatigue(): suspend RoutingContext.() -> Unit {
val fatigue = call.queryParameters["fatigue"]?.toIntOrNull()
?: throw MissingParameterException(
name = "fatigue",
errorCode = ResultJson.Error.MISSING_FATIGUE
errorCode = APIResponse.MISSING_FATIGUE
)
// fetch the character sheet
val characterSheet = characterService.character(characterSheetId)
@ -28,7 +28,7 @@ fun Engine.putCharacterFatigue(): suspend RoutingContext.() -> Unit {
)
// API & WebSocket responses.
call.respond(
message = ResultJson.Success()
message = APIResponse.success()
)
webSocket.emit(
value = CharacterSheetEvent.UpdateFatigue(
@ -40,15 +40,15 @@ fun Engine.putCharacterFatigue(): suspend RoutingContext.() -> Unit {
)
} catch (exception: MissingParameterException) {
call.respond(
message = ResultJson.Error(
message = APIResponse.error(
status = exception.errorCode,
message = exception.message ?: "?",
)
)
} catch (exception: Exception) {
call.respond(
message = ResultJson.Error(
status = ResultJson.Error.GENERIC,
message = APIResponse.error(
status = APIResponse.GENERIC,
message = exception.message ?: "?",
)
)

View file

@ -1,13 +1,13 @@
package com.pixelized.server.lwa.utils.extentions
import com.pixelized.shared.lwa.protocol.rest.ResultJson
import com.pixelized.shared.lwa.protocol.rest.APIResponse
import io.ktor.http.Parameters
val Parameters.characterSheetId
get() = "characterSheetId".let { param ->
this[param] ?: throw MissingParameterException(
name = param,
errorCode = ResultJson.Error.MISSING_CHARACTER_SHEET_ID,
errorCode = APIResponse.MISSING_CHARACTER_SHEET_ID,
)
}
@ -15,7 +15,7 @@ val Parameters.alterationId
get() = "alterationId".let { param ->
this[param] ?: throw MissingParameterException(
name = param,
errorCode = ResultJson.Error.MISSING_ALTERATION_ID,
errorCode = APIResponse.MISSING_ALTERATION_ID,
)
}
@ -23,7 +23,7 @@ val Parameters.create
get() = "create".let { param ->
this[param]?.toBooleanStrictOrNull() ?: throw MissingParameterException(
name = param,
errorCode = ResultJson.Error.MISSING_CREATE
errorCode = APIResponse.MISSING_CREATE
)
}
@ -31,7 +31,7 @@ val Parameters.active
get() = "active".let { param ->
this[param]?.toBooleanStrictOrNull() ?: throw MissingParameterException(
name = param,
errorCode = ResultJson.Error.MISSING_ACTIVE
errorCode = APIResponse.MISSING_ACTIVE
)
}

View file

@ -0,0 +1,52 @@
package com.pixelized.shared.lwa.protocol.rest
import kotlinx.serialization.Serializable
@Serializable
data class APIResponse<T>(
val success: Boolean,
val status: Int,
val message: String?,
val data: T?,
) {
companion object {
const val SUCCESS = 100
const val GENERIC = 600
const val MISSING_PARAMETER = 700
const val MISSING_CHARACTER_SHEET_ID = MISSING_PARAMETER + 1
const val MISSING_ALTERATION_ID = MISSING_PARAMETER + 2
const val MISSING_CREATE = MISSING_PARAMETER + 3
const val MISSING_ACTIVE = MISSING_PARAMETER + 4
const val MISSING_DAMAGE = MISSING_PARAMETER + 5
const val MISSING_FATIGUE = MISSING_PARAMETER + 6
const val MISSING_DIMINISHED = MISSING_PARAMETER + 7
fun error(
status: Int,
message: String?,
) = APIResponse(
success = false,
status = status,
message = message,
data = null,
)
fun success() = APIResponse(
success = true,
status = SUCCESS,
message = null,
data = null,
)
inline fun <reified T> success(
data: T? = null,
) = APIResponse(
success = true,
status = SUCCESS,
message = null,
data = data,
)
}
}

View file

@ -1,34 +0,0 @@
package com.pixelized.shared.lwa.protocol.rest
import kotlinx.serialization.Serializable
@Serializable
sealed interface ResultJson {
val success: Boolean
@Serializable
data class Error(
override val success: Boolean = false,
val status: Int,
val message: String,
) : ResultJson {
companion object {
const val GENERIC = 600
const val MISSING_PARAMETER = 700
const val MISSING_CHARACTER_SHEET_ID = MISSING_PARAMETER + 1
const val MISSING_ALTERATION_ID = MISSING_PARAMETER + 2
const val MISSING_CREATE = MISSING_PARAMETER + 3
const val MISSING_ACTIVE = MISSING_PARAMETER + 4
const val MISSING_DAMAGE = MISSING_PARAMETER + 5
const val MISSING_FATIGUE = MISSING_PARAMETER + 6
const val MISSING_DIMINISHED = MISSING_PARAMETER + 7
}
}
@Serializable
data class Success(
override val success: Boolean = true,
val status: Int = 100,
) : ResultJson
}