Skip to content

Commit fbffaf1

Browse files
committed
Add file dump functionality from live tracing mode
1 parent 18c3b6f commit fbffaf1

File tree

3 files changed

+78
-3
lines changed

3 files changed

+78
-3
lines changed

workflow-trace-viewer/src/jvmMain/kotlin/com/squareup/workflow1/traceviewer/App.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import com.squareup.workflow1.traceviewer.ui.FrameSelectTab
1919
import com.squareup.workflow1.traceviewer.ui.RenderTrace
2020
import com.squareup.workflow1.traceviewer.ui.RightInfoPanel
2121
import com.squareup.workflow1.traceviewer.ui.TraceModeToggleSwitch
22+
import com.squareup.workflow1.traceviewer.util.FileDump
2223
import com.squareup.workflow1.traceviewer.util.SandboxBackground
2324
import com.squareup.workflow1.traceviewer.util.SocketClient
2425
import com.squareup.workflow1.traceviewer.util.UploadFile
@@ -33,6 +34,7 @@ internal fun App(
3334
) {
3435
var selectedNode by remember { mutableStateOf<NodeUpdate?>(null) }
3536
var frameSize by remember { mutableIntStateOf(0) }
37+
var rawRenderPass by remember { mutableStateOf("")}
3638
var frameIndex by remember { mutableIntStateOf(0) }
3739
val sandboxState = remember { SandboxState() }
3840

@@ -80,7 +82,8 @@ internal fun App(
8082
frameInd = frameIndex,
8183
onFileParse = { frameSize += it },
8284
onNodeSelect = { selectedNode = it },
83-
onNewFrame = { frameIndex += 1 }
85+
onNewFrame = { frameIndex += 1 },
86+
onNewData = { rawRenderPass += "$it," },
8487
)
8588
}
8689
}
@@ -125,6 +128,13 @@ internal fun App(
125128
)
126129
}
127130

131+
if (traceMode is TraceMode.Live) {
132+
FileDump(
133+
trace = rawRenderPass,
134+
modifier = Modifier.align(Alignment.BottomStart)
135+
)
136+
}
137+
128138
if (active) {
129139
ColorLegend(
130140
modifier = Modifier.align(Alignment.BottomEnd)

workflow-trace-viewer/src/jvmMain/kotlin/com/squareup/workflow1/traceviewer/ui/WorkflowTree.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ internal fun RenderTrace(
5353
onFileParse: (Int) -> Unit,
5454
onNodeSelect: (NodeUpdate) -> Unit,
5555
onNewFrame: () -> Unit,
56+
onNewData: (String) -> Unit,
5657
modifier: Modifier = Modifier
5758
) {
5859
var isLoading by remember(traceSource) { mutableStateOf(true) }
@@ -79,6 +80,7 @@ internal fun RenderTrace(
7980
// for when a new frame is received.
8081
fun handleParseResult(
8182
parseResult: ParseResult,
83+
rawRenderPass: String? = null,
8284
onNewFrame: (() -> Unit)? = null
8385
): Boolean {
8486
return when (parseResult) {
@@ -94,6 +96,8 @@ internal fun RenderTrace(
9496
affected = parseResult.affectedNodes
9597
)
9698
onNewFrame?.invoke()
99+
// Only for live tracing, we want to store raw render pass data to be able to file dump.
100+
rawRenderPass?.let { onNewData(it) }
97101
true
98102
}
99103
}
@@ -117,7 +121,7 @@ internal fun RenderTrace(
117121
for (renderPass in socket.renderPassChannel) {
118122
val currentTree = if (fullTree.isEmpty()) null else fullTree.last()
119123
val parseResult = parseLiveTrace(renderPass, adapter, currentTree)
120-
handleParseResult(parseResult, onNewFrame)
124+
handleParseResult(parseResult, renderPass, onNewFrame)
121125
}
122126
}
123127
}
@@ -148,7 +152,6 @@ internal fun RenderTrace(
148152
* A mutable map is used to persist the expansion state of the nodes, allowing them to be open and
149153
* closed from user clicks.
150154
*/
151-
@OptIn(ExperimentalComposeUiApi::class)
152155
@Composable
153156
private fun DrawTree(
154157
node: Node,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.squareup.workflow1.traceviewer.util
2+
3+
import androidx.compose.foundation.layout.padding
4+
import androidx.compose.foundation.shape.CircleShape
5+
import androidx.compose.material.Button
6+
import androidx.compose.material.ButtonDefaults.buttonColors
7+
import androidx.compose.material.Text
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.runtime.getValue
10+
import androidx.compose.runtime.mutableStateOf
11+
import androidx.compose.runtime.remember
12+
import androidx.compose.runtime.setValue
13+
import androidx.compose.ui.Modifier
14+
import androidx.compose.ui.graphics.Color
15+
import androidx.compose.ui.unit.dp
16+
import okio.FileSystem
17+
import okio.Path.Companion.toPath
18+
import okio.buffer
19+
import java.time.LocalDateTime
20+
import java.time.format.DateTimeFormatter
21+
22+
@Composable
23+
internal fun FileDump(
24+
trace: String,
25+
modifier: Modifier
26+
) {
27+
var clicked by remember { mutableStateOf(false) }
28+
Button (
29+
modifier = modifier.padding(16.dp),
30+
shape = CircleShape,
31+
colors = buttonColors(Color.Black),
32+
onClick = {
33+
clicked = true
34+
writeToFile(trace)
35+
}
36+
) {
37+
val text = if (clicked) {
38+
"Trace saved to Downloads"
39+
} else {
40+
"Save trace to file"
41+
}
42+
Text(
43+
text = text,
44+
color = Color.White
45+
)
46+
}
47+
}
48+
49+
private fun writeToFile(trace: String) {
50+
val timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"))
51+
val home = System.getProperty("user.home")
52+
val path = "$home/Downloads/workflow-trace_$timestamp.json".toPath()
53+
54+
FileSystem.SYSTEM.sink(path).use { sink ->
55+
sink.buffer().use { bufferedSink ->
56+
bufferedSink.writeUtf8("[")
57+
bufferedSink.writeUtf8(trace.dropLast(1)) // Fenceposting final comma
58+
bufferedSink.writeUtf8("]")
59+
}
60+
}
61+
}
62+

0 commit comments

Comments
 (0)