Change the Damage/Fatigue/Diminished text message feature.
This commit is contained in:
parent
8f87c63e34
commit
193b0d85d5
12 changed files with 51 additions and 26 deletions
|
|
@ -58,7 +58,7 @@ class DataSyncViewModel(
|
||||||
|
|
||||||
networkRepository.status
|
networkRepository.status
|
||||||
.filter { status -> status == NetworkRepository.Status.CONNECTED }
|
.filter { status -> status == NetworkRepository.Status.CONNECTED }
|
||||||
.flatMapLatest { campaignRepository.campaignFlow.map { it.instances } }
|
.flatMapLatest { campaignRepository.campaignFlow().map { it.instances } }
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.onEach { instances ->
|
.onEach { instances ->
|
||||||
instances.forEach { characterSheetId ->
|
instances.forEach { characterSheetId ->
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ class AlterationRepository(
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
private val campaignCharactersFlow: Flow<Map<String, List<String>>> =
|
private val campaignCharactersFlow: Flow<Map<String, List<String>>> =
|
||||||
campaignRepository.campaignFlow
|
campaignRepository.campaignFlow()
|
||||||
.flatMapLatest { campaign ->
|
.flatMapLatest { campaign ->
|
||||||
val flows = campaign.instances.map {
|
val flows = campaign.instances.map {
|
||||||
characterRepository.characterDetailFlow(characterSheetId = it)
|
characterRepository.characterDetailFlow(characterSheetId = it)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
package com.pixelized.desktop.lwa.repository.campaign
|
package com.pixelized.desktop.lwa.repository.campaign
|
||||||
|
|
||||||
|
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
class CampaignRepository(
|
class CampaignRepository(
|
||||||
private val store: CampaignStore,
|
private val store: CampaignStore,
|
||||||
) {
|
) {
|
||||||
val campaignFlow = store.campaignFlow()
|
fun campaignFlow(): StateFlow<Campaign> {
|
||||||
|
return store.campaignFlow()
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun updateCampaign() {
|
suspend fun updateCampaign() {
|
||||||
store.updateCampaignFlow()
|
store.updateCampaignFlow()
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,9 @@ class CharacterSheetRepository(
|
||||||
) {
|
) {
|
||||||
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||||
|
|
||||||
val characterSheetPreviewFlow get() = store.previewFlow
|
fun characterSheetPreviewFlow(): StateFlow<List<CharacterSheetPreview>> {
|
||||||
|
return store.previewFlow
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun updateCharacterPreviews() {
|
suspend fun updateCharacterPreviews() {
|
||||||
store.updateCharactersPreviewFlow()
|
store.updateCharactersPreviewFlow()
|
||||||
|
|
@ -26,7 +28,7 @@ class CharacterSheetRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun characterPreview(characterId: String?): CharacterSheetPreview? {
|
fun characterPreview(characterId: String?): CharacterSheetPreview? {
|
||||||
return characterSheetPreviewFlow.value.firstOrNull { it.characterSheetId == characterId }
|
return store.previewFlow.value.firstOrNull { it.characterSheetId == characterId }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun characterDetail(
|
fun characterDetail(
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,12 @@ class RollHistoryRepository(
|
||||||
) {
|
) {
|
||||||
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
private val scope = CoroutineScope(Dispatchers.IO + Job())
|
||||||
|
|
||||||
val rolls: SharedFlow<RollEvent> = network.data
|
private val rolls: SharedFlow<RollEvent> = network.data
|
||||||
.filterIsInstance(RollEvent::class)
|
.filterIsInstance(RollEvent::class)
|
||||||
.shareIn(
|
.shareIn(
|
||||||
scope = scope,
|
scope = scope,
|
||||||
started = SharingStarted.Eagerly,
|
started = SharingStarted.Eagerly,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun rolls(): SharedFlow<RollEvent> = rolls
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +64,7 @@ abstract class CharacterRibbonViewModel(
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
val characters: StateFlow<List<CharacterPortraitUio>> = combine(
|
val characters: StateFlow<List<CharacterPortraitUio>> = combine(
|
||||||
settingsRepository.settingsFlow(),
|
settingsRepository.settingsFlow(),
|
||||||
campaignRepository.campaignFlow,
|
campaignRepository.campaignFlow(),
|
||||||
) { settings, campaign -> campaign to settings }
|
) { settings, campaign -> campaign to settings }
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.flatMapLatest { (campaign, settings) ->
|
.flatMapLatest { (campaign, settings) ->
|
||||||
|
|
@ -111,7 +111,7 @@ abstract class CharacterRibbonViewModel(
|
||||||
LaunchedEffect(characterSheetId) {
|
LaunchedEffect(characterSheetId) {
|
||||||
combine(
|
combine(
|
||||||
settingsRepository.settingsFlow(),
|
settingsRepository.settingsFlow(),
|
||||||
rollHistoryRepository.rolls,
|
rollHistoryRepository.rolls(),
|
||||||
) { settings, roll ->
|
) { settings, roll ->
|
||||||
if (settings.portrait.dynamicDice && characterSheetId == roll.characterSheetId) {
|
if (settings.portrait.dynamicDice && characterSheetId == roll.characterSheetId) {
|
||||||
state.value = CharacterPortraitRollUio(
|
state.value = CharacterPortraitRollUio(
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.compose.animation.core.Animatable
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
|
||||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||||
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
|
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
|
||||||
import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
|
import com.pixelized.shared.lwa.protocol.websocket.SocketMessage
|
||||||
|
|
@ -16,6 +17,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
||||||
class CampaignChatViewModel(
|
class CampaignChatViewModel(
|
||||||
private val settingsRepository: SettingsRepository,
|
private val settingsRepository: SettingsRepository,
|
||||||
|
private val campaignRepository: CampaignRepository,
|
||||||
networkRepository: NetworkRepository,
|
networkRepository: NetworkRepository,
|
||||||
textMessageFactory: TextMessageFactory,
|
textMessageFactory: TextMessageFactory,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
@ -36,14 +38,16 @@ class CampaignChatViewModel(
|
||||||
|
|
||||||
val messages = combine(
|
val messages = combine(
|
||||||
settingsRepository.settingsFlow(),
|
settingsRepository.settingsFlow(),
|
||||||
|
campaignRepository.campaignFlow(),
|
||||||
networkRepository.data.runningFold(
|
networkRepository.data.runningFold(
|
||||||
initial = mutableListOf(),
|
initial = mutableListOf(),
|
||||||
operation = List<SocketMessage>::plus
|
operation = List<SocketMessage>::plus
|
||||||
)
|
)
|
||||||
) { settings, messages ->
|
) { settings, campaign, messages ->
|
||||||
messages.mapNotNull { message ->
|
messages.mapNotNull { message ->
|
||||||
textMessageFactory.convertToTextMessage(
|
textMessageFactory.convertToTextMessage(
|
||||||
settings = settings,
|
settings = settings,
|
||||||
|
campaign = campaign,
|
||||||
message = message,
|
message = message,
|
||||||
)
|
)
|
||||||
}.takeLast(
|
}.takeLast(
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,7 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.Characteristic
|
||||||
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.DiminishedTextMessageUio
|
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.DiminishedTextMessageUio
|
||||||
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessageUio
|
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessageUio
|
||||||
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage
|
import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage
|
||||||
import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Damage
|
import com.pixelized.shared.lwa.model.campaign.Campaign
|
||||||
import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Power
|
|
||||||
import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
|
import com.pixelized.shared.lwa.protocol.websocket.ApiSynchronisation
|
||||||
import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent
|
import com.pixelized.shared.lwa.protocol.websocket.CampaignEvent
|
||||||
import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent
|
import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent
|
||||||
|
|
@ -29,6 +28,7 @@ class TextMessageFactory(
|
||||||
|
|
||||||
suspend fun convertToTextMessage(
|
suspend fun convertToTextMessage(
|
||||||
settings: Settings,
|
settings: Settings,
|
||||||
|
campaign: Campaign,
|
||||||
message: SocketMessage,
|
message: SocketMessage,
|
||||||
): TextMessage? {
|
): TextMessage? {
|
||||||
return when (message) {
|
return when (message) {
|
||||||
|
|
@ -62,6 +62,11 @@ class TextMessageFactory(
|
||||||
is CharacterSheetEvent -> when (message) {
|
is CharacterSheetEvent -> when (message) {
|
||||||
|
|
||||||
is CharacterSheetEvent.UpdateDiminished -> {
|
is CharacterSheetEvent.UpdateDiminished -> {
|
||||||
|
// only display the message if the character is in the party or npcs.
|
||||||
|
val isInParty = campaign.characters.contains(message.characterSheetId)
|
||||||
|
val isInNpcs = campaign.npcs.contains(message.characterSheetId)
|
||||||
|
if ((isInParty || isInNpcs).not()) return null
|
||||||
|
// get the character sheet
|
||||||
val sheetPreview = characterSheetRepository
|
val sheetPreview = characterSheetRepository
|
||||||
.characterPreview(characterId = message.characterSheetId)
|
.characterPreview(characterId = message.characterSheetId)
|
||||||
?: return null
|
?: return null
|
||||||
|
|
@ -75,10 +80,14 @@ class TextMessageFactory(
|
||||||
}
|
}
|
||||||
|
|
||||||
is CharacterSheetEvent.UpdateDamage -> {
|
is CharacterSheetEvent.UpdateDamage -> {
|
||||||
val sheet = characterSheetRepository.characterDetail(
|
// only display the message if the character is in the party or npcs.
|
||||||
characterSheetId = message.characterSheetId,
|
val isInParty = campaign.characters.contains(message.characterSheetId)
|
||||||
) ?: return null
|
val isInNpcs = campaign.npcs.contains(message.characterSheetId)
|
||||||
|
if ((isInParty || isInNpcs).not()) return null
|
||||||
|
// get the character sheet
|
||||||
|
val sheet = characterSheetRepository
|
||||||
|
.characterDetail(characterSheetId = message.characterSheetId)
|
||||||
|
?: return null
|
||||||
// We are talking about damage / consumption there so old value have to be put first.
|
// We are talking about damage / consumption there so old value have to be put first.
|
||||||
val value = message.oldValue - message.damage
|
val value = message.oldValue - message.damage
|
||||||
|
|
||||||
|
|
@ -95,10 +104,13 @@ class TextMessageFactory(
|
||||||
}
|
}
|
||||||
|
|
||||||
is CharacterSheetEvent.UpdateFatigue -> {
|
is CharacterSheetEvent.UpdateFatigue -> {
|
||||||
val sheet = characterSheetRepository.characterDetail(
|
// only display the message if the character is in the party.
|
||||||
characterSheetId = message.characterSheetId,
|
val isInParty = campaign.characters.contains(message.characterSheetId)
|
||||||
) ?: return null
|
if (isInParty.not()) return null
|
||||||
|
// get the character sheet
|
||||||
|
val sheet = characterSheetRepository
|
||||||
|
.characterDetail(characterSheetId = message.characterSheetId)
|
||||||
|
?: return null
|
||||||
// We are talking about damage / consumption there so old value have to be put first.
|
// We are talking about damage / consumption there so old value have to be put first.
|
||||||
val value = message.oldValue - message.fatigue
|
val value = message.oldValue - message.fatigue
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class CampaignToolbarViewModel(
|
||||||
|
|
||||||
val status = networkRepository.status
|
val status = networkRepository.status
|
||||||
|
|
||||||
val title = campaignRepository.campaignFlow
|
val title = campaignRepository.campaignFlow()
|
||||||
.map { it.scene.name }
|
.map { it.scene.name }
|
||||||
.stateIn(
|
.stateIn(
|
||||||
scope = viewModelScope,
|
scope = viewModelScope,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ class GMActionViewModel(
|
||||||
private val _error = MutableSharedFlow<ErrorSnackUio>()
|
private val _error = MutableSharedFlow<ErrorSnackUio>()
|
||||||
val error: SharedFlow<ErrorSnackUio> get() = _error
|
val error: SharedFlow<ErrorSnackUio> get() = _error
|
||||||
|
|
||||||
val actions: StateFlow<ActionPageUio?> = campaignRepository.campaignFlow
|
val actions: StateFlow<ActionPageUio?> = campaignRepository.campaignFlow()
|
||||||
.map {
|
.map {
|
||||||
ActionPageUio(
|
ActionPageUio(
|
||||||
party = it.options.showParty,
|
party = it.options.showParty,
|
||||||
|
|
@ -39,7 +39,7 @@ class GMActionViewModel(
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun onPartyHeal() {
|
suspend fun onPartyHeal() {
|
||||||
campaignRepository.campaignFlow.value.characters.forEach { characterSheetId ->
|
campaignRepository.campaignFlow().value.characters.forEach { characterSheetId ->
|
||||||
val sheet = characterRepository.characterDetail(
|
val sheet = characterRepository.characterDetail(
|
||||||
characterSheetId = characterSheetId,
|
characterSheetId = characterSheetId,
|
||||||
) ?: return@forEach
|
) ?: return@forEach
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ class GMCharacterViewModel(
|
||||||
)
|
)
|
||||||
|
|
||||||
val characters = combine(
|
val characters = combine(
|
||||||
campaignRepository.campaignFlow,
|
campaignRepository.campaignFlow(),
|
||||||
characterSheetRepository.characterSheetPreviewFlow,
|
characterSheetRepository.characterSheetPreviewFlow(),
|
||||||
filter.valueFlow.map { it.unAccent() },
|
filter.valueFlow.map { it.unAccent() },
|
||||||
tags,
|
tags,
|
||||||
selectedTagId,
|
selectedTagId,
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ class RollHistoryViewModel(
|
||||||
|
|
||||||
private var _rolls: List<RollHistoryItemUio> = emptyList()
|
private var _rolls: List<RollHistoryItemUio> = emptyList()
|
||||||
val rolls = combine(
|
val rolls = combine(
|
||||||
characterRepository.characterSheetPreviewFlow,
|
characterRepository.characterSheetPreviewFlow(),
|
||||||
rollRepository.rolls,
|
rollRepository.rolls(),
|
||||||
) { sheets, message ->
|
) { sheets, message ->
|
||||||
val name = sheets.firstOrNull { it.characterSheetId == message.characterSheetId }?.name ?: ""
|
val name = sheets.firstOrNull { it.characterSheetId == message.characterSheetId }?.name ?: ""
|
||||||
val roll = RollHistoryItemUio(
|
val roll = RollHistoryItemUio(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue