2 Commits
Author SHA1 Message Date
AramJonghu 5a01c4b472 chore: added missing dependency to pyproject
C++ / fmt (pull_request) Successful in 3s
JS/TS / fmt (pull_request) Successful in 8s
JS/TS / lint (pull_request) Successful in 22s
Python / verify (pull_request) Failing after 19s
Python / static (pull_request) Failing after 22s
C++ / build (pull_request) Canceled after 9m5s
C++ / clang-tidy (pull_request) Canceled after 9m3s
Rust / build (pull_request) Canceled after 8m57s
Rust / fmt (pull_request) Canceled after 8m41s
Rust / clippy (pull_request) Canceled after 8m39s
2026-08-15 22:01:22 +02:00
AramJonghu 9271fa47bc ci(python): rework of jobs + fix import issue 2026-08-15 22:01:22 +02:00
230 changed files with 2999 additions and 5449 deletions
+2 -2
View File
@@ -9,7 +9,7 @@ on:
jobs: jobs:
static: static:
runs-on: debian runs-on: debian
container: node:26-trixie-slim container: python:3.13-slim
steps: steps:
- name: Checkout - name: Checkout
@@ -36,7 +36,7 @@ jobs:
verify: verify:
if: always() if: always()
runs-on: debian runs-on: debian
container: node:26-trixie-slim container: python:3.13-slim
steps: steps:
- name: Checkout - name: Checkout
+9 -9
View File
@@ -27,25 +27,25 @@ AnchorAnimation {
if (type == AnchorAnim.DefaultSpatial) if (type == AnchorAnim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial; return Tokens.anim.durations.expressiveDefaultSpatial;
if (type == AnchorAnim.SlowSpatial) if (type == AnchorAnim.SlowSpatial)
return Tokens.anim.durations.expressiveSlowSpatial; return Tokens.anim.durations.large;
const types = ["small", "normal", "large", "extraLarge"]; const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; // 0-7 are the 4 standard types const idx = type % 4;
return Tokens.anim.durations[types[idx]]; return Tokens.anim.durations[types[idx]];
} }
easing: { easing.bezierCurve: {
if (type == AnchorAnim.FastSpatial) if (type == AnchorAnim.FastSpatial)
return Tokens.anim.expressiveFastSpatial; return Tokens.anim.curves.expressiveFastSpatial;
if (type == AnchorAnim.DefaultSpatial) if (type == AnchorAnim.DefaultSpatial)
return Tokens.anim.expressiveDefaultSpatial; return Tokens.anim.curves.expressiveDefaultSpatial;
if (type == AnchorAnim.SlowSpatial) if (type == AnchorAnim.SlowSpatial)
return Tokens.anim.expressiveSlowSpatial; return Tokens.anim.curves.expressiveSlowSpatial;
if (type >= AnchorAnim.StandardSmall && type <= AnchorAnim.StandardExtraLarge) if (type >= AnchorAnim.StandardSmall && type <= AnchorAnim.StandardExtraLarge)
return Tokens.anim.standard; return Tokens.anim.curves.standard;
if (type >= AnchorAnim.EmphasizedSmall && type <= AnchorAnim.EmphasizedExtraLarge) if (type >= AnchorAnim.EmphasizedSmall && type <= AnchorAnim.EmphasizedExtraLarge)
return Tokens.anim.emphasized; return Tokens.anim.curves.emphasized;
return Tokens.anim.expressiveDefaultSpatial; return Tokens.anim.curves.expressiveDefaultSpatial;
} }
} }
+12 -12
View File
@@ -30,34 +30,34 @@ NumberAnimation {
if (type === Anim.DefaultSpatial) if (type === Anim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial; return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial) if (type === Anim.SlowSpatial)
return Tokens.anim.durations.expressiveSlowSpatial; return Tokens.anim.durations.large;
if (type === Anim.FastEffects) if (type === Anim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects; return Tokens.anim.durations.expressiveFastEffects;
if (type === Anim.DefaultEffects) if (type === Anim.DefaultEffects)
return Tokens.anim.durations.expressiveDefaultEffects; return Tokens.anim.durations.expressiveEffects;
if (type === Anim.SlowEffects) if (type === Anim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects; return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"]; const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4; // 0-7 are the 4 standard types const idx = type % 4;
return Tokens.anim.durations[types[idx]]; return Tokens.anim.durations[types[idx]];
} }
easing: { easing.bezierCurve: {
if (type === Anim.FastSpatial) if (type === Anim.FastSpatial)
return Tokens.anim.expressiveFastSpatial; return Tokens.anim.curves.expressiveFastSpatial;
if (type === Anim.DefaultSpatial) if (type === Anim.DefaultSpatial)
return Tokens.anim.expressiveDefaultSpatial; return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial) if (type === Anim.SlowSpatial)
return Tokens.anim.expressiveSlowSpatial; return Tokens.anim.curves.expressiveSlowSpatial;
if (type === Anim.FastEffects) if (type === Anim.FastEffects)
return Tokens.anim.expressiveFastEffects; return Tokens.anim.curves.expressiveFastEffects;
if (type === Anim.DefaultEffects) if (type === Anim.DefaultEffects)
return Tokens.anim.expressiveDefaultEffects; return Tokens.anim.curves.expressiveDefaultEffects;
if (type === Anim.SlowEffects) if (type === Anim.SlowEffects)
return Tokens.anim.expressiveSlowEffects; return Tokens.anim.curves.expressiveSlowEffects;
if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge) if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.emphasized; return Tokens.anim.curves.emphasized;
return Tokens.anim.standard; return Tokens.anim.curves.standard;
} }
} }
+2 -2
View File
@@ -107,7 +107,7 @@ Slider {
Anim { Anim {
duration: Tokens.anim.durations.normal / 2 duration: Tokens.anim.durations.normal / 2
easing: Tokens.anim.standardAccel easing.bezierCurve: Tokens.anim.curves.standardAccel
property: "scale" property: "scale"
target: icon target: icon
to: 0 to: 0
@@ -119,7 +119,7 @@ Slider {
Anim { Anim {
duration: Tokens.anim.durations.normal / 2 duration: Tokens.anim.durations.normal / 2
easing: Tokens.anim.standardDecel easing.bezierCurve: Tokens.anim.curves.standardDecel
property: "scale" property: "scale"
target: icon target: icon
to: 1 to: 1
+1 -2
View File
@@ -1,6 +1,5 @@
import QtQuick import QtQuick
import ZShell.Config import ZShell.Config
import qs.Components
import qs.Services import qs.Services
CustomRect { CustomRect {
@@ -37,7 +36,7 @@ CustomRect {
readonly property color onColor: !enabled ? disabledOnColor : internalChecked ? activeOnColor : inactiveOnColor readonly property color onColor: !enabled ? disabledOnColor : internalChecked ? activeOnColor : inactiveOnColor
property real padding property real padding
readonly property alias pressed: stateLayer.pressed readonly property alias pressed: stateLayer.pressed
property real pressedRadius: Tokens.rounding.small property real pressedRadius: Tokens.rounding.smallest
readonly property alias radiusAnim: radiusAnim readonly property alias radiusAnim: radiusAnim
property bool radiusMorph: true property bool radiusMorph: true
property alias shapeMorph: stateLayer.shapeMorph property alias shapeMorph: stateLayer.shapeMorph
+58 -2
View File
@@ -2,6 +2,62 @@ import QtQuick
import ZShell.Config import ZShell.Config
ColorAnimation { ColorAnimation {
duration: Tokens.anim.durations.expressiveSlowEffects enum Type {
easing: Tokens.anim.expressiveSlowEffects StandardSmall = 0,
Standard,
StandardLarge,
StandardExtraLarge,
EmphasizedSmall,
Emphasized,
EmphasizedLarge,
EmphasizedExtraLarge,
FastSpatial,
DefaultSpatial,
SlowSpatial,
FastEffects,
DefaultEffects,
SlowEffects
}
property int type: CAnim.DefaultSpatial
duration: {
if (type < CAnim.StandardSmall || type > Anim.SlowEffects)
return Tokens.anim.durations.normal;
if (type === CAnim.FastSpatial)
return Tokens.anim.durations.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.durations.large;
if (type === CAnim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.durations.expressiveEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4;
return Tokens.anim.durations[types[idx]];
}
easing.bezierCurve: {
if (type === CAnim.FastSpatial)
return Tokens.anim.curves.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.curves.expressiveSlowSpatial;
if (type === CAnim.FastEffects)
return Tokens.anim.curves.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.curves.expressiveDefaultEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.curves.expressiveSlowEffects;
if (type >= CAnim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.curves.emphasized;
return Tokens.anim.curves.standard;
}
} }
+1 -1
View File
@@ -23,7 +23,7 @@ BusyIndicator {
property real implicitSize: Tokens.font.size.normal * 3 property real implicitSize: Tokens.font.size.normal * 3
property real internalStrokeWidth: strokeWidth property real internalStrokeWidth: strokeWidth
readonly property alias progress: manager.progress readonly property alias progress: manager.progress
property real strokeWidth: Tokens.padding.extraSmall * 0.8 property real strokeWidth: Tokens.padding.small * 0.8
property alias type: manager.indeterminateAnimationType property alias type: manager.indeterminateAnimationType
implicitHeight: implicitSize implicitHeight: implicitSize
+1 -1
View File
@@ -21,7 +21,7 @@ Item {
readonly property real size: Math.min(width, height) readonly property real size: Math.min(width, height)
property int spacing: Tokens.spacing.small property int spacing: Tokens.spacing.small
property int startAngle: -90 property int startAngle: -90
property int strokeWidth: Tokens.padding.extraSmall property int strokeWidth: Tokens.padding.small
property int sweepAngle: 360 property int sweepAngle: 360
readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2 readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2
property real value property real value
+1 -1
View File
@@ -23,7 +23,7 @@ CheckBox {
color: Colors.palette.m3surfaceVariant color: Colors.palette.m3surfaceVariant
implicitHeight: control.checkHeight implicitHeight: control.checkHeight
implicitWidth: control.checkWidth implicitWidth: control.checkWidth
radius: Tokens.rounding.small / 2 radius: Tokens.rounding.smallest / 2
CustomRect { CustomRect {
color: Colors.palette.m3primary color: Colors.palette.m3primary
+1 -4
View File
@@ -13,13 +13,11 @@ Slider {
property bool animateWave property bool animateWave
property color bgColor: enabled ? Colors.palette.m3secondaryContainer : Qt.alpha(Colors.palette.m3onSurface, 0.1) property color bgColor: enabled ? Colors.palette.m3secondaryContainer : Qt.alpha(Colors.palette.m3onSurface, 0.1)
readonly property bool dragging: mouse.pressed
property color fgColor: enabled ? Colors.palette.m3primary : Qt.alpha(Colors.palette.m3onSurface, 0.38) property color fgColor: enabled ? Colors.palette.m3primary : Qt.alpha(Colors.palette.m3onSurface, 0.38)
property real filledWidth property real filledWidth
property alias inset: inset property alias inset: inset
property color insetColor: enabled ? (inset.attached ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onPrimary) : Colors.palette.m3onSurface property color insetColor: enabled ? (inset.attached ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onPrimary) : Colors.palette.m3onSurface
property string insetIcon: "" property string insetIcon: ""
property bool interactionOnMove: true
property real pos: visualPosition property real pos: visualPosition
property int radius: Tokens.rounding.small property int radius: Tokens.rounding.small
property int waveDuration: 1000 property int waveDuration: 1000
@@ -188,8 +186,7 @@ Slider {
onPositionChanged: e => { onPositionChanged: e => {
dragMovement = (e.x - pressStartX) / width; dragMovement = (e.x - pressStartX) / width;
if (root.interactionOnMove) root.interaction(posBinding.value);
root.interaction(posBinding.value);
} }
onPressed: e => { onPressed: e => {
widthBehavior.enabled = false; widthBehavior.enabled = false;
+2 -2
View File
@@ -38,9 +38,9 @@ DoubleSpinBox {
horizontalAlignment: TextField.AlignHCenter horizontalAlignment: TextField.AlignHCenter
implicitWidth: 65 implicitWidth: 65
inputMethodHints: Qt.ImhFormattedNumbersOnly inputMethodHints: Qt.ImhFormattedNumbersOnly
leftPadding: Tokens.padding.small leftPadding: Tokens.padding.larger
readOnly: !root.editable readOnly: !root.editable
rightPadding: Tokens.padding.small rightPadding: Tokens.padding.larger
text: root.textFromValue(root.value, root.locale) text: root.textFromValue(root.value, root.locale)
validator: root.validator validator: root.validator
@@ -12,14 +12,14 @@ Row {
} }
property alias active: menu.active property alias active: menu.active
property color color: type == SplitButton.Filled ? Colors.palette.m3primary : Colors.palette.m3secondaryContainer property color color: type == CustomSplitButton.Filled ? Colors.palette.m3primary : Colors.palette.m3secondaryContainer
property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1) property color disabledColor: Qt.alpha(Colors.palette.m3onSurface, 0.1)
property color disabledTextColor: Qt.alpha(Colors.palette.m3onSurface, 0.38) property color disabledTextColor: Qt.alpha(Colors.palette.m3onSurface, 0.38)
readonly property alias expandBtn: expandBtn readonly property alias expandBtn: expandBtn
property alias expanded: menu.expanded property alias expanded: menu.expanded
property string fallbackIcon property string fallbackIcon
property string fallbackText property string fallbackText
property real horizontalPadding: Tokens.padding.medium property real horizontalPadding: Tokens.padding.larger
readonly property alias iconLabel: iconLabel readonly property alias iconLabel: iconLabel
readonly property alias label: label readonly property alias label: label
readonly property alias menu: menu readonly property alias menu: menu
@@ -27,20 +27,20 @@ Row {
property bool menuOnTop property bool menuOnTop
property real minLeftWidth property real minLeftWidth
readonly property alias stateLayer: stateLayer readonly property alias stateLayer: stateLayer
property color textColor: type == SplitButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondaryContainer property color textColor: type == CustomSplitButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondaryContainer
readonly property alias textRow: textRow readonly property alias textRow: textRow
property int type: SplitButton.Filled property int type: CustomSplitButton.Filled
property real verticalPadding: Tokens.padding.small property real verticalPadding: Tokens.padding.small
spacing: Math.floor(Tokens.spacing.extraSmall / 2) spacing: Math.floor(Tokens.spacing.extraSmall)
CustomRect { CustomRect {
bottomRightRadius: Tokens.rounding.medium / 2 bottomRightRadius: Tokens.rounding.small / 2
color: !root.enabled ? root.disabledColor : root.color color: !root.enabled ? root.disabledColor : root.color
implicitHeight: expandBtn.implicitHeight implicitHeight: expandBtn.implicitHeight
implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2) implicitWidth: Math.max(root.minLeftWidth, textRow.implicitWidth + root.horizontalPadding * 2)
radius: implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) radius: implicitHeight / 2 * Math.min(1, Tokens.rounding.scale)
topRightRadius: Tokens.rounding.medium / 2 topRightRadius: Tokens.rounding.small / 2
StateLayer { StateLayer {
id: stateLayer id: stateLayer
@@ -92,7 +92,7 @@ Row {
CustomRect { CustomRect {
id: expandBtn id: expandBtn
property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) : Tokens.rounding.medium / 2 property real rad: root.expanded ? implicitHeight / 2 * Math.min(1, Tokens.rounding.scale) : Tokens.rounding.small / 2
bottomLeftRadius: rad bottomLeftRadius: rad
color: !root.enabled ? root.disabledColor : root.color color: !root.enabled ? root.disabledColor : root.color
+70
View File
@@ -0,0 +1,70 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Services
Item {
id: root
property alias active: splitButton.active
property alias buttonAlias: splitButton
property alias expanded: splitButton.expanded
property int expandedZ: 100
required property string label
property alias menuItems: splitButton.menuItems
property bool shouldBeActive: true
property alias type: splitButton.type
signal selected(item: MenuItem)
anchors.left: parent.left
anchors.right: parent.right
clip: false
implicitHeight: row.implicitHeight + Tokens.padding.smaller * 2
opacity: shouldBeActive ? 1 : 0
scale: shouldBeActive ? 1 : 0.8
z: splitButton.menu.implicitHeight > 0 ? expandedZ : 1
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
RowLayout {
id: row
anchors.left: parent.left
anchors.margins: Tokens.padding.small
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Tokens.spacing.normal
CustomText {
Layout.fillWidth: true
color: root.enabled ? Colors.palette.m3onSurface : Colors.palette.m3onSurfaceVariant
font.pointSize: Tokens.font.size.larger
text: root.label
}
CustomSplitButton {
id: splitButton
enabled: root.enabled
type: CustomSplitButton.Filled
z: 2
menu.onItemSelected: item => {
root.selected(item);
}
stateLayer.onClicked: {
splitButton.expanded = !splitButton.expanded;
}
}
}
}
+8 -20
View File
@@ -13,12 +13,8 @@ Switch {
implicitWidth: implicitIndicatorWidth implicitWidth: implicitIndicatorWidth
indicator: CustomRect { indicator: CustomRect {
color: { color: root.checked && root.enabled ? Colors.palette.m3primary : Colors.layer(Colors.palette.m3surfaceContainerHighest, root.cLayer)
if (!root.enabled) implicitHeight: Tokens.font.size.medium + Tokens.padding.normal * 2
return root.checked ? Qt.alpha(Colors.palette.m3onSurface, 0.12) : Qt.alpha(Colors.palette.m3surfaceContainerHighest, 0.38);
return root.checked ? Colors.palette.m3primary : Colors.layer(Colors.palette.m3surfaceContainerHighest, root.cLayer);
}
implicitHeight: 14 + Tokens.padding.small * 2
implicitWidth: implicitHeight * 1.7 implicitWidth: implicitHeight * 1.7
radius: Tokens.rounding.full radius: Tokens.rounding.full
@@ -26,11 +22,7 @@ Switch {
readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.2 : implicitHeight readonly property real nonAnimWidth: root.pressed ? implicitHeight * 1.2 : implicitHeight
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: { color: root.checked && root.enabled ? Colors.palette.m3onPrimary : Colors.layer(Colors.palette.m3outline, root.cLayer + 1)
if (!root.enabled)
return root.checked ? Qt.alpha(Colors.palette.m3surface, 0.7) : Qt.alpha(Colors.palette.m3onSurface, 0.12);
return root.checked ? Colors.palette.m3onPrimary : Colors.layer(Colors.palette.m3outline, root.cLayer + 1);
}
implicitHeight: parent.implicitHeight - Tokens.padding.extraSmall implicitHeight: parent.implicitHeight - Tokens.padding.extraSmall
implicitWidth: nonAnimWidth implicitWidth: nonAnimWidth
radius: Tokens.rounding.full radius: Tokens.rounding.full
@@ -100,7 +92,7 @@ Switch {
anchors.centerIn: parent anchors.centerIn: parent
asynchronous: true asynchronous: true
height: parent.implicitHeight - Tokens.padding.medium height: parent.implicitHeight - Tokens.padding.larger
preferredRendererType: Shape.CurveRenderer preferredRendererType: Shape.CurveRenderer
width: height width: height
@@ -122,16 +114,12 @@ Switch {
} }
ShapePath { ShapePath {
capStyle: Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap capStyle: ShapePath.RoundCap
fillColor: "transparent" fillColor: "transparent"
startX: icon.start1.x startX: icon.start1.x
startY: icon.start1.y startY: icon.start1.y
strokeColor: { strokeColor: root.checked && root.enabled ? Colors.palette.m3primary : Colors.palette.m3surfaceContainerHighest
if (!root.enabled) strokeWidth: Tokens.font.size.larger * 0.15
return root.checked ? Colors.palette.m3outline : Colors.palette.m3surfaceContainer;
return root.checked ? Colors.palette.m3primary : Colors.palette.m3surfaceContainerHighest;
}
strokeWidth: 16 * 0.15
Behavior on strokeColor { Behavior on strokeColor {
CAnim { CAnim {
@@ -165,6 +153,6 @@ Switch {
component PropAnim: PropertyAnimation { component PropAnim: PropertyAnimation {
duration: Tokens.anim.durations.expressiveFastSpatial duration: Tokens.anim.durations.expressiveFastSpatial
easing: Tokens.anim.expressiveFastSpatial easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
} }
} }
+4 -4
View File
@@ -129,8 +129,8 @@ TextFieldBase {
} }
AnchorAnim { AnchorAnim {
duration: Tokens.anim.durations.expressiveDefaultEffects duration: Tokens.anim.durations.expressiveEffects
easing: Tokens.anim.expressiveDefaultEffects easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
} }
@@ -140,7 +140,7 @@ TextFieldBase {
active: root.leadingIcon active: root.leadingIcon
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
sourceComponent: MaterialIcon { sourceComponent: MaterialIcon {
@@ -154,7 +154,7 @@ TextFieldBase {
active: root.trailingIcon active: root.trailingIcon
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Tokens.padding.small anchors.rightMargin: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
sourceComponent: MaterialIcon { sourceComponent: MaterialIcon {
+1 -1
View File
@@ -27,7 +27,7 @@ ButtonBase {
return Colors.palette.m3onPrimary; return Colors.palette.m3onPrimary;
return type === IconButton.Tonal ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onSurfaceVariant; return type === IconButton.Tonal ? Colors.palette.m3onSecondaryContainer : Colors.palette.m3onSurfaceVariant;
} }
padding: type === IconButton.Text ? Tokens.padding.extraSmall / 2 : Tokens.padding.extraSmall padding: type === IconButton.Text ? Tokens.padding.extraSmall / 2 : Tokens.padding.small
MaterialIcon { MaterialIcon {
id: label id: label
+2 -2
View File
@@ -17,7 +17,7 @@ ButtonBase {
return Colors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondary; return type === TextButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondary;
} }
horizontalPadding: Tokens.padding.small horizontalPadding: Tokens.padding.larger
implicitHeight: row.implicitHeight + verticalPadding * 2 implicitHeight: row.implicitHeight + verticalPadding * 2
implicitWidth: row.implicitWidth + horizontalPadding * 2 implicitWidth: row.implicitWidth + horizontalPadding * 2
inactiveColor: { inactiveColor: {
@@ -32,7 +32,7 @@ ButtonBase {
return Colors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? Colors.palette.m3onSurface : Colors.palette.m3onSecondaryContainer; return type === TextButton.Filled ? Colors.palette.m3onSurface : Colors.palette.m3onSecondaryContainer;
} }
verticalPadding: Tokens.padding.extraSmall verticalPadding: Tokens.padding.small
RowLayout { RowLayout {
id: row id: row
+130 -148
View File
@@ -18,14 +18,13 @@ Item {
property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle
property int leftFadeWidth: 28 property int leftFadeWidth: 28
property bool marqueeEnabled: true property bool marqueeEnabled: true
readonly property bool overflowing: metrics.width > content.width readonly property bool overflowing: metrics.width > root.width
property int pauseMs: 1200 property int pauseMs: 1200
property real pixelsPerSecond: 40 property real pixelsPerSecond: 40
property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle
property int rightFadeWidth: 28 property int rightFadeWidth: 28
property bool sliding: false property bool sliding: false
property alias text: elideText.text property alias text: elideText.text
property bool vertical: false
function durationForDistance(px): int { function durationForDistance(px): int {
return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000)); return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000));
@@ -42,9 +41,8 @@ Item {
} }
} }
clip: false clip: true
implicitHeight: vertical ? elideText.implicitWidth : elideText.implicitHeight implicitHeight: elideText.implicitHeight
implicitWidth: vertical ? elideText.implicitHeight : elideText.implicitWidth
Behavior on leftFadeStrength { Behavior on leftFadeStrength {
Anim { Anim {
@@ -55,187 +53,171 @@ Item {
} }
} }
onHeightChanged: resetMarquee()
onTextChanged: resetMarquee() onTextChanged: resetMarquee()
onVerticalChanged: resetMarquee()
onVisibleChanged: if (!visible) onVisibleChanged: if (!visible)
resetMarquee() resetMarquee()
onWidthChanged: resetMarquee() onWidthChanged: resetMarquee()
TextMetrics {
id: metrics
font: elideText.font
text: elideText.text
}
CustomText {
id: elideText
anchors.verticalCenter: parent.verticalCenter
animate: root.animate
animateProp: "scale,opacity"
color: root.color
elide: Text.ElideNone
visible: !root.overflowing
width: root.width
}
Item { Item {
id: content id: marqueeViewport
anchors.centerIn: parent anchors.fill: parent
height: root.vertical ? root.width : root.height clip: true
width: root.vertical ? root.height : root.width layer.enabled: true
visible: root.overflowing
transform: Rotation { layer.effect: OpacityMask {
angle: root.vertical ? -90 : 0 maskSource: rightFadeMask
origin.x: content.width / 2
origin.y: content.height / 2
}
TextMetrics {
id: metrics
font: elideText.font
text: elideText.text
}
CustomText {
id: elideText
anchors.verticalCenter: parent.verticalCenter
animate: root.animate
animateProp: "scale,opacity"
color: root.color
elide: Text.ElideNone
visible: !root.overflowing
width: content.width
} }
Item { Item {
id: marqueeViewport id: strip
anchors.fill: parent anchors.verticalCenter: parent.verticalCenter
clip: false height: t1.implicitHeight
layer.enabled: true width: t1.width + root.gap + t2.width
visible: root.overflowing x: 0
layer.effect: OpacityMask { CustomText {
maskSource: rightFadeMask id: t1
animate: root.animate
animateProp: "opacity"
color: root.color
font.pointSize: elideText.font.pointSize
text: elideText.text
} }
Item { CustomText {
id: strip id: t2
anchors.verticalCenter: parent.verticalCenter animate: root.animate
height: t1.implicitHeight animateProp: "opacity"
width: t1.width + root.gap + t2.width color: root.color
x: 0 font.pointSize: elideText.font.pointSize
text: t1.text
x: t1.width + root.gap
}
}
CustomText { SequentialAnimation {
id: t1 id: marqueeAnim
animate: root.animate running: false
animateProp: "opacity"
color: root.color
font.pointSize: elideText.font.pointSize
text: elideText.text
}
CustomText { onFinished: pauseTimer.restart()
id: t2
animate: root.animate ScriptAction {
animateProp: "opacity" script: {
color: root.color root.sliding = true;
font.pointSize: elideText.font.pointSize root.leftFadeEnabled = true;
text: t1.text
x: t1.width + root.gap
} }
} }
SequentialAnimation { Anim {
id: marqueeAnim duration: root.durationForDistance(t1.width)
easing.bezierCurve: Easing.Linear
easing.type: Easing.Linear
from: 0
property: "x"
target: strip
to: -t1.width
}
running: false ScriptAction {
script: {
onFinished: pauseTimer.restart() root.leftFadeEnabled = false;
ScriptAction {
script: {
root.sliding = true;
root.leftFadeEnabled = true;
}
}
Anim {
duration: root.durationForDistance(t1.width)
easing.bezierCurve: Easing.Linear
easing.type: Easing.Linear
from: 0
property: "x"
target: strip
to: -t1.width
}
ScriptAction {
script: {
root.leftFadeEnabled = false;
}
}
Anim {
duration: root.durationForDistance(root.gap)
easing.bezierCurve: Easing.Linear
easing.type: Easing.Linear
from: -t1.width
property: "x"
target: strip
to: -(t1.width + root.gap)
}
ScriptAction {
script: {
root.sliding = false;
strip.x = 0;
}
} }
} }
Timer { Anim {
id: pauseTimer duration: root.durationForDistance(root.gap)
easing.bezierCurve: Easing.Linear
easing.type: Easing.Linear
from: -t1.width
property: "x"
target: strip
to: -(t1.width + root.gap)
}
interval: root.pauseMs ScriptAction {
repeat: false script: {
running: true root.sliding = false;
strip.x = 0;
onTriggered: {
if (root.marqueeEnabled)
marqueeAnim.start();
} }
} }
} }
Rectangle { Timer {
id: rightFadeMask id: pauseTimer
readonly property real fadeStartPos: { interval: root.pauseMs
const w = Math.max(1, width); repeat: false
return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w)); running: true
onTriggered: {
if (root.marqueeEnabled)
marqueeAnim.start();
} }
readonly property real leftFadeEndPos: { }
const w = Math.max(1, width); }
return Math.max(0, Math.min(1, root.leftFadeWidth / w));
Rectangle {
id: rightFadeMask
readonly property real fadeStartPos: {
const w = Math.max(1, width);
return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w));
}
readonly property real leftFadeEndPos: {
const w = Math.max(1, width);
return Math.max(0, Math.min(1, root.leftFadeWidth / w));
}
anchors.fill: marqueeViewport
layer.enabled: true
visible: false
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop {
color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength)
position: 0.0
} }
anchors.fill: marqueeViewport GradientStop {
layer.enabled: true color: Qt.rgba(1, 1, 1, 1.0)
visible: false position: rightFadeMask.leftFadeEndPos
}
gradient: Gradient { GradientStop {
orientation: Gradient.Horizontal color: Qt.rgba(1, 1, 1, 1.0)
position: rightFadeMask.fadeStartPos
}
GradientStop { GradientStop {
color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength) color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength)
position: 0.0 position: 1.0
}
GradientStop {
color: Qt.rgba(1, 1, 1, 1.0)
position: rightFadeMask.leftFadeEndPos
}
GradientStop {
color: Qt.rgba(1, 1, 1, 1.0)
position: rightFadeMask.fadeStartPos
}
GradientStop {
color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength)
position: 1.0
}
} }
} }
} }
+9 -9
View File
@@ -78,7 +78,7 @@ MouseArea {
implicitHeight: column.implicitHeight + column.anchors.margins * 2 implicitHeight: column.implicitHeight + column.anchors.margins * 2
implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2) implicitWidth: Math.max(200, column.implicitWidth + column.anchors.margins * 2)
level: 2 level: 2
radius: Tokens.rounding.large radius: Tokens.rounding.medium
x: { x: {
watcher.transform; watcher.transform;
const item = root.attachTo; const item = root.attachTo;
@@ -126,15 +126,15 @@ MouseArea {
CustomRect { CustomRect {
id: item id: item
readonly property bool active: modelData === root?.active readonly property bool active: modelData === root.active
required property int index required property int index
required property MenuItem modelData required property MenuItem modelData
Layout.fillWidth: true Layout.fillWidth: true
color: Qt.alpha(Colors.palette.m3tertiaryContainer, active ? 1 : 0) color: Qt.alpha(Colors.palette.m3tertiaryContainer, active ? 1 : 0)
implicitHeight: menuOptionRow.implicitHeight + Tokens.padding.medium * 2 implicitHeight: menuOptionRow.implicitHeight + Tokens.padding.larger * 2
implicitWidth: menuOptionRow.implicitWidth + Tokens.padding.medium * 2 implicitWidth: menuOptionRow.implicitWidth + Tokens.padding.larger * 2
radius: menu.radius - column.anchors.margins radius: Tokens.rounding.small
Behavior on radius { Behavior on radius {
Anim { Anim {
@@ -157,25 +157,25 @@ MouseArea {
id: menuOptionRow id: menuOptionRow
anchors.fill: parent anchors.fill: parent
anchors.margins: Tokens.padding.medium anchors.margins: Tokens.padding.larger
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurfaceVariant color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurfaceVariant
text: item.modelData?.icon ?? "" text: item.modelData.icon
} }
CustomText { CustomText {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: true Layout.fillWidth: true
color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurface color: item.active ? Colors.palette.m3onTertiaryContainer : Colors.palette.m3onSurface
text: item.modelData?.text ?? "" text: item.modelData.text
} }
Loader { Loader {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
active: item.modelData?.trailingIcon.length > 0 active: item.modelData.trailingIcon.length > 0
asynchronous: true asynchronous: true
visible: active visible: active
+1 -1
View File
@@ -70,7 +70,7 @@ TextFieldBase {
id: clearIcon id: clearIcon
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Tokens.padding.small anchors.rightMargin: Tokens.padding.larger
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
enabled: root.text enabled: root.text
icon: "clear" icon: "clear"
+3 -2
View File
@@ -1,8 +1,9 @@
import QtQuick import QtQuick
import QtQuick.Shapes import QtQuick.Shapes
import ZShell import ZShell
import ZShell.Config import ZShell.Components
import qs.Helpers import qs.Helpers
import ZShell.Config
import qs.Services import qs.Services
MouseArea { MouseArea {
@@ -80,7 +81,7 @@ MouseArea {
alwaysRunToEnd: true alwaysRunToEnd: true
duration: Tokens.anim.durations.expressiveSlowEffects * 2 duration: Tokens.anim.durations.expressiveSlowEffects * 2
easing: Tokens.anim.standard easing.bezierCurve: Tokens.anim.curves.standard
property: "circleRadius" property: "circleRadius"
target: root target: root
to: root.endRadius to: root.endRadius
+2 -2
View File
@@ -14,7 +14,7 @@ ButtonBase {
return Colors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondary; return type === TextButton.Filled ? Colors.palette.m3onPrimary : Colors.palette.m3onSecondary;
} }
horizontalPadding: Tokens.padding.small horizontalPadding: Tokens.padding.normal
implicitHeight: label.implicitHeight + verticalPadding * 2 implicitHeight: label.implicitHeight + verticalPadding * 2
implicitWidth: label.implicitWidth + horizontalPadding * 2 implicitWidth: label.implicitWidth + horizontalPadding * 2
inactiveColor: { inactiveColor: {
@@ -29,7 +29,7 @@ ButtonBase {
return Colors.palette.m3primary; return Colors.palette.m3primary;
return type === TextButton.Filled ? Colors.palette.m3onSurface : Colors.palette.m3onSecondaryContainer; return type === TextButton.Filled ? Colors.palette.m3onSurface : Colors.palette.m3onSecondaryContainer;
} }
verticalPadding: Tokens.padding.extraSmall verticalPadding: Tokens.padding.small
CustomText { CustomText {
id: label id: label
+1 -1
View File
@@ -36,7 +36,7 @@ TextField {
color: Colors.palette.m3primary color: Colors.palette.m3primary
implicitHeight: root.cursorRectangle.height implicitHeight: root.cursorRectangle.height
implicitWidth: 1.5 implicitWidth: 1.5
radius: Tokens.rounding.largeIncreased radius: Tokens.rounding.large
x: root.cursorRectangle.x x: root.cursorRectangle.x
y: root.cursorRectangle.y y: root.cursorRectangle.y
+8 -8
View File
@@ -32,8 +32,8 @@ CustomRect {
return Colors.palette.m3errorContainer; return Colors.palette.m3errorContainer;
return Colors.palette.m3surface; return Colors.palette.m3surface;
} }
implicitHeight: layout.implicitHeight + Tokens.padding.small * 2 implicitHeight: layout.implicitHeight + Tokens.padding.smaller * 2
radius: Tokens.rounding.medium radius: Tokens.rounding.normal
Behavior on border.color { Behavior on border.color {
CAnim { CAnim {
@@ -52,10 +52,10 @@ CustomRect {
id: layout id: layout
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.normal
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.smaller
anchors.rightMargin: Tokens.padding.small anchors.rightMargin: Tokens.padding.normal
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
CustomRect { CustomRect {
color: { color: {
@@ -67,9 +67,9 @@ CustomRect {
return Colors.palette.m3error; return Colors.palette.m3error;
return Colors.palette.m3surfaceContainerHigh; return Colors.palette.m3surfaceContainerHigh;
} }
implicitHeight: icon.implicitHeight + Tokens.padding.small * 2 implicitHeight: icon.implicitHeight + Tokens.padding.smaller * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: Tokens.rounding.medium radius: Tokens.rounding.normal
MaterialIcon { MaterialIcon {
id: icon id: icon
+3 -3
View File
@@ -21,7 +21,7 @@ Item {
} }
return h; return h;
} }
implicitWidth: Config.utilities.sizes.toastWidth - Tokens.padding.small * 2 implicitWidth: Config.utilities.sizes.toastWidth - Tokens.padding.normal * 2
Repeater { Repeater {
id: repeater id: repeater
@@ -82,7 +82,7 @@ Item {
Behavior on anchors.bottomMargin { Behavior on anchors.bottomMargin {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
} }
} }
Behavior on opacity { Behavior on opacity {
@@ -105,7 +105,7 @@ Item {
id: initAnim id: initAnim
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
from: 0 from: 0
properties: "opacity,scale" properties: "opacity,scale"
target: toast target: toast
+2 -33
View File
@@ -11,46 +11,15 @@ Variants {
required property ShellScreen modelData required property ShellScreen modelData
function rebuild(): void {
loader.active = false;
loader.active = true;
}
LazyLoader {
id: loader
active: true
Drawer {
screen: scope.modelData
}
}
Connections {
function onConfigPositionChanged(): void {
Qt.callLater(scope.rebuild);
}
target: (loader.item as Drawer)?.geometry ?? null
}
}
component Drawer: Scope {
id: drawer
readonly property alias geometry: content.geometry
required property ShellScreen screen
Exclusions { Exclusions {
bar: content.bar bar: content.bar
geometry: content.geometry screen: scope.modelData
screen: drawer.screen
} }
Windows { Windows {
id: content id: content
screen: drawer.screen screen: scope.modelData
} }
} }
} }
-55
View File
@@ -1,55 +0,0 @@
import QtQuick
import qs.Modules.Bar as Bar
QtObject {
id: root
required property Bar.BarLoader bar
readonly property real barClamped: bar.clampedExtent
readonly property real barExtent: bar.extent
readonly property bool barOnBottom: position === "bottom"
readonly property bool barOnLeft: position === "left"
readonly property bool barOnTop: position === "top"
required property string configPosition
readonly property bool horizontal: position !== "left"
readonly property string position: configPosition === "top" || configPosition === "bottom" ? configPosition : "left"
required property var win
function axisPos(x: real, y: real): real {
return horizontal ? x : y;
}
function barContains(x: real, y: real, clamped = false): bool {
const extent = clamped ? barClamped : barExtent;
if (barOnTop)
return y < extent;
if (barOnBottom)
return y > win.height - extent;
return x < extent;
}
function insetBottom(border: real, clamped = false): real {
return barOnBottom ? (clamped ? barClamped : barExtent) : border;
}
function insetLeft(border: real, clamped = false): real {
return barOnLeft ? (clamped ? barClamped : barExtent) : border;
}
function insetTop(border: real, clamped = false): real {
return barOnTop ? (clamped ? barClamped : barExtent) : border;
}
function inwardDrag(dragX: real, dragY: real): real {
if (barOnTop)
return dragY;
if (barOnBottom)
return -dragY;
return dragX;
}
onConfigPositionChanged: {
if (!["left", "top", "bottom"].includes(configPosition))
console.warn(`Invalid bar position '${configPosition}', falling back to left`);
}
}
+2 -11
View File
@@ -1,7 +1,6 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import Quickshell.Wayland
import QtQuick import QtQuick
import ZShell.Config import ZShell.Config
import qs.Components import qs.Components
@@ -10,24 +9,19 @@ Scope {
id: root id: root
required property Item bar required property Item bar
required property EdgeGeometry geometry
required property ShellScreen screen required property ShellScreen screen
ExclusionZone { ExclusionZone {
id: top id: top
WlrLayershell.layer: WlrLayer.Overlay
anchors.left: true
anchors.right: true
anchors.top: true anchors.top: true
hasBar: root.geometry.barOnTop exclusiveZone: root.bar.exclusiveZone
} }
ExclusionZone { ExclusionZone {
id: left id: left
anchors.left: true anchors.left: true
hasBar: root.geometry.barOnLeft
} }
ExclusionZone { ExclusionZone {
@@ -40,7 +34,6 @@ Scope {
id: bottom id: bottom
anchors.bottom: true anchors.bottom: true
hasBar: root.geometry.barOnBottom
} }
Timer { Timer {
@@ -51,9 +44,7 @@ Scope {
} }
component ExclusionZone: CustomWindow { component ExclusionZone: CustomWindow {
property bool hasBar exclusiveZone: Config.bar.border
exclusiveZone: hasBar ? root.bar.exclusiveZone : Config.bar.border
implicitHeight: 1 implicitHeight: 1
implicitWidth: 1 implicitWidth: 1
name: "Bar-Exclusion" name: "Bar-Exclusion"
+23 -41
View File
@@ -3,7 +3,7 @@ import QtQuick
import qs.Components import qs.Components
import ZShell.Config import ZShell.Config
import qs.Helpers import qs.Helpers
import qs.Modules.Bar.Popouts import qs.Modules as BarPopouts
Item { Item {
id: root id: root
@@ -12,47 +12,43 @@ Item {
required property real borderThickness required property real borderThickness
property bool dashboardShortcutActive property bool dashboardShortcutActive
required property Drawing drawing required property Drawing drawing
required property EdgeGeometry geometry
property bool osdShortcutActive property bool osdShortcutActive
required property Panels panels required property Panels panels
required property Wrapper popouts required property BarPopouts.Wrapper popouts
required property ShellScreen screen required property ShellScreen screen
property bool singleGestureTriggered: false property bool singleGestureTriggered: false
property bool utilitiesShortcutActive property bool utilitiesShortcutActive
required property PersistentProperties visibilities required property PersistentProperties visibilities
function inBottomPanel(panel: Item, x: real, y: real): bool { function inBottomPanel(panel: Item, x: real, y: real): bool {
const panelHeight = panel.height * (1 - (panel.offsetScale ?? 0)); return y > root.height - panel.height - Config.bar.border && withinPanelWidth(panel, x, y);
return y > root.height - (panelHeight + geometry.insetBottom(borderThickness)) && withinPanelWidth(panel, x, y);
} }
function inLeftPanel(panel: Item, x: real, y: real): bool { function inLeftPanel(panel: Item, x: real, y: real): bool {
return x < panel.x + panel.width + geometry.insetLeft(borderThickness) && withinPanelHeight(panel, x, y); return x < panel.x + panel.width + Config.bar.border && withinPanelHeight(panel, x, y);
}
function inPopoutArea(x: real, y: real): bool {
const panel = panels.popoutsWrapper;
if (!geometry.horizontal)
return inLeftPanel(panel, x, y);
return withinPanelWidth(panel, x, y) && withinPanelHeight(panel, x, y);
} }
function inRightPanel(panel: Item, x: real, y: real): bool { function inRightPanel(panel: Item, x: real, y: real): bool {
return x > panel.x + geometry.insetLeft(borderThickness) && withinPanelHeight(panel, x, y); return x > panel.x - Config.bar.border && withinPanelHeight(panel, x, y);
} }
function inTopPanel(panel: Item, x: real, y: real): bool { function inTopPanel(panel: Item, x: real, y: real): bool {
const panelHeight = panel.height * (1 - (panel.offsetScale ?? 0)); return y < bar.implicitHeight + panel.height && withinPanelWidth(panel, x, y);
return y < geometry.insetTop(borderThickness) + panelHeight && withinPanelWidth(panel, x, y); }
function onWheel(event: WheelEvent): void {
if (event.x < bar.implicitWidth) {
bar.handleWheel(event.y, event.angleDelta);
}
} }
function withinPanelHeight(panel: Item, x: real, y: real): bool { function withinPanelHeight(panel: Item, x: real, y: real): bool {
const panelY = panel.y + geometry.insetTop(borderThickness); const panelY = panel.y + bar.implicitHeight;
return y >= panelY && y <= panelY + panel.height; return y >= panelY && y <= panelY + panel.height;
} }
function withinPanelWidth(panel: Item, x: real, y: real): bool { function withinPanelWidth(panel: Item, x: real, y: real): bool {
const panelX = panel.x + geometry.insetLeft(borderThickness); const panelX = panel.x + root.borderThickness;
return x >= panelX && x <= panelX + panel.width; return x >= panelX && x <= panelX + panel.width;
} }
@@ -85,7 +81,7 @@ Item {
if (root.singleGestureTriggered) if (root.singleGestureTriggered)
return; return;
if (root.geometry.insetTop(root.borderThickness) > centroid.pressPosition.y) { if (centroid.pressPosition.y < root.bar.implicitHeight) {
if (dragY > 20) { if (dragY > 20) {
root.visibilities.settings = true; root.visibilities.settings = true;
root.singleGestureTriggered = true; root.singleGestureTriggered = true;
@@ -95,10 +91,10 @@ Item {
} }
} }
if (centroid.pressPosition.y > root.screen.height - root.geometry.insetBottom(root.borderThickness) && centroid.pressPosition.x < root.screen.width / 5 && dragY < -50) if (centroid.pressPosition.y > root.screen.height - Config.bar.border && centroid.pressPosition.x < root.screen.width / 5 && dragY < -50)
root.visibilities.clipboard = true; root.visibilities.clipboard = true;
if (!Config.dock.hoverToReveal && centroid.pressPosition.y > root.screen.height - root.geometry.insetTop(root.borderThickness) && centroid.pressPosition.x > root.screen.width / 5 && !root.visibilities.launcher) if (!Config.dock.hoverToReveal && centroid.pressPosition.y > root.screen.height - root.bar.implicitHeight && centroid.pressPosition.x > root.screen.width / 5 && !root.visibilities.launcher)
if (dragY < -10) { if (dragY < -10) {
root.visibilities.dock = true; root.visibilities.dock = true;
root.singleGestureTriggered = true; root.singleGestureTriggered = true;
@@ -162,19 +158,6 @@ Item {
} }
} }
Timer {
id: unhideTimer
interval: Config.bar.revealDelay
repeat: false
running: false
onTriggered: {
if (hoverHandler.hovered)
root.bar.isHovered = true;
}
}
HoverHandler { HoverHandler {
id: hoverHandler id: hoverHandler
@@ -191,7 +174,7 @@ Item {
root.popouts.hasCurrent = false; root.popouts.hasCurrent = false;
} }
if (Config.bar.autoHide || root.bar.fullscreen) if (Config.bar.autoHide)
root.bar.isHovered = false; root.bar.isHovered = false;
} }
} }
@@ -210,12 +193,9 @@ Item {
return; return;
} }
if (!root.visibilities.bar && Config.bar.autoHide && root.geometry.barContains(x, y, true)) if (!root.visibilities.bar && Config.bar.autoHide && y < root.bar.implicitHeight)
root.bar.isHovered = true; root.bar.isHovered = true;
if (root.bar.fullscreen && !root.bar.isHovered)
unhideTimer.start();
if (root.panels.sidebar.offsetScale === 1) { if (root.panels.sidebar.offsetScale === 1) {
const showOsd = root.inRightPanel(root.panels.osdWrapper, x, y); const showOsd = root.inRightPanel(root.panels.osdWrapper, x, y);
@@ -239,8 +219,8 @@ Item {
if (Config.dock.enable && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y)) if (Config.dock.enable && Config.dock.hoverToReveal && !root.visibilities.dock && !root.visibilities.launcher && root.inBottomPanel(root.panels.dock, x, y))
root.visibilities.dock = true; root.visibilities.dock = true;
if (root.geometry.barContains(x, y)) if (y < root.bar.implicitHeight)
root.bar.checkPopout(root.geometry.axisPos(x, y)); root.bar.checkPopout(x);
} }
} }
@@ -318,6 +298,8 @@ Item {
root.visibilities.sidebar = false; root.visibilities.sidebar = false;
root.panels.popouts.hasCurrent = false; root.panels.popouts.hasCurrent = false;
root.visibilities.launcher = false; root.visibilities.launcher = false;
} else {
Config.save();
} }
} }
+18 -21
View File
@@ -1,7 +1,7 @@
import Quickshell import Quickshell
import QtQuick import QtQuick
import qs.Components import qs.Components
import qs.Modules.Bar.Popouts as Popouts import qs.Modules as Modules
import qs.Modules.Notifications as Notifications import qs.Modules.Notifications as Notifications
import qs.Modules.Notifications.Sidebar as Sidebar import qs.Modules.Notifications.Sidebar as Sidebar
import qs.Modules.Notifications.Sidebar.Utils as Utils import qs.Modules.Notifications.Sidebar.Utils as Utils
@@ -27,7 +27,6 @@ Item {
readonly property alias dock: dock readonly property alias dock: dock
readonly property alias drawing: drawing readonly property alias drawing: drawing
required property var drawingItem required property var drawingItem
required property EdgeGeometry geometry
readonly property alias launcher: launcher readonly property alias launcher: launcher
readonly property alias notifications: notifications readonly property alias notifications: notifications
readonly property alias osd: osd readonly property alias osd: osd
@@ -44,26 +43,24 @@ Item {
readonly property alias utilities: utilities readonly property alias utilities: utilities
required property PersistentProperties visibilities required property PersistentProperties visibilities
anchors.bottomMargin: geometry.insetBottom(borderThickness)
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: geometry.insetLeft(borderThickness)
anchors.margins: borderThickness anchors.margins: borderThickness
anchors.topMargin: geometry.insetTop(borderThickness) anchors.topMargin: bar.implicitHeight
Item { Item {
id: resourcesWrapper id: resourcesWrapper
anchors.bottom: root.geometry.position === "bottom" ? parent.bottom : undefined
anchors.left: parent.left anchors.left: parent.left
anchors.top: root.geometry.position !== "bottom" ? parent.top : undefined anchors.top: parent.top
clip: true clip: true
implicitHeight: root.geometry.horizontal ? resources.implicitHeight * (1 - resources.offsetScale) : resources.implicitHeight implicitHeight: resources.implicitHeight * (1 - resources.offsetScale)
implicitWidth: root.geometry.horizontal ? resources.implicitWidth : resources.implicitWidth * (1 - resources.offsetScale) implicitWidth: resources.implicitWidth
Resources.Wrapper { Resources.Wrapper {
id: resources id: resources
position: root.geometry.position anchors.left: parent.left
anchors.top: parent.top
visibilities: root.visibilities visibilities: root.visibilities
} }
} }
@@ -99,11 +96,11 @@ Item {
visibilities: root.visibilities visibilities: root.visibilities
} }
Popouts.ClipWrapper { Modules.ClipWrapper {
id: popouts id: popouts
anchors.top: parent.top
borderThickness: root.borderThickness borderThickness: root.borderThickness
position: root.geometry.position
screen: root.screen screen: root.screen
} }
@@ -111,7 +108,7 @@ Item {
id: toasts id: toasts
anchors.bottom: sidebar.visible ? parent.bottom : utilities.top anchors.bottom: sidebar.visible ? parent.bottom : utilities.top
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.normal
anchors.right: sidebar.left anchors.right: sidebar.left
} }
@@ -150,26 +147,26 @@ Item {
property real offsetScale: dashboard.shouldBeActive ? 0 : 1 property real offsetScale: dashboard.shouldBeActive ? 0 : 1
anchors.bottom: root.geometry.barOnLeft || root.geometry.barOnBottom ? parent.bottom : undefined anchors.right: parent.right
anchors.left: root.geometry.barOnLeft ? parent.left : undefined anchors.top: parent.top
anchors.right: root.geometry.barOnLeft ? undefined : parent.right
anchors.top: root.geometry.barOnBottom || root.geometry.barOnLeft ? undefined : parent.top
clip: true clip: true
implicitHeight: root.geometry.horizontal ? dashboard.implicitHeight * (1 - offsetScale) : dashboard.implicitHeight implicitHeight: dashboard.implicitHeight * (1 - offsetScale)
implicitWidth: root.geometry.horizontal ? dashboard.implicitWidth : dashboard.implicitWidth * (1 - offsetScale) implicitWidth: dashboard.implicitWidth
Behavior on offsetScale { Behavior on offsetScale {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
} }
} }
Dashboard.Wrapper { Dashboard.Wrapper {
id: dashboard id: dashboard
anchors.right: parent.right
anchors.top: parent.top
anchors.topMargin: (-implicitHeight - 5) * offsetScale
offsetScale: dashboardWrapper.offsetScale offsetScale: dashboardWrapper.offsetScale
position: root.geometry.position
visibilities: root.visibilities visibilities: root.visibilities
} }
} }
+8 -13
View File
@@ -7,18 +7,17 @@ import qs.Modules.Bar as Bar
Region { Region {
id: root id: root
// required property Bar.BarLoader bar required property Bar.BarLoader bar
readonly property real borderThickness: win.borderThickness readonly property real borderThickness: win.borderThickness
required property EdgeGeometry geometry
readonly property alias menuPopoutRegion: menuPopoutRegion readonly property alias menuPopoutRegion: menuPopoutRegion
required property Panels panels required property Panels panels
required property var win required property var win
height: win.height - geometry.insetTop(borderThickness, true) - geometry.insetBottom(borderThickness, true) - win.dragMaskPadding * 2 height: win.height - bar.implicitHeight - win.borderThickness - win.dragMaskPadding * 2
intersection: Intersection.Xor intersection: Intersection.Xor
width: win.width - geometry.insetLeft(borderThickness, true) * 2 - win.dragMaskPadding * 2 width: win.width - win.borderThickness * 2 - win.dragMaskPadding * 2
x: geometry.insetLeft(borderThickness, true) + win.dragMaskPadding x: win.borderThickness + win.dragMaskPadding
y: geometry.insetTop(borderThickness, true) + win.dragMaskPadding y: bar.implicitHeight + win.dragMaskPadding
R { R {
panel: root.panels.dashboardWrapper panel: root.panels.dashboardWrapper
@@ -42,21 +41,17 @@ Region {
} }
R { R {
height: panel.height + root.geometry.insetTop(root.borderThickness)
panel: root.panels.notifications panel: root.panels.notifications
y: 0
} }
R { R {
height: panel.height * (1 - root.panels.utilities.offsetScale) + root.geometry.insetBottom(root.borderThickness) height: panel.height * (1 - root.panels.utilities.offsetScale) + root.borderThickness
panel: root.panels.utilities panel: root.panels.utilities
y: root.win.height - height y: root.win.height - height
} }
R { R {
height: root.geometry.horizontal ? panel.height * (1 - root.panels.popoutsWrapper.offsetScale) : panel.height
panel: root.panels.popoutsWrapper panel: root.panels.popoutsWrapper
width: root.geometry.horizontal ? panel.width : panel.width * (1 - root.panels.popoutsWrapper.offsetScale)
} }
R { R {
@@ -87,7 +82,7 @@ Region {
height: panel.height height: panel.height
intersection: Intersection.Subtract intersection: Intersection.Subtract
width: panel.width width: panel.width
x: panel.x + root.geometry.insetLeft(root.borderThickness) x: panel.x + root.borderThickness
y: panel.y + root.geometry.insetTop(root.borderThickness) y: panel.y + root.bar.implicitHeight
} }
} }
+36 -56
View File
@@ -33,7 +33,6 @@ CustomWindow {
return 100; return 100;
} }
property real fsTransitionProg: hasFullscreen ? 1 : 0 property real fsTransitionProg: hasFullscreen ? 1 : 0
readonly property alias geometry: geometry
readonly property bool hasFullscreen: { readonly property bool hasFullscreen: {
if (hasSpecialWorkspace) { if (hasSpecialWorkspace) {
const specialName = monitor?.lastIpcObject.specialWorkspace?.name; const specialName = monitor?.lastIpcObject.specialWorkspace?.name;
@@ -51,7 +50,7 @@ CustomWindow {
readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen) readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
property var root: Quickshell.shellDir property var root: Quickshell.shellDir
readonly property real sdfBorderOffset: 2 * fsTransitionProg readonly property real sdfBorderOffset: 2 * fsTransitionProg
readonly property real shadowOpacity: 0.7 * (1 - (bar.isHovered ? 0 : fsTransitionProg)) readonly property real shadowOpacity: 0.7 * (1 - fsTransitionProg)
property color surfaceColor: Colors.tPalette.m3surface property color surfaceColor: Colors.tPalette.m3surface
WlrLayershell.exclusionMode: ExclusionMode.Ignore WlrLayershell.exclusionMode: ExclusionMode.Ignore
@@ -59,7 +58,7 @@ CustomWindow {
WlrLayershell.layer: (fsTransitionProg > 0 && Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top WlrLayershell.layer: (fsTransitionProg > 0 && Config.general.showOverFullscreen) || (hasSpecialWorkspace && hasFullscreenOnNormalWs) ? WlrLayer.Overlay : WlrLayer.Top
color: "transparent" color: "transparent"
contentItem.focus: true contentItem.focus: true
mask: visibilities.isDrawing ? null : (hasFullscreen && !bar.isHovered ? emptyRegion : regions) mask: visibilities.isDrawing ? null : (hasFullscreen ? emptyRegion : regions)
name: "Bar" name: "Bar"
Behavior on fsTransitionProg { Behavior on fsTransitionProg {
@@ -96,21 +95,13 @@ CustomWindow {
panels.popouts.hasCurrent = false; panels.popouts.hasCurrent = false;
} }
EdgeGeometry {
id: geometry
bar: bar
configPosition: Config.bar.position
win: root
}
Region { Region {
id: emptyRegion id: emptyRegion
height: panels.notifications.height height: panels.notifications.height
width: panels.notifications.width width: panels.notifications.width
x: panels.notifications.x + geometry.insetLeft(root.borderThickness) x: panels.notifications.x + root.borderThickness
y: panels.notifications.y + geometry.insetTop(root.borderThickness) y: panels.notifications.y + bar.implicitHeight
Region { Region {
height: panels.osd.height height: panels.osd.height
@@ -118,18 +109,12 @@ CustomWindow {
x: root.width - width x: root.width - width
y: panels.osdWrapper.y + bar.implicitHeight y: panels.osdWrapper.y + bar.implicitHeight
} }
Region {
height: geometry.horizontal ? 1 : root.screen.height
width: geometry.horizontal ? root.screen.width : 1
y: geometry.position === "bottom" ? root.screen.height - 1 : 0
}
} }
Regions { Regions {
id: regions id: regions
geometry: geometry bar: bar
panels: panels panels: panels
win: root win: root
} }
@@ -208,10 +193,10 @@ CustomWindow {
BlobInvertedRect { BlobInvertedRect {
anchors.fill: parent anchors.fill: parent
anchors.margins: -50 anchors.margins: -50
borderBottom: geometry.insetBottom(root.borderThickness) - anchors.margins - root.sdfBorderOffset borderBottom: root.borderThickness - anchors.margins - root.sdfBorderOffset
borderLeft: geometry.insetLeft(root.borderThickness) - anchors.margins - root.sdfBorderOffset borderLeft: root.borderThickness - anchors.margins - root.sdfBorderOffset
borderRight: root.borderThickness - anchors.margins - root.sdfBorderOffset borderRight: root.borderThickness - anchors.margins - root.sdfBorderOffset
borderTop: geometry.insetTop(root.borderThickness) - anchors.margins - root.sdfBorderOffset borderTop: bar.implicitHeight - anchors.margins - root.sdfBorderOffset
group: blobGroup group: blobGroup
radius: root.borderRounding radius: root.borderRounding
} }
@@ -219,15 +204,15 @@ CustomWindow {
PanelBg { PanelBg {
id: dashBg id: dashBg
property real extraExtent: 0.2 property real extraHeight: 0.2
deformAmount: 0.06 deformAmount: 0.06
implicitHeight: panels.dashboard.height * (geometry.horizontal ? 1 + extraExtent : 1) implicitHeight: panels.dashboard.height * (1 + extraHeight)
implicitWidth: panels.dashboard.width * (geometry.horizontal ? 1 : 1 + extraExtent) implicitWidth: panels.dashboard.width
panel: panels.dashboardWrapper panel: panels.dashboardWrapper
radius: Tokens.rounding.extraLarge radius: Tokens.rounding.normal
x: panels.dashboardWrapper.x + panels.dashboard.x + geometry.insetLeft(root.borderThickness) - (geometry.horizontal ? 0 : panels.dashboard.width * extraExtent) x: panels.dashboardWrapper.x + panels.dashboard.x + root.borderThickness
y: panels.dashboardWrapper.y + panels.dashboard.y + geometry.insetTop(root.borderThickness) - (geometry.horizontal && geometry.position !== "bottom" ? panels.dashboard.height * extraExtent : 0) y: panels.dashboardWrapper.y + panels.dashboard.y + bar.implicitHeight - panels.dashboard.height * extraHeight
} }
PanelBg { PanelBg {
@@ -238,8 +223,8 @@ CustomWindow {
deformAmount: 0.06 deformAmount: 0.06
implicitHeight: panels.launcher.height * (1 + extraHeight) implicitHeight: panels.launcher.height * (1 + extraHeight)
panel: panels.launcher panel: panels.launcher
radius: Tokens.rounding.medium + (Tokens.padding.largeIncreased / 4) radius: Tokens.rounding.smallest + 5
y: panels.launcher.y + geometry.insetTop(root.borderThickness) y: panels.launcher.y + bar.implicitHeight
} }
PanelBg { PanelBg {
@@ -260,14 +245,15 @@ CustomWindow {
implicitWidth: panels.osd.width implicitWidth: panels.osd.width
panel: panels.osdWrapper panel: panels.osdWrapper
radius: 20 radius: 20
x: panels.osdWrapper.x + panels.osd.x + geometry.insetLeft(root.borderThickness) x: panels.osdWrapper.x + panels.osd.x + root.borderThickness
y: panels.osdWrapper.y + panels.osd.y + bar.implicitHeight
} }
PanelBg { PanelBg {
id: notifsBg id: notifsBg
panel: panels.notifications panel: panels.notifications
radius: Tokens.rounding.large radius: Tokens.rounding.normal
} }
PanelBg { PanelBg {
@@ -282,17 +268,17 @@ CustomWindow {
PanelBg { PanelBg {
id: popoutBg id: popoutBg
property real extraExtent: 0.2 property real extraHeight: 0.2
deformAmount: panels.popouts.currentName.startsWith("traymenu") ? 0.15 : 0.08 deformAmount: panels.popouts.currentName.startsWith("traymenu") ? 0.15 : 0.08
implicitHeight: panels.popouts.height * (geometry.horizontal ? 1 + extraExtent : 1) implicitHeight: panels.popouts.height * (1 + extraHeight)
implicitWidth: panels.popouts.width * (geometry.horizontal ? 1 : 1 + extraExtent) implicitWidth: panels.popouts.width
panel: panels.popoutsWrapper panel: panels.popoutsWrapper
radius: panels.popouts.current?.panelRadius ?? Tokens.rounding.large radius: panels.popouts.current?.panelRadius ?? Tokens.rounding.normal
x: panels.popoutsWrapper.x + panels.popouts.x + geometry.insetLeft(root.borderThickness) - (geometry.horizontal ? 0 : panels.popouts.width * extraExtent) x: panels.popoutsWrapper.x + panels.popouts.x + root.borderThickness
y: panels.popoutsWrapper.y + panels.popouts.y + geometry.insetTop(root.borderThickness) - (geometry.barOnTop ? panels.popouts.height * extraExtent : 0) y: panels.popoutsWrapper.y + panels.popouts.y + bar.implicitHeight - panels.popouts.height * extraHeight
Behavior on extraExtent { Behavior on extraHeight {
Anim { Anim {
} }
} }
@@ -305,9 +291,9 @@ CustomWindow {
implicitHeight: panels.resources.height implicitHeight: panels.resources.height
implicitWidth: panels.resources.width implicitWidth: panels.resources.width
panel: panels.resourcesWrapper panel: panels.resourcesWrapper
radius: Tokens.rounding.largeIncreased + Tokens.padding.small radius: Tokens.rounding.large
x: panels.resourcesWrapper.x + panels.resources.x + geometry.insetLeft(root.borderThickness) x: panels.resourcesWrapper.x + panels.resources.x + root.borderThickness
y: panels.resourcesWrapper.y + panels.resources.y + geometry.insetTop(root.borderThickness) y: panels.resourcesWrapper.y + panels.resources.y + bar.implicitHeight
} }
PanelBg { PanelBg {
@@ -315,7 +301,7 @@ CustomWindow {
deformAmount: 0.03 deformAmount: 0.03
panel: panels.settings panel: panels.settings
radius: Tokens.rounding.largeIncreased + Tokens.padding.small radius: Tokens.rounding.large + Tokens.padding.normal
} }
PanelBg { PanelBg {
@@ -323,7 +309,7 @@ CustomWindow {
deformAmount: 0.08 deformAmount: 0.08
panel: panels.dock panel: panels.dock
radius: Tokens.rounding.medium radius: Tokens.rounding.normal
} }
PanelBg { PanelBg {
@@ -331,7 +317,7 @@ CustomWindow {
deformAmount: 0.08 deformAmount: 0.08
panel: panels.drawing panel: panels.drawing
radius: Tokens.rounding.medium radius: Tokens.rounding.normal
} }
PanelBg { PanelBg {
@@ -385,7 +371,6 @@ CustomWindow {
borderThickness: root.borderLayoutThickness borderThickness: root.borderLayoutThickness
drawing: drawing drawing: drawing
enabled: true enabled: true
geometry: geometry
panels: panels panels: panels
popouts: panels.popouts popouts: panels.popouts
screen: root.screen screen: root.screen
@@ -397,7 +382,6 @@ CustomWindow {
bar: bar bar: bar
borderThickness: root.borderThickness borderThickness: root.borderThickness
drawingItem: drawing drawingItem: drawing
geometry: geometry
screen: root.screen screen: root.screen
visibilities: visibilities visibilities: visibilities
@@ -439,18 +423,14 @@ CustomWindow {
BarLoader { BarLoader {
id: bar id: bar
anchors.bottom: geometry.barOnBottom ? parent.bottom : undefined
anchors.left: parent.left anchors.left: parent.left
anchors.top: geometry.barOnBottom ? undefined : parent.top anchors.right: parent.right
enabled: !visibilities.isDrawing enabled: !visibilities.isDrawing
fullscreen: root.hasFullscreen fullscreen: root.hasFullscreen
height: geometry.horizontal ? implicitHeight : parent.height
popouts: panels.popouts popouts: panels.popouts
popoutsWrapper: panels.popoutsWrapper popoutsWrapper: panels.popoutsWrapper
position: geometry.position
screen: root.screen screen: root.screen
visibilities: visibilities visibilities: visibilities
width: geometry.horizontal ? parent.width : implicitWidth
} }
} }
@@ -462,8 +442,8 @@ CustomWindow {
group: blobGroup group: blobGroup
implicitHeight: panel.height implicitHeight: panel.height
implicitWidth: panel.width implicitWidth: panel.width
radius: Tokens.rounding.small radius: Tokens.rounding.smallest
x: panel.x + geometry.insetLeft(root.borderThickness) x: panel.x + root.borderThickness
y: panel.y + geometry.insetTop(root.borderThickness) y: panel.y + bar.implicitHeight
} }
} }
+33
View File
@@ -0,0 +1,33 @@
import QtQuick
import QtQuick.Effects
Item {
id: root
property real radius
Rectangle {
id: shadowRect
anchors.fill: root
color: "black"
layer.enabled: true
radius: root.radius
visible: false
}
MultiEffect {
id: effects
anchors.fill: shadowRect
autoPaddingEnabled: true
maskEnabled: true
maskInverted: true
maskSource: shadowRect
shadowBlur: 2.0
shadowColor: "black"
shadowEnabled: true
shadowOpacity: 1
source: shadowRect
}
}
+8 -8
View File
@@ -18,7 +18,7 @@ ColumnLayout {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: false Layout.fillWidth: false
Layout.preferredWidth: centerWidth Layout.preferredWidth: centerWidth
spacing: Tokens.spacing.largeIncreased * 2 spacing: Tokens.spacing.large * 2
RowLayout { RowLayout {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
@@ -64,7 +64,7 @@ ColumnLayout {
CustomClippingRect { CustomClippingRect {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Tokens.spacing.largeIncreased * 2 Layout.topMargin: Tokens.spacing.large * 2
color: Colors.tPalette.m3surfaceContainer color: Colors.tPalette.m3surfaceContainer
implicitHeight: root.centerWidth / 2 implicitHeight: root.centerWidth / 2
implicitWidth: root.centerWidth / 2 implicitWidth: root.centerWidth / 2
@@ -99,7 +99,7 @@ ColumnLayout {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
color: Colors.tPalette.m3surfaceContainer color: Colors.tPalette.m3surfaceContainer
focus: true focus: true
implicitHeight: input.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: input.implicitHeight + Tokens.padding.small * 2
implicitWidth: root.centerWidth * 0.8 implicitWidth: root.centerWidth * 0.8
radius: Tokens.rounding.full radius: Tokens.rounding.full
@@ -130,11 +130,11 @@ ColumnLayout {
id: input id: input
anchors.fill: parent anchors.fill: parent
anchors.margins: Tokens.padding.extraSmall anchors.margins: Tokens.padding.small
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
Item { Item {
implicitHeight: statusIcon.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: statusIcon.implicitHeight + Tokens.padding.small * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
MaterialIcon { MaterialIcon {
@@ -174,7 +174,7 @@ ColumnLayout {
CustomRect { CustomRect {
color: root.greeter.buffer && !root.greeter.launching ? Colors.palette.m3primary : Colors.layer(Colors.palette.m3surfaceContainerHigh, 2) color: root.greeter.buffer && !root.greeter.launching ? Colors.palette.m3primary : Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
implicitHeight: enterIcon.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: enterIcon.implicitHeight + Tokens.padding.small * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
radius: Tokens.rounding.full radius: Tokens.rounding.full
@@ -200,7 +200,7 @@ ColumnLayout {
Item { Item {
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: -Tokens.spacing.largeIncreased Layout.topMargin: -Tokens.spacing.large
implicitHeight: Math.max(message.implicitHeight, stateMessage.implicitHeight) implicitHeight: Math.max(message.implicitHeight, stateMessage.implicitHeight)
Behavior on implicitHeight { Behavior on implicitHeight {
+11 -11
View File
@@ -30,11 +30,11 @@ NumberAnimation {
if (type === Anim.DefaultSpatial) if (type === Anim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial; return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial) if (type === Anim.SlowSpatial)
return Tokens.anim.durations.expressiveSlowSpatial; return Tokens.anim.durations.large;
if (type === Anim.FastEffects) if (type === Anim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects; return Tokens.anim.durations.expressiveFastEffects;
if (type === Anim.DefaultEffects) if (type === Anim.DefaultEffects)
return Tokens.anim.durations.expressiveDefaultEffects; return Tokens.anim.durations.expressiveEffects;
if (type === Anim.SlowEffects) if (type === Anim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects; return Tokens.anim.durations.expressiveSlowEffects;
@@ -42,22 +42,22 @@ NumberAnimation {
const idx = type % 4; // 0-7 are the 4 standard types const idx = type % 4; // 0-7 are the 4 standard types
return Tokens.anim.durations[types[idx]]; return Tokens.anim.durations[types[idx]];
} }
easing: { easing.bezierCurve: {
if (type === Anim.FastSpatial) if (type === Anim.FastSpatial)
return Tokens.anim.expressiveFastSpatial; return Tokens.anim.curves.expressiveFastSpatial;
if (type === Anim.DefaultSpatial) if (type === Anim.DefaultSpatial)
return Tokens.anim.expressiveDefaultSpatial; return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === Anim.SlowSpatial) if (type === Anim.SlowSpatial)
return Tokens.anim.expressiveSlowSpatial; return Tokens.anim.curves.expressiveSlowSpatial;
if (type === Anim.FastEffects) if (type === Anim.FastEffects)
return Tokens.anim.expressiveFastEffects; return Tokens.anim.curves.expressiveFastEffects;
if (type === Anim.DefaultEffects) if (type === Anim.DefaultEffects)
return Tokens.anim.expressiveDefaultEffects; return Tokens.anim.curves.expressiveDefaultEffects;
if (type === Anim.SlowEffects) if (type === Anim.SlowEffects)
return Tokens.anim.expressiveSlowEffects; return Tokens.anim.curves.expressiveSlowEffects;
if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge) if (type >= Anim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.emphasized; return Tokens.anim.curves.emphasized;
return Tokens.anim.standard; return Tokens.anim.curves.standard;
} }
} }
+58 -2
View File
@@ -2,6 +2,62 @@ import QtQuick
import ZShell.Config import ZShell.Config
ColorAnimation { ColorAnimation {
duration: Tokens.anim.durations.expressiveSlowEffects enum Type {
easing: Tokens.anim.expressiveSlowEffects StandardSmall = 0,
Standard,
StandardLarge,
StandardExtraLarge,
EmphasizedSmall,
Emphasized,
EmphasizedLarge,
EmphasizedExtraLarge,
FastSpatial,
DefaultSpatial,
SlowSpatial,
FastEffects,
DefaultEffects,
SlowEffects
}
property int type: CAnim.DefaultSpatial
duration: {
if (type < CAnim.StandardSmall || type > Anim.SlowEffects)
return Tokens.anim.durations.normal;
if (type === CAnim.FastSpatial)
return Tokens.anim.durations.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.durations.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.durations.large;
if (type === CAnim.FastEffects)
return Tokens.anim.durations.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.durations.expressiveEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.durations.expressiveSlowEffects;
const types = ["small", "normal", "large", "extraLarge"];
const idx = type % 4;
return Tokens.anim.durations[types[idx]];
}
easing.bezierCurve: {
if (type === CAnim.FastSpatial)
return Tokens.anim.curves.expressiveFastSpatial;
if (type === CAnim.DefaultSpatial)
return Tokens.anim.curves.expressiveDefaultSpatial;
if (type === CAnim.SlowSpatial)
return Tokens.anim.curves.expressiveSlowSpatial;
if (type === CAnim.FastEffects)
return Tokens.anim.curves.expressiveFastEffects;
if (type === CAnim.DefaultEffects)
return Tokens.anim.curves.expressiveDefaultEffects;
if (type === CAnim.SlowEffects)
return Tokens.anim.curves.expressiveSlowEffects;
if (type >= CAnim.EmphasizedSmall && type <= Anim.EmphasizedExtraLarge)
return Tokens.anim.curves.emphasized;
return Tokens.anim.curves.standard;
}
} }
+1 -1
View File
@@ -23,7 +23,7 @@ BusyIndicator {
property real implicitSize: Tokens.font.size.normal * 3 property real implicitSize: Tokens.font.size.normal * 3
property real internalStrokeWidth: strokeWidth property real internalStrokeWidth: strokeWidth
readonly property alias progress: manager.progress readonly property alias progress: manager.progress
property real strokeWidth: Tokens.padding.extraSmall * 0.8 property real strokeWidth: Tokens.padding.small * 0.8
property alias type: manager.indeterminateAnimationType property alias type: manager.indeterminateAnimationType
implicitHeight: implicitSize implicitHeight: implicitSize
+1 -1
View File
@@ -21,7 +21,7 @@ Item {
readonly property real size: Math.min(width, height) readonly property real size: Math.min(width, height)
property int spacing: Tokens.spacing.small property int spacing: Tokens.spacing.small
property int startAngle: -90 property int startAngle: -90
property int strokeWidth: Tokens.padding.extraSmall property int strokeWidth: Tokens.padding.small
property int sweepAngle: 360 property int sweepAngle: 360
readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2 readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2
property real value property real value
+1 -1
View File
@@ -27,7 +27,7 @@ TextField {
color: Colors.palette.m3primary color: Colors.palette.m3primary
implicitWidth: 2 implicitWidth: 2
radius: Tokens.rounding.medium radius: Tokens.rounding.normal
Behavior on opacity { Behavior on opacity {
Anim { Anim {
+2 -1
View File
@@ -1,4 +1,5 @@
import QtQuick import QtQuick
import QtQuick.Controls
import ZShell.Config import ZShell.Config
import qs.Services import qs.Services
@@ -10,6 +11,6 @@ TextInput {
font { font {
family: Config.appearance?.font.family.sans ?? "sans-serif" family: Config.appearance?.font.family.sans ?? "sans-serif"
hintingPreference: Font.PreferFullHinting hintingPreference: Font.PreferFullHinting
pixelSize: Tokens?.font.size.normal ?? 15 pixelSize: Config.appearance?.font.size.normal ?? 15
} }
} }
+1 -1
View File
@@ -81,7 +81,7 @@ MouseArea {
alwaysRunToEnd: true alwaysRunToEnd: true
duration: Tokens.anim.durations.expressiveSlowEffects * 2 duration: Tokens.anim.durations.expressiveSlowEffects * 2
easing: Tokens.anim.standard easing.bezierCurve: Tokens.anim.curves.standard
property: "circleRadius" property: "circleRadius"
target: root target: root
to: root.endRadius to: root.endRadius
+7 -7
View File
@@ -11,18 +11,18 @@ RowLayout {
required property var greeter required property var greeter
required property real screenHeight required property real screenHeight
spacing: Tokens.spacing.largeIncreased * 2 spacing: Tokens.spacing.large * 2
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
CustomRect { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
color: Colors.tPalette.m3surfaceContainer color: Colors.tPalette.m3surfaceContainer
implicitHeight: weather.implicitHeight implicitHeight: weather.implicitHeight
radius: Tokens.rounding.small radius: Tokens.rounding.small
topLeftRadius: Tokens.rounding.largeIncreased topLeftRadius: Tokens.rounding.large
WeatherInfo { WeatherInfo {
id: weather id: weather
@@ -34,7 +34,7 @@ RowLayout {
CustomClippingRect { CustomClippingRect {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
bottomLeftRadius: Tokens.rounding.largeIncreased bottomLeftRadius: Tokens.rounding.large
color: Colors.tPalette.m3surfaceContainer color: Colors.tPalette.m3surfaceContainer
radius: Tokens.rounding.small radius: Tokens.rounding.small
@@ -51,15 +51,15 @@ RowLayout {
ColumnLayout { ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
CustomRect { CustomRect {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
bottomRightRadius: Tokens.rounding.largeIncreased bottomRightRadius: Tokens.rounding.large
color: Colors.tPalette.m3surfaceContainer color: Colors.tPalette.m3surfaceContainer
radius: Tokens.rounding.small radius: Tokens.rounding.small
topRightRadius: Tokens.rounding.largeIncreased topRightRadius: Tokens.rounding.large
SessionDock { SessionDock {
greeter: root.greeter greeter: root.greeter
+5 -5
View File
@@ -43,7 +43,7 @@ Scope {
ParallelAnimation { ParallelAnimation {
Anim { Anim {
duration: Tokens.anim.durations.expressiveFastSpatial duration: Tokens.anim.durations.expressiveFastSpatial
easing: Tokens.anim.expressiveFastSpatial easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
property: "scale" property: "scale"
target: lockContent target: lockContent
to: 1 to: 1
@@ -65,7 +65,7 @@ Scope {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
property: "scale" property: "scale"
target: content target: content
to: 1 to: 1
@@ -74,12 +74,12 @@ Scope {
Anim { Anim {
property: "radius" property: "radius"
target: lockBg target: lockBg
to: Tokens.rounding.largeIncreased * 1.5 to: Tokens.rounding.large * 1.5
} }
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
property: "implicitWidth" property: "implicitWidth"
target: lockContent target: lockContent
to: (win.screen?.height ?? 0) * Config.lock.sizes.heightMult * Config.lock.sizes.ratio to: (win.screen?.height ?? 0) * Config.lock.sizes.heightMult * Config.lock.sizes.ratio
@@ -87,7 +87,7 @@ Scope {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
property: "implicitHeight" property: "implicitHeight"
target: lockContent target: lockContent
to: (win.screen?.height ?? 0) * Config.lock.sizes.heightMult to: (win.screen?.height ?? 0) * Config.lock.sizes.heightMult
+1 -1
View File
@@ -113,7 +113,7 @@ Item {
Behavior on scale { Behavior on scale {
Anim { Anim {
duration: Tokens.anim.durations.expressiveFastSpatial duration: Tokens.anim.durations.expressiveFastSpatial
easing: Tokens.anim.expressiveFastSpatial easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
} }
} }
+8 -8
View File
@@ -13,7 +13,7 @@ ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: Tokens.padding.large anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.small spacing: Tokens.spacing.smaller
CustomText { CustomText {
Layout.fillWidth: true Layout.fillWidth: true
@@ -41,7 +41,7 @@ ColumnLayout {
} }
} }
sourceComponent: ColumnLayout { sourceComponent: ColumnLayout {
spacing: Tokens.spacing.largeIncreased spacing: Tokens.spacing.large
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
@@ -79,8 +79,8 @@ ColumnLayout {
anchors.left: parent?.left anchors.left: parent?.left
anchors.right: parent?.right anchors.right: parent?.right
implicitHeight: row.implicitHeight + Tokens.padding.small * 2 implicitHeight: row.implicitHeight + Tokens.padding.normal * 2
radius: Tokens.rounding.medium - Tokens.padding.small radius: Tokens.rounding.normal - Tokens.padding.smaller
StateLayer { StateLayer {
onClicked: { onClicked: {
@@ -92,8 +92,8 @@ ColumnLayout {
id: row id: row
anchors.fill: parent anchors.fill: parent
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.normal
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
MaterialIcon { MaterialIcon {
color: session.index === sessions.currentIndex ? Colors.palette.m3onPrimary : Colors.palette.m3onSurfaceVariant color: session.index === sessions.currentIndex ? Colors.palette.m3onPrimary : Colors.palette.m3onSurfaceVariant
@@ -129,13 +129,13 @@ ColumnLayout {
color: Colors.palette.m3primary color: Colors.palette.m3primary
implicitHeight: sessions.currentItem?.implicitHeight ?? 0 implicitHeight: sessions.currentItem?.implicitHeight ?? 0
implicitWidth: sessions.width implicitWidth: sessions.width
radius: Tokens.rounding.medium - Tokens.padding.small radius: Tokens.rounding.normal - Tokens.padding.smaller
y: sessions.currentItem?.y ?? 0 y: sessions.currentItem?.y ?? 0
Behavior on y { Behavior on y {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
} }
+9 -9
View File
@@ -14,7 +14,7 @@ ColumnLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: Tokens.padding.large anchors.margins: Tokens.padding.large
spacing: Tokens.spacing.small spacing: Tokens.spacing.smaller
CustomText { CustomText {
Layout.fillWidth: true Layout.fillWidth: true
@@ -42,7 +42,7 @@ ColumnLayout {
} }
} }
sourceComponent: ColumnLayout { sourceComponent: ColumnLayout {
spacing: Tokens.spacing.largeIncreased spacing: Tokens.spacing.large
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
@@ -81,8 +81,8 @@ ColumnLayout {
anchors.left: parent?.left anchors.left: parent?.left
anchors.right: parent?.right anchors.right: parent?.right
implicitHeight: row.implicitHeight + Tokens.padding.small * 2 implicitHeight: row.implicitHeight + Tokens.padding.normal * 2
radius: Tokens.rounding.medium - Tokens.padding.small radius: Tokens.rounding.normal - Tokens.padding.smaller
StateLayer { StateLayer {
onClicked: { onClicked: {
@@ -94,8 +94,8 @@ ColumnLayout {
id: row id: row
anchors.fill: parent anchors.fill: parent
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.normal
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
CustomClippingRect { CustomClippingRect {
Layout.preferredHeight: 50 Layout.preferredHeight: 50
@@ -135,13 +135,13 @@ ColumnLayout {
color: Colors.palette.m3primary color: Colors.palette.m3primary
implicitHeight: users.currentItem?.implicitHeight ?? 0 implicitHeight: users.currentItem?.implicitHeight ?? 0
implicitWidth: users.width implicitWidth: users.width
radius: Tokens.rounding.medium - Tokens.padding.small radius: Tokens.rounding.normal - Tokens.padding.smaller
y: users.currentItem?.y ?? 0 y: users.currentItem?.y ?? 0
Behavior on y { Behavior on y {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultEffects duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
} }
+4 -4
View File
@@ -34,7 +34,7 @@ ColumnLayout {
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
spacing: Tokens.spacing.largeIncreased spacing: Tokens.spacing.large
MaterialIcon { MaterialIcon {
animate: true animate: true
@@ -67,7 +67,7 @@ ColumnLayout {
} }
Loader { Loader {
Layout.rightMargin: Tokens.padding.small Layout.rightMargin: Tokens.padding.smaller
active: root.width > 400 active: root.width > 400
visible: active visible: active
@@ -103,12 +103,12 @@ ColumnLayout {
Layout.bottomMargin: Tokens.padding.large * 2 Layout.bottomMargin: Tokens.padding.large * 2
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: Tokens.spacing.small Layout.topMargin: Tokens.spacing.smaller
active: root.rootHeight > 820 active: root.rootHeight > 820
visible: active visible: active
sourceComponent: RowLayout { sourceComponent: RowLayout {
spacing: Tokens.spacing.largeIncreased spacing: Tokens.spacing.large
Repeater { Repeater {
model: { model: {
+70
View File
@@ -0,0 +1,70 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Components
import ZShell.Config
Singleton {
id: root
property list<var> apps: {
var map = new Map();
const pinnedApps = Config.dock?.pinnedApps ?? [];
for (const appId of pinnedApps) {
if (!map.has(appId.toLowerCase()))
map.set(appId.toLowerCase(), ({
pinned: true,
toplevels: []
}));
}
if (pinnedApps.length > 0) {
map.set("SEPARATOR", {
pinned: false,
toplevels: []
});
}
var values = [];
for (const [key, value] of map) {
values.push(appEntryComp.createObject(null, {
appId: key,
toplevels: value.toplevels,
pinned: value.pinned
}));
}
return values;
}
function isPinned(appId) {
return Config.dock.pinnedApps.indexOf(appId) !== -1;
}
function togglePin(appId) {
if (root.isPinned(appId)) {
Config.dock.pinnedApps = Config.dock.pinnedApps.filter(id => id !== appId);
} else {
Config.dock.pinnedApps = Config.dock.pinnedApps.concat([appId]);
}
}
Component {
id: appEntryComp
TaskbarAppEntry {
}
}
component TaskbarAppEntry: QtObject {
id: wrapper
required property string appId
required property bool pinned
required property list<var> toplevels
}
}
+63
View File
@@ -0,0 +1,63 @@
// FetchPresets.qml
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
Singleton {
id: root
property var parsedPresets: ({})
readonly property var presets: parsedPresets
property bool ready: false
function accents(presetName, variantName) {
const variant = parsedPresets[presetName]?.variants?.[variantName];
return variant?.accents ?? [];
}
function defaultAccent(presetName, variantName) {
const variant = parsedPresets[presetName]?.variants?.[variantName];
return variant?.default_accent ?? "";
}
function modes(presetName, variantName) {
const variant = parsedPresets[presetName]?.variants?.[variantName];
return variant?.modes ?? [];
}
function presetNames() {
return Object.keys(parsedPresets);
}
function variantNames(presetName) {
const preset = parsedPresets[presetName];
if (!preset || !preset.variants)
return [];
return Object.keys(preset.variants);
}
Process {
command: ["zshell-cli", "scheme", "list-presets", "--json"]
running: true
stdout: StdioCollector {
onStreamFinished: {
try {
const parsed = JSON.parse(text);
root.parsedPresets = parsed.presets ?? {};
root.ready = true;
} catch (e) {
console.error("Failed to parse presets JSON:", e);
}
}
}
}
}
+2 -51
View File
@@ -1,8 +1,9 @@
pragma Singleton pragma Singleton
import QtQuick import ZShell.Config
import Quickshell import Quickshell
import Quickshell.Services.Notifications import Quickshell.Services.Notifications
import QtQuick
Singleton { Singleton {
id: root id: root
@@ -94,15 +95,6 @@ Singleton {
return Quickshell.iconPath(icon); return Quickshell.iconPath(icon);
} }
function getBatteryIcon(percentage: real, charging = false): string {
if (percentage === 1)
return charging ? "battery_charging_full" : "battery_full";
let level = Math.floor(percentage * 7);
if (charging && (level === 4 || level === 1))
level--;
return charging ? `battery_charging_${(level + 3) * 10}` : `battery_${level}_bar`;
}
function getBluetoothIcon(icon: string): string { function getBluetoothIcon(icon: string): string {
if (icon.includes("headset") || icon.includes("headphones")) if (icon.includes("headset") || icon.includes("headphones"))
return "headphones"; return "headphones";
@@ -176,32 +168,6 @@ Singleton {
return "chat"; return "chat";
} }
function getSpecialWsIcon(name: string): string {
name = name.toLowerCase().slice("special:".length);
if (name === "special")
return "star";
if (name === "communication")
return "forum";
if (name === "music")
return "music_cast";
if (name === "todo")
return "checklist";
if (name === "sysmon")
return "monitor_heart";
return name[0].toUpperCase();
}
function getTrayIcon(id: string, icon: string): string {
if (icon.includes("?path=")) {
const [name, path] = icon.split("?path=");
const file = name.slice(name.lastIndexOf("/") + 1);
const themed = Quickshell.iconPath(file, true);
icon = themed ? themed : Qt.resolvedUrl(`${path}/${file}`);
}
return icon;
}
function getVolumeIcon(volume: real, isMuted: bool): string { function getVolumeIcon(volume: real, isMuted: bool): string {
if (isMuted) if (isMuted)
return "no_sound"; return "no_sound";
@@ -217,19 +183,4 @@ Singleton {
return weatherIcons[code]; return weatherIcons[code];
return "air"; return "air";
} }
function matchIconConfig(name: string, iconConfig: var): bool {
if (!iconConfig.icon)
return false;
if (iconConfig.regex) {
const re = new RegExp(iconConfig.regex, iconConfig.flags ?? "");
if (re.test(name))
return true;
} else if (iconConfig.name === name) {
return true;
}
return false;
}
} }
+1 -1
View File
@@ -391,7 +391,7 @@ Item {
tool: root.tool tool: root.tool
visible: root.mode === "edit" visible: root.mode === "edit"
x: Math.max(8, Math.min(root.rsx + root.sw / 2 - width / 2, root.screen.width - width - 8)) x: Math.max(8, Math.min(root.rsx + root.sw / 2 - width / 2, root.screen.width - width - 8))
y: (root.rsy + root.sh + height + Tokens.padding.small <= root.screen.height) ? root.rsy + root.sh + Tokens.padding.small : (root.rsy - height - Tokens.padding.small <= 0) ? root.rsy + root.sh - height - Tokens.padding.small : root.rsy - height - Tokens.padding.small y: (root.rsy + root.sh + height + Tokens.padding.normal <= root.screen.height) ? root.rsy + root.sh + Tokens.padding.normal : (root.rsy - height - Tokens.padding.normal <= 0) ? root.rsy + root.sh - height - Tokens.padding.normal : root.rsy - height - Tokens.padding.normal
onCancelRequested: root.cancel() onCancelRequested: root.cancel()
onClearRequested: annotations.clearAll() onClearRequested: annotations.clearAll()
+4 -10
View File
@@ -49,9 +49,9 @@ CustomRect {
signal undoRequested signal undoRequested
color: Colors.palette.m3surface color: Colors.palette.m3surface
height: row.implicitHeight + Tokens.padding.small * 2 height: row.implicitHeight + Tokens.padding.normal * 2
radius: Tokens.rounding.full radius: Tokens.rounding.full
width: row.implicitWidth + Tokens.padding.small * 2 width: row.implicitWidth + Tokens.padding.normal * 2
RowLayout { RowLayout {
id: row id: row
@@ -73,7 +73,6 @@ CustomRect {
required property var modelData required property var modelData
color: root.tool === modelData.id ? "#3584e4" : "transparent" color: root.tool === modelData.id ? "#3584e4" : "transparent"
font.pointSize: Tokens.font.size.large
icon: tool.modelData.glyph icon: tool.modelData.glyph
inactiveColor: root.tool === modelData.id ? Colors.palette.m3primary : "transparent" inactiveColor: root.tool === modelData.id ? Colors.palette.m3primary : "transparent"
inactiveOnColor: root.tool === modelData.id ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface inactiveOnColor: root.tool === modelData.id ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
@@ -99,11 +98,11 @@ CustomRect {
model: root.colorPalette model: root.colorPalette
delegate: IconButton { delegate: IconButton {
readonly property real buttonSize: toolRow.implicitHeight - Tokens.padding.small readonly property real buttonSize: toolRow.implicitHeight - Tokens.padding.normal
required property color modelData required property color modelData
fillWidth: false fillWidth: false
font.pointSize: Tokens.font.size.large font.pointSize: 0
icon: "" icon: ""
implicitHeight: buttonSize implicitHeight: buttonSize
implicitWidth: buttonSize implicitWidth: buttonSize
@@ -128,7 +127,6 @@ CustomRect {
spacing: Tokens.spacing.extraSmall spacing: Tokens.spacing.extraSmall
IconButton { IconButton {
font.pointSize: Tokens.font.size.large
icon: "undo" icon: "undo"
inactiveColor: "transparent" inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface inactiveOnColor: Colors.palette.m3onSurface
@@ -140,7 +138,6 @@ CustomRect {
} }
IconButton { IconButton {
font.pointSize: Tokens.font.size.large
icon: "delete_history" icon: "delete_history"
inactiveColor: "transparent" inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface inactiveOnColor: Colors.palette.m3onSurface
@@ -152,7 +149,6 @@ CustomRect {
} }
IconButton { IconButton {
font.pointSize: Tokens.font.size.large
icon: "content_copy" icon: "content_copy"
inactiveColor: "transparent" inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface inactiveOnColor: Colors.palette.m3onSurface
@@ -164,7 +160,6 @@ CustomRect {
} }
IconButton { IconButton {
font.pointSize: Tokens.font.size.large
icon: "delete_forever" icon: "delete_forever"
inactiveColor: "transparent" inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface inactiveOnColor: Colors.palette.m3onSurface
@@ -176,7 +171,6 @@ CustomRect {
} }
IconButton { IconButton {
font.pointSize: Tokens.font.size.large
icon: "check" icon: "check"
inactiveColor: "transparent" inactiveColor: "transparent"
inactiveOnColor: Colors.palette.m3onSurface inactiveOnColor: Colors.palette.m3onSurface
+1
View File
@@ -73,6 +73,7 @@ Singleton {
Config.dock.pinnedApps = pinnedApps; Config.dock.pinnedApps = pinnedApps;
root.unpinnedOrder = visibleUnpinned.concat(root.unpinnedOrder.map(normalizeId).filter(id => !pinnedApps.includes(id) && !visibleUnpinned.includes(id))); root.unpinnedOrder = visibleUnpinned.concat(root.unpinnedOrder.map(normalizeId).filter(id => !pinnedApps.includes(id) && !visibleUnpinned.includes(id)));
Config.saveNoToast();
} }
function isPinned(appId) { function isPinned(appId) {
+41 -8
View File
@@ -11,8 +11,8 @@ Singleton {
id: root id: root
property int availableUpdates: 0 property int availableUpdates: 0
property string cmd: ""
property bool commandReady property bool commandReady
property bool hasHelper
property bool loaded property bool loaded
property double now: Date.now() property double now: Date.now()
property var updates: ({}) property var updates: ({})
@@ -38,12 +38,18 @@ Singleton {
} }
function performPackageUpdate(pkg: string): void { function performPackageUpdate(pkg: string): void {
pkgUpdateProc.command = ["pkexec", "pacman", "--noconfirm", "-Sy", pkg]; if (root.cmd === "pacman")
pkgUpdateProc.command = ["pkexec", root.cmd, "--noconfirm", "-Sy", pkg];
else
pkgUpdateProc.command = [root.cmd, "--noconfirm", "--sudo", "pkexec", "-Sy", pkg];
pkgUpdateProc.running = true; pkgUpdateProc.running = true;
} }
function performSystemUpdate(): void { function performSystemUpdate(): void {
sysUpdateProc.command = ["pkexec", "pacman", "--noconfirm", "-Syu"]; if (root.cmd === "pacman")
sysUpdateProc.command = ["pkexec", root.cmd, "--noconfirm", "-Syu"];
else
sysUpdateProc.command = [root.cmd, "--noconfirm", "--sudo", "pkexec", "-Syu"];
sysUpdateProc.running = true; sysUpdateProc.running = true;
} }
@@ -81,7 +87,7 @@ Singleton {
Process { Process {
id: cmdDetect id: cmdDetect
command: ["sh", "-c", "command -v checkupdates"] command: ["sh", "-c", "command -v checkupdates || command -v yay || command -v paru"]
running: true running: true
stdout: StdioCollector { stdout: StdioCollector {
@@ -90,20 +96,47 @@ Singleton {
let helper; let helper;
if (cmd.length > 0) { if (cmd.length > 0) {
helper = true; helper = cmd.split("/").pop();
} else { } else {
helper = false; helper = "pacman";
}
if (helper === "checkupdates") {
updatesProc.command = [helper];
} else {
updatesProc.command = [helper, "-Qu"];
} }
root.hasHelper = helper;
root.commandReady = true; root.commandReady = true;
} }
} }
} }
Process {
id: updateCmdDetect
command: ["sh", "-c", "command -v yay || command -v paru"]
running: true
stdout: StdioCollector {
onStreamFinished: {
const cmd = this.text.trim();
let helper;
if (cmd.length > 0) {
helper = cmd.split("/").pop();
} else {
helper = "pacman";
}
root.cmd = helper;
}
}
}
Process { Process {
id: updatesProc id: updatesProc
command: root.hasHelper ? ["checkupdates"] : [] command: []
running: false running: false
stdout: StdioCollector { stdout: StdioCollector {
+1 -4
View File
@@ -17,10 +17,7 @@ Singleton {
watchChanges: true watchChanges: true
onAdapterUpdated: writeAdapter() onAdapterUpdated: writeAdapter()
onFileChanged: { onFileChanged: reload()
reload();
Wallpapers.previewColorLock = false;
}
JsonAdapter { JsonAdapter {
id: adapter id: adapter
+6 -28
View File
@@ -6,7 +6,7 @@ import Quickshell.Io
import QtQuick import QtQuick
import ZShell.Models import ZShell.Models
import ZShell.Config import ZShell.Config
import qs.Services import qs.Modules
import qs.Helpers import qs.Helpers
import qs.Paths import qs.Paths
@@ -17,8 +17,6 @@ Searcher {
property alias crops: adapter.monitorCrops property alias crops: adapter.monitorCrops
readonly property string current: showPreview ? previewPath : actualCurrent readonly property string current: showPreview ? previewPath : actualCurrent
property alias monitorCrops: monitorCrops property alias monitorCrops: monitorCrops
property bool pendingPreviewClear
property bool previewColorLock
property string previewPath property string previewPath
property bool recentlyChanged property bool recentlyChanged
property bool showPreview: false property bool showPreview: false
@@ -36,10 +34,9 @@ Searcher {
function preview(path: string): void { function preview(path: string): void {
previewPath = path; previewPath = path;
showPreview = true;
if (Config.general.color.schemeGeneration) if (Config.general.color.schemeGeneration)
previewColorsProc.running = true; Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${previewPath}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.general.color.mode}`]);
showPreview = true;
} }
function setCrop(screen: string, rect: rect, zoom: real): void { function setCrop(screen: string, rect: rect, zoom: real): void {
@@ -55,6 +52,7 @@ Searcher {
height: rect.height, height: rect.height,
zoom: zoom zoom: zoom
}; };
// root.crops = updated;
} }
function setWallpaper(path: string): void { function setWallpaper(path: string): void {
@@ -68,10 +66,8 @@ Searcher {
function stopPreview(): void { function stopPreview(): void {
showPreview = false; showPreview = false;
if (previewColorLock) if (Config.general.color.schemeGeneration)
pendingPreviewClear = true; Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${root.actualCurrent}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.general.color.mode}`]);
else
Colors.showPreview = false;
} }
extraOpts: useFuzzy ? ({}) : ({ extraOpts: useFuzzy ? ({}) : ({
@@ -81,11 +77,6 @@ Searcher {
list: wallpapers.entries list: wallpapers.entries
useFuzzy: true useFuzzy: true
onPreviewColorLockChanged: {
if (!previewColorLock && pendingPreviewClear)
Colors.showPreview = false;
}
IpcHandler { IpcHandler {
function set(path: string): void { function set(path: string): void {
root.setWallpaper(path); root.setWallpaper(path);
@@ -127,17 +118,4 @@ Searcher {
path: Config.general.wallpaperPath path: Config.general.wallpaperPath
recursive: true recursive: true
} }
Process {
id: previewColorsProc
command: ["zshell-cli", "scheme", "generate", "-p", "-i", root.previewPath]
stdout: StdioCollector {
onStreamFinished: {
Colors.load(text, true);
Colors.showPreview = true;
}
}
}
} }
+31 -52
View File
@@ -3,29 +3,24 @@ pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import qs.Modules
import ZShell.Config import ZShell.Config
import qs.Modules.Bar.Components import qs.Modules.SysTray
import qs.Modules.Bar.Popouts import qs.Modules.Network
import qs.Modules.Updates
GridLayout { RowLayout {
id: root id: root
required property bool fullscreen required property bool fullscreen
required property bool horizontal
required property bool isHovered
required property Wrapper popouts required property Wrapper popouts
required property ClipWrapper popoutsWrapper required property ClipWrapper popoutsWrapper
required property ShellScreen screen required property ShellScreen screen
readonly property int vPadding: 6 readonly property int vPadding: 6
required property PersistentProperties visibilities required property PersistentProperties visibilities
function axisCenterOf(item: Item): real { function checkPopout(x: real): void {
const c = item.mapToItem(root, item.implicitWidth / 2, item.implicitHeight / 2); const ch = childAt(x, height / 2) as EntryWrapper;
return horizontal ? c.x : c.y;
}
function checkPopout(pos: real): void {
const ch = (horizontal ? childAt(pos, height / 2) : childAt(width / 2, pos)) as EntryWrapper;
const id = ch?.entryId; const id = ch?.entryId;
if (!ch || id === undefined) { if (!ch || id === undefined) {
@@ -39,21 +34,26 @@ GridLayout {
if (id === "statusIcons" && Config.bar.popouts.statusIcons) { if (id === "statusIcons" && Config.bar.popouts.statusIcons) {
const items = (ch.item as StatusIcons).items; const items = (ch.item as StatusIcons).items;
const icon = horizontal ? items.childAt(mapToItem(items, pos, 0).x, items.height / 2) : items.childAt(items.width / 2, mapToItem(items, 0, pos).y); const localX = mapToItem(items, x, 0).x;
const icon = items.childAt(localX, items.height / 2);
if (icon) { if (icon) {
popouts.currentName = icon.name; popouts.currentName = icon.name;
popouts.currentCenter = Qt.binding(() => axisCenterOf(icon)); popouts.currentCenter = Qt.binding(() => icon.mapToItem(root, icon.implicitWidth / 2, 0).x);
popouts.hasCurrent = true; popouts.hasCurrent = true;
} }
} else if (id === "tray" && Config.bar.popouts.tray && Config.bar.tray.showOnHover) { } else if (id === "tray" && Config.bar.popouts.tray && Config.bar.tray.showOnHover) {
const tray = ch.item as TrayIcons; const tray = ch.item as TrayIcons;
const layout = tray.layout; const layout = tray.layout;
const trayItem = horizontal ? layout.childAt(mapToItem(layout, pos, 0).x, layout.height / 2) : layout.childAt(tray.width / 2, mapToItem(layout, 0, pos).y); const localX = mapToItem(layout, x, 0).x;
const trayItem = layout.childAt(localX, layout.height / 2);
if (trayItem) { if (trayItem) {
const idx = trayItem.index; const idx = trayItem.index;
popouts.currentName = `traymenu${idx}`; popouts.currentName = `traymenu${idx}`;
popouts.currentCenter = Qt.binding(() => axisCenterOf(trayItem)); popouts.currentCenter = Qt.binding(() => {
const it = tray.items.itemAt(idx);
return it ? it.mapToItem(root, it.implicitWidth / 2, 0).x : popouts.currentCenter;
});
popouts.hasCurrent = true; popouts.hasCurrent = true;
} }
@@ -63,19 +63,12 @@ GridLayout {
if (id === "updates") { if (id === "updates") {
popouts.currentName = "updates"; popouts.currentName = "updates";
popouts.currentCenter = Qt.binding(() => axisCenterOf(ch.item as Item)); popouts.currentCenter = Qt.binding(() => ch.item.mapToItem(root, (ch.item as Item).implicitWidth / 2, 0).x);
popouts.hasCurrent = true; popouts.hasCurrent = true;
} }
} }
function entryAt(pos: real): string { spacing: Tokens.spacing.small
const ch = (horizontal ? childAt(pos, height / 2) : childAt(width / 2, pos)) as EntryWrapper;
return ch?.entryId ?? "";
}
columnSpacing: Tokens.spacing.small
columns: horizontal ? -1 : 1
rowSpacing: Tokens.spacing.small
Repeater { Repeater {
id: repeater id: repeater
@@ -92,8 +85,7 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
HyprsunsetWidget { HyprsunsetWidget {
horizontal: root.horizontal visible: !root.fullscreen
visible: !root.fullscreen || root.isHovered
} }
} }
} }
@@ -102,8 +94,7 @@ GridLayout {
roleValue: "spacer" roleValue: "spacer"
delegate: EntryWrapper { delegate: EntryWrapper {
Layout.fillHeight: !root.horizontal Layout.fillWidth: true
Layout.fillWidth: root.horizontal
} }
} }
@@ -112,9 +103,8 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
Workspaces { Workspaces {
horizontal: root.horizontal
screen: root.screen screen: root.screen
visible: !root.fullscreen || root.isHovered visible: !root.fullscreen
} }
} }
} }
@@ -124,10 +114,9 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
TrayIcons { TrayIcons {
horizontal: root.horizontal
loader: root loader: root
popouts: root.popouts popouts: root.popouts
visible: !root.fullscreen || root.isHovered visible: !root.fullscreen
} }
} }
} }
@@ -137,8 +126,6 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
StatusIcons { StatusIcons {
horizontal: root.horizontal
visible: !root.fullscreen || root.isHovered
} }
} }
} }
@@ -148,9 +135,8 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
Resources { Resources {
horizontal: root.horizontal
visibilities: root.visibilities visibilities: root.visibilities
visible: !root.fullscreen || root.isHovered visible: !root.fullscreen
} }
} }
} }
@@ -160,8 +146,7 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
UpdatesWidget { UpdatesWidget {
horizontal: root.horizontal visible: !root.fullscreen
visible: !root.fullscreen || root.isHovered
} }
} }
} }
@@ -171,10 +156,9 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
NotifBell { NotifBell {
horizontal: root.horizontal
popouts: root.popouts popouts: root.popouts
visibilities: root.visibilities visibilities: root.visibilities
visible: !root.fullscreen || root.isHovered visible: !root.fullscreen
} }
} }
} }
@@ -184,11 +168,10 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
Clock { Clock {
horizontal: root.horizontal
loader: root loader: root
popouts: root.popouts popouts: root.popouts
visibilities: root.visibilities visibilities: root.visibilities
visible: !root.fullscreen || root.isHovered visible: !root.fullscreen
} }
} }
} }
@@ -199,8 +182,7 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
WindowTitle { WindowTitle {
bar: root bar: root
horizontal: root.horizontal visible: !root.fullscreen
visible: !root.fullscreen || root.isHovered
} }
} }
} }
@@ -219,8 +201,7 @@ GridLayout {
delegate: EntryWrapper { delegate: EntryWrapper {
MediaWidget { MediaWidget {
horizontal: root.horizontal visible: !root.fullscreen
visible: !root.fullscreen || root.isHovered
} }
} }
} }
@@ -233,11 +214,9 @@ GridLayout {
default property Item item default property Item item
required property var modelData required property var modelData
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter Layout.alignment: Qt.AlignVCenter
Layout.bottomMargin: !root.horizontal && index === repeater.count - 1 ? root.vPadding : 0 Layout.leftMargin: index === 0 ? root.vPadding : (entryId === "statusIcons") ? -root.spacing + Tokens.spacing.extraSmall : 0
Layout.leftMargin: root.horizontal && index === 0 ? root.vPadding : (entryId === "statusIcons" && root.horizontal) ? -root.rowSpacing + Tokens.spacing.extraSmall : 0 Layout.rightMargin: index === repeater.count - 1 ? root.vPadding : 0
Layout.rightMargin: root.horizontal && index === repeater.count - 1 ? root.vPadding : 0
Layout.topMargin: !root.horizontal && index === 0 ? root.vPadding : (entryId === "statusIcons" && !root.horizontal) ? -root.columnSpacing + Tokens.spacing.extraSmall : 0
children: item children: item
implicitHeight: item?.implicitHeight ?? 0 implicitHeight: item?.implicitHeight ?? 0
implicitWidth: item?.implicitWidth ?? 0 implicitWidth: item?.implicitWidth ?? 0
+22 -30
View File
@@ -1,48 +1,45 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import Quickshell.Hyprland
import QtQuick import QtQuick
import ZShell.Config import QtQuick.Layouts
import qs.Modules.Bar.Popouts
import qs.Components import qs.Components
import qs.Modules
import ZShell.Config
import qs.Helpers
import qs.Modules.SysTray
import qs.Modules.SysTray.Widgets
import qs.Modules.Network
Item { Item {
id: root id: root
readonly property int clampedExtent: Math.max(Config.bar.border, extent) readonly property int contentHeight: Config.bar.height + padding * 2
readonly property int contentThickness: Math.floor(Math.max(Config.bar.height, Tokens.bar.innerSize * (horizontal ? 1 : 1.5))) + padding * 2 readonly property int exclusiveZone: Config.bar.autoHide ? Config.bar.border : contentHeight
readonly property int exclusiveZone: Config.bar.autoHide ? Config.bar.border : contentThickness
property real extent: fullscreen ? 0 : Config.bar.border
required property bool fullscreen required property bool fullscreen
readonly property bool horizontal: position !== "left"
property bool isHovered property bool isHovered
readonly property int padding: Math.max(Tokens.padding.small, Config.bar.border) readonly property int padding: Math.max(Tokens.padding.smaller, Config.bar.border)
required property Wrapper popouts required property Wrapper popouts
required property ClipWrapper popoutsWrapper required property ClipWrapper popoutsWrapper
required property string position
required property ShellScreen screen required property ShellScreen screen
readonly property bool shouldBeVisible: (!fullscreen && (!Config.bar.autoHide || visibilities.bar)) || isHovered readonly property bool shouldBeVisible: !fullscreen && (!Config.bar.autoHide || visibilities.bar || isHovered)
readonly property int vPadding: 6 readonly property int vPadding: 6
required property PersistentProperties visibilities required property PersistentProperties visibilities
function checkPopout(pos: real): void { function checkPopout(x: real): void {
(content.item as Bar)?.checkPopout(pos); content.item?.checkPopout(x);
} }
function entryAt(pos: real): string { implicitHeight: fullscreen ? 0 : Config.bar.border
return (content.item as Bar)?.entryAt(pos) ?? ""; visible: height > Config.bar.border
}
implicitHeight: extent
implicitWidth: extent
visible: extent > Config.bar.border
states: State { states: State {
name: "visible" name: "visible"
when: root.shouldBeVisible when: root.shouldBeVisible
PropertyChanges { PropertyChanges {
root.extent: root.contentThickness root.implicitHeight: root.contentHeight
} }
} }
transitions: [ transitions: [
@@ -51,7 +48,7 @@ Item {
to: "visible" to: "visible"
Anim { Anim {
property: "extent" property: "implicitHeight"
target: root target: root
} }
}, },
@@ -60,7 +57,7 @@ Item {
to: "" to: ""
Anim { Anim {
property: "extent" property: "implicitHeight"
target: root target: root
} }
} }
@@ -70,18 +67,13 @@ Item {
id: content id: content
active: root.shouldBeVisible || root.visible active: root.shouldBeVisible || root.visible
anchors.bottom: root.position !== "bottom" ? parent.bottom : undefined anchors.bottom: parent.bottom
anchors.left: root.horizontal ? parent.left : undefined anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: root.position !== "top" ? parent.top : undefined
height: root.contentThickness
width: root.contentThickness
sourceComponent: Bar { sourceComponent: Bar {
fullscreen: root.fullscreen fullscreen: root.fullscreen
height: root.contentThickness height: root.contentHeight
horizontal: root.horizontal
isHovered: root.isHovered
popouts: root.popouts popouts: root.popouts
popoutsWrapper: root.popoutsWrapper popoutsWrapper: root.popoutsWrapper
screen: root.screen screen: root.screen
-157
View File
@@ -1,157 +0,0 @@
pragma ComponentBehavior: Bound
import Quickshell
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Modules.Bar.Popouts
import qs.Modules.Bar.Components.Common
import qs.Helpers
import qs.Components
import qs.Services
WidgetBase {
id: root
readonly property color contentColor: visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
readonly property string effectiveFormat: {
let fmt = Config.general.dateFormat;
if (!root.horizontal)
fmt = fmt.replace("dddd", "ddd");
return fmt;
}
readonly property var formatParts: {
const segments = root.effectiveFormat.split(" - ");
let datePart = "";
let timePart = "";
if (segments.length > 1) {
datePart = segments[0];
timePart = segments[1];
} else if (/[hms]/.test(segments[0])) {
timePart = segments[0];
} else {
datePart = segments[0];
}
const dateTokens = datePart.trim().length ? datePart.trim().split(/\s+/) : [];
const timeTokens = timePart.trim().length ? timePart.trim().split(":") : [];
return {
dateTokens: dateTokens,
timeTokens: timeTokens
};
}
required property GridLayout loader
required property Wrapper popouts
readonly property real size: horizontal ? timeText.contentWidth + Tokens.padding.small * 2 : verticalColumn.implicitHeight + Tokens.padding.small * 2
required property PersistentProperties visibilities
color: visibilities.dashboard ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
implicitHeight: horizontal ? baseSize : size
implicitWidth: horizontal ? size : baseSize
radius: Tokens.rounding.full
CustomText {
id: timeText
anchors.centerIn: parent
color: root.contentColor
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
height: implicitHeight
text: Time.dateStr
visible: root.horizontal
Behavior on color {
CAnim {
}
}
}
ColumnLayout {
id: verticalColumn
anchors.centerIn: parent
spacing: Tokens.padding.extraSmall ?? 2
visible: !root.horizontal
width: root.baseSize
Repeater {
model: root.formatParts.dateTokens
CustomText {
required property string modelData
Layout.alignment: Qt.AlignHCenter
color: root.contentColor
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
text: Qt.formatDateTime(Time.date, modelData)
Behavior on color {
CAnim {
}
}
}
}
Rectangle {
Layout.alignment: Qt.AlignHCenter
Layout.bottomMargin: Tokens.padding.extraSmall ?? 2
Layout.topMargin: Tokens.padding.extraSmall ?? 2
color: root.contentColor
height: 1
implicitWidth: root.baseSize * 0.5
opacity: 0.4
radius: 1
visible: root.formatParts.dateTokens.length > 0 && root.formatParts.timeTokens.length > 0
}
Repeater {
model: root.formatParts.timeTokens
CustomText {
required property string modelData
Layout.alignment: Qt.AlignHCenter
color: root.contentColor
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
text: {
if (modelData.includes("h"))
return Time.hourStr;
if (modelData.includes("m"))
return Time.minuteStr;
if (modelData.includes("s"))
return Time.secondStr;
return "";
}
Behavior on color {
CAnim {
}
}
}
}
CustomText {
Layout.alignment: Qt.AlignHCenter
color: root.contentColor
font.family: Config.appearance.font.family.mono // qmllint disable incompatible-type
text: Qt.formatDateTime(Time.date, "AP")
visible: Config.services.useTwelveHourClock && root.formatParts.timeTokens.length > 0
Behavior on color {
CAnim {
}
}
}
}
StateLayer {
acceptedButtons: Qt.LeftButton
color: root.contentColor
onClicked: {
root.visibilities.dashboard = !root.visibilities.dashboard;
}
}
}
@@ -1,16 +0,0 @@
import QtQuick
import ZShell.Config
import qs.Components
import qs.Services
CustomRect {
id: root
readonly property int baseSize: horizontal ? Math.max(Config.bar.height, Tokens.bar.innerSize) : Math.max(Config.bar.height, Math.floor(Tokens.bar.innerSize * 1.5))
required property bool horizontal
color: Colors.tPalette.m3surfaceContainer
implicitHeight: horizontal ? baseSize : width
implicitWidth: horizontal ? height : baseSize
radius: Tokens.rounding.full
}
-92
View File
@@ -1,92 +0,0 @@
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Components
import qs.Modules.Bar.Components.Common
import qs.Helpers
import qs.Services
WidgetBase {
id: root
readonly property string currentMedia: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
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
radius: Tokens.rounding.full
Behavior on implicitHeight {
enabled: !root.horizontal
Anim {
}
}
Behavior on implicitWidth {
enabled: root.horizontal
Anim {
}
}
TextMetrics {
id: metrics
font: mediatext.font
text: mediatext.text
}
GridLayout {
id: layout
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.small
anchors.fill: parent
anchors.leftMargin: root.horizontal ? Tokens.padding.small : 0
anchors.rightMargin: root.horizontal ? Tokens.padding.small : 0
anchors.topMargin: root.horizontal ? 0 : Tokens.padding.small
columns: root.horizontal ? -1 : 1
Behavior on implicitWidth {
Anim {
}
}
MaterialIcon {
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
animate: true
color: Players.active?.isPlaying ? Colors.palette.m3primary : Colors.palette.m3onSurface
font.pointSize: Tokens.font.size.larger
text: Players.active?.isPlaying ? "music_note" : "music_off"
}
MarqueeText {
id: mediatext
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
animate: true
color: Players.active?.isPlaying ? Colors.palette.m3primary : Colors.palette.m3onSurface
font.pointSize: Tokens.font.size.normal
horizontalAlignment: Text.AlignHCenter
implicitHeight: root.horizontal ? root.implicitHeight : root.textWidth
implicitWidth: root.horizontal ? root.textWidth : root.implicitWidth
marqueeEnabled: false
pauseMs: 4000
text: root.currentMedia
vertical: !root.horizontal
}
}
CustomMouseArea {
anchors.fill: parent
hoverEnabled: true
onContainsMouseChanged: {
if (!containsMouse) {
mediatext.marqueeEnabled = false;
} else {
mediatext.marqueeEnabled = true;
mediatext.anim.start();
}
}
}
}
-63
View File
@@ -1,63 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Layouts
import Quickshell.Services.SystemTray
import ZShell.Config
import qs.Components
import qs.Modules.Bar.Components.Common
import qs.Modules.Bar.Components.Tray
import qs.Modules.Bar.Popouts
import qs.Services
WidgetBase {
id: root
readonly property alias items: repeater
readonly property alias layout: sysGrid
required property GridLayout loader
readonly property int padding: Tokens.padding.extraSmall
required property Wrapper popouts
readonly property real size: horizontal ? sysGrid.implicitWidth + sysGrid.anchors.leftMargin + sysGrid.anchors.rightMargin : sysGrid.implicitHeight + sysGrid.anchors.topMargin + sysGrid.anchors.bottomMargin
bottomLeftRadius: horizontal ? Tokens.rounding.full : Tokens.rounding.small / 2
bottomRightRadius: Tokens.rounding.small / 2
color: Colors.tPalette.m3surfaceContainer
implicitHeight: horizontal ? baseSize : size
implicitWidth: horizontal ? size : baseSize
radius: Tokens.rounding.full
topRightRadius: horizontal ? Tokens.rounding.small / 2 : Tokens.rounding.full
GridLayout {
id: sysGrid
anchors.bottomMargin: root.horizontal ? 0 : Tokens.padding.extraSmall
anchors.centerIn: parent
anchors.leftMargin: root.horizontal ? Tokens.padding.extraSmall : 0
anchors.rightMargin: root.horizontal ? Tokens.padding.extraSmall : 0
anchors.topMargin: root.horizontal ? 0 : Tokens.padding.extraSmall
columns: root.horizontal ? -1 : 1
rowSpacing: -2
Repeater {
id: repeater
model: SystemTray.items
TrayItem {
id: trayItem
required property int index
required property SystemTrayItem modelData
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
implicitHeight: 34
implicitWidth: 34
ind: index
item: modelData
loader: root.loader
popouts: root.popouts
}
}
}
}
-41
View File
@@ -1,41 +0,0 @@
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Components
import qs.Modules.Bar.Components.Common
import qs.Helpers
import qs.Services
WidgetBase {
id: root
property int countUpdates: Updates.availableUpdates
property color textColor: Colors.palette.m3onSurface
color: Colors.tPalette.m3surfaceContainer
implicitHeight: horizontal ? baseSize : content.implicitHeight + Tokens.spacing.small
implicitWidth: horizontal ? content.implicitWidth + Tokens.spacing.small * 2 : baseSize
radius: Tokens.rounding.full
GridLayout {
id: content
anchors.centerIn: parent
columnSpacing: Tokens.spacing.small
columns: root.horizontal ? -1 : 1
rowSpacing: -Tokens.spacing.extraSmall / 2
MaterialIcon {
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
font.pointSize: root.horizontal ? Tokens.font.size.larger : Tokens.font.size.large
text: "package_2"
}
CustomText {
Layout.alignment: root.horizontal ? Qt.AlignVCenter : Qt.AlignHCenter
color: root.textColor
font.pointSize: Tokens.font.size.normal
text: root.countUpdates
}
}
}
-98
View File
@@ -1,98 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import ZShell.Config
import qs.Components
import qs.Helpers
import qs.Services
Item {
id: root
required property var bar
property color color: Colors.palette.m3primary
property Title current: text1
required property bool horizontal
// readonly property int maxWidth: 300
readonly property int maxSize: {
const otherModules = bar.children.filter(c => c.enabled && c.entryId && c.item !== this && c.entryId !== "spacer");
const otherSize = otherModules.reduce((acc, curr) => acc + (horizontal ? (curr.item?.nonAnimWidth ?? curr.width ?? 0) : (curr.item.nonAnimHeight ?? curr.height ?? 0)), 0);
return horizontal ? (bar.width - otherSize - bar.columnSpacing * (bar.children.length - 1) - bar.vPadding * 2) : (bar.height - otherSize - bar.rowSpacing * (bar.children.length - 1) - bar.vPadding * 4);
}
clip: true
implicitHeight: horizontal ? current.implicitHeight : current.implicitWidth + current.anchors.topMargin
implicitWidth: horizontal ? current.implicitWidth + current.anchors.leftMargin : current.implicitHeight + current.anchors.topMargin
Behavior on implicitHeight {
enabled: !root.horizontal
Anim {
type: Anim.DefaultEffects
}
}
Behavior on implicitWidth {
enabled: root.horizontal
Anim {
type: Anim.DefaultEffects
}
}
Title {
id: text1
}
Title {
id: text2
}
TextMetrics {
id: metrics
elide: Qt.ElideRight
elideWidth: root.maxSize - (root.horizontal ? root.current.anchors.leftMargin : 0)
font.family: "Rubik"
font.pointSize: Tokens.font.size.normal
text: Hypr.activeToplevel?.title ?? qsTr("Desktop")
onElideWidthChanged: root.current.text = elidedText
onTextChanged: {
const next = root.current === text1 ? text2 : text1;
next.text = elidedText;
root.current = next;
}
}
component Title: CustomText {
id: text
anchors.horizontalCenter: root.horizontal ? undefined : parent.horizontalCenter
anchors.left: root.horizontal ? parent.left : undefined
anchors.leftMargin: root.horizontal ? Tokens.spacing.small : 0
anchors.top: root.horizontal ? undefined : parent.top
anchors.topMargin: root.horizontal ? 0 : Tokens.spacing.small
anchors.verticalCenter: root.horizontal ? parent.verticalCenter : undefined
color: root.color
font.family: metrics.font.family
font.pointSize: metrics.font.pointSize
height: root.horizontal ? implicitHeight : implicitWidth
opacity: root.current === this ? 1 : 0
width: root.horizontal ? implicitWidth : implicitHeight
Behavior on opacity {
Anim {
}
}
transform: [
Translate {
x: !root.horizontal ? -text.implicitWidth + text.implicitHeight : 0
},
Rotation {
angle: root.horizontal ? 0 : 270
origin.x: text.implicitHeight / 2
origin.y: text.implicitHeight / 2
}
]
}
}
-88
View File
@@ -1,88 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.Components
import ZShell.Config
Item {
id: root
required property real borderThickness
readonly property alias content: content
readonly property bool horizontal: position !== "left"
// property real offsetScale: y > 0 || content.hasCurrent ? 0 : 1
property real offsetScale: {
if (content.hasCurrent)
return 0;
if (position === "top")
return y > 0 ? 0 : 1;
if (position === "bottom")
return 1;
return x > 0 ? 0 : 1;
}
required property string position
required property ShellScreen screen
anchors.bottom: position === "bottom" ? parent.bottom : undefined
clip: true
implicitHeight: horizontal ? content.implicitHeight * (1 - offsetScale) : content.implicitHeight
implicitWidth: horizontal ? content.implicitWidth : content.implicitWidth * (1 - offsetScale)
visible: width > 0 && height > 0
x: {
if (!horizontal)
return 0;
const off = content.currentCenter - borderThickness - content.nonAnimWidth / 2;
const diff = parent.width - Math.floor(off + content.nonAnimWidth);
if (diff < 0)
return off + diff;
return Math.floor(Math.max(off, 0));
}
y: {
if (horizontal)
return 0;
const off = content.currentCenter - borderThickness - content.nonAnimHeight / 2;
const diff = parent.height - Math.floor(off + content.nonAnimHeight);
if (diff < 0)
return off + diff;
return Math.max(off, 0);
}
Behavior on offsetScale {
Anim {
}
}
Behavior on x {
enabled: !root.horizontal || root.offsetScale < 1
Anim {
duration: content.animLength
easing: content.animCurve
}
}
Behavior on y {
enabled: root.horizontal || root.offsetScale < 1
Anim {
duration: content.animLength
easing: content.animCurve
}
}
Wrapper {
id: content
anchors.bottom: root.position === "bottom" ? parent.bottom : undefined
anchors.bottomMargin: (-implicitHeight - 5) * root.offsetScale
anchors.horizontalCenter: root.horizontal ? parent.horizontalCenter : undefined
anchors.left: root.horizontal ? undefined : parent.left
anchors.leftMargin: (-implicitWidth - 5) * root.offsetScale
anchors.top: root.position === "top" ? parent.top : undefined
anchors.topMargin: (-implicitHeight - 5) * root.offsetScale
anchors.verticalCenter: root.horizontal ? undefined : parent.verticalCenter
horizontal: root.horizontal
offsetScale: root.offsetScale
screen: root.screen
}
}
+56
View File
@@ -0,0 +1,56 @@
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import qs.Components
import ZShell.Config
Item {
id: root
required property real borderThickness
readonly property alias content: content
property real offsetScale: y > 0 || content.hasCurrent ? 0 : 1
required property ShellScreen screen
clip: true
implicitHeight: content.implicitHeight * (1 - offsetScale)
implicitWidth: content.implicitWidth
visible: width > 0 && height > 0
x: {
const off = content.currentCenter - borderThickness - content.nonAnimWidth / 2;
const diff = parent.width - Math.floor(off + content.nonAnimWidth);
if (diff < 0)
return off + diff;
return Math.floor(Math.max(off, 0));
}
Behavior on offsetScale {
Anim {
}
}
Behavior on x {
enabled: root.offsetScale < 1
Anim {
duration: content.animLength
easing.bezierCurve: content.animCurve
}
}
Behavior on y {
Anim {
duration: content.animLength
easing.bezierCurve: content.animCurve
}
}
Wrapper {
id: content
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: (-implicitHeight - 5) * root.offsetScale
offsetScale: root.offsetScale
screen: root.screen
}
}
+9 -9
View File
@@ -59,7 +59,7 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: entries.right anchors.left: entries.right
anchors.leftMargin: Tokens.spacing.medium anchors.leftMargin: Tokens.spacing.normal
anchors.top: parent.top anchors.top: parent.top
color: Colors.tPalette.m3surfaceContainer 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) 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)
@@ -75,7 +75,7 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 0 anchors.leftMargin: 0
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.normal
anchors.top: parent.top anchors.top: parent.top
visible: !ClipHistory.previewIsImage visible: !ClipHistory.previewIsImage
@@ -90,7 +90,7 @@ Item {
required property int index required property int index
required property var modelData required property var modelData
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
CustomRect { CustomRect {
color: lineRow.index % 2 ? Colors.tPalette.m3surfaceContainer : "transparent" color: lineRow.index % 2 ? Colors.tPalette.m3surfaceContainer : "transparent"
@@ -192,7 +192,7 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.top: search.bottom anchors.top: search.bottom
anchors.topMargin: Tokens.spacing.medium anchors.topMargin: Tokens.spacing.normal
implicitWidth: Config.clipboard.sizes.width implicitWidth: Config.clipboard.sizes.width
CustomListView { CustomListView {
@@ -204,7 +204,7 @@ Item {
highlightRangeMode: ListView.ApplyRange highlightRangeMode: ListView.ApplyRange
preferredHighlightBegin: 0 preferredHighlightBegin: 0
preferredHighlightEnd: height preferredHighlightEnd: height
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
CustomScrollBar.vertical: CustomScrollBar { CustomScrollBar.vertical: CustomScrollBar {
flickable: view flickable: view
@@ -250,7 +250,7 @@ Item {
id: icon id: icon
anchors.left: parent.left anchors.left: parent.left
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
font.pointSize: Tokens.font.size.large font.pointSize: Tokens.font.size.large
text: clipItem.isImage ? "image" : "text_fields" text: clipItem.isImage ? "image" : "text_fields"
@@ -260,7 +260,7 @@ Item {
id: text id: text
anchors.left: icon.right anchors.left: icon.right
anchors.margins: Tokens.spacing.medium anchors.margins: Tokens.spacing.normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
elide: Text.ElideRight elide: Text.ElideRight
text: clipItem.isImage ? qsTr("Image") : ClipHistory.displayText(clipItem.modelData) text: clipItem.isImage ? qsTr("Image") : ClipHistory.displayText(clipItem.modelData)
@@ -292,7 +292,7 @@ Item {
IconButton { IconButton {
Layout.fillHeight: true Layout.fillHeight: true
Layout.margins: Tokens.padding.small Layout.margins: Tokens.padding.normal
Layout.preferredWidth: height Layout.preferredWidth: height
icon: "delete" icon: "delete"
inactiveColor: Qt.alpha(Colors.palette.m3error, 0.8) inactiveColor: Qt.alpha(Colors.palette.m3error, 0.8)
@@ -320,7 +320,7 @@ Item {
Behavior on y { Behavior on y {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
} }
+3 -3
View File
@@ -15,15 +15,15 @@ Item {
required property PersistentProperties visibilities required property PersistentProperties visibilities
anchors.bottomMargin: (-implicitHeight - 5) * offsetScale anchors.bottomMargin: (-implicitHeight - 5) * offsetScale
implicitHeight: content.implicitHeight + Tokens.padding.small * 2 implicitHeight: content.implicitHeight + Tokens.padding.normal * 2
implicitWidth: content.implicitWidth + Tokens.padding.small * 2 || 400 implicitWidth: content.implicitWidth + Tokens.padding.normal * 2 || 400
opacity: 1 - offsetScale opacity: 1 - offsetScale
visible: offsetScale < 1 visible: offsetScale < 1
Behavior on offsetScale { Behavior on offsetScale {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
} }
} }
+44
View File
@@ -0,0 +1,44 @@
import Quickshell
import QtQuick
import QtQuick.Layouts
import ZShell.Config
import qs.Modules
import qs.Helpers
import qs.Components
import qs.Services
CustomRect {
id: root
required property RowLayout loader
required property Wrapper popouts
required property PersistentProperties visibilities
color: visibilities.dashboard ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
implicitWidth: timeText.contentWidth + Tokens.padding.normal * 2
radius: Tokens.rounding.full
CustomText {
id: timeText
anchors.centerIn: parent
color: root.visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
font: Config.appearance.font.family.mono
text: Time.dateStr
Behavior on color {
CAnim {
}
}
}
StateLayer {
acceptedButtons: Qt.LeftButton
color: root.visibilities.dashboard ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
onClicked: {
root.visibilities.dashboard = !root.visibilities.dashboard;
}
}
}
@@ -5,17 +5,20 @@ import Quickshell.Services.SystemTray
import QtQuick import QtQuick
import ZShell.Config import ZShell.Config
import qs.Components import qs.Components
import qs.Modules.WSOverview
import qs.Modules.Network
import qs.Modules.SysTray.Popouts
import qs.Modules.Updates
Item { Item {
id: root id: root
readonly property Item current: currentPopout?.item ?? null readonly property Item current: currentPopout?.item ?? null
readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null readonly property Popout currentPopout: content.children.find(c => c.shouldBeActive) ?? null
required property bool horizontal
required property PopoutState popouts required property PopoutState popouts
implicitHeight: (currentPopout?.implicitHeight ?? 0) + Tokens.padding.smaller * 2 implicitHeight: (currentPopout?.implicitHeight ?? 0) + Tokens.padding.small * 2
implicitWidth: (currentPopout?.implicitWidth ?? 0) + Tokens.padding.smaller * 2 implicitWidth: (currentPopout?.implicitWidth ?? 0) + Tokens.padding.small * 2
Item { Item {
id: content id: content
@@ -70,7 +73,6 @@ Item {
name: "upower" name: "upower"
sourceComponent: UPowerPopout { sourceComponent: UPowerPopout {
horizontal: root.horizontal
} }
} }
@@ -98,10 +100,10 @@ Item {
readonly property bool shouldBeActive: root.popouts.currentName === name readonly property bool shouldBeActive: root.popouts.currentName === name
active: false active: false
anchors.centerIn: opacity === 1 ? undefined : parent // anchors.horizontalCenter: parent.horizontalCenter
anchors.horizontalCenter: parent.horizontalCenter // anchors.top: parent.top
anchors.top: opacity === 1 ? parent.top : undefined // anchors.topMargin: 5
anchors.topMargin: Tokens.padding.smaller anchors.centerIn: parent
opacity: 0 opacity: 0
scale: 0.8 scale: 0.8
+3 -3
View File
@@ -32,16 +32,16 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.smaller
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
color: "transparent" color: "transparent"
radius: Tokens.rounding.extraLarge - anchors.margins radius: Tokens.rounding.normal - anchors.margins
Item { Item {
id: view id: view
readonly property int currentIndex: root.dashState?.currentTab readonly property int currentIndex: root.state.currentTab
readonly property Item currentItem: row.children[currentIndex] readonly property Item currentItem: row.children[currentIndex]
anchors.fill: parent anchors.fill: parent
+4 -5
View File
@@ -13,11 +13,11 @@ GridLayout {
required property PersistentProperties dashState required property PersistentProperties dashState
readonly property bool dashboardVisible: visibilities.dashboard readonly property bool dashboardVisible: visibilities.dashboard
property int radius: Tokens.rounding.medium property int radius: Tokens.rounding.smallest
required property PersistentProperties visibilities required property PersistentProperties visibilities
columnSpacing: Tokens.spacing.small columnSpacing: Tokens.spacing.smaller
rowSpacing: Tokens.spacing.small rowSpacing: Tokens.spacing.smaller
ParallelAnimation { ParallelAnimation {
id: openAnim id: openAnim
@@ -104,13 +104,12 @@ GridLayout {
} }
} }
CustomClippingRect { Rect {
Layout.column: 0 Layout.column: 0
Layout.columnSpan: 5 Layout.columnSpan: 5
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: media.implicitHeight Layout.preferredHeight: media.implicitHeight
Layout.row: 2 Layout.row: 2
color: Colors.tPalette.m3surfaceContainer
radius: root.radius radius: root.radius
Media { Media {
+4 -4
View File
@@ -132,7 +132,7 @@ CustomMouseArea {
IconButton { IconButton {
icon: "chevron_left" icon: "chevron_left"
padding: Tokens.padding.extraSmall padding: Tokens.padding.small
type: IconButton.Text type: IconButton.Text
onClicked: root.dashState.currentDate = new Date(root.realCurrYear, root.realCurrMonth - 1, 1) onClicked: root.dashState.currentDate = new Date(root.realCurrYear, root.realCurrMonth - 1, 1)
@@ -150,7 +150,7 @@ CustomMouseArea {
const now = new Date(); const now = new Date();
return root.realCurrMonth !== now.getMonth() || root.realCurrYear !== now.getFullYear(); return root.realCurrMonth !== now.getMonth() || root.realCurrYear !== now.getFullYear();
} }
radius: pressed ? Tokens.rounding.small : Tokens.rounding.largeIncreased radius: pressed ? Tokens.rounding.small : Tokens.rounding.large
Behavior on radius { Behavior on radius {
Anim { Anim {
@@ -203,7 +203,7 @@ CustomMouseArea {
IconButton { IconButton {
icon: "chevron_right" icon: "chevron_right"
padding: Tokens.padding.extraSmall padding: Tokens.padding.small
type: IconButton.Text type: IconButton.Text
onClicked: root.dashState.currentDate = new Date(root.realCurrYear, root.realCurrMonth + 1, 1) onClicked: root.dashState.currentDate = new Date(root.realCurrYear, root.realCurrMonth + 1, 1)
@@ -259,7 +259,7 @@ CustomMouseArea {
required property var model required property var model
implicitHeight: text.implicitHeight + Tokens.padding.small * 2 implicitHeight: text.implicitHeight + Tokens.padding.normal * 2
implicitWidth: implicitHeight implicitWidth: implicitHeight
CustomText { CustomText {
+190 -162
View File
@@ -1,15 +1,12 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import Quickshell.Services.Mpris
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Shapes import QtQuick.Shapes
import QtQuick.Effects import QtQuick.Effects
import ZShell.Components
import ZShell.Services import ZShell.Services
import ZShell.Config import ZShell.Config
import qs.Modules.Dashboard.Dash.Media
import qs.Daemons import qs.Daemons
import qs.Components import qs.Components
import qs.Helpers import qs.Helpers
@@ -17,7 +14,7 @@ import qs.Services
Item { Item {
id: root id: root
readonly property bool hasUnknownLength: (Players.active?.length ?? 0) > 2147483647
property real playerProgress: { property real playerProgress: {
const active = Players.active; const active = Players.active;
return active?.length ? (active.position % active.length) / active.length : 0; return active?.length ? (active.position % active.length) / active.length : 0;
@@ -26,19 +23,7 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
implicitHeight: layout.implicitHeight + layout.anchors.margins * 2 implicitHeight: cover.height + rowHeight * 2
function lengthStr(length: int): string {
if (length < 0)
return "-1:-1";
const hours = Math.floor(length / 3600);
const mins = Math.floor((length % 3600) / 60);
const secs = Math.floor(length % 60).toString().padStart(2, "0");
if (hours > 0)
return `${hours}:${mins.toString().padStart(2, "0")}:${secs}`;
return `${mins}:${secs}`;
}
Behavior on playerProgress { Behavior on playerProgress {
Anim { Anim {
@@ -47,10 +32,11 @@ Item {
} }
Timer { Timer {
running: Players.active?.isPlaying ?? false
interval: Config.dashboard.mediaUpdateInterval interval: Config.dashboard.mediaUpdateInterval
triggeredOnStart: true
repeat: true repeat: true
running: Players.active?.isPlaying ?? false
triggeredOnStart: true
onTriggered: Players.active?.positionChanged() onTriggered: Players.active?.positionChanged()
} }
@@ -58,18 +44,14 @@ Item {
service: Audio.cava service: Audio.cava
} }
BackgroundShapes {
anchors.fill: parent
}
Shape { Shape {
id: visualizer id: visualizer
readonly property int bars: Config.services.visualizerBars readonly property int bars: Config.services.visualizerBars
property color color: Qt.alpha(Colors.palette.m3primary, 0.5) property color color: Colors.palette.m3tertiary
property color fillColor: Qt.alpha(color, 0.1) property color fillColor: Qt.alpha(color, 0.25)
anchors.fill: parent anchors.fill: layout
anchors.leftMargin: -(shape.strokeWidth / 2) anchors.leftMargin: -(shape.strokeWidth / 2)
layer.enabled: true layer.enabled: true
asynchronous: true asynchronous: true
@@ -90,17 +72,17 @@ Item {
const n = values.length; const n = values.length;
if (n < 2) if (n < 2)
return ""; return "";
const h = root.height + shape.strokeWidth / 2; const h = layout.height + shape.strokeWidth / 2;
const w = root.width + shape.strokeWidth; const w = layout.width + shape.strokeWidth;
function x(i) { function x(i) {
return i * w / (n - 1); return i * w / (n - 1);
} }
function y(i) { function y(i) {
return h - (values[i] * Config.dashboard.sizes.mediaVisualizerSize) / 2; return h - values[i] * Config.dashboard.sizes.mediaVisualizerSize;
} }
let d = `M 0 ${h} `; let d = `M 0 ${h} `;
@@ -144,186 +126,232 @@ Item {
} }
} }
Shape {
preferredRendererType: Shape.CurveRenderer
ShapePath {
capStyle: Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
fillColor: "transparent"
strokeColor: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
strokeWidth: Config.dashboard.sizes.mediaProgressThickness
Behavior on strokeColor {
CAnim {
}
}
PathAngleArc {
centerX: cover.x + cover.width / 2
centerY: cover.y + cover.height / 2
radiusX: (cover.width + Config.dashboard.sizes.mediaProgressThickness) / 2 + Tokens.spacing.small
radiusY: (cover.height + Config.dashboard.sizes.mediaProgressThickness) / 2 + Tokens.spacing.small
startAngle: -90 - Config.dashboard.sizes.mediaProgressSweep / 2
sweepAngle: Config.dashboard.sizes.mediaProgressSweep
}
}
ShapePath {
capStyle: Tokens.rounding.scale === 0 ? ShapePath.SquareCap : ShapePath.RoundCap
fillColor: "transparent"
strokeColor: Colors.palette.m3primary
strokeWidth: Config.dashboard.sizes.mediaProgressThickness
Behavior on strokeColor {
CAnim {
}
}
PathAngleArc {
centerX: cover.x + cover.width / 2
centerY: cover.y + cover.height / 2
radiusX: (cover.width + Config.dashboard.sizes.mediaProgressThickness) / 2 + Tokens.spacing.small
radiusY: (cover.height + Config.dashboard.sizes.mediaProgressThickness) / 2 + Tokens.spacing.small
startAngle: -90 - Config.dashboard.sizes.mediaProgressSweep / 2
sweepAngle: Config.dashboard.sizes.mediaProgressSweep * root.playerProgress
}
}
}
RowLayout { RowLayout {
id: layout id: layout
anchors.fill: parent anchors.left: parent.left
anchors.margins: Tokens.padding.large anchors.right: parent.right
anchors.leftMargin: Tokens.padding.extraLarge implicitHeight: root.implicitHeight
CoverVisualizer { CustomClippingRect {
Layout.fillHeight: true id: cover
implicitWidth: Config.dashboard.sizes.mediaCoverArtSize
Layout.alignment: Qt.AlignLeft
Layout.bottomMargin: Tokens.padding.large + Config.dashboard.sizes.mediaProgressThickness + Tokens.spacing.small
Layout.leftMargin: Tokens.padding.large + Config.dashboard.sizes.mediaProgressThickness + Tokens.spacing.small
Layout.preferredHeight: Config.dashboard.sizes.mediaCoverArtSize
Layout.preferredWidth: Config.dashboard.sizes.mediaCoverArtSize
Layout.topMargin: Tokens.padding.large + Config.dashboard.sizes.mediaProgressThickness + Tokens.spacing.small
color: Colors.tPalette.m3surfaceContainerHigh
radius: Infinity
MaterialIcon {
anchors.centerIn: parent
color: Colors.palette.m3onSurfaceVariant
font.pointSize: (parent.width * 0.4) || 1
grade: 200
text: "art_track"
}
Image {
id: image
anchors.fill: parent
asynchronous: true
fillMode: Image.PreserveAspectCrop
source: Players.active?.trackArtUrl ?? ""
sourceSize.height: Math.floor(height)
sourceSize.width: Math.floor(width)
}
} }
ColumnLayout { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
Layout.leftMargin: Tokens.spacing.largeIncreased Layout.preferredHeight: childrenRect.height
Layout.rightMargin: Tokens.spacing.largeIncreased
spacing: Tokens.spacing.small
MarqueeText { MarqueeText {
id: title id: title
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
color: Colors.palette.m3primary color: Colors.palette.m3primary
font.pointSize: Tokens.font.size.normal font.pointSize: Tokens.font.size.normal
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
pauseMs: 4000 pauseMs: 4000
text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title") text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title")
implicitWidth: parent.width - Tokens.padding.large * 4 width: parent.width - Tokens.padding.large * 4
} }
MarqueeText { MarqueeText {
id: album id: album
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: title.bottom
anchors.topMargin: Tokens.spacing.small
color: Colors.palette.m3outline color: Colors.palette.m3outline
font.pointSize: Tokens.font.size.small font.pointSize: Tokens.font.size.small
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
pauseMs: 4000 pauseMs: 4000
text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album") text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album")
implicitWidth: parent.width - Tokens.padding.large * 4 width: parent.width - Tokens.padding.large * 4
} }
MarqueeText { MarqueeText {
id: artist id: artist
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: album.bottom
anchors.topMargin: Tokens.spacing.small
color: Colors.palette.m3secondary color: Colors.palette.m3secondary
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
pauseMs: 4000 pauseMs: 4000
text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist") text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist")
implicitWidth: parent.width - Tokens.padding.large * 4 width: parent.width - Tokens.padding.large * 4
} }
RowLayout { RowLayout {
id: positionSliderLayout id: controls
Layout.topMargin: Tokens.spacing.large
Layout.fillWidth: true anchors.horizontalCenter: parent.horizontalCenter
anchors.top: artist.bottom
anchors.topMargin: Tokens.spacing.smaller
spacing: Tokens.spacing.small spacing: Tokens.spacing.small
TextMetrics { Control {
id: timeMetrics function onClicked(): void {
Players.active?.previous();
text: Players.active ? root.lengthStr(Math.max(Players.active.position, root.hasUnknownLength ? 0 : Players.active.length)).replace(/[1-9]/g, "0") : "00:00"
}
CustomText {
id: positionLabel
Layout.preferredWidth: timeMetrics.width
text: root.lengthStr(Players.active?.position ?? -1)
color: Colors.palette.m3onSurfaceVariant
font: timeMetrics.font
horizontalAlignment: Text.AlignHCenter
}
CustomSlider {
id: positionSlider
Layout.fillWidth: true
value: Players.active ? Players.active.position / (Players.active.length || 1) : 0
enabled: (Players.active?.canSeek ?? false) && !root.hasUnknownLength
wavy: true
animateWave: Players.active?.isPlaying ?? false
waveFrequency: 5
waveDuration: 2000
interactionOnMove: false
onInteraction: value => {
const active = Players.active;
if (active?.canSeek && active?.positionSupported)
active.position = value * active.length;
} }
Binding {
target: positionLabel
property: "text"
value: root.lengthStr(positionSlider.pos * (Players.active?.length ?? 0))
when: positionSlider.dragging
}
}
CustomText { canUse: Players.active?.canGoPrevious ?? false
Layout.preferredWidth: timeMetrics.width
text: root.hasUnknownLength ? "--:--" : root.lengthStr(Players.active?.length ?? -1)
color: Colors.palette.m3onSurfaceVariant
font: timeMetrics.font
horizontalAlignment: Text.AlignHCenter
}
}
ButtonRow {
Layout.topMargin: Tokens.spacing.largeIncreased
Layout.fillWidth: true
spacing: Tokens.spacing.extraSmall
Layout.leftMargin: positionSliderLayout.implicitWidth / 4
Layout.rightMargin: positionSliderLayout.implicitWidth / 4
IconButton {
type: IconButton.Tonal
icon: "shuffle"
isRound: true
shapeMorph: true
checked: Players.active?.shuffle ?? false
enabled: Players.active?.shuffleSupported
onClicked: Players.active.shuffle = !Players.active?.shuffle
}
IconButton {
id: previousBtn
type: IconButton.Tonal
icon: "skip_previous" icon: "skip_previous"
isRound: true
shapeMorph: true
enabled: Players.active?.canGoPrevious
onClicked: Players.active?.previous()
font.pointSize: Tokens.font.size.large
} }
IconButton { Control {
id: playPauseBtn function onClicked(): void {
Players.active?.togglePlaying();
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
isRound: true
shapeMorph: true
fillWidth: true
checked: Players.active?.isPlaying ?? false
enabled: Players.active?.canTogglePlaying
onClicked: Players.active?.togglePlaying()
font.pointSize: Tokens.font.size.large
}
IconButton {
id: nextBtn
type: IconButton.Tonal
icon: "skip_next"
isRound: true
shapeMorph: true
enabled: Players.active?.canGoNext
onClicked: Players.active?.next()
font.pointSize: Tokens.font.size.large
}
IconButton {
type: IconButton.Tonal
icon: Players.active?.loopState === MprisLoopState.Track ? "repeat_one" : "repeat"
isRound: true
shapeMorph: true
checked: Players.active?.loopState === MprisLoopState.Track || Players.active?.loopState === MprisLoopState.Playlist
enabled: Players.active?.loopSupported
onClicked: {
const state = Players.active.loopState;
if (state === MprisLoopState.None)
Players.active.loopState = MprisLoopState.Track;
else if (state === MprisLoopState.Track)
Players.active.loopState = MprisLoopState.Playlist;
else
Players.active.loopState = MprisLoopState.None;
} }
canUse: Players.active?.canTogglePlaying ?? false
icon: Players.active?.isPlaying ? "pause" : "play_arrow"
}
Control {
function onClicked(): void {
Players.active?.next();
}
canUse: Players.active?.canGoNext ?? false
icon: "skip_next"
} }
} }
} }
} }
component Control: CustomRect {
id: control
required property bool canUse
required property string icon
property int level: 1
property string set_color: "Secondary"
function onClicked(): void {
}
Layout.preferredWidth: implicitWidth + (controlState.pressed ? Tokens.padding.normal * 2 : 0)
color: canUse ? Colors.palette[`m3${set_color.toLowerCase()}`] : Colors.palette[`m3${set_color.toLowerCase()}Container`]
implicitHeight: implicitWidth
implicitWidth: Math.max(icon.implicitHeight, icon.implicitHeight) + Tokens.padding.small
radius: Tokens.rounding.full
Behavior on Layout.preferredWidth {
Anim {
duration: Tokens.anim.durations.expressiveFastSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
}
}
Behavior on radius {
Anim {
duration: Tokens.anim.durations.expressiveFastSpatial
easing.bezierCurve: Tokens.anim.curves.expressiveFastSpatial
}
}
Elevation {
anchors.fill: parent
level: controlState.containsMouse && !controlState.pressed ? control.level + 1 : control.level
radius: parent.radius
z: -1
}
StateLayer {
id: controlState
color: control.canUse ? Colors.palette[`m3on${control.set_color}`] : Colors.palette[`m3on${control.set_color}Container`]
enabled: control.canUse
onClicked: {
control.onClicked();
}
// radius: Tokens.rounding.full
}
MaterialIcon {
id: icon
anchors.centerIn: parent
anchors.verticalCenterOffset: font.pointSize * 0.05
animate: true
color: control.canUse ? Colors.palette[`m3on${control.set_color}`] : Colors.palette[`m3on${control.set_color}Container`]
fill: control.canUse ? 1 : 0
font.pointSize: Tokens.font.size.large
text: control.icon
}
}
} }
@@ -1,97 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import M3Shapes
import qs.Components
import qs.Services
import qs.Helpers
Item {
id: root
property int count: 14
property list<real> darkOpacities: [0.10, 0.20, 0.10, 0.20]
property list<real> lightOpacities: [0.34, 0.34, 0.08, 0.2]
property real maxRotSpeed: 12
property real maxSize: 124
property real maxSpeed: 18
property real minRotSpeed: -12
property real minSize: 36
property real minSpeed: 4
readonly property list<int> shapePool: [MaterialShape.Circle, MaterialShape.Cookie4Sided, MaterialShape.Cookie6Sided, MaterialShape.Cookie7Sided, MaterialShape.Cookie9Sided, MaterialShape.Cookie12Sided, MaterialShape.Sunny, MaterialShape.VerySunny, MaterialShape.SoftBurst, MaterialShape.Pentagon, MaterialShape.Gem, MaterialShape.Arch, MaterialShape.Arrow, MaterialShape.Pill, MaterialShape.Triangle, MaterialShape.Fan, MaterialShape.Oval]
function rand(min: real, max: real): real {
return min + Math.random() * (max - min);
}
function signedRand(min: real, max: real): real {
return rand(min, max) * (Math.random() < 0.5 ? -1 : 1);
}
Component.onCompleted: shapes.model = count
Repeater {
id: shapes
DriftingShape {
}
}
FrameAnimation {
running: root.visible && root.width > 0 && root.height > 0 && (Players.active?.isPlaying ?? false)
onTriggered: {
const dt = frameTime;
for (let i = 0; i < shapes.count; i++) {
const s = shapes.itemAt(i) as DriftingShape;
if (!s)
continue;
s.x += s.vx * dt;
s.y += s.vy * dt;
s.rotation += s.vr * dt;
if (s.x + s.width < 0)
s.x = root.width;
else if (s.x > root.width)
s.x = -s.width;
if (s.y + s.height < 0)
s.y = root.height;
else if (s.y > root.height)
s.y = -s.height;
}
}
}
component DriftingShape: MaterialShape {
id: shapeItem
readonly property int colorIdx: Math.floor(Math.random() * 4)
required property int index
property real vr: root.rand(root.minRotSpeed, root.maxRotSpeed)
property real vx: root.signedRand(root.minSpeed, root.maxSpeed)
property real vy: root.signedRand(root.minSpeed, root.maxSpeed)
color: [Colors.palette.m3primaryContainer, Colors.palette.m3secondaryContainer, Colors.palette.m3tertiaryContainer, Colors.palette.m3outlineVariant][colorIdx]
implicitSize: root.minSize + (index / root.count) * (root.maxSize - root.minSize)
opacity: Colors.light ? root.lightOpacities[colorIdx] : root.darkOpacities[colorIdx]
rotation: root.rand(0, 360)
shape: root.shapePool[Math.floor(Math.random() * root.shapePool.length)]
Behavior on color {
CAnim {
}
}
Behavior on opacity {
Anim {
type: Anim.SlowEffects
}
}
Component.onCompleted: {
x = root.rand(0, root.width - implicitSize);
y = root.rand(0, root.height - implicitSize);
}
}
}
-100
View File
@@ -1,100 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Effects
import M3Shapes
import qs.Helpers
import qs.Effects
import qs.Components
import qs.Services
Item {
id: root
property color fallbackColor: Colors.layer(Colors.palette.m3surfaceContainerHighest, 2)
property bool hadPrevious
readonly property alias shape: shape
layer.enabled: true
Behavior on fallbackColor {
CAnim {
}
}
layer.effect: MultiEffect {
blurMax: 1
shadowColor: Colors.palette.m3outline
shadowEnabled: true
shadowOpacity: 0.3
}
Item {
id: shapeWrapper
anchors.fill: parent
layer.enabled: true
opacity: root.fallbackColor.a
MaterialShape {
id: shape
color: Qt.alpha(root.fallbackColor, 1)
implicitSize: root.width
shape: MaterialShape.Cookie12Sided
Anim on rotation {
duration: 23500
easing.type: Easing.Linear
from: 360
loops: Animation.Infinite
paused: !Players.active?.isPlaying
running: true
to: 0
}
}
}
MaterialIcon {
anchors.centerIn: parent
animate: true
color: Colors.palette.m3onSurfaceVariant
grade: 200
opacity: image.status === Image.Null || image.status === Image.Error ? 1 : 0
text: image.status === Image.Error ? "broken_image" : "art_track"
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
}
Loader {
active: opacity > 0
anchors.centerIn: parent
asynchronous: true
opacity: image.status === Image.Loading ? 1 : 0
Behavior on opacity {
Anim {
type: Anim.DefaultEffects
}
}
sourceComponent: LoadingIndicator {
color: Colors.palette.m3primaryContainer
implicitSize: root.width * 0.3
}
}
FadeImage {
id: image
anchors.fill: parent
layer.enabled: true
source: Players.getArtUrl(Players.active)
layer.effect: Mask {
maskSource: shapeWrapper
}
}
}
@@ -1,18 +0,0 @@
pragma ComponentBehavior: Bound
import QtQuick
import M3Shapes
import ZShell.Config
Item {
id: root
CoverArt {
id: cover
anchors.centerIn: parent
implicitHeight: Config.dashboard.sizes.mediaCoverArtSize
implicitWidth: Config.dashboard.sizes.mediaCoverArtSize
shape.shape: MaterialShape.Cookie9Sided
}
}
+1 -1
View File
@@ -35,7 +35,7 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: Tokens.padding.large anchors.margins: Tokens.padding.large
anchors.top: parent.top anchors.top: parent.top
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
Resource { Resource {
fgColor: Colors.palette.m3primary fgColor: Colors.palette.m3primary
+1 -1
View File
@@ -18,7 +18,7 @@ Row {
color: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2) color: Colors.layer(Colors.palette.m3surfaceContainerHigh, 2)
implicitHeight: info.implicitHeight implicitHeight: info.implicitHeight
implicitWidth: info.implicitHeight implicitWidth: info.implicitHeight
radius: Tokens.rounding.small radius: Tokens.rounding.smallest
MaterialIcon { MaterialIcon {
anchors.centerIn: parent anchors.centerIn: parent
+1 -1
View File
@@ -27,7 +27,7 @@ Item {
id: info id: info
anchors.left: icon.right anchors.left: icon.right
anchors.leftMargin: Tokens.spacing.largeIncreased anchors.leftMargin: Tokens.spacing.large
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: 8 spacing: 8
+1 -1
View File
@@ -181,7 +181,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: "transparent" color: "transparent"
implicitHeight: parent.height + 8 * 2 implicitHeight: parent.height + 8 * 2
radius: Tokens.rounding.small radius: Tokens.rounding.smallest
CustomRect { CustomRect {
id: stateLayer id: stateLayer
+2 -12
View File
@@ -16,16 +16,9 @@ Item {
} }
readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0 readonly property real nonAnimHeight: state === "visible" ? (content.item?.nonAnimHeight ?? 0) : 0
required property real offsetScale required property real offsetScale
required property string position
readonly property bool shouldBeActive: root.visibilities.dashboard && Config.dashboard.enabled readonly property bool shouldBeActive: root.visibilities.dashboard && Config.dashboard.enabled
required property PersistentProperties visibilities required property PersistentProperties visibilities
anchors.bottom: position === "bottom" ? parent.bottom : undefined
anchors.bottomMargin: position === "bottom" ? (-implicitHeight - 5) * offsetScale : 0
anchors.left: position === "left" ? parent.left : undefined
anchors.leftMargin: position === "left" ? (-implicitWidth - 5) * offsetScale : 0
anchors.top: position === "top" ? parent.top : undefined
anchors.topMargin: position === "top" ? (-implicitHeight - 5) * offsetScale : 0
implicitHeight: content.implicitHeight implicitHeight: content.implicitHeight
implicitWidth: content.implicitWidth || 854 implicitWidth: content.implicitWidth || 854
opacity: 1 - offsetScale opacity: 1 - offsetScale
@@ -35,11 +28,8 @@ Item {
id: content id: content
active: root.shouldBeActive || root.visible active: root.shouldBeActive || root.visible
anchors.bottom: root.position === "top" ? parent.bottom : undefined anchors.bottom: parent.bottom
anchors.horizontalCenter: root.position !== "left" ? parent.horizontalCenter : undefined anchors.horizontalCenter: parent.horizontalCenter
anchors.right: root.position !== "left" ? undefined : parent.right
anchors.top: root.position === "bottom" ? parent.top : undefined
anchors.verticalCenter: root.position === "left" ? undefined : parent.verticalCenter
sourceComponent: Content { sourceComponent: Content {
dashState: root.dashState dashState: root.dashState
@@ -32,7 +32,7 @@ Item {
y: root.menuY y: root.menuY
color: Colors.tPalette.m3surface color: Colors.tPalette.m3surface
radius: Tokens.rounding.medium radius: Tokens.rounding.normal
implicitWidth: menuLayout.implicitWidth + padding * 2 implicitWidth: menuLayout.implicitWidth + padding * 2
implicitHeight: menuLayout.implicitHeight + padding * 2 implicitHeight: menuLayout.implicitHeight + padding * 2
@@ -48,13 +48,13 @@ Item {
CustomRect { CustomRect {
Layout.preferredWidth: 200 Layout.preferredWidth: 200
radius: popupBackground.radius - popupBackground.padding radius: popupBackground.radius - popupBackground.padding
implicitHeight: openTerminalRow.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: openTerminalRow.implicitHeight + Tokens.padding.small * 2
RowLayout { RowLayout {
id: openTerminalRow id: openTerminalRow
spacing: 8 spacing: 8
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.smaller
MaterialIcon { text: "terminal"; font.pointSize: 20 } MaterialIcon { text: "terminal"; font.pointSize: 20 }
CustomText { text: "Open terminal"; Layout.fillWidth: true } CustomText { text: "Open terminal"; Layout.fillWidth: true }
@@ -81,13 +81,13 @@ Item {
CustomRect { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
radius: popupBackground.radius - popupBackground.padding radius: popupBackground.radius - popupBackground.padding
implicitHeight: settingsRow.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: settingsRow.implicitHeight + Tokens.padding.small * 2
RowLayout { RowLayout {
id: settingsRow id: settingsRow
spacing: 8 spacing: 8
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.smaller
MaterialIcon { text: "settings"; font.pointSize: 20 } MaterialIcon { text: "settings"; font.pointSize: 20 }
CustomText { text: "ZShell settings"; Layout.fillWidth: true } CustomText { text: "ZShell settings"; Layout.fillWidth: true }
@@ -115,13 +115,13 @@ Item {
CustomRect { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
radius: popupBackground.radius - popupBackground.padding radius: popupBackground.radius - popupBackground.padding
implicitHeight: logoutRow.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: logoutRow.implicitHeight + Tokens.padding.small * 2
RowLayout { RowLayout {
id: logoutRow id: logoutRow
spacing: 8 spacing: 8
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.smaller
MaterialIcon { text: "logout"; font.pointSize: 20 } MaterialIcon { text: "logout"; font.pointSize: 20 }
CustomText { text: "Logout"; Layout.fillWidth: true } CustomText { text: "Logout"; Layout.fillWidth: true }
@@ -148,13 +148,13 @@ Item {
// CustomRect { // CustomRect {
// Layout.fillWidth: true // Layout.fillWidth: true
// radius: popupBackground.radius - popupBackground.padding // radius: popupBackground.radius - popupBackground.padding
// implicitHeight: desktopIconsRow.implicitHeight + Tokens.padding.extraSmall * 2 // implicitHeight: desktopIconsRow.implicitHeight + Tokens.padding.small * 2
// //
// RowLayout { // RowLayout {
// id: desktopIconsRow // id: desktopIconsRow
// spacing: 8 // spacing: 8
// anchors.fill: parent // anchors.fill: parent
// anchors.leftMargin: Tokens.padding.small // anchors.leftMargin: Tokens.padding.smaller
// //
// MaterialIcon { text: Config.options.background.showDesktopIcons ? "visibility_off" : "visibility"; font.pointSize: 20 } // MaterialIcon { text: Config.options.background.showDesktopIcons ? "visibility_off" : "visibility"; font.pointSize: 20 }
// CustomText { text: Config.options.background.showDesktopIcons ? "Hide icons" : "Show icons"; Layout.fillWidth: true } // CustomText { text: Config.options.background.showDesktopIcons ? "Hide icons" : "Show icons"; Layout.fillWidth: true }
+12 -12
View File
@@ -43,13 +43,13 @@ Item {
CustomClippingRect { CustomClippingRect {
id: popupBackground id: popupBackground
readonly property real padding: Tokens.padding.extraSmall readonly property real padding: Tokens.padding.small
color: Colors.tPalette.m3surface color: Colors.tPalette.m3surface
implicitHeight: menuLayout.implicitHeight + padding * 2 implicitHeight: menuLayout.implicitHeight + padding * 2
implicitWidth: menuLayout.implicitWidth + padding * 2 implicitWidth: menuLayout.implicitWidth + padding * 2
opacity: contextMenu.visible ? 1 : 0 opacity: contextMenu.visible ? 1 : 0
radius: Tokens.rounding.medium radius: Tokens.rounding.normal
x: contextMenu.menuX x: contextMenu.menuX
y: contextMenu.menuY y: contextMenu.menuY
@@ -66,14 +66,14 @@ Item {
CustomRect { CustomRect {
Layout.preferredWidth: 160 Layout.preferredWidth: 160
implicitHeight: openRow.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: openRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding radius: popupBackground.radius - popupBackground.padding
RowLayout { RowLayout {
id: openRow id: openRow
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.smaller
spacing: 8 spacing: 8
MaterialIcon { MaterialIcon {
@@ -109,14 +109,14 @@ Item {
CustomRect { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: openWithRow.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: openWithRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding radius: popupBackground.radius - popupBackground.padding
RowLayout { RowLayout {
id: openWithRow id: openWithRow
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.smaller
spacing: 8 spacing: 8
MaterialIcon { MaterialIcon {
@@ -154,14 +154,14 @@ Item {
CustomRect { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: copyPathRow.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: copyPathRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding radius: popupBackground.radius - popupBackground.padding
RowLayout { RowLayout {
id: copyPathRow id: copyPathRow
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.smaller
spacing: 8 spacing: 8
MaterialIcon { MaterialIcon {
@@ -187,7 +187,7 @@ Item {
CustomRect { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: renameRow.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: renameRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding radius: popupBackground.radius - popupBackground.padding
visible: contextMenu.targetPaths.length === 1 visible: contextMenu.targetPaths.length === 1
@@ -195,7 +195,7 @@ Item {
id: renameRow id: renameRow
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.smaller
spacing: 8 spacing: 8
MaterialIcon { MaterialIcon {
@@ -229,14 +229,14 @@ Item {
CustomRect { CustomRect {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: deleteRow.implicitHeight + Tokens.padding.extraSmall * 2 implicitHeight: deleteRow.implicitHeight + Tokens.padding.small * 2
radius: popupBackground.radius - popupBackground.padding radius: popupBackground.radius - popupBackground.padding
RowLayout { RowLayout {
id: deleteRow id: deleteRow
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.smaller
spacing: 8 spacing: 8
MaterialIcon { MaterialIcon {
+2 -2
View File
@@ -205,7 +205,7 @@ Item {
anchors.margins: 4 anchors.margins: 4
color: "white" color: "white"
opacity: root.iconsRoot.selectedIcons.includes(root.filePath) ? 0.2 : 0.0 opacity: root.iconsRoot.selectedIcons.includes(root.filePath) ? 0.2 : 0.0
radius: Tokens.rounding.small radius: Tokens.rounding.smallest
Behavior on opacity { Behavior on opacity {
Anim { Anim {
@@ -265,7 +265,7 @@ Item {
anchors.margins: 4 anchors.margins: 4
color: "white" color: "white"
opacity: parent.containsMouse ? 0.1 : 0.0 opacity: parent.containsMouse ? 0.1 : 0.0
radius: Tokens.rounding.small radius: Tokens.rounding.smallest
Behavior on opacity { Behavior on opacity {
Anim { Anim {
+4 -4
View File
@@ -22,10 +22,10 @@ Item {
property string draggedAppId: "" property string draggedAppId: ""
property var draggedModelData: null property var draggedModelData: null
property bool dropAnimating: false property bool dropAnimating: false
readonly property int padding: Tokens.padding.extraSmall readonly property int padding: Tokens.padding.small
required property var panels required property var panels
property var pendingCommitIds: [] property var pendingCommitIds: []
readonly property int rounding: Tokens.rounding.largeIncreased readonly property int rounding: Tokens.rounding.large
required property ShellScreen screen required property ShellScreen screen
required property PersistentProperties visibilities required property PersistentProperties visibilities
property var visualIds: [] property var visualIds: []
@@ -247,7 +247,7 @@ Item {
property bool enableAddAnimation: false property bool enableAddAnimation: false
anchors.left: parent.left anchors.left: parent.left
anchors.margins: Tokens.padding.extraSmall anchors.margins: Tokens.padding.small
anchors.top: parent.top anchors.top: parent.top
boundsBehavior: Flickable.StopAtBounds boundsBehavior: Flickable.StopAtBounds
height: Config.dock.height height: Config.dock.height
@@ -255,7 +255,7 @@ Item {
interactive: !(root.dragActive || root.dropAnimating) interactive: !(root.dragActive || root.dropAnimating)
model: visualModel model: visualModel
orientation: ListView.Horizontal orientation: ListView.Horizontal
spacing: Tokens.padding.small spacing: Tokens.padding.smaller
add: Transition { add: Transition {
ParallelAnimation { ParallelAnimation {
+1 -1
View File
@@ -23,7 +23,7 @@ CustomRect {
implicitHeight: Config.dock.height implicitHeight: Config.dock.height
implicitWidth: isSeparator ? 1 : implicitHeight implicitWidth: isSeparator ? 1 : implicitHeight
radius: Tokens.rounding.medium - Tokens.padding.extraSmall radius: Tokens.rounding.normal - Tokens.padding.small
Loader { Loader {
active: !isSeparator active: !isSeparator
+2 -2
View File
@@ -5,9 +5,9 @@ import ZShell.Config
import qs.Services import qs.Services
CustomRect { CustomRect {
Layout.bottomMargin: dockRow.padding + Tokens.rounding.medium Layout.bottomMargin: dockRow.padding + Tokens.rounding.normal
Layout.fillHeight: true Layout.fillHeight: true
Layout.topMargin: dockRow.padding + Tokens.rounding.medium Layout.topMargin: dockRow.padding + Tokens.rounding.normal
color: Colors.palette.m3outlineVariant color: Colors.palette.m3outlineVariant
implicitWidth: 1 implicitWidth: 1
} }
+1 -1
View File
@@ -24,7 +24,7 @@ Item {
Behavior on offsetScale { Behavior on offsetScale {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
} }
} }
+5 -5
View File
@@ -33,8 +33,8 @@ Item {
drawing.drawingState.penColor = Qt.hsva(huePicker.currentHue, saturationSlider.value, brightnessSlider.value, drawing.drawingState.penColor.a); drawing.drawingState.penColor = Qt.hsva(huePicker.currentHue, saturationSlider.value, brightnessSlider.value, drawing.drawingState.penColor.a);
} }
implicitHeight: column.height + Tokens.padding.small * 2 implicitHeight: column.height + Tokens.padding.larger * 2
implicitWidth: huePicker.implicitWidth + Tokens.padding.small * 2 implicitWidth: huePicker.implicitWidth + Tokens.padding.normal * 2
Component.onCompleted: syncFromPenColor() Component.onCompleted: syncFromPenColor()
@@ -97,7 +97,7 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
Repeater { Repeater {
model: root.colors1 model: root.colors1
@@ -113,7 +113,7 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
Repeater { Repeater {
model: root.colors2 model: root.colors2
@@ -172,7 +172,7 @@ Item {
} }
IconButton { IconButton {
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.normal
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
checked: root.wrapper.pinned checked: root.wrapper.pinned
+2 -2
View File
@@ -49,13 +49,13 @@ Item {
Behavior on implicitWidth { Behavior on implicitWidth {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
} }
} }
Behavior on offsetScale { Behavior on offsetScale {
Anim { Anim {
duration: Tokens.anim.durations.expressiveDefaultSpatial duration: Tokens.anim.durations.expressiveDefaultSpatial
easing: Tokens.anim.expressiveDefaultSpatial easing.bezierCurve: Tokens.anim.curves.expressiveDefaultSpatial
} }
} }
@@ -1,16 +1,17 @@
import QtQuick import QtQuick
import ZShell.Config
import qs.Components import qs.Components
import qs.Modules.Bar.Components.Common
import qs.Helpers import qs.Helpers
import ZShell.Config
import qs.Services import qs.Services
WidgetBase { CustomRect {
id: root id: root
property bool tempEnabled: Hyprsunset.enabled property bool tempEnabled: Hyprsunset.enabled
color: root.tempEnabled ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer color: root.tempEnabled ? Colors.palette.m3primary : Colors.tPalette.m3surfaceContainer
implicitHeight: Config.bar.height + Tokens.padding.smallest * 2
implicitWidth: implicitHeight
radius: Tokens.rounding.full radius: Tokens.rounding.full
StateLayer { StateLayer {
@@ -25,7 +26,6 @@ WidgetBase {
animate: true animate: true
color: root.tempEnabled ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface color: root.tempEnabled ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
fill: root.tempEnabled ? 1 : 0 fill: root.tempEnabled ? 1 : 0
font.pointSize: Tokens.font.size.larger
text: root.tempEnabled ? "lightbulb" : "light_off" text: root.tempEnabled ? "lightbulb" : "light_off"
Behavior on fill { Behavior on fill {
+33 -84
View File
@@ -1,36 +1,28 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick
import Quickshell import Quickshell
import ZShell.Config import QtQuick
import qs.Components
import qs.Services
import qs.Modules.Launcher.Items
import qs.Modules.Launcher.Services import qs.Modules.Launcher.Services
import qs.Modules.Launcher.Items
import qs.Components
import ZShell.Config
import qs.Services
CustomListView { CustomListView {
id: root id: root
readonly property string displayState: stateForText(displayText)
property string displayText
readonly property string requestedState: stateForText(search.text)
required property SearchBar search required property SearchBar search
required property PersistentProperties visibilities required property PersistentProperties visibilities
function resultsForText(text: string): var { highlightFollowsCurrentItem: false
switch (stateForText(text)) { highlightRangeMode: ListView.ApplyRange
case "actions": implicitHeight: (Config.launcher.sizes.itemHeight + spacing) * Math.min(Config.launcher.maxAppsShown, count) - spacing
return Actions.query(text); orientation: Qt.Vertical
case "calc": preferredHighlightBegin: 0
return [0]; preferredHighlightEnd: height
case "variant": spacing: Tokens.spacing.small
return SchemeVariants.query(text); state: {
default: const text = search.text;
return Apps.search(text);
}
}
function stateForText(text: string): string {
const prefix = Config.launcher.actionPrefix; const prefix = Config.launcher.actionPrefix;
if (text.startsWith(prefix)) { if (text.startsWith(prefix)) {
for (const action of ["calc", "scheme", "variant"]) for (const action of ["calc", "scheme", "variant"])
@@ -42,20 +34,6 @@ CustomListView {
return "apps"; return "apps";
} }
function syncDisplayText(): void {
if (visibilities.launcher && requestedState === displayState)
displayText = search.text;
}
highlightFollowsCurrentItem: false
highlightRangeMode: ListView.ApplyRange
implicitHeight: (Config.launcher.sizes.itemHeight + spacing) * Math.min(Config.launcher.maxAppsShown, count) - spacing
orientation: Qt.Vertical
preferredHighlightBegin: 0
preferredHighlightEnd: height
spacing: Tokens.spacing.small
state: visibilities.launcher ? requestedState : displayState
verticalLayoutDirection: ListView.BottomToTop verticalLayoutDirection: ListView.BottomToTop
CustomScrollBar.vertical: CustomScrollBar { CustomScrollBar.vertical: CustomScrollBar {
@@ -66,21 +44,19 @@ CustomListView {
Anim { Anim {
from: 0 from: 0
property: "opacity" properties: "opacity,scale"
to: 1 to: 1
type: Anim.DefaultEffects
} }
} }
addDisplaced: Transition { addDisplaced: Transition {
Anim { Anim {
duration: Tokens.anim.durations.small
property: "y" property: "y"
type: Anim.StandardSmall
} }
Anim { Anim {
property: "opacity" properties: "opacity,scale"
to: 1 to: 1
type: Anim.DefaultEffects
} }
} }
displaced: Transition { displaced: Transition {
@@ -89,9 +65,8 @@ CustomListView {
} }
Anim { Anim {
property: "opacity" properties: "opacity,scale"
to: 1 to: 1
type: Anim.DefaultEffects
} }
} }
highlight: CustomRect { highlight: CustomRect {
@@ -99,18 +74,18 @@ CustomListView {
implicitHeight: root.currentItem?.implicitHeight ?? 0 implicitHeight: root.currentItem?.implicitHeight ?? 0
implicitWidth: root.width implicitWidth: root.width
opacity: 0.08 opacity: 0.08
radius: Tokens.rounding.medium radius: Tokens.rounding.smallest
y: root.currentItem?.y ?? 0 y: root.currentItem?.y ?? 0
Behavior on y { Behavior on y {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
} }
model: ScriptModel { model: ScriptModel {
values: root.resultsForText(root.displayText) id: model
onValuesChanged: root.currentIndex = 0 onValuesChanged: root.currentIndex = 0
} }
@@ -120,9 +95,8 @@ CustomListView {
} }
Anim { Anim {
property: "opacity" properties: "opacity,scale"
to: 1 to: 1
type: Anim.DefaultEffects
} }
} }
remove: Transition { remove: Transition {
@@ -130,9 +104,8 @@ CustomListView {
Anim { Anim {
from: 1 from: 1
property: "opacity" properties: "opacity,scale"
to: 0 to: 0
type: Anim.DefaultEffects
} }
} }
states: [ states: [
@@ -140,6 +113,7 @@ CustomListView {
name: "apps" name: "apps"
PropertyChanges { PropertyChanges {
model.values: Apps.search(search.text)
root.delegate: appItem root.delegate: appItem
} }
}, },
@@ -147,6 +121,7 @@ CustomListView {
name: "actions" name: "actions"
PropertyChanges { PropertyChanges {
model.values: Actions.query(search.text)
root.delegate: actionItem root.delegate: actionItem
} }
}, },
@@ -154,6 +129,7 @@ CustomListView {
name: "calc" name: "calc"
PropertyChanges { PropertyChanges {
model.values: [0]
root.delegate: calcItem root.delegate: calcItem
} }
}, },
@@ -161,6 +137,7 @@ CustomListView {
name: "variant" name: "variant"
PropertyChanges { PropertyChanges {
model.values: SchemeVariants.query(search.text)
root.delegate: variantItem root.delegate: variantItem
} }
} }
@@ -170,7 +147,7 @@ CustomListView {
ParallelAnimation { ParallelAnimation {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.standardAccel easing.bezierCurve: Tokens.anim.curves.expressiveEffects
from: 1 from: 1
property: "opacity" property: "opacity"
target: root target: root
@@ -179,7 +156,7 @@ CustomListView {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.standardAccel easing.bezierCurve: Tokens.anim.curves.expressiveEffects
from: 1 from: 1
property: "scale" property: "scale"
target: root target: root
@@ -188,24 +165,14 @@ CustomListView {
} }
PropertyAction { PropertyAction {
property: "delegate" properties: "values,delegate"
target: root targets: [model, root]
value: null
}
ScriptAction {
script: root.displayText = root.search.text
}
PropertyAction {
property: "delegate"
target: root
} }
ParallelAnimation { ParallelAnimation {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.standardDecel easing.bezierCurve: Tokens.anim.curves.expressiveEffects
from: 0 from: 0
property: "opacity" property: "opacity"
target: root target: root
@@ -214,7 +181,7 @@ CustomListView {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.standardDecel easing.bezierCurve: Tokens.anim.curves.expressiveEffects
from: 0.9 from: 0.9
property: "scale" property: "scale"
target: root target: root
@@ -230,8 +197,6 @@ CustomListView {
} }
} }
Component.onCompleted: displayText = search.text
Component { Component {
id: appItem id: appItem
@@ -263,20 +228,4 @@ CustomListView {
list: root list: root
} }
} }
Connections {
function onTextChanged() {
root.syncDisplayText();
}
target: root.search
}
Connections {
function onLauncherChanged() {
root.syncDisplayText();
}
target: root.visibilities
}
} }
-53
View File
@@ -1,53 +0,0 @@
import Quickshell
import QtQuick
import ZShell.Components
import ZShell.Config
import qs.Modules.Launcher.Items
import qs.Components
import qs.Helpers
CarouselView {
id: root
required property var panels
readonly property var screen: QsWindow.window?.screen
required property SearchBar search
readonly property var values: Wallpapers.query(root.search.text.split(" ").slice(1).join(" "))
required property var visibilities
currentIndex: {
const idx = Wallpapers.list.findIndex(w => w.path === Wallpapers.actualCurrent);
return idx >= 0 ? idx : 0;
}
delegateProperties: ({
visibilities: root.visibilities
})
focalWidth: Config.launcher.sizes.wallpaperWidth
glideDuration: 250
glideEasingType: Easing.OutCubic
implicitHeight: tileHeight + Tokens.spacing.small / 2 + Tokens.padding.large + Tokens.padding.small
itemSpacing: Tokens.spacing.small
maxWidth: {
if (!screen)
return 0;
const barMargins = Config.bar.border * 2;
let margins = Math.round(screen.width / 6);
if (visibilities.utilities || visibilities.sidebar)
margins = Config.sidebar.sizes.width;
return screen.width - (barMargins + margins) * 2 - Config.bar.rounding * 4;
}
minEdgeWidth: 56
model: values
tileHeight: focalWidth / 16 * 9
delegate: Component {
WallpaperTile {
}
}
Component.onDestruction: Wallpapers.stopPreview()
onCurrentItemChanged: {
if (currentItem)
Wallpapers.preview(currentItem.modelData.path);
}
}
+5 -5
View File
@@ -12,9 +12,9 @@ Item {
id: root id: root
required property real maxHeight required property real maxHeight
readonly property int padding: Tokens.padding.largeIncreased / 4 readonly property int padding: Tokens.padding.small
required property var panels required property var panels
readonly property int rounding: Tokens.rounding.largeIncreased readonly property int rounding: Tokens.rounding.large
required property PersistentProperties visibilities required property PersistentProperties visibilities
implicitHeight: search.height + listWrapper.height + padding * 2 implicitHeight: search.height + listWrapper.height + padding * 2
@@ -49,9 +49,9 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.margins: root.padding anchors.margins: root.padding
anchors.right: parent.right anchors.right: parent.right
bottomPadding: Tokens.padding.medium bottomPadding: Tokens.padding.larger
placeholderText: qsTr("Type \"%1\" for commands").arg(Config.launcher.actionPrefix) placeholderText: qsTr("Type \"%1\" for commands").arg(Config.launcher.actionPrefix)
topPadding: Tokens.padding.medium topPadding: Tokens.padding.larger
Component.onCompleted: forceActiveFocus() Component.onCompleted: forceActiveFocus()
Keys.onDownPressed: list.currentList?.decrementCurrentIndex() Keys.onDownPressed: list.currentList?.decrementCurrentIndex()
@@ -79,7 +79,7 @@ Item {
if (currentItem) { if (currentItem) {
if (list.showWallpapers) { if (list.showWallpapers) {
if (Colors.scheme === "dynamic" && currentItem.modelData.path !== Wallpapers.actualCurrent) if (Colors.scheme === "dynamic" && currentItem.modelData.path !== Wallpapers.actualCurrent)
Wallpapers.previewColorLock = true; Wallpapers.previewColourLock = true;
Wallpapers.setWallpaper(currentItem.modelData.path); Wallpapers.setWallpaper(currentItem.modelData.path);
root.visibilities.launcher = false; root.visibilities.launcher = false;
} else if (text.startsWith(Config.launcher.actionPrefix)) { } else if (text.startsWith(Config.launcher.actionPrefix)) {
+5 -5
View File
@@ -32,7 +32,7 @@ Item {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
Behavior on implicitWidth { Behavior on implicitWidth {
@@ -40,7 +40,7 @@ Item {
Anim { Anim {
duration: Tokens.anim.durations.small duration: Tokens.anim.durations.small
easing: Tokens.anim.expressiveDefaultEffects easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
Behavior on state { Behavior on state {
@@ -110,9 +110,9 @@ Item {
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top anchors.top: parent.top
width: root.implicitWidth
sourceComponent: CarouselView { sourceComponent: WallpaperList {
content: root.content
panels: root.panels panels: root.panels
search: root.search search: root.search
visibilities: root.visibilities visibilities: root.visibilities
@@ -127,7 +127,7 @@ Item {
opacity: root.currentList?.count === 0 ? 1 : 0 opacity: root.currentList?.count === 0 ? 1 : 0
padding: Tokens.padding.large padding: Tokens.padding.large
scale: root.currentList?.count === 0 ? 1 : 0.5 scale: root.currentList?.count === 0 ? 1 : 0.5
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
Behavior on opacity { Behavior on opacity {
Anim { Anim {
+6 -6
View File
@@ -16,7 +16,7 @@ Item {
implicitHeight: Config.launcher.sizes.itemHeight implicitHeight: Config.launcher.sizes.itemHeight
StateLayer { StateLayer {
radius: Tokens.rounding.small radius: Tokens.rounding.smallest
onClicked: { onClicked: {
root.modelData?.onClicked(root.list); root.modelData?.onClicked(root.list);
@@ -25,9 +25,9 @@ Item {
Item { Item {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.small anchors.leftMargin: Tokens.padding.larger
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.smaller
anchors.rightMargin: Tokens.padding.small anchors.rightMargin: Tokens.padding.larger
MaterialIcon { MaterialIcon {
id: icon id: icon
@@ -39,7 +39,7 @@ Item {
Item { Item {
anchors.left: icon.right anchors.left: icon.right
anchors.leftMargin: Tokens.spacing.medium anchors.leftMargin: Tokens.spacing.normal
anchors.verticalCenter: icon.verticalCenter anchors.verticalCenter: icon.verticalCenter
implicitHeight: name.implicitHeight + desc.implicitHeight implicitHeight: name.implicitHeight + desc.implicitHeight
implicitWidth: parent.width - icon.width implicitWidth: parent.width - icon.width
@@ -59,7 +59,7 @@ Item {
elide: Text.ElideRight elide: Text.ElideRight
font.pointSize: Tokens.font.size.small font.pointSize: Tokens.font.size.small
text: root.modelData?.desc ?? "" text: root.modelData?.desc ?? ""
width: root.width - icon.width - Tokens.rounding.medium * 2 width: root.width - icon.width - Tokens.rounding.normal * 2
} }
} }
} }
+6 -6
View File
@@ -19,7 +19,7 @@ Item {
implicitHeight: Config.launcher.sizes.itemHeight implicitHeight: Config.launcher.sizes.itemHeight
StateLayer { StateLayer {
radius: Tokens.rounding.small radius: Tokens.rounding.smallest
onClicked: { onClicked: {
Apps.launch(root.modelData); Apps.launch(root.modelData);
@@ -29,9 +29,9 @@ Item {
Item { Item {
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: Tokens.padding.medium anchors.leftMargin: Tokens.padding.larger
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.smaller
anchors.rightMargin: Tokens.padding.medium anchors.rightMargin: Tokens.padding.larger
IconImage { IconImage {
id: icon id: icon
@@ -43,7 +43,7 @@ Item {
Item { Item {
anchors.left: icon.right anchors.left: icon.right
anchors.leftMargin: Tokens.spacing.medium anchors.leftMargin: Tokens.spacing.normal
anchors.verticalCenter: icon.verticalCenter anchors.verticalCenter: icon.verticalCenter
implicitHeight: name.implicitHeight + comment.implicitHeight implicitHeight: name.implicitHeight + comment.implicitHeight
implicitWidth: parent.width - icon.width implicitWidth: parent.width - icon.width
@@ -63,7 +63,7 @@ Item {
elide: Text.ElideRight elide: Text.ElideRight
font.pointSize: Tokens.font.size.small font.pointSize: Tokens.font.size.small
text: (root.modelData?.comment || root.modelData?.genericName || root.modelData?.name) ?? "" text: (root.modelData?.comment || root.modelData?.genericName || root.modelData?.name) ?? ""
width: root.width - icon.width - Tokens.rounding.medium - Tokens.padding.medium * 2 width: root.width - icon.width - Tokens.rounding.normal * 2
} }
} }
+8 -8
View File
@@ -24,7 +24,7 @@ Item {
implicitHeight: Config.launcher.sizes.itemHeight implicitHeight: Config.launcher.sizes.itemHeight
StateLayer { StateLayer {
radius: Tokens.rounding.small radius: Tokens.rounding.smallest
onClicked: { onClicked: {
root.onClicked(); root.onClicked();
@@ -33,10 +33,10 @@ Item {
RowLayout { RowLayout {
anchors.left: parent.left anchors.left: parent.left
anchors.margins: Tokens.padding.small anchors.margins: Tokens.padding.larger
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
spacing: Tokens.spacing.medium spacing: Tokens.spacing.normal
MaterialIcon { MaterialIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
@@ -64,13 +64,13 @@ Item {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
clip: true clip: true
color: Colors.palette.m3tertiary color: Colors.palette.m3tertiary
implicitHeight: Math.max(label.implicitHeight, icon.implicitHeight) + Tokens.padding.extraSmall * 2 implicitHeight: Math.max(label.implicitHeight, icon.implicitHeight) + Tokens.padding.small * 2
implicitWidth: (stateLayer.containsMouse ? label.implicitWidth + label.anchors.rightMargin : 0) + icon.implicitWidth + Tokens.padding.small * 2 implicitWidth: (stateLayer.containsMouse ? label.implicitWidth + label.anchors.rightMargin : 0) + icon.implicitWidth + Tokens.padding.normal * 2
radius: Tokens.rounding.medium radius: Tokens.rounding.normal
Behavior on implicitWidth { Behavior on implicitWidth {
Anim { Anim {
easing: Tokens.anim.expressiveDefaultEffects easing.bezierCurve: Tokens.anim.curves.expressiveEffects
} }
} }
@@ -106,7 +106,7 @@ Item {
id: icon id: icon
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Tokens.padding.small anchors.rightMargin: Tokens.padding.normal
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
color: Colors.palette.m3onTertiary color: Colors.palette.m3onTertiary
font.pointSize: Tokens.font.size.large font.pointSize: Tokens.font.size.large

Some files were not shown because too many files have changed in this diff Show More