7.3 KiB · text History 49b9ecf
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as QQC2
import org.kde.plasma.components as PlasmaComponents3
import org.kde.kirigami as Kirigami

import "Status.js" as Status

// One run as an accordion: the header toggles the job list, each job
// toggles its steps, and each step toggles its log slice — the same
// run → job → step drill-down the Android client uses. Expansion state
// and fetched details live on `store` (the root item) so they survive
// the list refreshing underneath. The header's bell asks for a
// notification when the run finishes; the window button (or the context
// menu) breaks the run out into its own window.
ColumnLayout {
    id: runItem

    required property var store
    required property string fullName
    required property var run
    property bool showRepo: true

    readonly property string runKey: fullName + "#" + run.number
    readonly property bool expanded: store.expandedRuns[runKey] === true
    readonly property var detail: store.runDetails[runKey] || null
    readonly property string status: Status.runStatus(run)
    readonly property bool active: Status.isActive(run.status)
    readonly property bool watching: store.watchingRun(runKey)
    readonly property bool eachJob: store.notifyingEachJob(runKey)
    // The detail's copy is fresher than the list row's once it's loaded.
    readonly property var current: detail ? detail.run : run

    spacing: 0

    // ── header ──────────────────────────────────────────────────────────
    PlasmaComponents3.ItemDelegate {
        id: header
        Layout.fillWidth: true
        onClicked: runItem.store.toggleRun(runItem.fullName, runItem.run.number)

        TapHandler {
            acceptedButtons: Qt.RightButton
            onTapped: contextMenu.popup()
        }

        PlasmaComponents3.Menu {
            id: contextMenu

            PlasmaComponents3.MenuItem {
                icon.name: "window-new"
                text: i18n("Open in Window")
                onClicked: runItem.store.openRunWindow(runItem.fullName, runItem.run.number)
            }

            PlasmaComponents3.MenuItem {
                enabled: runItem.active || runItem.watching
                icon.name: runItem.watching ? "notifications-disabled" : "notifications"
                text: runItem.watching ? i18n("Don't Notify When Finished") : i18n("Notify When Finished")
                onClicked: runItem.store.toggleWatchRun(runItem.fullName, runItem.run.number)
            }

            PlasmaComponents3.MenuItem {
                enabled: runItem.active || runItem.eachJob
                checkable: true
                checked: runItem.eachJob
                text: i18n("Notify For Each Job")
                onTriggered: runItem.store.toggleEachJob(runItem.fullName, runItem.run.number)
            }

            PlasmaComponents3.MenuItem {
                icon.name: "internet-web-browser"
                text: i18n("Open in Browser")
                onClicked: Qt.openUrlExternally(runItem.store.api.webUrl(runItem.fullName, runItem.run.number))
            }
        }

        contentItem: RowLayout {
            spacing: Kirigami.Units.smallSpacing

            Kirigami.Icon {
                source: runItem.expanded ? "arrow-down" : "arrow-right"
                Layout.preferredWidth: Kirigami.Units.iconSizes.small
                Layout.preferredHeight: Kirigami.Units.iconSizes.small
            }

            StatusCircle {
                status: runItem.status
                Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
                Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
            }

            ColumnLayout {
                Layout.fillWidth: true
                spacing: 0

                PlasmaComponents3.Label {
                    Layout.fillWidth: true
                    elide: Text.ElideRight
                    textFormat: Text.StyledText
                    text: (runItem.showRepo ? "<b>" + runItem.fullName + "</b> · " : "")
                          + Status.runTitle(runItem.run) + " #" + runItem.run.number
                }

                PlasmaComponents3.Label {
                    Layout.fillWidth: true
                    elide: Text.ElideRight
                    font: Kirigami.Theme.smallFont
                    opacity: 0.7
                    text: Status.runMeta(runItem.run)
                }
            }

            ColumnLayout {
                spacing: 0

                PlasmaComponents3.Label {
                    Layout.alignment: Qt.AlignRight
                    font: Kirigami.Theme.smallFont
                    color: Status.color(runItem.status, Kirigami.Theme)
                    text: Status.label(runItem.status)
                }

                PlasmaComponents3.Label {
                    Layout.alignment: Qt.AlignRight
                    font: Kirigami.Theme.smallFont
                    opacity: 0.7
                    // `store.now` ticks so relative times stay fresh.
                    text: (runItem.store.now, [Status.relativeTime(runItem.run.inserted_at),
                           Status.duration(runItem.run.started_at, runItem.run.completed_at)]
                          .filter(function(s) { return s !== "" }).join(" · "))
                }
            }

            // Shown while hovered, and always once ringing so you can
            // see which runs you're waiting on.
            PlasmaComponents3.ToolButton {
                visible: runItem.watching || (header.hovered && runItem.active)
                checkable: true
                checked: runItem.watching
                icon.name: runItem.watching ? "notifications" : "notification-inactive"
                text: i18n("Notify When Finished")
                display: QQC2.AbstractButton.IconOnly
                onToggled: runItem.store.toggleWatchRun(runItem.fullName, runItem.run.number)
                PlasmaComponents3.ToolTip {
                    text: runItem.eachJob ? i18n("You'll be notified as each job finishes, and when the run does")
                          : runItem.watching ? i18n("You'll be notified when this run finishes")
                          : i18n("Notify When Finished")
                }
            }

            PlasmaComponents3.ToolButton {
                visible: header.hovered
                icon.name: "window-new"
                text: i18n("Open in Window")
                display: QQC2.AbstractButton.IconOnly
                onClicked: runItem.store.openRunWindow(runItem.fullName, runItem.run.number)
                PlasmaComponents3.ToolTip { text: i18n("Open in Window") }
            }
        }
    }

    // ── body ────────────────────────────────────────────────────────────
    RunBody {
        visible: runItem.expanded
        Layout.fillWidth: true
        Layout.leftMargin: Kirigami.Units.gridUnit
        Layout.bottomMargin: Kirigami.Units.smallSpacing
        store: runItem.store
        fullName: runItem.fullName
        runNumber: runItem.run.number
        run: runItem.current
        detail: runItem.detail
    }

    Kirigami.Separator {
        Layout.fillWidth: true
        opacity: 0.5
    }
}