-
-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathFamilyTransitionOverlay.qml
More file actions
397 lines (341 loc) · 16.1 KB
/
FamilyTransitionOverlay.qml
File metadata and controls
397 lines (341 loc) · 16.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
import QtQuick
import QtQuick.Effects
import Quickshell
import Quickshell.Wayland
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
import qs.services
// Family transition with blurred wallpaper backdrop
// Waffle: 4 tiles expand from center
// Material: Ripple circle expands from center
Scope {
id: root
signal exitComplete()
signal enterComplete()
readonly property int enterDuration: Appearance.animationsEnabled ? 400 : 10
readonly property int holdDuration: 250
readonly property int exitDuration: Appearance.animationsEnabled ? 450 : 10
property bool _isWaffle: false
property bool _phase: false
property bool _active: false
property real _overlayOpacity: 0
Connections {
target: GlobalStates
function onFamilyTransitionActiveChanged() {
if (GlobalStates.familyTransitionActive) {
fadeOut.stop()
root._isWaffle = GlobalStates.familyTransitionDirection === "left"
root._phase = false
root._active = true
root._overlayOpacity = 1
enterTimer.start()
}
}
}
Timer {
id: enterTimer
interval: root.enterDuration + 80
onTriggered: {
root.exitComplete()
holdTimer.start()
}
}
Timer {
id: holdTimer
interval: root.holdDuration
onTriggered: {
root._phase = true
fadeOut.restart()
}
}
NumberAnimation {
id: fadeOut
target: root
property: "_overlayOpacity"
to: 0
duration: root.exitDuration
easing.type: Easing.InOutCubic
onFinished: {
root._active = false
root.enterComplete()
}
}
Loader {
active: GlobalStates.familyTransitionActive || root._active
sourceComponent: PanelWindow {
visible: true
color: "transparent"
exclusionMode: ExclusionMode.Ignore
exclusiveZone: -1
anchors {
top: true
bottom: true
left: true
right: true
}
WlrLayershell.namespace: "quickshell:familyTransition"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive
implicitWidth: screen?.width ?? 1920
implicitHeight: screen?.height ?? 1080
Item {
id: content
anchors.fill: parent
opacity: root._overlayOpacity
Rectangle {
anchors.fill: parent
color: root._isWaffle ? Looks.colors.bg0 : Appearance.m3colors.m3background
opacity: 1
}
// Blurred wallpaper background
Item {
id: blurredBg
anchors.fill: parent
opacity: 1
Image {
id: wallpaperImg
anchors.fill: parent
source: {
// Use target family's wallpaper
let path = ""
if (root._isWaffle) {
// Going to Waffle - use waffle wallpaper (or main if shared)
const wBg = Config.options?.waffles?.background ?? {}
const useMain = wBg.useMainWallpaper ?? true
path = useMain
? (Config.options?.background?.wallpaperPath ?? "")
: (wBg.wallpaperPath ?? Config.options?.background?.wallpaperPath ?? "")
} else {
// Going to Material - use main wallpaper
path = Config.options?.background?.wallpaperPath ?? ""
}
if (!path) return ""
return path.startsWith("file://") ? path : "file://" + path
}
fillMode: Image.PreserveAspectCrop
asynchronous: true
cache: true
visible: false
}
MultiEffect {
anchors.fill: parent
source: wallpaperImg
visible: wallpaperImg.status === Image.Ready
blurEnabled: Appearance.effectsEnabled
blur: 0.8
blurMax: 64
saturation: 0.3
}
// Subtle tint overlay (only for Material, Waffle uses clean blur)
Rectangle {
anchors.fill: parent
color: Appearance.m3colors.m3background
opacity: root._isWaffle ? 0 : 0.3
visible: !root._isWaffle
}
}
// Family-specific transition effect
Loader {
anchors.fill: parent
sourceComponent: root._isWaffle ? waffleTransition : materialTransition
}
}
}
}
// ═══════════════════════════════════════════════════════════════════════
// WAFFLE - Fluent Reveal: Acrylic panel emerges from center
// ═══════════════════════════════════════════════════════════════════════
Component {
id: waffleTransition
Item {
id: waffleRoot
anchors.fill: parent
property bool expanded: false
property bool showContent: false
Component.onCompleted: Qt.callLater(() => expanded = true)
Timer {
interval: 250
running: waffleRoot.expanded
onTriggered: waffleRoot.showContent = true
}
// Acrylic panel - the main element
Rectangle {
id: acrylicPanel
anchors.centerIn: parent
width: waffleRoot.expanded && !root._phase ? 280 : 56
height: waffleRoot.expanded && !root._phase ? 200 : 56
radius: waffleRoot.expanded ? Looks.radius.xLarge : 28
color: ColorUtils.transparentize(Looks.colors.bg0, 0.12)
border.width: 1
border.color: ColorUtils.transparentize(Looks.colors.fg, 0.88)
opacity: root._phase ? 0 : 1
scale: root._phase ? 0.92 : 1
Behavior on width { NumberAnimation { duration: root._phase ? 280 : root.enterDuration; easing.type: Easing.OutCubic } }
Behavior on height { NumberAnimation { duration: root._phase ? 280 : root.enterDuration; easing.type: Easing.OutCubic } }
Behavior on radius { NumberAnimation { duration: root.enterDuration * 0.5; easing.type: Easing.OutQuad } }
Behavior on opacity { NumberAnimation { duration: root._phase ? 250 : 100 } }
Behavior on scale { NumberAnimation { duration: 280; easing.type: Easing.OutCubic } }
// Accent line at bottom
Rectangle {
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
width: waffleRoot.showContent && !root._phase ? 60 : 0
height: 3
radius: 1.5
color: Looks.colors.accent
opacity: root._phase ? 0 : 1
Behavior on width { NumberAnimation { duration: root._phase ? 150 : 300; easing.type: Easing.OutCubic } }
Behavior on opacity { NumberAnimation { duration: 150 } }
}
}
// Content
Column {
anchors.centerIn: parent
spacing: 14
opacity: root._phase ? 0 : (waffleRoot.showContent ? 1 : 0)
scale: root._phase ? 0.95 : (waffleRoot.showContent ? 1 : 0.9)
Behavior on opacity { NumberAnimation { duration: root._phase ? 150 : 220; easing.type: Easing.OutQuad } }
Behavior on scale { NumberAnimation { duration: root._phase ? 150 : 280; easing.type: Easing.OutCubic } }
// Windows logo
Image {
anchors.horizontalCenter: parent.horizontalCenter
width: 52
height: 52
source: `${Looks.iconsPath}/start-here.svg`
sourceSize: Qt.size(52, 52)
layer.enabled: Appearance.effectsEnabled
layer.effect: MultiEffect {
colorization: 1.0
colorizationColor: Looks.colors.fg
}
}
// Text
Column {
anchors.horizontalCenter: parent.horizontalCenter
spacing: 2
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: "Waffle"
font.pixelSize: 20
font.family: Looks.font.family.ui
font.weight: Font.DemiBold
color: Looks.colors.fg
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: "Windows 11 Style"
font.pixelSize: Looks.font.pixelSize.small
font.family: Looks.font.family.ui
color: Looks.colors.subfg
}
}
}
}
}
// ═══════════════════════════════════════════════════════════════════════
// MATERIAL II - Ripple circle expands from center
// ═══════════════════════════════════════════════════════════════════════
Component {
id: materialTransition
Item {
id: materialRoot
anchors.fill: parent
readonly property real maxRadius: Math.sqrt(width * width + height * height) / 2 + 100
property bool expanded: false
property bool showContent: false
Component.onCompleted: Qt.callLater(() => expanded = true)
Timer {
interval: 180
running: materialRoot.expanded
onTriggered: materialRoot.showContent = true
}
// Expanding ripple circle
Rectangle {
anchors.centerIn: parent
width: materialRoot.expanded && !root._phase ? materialRoot.maxRadius * 2 : 0
height: width
radius: width / 2
color: ColorUtils.transparentize(Appearance.colors.colPrimaryContainer, 0.4)
opacity: root._phase ? 0 : 1
Behavior on width { NumberAnimation { duration: root._phase ? root.exitDuration * 0.7 : root.enterDuration; easing.type: Easing.OutQuart } }
Behavior on opacity { NumberAnimation { duration: root.exitDuration; easing.type: Easing.OutQuad } }
}
// Secondary ripple ring
Rectangle {
anchors.centerIn: parent
width: materialRoot.expanded && !root._phase ? materialRoot.maxRadius * 2.1 : 0
height: width
radius: width / 2
color: "transparent"
border.width: 2
border.color: ColorUtils.transparentize(Appearance.colors.colPrimary, 0.7)
opacity: root._phase ? 0 : 1
Behavior on width { NumberAnimation { duration: root._phase ? root.exitDuration * 0.6 : root.enterDuration + 80; easing.type: Easing.OutQuart } }
Behavior on opacity { NumberAnimation { duration: root.exitDuration * 0.8 } }
}
// Center content
Column {
anchors.centerIn: parent
spacing: 14
opacity: root._phase ? 0 : (materialRoot.showContent ? 1 : 0)
scale: root._phase ? 0.9 : (materialRoot.showContent ? 1 : 0.75)
Behavior on opacity { NumberAnimation { duration: root._phase ? 200 : 280; easing.type: Easing.OutQuad } }
Behavior on scale { NumberAnimation { duration: root._phase ? 200 : 350; easing.type: Easing.OutCubic } }
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
width: 64
height: 64
radius: 32
color: Appearance.colors.colPrimaryContainer
Image {
anchors.centerIn: parent
width: 36
height: 36
source: Qt.resolvedUrl("assets/icons/illogical-impulse.svg")
sourceSize: Qt.size(36, 36)
layer.enabled: Appearance.effectsEnabled
layer.effect: MultiEffect {
colorization: 1.0
colorizationColor: Appearance.colors.colOnPrimaryContainer
}
}
}
Column {
anchors.horizontalCenter: parent.horizontalCenter
spacing: 2
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: "Material ii"
font.pixelSize: Appearance.font.pixelSize.title
font.family: Appearance.font.family.title
font.weight: Font.Medium
color: Appearance.m3colors.m3onSurface
layer.enabled: Appearance.effectsEnabled
layer.effect: MultiEffect {
shadowEnabled: true
shadowColor: Appearance.m3colors.darkmode ? "#000000" : "#FFFFFF"
shadowBlur: 0.8
shadowVerticalOffset: 1
}
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: "Material Design"
font.pixelSize: Appearance.font.pixelSize.small
font.family: Appearance.font.family.main
color: Appearance.m3colors.m3onSurface
opacity: 0.7
layer.enabled: Appearance.effectsEnabled
layer.effect: MultiEffect {
shadowEnabled: true
shadowColor: Appearance.m3colors.darkmode ? "#000000" : "#FFFFFF"
shadowBlur: 0.6
shadowVerticalOffset: 1
}
}
}
}
}
}
}