From a4391a14f24238319f113c7aadd459bd0d92da05 Mon Sep 17 00:00:00 2001 From: papi-ux Date: Fri, 19 Jun 2026 19:08:25 -0400 Subject: [PATCH 1/3] fix(deck): tidy Moonlight preflight preview layout --- clients/deck/qml/Main.qml | 285 +++++++++++++++--------- clients/deck/tests/deck_layout_test.cpp | 20 +- 2 files changed, 199 insertions(+), 106 deletions(-) diff --git a/clients/deck/qml/Main.qml b/clients/deck/qml/Main.qml index e2cb5ac3..855e8d9e 100644 --- a/clients/deck/qml/Main.qml +++ b/clients/deck/qml/Main.qml @@ -20,7 +20,7 @@ ApplicationWindow { readonly property int detailColumnWidth: 424 readonly property int hostCardHeight: 104 readonly property int detailPanelHeight: 150 - readonly property int launchPreviewHeight: 400 + readonly property int launchPreviewHeight: 372 readonly property int hostTextWidth: hostColumnWidth - 40 readonly property int sampleTextWidth: sampleCardWidth - 48 readonly property int detailTextWidth: detailColumnWidth - 48 @@ -530,8 +530,8 @@ ApplicationWindow { ColumnLayout { anchors.fill: parent - anchors.margins: 20 - spacing: 8 + anchors.margins: 18 + spacing: 6 Label { text: "Selected host" @@ -540,32 +540,31 @@ ApplicationWindow { } Label { + Layout.preferredWidth: detailTextWidth text: selectedHostForPreview.displayName color: "#E9ECFF" - font.pixelSize: 30 + font.pixelSize: 28 font.bold: true + maximumLineCount: 1 + elide: Text.ElideRight } Label { + Layout.preferredWidth: detailTextWidth text: selectedHostForPreview.statusLabel color: "#B8C2F0" - font.pixelSize: 19 + font.pixelSize: 17 + maximumLineCount: 1 + elide: Text.ElideRight } Label { Layout.preferredWidth: detailTextWidth text: selectedHostForPreview.subtitle color: "#A8B0D8" - font.pixelSize: 16 - wrapMode: Text.WordWrap - } - - Label { - Layout.preferredWidth: detailTextWidth - text: "Selected game: " + selectedGameForPreview.title - color: "#8AFFC1" font.pixelSize: 14 - wrapMode: Text.WordWrap + maximumLineCount: 1 + elide: Text.ElideRight } } } @@ -593,71 +592,68 @@ ApplicationWindow { ColumnLayout { anchors.fill: parent - anchors.margins: 18 - spacing: 5 - - Label { - text: novaHostLaunchCta.label - color: "#E9ECFF" - font.pixelSize: 20 - font.bold: true - } + anchors.margins: 16 + spacing: 8 - Label { + RowLayout { Layout.preferredWidth: detailTextWidth - text: novaHostLaunchCta.helpText - color: "#B8C2F0" - font.pixelSize: 14 - wrapMode: Text.WordWrap - } + spacing: 10 - Label { - Layout.preferredWidth: detailTextWidth - text: novaHostLaunchCta.previewStateLabel - color: "#FFDDA8" - font.pixelSize: 14 - font.bold: true - wrapMode: Text.WordWrap - } + ColumnLayout { + Layout.fillWidth: true + spacing: 2 - Label { - Layout.preferredWidth: detailTextWidth - text: "Safe preview: no game, stream, or network launch starts from this screen." - color: "#FFDDA8" - font.pixelSize: 13 - wrapMode: Text.WordWrap - } + Label { + text: novaHostLaunchCta.label + color: "#E9ECFF" + font.pixelSize: 19 + font.bold: true + } - Label { - Layout.preferredWidth: detailTextWidth - text: novaLaunchIntentBoundary.reason - color: "#A8B0D8" - font.pixelSize: 13 - wrapMode: Text.WordWrap + Label { + Layout.preferredWidth: detailTextWidth - 124 + text: novaHostLaunchCta.helpText + color: "#B8C2F0" + font.pixelSize: 12 + wrapMode: Text.WordWrap + } + } + + Rectangle { + Layout.preferredWidth: 138 + Layout.preferredHeight: 30 + radius: 15 + color: "#2A2539" + border.color: "#FFDDA8" + border.width: 1 + + Label { + anchors.centerIn: parent + text: novaHostLaunchCta.previewStateLabel.replace(" — not executable", "") + color: "#FFDDA8" + font.pixelSize: 10 + font.bold: true + elide: Text.ElideRight + } + } } Label { Layout.preferredWidth: detailTextWidth text: selectedLaunchPublicCopy color: "#C9F0D4" - font.pixelSize: 13 - wrapMode: Text.WordWrap - } - - Label { - Layout.preferredWidth: detailTextWidth - text: selectedStreamLifecycleCopy - color: "#A8B0D8" - font.pixelSize: 13 + font.pixelSize: 12 wrapMode: Text.WordWrap + maximumLineCount: 2 + elide: Text.ElideRight } Rectangle { id: moonlightHandoffPanel objectName: "moonlight-handoff-panel" Layout.preferredWidth: detailTextWidth - Layout.preferredHeight: 118 - radius: 14 + Layout.preferredHeight: 166 + radius: 16 color: "#101A30" border.color: "#7C73FF" border.width: 2 @@ -665,13 +661,38 @@ ApplicationWindow { ColumnLayout { anchors.fill: parent anchors.margins: 12 - spacing: 3 + spacing: 5 - Label { - text: "Moonlight handoff preview — Nothing will launch yet" - color: "#E9ECFF" - font.pixelSize: 14 - font.bold: true + RowLayout { + objectName: "moonlight-handoff-title-row" + Layout.preferredWidth: detailTextWidth - 24 + spacing: 8 + + Label { + Layout.fillWidth: true + text: "Moonlight handoff preview" + color: "#E9ECFF" + font.pixelSize: 14 + font.bold: true + elide: Text.ElideRight + } + + Rectangle { + Layout.preferredWidth: 132 + Layout.preferredHeight: 24 + radius: 12 + color: "#1E2846" + border.color: "#8AFFC1" + border.width: 1 + + Label { + anchors.centerIn: parent + text: "Nothing will launch yet" + color: "#8AFFC1" + font.pixelSize: 10 + font.bold: true + } + } } Label { @@ -680,6 +701,63 @@ ApplicationWindow { color: "#C9F0D4" font.pixelSize: 11 wrapMode: Text.WordWrap + maximumLineCount: 2 + elide: Text.ElideRight + } + + RowLayout { + objectName: "moonlight-safety-chip-row" + Layout.preferredWidth: detailTextWidth - 24 + spacing: 6 + + Rectangle { + Layout.preferredWidth: 86 + Layout.preferredHeight: 24 + radius: 12 + color: "#192842" + + Label { + anchors.centerIn: parent + text: "No launch" + color: "#E9ECFF" + font.pixelSize: 10 + font.bold: true + } + } + + Rectangle { + id: moonlightRuntimeGateChip + objectName: "moonlight-runtime-gate-chip" + Layout.preferredWidth: 134 + Layout.preferredHeight: 24 + radius: 12 + color: moonlightHandoffRuntimeGatesClosed() ? "#173326" : "#3A2224" + + Label { + anchors.centerIn: parent + text: moonlightHandoffRuntimeGatesClosed() ? "No network/process" : "Blocked" + color: moonlightHandoffRuntimeGatesClosed() ? "#8AFFC1" : "#FFDDA8" + font.pixelSize: 10 + font.bold: true + } + } + + Rectangle { + id: moonlightFocusChip + objectName: "moonlight-focus-chip" + Layout.fillWidth: true + Layout.preferredHeight: 24 + radius: 12 + color: "#151D39" + + Label { + anchors.centerIn: parent + text: "Focus: unproven_static" + color: "#B8C2F0" + font.pixelSize: 10 + font.bold: true + } + } } Label { @@ -688,6 +766,8 @@ ApplicationWindow { color: "#B8C2F0" font.pixelSize: 10 wrapMode: Text.WordWrap + maximumLineCount: 2 + elide: Text.ElideRight } Label { @@ -700,50 +780,53 @@ ApplicationWindow { font.bold: true wrapMode: Text.WordWrap } - - Label { - Layout.preferredWidth: detailTextWidth - 24 - text: "Focus return: unproven_static" - color: "#7C88B8" - font.pixelSize: 10 - wrapMode: Text.WordWrap - } } } - Button { - id: copyPreviewButton - objectName: launchPreviewCopyAction.id - text: activeFocus ? "D-pad focus · A · " + launchPreviewCopyAction.label : launchPreviewCopyAction.label - enabled: launchPreviewCopyAction.enabled - focusPolicy: Qt.StrongFocus - activeFocusOnTab: true - KeyNavigation.up: launchCtaPlaceholder - KeyNavigation.down: hostDetailPanel - Keys.onUpPressed: launchCtaPlaceholder.forceActiveFocus() - Keys.onDownPressed: hostDetailPanel.forceActiveFocus() - Keys.onLeftPressed: focusSelectedLibraryItem() - Keys.onReturnPressed: activateLaunchPreviewCopyFromController() - Keys.onEnterPressed: activateLaunchPreviewCopyFromController() - Keys.onSpacePressed: activateLaunchPreviewCopyFromController() - onClicked: activateLaunchPreviewCopyFromController() - } - - Label { + RowLayout { + objectName: "copy-preview-action-row" Layout.preferredWidth: detailTextWidth - text: "Exact preview details stay behind Copy preview details — copy locally to inspect the preview URI." - color: "#7C88B8" - font.pixelSize: 10 - wrapMode: Text.WordWrap + spacing: 10 + + Button { + id: copyPreviewButton + objectName: launchPreviewCopyAction.id + Layout.preferredWidth: 184 + Layout.preferredHeight: 30 + text: launchPreviewCopyAction.label + enabled: launchPreviewCopyAction.enabled + focusPolicy: Qt.StrongFocus + activeFocusOnTab: true + KeyNavigation.up: launchCtaPlaceholder + KeyNavigation.down: hostDetailPanel + Keys.onUpPressed: launchCtaPlaceholder.forceActiveFocus() + Keys.onDownPressed: hostDetailPanel.forceActiveFocus() + Keys.onLeftPressed: focusSelectedLibraryItem() + Keys.onReturnPressed: activateLaunchPreviewCopyFromController() + Keys.onEnterPressed: activateLaunchPreviewCopyFromController() + Keys.onSpacePressed: activateLaunchPreviewCopyFromController() + onClicked: activateLaunchPreviewCopyFromController() + } + + Label { + Layout.fillWidth: true + text: "Copy locally — no launch" + color: "#8AFFC1" + font.pixelSize: 12 + font.bold: true + wrapMode: Text.WordWrap + } } Label { id: copyStatusLabel Layout.preferredWidth: detailTextWidth - text: launchPreviewCopyAction.idleStatusLabel + " · A Copy preview saves this safe plan locally for inspection." + text: "D-pad focus · A copies preview locally; no launch." color: "#FFDDA8" - font.pixelSize: 10 - wrapMode: Text.WordWrap + font.pixelSize: 9 + wrapMode: Text.NoWrap + maximumLineCount: 1 + elide: Text.ElideRight } } } diff --git a/clients/deck/tests/deck_layout_test.cpp b/clients/deck/tests/deck_layout_test.cpp index 5cbc497a..fd4385c5 100644 --- a/clients/deck/tests/deck_layout_test.cpp +++ b/clients/deck/tests/deck_layout_test.cpp @@ -77,19 +77,20 @@ int main() { assert(mainQml.find("novaLibraryHosts") != std::string::npos); assert(mainQml.find("libraryGameRepeater") != std::string::npos); assert(mainQml.find("Polaris library preview") != std::string::npos); - assert(mainQml.find("novaLaunchIntentBoundary") != std::string::npos); - assert(mainQml.find("Safe preview: no game, stream, or network launch starts from this screen.") != std::string::npos); + assert(mainQml.find("novaHostLaunchCta.helpText") != std::string::npos); + assert(mainQml.find("novaHostLaunchCta.previewStateLabel") != std::string::npos); + assert(mainQml.find("text: novaHostLaunchCta.helpText") != std::string::npos); assert(mainQml.find("D-pad Navigate") != std::string::npos); assert(mainQml.find("selectedHostForPreview") != std::string::npos); assert(mainQml.find("selectedGameForPreview") != std::string::npos); assert(mainQml.find("refreshLaunchPreviewBinding") != std::string::npos); assert(mainQml.find("selectedLaunchPreviewText") != std::string::npos); assert(mainQml.find("Selected host") != std::string::npos); - assert(mainQml.find("Selected game") != std::string::npos); + assert(mainQml.find("selectedGameForPreview.title") != std::string::npos); assert(mainQml.find("No games in read-only snapshot") != std::string::npos); assert(mainQml.find("Preview snapshot ready") != std::string::npos); assert(mainQml.find("Snapshot unavailable in this preview shell") != std::string::npos); - assert(mainQml.find("A Copy preview saves this safe plan locally for inspection") != std::string::npos); + assert(mainQml.find("A copies preview locally; no launch") != std::string::npos); assert(mainQml.find("novaLaunchIntentPreview") != std::string::npos); assert(mainQml.find("selectedLaunchPublicCopy") != std::string::npos); assert(mainQml.find("selectedStreamLifecycleCopy") != std::string::npos); @@ -98,9 +99,18 @@ int main() { assert(mainQml.find("readonly property color focusGlowColor") != std::string::npos); assert(mainQml.find("cursorShape: Qt.BlankCursor") != std::string::npos); assert(mainQml.find("D-pad focus") != std::string::npos); - assert(mainQml.find("Exact preview details stay behind Copy preview details") != std::string::npos); + assert(mainQml.find("Exact preview details stay behind Copy preview details") == std::string::npos); assert(mainQml.find("objectName: \"moonlight-handoff-panel\"") != std::string::npos); + assert(mainQml.find("objectName: \"moonlight-handoff-title-row\"") != std::string::npos); + assert(mainQml.find("objectName: \"moonlight-safety-chip-row\"") != std::string::npos); + assert(mainQml.find("objectName: \"moonlight-runtime-gate-chip\"") != std::string::npos); + assert(mainQml.find("objectName: \"moonlight-focus-chip\"") != std::string::npos); + assert(mainQml.find("objectName: \"copy-preview-action-row\"") != std::string::npos); assert(mainQml.find("Moonlight handoff preview") != std::string::npos); + assert(mainQml.find("No launch") != std::string::npos); + assert(mainQml.find("No network/process") != std::string::npos); + assert(mainQml.find("Focus: unproven_static") != std::string::npos); + assert(mainQml.find("Copy locally — no launch") != std::string::npos); assert(mainQml.find("selectedMoonlightHandoffCopy") != std::string::npos); assert(mainQml.find("selectedMoonlightHandoffArgvPreview") != std::string::npos); assert(mainQml.find("Typed argv plan") != std::string::npos); From 5e1fa0b23bd75727321ef42a135e0b6233e74425 Mon Sep 17 00:00:00 2001 From: papi-ux Date: Fri, 19 Jun 2026 19:51:46 -0400 Subject: [PATCH 2/3] fix(deck): refine Moonlight preview right rail --- clients/deck/qml/Main.qml | 106 ++++++++++++++++++------ clients/deck/tests/deck_layout_test.cpp | 17 +++- 2 files changed, 93 insertions(+), 30 deletions(-) diff --git a/clients/deck/qml/Main.qml b/clients/deck/qml/Main.qml index 855e8d9e..157b6890 100644 --- a/clients/deck/qml/Main.qml +++ b/clients/deck/qml/Main.qml @@ -19,8 +19,8 @@ ApplicationWindow { readonly property int sampleCardWidth: 392 readonly property int detailColumnWidth: 424 readonly property int hostCardHeight: 104 - readonly property int detailPanelHeight: 150 - readonly property int launchPreviewHeight: 372 + readonly property int detailPanelHeight: 132 + readonly property int launchPreviewHeight: 400 readonly property int hostTextWidth: hostColumnWidth - 40 readonly property int sampleTextWidth: sampleCardWidth - 48 readonly property int detailTextWidth: detailColumnWidth - 48 @@ -530,20 +530,20 @@ ApplicationWindow { ColumnLayout { anchors.fill: parent - anchors.margins: 18 - spacing: 6 + anchors.margins: 14 + spacing: 4 Label { text: "Selected host" color: "#7C88B8" - font.pixelSize: 16 + font.pixelSize: 13 } Label { Layout.preferredWidth: detailTextWidth text: selectedHostForPreview.displayName color: "#E9ECFF" - font.pixelSize: 28 + font.pixelSize: 24 font.bold: true maximumLineCount: 1 elide: Text.ElideRight @@ -553,7 +553,7 @@ ApplicationWindow { Layout.preferredWidth: detailTextWidth text: selectedHostForPreview.statusLabel color: "#B8C2F0" - font.pixelSize: 17 + font.pixelSize: 14 maximumLineCount: 1 elide: Text.ElideRight } @@ -562,7 +562,7 @@ ApplicationWindow { Layout.preferredWidth: detailTextWidth text: selectedHostForPreview.subtitle color: "#A8B0D8" - font.pixelSize: 14 + font.pixelSize: 12 maximumLineCount: 1 elide: Text.ElideRight } @@ -638,21 +638,55 @@ ApplicationWindow { } } - Label { + Rectangle { + id: launchTargetSummaryCard + objectName: "launch-target-summary-card" Layout.preferredWidth: detailTextWidth - text: selectedLaunchPublicCopy - color: "#C9F0D4" - font.pixelSize: 12 - wrapMode: Text.WordWrap - maximumLineCount: 2 - elide: Text.ElideRight + Layout.preferredHeight: 70 + radius: 14 + color: "#10172B" + border.color: "#2E3B66" + border.width: 1 + + ColumnLayout { + anchors.fill: parent + anchors.margins: 10 + spacing: 3 + + Label { + text: "Review path" + color: "#7C88B8" + font.pixelSize: 11 + font.bold: true + } + + Label { + objectName: "launch-target-title" + Layout.preferredWidth: detailTextWidth - 20 + text: selectedGameForPreview.title + " → " + selectedHostForPreview.displayName + color: "#C9F0D4" + font.pixelSize: 13 + font.bold: true + maximumLineCount: 1 + elide: Text.ElideRight + } + + Label { + Layout.preferredWidth: detailTextWidth - 20 + text: "Safe preview only · no game or stream starts" + color: "#FFDDA8" + font.pixelSize: 11 + maximumLineCount: 1 + elide: Text.ElideRight + } + } } Rectangle { id: moonlightHandoffPanel objectName: "moonlight-handoff-panel" Layout.preferredWidth: detailTextWidth - Layout.preferredHeight: 166 + Layout.preferredHeight: 178 radius: 16 color: "#101A30" border.color: "#7C73FF" @@ -760,25 +794,43 @@ ApplicationWindow { } } - Label { + RowLayout { + objectName: "moonlight-plan-row" Layout.preferredWidth: detailTextWidth - 24 - text: "Typed argv plan · redacted host selector · " + selectedMoonlightHandoffArgvPreview - color: "#B8C2F0" - font.pixelSize: 10 - wrapMode: Text.WordWrap - maximumLineCount: 2 - elide: Text.ElideRight + spacing: 8 + + Label { + Layout.fillWidth: true + text: "Typed argv plan" + color: "#B8C2F0" + font.pixelSize: 10 + font.bold: true + maximumLineCount: 1 + elide: Text.ElideRight + } + + Label { + Layout.preferredWidth: 210 + text: "redacted argv · local preview only" + color: "#B8C2F0" + font.pixelSize: 10 + horizontalAlignment: Text.AlignRight + maximumLineCount: 1 + elide: Text.ElideRight + } } Label { + objectName: "moonlight-runtime-gates-line" Layout.preferredWidth: detailTextWidth - 24 text: moonlightHandoffRuntimeGatesClosed() - ? "Runtime gates: network off · process off · Moonlight off · host mutation off" + ? "Runtime locked: network · process · Moonlight · host off" : "Runtime gate failed — review blocked" color: "#FFDDA8" font.pixelSize: 10 font.bold: true - wrapMode: Text.WordWrap + maximumLineCount: 1 + elide: Text.ElideRight } } } @@ -821,7 +873,9 @@ ApplicationWindow { Label { id: copyStatusLabel Layout.preferredWidth: detailTextWidth - text: "D-pad focus · A copies preview locally; no launch." + Layout.preferredHeight: visible ? 14 : 0 + text: "" + visible: text.length > 0 color: "#FFDDA8" font.pixelSize: 9 wrapMode: Text.NoWrap diff --git a/clients/deck/tests/deck_layout_test.cpp b/clients/deck/tests/deck_layout_test.cpp index fd4385c5..19e0ad51 100644 --- a/clients/deck/tests/deck_layout_test.cpp +++ b/clients/deck/tests/deck_layout_test.cpp @@ -90,7 +90,7 @@ int main() { assert(mainQml.find("No games in read-only snapshot") != std::string::npos); assert(mainQml.find("Preview snapshot ready") != std::string::npos); assert(mainQml.find("Snapshot unavailable in this preview shell") != std::string::npos); - assert(mainQml.find("A copies preview locally; no launch") != std::string::npos); + assert(mainQml.find("copyStatusLabel.text = didCopyPreview") != std::string::npos); assert(mainQml.find("novaLaunchIntentPreview") != std::string::npos); assert(mainQml.find("selectedLaunchPublicCopy") != std::string::npos); assert(mainQml.find("selectedStreamLifecycleCopy") != std::string::npos); @@ -98,11 +98,16 @@ int main() { assert(mainQml.find("readonly property color focusRingColor") != std::string::npos); assert(mainQml.find("readonly property color focusGlowColor") != std::string::npos); assert(mainQml.find("cursorShape: Qt.BlankCursor") != std::string::npos); - assert(mainQml.find("D-pad focus") != std::string::npos); + assert(mainQml.find("D-pad Navigate") != std::string::npos); assert(mainQml.find("Exact preview details stay behind Copy preview details") == std::string::npos); + assert(mainQml.find("objectName: \"launch-target-summary-card\"") != std::string::npos); + assert(mainQml.find("objectName: \"launch-target-title\"") != std::string::npos); + assert(mainQml.find("Review path") != std::string::npos); assert(mainQml.find("objectName: \"moonlight-handoff-panel\"") != std::string::npos); assert(mainQml.find("objectName: \"moonlight-handoff-title-row\"") != std::string::npos); assert(mainQml.find("objectName: \"moonlight-safety-chip-row\"") != std::string::npos); + assert(mainQml.find("objectName: \"moonlight-plan-row\"") != std::string::npos); + assert(mainQml.find("objectName: \"moonlight-runtime-gates-line\"") != std::string::npos); assert(mainQml.find("objectName: \"moonlight-runtime-gate-chip\"") != std::string::npos); assert(mainQml.find("objectName: \"moonlight-focus-chip\"") != std::string::npos); assert(mainQml.find("objectName: \"copy-preview-action-row\"") != std::string::npos); @@ -111,11 +116,15 @@ int main() { assert(mainQml.find("No network/process") != std::string::npos); assert(mainQml.find("Focus: unproven_static") != std::string::npos); assert(mainQml.find("Copy locally — no launch") != std::string::npos); + assert(mainQml.find("id: copyStatusLabel") != std::string::npos); + assert(mainQml.find("visible: text.length > 0") != std::string::npos); + assert(mainQml.find("D-pad focus · A copies preview locally; no launch.") == std::string::npos); assert(mainQml.find("selectedMoonlightHandoffCopy") != std::string::npos); assert(mainQml.find("selectedMoonlightHandoffArgvPreview") != std::string::npos); assert(mainQml.find("Typed argv plan") != std::string::npos); - assert(mainQml.find("redacted host selector") != std::string::npos); - assert(mainQml.find("Runtime gates: network off · process off · Moonlight off · host mutation off") != std::string::npos); + assert(mainQml.find("redacted argv · local preview only") != std::string::npos); + assert(mainQml.find("Typed argv plan · redacted host selector · ") == std::string::npos); + assert(mainQml.find("Runtime locked: network · process · Moonlight · host off") != std::string::npos); assert(mainQml.find("unproven_static") != std::string::npos); assert(mainQml.find("Nothing will launch yet") != std::string::npos); assert(mainQml.find("novaMoonlightHandoffPreflightBridge.resolve") != std::string::npos); From b6170aec0e8af5d3ecabdcfc537cc5bf179c9252 Mon Sep 17 00:00:00 2001 From: papi-ux Date: Fri, 19 Jun 2026 20:35:40 -0400 Subject: [PATCH 3/3] fix(deck): gate Moonlight plan copy in preview --- clients/deck/qml/Main.qml | 6 +++--- clients/deck/tests/deck_layout_test.cpp | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/clients/deck/qml/Main.qml b/clients/deck/qml/Main.qml index 157b6890..1d865094 100644 --- a/clients/deck/qml/Main.qml +++ b/clients/deck/qml/Main.qml @@ -611,7 +611,7 @@ ApplicationWindow { } Label { - Layout.preferredWidth: detailTextWidth - 124 + Layout.preferredWidth: detailTextWidth - 148 text: novaHostLaunchCta.helpText color: "#B8C2F0" font.pixelSize: 12 @@ -801,7 +801,7 @@ ApplicationWindow { Label { Layout.fillWidth: true - text: "Typed argv plan" + text: moonlightHandoffRuntimeGatesClosed() ? "Typed argv plan" : "Review blocked" color: "#B8C2F0" font.pixelSize: 10 font.bold: true @@ -811,7 +811,7 @@ ApplicationWindow { Label { Layout.preferredWidth: 210 - text: "redacted argv · local preview only" + text: moonlightHandoffRuntimeGatesClosed() ? "redacted argv · local preview only" : selectedMoonlightHandoffArgvPreview color: "#B8C2F0" font.pixelSize: 10 horizontalAlignment: Text.AlignRight diff --git a/clients/deck/tests/deck_layout_test.cpp b/clients/deck/tests/deck_layout_test.cpp index 19e0ad51..9029db40 100644 --- a/clients/deck/tests/deck_layout_test.cpp +++ b/clients/deck/tests/deck_layout_test.cpp @@ -103,6 +103,8 @@ int main() { assert(mainQml.find("objectName: \"launch-target-summary-card\"") != std::string::npos); assert(mainQml.find("objectName: \"launch-target-title\"") != std::string::npos); assert(mainQml.find("Review path") != std::string::npos); + assert(mainQml.find("Layout.preferredWidth: detailTextWidth - 148") != std::string::npos); + assert(mainQml.find("Layout.preferredWidth: detailTextWidth - 124") == std::string::npos); assert(mainQml.find("objectName: \"moonlight-handoff-panel\"") != std::string::npos); assert(mainQml.find("objectName: \"moonlight-handoff-title-row\"") != std::string::npos); assert(mainQml.find("objectName: \"moonlight-safety-chip-row\"") != std::string::npos); @@ -122,6 +124,10 @@ int main() { assert(mainQml.find("selectedMoonlightHandoffCopy") != std::string::npos); assert(mainQml.find("selectedMoonlightHandoffArgvPreview") != std::string::npos); assert(mainQml.find("Typed argv plan") != std::string::npos); + assert(mainQml.find("Review blocked") != std::string::npos); + assert(mainQml.find("text: moonlightHandoffRuntimeGatesClosed() ? \"Typed argv plan\" : \"Review blocked\"") != std::string::npos); + assert(mainQml.find("text: moonlightHandoffRuntimeGatesClosed() ? \"redacted argv · local preview only\" : selectedMoonlightHandoffArgvPreview") != std::string::npos); + assert(mainQml.find("Typed argv plan unavailable until the preflight is safe to render") != std::string::npos); assert(mainQml.find("redacted argv · local preview only") != std::string::npos); assert(mainQml.find("Typed argv plan · redacted host selector · ") == std::string::npos); assert(mainQml.find("Runtime locked: network · process · Moonlight · host off") != std::string::npos);