rotated view + wheel inverter

This commit is contained in:
2026-08-26 17:10:34 +02:00
parent 78988700be
commit c33dbc147f
7 changed files with 341 additions and 135 deletions
@@ -5,92 +5,106 @@ import ZShell.Llm
import qs.Components
import qs.Services
Item {
CustomClippingRect {
id: root
required property var segments
required property bool isActive
required property int index
required property var modelData
required property var blocks
readonly property var segments: modelData.segments
readonly property bool isActive: index === blocks.length - 1
property bool expanded: false
readonly property LlmSegment lastSegment: root.segments[root.segments.length - 1]
readonly property real totalElapsedMs: root.segments.reduce((sum, s) => sum + (s.elapsedMs ?? 0), 0)
implicitHeight: expandedRect.implicitHeight + collapsedText.implicitHeight + expandedRect.anchors.topMargin
implicitHeight: expanded ? expandedRect.implicitHeight + layout.implicitHeight + expandedRect.anchors.topMargin * 2 : layout.implicitHeight + Tokens.spacing.small
LoadingIndicator {
id: spinnerReasoning
anchors.centerIn: expandBtn
implicitSize: collapsedText.implicitHeight
opacity: root.isActive ? 1 : 0
visible: opacity > 0
Behavior on opacity {
Anim {}
Behavior on implicitHeight {
Anim {
type: Anim.DefaultEffects
}
}
IconButton {
id: expandBtn
RowLayout {
id: layout
anchors.left: parent.left
anchors.verticalCenter: collapsedText.verticalCenter
font.pointSize: Tokens.font.size.large
anchors.topMargin: 0
icon: "keyboard_arrow_down"
inactiveOnColor: hovered ? Colors.palette.m3onSurface : Colors.palette.m3outline
opacity: root.isActive ? 0 : 1
rotation: root.expanded ? 180 : 0
type: IconButton.Text
Behavior on rotation {
Anim {}
}
onClicked: root.expanded = !root.expanded
}
CustomText {
id: collapsedText
anchors.left: expandBtn.right
anchors.margins: Tokens.padding.medium
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: 0
color: Colors.palette.m3outline
font.pointSize: Tokens.font.size.small
text: {
if (root.isActive) {
if (root.lastSegment.type === LlmSegment.Type.ToolCall)
return qsTr("Using %1...").arg(root.lastSegment.name);
return qsTr("Thinking...");
anchors.left: parent.left
anchors.right: parent.right
Item {
implicitHeight: expandBtn.implicitHeight
implicitWidth: expandBtn.implicitWidth
LoadingIndicator {
id: spinnerReasoning
implicitSize: collapsedText.implicitHeight
anchors.centerIn: parent
opacity: root.isActive ? 1 : 0
visible: opacity > 0
Behavior on opacity {
Anim {}
}
}
IconButton {
id: expandBtn
font.pointSize: Tokens.font.size.large
icon: "keyboard_arrow_down"
inactiveOnColor: hovered ? Colors.palette.m3onSurface : Colors.palette.m3outline
anchors.centerIn: parent
opacity: root.isActive ? 0 : 1
rotation: root.expanded ? 180 : 0
type: IconButton.Text
Behavior on rotation {
Anim {}
}
onClicked: root.expanded = !root.expanded
}
return qsTr("Worked for %1s").arg((root.totalElapsedMs / 1000).toFixed(1));
}
Behavior on opacity {
Anim {}
CustomText {
id: collapsedText
color: Colors.palette.m3outline
font.pointSize: Tokens.font.size.small
Layout.fillWidth: true
Layout.leftMargin: Tokens.spacing.medium
text: {
if (root.isActive) {
if (root.lastSegment.type === LlmSegment.Type.ToolCall)
return qsTr("Using %1...").arg(root.lastSegment.name);
return qsTr("Thinking...");
}
return qsTr("Worked for %1s").arg((root.totalElapsedMs / 1000).toFixed(1));
}
Behavior on opacity {
Anim {}
}
}
}
CustomClippingRect {
CustomRect {
id: expandedRect
anchors.left: parent.left
anchors.right: parent.right
anchors.top: collapsedText.bottom
anchors.topMargin: Tokens.spacing.medium
anchors.top: layout.bottom
anchors.bottom: parent.bottom
anchors.topMargin: Tokens.spacing.small
anchors.bottomMargin: Tokens.spacing.small
color: Colors.palette.m3surfaceContainerLow
implicitHeight: root.expanded ? expandedContent.contentHeight + expandedContent.anchors.margins * 2 : 0
implicitHeight: expandedContent.contentHeight + expandedContent.anchors.margins * 2
opacity: root.expanded ? 1 : 0
radius: Tokens.rounding.medium
visible: opacity > 0
Behavior on implicitHeight {
Anim {
type: Anim.DefaultEffects
}
}
Behavior on opacity {
Anim {}
}