Skip to content

Commit a8ca57d

Browse files
TbaileDanySK
authored andcommitted
feat: added alert in case of error
1 parent e71df7b commit a8ca57d

2 files changed

Lines changed: 69 additions & 17 deletions

File tree

alchemist-composeui/src/commonMain/kotlin/it/unibo/alchemist/boundary/composeui/App.kt

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
package it.unibo.alchemist.boundary.composeui
1111

1212
import androidx.compose.foundation.BorderStroke
13-
import androidx.compose.foundation.Canvas
1413
import androidx.compose.foundation.layout.Arrangement
1514
import androidx.compose.foundation.layout.Column
1615
import androidx.compose.foundation.layout.fillMaxSize
1716
import androidx.compose.foundation.layout.padding
17+
import androidx.compose.material3.AlertDialog
1818
import androidx.compose.material3.Button
1919
import androidx.compose.material3.CardDefaults
2020
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -27,12 +27,11 @@ import androidx.compose.material3.TopAppBarDefaults
2727
import androidx.compose.runtime.Composable
2828
import androidx.compose.runtime.getValue
2929
import androidx.compose.ui.Modifier
30-
import androidx.compose.ui.geometry.Offset
3130
import androidx.compose.ui.graphics.Color
32-
import androidx.compose.ui.graphics.drawscope.DrawScope
3331
import androidx.compose.ui.unit.dp
3432
import androidx.lifecycle.compose.collectAsStateWithLifecycle
3533
import androidx.lifecycle.viewmodel.compose.viewModel
34+
import com.apollographql.apollo3.api.Error
3635
import it.unibo.alchemist.boundary.composeui.viewmodels.SimulationStatus
3736
import it.unibo.alchemist.boundary.composeui.viewmodels.SimulationStatusViewModel
3837

@@ -41,22 +40,27 @@ import it.unibo.alchemist.boundary.composeui.viewmodels.SimulationStatusViewMode
4140
*/
4241
@Composable
4342
fun app(viewModel: SimulationStatusViewModel = viewModel { SimulationStatusViewModel() }) {
44-
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
43+
val simulationStatus by viewModel.simulationStatus.collectAsStateWithLifecycle()
44+
val time by viewModel.time.collectAsStateWithLifecycle()
45+
val errors by viewModel.errors.collectAsStateWithLifecycle()
4546
Scaffold(
46-
topBar = { topBar(uiState) },
47+
topBar = { topBar(simulationStatus) },
4748
) { innerPadding ->
4849
Column(
4950
modifier = Modifier.padding(innerPadding).padding(horizontal = 8.dp, vertical = 16.dp),
5051
verticalArrangement = Arrangement.spacedBy(16.dp),
5152
) {
52-
controlButton(uiState, viewModel::play, viewModel::pause)
53+
controlButton(simulationStatus, viewModel::play, viewModel::pause)
5354
OutlinedCard(
55+
modifier = Modifier.fillMaxSize(),
5456
colors = CardDefaults.cardColors(
5557
containerColor = MaterialTheme.colorScheme.surface,
5658
),
5759
border = BorderStroke(1.dp, Color.Black),
5860
) {
59-
Canvas(modifier = Modifier.fillMaxSize()) {
61+
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
62+
Text("Time: $time")
63+
errorDialog(viewModel::monitor, errors)
6064
}
6165
}
6266
}
@@ -98,12 +102,22 @@ fun controlButton(status: SimulationStatus, resume: () -> Unit, pause: () -> Uni
98102
}
99103
}
100104

101-
/**
102-
* Node graphical representation.
103-
*/
104105
@Composable
105-
fun node(drawScope: DrawScope, id: Int) {
106-
val x = (drawScope.size.width / 2) + (id * 10)
107-
val y = (drawScope.size.height / 2) + (id * 10)
108-
drawScope.drawCircle(Color.White, radius = 10f, center = Offset(x, y))
106+
fun errorDialog(dismiss: () -> Unit, errors: List<Error>?) {
107+
if (!errors.isNullOrEmpty()) {
108+
AlertDialog(
109+
onDismissRequest = dismiss,
110+
title = { Text("Error") },
111+
text = {
112+
for (error in errors) {
113+
Text(error.message)
114+
}
115+
},
116+
confirmButton = {
117+
Button(onClick = dismiss) {
118+
Text("OK")
119+
}
120+
},
121+
)
122+
}
109123
}

alchemist-composeui/src/commonMain/kotlin/it/unibo/alchemist/boundary/composeui/viewmodels/SimulationStatusViewModel.kt

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ package it.unibo.alchemist.boundary.composeui.viewmodels
1111

1212
import androidx.lifecycle.ViewModel
1313
import androidx.lifecycle.viewModelScope
14+
import com.apollographql.apollo3.api.Error
1415
import it.unibo.alchemist.boundary.graphql.client.GraphQLClientFactory
16+
import it.unibo.alchemist.boundary.graphql.client.NodesSubscription
1517
import it.unibo.alchemist.boundary.graphql.client.PauseSimulationMutation
1618
import it.unibo.alchemist.boundary.graphql.client.PlaySimulationMutation
1719
import it.unibo.alchemist.boundary.graphql.client.SimulationStatusQuery
@@ -29,9 +31,19 @@ enum class SimulationStatus {
2931
Terminated,
3032
}
3133

34+
var i = 0
35+
var j = 0
36+
3237
class SimulationStatusViewModel : ViewModel() {
33-
private val _uiState = MutableStateFlow(SimulationStatus.Init)
34-
val uiState = _uiState.asStateFlow()
38+
private val _simulationStatus = MutableStateFlow(SimulationStatus.Init)
39+
val simulationStatus = _simulationStatus.asStateFlow()
40+
41+
private val _time = MutableStateFlow(0.0)
42+
val time = _time.asStateFlow()
43+
private var tempTime = 0.0
44+
45+
private val _errors = MutableStateFlow<List<Error>>(emptyList())
46+
val errors = _errors.asStateFlow()
3547

3648
// TODO: parameterize the host and port and separate client in different file
3749
private val client = GraphQLClientFactory.subscriptionClient(
@@ -51,14 +63,40 @@ class SimulationStatusViewModel : ViewModel() {
5163
}
5264
}
5365

66+
fun monitor() {
67+
_errors.value = emptyList()
68+
viewModelScope.launch {
69+
client.subscription(NodesSubscription())
70+
.toFlow()
71+
.collect { response ->
72+
if (response.hasErrors()) {
73+
response.errors?.let { errors ->
74+
_errors.update { errors }
75+
}
76+
}
77+
i++
78+
println("data received $i")
79+
if (i > 99) {
80+
i = 0
81+
j++
82+
println("fetching data $j")
83+
response.data?.let { data ->
84+
_time.value = data.simulation.time
85+
}
86+
}
87+
}
88+
}
89+
}
90+
5491
init {
92+
monitor()
5593
viewModelScope.launch {
5694
while (true) {
5795
client.query(SimulationStatusQuery())
5896
.toFlow()
5997
.collect { response ->
6098
response.data?.let { data ->
61-
_uiState.update {
99+
_simulationStatus.update {
62100
// True correlation can be achieved only moving
63101
// alchemist-api Status enum class to commonMain
64102
when (data.simulation.status) {

0 commit comments

Comments
 (0)