summaryrefslogtreecommitdiff
path: root/modules/utilities/toasts/Toasts.qml
blob: c23790d0022d819b15320500e7158ececa88ca5c (plain)
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
pragma ComponentBehavior: Bound

import qs.components
import qs.config
import Caelestia
import Quickshell
import QtQuick
import QtQuick.Layouts

Item {
    id: root

    readonly property int spacing: Appearance.spacing.small
    property bool flag

    implicitWidth: Config.utilities.sizes.width - Appearance.padding.normal * 2
    implicitHeight: {
        let h = -spacing;
        for (let i = 0; i < repeater.count; i++) {
            const item = repeater.itemAt(i);
            if (!item.modelData.closed && !item.previewHidden)
                h += item.implicitHeight + spacing;
        }
        return h;
    }

    Repeater {
        id: repeater

        model: ScriptModel {
            values: {
                const toasts = [];
                let count = 0;
                for (const toast of Toaster.toasts) {
                    toasts.push(toast);
                    if (!toast.closed) {
                        count++;
                        if (count > Config.utilities.maxToasts)
                            break;
                    }
                }
                return toasts;
            }
            onValuesChanged: root.flagChanged()
        }

        MouseArea {
            id: toast

            required property int index
            required property Toast modelData

            readonly property bool previewHidden: {
                let extraHidden = 0;
                for (let i = 0; i < index; i++)
                    if (Toaster.toasts[i].closed)
                        extraHidden++;
                return index >= Config.utilities.maxToasts + extraHidden;
            }

            opacity: modelData.closed || previewHidden ? 0 : 1
            scale: modelData.closed || previewHidden ? 0.7 : 1

            anchors.bottomMargin: {
                root.flag; // Force update
                let y = 0;
                for (let i = 0; i < index; i++) {
                    const item = repeater.itemAt(i);
                    if (item && !item.modelData.closed && !item.previewHidden)
                        y += item.implicitHeight + root.spacing;
                }
                return y;
            }

            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            implicitHeight: toastInner.implicitHeight

            acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
            onClicked: modelData.close()

            Component.onCompleted: modelData.lock(this)

            Anim {
                Component.onCompleted: running = !toast.previewHidden

                target: toast
                properties: "opacity,scale"
                from: 0
                to: 1
                duration: Appearance.anim.durations.expressiveDefaultSpatial
                easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
            }

            ParallelAnimation {
                running: toast.modelData.closed
                onStarted: toast.anchors.bottomMargin = toast.anchors.bottomMargin
                onFinished: toast.modelData.unlock(toast)

                Anim {
                    target: toast
                    property: "opacity"
                    to: 0
                }
                Anim {
                    target: toast
                    property: "scale"
                    to: 0.7
                }
            }

            ToastItem {
                id: toastInner

                modelData: toast.modelData
            }

            Behavior on opacity {
                Anim {}
            }

            Behavior on scale {
                Anim {}
            }

            Behavior on anchors.bottomMargin {
                Anim {
                    duration: Appearance.anim.durations.expressiveDefaultSpatial
                    easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
                }
            }
        }
    }
}