1
1
package com.squareup.workflow1.traceviewer
2
2
3
+ import androidx.compose.foundation.background
3
4
import androidx.compose.foundation.layout.Box
5
+ import androidx.compose.foundation.layout.Column
6
+ import androidx.compose.foundation.layout.Row
7
+ import androidx.compose.foundation.layout.fillMaxHeight
8
+ import androidx.compose.foundation.layout.fillMaxSize
9
+ import androidx.compose.foundation.layout.fillMaxWidth
10
+ import androidx.compose.foundation.layout.padding
11
+ import androidx.compose.foundation.layout.size
12
+ import androidx.compose.foundation.layout.width
13
+ import androidx.compose.foundation.layout.widthIn
14
+ import androidx.compose.material.Icon
15
+ import androidx.compose.material.IconButton
4
16
import androidx.compose.material.Text
5
17
import androidx.compose.runtime.Composable
6
18
import androidx.compose.runtime.LaunchedEffect
@@ -19,28 +31,90 @@ import io.github.vinceglb.filekit.readString
19
31
public fun App (
20
32
modifier : Modifier = Modifier
21
33
) {
22
- Box {
23
- var selectedFile by remember { mutableStateOf<PlatformFile ?>(null ) }
34
+ var selectedFile by remember { mutableStateOf<PlatformFile ?>(null ) }
35
+ var selectedNode by remember { mutableStateOf<WorkflowNode ?>(null ) }
36
+ // Used when user selects a new file in [UploadFile]
37
+ val resetSelectedNode = { selectedNode = null }
24
38
39
+ Box {
40
+ // Main content
25
41
if (selectedFile != null ) {
26
- SandboxBackground { WorkflowContent (selectedFile!! ) }
42
+ SandboxBackground {
43
+ LoadWorkflowContent (selectedFile) {
44
+ selectedNode = it
45
+ }
46
+ }
27
47
}
28
48
29
- UploadFile (onFileSelect = { selectedFile = it })
49
+ // Left side information panel
50
+ InfoPanel (
51
+ selectedNode.value
52
+ )
53
+
54
+ // Bottom right upload button
55
+ UploadFile (resetSelectedNode, { selectedFile.value = it })
30
56
}
31
57
}
32
58
59
+
60
+
33
61
@Composable
34
- private fun WorkflowContent (file : PlatformFile ) {
35
- var jsonString by remember { mutableStateOf<String ?>(null ) }
36
- LaunchedEffect (file) {
37
- jsonString = file.readString()
62
+ private fun InfoPanel (
63
+ selectedNode : WorkflowNode ?
64
+ ) {
65
+ Row {
66
+ val panelOpen = remember { mutableStateOf(false ) }
67
+
68
+ // based on open/close, display the node details (Column)
69
+ if (panelOpen.value) {
70
+ PanelDetails (
71
+ selectedNode,
72
+ Modifier .fillMaxWidth(.35f )
73
+ )
74
+ }
75
+
76
+ IconButton (
77
+ onClick = { panelOpen.value = ! panelOpen.value },
78
+ modifier = Modifier
79
+ .padding(8 .dp)
80
+ .size(30 .dp)
81
+ .align(Alignment .Top )
82
+ ) {
83
+ Icon (
84
+ imageVector = if (panelOpen.value) Filled .KeyboardArrowLeft else Filled .KeyboardArrowRight ,
85
+ contentDescription = if (panelOpen.value) " Close Panel" else " Open Panel" ,
86
+ modifier = Modifier
87
+ )
88
+ }
38
89
}
39
- val root = jsonString?.let { parseTrace(it) }
90
+ }
91
+
92
+ @Composable
93
+ private fun PanelDetails (
94
+ node : WorkflowNode ? ,
95
+ modifier : Modifier = Modifier
96
+ ) {
97
+ Column (
98
+ modifier
99
+ .fillMaxHeight()
100
+ .background(Color .LightGray )
101
+ ) {
102
+ if (node == null ) {
103
+ Text (" No node selected" )
104
+ return @Column
105
+ }
40
106
41
- if (root != null ) {
42
- DrawWorkflowTree (root)
43
- } else {
44
- Text (" Empty data or failed to parse data" ) // TODO: proper handling of error
107
+ Column (
108
+ modifier = Modifier
109
+ .padding(8 .dp),
110
+ horizontalAlignment = Alignment .CenterHorizontally
111
+ ) {
112
+ Text (" only visible with a node selected" )
113
+ Text (
114
+ text = " This is a node panel for ${node.name} " ,
115
+ fontSize = 20 .sp,
116
+ modifier = Modifier .padding(8 .dp)
117
+ )
118
+ }
45
119
}
46
120
}
0 commit comments