diff --git a/Components/ClipRect.qml b/Components/ClipRect.qml index 39ac012..48deed0 100644 --- a/Components/ClipRect.qml +++ b/Components/ClipRect.qml @@ -1,4 +1,5 @@ import QtQuick +import Quickshell import ZShell.Components Item { @@ -19,7 +20,7 @@ Item { } ShaderEffectSource { - id: source + id: src hideSource: true sourceItem: contentItem @@ -27,7 +28,7 @@ Item { RoundedMask { anchors.fill: parent - source: source + source: src topLeftRadius: root.topLeftRadius topRightRadius: root.topRightRadius bottomRightRadius: root.bottomRightRadius diff --git a/Modules/Bar/Bar.qml b/Modules/Bar/Bar.qml index 856b391..07ef70c 100644 --- a/Modules/Bar/Bar.qml +++ b/Modules/Bar/Bar.qml @@ -210,8 +210,7 @@ GridLayout { roleValue: "network" delegate: EntryWrapper { - NetworkWidget { - } + NetworkWidget {} } } diff --git a/Modules/Bar/Components/MediaWidget.qml b/Modules/Bar/Components/MediaWidget.qml index 7d2297f..4676109 100644 --- a/Modules/Bar/Components/MediaWidget.qml +++ b/Modules/Bar/Components/MediaWidget.qml @@ -13,7 +13,7 @@ WidgetBase { readonly property int textWidth: Math.min(metrics.width, 200) implicitHeight: horizontal ? baseSize : layout.implicitHeight + Tokens.padding.small * 2 - implicitWidth: horizontal ? layout.implicitWidth + Tokens.padding.small * 2 : baseSize + implicitWidth: horizontal ? (layout.implicitWidth % 2 === 0 ? layout.implicitWidth : layout.implicitWidth + 1) + Tokens.padding.small * 2 : baseSize radius: Tokens.rounding.full Behavior on implicitHeight { @@ -76,6 +76,8 @@ WidgetBase { anchors.fill: parent hoverEnabled: true + onClicked: console.log(root.mapToGlobal(0, 0), layout.implicitWidth) + onContainsMouseChanged: { if (!containsMouse) { mediatext.marqueeEnabled = false; diff --git a/Modules/Bar/Components/Resource.qml b/Modules/Bar/Components/Resource.qml index b22d9e7..20b0816 100644 --- a/Modules/Bar/Components/Resource.qml +++ b/Modules/Bar/Components/Resource.qml @@ -12,7 +12,6 @@ GridLayout { property real animatedPercentage: 0 readonly property real arcStartAngle: 0.75 * Math.PI readonly property real arcSweep: 1.5 * Math.PI - readonly property real dpr: (QsWindow.window as QsWindow)?.devicePixelRatio ?? 1 required property bool horizontal property string icon required property color iconColor @@ -23,17 +22,12 @@ GridLayout { property bool warning: percentage * 100 >= warningThreshold property int warningThreshold: 80 - function snap(v) { - return Math.round(v * dpr) / dpr; - } - columnSpacing: Tokens.spacing.medium columns: horizontal ? -1 : 1 percentage: 0 Behavior on animatedPercentage { - Anim { - } + Anim {} } Component.onCompleted: animatedPercentage = percentage @@ -59,7 +53,7 @@ GridLayout { Layout.preferredHeight: root.horizontal ? icon.implicitHeight - Tokens.padding.extraSmall : 4 Layout.preferredWidth: root.horizontal ? 4 : icon.implicitWidth color: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2) - radius: Math.min(width, height) / 2 + radius: Tokens.rounding.full Item { id: clipper @@ -69,18 +63,20 @@ GridLayout { anchors.left: root.horizontal ? undefined : parent.left anchors.verticalCenter: root.horizontal ? undefined : parent.verticalCenter clip: true - height: root.horizontal ? root.snap(root.percentage * track.height) : track.height * 2 - width: root.horizontal ? track.width * 2 : root.snap(root.percentage * track.width) + implicitHeight: root.horizontal ? root.percentage * track.height : track.height * 2 + implicitWidth: root.horizontal ? track.width * 2 : root.percentage * track.width CustomRect { anchors.bottom: root.horizontal ? parent.bottom : undefined anchors.horizontalCenter: root.horizontal ? parent.horizontalCenter : undefined anchors.left: root.horizontal ? undefined : parent.left anchors.verticalCenter: root.horizontal ? undefined : parent.verticalCenter + color: root.mainColor - height: track.height radius: track.radius - width: track.width + + implicitHeight: track.height + implicitWidth: track.width } } } diff --git a/Modules/Bar/Components/Resources.qml b/Modules/Bar/Components/Resources.qml index 32bd1f2..8de95ae 100644 --- a/Modules/Bar/Components/Resources.qml +++ b/Modules/Bar/Components/Resources.qml @@ -23,7 +23,8 @@ WidgetBase { StateLayer { color: root.screenState.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface - onClicked: root.screenState.resources = !root.screenState.resources + // onClicked: root.screenState.resources = !root.screenState.resources + onClicked: console.log(root.mapToGlobal(0, 0)) } GridLayout { @@ -33,6 +34,7 @@ WidgetBase { anchors.horizontalCenterOffset: root.horizontal ? 0 : 1 anchors.verticalCenterOffset: root.horizontal ? 0 : -3 columnSpacing: Tokens.spacing.small + rowSpacing: 0 columns: root.horizontal ? -1 : 1 ServiceRef { @@ -51,6 +53,7 @@ WidgetBase { Layout.alignment: Qt.AlignVCenter Layout.fillHeight: root.horizontal Layout.fillWidth: !root.horizontal + horizontal: root.horizontal icon: "memory" iconColor: root.screenState.resources ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface diff --git a/Modules/Bar/Components/Workspaces.qml b/Modules/Bar/Components/Workspaces.qml index 9c5d448..09cebc5 100644 --- a/Modules/Bar/Components/Workspaces.qml +++ b/Modules/Bar/Components/Workspaces.qml @@ -12,13 +12,14 @@ import qs.Services Item { id: root - property real activeWorkspaceMargin: Math.ceil(Tokens.padding.medium / 4) + property real activeWorkspaceMargin: Tokens.padding.extraSmall / 2 + readonly property int spacing: Tokens.spacing.extraSmall / 2 readonly property int effectiveActiveWorkspaceId: monitor?.activeWorkspace?.id ?? 1 required property bool horizontal readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen) required property ShellScreen screen readonly property real shortSize: Math.max(Config.bar.height, Tokens.sizes.bar.innerSize) - readonly property real size: (workspaceButtonWidth * workspacesShown) + activeWorkspaceMargin * 2 + readonly property real size: (workspaceButtonWidth * workspacesShown) + (spacing * Math.max(0, workspacesShown - 1)) + activeWorkspaceMargin * 2 property int workspaceButtonWidth: (horizontal ? bgRect.implicitHeight : bgRect.implicitWidth) - root.activeWorkspaceMargin * 2 property int workspaceIndexInGroup: (effectiveActiveWorkspaceId - 1) % root.workspacesShown readonly property list workspaces: Hyprland.workspaces.values.filter(w => w.monitor === root.monitor) @@ -59,15 +60,17 @@ Item { anchors.fill: parent anchors.margins: root.activeWorkspaceMargin - columnSpacing: 0 + columnSpacing: root.spacing columns: root.horizontal ? root.workspacesShown : 1 - rowSpacing: 0 + rowSpacing: root.spacing rows: root.horizontal ? 1 : root.workspacesShown + layer.enabled: true + layer.mipmap: true Repeater { model: root.workspaces - Button { + CustomRect { id: button required property int index @@ -75,27 +78,19 @@ Item { implicitHeight: indicator.indicatorThickness implicitWidth: indicator.indicatorThickness - width: root.workspaceButtonWidth + radius: Tokens.rounding.full - background: Item { - id: workspaceButtonBackground - - implicitHeight: root.workspaceButtonWidth - implicitWidth: root.workspaceButtonWidth - - CustomText { - anchors.centerIn: parent - color: Colors.palette.m3onSecondaryContainer - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - text: button.modelData?.name ?? "" - verticalAlignment: Text.AlignVCenter - } + CustomText { + anchors.centerIn: parent + color: Colors.palette.m3onSecondaryContainer + text: button.modelData?.name ?? "" } - onPressed: { - const ws = button.modelData.name; - Hyprland.dispatch(Hyprland.usingLua ? `hl.dsp.focus({ workspace= "${ws}"})` : `workspace ${ws}`); + StateLayer { + onPressed: { + const ws = button.modelData.name; + Hyprland.dispatch(Hyprland.usingLua ? `hl.dsp.focus({ workspace= "${ws}"})` : `workspace ${ws}`); + } } } } @@ -104,8 +99,10 @@ Item { CustomRect { id: indicator - property real indicatorLength: (Math.abs(idxPair.idx1 - idxPair.idx2) + 1) * root.workspaceButtonWidth - property real indicatorPosition: Math.min(idxPair.idx1, idxPair.idx2) * root.workspaceButtonWidth + root.activeWorkspaceMargin + readonly property real step: root.workspaceButtonWidth + root.spacing + + property real indicatorLength: (Math.abs(idxPair.idx1 - idxPair.idx2) + 1) * root.workspaceButtonWidth + Math.abs(idxPair.idx1 - idxPair.idx2) * root.spacing + property real indicatorPosition: Math.min(idxPair.idx1, idxPair.idx2) * step + root.activeWorkspaceMargin property real indicatorThickness: root.workspaceButtonWidth anchors.horizontalCenter: root.horizontal ? undefined : parent.horizontalCenter @@ -129,9 +126,10 @@ Item { implicitHeight: grid.height implicitWidth: grid.width source: grid + autoPaddingEnabled: false sourceColor: Colors.palette.m3onSurface - x: root.horizontal ? -indicator.x + 3 : 0 - y: root.horizontal ? 0 : -indicator.y + 3 + x: root.horizontal ? -indicator.x + root.activeWorkspaceMargin : 0 + y: root.horizontal ? 0 : -indicator.y + root.activeWorkspaceMargin } } } diff --git a/Modules/Clipboard/Content.qml b/Modules/Clipboard/Content.qml index 8fd5c62..e287e86 100644 --- a/Modules/Clipboard/Content.qml +++ b/Modules/Clipboard/Content.qml @@ -54,7 +54,7 @@ Item { } } - ClipRect { + CustomRect { id: preview anchors.bottom: parent.bottom @@ -64,6 +64,7 @@ Item { color: Colors.tPalette.m3surfaceContainer implicitWidth: ClipHistory.previewIsImage ? Math.max(Math.min(imagePreview.sourceSize.width + Tokens.padding.large * 2, Config.clipboard.sizes.previewWidth), Config.clipboard.sizes.minPreviewWidth) : Math.max(Math.min(textPreviewColumn.width + textPreviewColumn.anchors.margins * 2, Config.clipboard.sizes.previewWidth), Config.clipboard.sizes.minPreviewWidth) radius: 25 + clip: true Behavior on implicitWidth { Anim {} @@ -228,11 +229,12 @@ Item { anchors.fill: parent spacing: Tokens.spacing.small - ClipRect { + Item { id: textRect Layout.fillHeight: true Layout.fillWidth: true + clip: true Item { id: textWrapper diff --git a/Modules/Lock/Content.qml b/Modules/Lock/Content.qml index 1d8e734..cbe2028 100644 --- a/Modules/Lock/Content.qml +++ b/Modules/Lock/Content.qml @@ -5,14 +5,13 @@ import qs.Helpers import ZShell.Config import qs.Services -ClipRect { +Item { id: root required property var lock implicitHeight: layout.implicitHeight implicitWidth: layout.implicitWidth - radius: Tokens.rounding.largeIncreased RowLayout { id: layout diff --git a/Modules/Lock/Media.qml b/Modules/Lock/Media.qml index 0d08f40..645101f 100644 --- a/Modules/Lock/Media.qml +++ b/Modules/Lock/Media.qml @@ -7,39 +7,44 @@ import qs.Components import qs.Helpers import qs.Services -ClipRect { +Item { id: root required property var lock - color: Colors.tPalette.m3surfaceContainer implicitHeight: layout.implicitHeight + layout.anchors.margins * 2 - radius: Tokens.rounding.small - - FadeImage { - id: image + ClipRect { anchors.fill: parent - asynchronous: true - fillMode: Image.PreserveAspectCrop - layer.enabled: true - opacity: status === Image.Ready ? 1 : 0 - source: Players.getArtUrl(Players.active) - sourceSize: { - const dpr = (QsWindow.window as QsWindow)?.devicePixelRatio ?? 1; - return Qt.size(width * dpr, height * dpr); - } - Behavior on opacity { - Anim { - type: Anim.StandardExtraLarge - } - } + color: Colors.tPalette.m3surfaceContainer + radius: Tokens.rounding.small + bottomLeftRadius: Tokens.rounding.largeIncreased + + FadeImage { + id: image - CustomRect { anchors.fill: parent - color: Colors.palette.m3surface - opacity: 0.7 + asynchronous: true + fillMode: Image.PreserveAspectCrop + opacity: status === Image.Ready ? 1 : 0 + source: Players.getArtUrl(Players.active) + sourceSize: { + const dpr = (QsWindow.window as QsWindow)?.devicePixelRatio ?? 1; + return Qt.size(width * dpr, height * dpr); + } + + Behavior on opacity { + Anim { + type: Anim.StandardExtraLarge + } + } + + CustomRect { + anchors.fill: parent + color: Colors.palette.m3surface + opacity: 0.7 + } } } @@ -77,7 +82,7 @@ ClipRect { spacing: Tokens.spacing.extraSmall IconButton { - enabled: Players.active?.canGoPrevious + enabled: Players.active?.canGoPrevious ?? false icon: "skip_previous" isRound: true shapeMorph: true @@ -88,7 +93,7 @@ ClipRect { IconButton { checked: Players.active?.isPlaying ?? false - enabled: Players.active?.canTogglePlaying + enabled: Players.active?.canTogglePlaying ?? false icon: Players.active?.isPlaying ? "pause" : "play_arrow" implicitWidth: implicitHeight + Tokens.padding.largeIncreased * 2 isRound: true @@ -98,7 +103,7 @@ ClipRect { } IconButton { - enabled: Players.active?.canGoNext + enabled: Players.active?.canGoNext ?? false icon: "skip_next" isRound: true shapeMorph: true diff --git a/Modules/Lock/NotifDock.qml b/Modules/Lock/NotifDock.qml index af8ed98..893e04e 100644 --- a/Modules/Lock/NotifDock.qml +++ b/Modules/Lock/NotifDock.qml @@ -28,13 +28,11 @@ ColumnLayout { text: NotifServer.list.length > 0 ? qsTr("%1 notification%2").arg(NotifServer.list.length).arg(NotifServer.list.length === 1 ? "" : "s") : qsTr("Notifications") } - ClipRect { + Item { id: clipRect Layout.fillHeight: true Layout.fillWidth: true - color: "transparent" - radius: Tokens.rounding.small Loader { active: opacity > 0 @@ -49,19 +47,6 @@ ColumnLayout { sourceComponent: ColumnLayout { spacing: Tokens.spacing.largeIncreased - Image { - asynchronous: true - fillMode: Image.PreserveAspectFit - layer.enabled: true - source: Qt.resolvedUrl(`${Quickshell.shellDir}/assets/dino.png`) - sourceSize.width: clipRect.width * 0.8 - - layer.effect: Coloriser { - brightness: 1 - colorizationColor: Colors.palette.m3outlineVariant - } - } - CustomText { Layout.alignment: Qt.AlignHCenter color: Colors.palette.m3outlineVariant diff --git a/Modules/Lock/Weather/BriefInfo.qml b/Modules/Lock/Weather/BriefInfo.qml index cd92521..57ae1b3 100644 --- a/Modules/Lock/Weather/BriefInfo.qml +++ b/Modules/Lock/Weather/BriefInfo.qml @@ -16,7 +16,7 @@ ColumnLayout { Layout.alignment: Qt.AlignHCenter animate: true color: Colors.palette.m3onSurfaceVariant - font: Tokens.font.title.large + font: Tokens.font.body.large text: Weather.description } @@ -29,7 +29,7 @@ ColumnLayout { animate: true color: Colors.palette.m3primary - font: Tokens.font.body.large + font: Tokens.font.title.large text: Weather.temp } @@ -37,6 +37,7 @@ ColumnLayout { animate: true color: Colors.palette.m3secondary text: Weather.icon + fontStyle: Tokens.font.icon.large } } @@ -53,7 +54,7 @@ ColumnLayout { Layout.alignment: Qt.AlignHCenter animate: true color: Colors.palette.m3onSurfaceVariant - font: Tokens.font.body.normal + font: Tokens.font.body.medium text: { const today = Weather.forecast[0]; return qsTr("High %1 • Low %2").arg(Weather.formatTemp(today?.maxTempC)).arg(Weather.formatTemp(today?.minTempC)); diff --git a/Modules/Lock/Weather/Forecast.qml b/Modules/Lock/Weather/Forecast.qml index dd8cf82..263d90e 100644 --- a/Modules/Lock/Weather/Forecast.qml +++ b/Modules/Lock/Weather/Forecast.qml @@ -36,7 +36,7 @@ CustomRect { } } - VerticalFadeListView { + CustomListView { id: layout anchors.bottom: parent.bottom @@ -45,13 +45,20 @@ CustomRect { anchors.margins: Tokens.padding.large anchors.right: parent.right implicitHeight: contentItem.childrenRect.height - model: Weather.hourlyForecast + currentIndex: Weather.currentHourIndex + // highlightFollowsCurrentItem: true + // preferredHighlightEnd: currentItem.implicitWidth + // preferredHighlightBegin: 0 + // highlightRangeMode: ListView.ApplyRange + clip: true + model: Weather.hourlyForecast.slice(Weather.currentHourIndex - 1) orientation: VerticalFadeListView.Horizontal spacing: Tokens.spacing.medium delegate: ColumnLayout { id: hour + readonly property bool current: ListView.view.currentItem === this readonly property var cond: modelData required property int index required property var modelData @@ -60,7 +67,7 @@ CustomRect { MaterialShape { Layout.alignment: Qt.AlignHCenter - color: Qt.alpha(Colors.palette.m3primary, hour.index === Weather.currentHourIndex ? 1 : 0) + color: Qt.alpha(Colors.palette.m3primary, hour.current ? 1 : 0) implicitSize: temp.implicitHeight + Tokens.padding.small * 2 shape: MaterialShape.Cookie4Sided @@ -72,7 +79,7 @@ CustomRect { id: temp anchors.centerIn: parent - color: hour.index === Weather.currentHourIndex ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface + color: hour.current ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface font: Tokens.font.body.medium text: Weather.formatTemp(hour.cond.tempC).slice(0, -1) // Remove C/F } @@ -96,7 +103,7 @@ CustomRect { Layout.topMargin: Tokens.spacing.extraSmall color: Colors.palette.m3onSurfaceVariant font: Tokens.font.body.small - text: hour.index === 0 ? qsTr("Now") : Qt.formatDateTime(new Date(hour.cond.timestamp.replace("T", " ")), Config.services.useTwelveHourClock ? "ha" : "hh:00") + text: hour.current ? qsTr("Now") : Qt.formatDateTime(new Date(hour.cond.timestamp.replace("T", " ")), Config.services.useTwelveHourClock ? "ha" : "hh:00") } } } diff --git a/Modules/Sidebar/Chat/Content/ApprovalPrompt.qml b/Modules/Sidebar/Chat/Content/ApprovalPrompt.qml index ae9549b..13ecf6c 100644 --- a/Modules/Sidebar/Chat/Content/ApprovalPrompt.qml +++ b/Modules/Sidebar/Chat/Content/ApprovalPrompt.qml @@ -337,7 +337,7 @@ Item { } } - ClipRect { + Item { id: expandedTool anchors.top: collapsedRow.bottom @@ -348,8 +348,16 @@ Item { anchors.topMargin: Tokens.spacing.medium implicitHeight: fullToolCall.implicitHeight + fullToolCall.anchors.margins * 2 - radius: Tokens.rounding.medium - color: Colors.palette.m3surfaceContainerLow + clip: true + + CustomRect { + id: bg + + anchors.fill: parent + + radius: Tokens.rounding.medium + color: Colors.palette.m3surfaceContainerLow + } CustomText { id: fullToolCall diff --git a/Modules/Sidebar/Chat/Content/ProcessBlock.qml b/Modules/Sidebar/Chat/Content/ProcessBlock.qml index 6458e0c..e349081 100644 --- a/Modules/Sidebar/Chat/Content/ProcessBlock.qml +++ b/Modules/Sidebar/Chat/Content/ProcessBlock.qml @@ -125,7 +125,7 @@ Item { current: root.current } - ClipRect { + Item { id: expandedRect anchors.left: parent.left @@ -133,11 +133,19 @@ Item { anchors.top: layout.bottom anchors.bottom: parent.bottom anchors.topMargin: Tokens.spacing.small - color: Colors.palette.m3surfaceContainerLow implicitHeight: expandedContent.contentHeight + expandedContent.anchors.margins * 2 opacity: root.expanded ? 1 : 0 - radius: Tokens.rounding.medium visible: opacity > 0 + clip: true + + CustomRect { + id: bg + + anchors.fill: parent + + radius: Tokens.rounding.medium + color: Colors.palette.m3surfaceContainerLow + } Behavior on opacity { Anim {}