Skip to content

Commit 0bfd80e

Browse files
committed
update Request Editor to resolve variables in inherited request bodies
1 parent f64c167 commit 0bfd80e

File tree

2 files changed

+102
-88
lines changed

2 files changed

+102
-88
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ _Changes since 1.7.3_
1818
- The "Copy All" button near the response body viewer has been relocated to the upper level, as it copies the whole Request and Response rather than only response body
1919
- The "Copy All" button under the response tab "Raw" has been renamed to "Copy"
2020
- The copying content of the above two copy functions now includes the request name and example name as the heading
21+
- Variables in request bodies inherited from the Base example are now resolved in the display
2122

2223
### Fixed
2324
- Crash when selecting the last tab of a HTTP request then switching to a gRPC or WS request

src/jvmMain/kotlin/com/sunnychung/application/multiplatform/hellohttp/ux/CodeEditorView.kt

Lines changed: 101 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -551,97 +551,109 @@ fun CodeEditorView(
551551
}
552552
)
553553

554-
if (isReadOnly) {
555-
val collapseIncrementalTransformation = remember(bigTextFieldState) {
556-
CollapseIncrementalTransformation(themeColours, collapsedChars.values.toList())
557-
}
558-
var transformedText by remember(bigTextFieldState) { mutableStateOf<BigTextTransformed?>(null) }
554+
var mouseHoverVariable by remember(bigTextFieldState) { mutableStateOf<String?>(null) }
555+
AppTooltipArea(
556+
isVisible = mouseHoverVariable != null && mouseHoverVariable in knownVariables,
557+
tooltipText = mouseHoverVariable?.let {
558+
val s = knownVariables[it] ?: return@let null
559+
if (s.length > ENV_VAR_VALUE_MAX_DISPLAY_LENGTH) {
560+
s.substring(0, ENV_VAR_VALUE_MAX_DISPLAY_LENGTH) + " ..."
561+
} else {
562+
s
563+
}
564+
} ?: "",
565+
modifier = Modifier.fillMaxSize(),
566+
) {
567+
if (isReadOnly) {
568+
val collapseIncrementalTransformation = remember(bigTextFieldState) {
569+
CollapseIncrementalTransformation(themeColours, collapsedChars.values.toList())
570+
}
571+
var transformedText by remember(bigTextFieldState) { mutableStateOf<BigTextTransformed?>(null) }
559572

560-
transformedText?.let { transformedText ->
561-
collapseIncrementalTransformation.update(collapsedChars.values.toList(), bigTextFieldState.viewState)
562-
}
573+
transformedText?.let { transformedText ->
574+
collapseIncrementalTransformation.update(
575+
collapsedChars.values.toList(),
576+
bigTextFieldState.viewState
577+
)
578+
}
579+
580+
BigTextLabel(
581+
text = bigTextValue,
582+
color = textColor,
583+
padding = PaddingValues(4.dp),
584+
inputFilter = inputFilter,
585+
textTransformation = rememberLast(bigTextFieldState, collapseIncrementalTransformation) {
586+
MultipleIncrementalTransformation(
587+
listOf(
588+
collapseIncrementalTransformation,
589+
) + variableTransformations
590+
)
591+
},
592+
textDecorator = //rememberLast(bigTextFieldState, syntaxHighlightDecorators, searchDecorators) {
593+
MultipleTextDecorator(syntaxHighlightDecorators + variableDecorators + searchDecorators)
594+
//},
595+
,
596+
fontSize = fonts.codeEditorBodyFontSize,
597+
fontFamily = fonts.monospaceFontFamily,
598+
isSoftWrapEnabled = true,
599+
isSelectable = true,
600+
scrollState = scrollState,
601+
viewState = bigTextFieldState.viewState,
602+
onPointerEvent = { event, charIndex, tag ->
603+
log.v { "onPointerEventOnAnnotatedTag $tag $event" }
604+
if (isShowCopyLiteralButton) {
605+
mouseHoverCharIndex = charIndex
606+
}
607+
608+
mouseHoverVariable =
609+
if (tag?.startsWith(EnvironmentVariableIncrementalTransformation.TAG_PREFIX) == true) {
610+
tag.replaceFirst(EnvironmentVariableIncrementalTransformation.TAG_PREFIX, "")
611+
} else {
612+
null
613+
}
563614

564-
BigTextLabel(
565-
text = bigTextValue,
566-
color = textColor,
567-
padding = PaddingValues(4.dp),
568-
inputFilter = inputFilter,
569-
textTransformation = rememberLast(bigTextFieldState, collapseIncrementalTransformation) {
570-
MultipleIncrementalTransformation(listOf(
571-
collapseIncrementalTransformation,
572-
))
573-
},
574-
textDecorator = //rememberLast(bigTextFieldState, syntaxHighlightDecorators, searchDecorators) {
575-
MultipleTextDecorator(syntaxHighlightDecorators + searchDecorators)
576-
//},
577-
,
578-
fontSize = fonts.codeEditorBodyFontSize,
579-
fontFamily = fonts.monospaceFontFamily,
580-
isSoftWrapEnabled = true,
581-
isSelectable = true,
582-
scrollState = scrollState,
583-
viewState = bigTextFieldState.viewState,
584-
onPointerEvent = letIf(onPointerEvent != null || isShowCopyLiteralButton) {
585-
{ event: PointerEvent, charIndex: Int, _ ->
586-
log.v { "CEV onPointerEvent $event" }
587-
mouseHoverCharIndex = charIndex
588615
onPointerEvent?.invoke(event, charIndex)
589-
}
590-
},
591-
onTextLayout = { layoutResult = it },
592-
onTransformInit = { transformedText = it },
593-
contextMenu = AppBigTextFieldContextMenu,
594-
modifier = Modifier.fillMaxSize()
595-
.focusRequester(textFieldFocusRequester)
596-
.run {
597-
if (testTag != null) {
598-
testTag(testTag)
599-
} else {
600-
this
616+
},
617+
onTextLayout = { layoutResult = it },
618+
onTransformInit = { transformedText = it },
619+
contextMenu = AppBigTextFieldContextMenu,
620+
modifier = Modifier.fillMaxSize()
621+
.focusRequester(textFieldFocusRequester)
622+
.run {
623+
if (testTag != null) {
624+
testTag(testTag)
625+
} else {
626+
this
627+
}
601628
}
602-
}
603-
)
629+
)
604630
// return@Row // compose bug: return here would crash
605-
} else {
606-
LaunchedEffect(bigTextFieldState, onTextChange) { // FIXME the flow is frequently recreated
607-
log.i { "CEV recreate change collection flow $bigTextFieldState ${onTextChange.hashCode()}" }
608-
withContext(Dispatchers.IO) {
609-
bigTextFieldState.valueChangesFlow
610-
.onEach { log.d { "bigTextFieldState change each ${it.changeId}" } }
611-
.chunkedLatest(200.milliseconds())
612-
.collect {
613-
log.d { "bigTextFieldState change collect ${it.changeId} ${it.bigText.length} ${it.bigText.buildString()}" }
614-
withContext(NonCancellable) { // continue to complete the current collect block even the flow is cancelled
615-
onTextChange?.let { onTextChange ->
616-
val string = it.bigText.buildCharSequence() as AnnotatedString
617-
withContext(Dispatchers.Main) {
618-
log.d { "${bigTextFieldState.text} : ${it.bigText} ${it.changeId} onTextChange(${string.text.abbr()} | ${string.text.length})" }
619-
onTextChange(string.text)
620-
log.d { "${bigTextFieldState.text} : ${it.bigText} ${it.changeId} called onTextChange(${string.text.abbr()} | ${string.text.length})" }
631+
} else {
632+
LaunchedEffect(bigTextFieldState, onTextChange) { // FIXME the flow is frequently recreated
633+
log.i { "CEV recreate change collection flow $bigTextFieldState ${onTextChange.hashCode()}" }
634+
withContext(Dispatchers.IO) {
635+
bigTextFieldState.valueChangesFlow
636+
.onEach { log.d { "bigTextFieldState change each ${it.changeId}" } }
637+
.chunkedLatest(200.milliseconds())
638+
.collect {
639+
log.d { "bigTextFieldState change collect ${it.changeId} ${it.bigText.length} ${it.bigText.buildString()}" }
640+
withContext(NonCancellable) { // continue to complete the current collect block even the flow is cancelled
641+
onTextChange?.let { onTextChange ->
642+
val string = it.bigText.buildCharSequence() as AnnotatedString
643+
withContext(Dispatchers.Main) {
644+
log.d { "${bigTextFieldState.text} : ${it.bigText} ${it.changeId} onTextChange(${string.text.abbr()} | ${string.text.length})" }
645+
onTextChange(string.text)
646+
log.d { "${bigTextFieldState.text} : ${it.bigText} ${it.changeId} called onTextChange(${string.text.abbr()} | ${string.text.length})" }
647+
}
621648
}
622-
}
623-
bigTextValueId = it.changeId
624-
searchTrigger.trySend(Unit)
649+
bigTextValueId = it.changeId
650+
searchTrigger.trySend(Unit)
625651

626-
bigTextFieldState.markConsumed(it.sequence)
652+
bigTextFieldState.markConsumed(it.sequence)
653+
}
627654
}
628-
}
629-
}
630-
}
631-
632-
var mouseHoverVariable by remember(bigTextFieldState) { mutableStateOf<String?>(null) }
633-
AppTooltipArea(
634-
isVisible = mouseHoverVariable != null && mouseHoverVariable in knownVariables,
635-
tooltipText = mouseHoverVariable?.let {
636-
val s = knownVariables[it] ?: return@let null
637-
if (s.length > ENV_VAR_VALUE_MAX_DISPLAY_LENGTH) {
638-
s.substring(0, ENV_VAR_VALUE_MAX_DISPLAY_LENGTH) + " ..."
639-
} else {
640-
s
641655
}
642-
} ?: "",
643-
modifier = Modifier.fillMaxSize(),
644-
) {
656+
}
645657
BigTextField(
646658
textFieldState = bigTextFieldState,
647659
inputFilter = inputFilter,
@@ -651,7 +663,7 @@ fun CodeEditorView(
651663
)
652664
},
653665
textDecorator = //rememberLast(bigTextFieldState, themeColours, searchResultRangeTree, searchResultViewIndex, syntaxHighlightDecorator) {
654-
MultipleTextDecorator(syntaxHighlightDecorators + variableDecorators + searchDecorators)
666+
MultipleTextDecorator(syntaxHighlightDecorators + variableDecorators + searchDecorators)
655667
//},
656668
,
657669
color = textColor,
@@ -696,11 +708,12 @@ fun CodeEditorView(
696708
},
697709
onPointerEvent = { event, charIndex, tag ->
698710
log.v { "onPointerEventOnAnnotatedTag $tag $event" }
699-
mouseHoverVariable = if (tag?.startsWith(EnvironmentVariableIncrementalTransformation.TAG_PREFIX) == true) {
700-
tag.replaceFirst(EnvironmentVariableIncrementalTransformation.TAG_PREFIX, "")
701-
} else {
702-
null
703-
}
711+
mouseHoverVariable =
712+
if (tag?.startsWith(EnvironmentVariableIncrementalTransformation.TAG_PREFIX) == true) {
713+
tag.replaceFirst(EnvironmentVariableIncrementalTransformation.TAG_PREFIX, "")
714+
} else {
715+
null
716+
}
704717
onPointerEvent?.invoke(event, charIndex)
705718
},
706719
modifier = Modifier.fillMaxSize()

0 commit comments

Comments
 (0)