summaryrefslogtreecommitdiff
path: root/popups/launcher/components/IComponent.qml
blob: c7b99b316ec6399f11c095e93881a781431eb7aa (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
136
import Quickshell
import QtQuick

import qs.components
import qs.config

IRect {
    id: root
    // virtual properties
    property bool standalone: false
    property var state: SelectionState
    property string name // Component/File name
    readonly property string _input: state.input
    readonly property string input: !standalone ? _input.slice(prefix.length) : _input
    readonly property string inputCleaned: input.toLowerCase().trim()
    property string prefix
    property bool active: !standalone ? input && _input.startsWith(prefix) : true
    property bool valid: !standalone ? processed?.valid || false : true
    property bool priority: !standalone ? valid && processed?.priority || false : true // please set priority to false if it's invalid
    property string answer: processed?.answer || ""
    property Component preview: Component {
        IText {
            // TODO: use proper active: false via Loader
            visible: answer.length <= Launcher.maxPreviewLen
            animate: true
            text: answer
        }
    }
    property string predictiveCompletion: processed?.predictiveCompletion || "" // would technically work with just from answer, but stuff like calc's answer wouldnt have anything to do with the input
    property var processed: active ? process() : {} // cached process, thought qml would do that automatically :/
    property var process: () => ({
                valid: valid,
                priority: priority,
                answer: answer,
                preview: preview,
                predictiveCompletion: predictiveCompletion
            })
    // use the current IRect if valid is set
    property var syncSelectionState: () => {}
    // actions
    property var up: () => ({
                top: true
            })
    property var down: () => ({
                bottom: true
            })
    property var prev: () => ({
                left: true
            })
    property var next: () => ({
                right: true
            })
    // true if not closed
    property var exec: () => {}
    property var home: () => ({
                top: true
            })
    property var end: () => ({
                bottom: true
            })
    property var pgup: () => ({
                top: true
            })
    property var pgdn: () => ({
                bottom: true
            })

    signal close

    function _exec() {
        if (!exec())
            close();
    }

    function getSelfPriority() {
        return state.priorities.indexOf(root);
    }

    function isSelectedPriority() {
        return state.selectedPriority === getSelfPriority();
    }

    function trySetSelfPriority() {
        let self = getSelfPriority();
        // ??? why tf is it -1 not null or undefined this is why rust is better
        if (self !== -1)
            state.selectedPriority = self;
    }

    // this doesn't change launcher size but only hides the actual content but the outside still think the content is there
    visible: active
    opacity: valid ? 1 : 0
    y: valid ? 0 : -Launcher.widgetHeight

    implicitWidth: valid ? Launcher.widgetWidth : 0
    implicitHeight: valid ? Launcher.widgetHeight : 0

    // implicitWidth: Launcher.widgetWidth
    // implicitHeight: Launcher.widgetHeight

    radius: Launcher.widgetRadius
    color: Qt.rgba(Colors.background3.r, Colors.background3.g, Colors.background3.b, Launcher.widgetBgTransparency) // TODO when prioritized, highlight

    onPriorityChanged: {
        // sync with state.priorities
        Qt.callLater(() => {
            if (!standalone)
                state.priorities = state.priorities.includes(root) ? state.priorities.filter(x => x !== root) : [...new Set(state.priorities), root];
            else
                state.priorities = [root];
        });
    }

    Behavior on y {
        NumberAnimation {
            duration: General.animationDuration / 4
            easing.type: Easing.InOutQuad
        }
    }

    HoverHandler {
        onHoveredChanged: {
            if (hovered)
                root.trySetSelfPriority();
            else
                root.syncSelectionState();
        }
    }

    // causes all of them fighting for selection state
    // Component.onCompleted: {
    //     Qt.callLater(() => {
    //         syncSelectionState();
    //     });
    // }
}