Multi-line action result values - #3866
Merged
Merged
Conversation
MattDHill
force-pushed
the
feat/known-registries
branch
from
September 3, 2026 03:14
b03057f to
038634c
Compare
`ActionResultValue` had two variants and neither could carry multi-line text.
`Single` renders as an `<input>`, and HTML's value-sanitization algorithm strips
CR/LF from a text input's value, so a multi-line `value` arrived with its lines
concatenated. That left `message` as the only home for a diagnostic report, a
generated config file or an exported key block — prose under the title, with no
name, no copy affordance, no QR and no download. Action *inputs* have had
`ValueSpecTextarea` since the start; results had no counterpart, and packagers
worked around the gap by returning the same report twice.
`Multiline` is a third variant rather than `Single { multiline: bool }`: the
widget differs, the sizing differs, and the flags mean different things per
widget. `filename` is what separates "here is some text" from "here is a file" —
set it and the value is offered as a download, leave it null and it is text on
the screen.
The component is StartTunnel's device-config dialog minus its help
infrastructure: a read-only `textarea tuiTextarea` inside a `tui-textfield`,
sized to content between 3 and 16 rows, monospace so aligned columns survive,
masked by blur with a reveal button, and a QR opened through the same dialog
`action-success-member` already used. Name and description sit above the field
as a `tuiTitle`/`tuiSubtitle` pair, the way the About modal groups an item with
its caption.
Two things the tall textarea exposed that a one-line input hid. Every in-field
control carries `(pointerdown.stop)`, because `TuiTextfieldComponent` projects
them into a `.t-content` span that focuses the input on any pointerdown that
reaches it — harmless for an `<input>`, a jarring scroll for a 16-row textarea.
And the result dialog opens at size `l` when the result carries a multiline
value at any depth, so a report's columns do not wrap mid-row.
`fmt_rec`'s `Single` and `Multiline` arms are one or-pattern that indents every
line of a value, so `start-cli` prints the new variant like the old one.
`--tui-typography-family-code` is defined in the theme sheet because Taiga's
default resolves to 'JetBrains Mono', which this app does not load, and would
have silently fallen back to the sans stack.
Closes #3810
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MattDHill
force-pushed
the
feat/action-result-multiline
branch
from
September 3, 2026 13:40
4f0bd30 to
d2645f6
Compare
dr-bonez
approved these changes
Sep 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3810.
The gap
ActionResultValuehad two variants and neither could carry multi-line text.Singlerenders as an<input>, and HTML's value-sanitization algorithm strips CR/LF from a text input's value, so a multi-linevaluearrived with its lines concatenated. That leftmessageas the only home for a diagnostic report, a generated config file or an exported key block — prose under the title, with no name, no copy affordance, no QR and no download. Action inputs have hadValueSpecTextareasince the start; results had no counterpart, and packagers worked around it by returning the same report twice (Start9-Community/vikunja-startos#6).The variant
A third variant rather than
Single { multiline: bool }: the widget differs, the sizing differs, and the flags mean different things per widget — one component branching across two layouts is the shape that produced the group-copy bug in #3792. It also keepsSingle's contract, and its doc comments, true.Every flag is optional and defaults to
false, the contract #3878 set forsingle's flags;launchablestays onsingle, where the value is a URL.filenameis what separates "here is some text" from "here is a file". Set it and the value is offered as a download under that name; omit it and it is text on the screen.The widget
StartTunnel's device-config dialog minus its help infrastructure: a read-only
textarea tuiTextareainside atui-textfield, sized to content between 3 and 16 rows, monospace so aligned columns survive, masked by blur with a reveal button, and a QR opened through the same dialogaction-success-memberalready used. Name and description sit above the field as atuiTitle/tuiSubtitlepair, the wayabout.component.tsgroups a modal item with its caption.Two things the tall textarea exposed that a one-line input had been hiding:
TuiTextfieldComponentprojects everything that isn't the input or label into a<span class="t-content" (pointerdown)="input()?.nativeElement?.focus()">. That handler has no.self, so clicking any in-field icon focuses the input — imperceptible for an<input>, a jarring scroll for a 16-row textarea below the fold. Every in-field control now carries(pointerdown.stop). Copy also moved fromtuiCopytoCopyService, sincetuiCopycopies by calling.select()on the native element, which scrolls for the same reason;CopyServiceis what both sibling components and the About modal already use.lwhen the result carries a multiline value at any depth, so a report's columns don't wrap mid-row.Elsewhere
fmt_rec'sSingleandMultilinearms are one or-pattern that indents every line of a value, sostart-cliprints the new variant the way it prints the old one.--tui-typography-family-codeis defined in the theme sheet alongside the existing family overrides. Taiga's default resolves to'JetBrains Mono', which this app doesn't load, so it would have silently fallen back to the sans stack and defeated the aligned columns.singleand threemultilinemembers).actions.md§ Result Types now documents all three variants and what each takes; changelog entries in0.4.0.2and SDK2.0.10. No new i18n keys —Show QR,Scan this QR,Reveal,Reveal/HideandDownloadall already existed.One thing to check
The two regenerated bindings are hand-written.
make start-core-ts-bindingscompiles start-core atopt-level = 3with full debuginfo, which does not fit in this machine's docker budget.ActionResultValue.tsandActionResultMember.tswere written by hand from the existing generated output, including #3878's optional-field form. TheGenerated Artifactsjob uploads what it regenerates, so ifstart-core-ts-bindings-checkfails, the run's artifact replaces them.🤖 Generated with Claude Code