pragma ComponentBehavior: Bound import Quickshell import QtQuick import ZShell.Config import qs.Components import qs.Helpers import qs.Services Item { id: root required property bool isCurrent required property var modelData required property real tileHeight required property real tileWidth required property ScreenState screenState signal requestActivate implicitHeight: tileHeight + Tokens.padding.large * 2 implicitWidth: tileWidth ClipRect { id: image anchors.horizontalCenter: parent.horizontalCenter color: Colors.tPalette.m3surfaceContainer implicitHeight: root.tileHeight implicitWidth: root.tileWidth radius: Tokens.rounding.small y: Tokens.padding.large Loader { active: opacity > 0 anchors.centerIn: parent opacity: img.status === Image.Ready ? 0 : 1 Behavior on opacity { Anim {} } sourceComponent: CustomRect { color: Colors.palette.m3primaryContainer implicitHeight: loadingIndicator.implicitSize + Tokens.padding.large * 2 implicitWidth: loadingIndicator.implicitSize + Tokens.padding.large * 2 radius: Tokens.rounding.full LoadingIndicator { id: loadingIndicator anchors.centerIn: parent containsIcon: true implicitSize: Math.min(image.width, image.height) * 0.3 } } } Image { id: img anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter anchors.top: parent.top asynchronous: true fillMode: Image.PreserveAspectCrop height: root.tileHeight source: root.modelData ? root.modelData.thumbnailPath : "" smooth: root.isCurrent sourceSize.height: root.tileHeight sourceSize.width: root.tileHeight * (16 / 9) width: root.tileHeight * (16 / 9) opacity: status === Image.Ready ? 1 : 0 Behavior on opacity { Anim { type: Anim.SlowEffects } } Loader { opacity: root.modelData.isVideo && img.status === Image.Ready ? 1 : 0 active: opacity > 0 anchors.centerIn: parent Behavior on opacity { Anim { type: Anim.SlowEffects } } sourceComponent: CustomRect { implicitWidth: videoIcon.implicitWidth + Tokens.padding.extraLarge * 2 implicitHeight: implicitWidth radius: Tokens.rounding.full color: Colors.tPalette.m3surface MaterialIcon { id: videoIcon anchors.centerIn: parent text: "video_library" fontStyle: Tokens.font.icon.extraLarge } } } } StateLayer { onClicked: root.requestActivate() } } }