@@ -2,6 +2,7 @@ pragma ComponentBehavior: Bound
22
33import QtQuick
44import Quickshell
5+ import M3Shapes
56import Caelestia.Config
67import qs.components
78import qs.services
@@ -10,9 +11,19 @@ import qs.modules.lock
1011Item {
1112 id: root
1213
14+ required property real centerScale
1315 required property Pam pam
1416 readonly property alias placeholder: placeholder
17+ readonly property alias placeholderWidth: nonAnimPlaceholder .width
1518 property string buffer
19+ readonly property list< int> shapeQueue: {
20+ const shapes = [MaterialShape .Slanted , MaterialShape .Arch , MaterialShape .Fan , MaterialShape .Arrow , MaterialShape .SemiCircle , MaterialShape .Triangle , MaterialShape .Diamond , MaterialShape .ClamShell , MaterialShape .Pentagon , MaterialShape .Gem , MaterialShape .Sunny , MaterialShape .VerySunny , MaterialShape .Cookie4Sided , MaterialShape .Ghostish , MaterialShape .SoftBurst ];
21+ for (let i = shapes .length - 1 ; i > 0 ; i-- ) {
22+ const j = Math .floor (Math .random () * (i + 1 ));
23+ [shapes[i], shapes[j]] = [shapes[j], shapes[i]];
24+ }
25+ return shapes;
26+ }
1627
1728 clip: true
1829
@@ -31,22 +42,30 @@ Item {
3142 target: root .pam
3243 }
3344
34- StyledText {
35- id: placeholder
36-
37- anchors .centerIn : parent
45+ TextMetrics {
46+ id: nonAnimPlaceholder
3847
3948 text: {
4049 if (root .pam .passwd .active )
4150 return qsTr (" Loading..." );
4251 if (root .pam .state === " max" )
43- return qsTr (" You have reached the maximum number of tries " );
52+ return qsTr (" Max tries reached" );
4453 return qsTr (" Enter your password" );
4554 }
55+ font: placeholder .font
56+ }
57+
58+ StyledText {
59+ id: placeholder
60+
61+ anchors .centerIn : parent
62+ anchors .verticalCenterOffset : 1
63+
64+ text: nonAnimPlaceholder .text
4665
4766 animate: true
4867 color: root .pam .passwd .active ? Colours .palette .m3secondary : Colours .palette .m3outline
49- font: Tokens .font .mono . medium
68+ font: Tokens .font .body . builders . medium . scale ( root . centerScale ). width ( 110 ). build ()
5069
5170 opacity: root .buffer ? 0 : 1
5271
@@ -60,7 +79,12 @@ Item {
6079 ListView {
6180 id: charList
6281
63- readonly property int fullWidth: count * (implicitHeight + spacing) - spacing
82+ readonly property int fullWidth: {
83+ let w = (count - 1 ) * spacing;
84+ for (let i = 0 ; i < count; i++ )
85+ w += ((itemAtIndex (i) as CharItem)? .nonAnimWidthScale ?? 1 ) * implicitHeight;
86+ return w + implicitHeight; // Extra padding at ends
87+ }
6488
6589 function bindImWidth (): void {
6690 imWidthBehavior .enabled = false ;
@@ -82,68 +106,129 @@ Item {
82106 values: root .buffer .split (" " )
83107 }
84108
85- delegate: StyledRect {
86- id: ch
109+ delegate: CharItem {}
110+
111+ Behavior on implicitWidth {
112+ id: imWidthBehavior
113+
114+ Anim {}
115+ }
116+ }
117+
118+ component CharItem: Item {
119+ id: char
120+
121+ required property int index
122+ property real nonAnimWidthScale: 1
123+
124+ implicitHeight: charList .implicitHeight
125+
126+ ListView .onRemove : {
127+ initAnim .stop ();
128+ removeAnim .start ();
129+ }
87130
88- implicitWidth : implicitHeight
89- implicitHeight : charList . implicitHeight
131+ MaterialShape {
132+ id : charShape
90133
134+ anchors .centerIn : parent
135+ implicitSize: charList .implicitHeight * 1.5
136+ shape: root .shapeQueue [char .index % root .shapeQueue .length ] ?? MaterialShape .Circle
91137 color: Colours .palette .m3onSurface
92- radius: Tokens .rounding .medium / 2
93138
94- opacity: 0
95- scale: 0
96- Component .onCompleted : {
97- opacity = 1 ;
98- scale = 1 ;
139+ Behavior on color {
140+ CAnim {}
141+ }
142+
143+ SequentialAnimation {
144+ id: initAnim
145+
146+ running: true
147+
148+ ParallelAnimation {
149+ Anim {
150+ target: charShape
151+ property: " opacity"
152+ from: 0
153+ to: 1
154+ type: Anim .DefaultEffects
155+ }
156+ Anim {
157+ target: charShape
158+ property: " scale"
159+ from: 0
160+ to: 1
161+ type: Anim .FastSpatial
162+ }
163+ Anim {
164+ target: char
165+ property: " implicitWidth"
166+ from: charList .implicitHeight
167+ to: charList .implicitHeight * 1.3
168+ type: Anim .DefaultEffects
169+ }
170+ PropertyAction {
171+ target: char
172+ property: " nonAnimWidthScale"
173+ value: 1.5
174+ }
175+ }
176+ PauseAnimation {
177+ duration: 180 * Tokens .anim .durations .scale
178+ }
179+ PropertyAction {
180+ target: charShape
181+ property: " shape"
182+ value: MaterialShape .Circle
183+ }
184+ ParallelAnimation {
185+ Anim {
186+ target: charShape
187+ property: " scale"
188+ to: 2 / 3
189+ type: Anim .FastSpatial
190+ }
191+ Anim {
192+ target: char
193+ property: " implicitWidth"
194+ to: charList .implicitHeight
195+ type: Anim .DefaultEffects
196+ }
197+ PropertyAction {
198+ target: char
199+ property: " nonAnimWidthScale"
200+ value: 1
201+ }
202+ }
99203 }
100- ListView .onRemove : removeAnim .start ()
101204
102205 SequentialAnimation {
103206 id: removeAnim
104207
105208 PropertyAction {
106- target: ch
209+ target: char
107210 property: " ListView.delayRemove"
108211 value: true
109212 }
110213 ParallelAnimation {
111214 Anim {
112215 type: Anim .DefaultEffects
113- target: ch
216+ target: charShape
114217 property: " opacity"
115218 to: 0
116219 }
117220 Anim {
118- target: ch
221+ target: charShape
119222 property: " scale"
120223 to: 0.5
121224 }
122225 }
123226 PropertyAction {
124- target: ch
227+ target: char
125228 property: " ListView.delayRemove"
126229 value: false
127230 }
128231 }
129-
130- Behavior on opacity {
131- Anim {
132- type: Anim .DefaultEffects
133- }
134- }
135-
136- Behavior on scale {
137- Anim {
138- type: Anim .FastSpatial
139- }
140- }
141- }
142-
143- Behavior on implicitWidth {
144- id: imWidthBehavior
145-
146- Anim {}
147232 }
148233 }
149234}
0 commit comments