Split the bar panel into one QML file per stage

Panel.qml keeps the state, the CLI calls and the stage switch (889 lines,
was 2360); each stage is its own file taking the panel as a required
property. The omarchy installer copies every QML/JS file and clears stale
ones. tests/static.sh filters qmllint on [syntax], not the word error.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
smoido
2026-09-15 02:12:49 +03:00
co-authored by Claude Opus 5
parent 4091746d4e
commit bb01418ce0
17 changed files with 1717 additions and 1510 deletions
@@ -0,0 +1,218 @@
import QtQuick
import qs.Commons
import qs.Ui
// BrokenSessions.qml - Sessions that a switch cut short. Shown in the list, because the point is to be noticed without going looking.
//
// One stage of the claude-mode panel. Panel.qml hands itself in as `panel`
// and owns all the state and actions; this file only draws them.
Column {
id: stage
required property var panel
width: parent.width
visible: stage.panel.stage === "list" && (stage.panel.broken.length > 0 || stage.panel.ignored.length > 0)
spacing: Style.space(4)
PanelSeparator { width: parent.width }
Text {
width: parent.width
visible: stage.panel.broken.length > 0
text: stage.panel.broken.length === 1
? "1 session cannot be resumed"
: stage.panel.broken.length + " sessions cannot be resumed"
color: stage.panel.urgentColor
wrapMode: Text.WordWrap
font.family: stage.panel.uiFont
font.pixelSize: Style.space(11)
font.bold: true
}
Repeater {
model: stage.panel.stage === "list" ? stage.panel.broken : []
Item {
id: brokenRow
required property var modelData
width: stage.width
height: Style.space(26)
Column {
anchors.left: parent.left
anchors.right: ignoreBtn.left
anchors.rightMargin: Style.space(6)
anchors.verticalCenter: parent.verticalCenter
spacing: 0
Text {
width: parent.width
text: String(brokenRow.modelData.sessionId).substring(0, 8)
+ " · " + stage.panel.projectLabel(brokenRow.modelData.project)
color: Color.popups.text
elide: Text.ElideMiddle
font.family: stage.panel.uiFont
font.pixelSize: Style.space(10)
}
Text {
width: parent.width
text: brokenRow.modelData.dropLines + " turn lines after the last good message"
color: Color.muted
elide: Text.ElideRight
font.family: stage.panel.uiFont
font.pixelSize: Style.space(9)
}
}
PillButton { fontFamily: stage.panel.uiFont;
id: ignoreBtn
anchors.right: repairBtn.left
anchors.rightMargin: Style.space(5)
anchors.verticalCenter: parent.verticalCenter
label: "Ignore"
onTriggered: stage.panel.setIgnored(brokenRow.modelData, true)
}
PillButton { fontFamily: stage.panel.uiFont;
id: repairBtn
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
label: "Repair"
onTriggered: stage.panel.askRepair(brokenRow.modelData)
}
}
}
// ---- Hidden: dismissed here, or broken but untouched for longer than
// the age limit. Collapsed, because the point of hiding them was that
// they stop taking up attention - but never gone without a trace.
Item {
width: parent.width
height: Style.space(20)
visible: stage.panel.ignored.length > 0
Text {
id: hiddenLabel
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: "hidden (" + stage.panel.ignored.length + ")"
color: hiddenArea.containsMouse ? Color.popups.text : Color.muted
font.family: stage.panel.uiFont
font.pixelSize: Style.space(10)
}
Text {
anchors.left: hiddenLabel.right
anchors.leftMargin: Style.space(4)
anchors.verticalCenter: parent.verticalCenter
text: String.fromCodePoint(stage.panel.hiddenExpanded ? 0xF0140 : 0xF0142)
color: hiddenLabel.color
font.family: stage.panel.uiFont
font.pixelSize: Style.space(11)
}
MouseArea {
id: hiddenArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: stage.panel.hiddenExpanded = !stage.panel.hiddenExpanded
}
}
Column {
width: parent.width
visible: stage.panel.hiddenExpanded && stage.panel.ignored.length > 0
spacing: Style.space(3)
Text {
visible: stage.panel.dismissedList.length > 0
text: "Ignored (" + stage.panel.dismissedList.length + ")"
color: Color.popups.text
font.family: stage.panel.uiFont
font.pixelSize: Style.space(10)
font.bold: true
}
Repeater {
model: stage.panel.hiddenExpanded ? stage.panel.dismissedList.slice(0, stage.panel.hiddenCap) : []
Item {
id: dismissedRow
required property var modelData
width: stage.width
height: Style.space(26)
Text {
anchors.left: parent.left
anchors.right: restoreBtn.left
anchors.rightMargin: Style.space(6)
anchors.verticalCenter: parent.verticalCenter
text: String(dismissedRow.modelData.sessionId).substring(0, 8)
+ " · " + stage.panel.projectLabel(dismissedRow.modelData.project)
color: Color.muted
elide: Text.ElideMiddle
font.family: stage.panel.uiFont
font.pixelSize: Style.space(10)
}
PillButton { fontFamily: stage.panel.uiFont;
id: restoreBtn
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
label: "Restore"
onTriggered: stage.panel.setIgnored(dismissedRow.modelData, false)
}
}
}
Text {
visible: stage.panel.dismissedList.length > stage.panel.hiddenCap
text: "… and " + (stage.panel.dismissedList.length - stage.panel.hiddenCap)
+ " more · claude-mode repair-session --ignored"
color: Color.muted
font.family: stage.panel.uiFont
font.pixelSize: Style.space(9)
}
Text {
visible: stage.panel.staleList.length > 0
text: "Older than " + stage.panel.ageDays + " days (" + stage.panel.staleList.length + ")"
color: Color.popups.text
font.family: stage.panel.uiFont
font.pixelSize: Style.space(10)
font.bold: true
}
Repeater {
model: stage.panel.hiddenExpanded ? stage.panel.staleList.slice(0, stage.panel.hiddenCap) : []
Text {
required property var modelData
width: stage.width
text: String(modelData.sessionId).substring(0, 8)
+ " · " + Math.floor((Date.now() / 1000 - Number(modelData.mtime)) / 86400) + "d"
+ " · " + stage.panel.projectLabel(modelData.project)
color: Color.muted
elide: Text.ElideMiddle
font.family: stage.panel.uiFont
font.pixelSize: Style.space(10)
}
}
Text {
width: parent.width
visible: stage.panel.staleList.length > 0
text: (stage.panel.staleList.length > stage.panel.hiddenCap
? "… and " + (stage.panel.staleList.length - stage.panel.hiddenCap) + " more. " : "")
+ "Not counted because nothing has touched them since. "
+ "claude-mode repair-session --all --max-age 0 lists them."
color: Color.muted
opacity: 0.85
wrapMode: Text.WordWrap
font.family: stage.panel.uiFont
font.pixelSize: Style.space(9)
}
}
}