pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import ZShell.Config import ZShell.Components import qs.Components import qs.Services SnapLayout { id: root required property var greeter anchors.fill: parent anchors.margins: Tokens.padding.large spacing: Tokens.spacing.large orientation: Qt.Vertical CustomText { Layout.fillWidth: true color: Colors.palette.m3outline elide: Text.ElideRight font: Tokens.font.mono.builders.small.weight(Font.Medium).build() text: root.greeter.sessions.length > 0 ? qsTr("%1 session%2").arg(root.greeter.sessions.length).arg(root.greeter.sessions.length === 1 ? "" : "s") : qsTr("Sessions") } Item { Layout.fillHeight: true Layout.fillWidth: true Loader { active: opacity > 0 anchors.centerIn: parent opacity: root.greeter.sessions.length > 0 ? 0 : 1 Behavior on opacity { Anim { duration: Tokens.anim.durations.extraLarge } } sourceComponent: SnapLayout { spacing: Tokens.spacing.largeIncreased orientation: Qt.Vertical MaterialIcon { Layout.alignment: Qt.AlignHCenter color: Colors.palette.m3outlineVariant fontStyle: Tokens.font.icon.large text: "desktop_windows" } CustomText { Layout.alignment: Qt.AlignHCenter color: Colors.palette.m3outlineVariant font: Tokens.font.headline.builders.small.width(90).build() text: qsTr("No Sessions Found") } } } ListView { id: sessions anchors.fill: parent clip: true currentIndex: root.greeter.sessionIndex highlightFollowsCurrentItem: false boundsBehavior: ListView.StopAtBounds model: root.greeter.sessions spacing: Tokens.spacing.small delegate: CustomRect { id: session required property int index required property var modelData anchors.left: parent?.left anchors.right: parent?.right implicitHeight: row.implicitHeight + Tokens.padding.small * 2 radius: Tokens.rounding.large StateLayer { onClicked: { root.greeter.sessionIndex = index; } } SnapLayout { id: row anchors.fill: parent anchors.margins: Tokens.padding.small spacing: Tokens.spacing.medium MaterialIcon { color: session.index === sessions.currentIndex ? Colors.palette.m3onPrimary : Colors.palette.m3onSurfaceVariant fontStyle: Tokens.font.icon.extraLarge text: modelData.kind === "x11" ? "tv" : "desktop_windows" } SnapLayout { Layout.fillWidth: true spacing: Tokens.spacing.small / 2 orientation: Qt.Vertical CustomText { Layout.fillWidth: true color: session.index === sessions.currentIndex ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface elide: Text.ElideRight font: Tokens.font.body.builders.medium.weight(Font.Bold).build() text: modelData.name } CustomText { Layout.fillWidth: true color: session.index === sessions.currentIndex ? Colors.palette.m3onPrimaryFixedVariant : Colors.palette.m3onSurfaceVariant elide: Text.ElideRight font: Tokens.font.mono.small text: modelData.kind } } } } highlight: CustomRect { color: Colors.palette.m3primary implicitHeight: sessions.currentItem?.implicitHeight ?? 0 implicitWidth: sessions.width radius: Tokens.rounding.large y: sessions.currentItem?.y ?? 0 Behavior on y { Anim { duration: Tokens.anim.durations.small easing: Tokens.anim.expressiveDefaultEffects } } } } } }