Add roll history page
This commit is contained in:
parent
f92922c228
commit
ca456b55d9
20 changed files with 488 additions and 133 deletions
|
|
@ -1,7 +1,9 @@
|
|||
plugins {
|
||||
// this is necessary to avoid the plugins to be loaded multiple times
|
||||
// in each subproject's classloader
|
||||
alias(libs.plugins.kotlinMultiplatform) apply false
|
||||
alias(libs.plugins.kotlinSerialization) apply false
|
||||
// alias(libs.plugins.kotlinKtor) apply false
|
||||
alias(libs.plugins.composeMultiplatform) apply false
|
||||
alias(libs.plugins.composeCompiler) apply false
|
||||
alias(libs.plugins.kotlinMultiplatform) apply false
|
||||
}
|
||||
|
|
@ -3,10 +3,9 @@ import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
|||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
// alias(libs.plugins.kotlinKtor)
|
||||
alias(libs.plugins.composeMultiplatform)
|
||||
alias(libs.plugins.composeCompiler)
|
||||
// kotlin("jvm") version "1.9.20"
|
||||
// alias(libs.plugins.kotlinKtor)
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<resources>
|
||||
<string name="main_page__create_action">Créer une feuille de personnage</string>
|
||||
<string name="main_page__network_action">Configuration réseau</string>
|
||||
<string name="main_page__roll_history_action">Consulter l'historique des lancés</string>
|
||||
<string name="main_page__network_action">Configuration de la table</string>
|
||||
<string name="main_page__roll_history_action">Consulter l'historique des lancers</string>
|
||||
|
||||
<string name="roll_page__roll__label">Jet de :</string>
|
||||
<string name="roll_page__roll__success_label">Réussite si lancer inférieur ou égale à : %1$s</string>
|
||||
<string name="roll_page__critical_success">Réussite critique</string>
|
||||
<string name="roll_page__special_success">Réussite spéciale</string>
|
||||
<string name="roll_page__success">Réussite</string>
|
||||
<string name="roll_page__failure">Échec</string>
|
||||
<string name="roll_page__critical_failure">Échec critique</string>
|
||||
<string name="roll_page__dc__label">Dégré de difficulté :</string>
|
||||
<string name="roll_page__dc_easy__label">Facile</string>
|
||||
<string name="roll_page__dc_normal__label">Normal</string>
|
||||
<string name="roll_page__dc_hard__label">Difficile</string>
|
||||
<string name="roll_page__dc_impossible__label">Impossible</string>
|
||||
|
||||
<string name="character_sheet_edit__title">Création de personnage</string>
|
||||
<string name="character_sheet_edit__name_placeholder">Nom</string>
|
||||
|
|
@ -68,7 +75,7 @@
|
|||
<string name="character_sheet__occupations_title">Occupations</string>
|
||||
<string name="character_sheet__magics__title">Compétences magiques</string>
|
||||
|
||||
<string name="network__title">Configuration réseau</string>
|
||||
<string name="network__title">Configuration de la table</string>
|
||||
<string name="network__player_name__label">Nom du joueur</string>
|
||||
<string name="network__host__label">host</string>
|
||||
<string name="network__port__label">port</string>
|
||||
|
|
@ -83,5 +90,7 @@
|
|||
<string name="network__socket__type_client">Client</string>
|
||||
<string name="network__socket__type_none">Aucun</string>
|
||||
|
||||
<string name="roll_history__title">Historique des lancés</string>
|
||||
<string name="roll_history__title">Historique des lancers</string>
|
||||
<string name="roll_history__item__throw">lance</string>
|
||||
<string name="roll_history__item__difficulty">Difficulté</string>
|
||||
</resources>
|
||||
|
|
@ -168,7 +168,10 @@ fun HandleCharacterSheetCreation(
|
|||
title = stringResource(Res.string.character_sheet_edit__title),
|
||||
) {
|
||||
CharacterSheetMainNavHost(
|
||||
startDestination = CharacterSheetEditDestination.navigationRoute(id = null)
|
||||
startDestination = CharacterSheetEditDestination.navigationRoute(
|
||||
id = null,
|
||||
enableBack = false,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.pixelized.desktop.lwa.navigation.destination
|
|||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.navigation.NavGraphBuilder
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navArgument
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditPage
|
||||
|
|
@ -11,22 +12,33 @@ import com.pixelized.desktop.lwa.utils.extention.ARG
|
|||
object CharacterSheetEditDestination {
|
||||
private const val ROUTE = "character.sheet.edit"
|
||||
private const val CHARACTER_ID = "id"
|
||||
private const val ENABLE_BACK = "enable_back"
|
||||
|
||||
fun baseRoute() = "$ROUTE?${CHARACTER_ID.ARG}"
|
||||
fun baseRoute() = "$ROUTE?${CHARACTER_ID.ARG}&${ENABLE_BACK.ARG}"
|
||||
|
||||
fun navigationRoute(id: String?) = "$ROUTE?$CHARACTER_ID=$id"
|
||||
fun navigationRoute(id: String?, enableBack: Boolean) = ROUTE +
|
||||
"?$CHARACTER_ID=$id" +
|
||||
"&$ENABLE_BACK=$enableBack"
|
||||
|
||||
fun arguments() = listOf(
|
||||
navArgument(CHARACTER_ID) {
|
||||
nullable = true
|
||||
type = NavType.StringType
|
||||
},
|
||||
navArgument(ENABLE_BACK) {
|
||||
nullable = false
|
||||
type = NavType.BoolType
|
||||
}
|
||||
)
|
||||
|
||||
data class Argument(
|
||||
val id: String?,
|
||||
val enableBack: Boolean,
|
||||
) {
|
||||
constructor(savedStateHandle: SavedStateHandle) : this(
|
||||
id = savedStateHandle.get<String>(CHARACTER_ID)
|
||||
id = savedStateHandle.get<String>(CHARACTER_ID),
|
||||
enableBack = savedStateHandle.get<Boolean>(ENABLE_BACK)
|
||||
?: error("Missing enableBack argument"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -42,7 +54,8 @@ fun NavGraphBuilder.composableCharacterSheetEditPage() {
|
|||
|
||||
fun NavHostController.navigateToCharacterSheetEdit(
|
||||
id: String? = null,
|
||||
enableBack: Boolean = true,
|
||||
) {
|
||||
val route = CharacterSheetEditDestination.navigationRoute(id = id)
|
||||
val route = CharacterSheetEditDestination.navigationRoute(id = id, enableBack = enableBack)
|
||||
navigate(route = route)
|
||||
}
|
||||
|
|
@ -27,6 +27,9 @@ typealias Server = EmbeddedServer<NettyApplicationEngine, NettyApplicationEngine
|
|||
typealias Client = HttpClient
|
||||
|
||||
object NetworkRepository {
|
||||
const val DEFAULT_PORT = 16030
|
||||
const val DEFAULT_HOST = "pixelized.freeboxos.fr"
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO)
|
||||
private var networkJob: Job? = null
|
||||
private var server: Server? = null
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import kotlin.time.Duration.Companion.seconds
|
|||
|
||||
// https://ktor.io/docs/server-websockets.html#handle-multiple-session
|
||||
fun server(
|
||||
port: Int = 8080,
|
||||
port: Int,
|
||||
handler: suspend DefaultWebSocketServerSession.() -> Unit
|
||||
): EmbeddedServer<NettyApplicationEngine, NettyApplicationEngine.Configuration> {
|
||||
return embeddedServer(
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import kotlinx.serialization.Serializable
|
|||
|
||||
@Serializable
|
||||
data class RollMessage(
|
||||
val label: String,
|
||||
val roll: Int,
|
||||
): MessageContent
|
||||
val skillLabel: String,
|
||||
val resultLabel: String?,
|
||||
val rollDifficulty: String?,
|
||||
val rollValue: Int,
|
||||
val rollSuccessLimit: Int?,
|
||||
) : MessageContent
|
||||
|
|
@ -31,11 +31,20 @@ object RollHistoryRepository {
|
|||
}
|
||||
|
||||
suspend fun share(
|
||||
label: String,
|
||||
roll: Int,
|
||||
skillLabel: String,
|
||||
rollDifficulty: String?,
|
||||
rollValue: Int,
|
||||
resultLabel: String?,
|
||||
rollSuccessLimit: Int?,
|
||||
) {
|
||||
network.share(
|
||||
content = RollMessage(label = label, roll = roll)
|
||||
content = RollMessage(
|
||||
skillLabel = skillLabel,
|
||||
rollDifficulty = rollDifficulty,
|
||||
rollValue = rollValue,
|
||||
resultLabel = resultLabel,
|
||||
rollSuccessLimit = rollSuccessLimit,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -113,11 +113,11 @@ fun CharacterSheetPage(
|
|||
CharacterSheetPageContent(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
characterSheet = sheet,
|
||||
onBack = {
|
||||
screen.popBackStack()
|
||||
},
|
||||
onEdit = {
|
||||
screen.navigateToCharacterSheetEdit(id = sheet.id)
|
||||
screen.navigateToCharacterSheetEdit(
|
||||
id = sheet.id,
|
||||
enableBack = true,
|
||||
)
|
||||
},
|
||||
onDelete = {
|
||||
scope.launch {
|
||||
|
|
@ -154,7 +154,6 @@ fun CharacterSheetPageContent(
|
|||
modifier: Modifier = Modifier,
|
||||
scrollState: ScrollState = rememberScrollState(),
|
||||
characterSheet: CharacterSheetPageUio,
|
||||
onBack: () -> Unit,
|
||||
onEdit: () -> Unit,
|
||||
onDelete: () -> Unit,
|
||||
onCharacteristic: (characteristic: CharacterSheetPageUio.Characteristic) -> Unit,
|
||||
|
|
@ -178,6 +177,7 @@ fun CharacterSheetPageContent(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Edit,
|
||||
tint = MaterialTheme.colors.primary,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -186,6 +186,7 @@ fun CharacterSheetPageContent(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Delete,
|
||||
tint = MaterialTheme.colors.primary,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -346,9 +347,10 @@ private fun Stat(
|
|||
)
|
||||
Text(
|
||||
modifier = Modifier.align(alignment = Alignment.Center),
|
||||
style = MaterialTheme.typography.h4,
|
||||
style = MaterialTheme.typography.h3,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
color = MaterialTheme.colors.primary,
|
||||
text = characteristic.value
|
||||
)
|
||||
}
|
||||
|
|
@ -402,6 +404,7 @@ private fun Roll(
|
|||
)
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.ic_d20_32dp),
|
||||
tint = MaterialTheme.colors.primary,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
|
|
@ -433,6 +436,7 @@ private fun Skill(
|
|||
Text(
|
||||
style = MaterialTheme.typography.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colors.primary,
|
||||
text = "$value",
|
||||
)
|
||||
Checkbox(modifier = Modifier.size(size = 32.dp), checked = false, onCheckedChange = { })
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
|||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -85,7 +86,13 @@ fun CharacterSheetEditPage(
|
|||
) {
|
||||
CharacterSheetEdit(
|
||||
form = viewModel.characterSheet.value,
|
||||
onBack = { screen.popBackStack() },
|
||||
onBack = remember {
|
||||
if (viewModel.enableBack) {
|
||||
{ screen.popBackStack() }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
},
|
||||
onNewSkill = viewModel::onSkill,
|
||||
onNewCategory = viewModel::onNewRoll,
|
||||
onSave = {
|
||||
|
|
@ -103,7 +110,7 @@ fun CharacterSheetEditPage(
|
|||
@Composable
|
||||
fun CharacterSheetEdit(
|
||||
form: CharacterSheetEditPageUio,
|
||||
onBack: () -> Unit,
|
||||
onBack: (() -> Unit)?,
|
||||
onNewSkill: (CharacterSheetEditPageUio.SkillGroup) -> Unit,
|
||||
onNewCategory: () -> Unit,
|
||||
onSave: () -> Unit,
|
||||
|
|
@ -118,14 +125,16 @@ fun CharacterSheetEdit(
|
|||
text = stringResource(Res.string.character_sheet_edit__title),
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(
|
||||
onClick = onBack,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = null,
|
||||
)
|
||||
navigationIcon = onBack?.let { action: () -> Unit ->
|
||||
{
|
||||
IconButton(
|
||||
onClick = action,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ class CharacterSheetEditViewModel(
|
|||
private val repository = CharacterSheetRepository
|
||||
private val factory = CharacterSheetEditFactory()
|
||||
|
||||
val enableBack = argument.enableBack
|
||||
|
||||
private val _characterSheet = mutableStateOf(
|
||||
repository.characterSheetFlow(id = argument.id).value.let {
|
||||
runBlocking { factory.convertToUio(it) }
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ class NetworkViewModel : ViewModel() {
|
|||
private val repository = NetworkRepository
|
||||
private val factory = NetworkFactory()
|
||||
|
||||
private val host = mutableStateOf("localhost")
|
||||
private val port = mutableStateOf(27030)
|
||||
private val host = mutableStateOf(NetworkRepository.DEFAULT_HOST)
|
||||
private val port = mutableStateOf(NetworkRepository.DEFAULT_PORT)
|
||||
|
||||
val network: State<NetworkPageUio>
|
||||
@Composable
|
||||
@Stable
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.pixelized.desktop.lwa.screen.roll
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
|
|
@ -11,15 +12,22 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
|||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.DropdownMenuItem
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.ExposedDropdownMenuBox
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -34,13 +42,23 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.pixelized.desktop.lwa.screen.roll.DifficultyUio.Difficulty
|
||||
import com.pixelized.desktop.lwa.utils.DisableInteractionSource
|
||||
import kotlinx.coroutines.launch
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_d20_32dp
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc_easy__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc_hard__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc_impossible__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc_normal__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__roll__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__roll__success_label
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
@Stable
|
||||
data class RollUio(
|
||||
data class RollTitleUio(
|
||||
val label: String,
|
||||
val value: Int?,
|
||||
)
|
||||
|
|
@ -51,6 +69,16 @@ data class RollResultUio(
|
|||
val value: Int,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class DifficultyUio(
|
||||
val open: Boolean,
|
||||
val difficulty: Difficulty,
|
||||
) {
|
||||
enum class Difficulty {
|
||||
EASY, NORMAL, HARD, IMPOSSIBLE
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RollPage(
|
||||
viewModel: RollViewModel = viewModel { RollViewModel() },
|
||||
|
|
@ -72,24 +100,24 @@ fun RollPage(
|
|||
style = MaterialTheme.typography.caption,
|
||||
textAlign = TextAlign.Center,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
text = "Jet de :",
|
||||
text = stringResource(Res.string.roll_page__roll__label),
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.typography.h5,
|
||||
textAlign = TextAlign.Center,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
text = viewModel.roll.value.label,
|
||||
text = viewModel.rollTitle.value.label,
|
||||
)
|
||||
viewModel.roll.value.value?.let {
|
||||
viewModel.rollTitle.value.value?.let {
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
textAlign = TextAlign.Center,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
text = "Réussite en dessous de : ${it}",
|
||||
text = stringResource(Res.string.roll_page__roll__success_label, it),
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
verticalArrangement = Arrangement.spacedBy(
|
||||
space = 24.dp,
|
||||
alignment = Alignment.CenterVertically,
|
||||
|
|
@ -114,7 +142,7 @@ fun RollPage(
|
|||
contentDescription = null,
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = viewModel.result.value?.value?.toString() ?: "",
|
||||
targetState = viewModel.rollResult.value?.value?.toString() ?: "",
|
||||
transitionSpec = {
|
||||
val enter = fadeIn() + slideInVertically { 32 }
|
||||
val exit = fadeOut() + slideOutVertically { -32 }
|
||||
|
|
@ -137,7 +165,7 @@ fun RollPage(
|
|||
}
|
||||
}
|
||||
AnimatedContent(
|
||||
targetState = viewModel.result.value?.label ?: "",
|
||||
targetState = viewModel.rollResult.value?.label ?: "",
|
||||
transitionSpec = { fadeIn() togetherWith fadeOut() },
|
||||
) { value ->
|
||||
Text(
|
||||
|
|
@ -148,5 +176,118 @@ fun RollPage(
|
|||
)
|
||||
}
|
||||
}
|
||||
viewModel.rollDifficulty.value?.let {
|
||||
Box(
|
||||
modifier = Modifier.clickable(
|
||||
interactionSource = remember { DisableInteractionSource() },
|
||||
indication = null,
|
||||
onClick = {},
|
||||
)
|
||||
) {
|
||||
Difficulty(
|
||||
difficulty = it,
|
||||
onToggle = { viewModel.toggleDifficulty() },
|
||||
onDifficulty = { viewModel.onDifficulty(it) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun Difficulty(
|
||||
modifier: Modifier = Modifier,
|
||||
difficulty: DifficultyUio,
|
||||
onToggle: () -> Unit,
|
||||
onDifficulty: (Difficulty) -> Unit
|
||||
) {
|
||||
ExposedDropdownMenuBox(
|
||||
modifier = modifier,
|
||||
expanded = difficulty.open,
|
||||
onExpandedChange = { onToggle() },
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = 16.dp,
|
||||
vertical = 8.dp,
|
||||
),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.body1,
|
||||
text = stringResource(Res.string.roll_page__dc__label)
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = MaterialTheme.colors.primary,
|
||||
text = when (difficulty.difficulty) {
|
||||
Difficulty.EASY -> stringResource(Res.string.roll_page__dc_easy__label)
|
||||
Difficulty.NORMAL -> stringResource(Res.string.roll_page__dc_normal__label)
|
||||
Difficulty.HARD -> stringResource(Res.string.roll_page__dc_hard__label)
|
||||
Difficulty.IMPOSSIBLE -> stringResource(Res.string.roll_page__dc_impossible__label)
|
||||
}
|
||||
)
|
||||
}
|
||||
val rotation = animateFloatAsState(
|
||||
targetValue = if (difficulty.open) -180f else 0f,
|
||||
)
|
||||
Icon(
|
||||
modifier = Modifier.graphicsLayer {
|
||||
rotationZ = rotation.value
|
||||
},
|
||||
imageVector = Icons.Default.ArrowDropDown,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
|
||||
ExposedDropdownMenu(
|
||||
expanded = difficulty.open,
|
||||
onDismissRequest = { onToggle() }
|
||||
) {
|
||||
DifficultyDropDownItem(
|
||||
label = stringResource(Res.string.roll_page__dc_easy__label),
|
||||
onClick = { onDifficulty(Difficulty.EASY) },
|
||||
)
|
||||
DifficultyDropDownItem(
|
||||
label = stringResource(Res.string.roll_page__dc_normal__label),
|
||||
onClick = { onDifficulty(Difficulty.NORMAL) },
|
||||
)
|
||||
DifficultyDropDownItem(
|
||||
label = stringResource(Res.string.roll_page__dc_hard__label),
|
||||
onClick = { onDifficulty(Difficulty.HARD) },
|
||||
)
|
||||
DifficultyDropDownItem(
|
||||
label = stringResource(Res.string.roll_page__dc_impossible__label),
|
||||
onClick = { onDifficulty(Difficulty.IMPOSSIBLE) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DifficultyDropDownItem(
|
||||
modifier: Modifier = Modifier,
|
||||
contentPadding: PaddingValues = PaddingValues(horizontal = 16.dp),
|
||||
label: String,
|
||||
onClick: () -> Unit,
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
modifier = modifier,
|
||||
onClick = onClick,
|
||||
enabled = true,
|
||||
contentPadding = contentPadding,
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
content = {
|
||||
Text(
|
||||
color = MaterialTheme.colors.primary,
|
||||
text = label,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet
|
|||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.desktop.lwa.repository.roll.RollHistoryRepository
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio
|
||||
import com.pixelized.desktop.lwa.screen.roll.DifficultyUio.Difficulty
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
|
|
@ -20,6 +21,10 @@ import kotlinx.coroutines.runBlocking
|
|||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__critical_failure
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__critical_success
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc_easy__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc_hard__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc_impossible__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__dc_normal__label
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__failure
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__special_success
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_page__success
|
||||
|
|
@ -28,30 +33,32 @@ import org.jetbrains.compose.resources.getString
|
|||
class RollViewModel : ViewModel() {
|
||||
private val repository = RollHistoryRepository
|
||||
|
||||
private val _roll = mutableStateOf(RollUio(label = "", value = 0))
|
||||
val roll: State<RollUio> get() = _roll
|
||||
private lateinit var sheet: CharacterSheet
|
||||
private lateinit var rollAction: String
|
||||
private var rollSuccessValue: Int? = null
|
||||
|
||||
private var rollJob: Job? = null
|
||||
private var rollStep: SkillStepUseCase.SkillStep? = null
|
||||
private lateinit var rollAction: String
|
||||
private lateinit var sheet: CharacterSheet
|
||||
|
||||
private val _rollTitle = mutableStateOf(RollTitleUio(label = "", value = 0))
|
||||
val rollTitle: State<RollTitleUio> get() = _rollTitle
|
||||
|
||||
private val _rollResult = mutableStateOf<RollResultUio?>(null)
|
||||
val rollResult: State<RollResultUio?> get() = _rollResult
|
||||
|
||||
val rollRotation = Animatable(0f)
|
||||
|
||||
private val _result = mutableStateOf<RollResultUio?>(null)
|
||||
val result: State<RollResultUio?> get() = _result
|
||||
private val _rollDifficulty = mutableStateOf<DifficultyUio?>(null)
|
||||
val rollDifficulty: State<DifficultyUio?> get() = _rollDifficulty
|
||||
|
||||
fun prepareRoll(
|
||||
sheet: CharacterSheetPageUio,
|
||||
characteristic: CharacterSheetPageUio.Characteristic,
|
||||
) {
|
||||
val step = SkillStepUseCase.computeSkillStep(
|
||||
skill = (characteristic.value.toIntOrNull() ?: 0) * 5
|
||||
)
|
||||
prepareRoll(
|
||||
sheet = sheet,
|
||||
label = characteristic.label,
|
||||
rollAction = "1d100",
|
||||
sheet = sheet,
|
||||
rollStep = step,
|
||||
rollSuccessValue = (characteristic.value.toIntOrNull() ?: 0) * 5,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -59,14 +66,11 @@ class RollViewModel : ViewModel() {
|
|||
sheet: CharacterSheetPageUio,
|
||||
node: CharacterSheetPageUio.Node,
|
||||
) {
|
||||
val step = SkillStepUseCase.computeSkillStep(
|
||||
skill = node.value,
|
||||
)
|
||||
prepareRoll(
|
||||
sheet = sheet,
|
||||
label = node.label,
|
||||
rollAction = "1d100",
|
||||
sheet = sheet,
|
||||
rollStep = step,
|
||||
rollSuccessValue = node.value,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -75,34 +79,45 @@ class RollViewModel : ViewModel() {
|
|||
roll: CharacterSheetPageUio.Roll,
|
||||
) {
|
||||
prepareRoll(
|
||||
sheet = sheet,
|
||||
label = roll.label,
|
||||
rollAction = roll.value,
|
||||
sheet = sheet,
|
||||
rollStep = null,
|
||||
rollSuccessValue = null,
|
||||
)
|
||||
}
|
||||
|
||||
private fun prepareRoll(
|
||||
sheet: CharacterSheetPageUio,
|
||||
label: String,
|
||||
rollAction: String,
|
||||
sheet: CharacterSheetPageUio,
|
||||
rollStep: SkillStepUseCase.SkillStep?,
|
||||
rollSuccessValue: Int?,
|
||||
) {
|
||||
runBlocking { rollRotation.snapTo(0f) }
|
||||
this.rollStep = rollStep
|
||||
this.rollAction = rollAction
|
||||
this.sheet = CharacterSheetRepository.characterSheetFlow(id = sheet.id).value!!
|
||||
|
||||
_result.value = null
|
||||
_roll.value = RollUio(
|
||||
this.sheet = CharacterSheetRepository.characterSheetFlow(id = sheet.id).value!!
|
||||
this.rollAction = rollAction
|
||||
this.rollSuccessValue = rollSuccessValue
|
||||
|
||||
val rollStep = rollSuccessValue?.let {
|
||||
SkillStepUseCase.computeSkillStep(skill = it)
|
||||
}
|
||||
|
||||
_rollResult.value = null
|
||||
_rollTitle.value = RollTitleUio(
|
||||
label = label,
|
||||
value = rollStep?.successRange?.last
|
||||
)
|
||||
_rollDifficulty.value = rollSuccessValue?.let {
|
||||
DifficultyUio(
|
||||
open = false,
|
||||
Difficulty.NORMAL,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun roll() {
|
||||
coroutineScope {
|
||||
_result.value = null
|
||||
_rollResult.value = null
|
||||
|
||||
rollJob?.cancel()
|
||||
rollJob = launch {
|
||||
|
|
@ -118,31 +133,81 @@ class RollViewModel : ViewModel() {
|
|||
launch {
|
||||
delay(500)
|
||||
|
||||
val rollStep = rollSuccessValue?.let {
|
||||
SkillStepUseCase.computeSkillStep(
|
||||
skill = when (_rollDifficulty.value?.difficulty) {
|
||||
Difficulty.EASY -> it * 2
|
||||
Difficulty.NORMAL -> it
|
||||
Difficulty.HARD -> it / 2
|
||||
Difficulty.IMPOSSIBLE -> it / 4
|
||||
else -> it
|
||||
}
|
||||
)
|
||||
}
|
||||
val roll = if (rollAction == "1d100") {
|
||||
RollUseCase.rollD100()
|
||||
} else {
|
||||
RollUseCase.roll(characterSheet = sheet, roll = rollAction)
|
||||
}
|
||||
val success = rollStep?.let {
|
||||
when (roll) {
|
||||
in it.criticalSuccessRange -> getString(resource = Res.string.roll_page__critical_success)
|
||||
in it.specialSuccessRange -> getString(resource = Res.string.roll_page__special_success)
|
||||
in it.successRange -> getString(resource = Res.string.roll_page__success)
|
||||
in it.failureRange -> getString(resource = Res.string.roll_page__failure)
|
||||
in it.criticalFailureRange -> getString(resource = Res.string.roll_page__critical_failure)
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
_result.value = RollResultUio(
|
||||
label = rollStep?.let { rollStep ->
|
||||
when (roll) {
|
||||
in rollStep.criticalSuccessRange -> getString(resource = Res.string.roll_page__critical_success)
|
||||
in rollStep.specialSuccessRange -> getString(resource = Res.string.roll_page__special_success)
|
||||
in rollStep.successRange -> getString(resource = Res.string.roll_page__success)
|
||||
in rollStep.failureRange -> getString(resource = Res.string.roll_page__failure)
|
||||
in rollStep.criticalFailureRange -> getString(resource = Res.string.roll_page__critical_failure)
|
||||
else -> ""
|
||||
}
|
||||
} ?: "",
|
||||
_rollResult.value = RollResultUio(
|
||||
label = success ?: "",
|
||||
value = roll,
|
||||
)
|
||||
|
||||
launch {
|
||||
repository.share(label = _roll.value.label, roll = roll)
|
||||
repository.share(
|
||||
skillLabel = _rollTitle.value.label,
|
||||
rollDifficulty = when (_rollDifficulty.value?.difficulty) {
|
||||
Difficulty.EASY -> getString(Res.string.roll_page__dc_easy__label)
|
||||
Difficulty.NORMAL -> getString(Res.string.roll_page__dc_normal__label)
|
||||
Difficulty.HARD -> getString(Res.string.roll_page__dc_hard__label)
|
||||
Difficulty.IMPOSSIBLE -> getString(Res.string.roll_page__dc_impossible__label)
|
||||
else -> null
|
||||
},
|
||||
rollValue = roll,
|
||||
rollSuccessLimit = rollStep?.successRange?.last,
|
||||
resultLabel = success,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun toggleDifficulty() {
|
||||
_rollDifficulty.value = _rollDifficulty.value?.copy(
|
||||
open = _rollDifficulty.value?.open?.not() ?: false
|
||||
)
|
||||
}
|
||||
|
||||
fun onDifficulty(difficulty: Difficulty) {
|
||||
_rollDifficulty.value = DifficultyUio(
|
||||
open = false,
|
||||
difficulty = difficulty,
|
||||
)
|
||||
val rollStep = rollSuccessValue?.let {
|
||||
SkillStepUseCase.computeSkillStep(
|
||||
skill = when (_rollDifficulty.value?.difficulty) {
|
||||
Difficulty.EASY -> it * 2
|
||||
Difficulty.NORMAL -> it
|
||||
Difficulty.HARD -> it / 2
|
||||
Difficulty.IMPOSSIBLE -> it / 4
|
||||
else -> it
|
||||
}
|
||||
)
|
||||
}
|
||||
_rollTitle.value = _rollTitle.value.copy(
|
||||
value = rollStep?.successRange?.last
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
package com.pixelized.desktop.lwa.screen.rollhistory
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_history__item__difficulty
|
||||
import lwacharactersheet.composeapp.generated.resources.roll_history__item__throw
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
|
||||
@Stable
|
||||
data class RollHistoryItemUio(
|
||||
val from: String,
|
||||
val skillLabel: String,
|
||||
val rollDifficulty: String?,
|
||||
val rollValue: Int,
|
||||
val rollSuccessLimit: Int?,
|
||||
val resultLabel: String?,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun RollHistoryItem(
|
||||
modifier: Modifier = Modifier,
|
||||
roll: RollHistoryItemUio,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.weight(1f)
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = roll.from,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.caption,
|
||||
text = stringResource(Res.string.roll_history__item__throw),
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.body1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
text = roll.skillLabel,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
|
||||
) {
|
||||
roll.rollDifficulty?.let {
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
text = stringResource(Res.string.roll_history__item__difficulty),
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
text = it,
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
text = "-",
|
||||
)
|
||||
}
|
||||
roll.resultLabel?.let {
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.h6,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = "${roll.rollValue}",
|
||||
)
|
||||
roll.rollSuccessLimit?.let {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.caption,
|
||||
fontWeight = FontWeight.Light,
|
||||
text = "/ $it",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,14 +2,13 @@ package com.pixelized.desktop.lwa.screen.rollhistory
|
|||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
|
|
@ -17,10 +16,8 @@ import androidx.compose.material.TopAppBar
|
|||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
|
|
@ -29,12 +26,6 @@ import lwacharactersheet.composeapp.generated.resources.Res
|
|||
import lwacharactersheet.composeapp.generated.resources.roll_history__title
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
|
||||
@Stable
|
||||
data class RollItemUio(
|
||||
val from: String,
|
||||
val label: String,
|
||||
val roll: Int,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun RollHistoryPage(
|
||||
|
|
@ -58,7 +49,7 @@ fun RollHistoryPage(
|
|||
@Composable
|
||||
private fun RollHistoryContent(
|
||||
modifier: Modifier = Modifier,
|
||||
rolls: State<List<RollItemUio>>,
|
||||
rolls: State<List<RollHistoryItemUio>>,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
Scaffold(
|
||||
|
|
@ -92,10 +83,11 @@ private fun RollHistoryContent(
|
|||
state = state,
|
||||
reverseLayout = true,
|
||||
contentPadding = PaddingValues(all = 24.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(space = 8.dp)
|
||||
verticalArrangement = Arrangement.spacedBy(space = 16.dp)
|
||||
) {
|
||||
items(items = rolls.value) {
|
||||
RollItem(
|
||||
RollHistoryItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
roll = it
|
||||
)
|
||||
}
|
||||
|
|
@ -104,32 +96,3 @@ private fun RollHistoryContent(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun RollItem(
|
||||
modifier: Modifier = Modifier,
|
||||
roll: RollItemUio,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.body1,
|
||||
fontWeight = FontWeight.Thin,
|
||||
text = roll.from,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.body1,
|
||||
fontWeight = FontWeight.Light,
|
||||
text = roll.label,
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
style = MaterialTheme.typography.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = "${roll.roll}",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -12,8 +12,8 @@ class RollHistoryViewModel : ViewModel() {
|
|||
|
||||
private val repository = RollHistoryRepository
|
||||
|
||||
private val _rolls = mutableStateOf((emptyList<RollItemUio>()))
|
||||
val rolls: State<List<RollItemUio>> get() = _rolls
|
||||
private val _rolls = mutableStateOf((emptyList<RollHistoryItemUio>()))
|
||||
val rolls: State<List<RollHistoryItemUio>> get() = _rolls
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
|
|
@ -22,10 +22,13 @@ class RollHistoryViewModel : ViewModel() {
|
|||
_rolls.value = _rolls.value.toMutableList().apply {
|
||||
add(
|
||||
index = 0,
|
||||
element = RollItemUio(
|
||||
element = RollHistoryItemUio(
|
||||
from = it.from,
|
||||
label = content.label,
|
||||
roll = content.roll
|
||||
skillLabel = content.skillLabel,
|
||||
rollDifficulty = content.rollDifficulty,
|
||||
resultLabel = content.resultLabel,
|
||||
rollValue = content.rollValue,
|
||||
rollSuccessLimit = content.rollSuccessLimit,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.pixelized.desktop.lwa.utils
|
||||
|
||||
import androidx.compose.foundation.interaction.Interaction
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
|
||||
class DisableInteractionSource : MutableInteractionSource {
|
||||
override val interactions: Flow<Interaction> = emptyFlow()
|
||||
|
||||
override suspend fun emit(interaction: Interaction) = Unit
|
||||
|
||||
override fun tryEmit(interaction: Interaction): Boolean = false
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ junit = "4.13.2"
|
|||
compose-multiplatform = "1.7.0"
|
||||
androidx-lifecycle = "2.8.3"
|
||||
androidx-navigation = "2.8.0-alpha10"
|
||||
ktor_version = "3.0.1"
|
||||
ktor_version = "3.0.0"
|
||||
|
||||
[plugins]
|
||||
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" }
|
||||
|
|
@ -24,6 +24,7 @@ androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle
|
|||
androidx-navigation-compose = { group = "org.jetbrains.androidx.navigation", name = "navigation-compose", version.ref = "androidx-navigation" }
|
||||
kotlinx-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" }
|
||||
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-json" }
|
||||
|
||||
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor_version" }
|
||||
ktor-client-cio = { group = 'io.ktor', name = "ktor-client-cio", version.ref = "ktor_version" }
|
||||
ktor-client-websockets = { group = 'io.ktor', name = "ktor-client-websockets", version.ref = "ktor_version" }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue