diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index 84f3684..1407017 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -2,6 +2,7 @@
Créer une feuille de personnage
Configuration réseau
+ Consulter l'historique des lancés
Réussite critique
Réussite spéciale
@@ -81,4 +82,6 @@
Serveur
Client
Aucun
+
+ Historique des lancés
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/App.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/App.kt
index 9636519..8d33b3c 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/App.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/App.kt
@@ -1,11 +1,16 @@
package com.pixelized.desktop.lwa
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material.Scaffold
+import androidx.compose.material.SnackbarHost
+import androidx.compose.material.SnackbarHostState
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
+import androidx.compose.runtime.State
import androidx.compose.runtime.compositionLocalOf
+import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@@ -13,9 +18,19 @@ import androidx.compose.ui.window.ApplicationScope
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.rememberWindowState
import com.pixelized.desktop.lwa.navigation.MainNavHost
+import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetDestination
+import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetEditDestination
+import com.pixelized.desktop.lwa.screen.characterSheet.CharacterSheetMainNavHost
+import com.pixelized.desktop.lwa.screen.main.CharacterUio
import com.pixelized.desktop.lwa.theme.LwaTheme
+import lwacharactersheet.composeapp.generated.resources.Res
+import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__title
+import org.jetbrains.compose.resources.stringResource
import org.jetbrains.compose.ui.tooling.preview.Preview
+val LocalSnackHost = compositionLocalOf {
+ error("Local Snack Controller is not yet ready")
+}
val LocalWindowController = compositionLocalOf {
error("Local Window Controller is not yet ready")
}
@@ -24,23 +39,47 @@ val LocalWindowController = compositionLocalOf {
data class WindowController(
private val onCloseRequest: () -> Unit
) {
- fun close() = onCloseRequest()
+ val sheet: State> get() = _sheet
+
+ val create: State> get() = _create
+
+ fun showCreateCharacterSheet() {
+ _create.value = _create.value.toMutableSet().apply { add(size) }
+ }
+
+ fun hideCreateCharacterSheet(id: Int) {
+ _create.value = _create.value.toMutableSet().apply { remove(id) }
+ }
+
+ fun showCharacterSheet(sheet: CharacterUio) {
+ _sheet.value = _sheet.value.toMutableSet().apply { add(sheet) }
+ }
+
+ fun hideCharacterSheet(sheet: CharacterUio) {
+ _sheet.value = _sheet.value.toMutableSet().apply { remove(sheet) }
+ }
+
+ fun closeWindows() = onCloseRequest()
+
+ companion object {
+ private val _sheet = mutableStateOf>(emptySet())
+ private val _create = mutableStateOf>(emptySet())
+ }
}
@Composable
@Preview
fun ApplicationScope.App() {
- val controller = remember {
- WindowController(
- onCloseRequest = ::exitApplication
- )
- }
+ val controller = remember { WindowController(onCloseRequest = ::exitApplication) }
+ val snackHostState = remember { SnackbarHostState() }
+
CompositionLocalProvider(
LocalWindowController provides controller,
+ LocalSnackHost provides snackHostState,
) {
Window(
onCloseRequest = {
- controller.close()
+ controller.closeWindows()
},
state = rememberWindowState(
width = 320.dp + 64.dp,
@@ -52,9 +91,86 @@ fun ApplicationScope.App() {
Surface(
modifier = Modifier.fillMaxSize()
) {
- MainNavHost()
+ Scaffold(
+ snackbarHost = {
+ SnackbarHost(
+ hostState = snackHostState,
+ )
+ },
+ content = {
+ MainNavHost()
+ }
+ )
+ HandleCharacterSheet(
+ sheets = controller.sheet,
+ onCloseRequest = { controller.hideCharacterSheet(sheet = it) }
+ )
+ HandleCharacterSheetCreation(
+ sheets = controller.create,
+ onCloseRequest = { controller.hideCreateCharacterSheet(id = it) },
+ )
}
}
}
}
+}
+
+@Composable
+fun HandleCharacterSheet(
+ sheets: State>,
+ onCloseRequest: (id: CharacterUio) -> Unit,
+) {
+ sheets.value.forEach { sheet ->
+ val controller = remember {
+ WindowController(
+ onCloseRequest = { onCloseRequest(sheet) }
+ )
+ }
+ CompositionLocalProvider(
+ LocalWindowController provides controller,
+ ) {
+ Window(
+ onCloseRequest = { onCloseRequest(sheet) },
+ state = rememberWindowState(
+ width = 400.dp + 64.dp,
+ height = 900.dp,
+ ),
+ title = sheet.name,
+ ) {
+ CharacterSheetMainNavHost(
+ startDestination = CharacterSheetDestination.navigationRoute(id = sheet.id)
+ )
+ }
+ }
+ }
+}
+
+@Composable
+fun HandleCharacterSheetCreation(
+ sheets: State>,
+ onCloseRequest: (id: Int) -> Unit,
+) {
+ sheets.value.forEach { sheet ->
+ val controller = remember {
+ WindowController(
+ onCloseRequest = { onCloseRequest(sheet) }
+ )
+ }
+ CompositionLocalProvider(
+ LocalWindowController provides controller,
+ ) {
+ Window(
+ onCloseRequest = { controller.closeWindows() },
+ state = rememberWindowState(
+ width = 400.dp + 64.dp,
+ height = 900.dp,
+ ),
+ title = stringResource(Res.string.character_sheet_edit__title),
+ ) {
+ CharacterSheetMainNavHost(
+ startDestination = CharacterSheetEditDestination.navigationRoute(id = null)
+ )
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/MainNavHost.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/MainNavHost.kt
index 22d6c92..6a9e995 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/MainNavHost.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/MainNavHost.kt
@@ -9,6 +9,8 @@ import androidx.navigation.compose.rememberNavController
import com.pixelized.desktop.lwa.navigation.destination.MainDestination
import com.pixelized.desktop.lwa.navigation.destination.composableMainPage
import com.pixelized.desktop.lwa.navigation.destination.composableNetworkPage
+import com.pixelized.desktop.lwa.navigation.destination.composableRollHistory
+import com.pixelized.desktop.lwa.screen.main.MainPageViewModel
val LocalScreenController = compositionLocalOf {
error("MainNavHost controller is not yet ready")
@@ -28,6 +30,7 @@ fun MainNavHost(
) {
composableMainPage()
composableNetworkPage()
+ composableRollHistory()
}
}
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/destination/MainDestination.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/destination/MainDestination.kt
index 49c9c51..f65d578 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/destination/MainDestination.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/destination/MainDestination.kt
@@ -4,6 +4,7 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.compose.composable
import com.pixelized.desktop.lwa.screen.main.MainPage
+import com.pixelized.desktop.lwa.screen.main.MainPageViewModel
object MainDestination {
private const val ROUTE = "main"
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/destination/RollHistoryDestination.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/destination/RollHistoryDestination.kt
new file mode 100644
index 0000000..c3373ac
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/navigation/destination/RollHistoryDestination.kt
@@ -0,0 +1,26 @@
+package com.pixelized.desktop.lwa.navigation.destination
+
+import androidx.navigation.NavGraphBuilder
+import androidx.navigation.NavHostController
+import androidx.navigation.compose.composable
+import com.pixelized.desktop.lwa.screen.rollhistory.RollHistoryPage
+
+object RollHistoryDestination {
+ private const val ROUTE = "roll_history"
+
+ fun baseRoute() = ROUTE
+ fun navigationRoute() = ROUTE
+}
+
+fun NavGraphBuilder.composableRollHistory() {
+ composable(
+ route = RollHistoryDestination.baseRoute()
+ ) {
+ RollHistoryPage()
+ }
+}
+
+fun NavHostController.navigateToRollHistory() {
+ val route = RollHistoryDestination.navigationRoute()
+ navigate(route = route)
+}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/NetworkRepository.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/NetworkRepository.kt
index d39b0e1..021d093 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/NetworkRepository.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/NetworkRepository.kt
@@ -4,6 +4,7 @@ import com.pixelized.desktop.lwa.repository.network.helper.client
import com.pixelized.desktop.lwa.repository.network.helper.connectWebSocket
import com.pixelized.desktop.lwa.repository.network.helper.server
import com.pixelized.desktop.lwa.repository.network.protocol.Message
+import com.pixelized.desktop.lwa.repository.network.protocol.MessageContent
import io.ktor.client.HttpClient
import io.ktor.server.engine.EmbeddedServer
import io.ktor.server.netty.NettyApplicationEngine
@@ -15,8 +16,8 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.json.Json
@@ -31,8 +32,9 @@ object NetworkRepository {
private var server: Server? = null
private var client: Client? = null
- private val messageResponseFlow = MutableSharedFlow()
- private val sharedFlow = messageResponseFlow.asSharedFlow()
+ private val outgoingMessageBuffer = MutableSharedFlow()
+ private val incomingMessageBuffer = MutableSharedFlow()
+ val data: SharedFlow get() = incomingMessageBuffer
private val _player = MutableStateFlow("")
val player: StateFlow get() = _player
@@ -57,17 +59,19 @@ object NetworkRepository {
println("Server launched")
val job = launch {
- sharedFlow.collect { message ->
- println("Broadcast: $message")
- send(Frame.Text(message))
+ // send local message to the clients
+ outgoingMessageBuffer.collect { message ->
+ send(Json.encodeToFrame(message = message))
}
}
-
runCatching {
+ // watching for clients incoming message
incoming.consumeEach { frame ->
if (frame is Frame.Text) {
- val receivedText = frame.readText()
- messageResponseFlow.emit(receivedText)
+ val message = Json.decodeFromFrame(frame = frame)
+ incomingMessageBuffer.emit(message)
+ // broadcast to clients the message
+ outgoingMessageBuffer.emit(message)
}
}
}.onFailure { exception ->
@@ -108,17 +112,17 @@ object NetworkRepository {
println("Client launched")
val job = launch {
- sharedFlow.collect { message ->
- println("Send: $message")
- send(Frame.Text(message))
+ // send message to the server
+ outgoingMessageBuffer.collect { message ->
+ send(Json.encodeToFrame(message = message))
}
}
-
runBlocking {
+ // watching for server incoming message
incoming.consumeEach { frame ->
if (frame is Frame.Text) {
- val receivedText = frame.readText()
- println("client received: $receivedText")
+ val message = Json.decodeFromFrame(frame = frame)
+ incomingMessageBuffer.emit(message)
}
}
}.also {
@@ -144,15 +148,19 @@ object NetworkRepository {
}
}
- fun share(
- type: String,
- value: String,
+ suspend fun share(
+ content: MessageContent,
) {
if (status.value == Status.CONNECTED) {
- scope.launch {
- val message = Message(from = player.value, type = type, value = value)
- val json = Json.encodeToJsonElement(message)
- messageResponseFlow.emit(json.toString())
+ val message = Message(
+ from = player.value,
+ value = content,
+ )
+ // emit the message into the outgoing buffer
+ outgoingMessageBuffer.emit(message)
+ // emit the message into the incoming buffer IF we are the server
+ if (type.value == Type.SERVER) {
+ incomingMessageBuffer.emit(message)
}
}
}
@@ -167,4 +175,14 @@ object NetworkRepository {
SERVER,
NONE,
}
+}
+
+private fun Json.decodeFromFrame(frame: Frame.Text): Message {
+ val json = frame.readText()
+ return decodeFromString(json)
+}
+
+private fun Json.encodeToFrame(message: Message): Frame {
+ val json = encodeToJsonElement(message)
+ return Frame.Text(text = json.toString())
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/Message.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/Message.kt
index 1048cc4..20904a0 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/Message.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/Message.kt
@@ -3,8 +3,7 @@ package com.pixelized.desktop.lwa.repository.network.protocol
import kotlinx.serialization.Serializable
@Serializable
-class Message(
+data class Message(
val from: String,
- val type: String,
- val value: String,
+ val value: MessageContent,
)
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/MessageContent.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/MessageContent.kt
new file mode 100644
index 0000000..bcfbb30
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/MessageContent.kt
@@ -0,0 +1,6 @@
+package com.pixelized.desktop.lwa.repository.network.protocol
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+sealed interface MessageContent
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/RollMessage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/RollMessage.kt
new file mode 100644
index 0000000..1893b26
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/network/protocol/RollMessage.kt
@@ -0,0 +1,9 @@
+package com.pixelized.desktop.lwa.repository.network.protocol
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class RollMessage(
+ val label: String,
+ val roll: Int,
+): MessageContent
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/roll/RollHistoryRepository.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/roll/RollHistoryRepository.kt
new file mode 100644
index 0000000..50557b2
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/roll/RollHistoryRepository.kt
@@ -0,0 +1,41 @@
+package com.pixelized.desktop.lwa.repository.roll
+
+import com.pixelized.desktop.lwa.repository.network.NetworkRepository
+import com.pixelized.desktop.lwa.repository.network.protocol.Message
+import com.pixelized.desktop.lwa.repository.network.protocol.RollMessage
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.launch
+
+object RollHistoryRepository {
+ private val scope = CoroutineScope(Dispatchers.IO)
+ private val network = NetworkRepository
+
+ val rolls: SharedFlow = network.data
+ .mapNotNull { it.takeIf { it.value is RollMessage } }
+ .shareIn(
+ scope = scope,
+ started = SharingStarted.Eagerly,
+ )
+
+ init {
+ scope.launch {
+ network.data.collect {
+ println(it)
+ }
+ }
+ }
+
+ suspend fun share(
+ label: String,
+ roll: Int,
+ ) {
+ network.share(
+ content = RollMessage(label = label, roll = roll)
+ )
+ }
+}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt
index 8677308..f371989 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt
@@ -24,7 +24,6 @@ import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Edit
import androidx.compose.runtime.Composable
@@ -124,7 +123,7 @@ fun CharacterSheetPage(
scope.launch {
viewModel.deleteCharacter(id = sheet.id)
if (screen.popBackStack().not()) {
- window.close()
+ window.closeWindows()
}
}
},
@@ -191,16 +190,6 @@ fun CharacterSheetPageContent(
)
}
},
- navigationIcon = {
- IconButton(
- onClick = onBack,
- ) {
- Icon(
- imageVector = Icons.AutoMirrored.Filled.ArrowBack,
- contentDescription = null,
- )
- }
- }
)
},
content = { paddingValues ->
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt
index a4af668..94d0845 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt
@@ -92,7 +92,7 @@ fun CharacterSheetEditPage(
scope.launch {
viewModel.save()
if (screen.popBackStack().not()) {
- window.close()
+ window.closeWindows()
}
}
},
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPage.kt
index f7ee73e..6a5f456 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPage.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPage.kt
@@ -3,7 +3,6 @@ package com.pixelized.desktop.lwa.screen.main
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
@@ -27,16 +26,17 @@ import androidx.compose.ui.window.rememberWindowState
import androidx.lifecycle.viewmodel.compose.viewModel
import com.pixelized.desktop.lwa.LocalWindowController
import com.pixelized.desktop.lwa.WindowController
-import com.pixelized.desktop.lwa.composable.decoratedBox.DecoratedBox
import com.pixelized.desktop.lwa.navigation.LocalScreenController
import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetDestination
import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetEditDestination
import com.pixelized.desktop.lwa.navigation.destination.navigateToNetwork
+import com.pixelized.desktop.lwa.navigation.destination.navigateToRollHistory
import com.pixelized.desktop.lwa.screen.characterSheet.CharacterSheetMainNavHost
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__title
import lwacharactersheet.composeapp.generated.resources.main_page__create_action
import lwacharactersheet.composeapp.generated.resources.main_page__network_action
+import lwacharactersheet.composeapp.generated.resources.main_page__roll_history_action
import org.jetbrains.compose.resources.stringResource
@Stable
@@ -49,6 +49,7 @@ data class CharacterUio(
fun MainPage(
viewModel: MainPageViewModel = viewModel { MainPageViewModel() },
) {
+ val window = LocalWindowController.current
val screen = LocalScreenController.current
Surface(
@@ -64,10 +65,13 @@ fun MainPage(
MainPageContent(
characters = viewModel.characters,
onCharacter = {
- viewModel.showCharacterSheet(sheet = it)
+ window.showCharacterSheet(sheet = it)
},
onCreateCharacter = {
- viewModel.showCreateCharacterSheet()
+ window.showCreateCharacterSheet()
+ },
+ onRollHistory = {
+ screen.navigateToRollHistory()
},
onNetwork = {
screen.navigateToNetwork()
@@ -75,140 +79,72 @@ fun MainPage(
)
}
}
-
- HandleCharacterSheet(
- sheets = viewModel.sheet,
- onCloseRequest = { viewModel.hideCharacterSheet(sheet = it) }
- )
-
- HandleCharacterSheetCreation(
- sheets = viewModel.create,
- onCloseRequest = { viewModel.hideCreateCharacterSheet(id = it) },
- )
}
-@Composable
-fun HandleCharacterSheet(
- sheets: State>,
- onCloseRequest: (id: CharacterUio) -> Unit,
-) {
- sheets.value.forEach { sheet ->
- val controller = remember {
- WindowController(
- onCloseRequest = { onCloseRequest(sheet) }
- )
- }
- CompositionLocalProvider(
- LocalWindowController provides controller,
- ) {
- Window(
- onCloseRequest = { onCloseRequest(sheet) },
- state = rememberWindowState(
- width = 400.dp + 64.dp,
- height = 900.dp,
- ),
- title = sheet.name,
- ) {
- CharacterSheetMainNavHost(
- startDestination = CharacterSheetDestination.navigationRoute(id = sheet.id)
- )
- }
- }
- }
-}
-
-@Composable
-fun HandleCharacterSheetCreation(
- sheets: State>,
- onCloseRequest: (id: Int) -> Unit,
-) {
- sheets.value.forEach { sheet ->
- val controller = remember {
- WindowController(
- onCloseRequest = { onCloseRequest(sheet) }
- )
- }
- CompositionLocalProvider(
- LocalWindowController provides controller,
- ) {
- Window(
- onCloseRequest = { controller.close() },
- state = rememberWindowState(
- width = 400.dp + 64.dp,
- height = 900.dp,
- ),
- title = stringResource(Res.string.character_sheet_edit__title),
- ) {
- CharacterSheetMainNavHost(
- startDestination = CharacterSheetEditDestination.navigationRoute(id = null)
- )
- }
- }
- }
-}
-
-
@Composable
fun MainPageContent(
modifier: Modifier = Modifier,
characters: State>,
onCharacter: (CharacterUio) -> Unit,
onCreateCharacter: () -> Unit,
+ onRollHistory: () -> Unit,
onNetwork: () -> Unit,
) {
Column(
modifier = modifier,
+ verticalArrangement = Arrangement.spacedBy(16.dp),
) {
- Spacer(
- modifier = Modifier.weight(weight = 1f)
- )
- DecoratedBox {
- Column(
- modifier = Modifier.padding(horizontal = 8.dp),
- verticalArrangement = Arrangement.spacedBy(space = 32.dp),
- ) {
- Column {
- characters.value.forEach { sheet ->
- TextButton(
- onClick = { onCharacter(sheet) },
- ) {
- Text(
- modifier = Modifier.fillMaxWidth(),
- overflow = TextOverflow.Ellipsis,
- textAlign = TextAlign.Start,
- maxLines = 1,
- text = sheet.name,
- )
- }
- }
- }
-
+ Column {
+ characters.value.forEach { sheet ->
TextButton(
- onClick = { onCreateCharacter() },
+ onClick = { onCharacter(sheet) },
) {
Text(
modifier = Modifier.fillMaxWidth(),
- maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Start,
- text = stringResource(Res.string.main_page__create_action),
+ maxLines = 1,
+ text = sheet.name,
)
}
}
}
- Spacer(
- modifier = Modifier.weight(weight = 1f)
- )
+
TextButton(
- onClick = { onNetwork() },
+ onClick = onCreateCharacter,
) {
Text(
modifier = Modifier.fillMaxWidth(),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Start,
- text = stringResource(Res.string.main_page__network_action),
+ text = stringResource(Res.string.main_page__create_action),
)
}
+
+ Column {
+ TextButton(
+ onClick = onRollHistory,
+ ) {
+ Text(
+ modifier = Modifier.fillMaxWidth(),
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ textAlign = TextAlign.Start,
+ text = stringResource(Res.string.main_page__roll_history_action),
+ )
+ }
+ TextButton(
+ onClick = onNetwork,
+ ) {
+ Text(
+ modifier = Modifier.fillMaxWidth(),
+ overflow = TextOverflow.Ellipsis,
+ textAlign = TextAlign.Start,
+ maxLines = 1,
+ text = stringResource(Res.string.main_page__network_action),
+ )
+ }
+ }
}
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPageViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPageViewModel.kt
index 0947b2a..5190a83 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPageViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPageViewModel.kt
@@ -3,7 +3,6 @@ package com.pixelized.desktop.lwa.screen.main
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
-import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.utils.extention.collectAsState
@@ -12,12 +11,6 @@ class MainPageViewModel : ViewModel() {
// using a variable to help with later injection.
private val repository = CharacterSheetRepository
- private val _sheet = mutableStateOf>(emptySet())
- val sheet: State> get() = _sheet
-
- private val _create = mutableStateOf>(emptySet())
- val create: State> get() = _create
-
val characters: State>
@Composable
@Stable
@@ -31,20 +24,4 @@ class MainPageViewModel : ViewModel() {
)
}
}
-
- fun showCreateCharacterSheet() {
- _create.value = _create.value.toMutableSet().apply { add(size) }
- }
-
- fun hideCreateCharacterSheet(id: Int) {
- _create.value = _create.value.toMutableSet().apply { remove(id) }
- }
-
- fun showCharacterSheet(sheet: CharacterUio) {
- _sheet.value = _sheet.value.toMutableSet().apply { add(sheet) }
- }
-
- fun hideCharacterSheet(sheet: CharacterUio) {
- _sheet.value = _sheet.value.toMutableSet().apply { remove(sheet) }
- }
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt
index e3b83d1..20bfb00 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt
@@ -10,7 +10,7 @@ import com.pixelized.desktop.lwa.business.RollUseCase
import com.pixelized.desktop.lwa.business.SkillStepUseCase
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
-import com.pixelized.desktop.lwa.repository.network.NetworkRepository
+import com.pixelized.desktop.lwa.repository.roll.RollHistoryRepository
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio
import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope
@@ -26,7 +26,7 @@ import lwacharactersheet.composeapp.generated.resources.roll_page__success
import org.jetbrains.compose.resources.getString
class RollViewModel : ViewModel() {
- private val network = NetworkRepository
+ private val repository = RollHistoryRepository
private val _roll = mutableStateOf(RollUio(label = "", value = 0))
val roll: State get() = _roll
@@ -138,13 +138,11 @@ class RollViewModel : ViewModel() {
value = roll,
)
- share(roll = roll)
+ launch {
+ repository.share(label = _roll.value.label, roll = roll)
+ }
}
}
}
}
-
- private fun share(roll: Int) {
- network.share(type = "roll", value = "$roll")
- }
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/rollhistory/RollHistoryPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/rollhistory/RollHistoryPage.kt
new file mode 100644
index 0000000..2023450
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/rollhistory/RollHistoryPage.kt
@@ -0,0 +1,135 @@
+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.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
+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
+import com.pixelized.desktop.lwa.navigation.LocalScreenController
+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(
+ viewModel: RollHistoryViewModel = viewModel { RollHistoryViewModel() }
+) {
+ val screen = LocalScreenController.current
+
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ ) {
+ RollHistoryContent(
+ modifier = Modifier.fillMaxSize(),
+ rolls = viewModel.rolls,
+ onBack = {
+ screen.popBackStack()
+ },
+ )
+ }
+}
+
+@Composable
+private fun RollHistoryContent(
+ modifier: Modifier = Modifier,
+ rolls: State>,
+ onBack: () -> Unit,
+) {
+ Scaffold(
+ modifier = modifier,
+ topBar = {
+ TopAppBar(
+ title = {
+ Text(
+ overflow = TextOverflow.Ellipsis,
+ maxLines = 1,
+ text = stringResource(Res.string.roll_history__title),
+ )
+ },
+ navigationIcon = {
+ IconButton(
+ onClick = onBack,
+ ) {
+ Icon(
+ imageVector = Icons.AutoMirrored.Filled.ArrowBack,
+ contentDescription = null,
+ )
+ }
+ }
+ )
+ },
+ content = {
+ val state = rememberLazyListState()
+
+ LazyColumn(
+ modifier = Modifier.fillMaxSize(),
+ state = state,
+ reverseLayout = true,
+ contentPadding = PaddingValues(all = 24.dp),
+ verticalArrangement = Arrangement.spacedBy(space = 8.dp)
+ ) {
+ items(items = rolls.value) {
+ RollItem(
+ roll = it
+ )
+ }
+ }
+ }
+ )
+}
+
+@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}",
+ )
+ }
+}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/rollhistory/RollHistoryViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/rollhistory/RollHistoryViewModel.kt
new file mode 100644
index 0000000..356fe50
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/rollhistory/RollHistoryViewModel.kt
@@ -0,0 +1,36 @@
+package com.pixelized.desktop.lwa.screen.rollhistory
+
+import androidx.compose.runtime.State
+import androidx.compose.runtime.mutableStateOf
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.pixelized.desktop.lwa.repository.network.protocol.RollMessage
+import com.pixelized.desktop.lwa.repository.roll.RollHistoryRepository
+import kotlinx.coroutines.launch
+
+class RollHistoryViewModel : ViewModel() {
+
+ private val repository = RollHistoryRepository
+
+ private val _rolls = mutableStateOf((emptyList()))
+ val rolls: State> get() = _rolls
+
+ init {
+ viewModelScope.launch {
+ repository.rolls.collect {
+ (it.value as? RollMessage)?.let { content ->
+ _rolls.value = _rolls.value.toMutableList().apply {
+ add(
+ index = 0,
+ element = RollItemUio(
+ from = it.from,
+ label = content.label,
+ roll = content.roll
+ )
+ )
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file