From 21b5972d46dcd492c81cb52f4d417925434da7e9 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Thu, 23 Apr 2026 21:54:06 +1000 Subject: [PATCH] feat: add circ prog end indicator --- components/controls/CircularProgress.qml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/components/controls/CircularProgress.qml b/components/controls/CircularProgress.qml index efeb1b4b..5a8acef2 100644 --- a/components/controls/CircularProgress.qml +++ b/components/controls/CircularProgress.qml @@ -1,3 +1,5 @@ +pragma ComponentBehavior: Bound + import QtQuick import QtQuick.Shapes import Caelestia.Components @@ -16,6 +18,7 @@ Item { property int spacing: Tokens.spacing.small property color fgColour: Colours.palette.m3primary property color bgColour: Colours.palette.m3secondaryContainer + property alias hasEndIndicator: dot.active property bool wavy: false property alias waveFrequency: wave.frequency @@ -27,6 +30,7 @@ Item { readonly property real arcRadius: (size - padding - strokeWidth * (1 + waveAmplitude * 2)) / 2 readonly property real clampedVal: Math.max(1 / 360, Math.min(1, value)) readonly property real gapAngle: ((spacing + strokeWidth) / (arcRadius || 1)) * (180 / Math.PI) + readonly property real dotAngleRad: (startAngle + sweepAngle - gapAngle * (sweepAngle < 360 ? 0 : 1)) * Math.PI / 180 readonly property real thickness: strokeWidth * (1 + waveAmplitude) * 2 // For consumers property real implicitSize @@ -53,7 +57,7 @@ Item { centerX: root.size / 2 centerY: root.size / 2 startAngle: root.startAngle + root.clampedVal * root.sweepAngle + root.gapAngle - sweepAngle: Math.max(1 / 360, root.sweepAngle * (1 - root.clampedVal) - root.gapAngle * 2) + sweepAngle: Math.max(1 / 360, root.sweepAngle * (1 - root.clampedVal) - root.gapAngle * (root.sweepAngle < 360 ? 1 : 2)) } Behavior on strokeColor { @@ -99,4 +103,19 @@ Item { } } } + + Loader { + id: dot + + x: root.size / 2 + root.arcRadius * Math.cos(root.dotAngleRad) - width / 2 + y: root.size / 2 + root.arcRadius * Math.sin(root.dotAngleRad) - height / 2 + + sourceComponent: StyledRect { + radius: Tokens.rounding.full + color: root.fgColour + opacity: Math.min(1, remainingArc.sweepAngle) + implicitWidth: Math.min(1, remainingArc.sweepAngle) * Math.min(4, root.strokeWidth) + implicitHeight: Math.min(1, remainingArc.sweepAngle) * Math.min(4, root.strokeWidth) + } + } }