summaryrefslogtreecommitdiff
path: root/popups/launcher/components/DuckDuckGo.qml
blob: ee5b752081f6b46f1812fc22552e9c8236c05850 (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
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
import Quickshell
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

import qs.components
import qs.services
import qs.config

import core

IComponent {
	id: root

	property int cursorPosition: SelectionState.cursorPosition
	property bool expand: false

	implicitHeight: valid ? expand ? layout.implicitHeight + (Launcher.duckduckgoSpacing * 2) : Launcher.widgetHeight : 0

	name: "DuckDuckGo" // subclass of WebSearch in the future
	preview: Component {
		Icon {
			text: "🌐"
		}
	}

	onInputChanged: {
		// TODO: think of this should be part of rs backend .query fn
		DuckDuckGo.reset();
	}

	// TODO: decouple all query logic from process -> onInputCleanedChanged and resetting / temp state on speciifc input -> onInputChanged
	onInputCleanedChanged: {
		if (inputCleaned)
			DuckDuckGo.query(inputCleaned);
	}

	process: function () {
		const valid = DuckDuckGo.ok;
		const answer = DuckDuckGo.title || DuckDuckGo.description_html;
		return {
			valid,
			priority: valid,
			answer,
			predictiveCompletion: valid && inputCleaned.toLowerCase() != answer.toLowerCase().trim() ? ' is ' + answer : ''
		};
	}
	exec: function () {
		// FIXME: doesn't work as enter closes the launcher
		// if (!expand) {
		//     expand = true;
		//     return false;
		// } else
		Clip.copy(`${DuckDuckGo.title}\n${DuckDuckGo.description_html}`);
	}

	IInnerComponent {
		anchors.margins: Launcher.duckduckgoSpacing
		RowLayout {
			id: layout
			spacing: Launcher.duckduckgoSpacing
			Layout.fillWidth: true
			Layout.fillHeight: true

			Item {
				Layout.fillWidth: true
				Layout.fillHeight: true
				Layout.preferredWidth: 0
				Layout.maximumWidth: image.maxWidth
				Layout.minimumWidth: 0

				visible: image.status === Image.Ready

				Image {
					id: image
					property real maxWidth: status === Image.Ready ? implicitWidth : 0
					anchors.fill: parent
					scale: root.isSelectedPriority() ? 1.01 : 0.99

					fillMode: Image.PreserveAspectCrop

					opacity: status === Image.Ready ? 1 : 0

					source: DuckDuckGo.image
					asynchronous: true

					Behavior on opacity {
						NumberAnimation {
							duration: General.animationDuration / 4
						}
					}

					Behavior on maxWidth {
						ISpringAnimation {}
					}

					Behavior on scale {
						ISpringAnimation {}
					}
				}
			}

			ColumnLayout {
				Layout.preferredWidth: 3
				Layout.minimumWidth: 0
				Layout.fillHeight: true
				Layout.fillWidth: true

				spacing: Launcher.duckduckgoImageSpacing / 4

				ITextEdit {
					animate: true

					Layout.alignment: Qt.AlignTop
					Layout.fillWidth: true

					readOnly: true
					renderType: Text.CurveRendering
					visible: valid
					text: answer
					font {
						pixelSize: Launcher.widgetFontSize * 1.1
						bold: root.isSelectedPriority()
					}
				}

				ScrollView {
					id: scroll
					Layout.fillWidth: true
					Layout.fillHeight: true
					contentWidth: availableWidth
					clip: true

					ITextEdit {
						id: text

						animate: true

						height: scroll.contentHeight
						width: scroll.contentWidth

						readOnly: true
						renderType: Text.CurveRendering
						visible: valid && DuckDuckGo.title
						text: DuckDuckGo.title ? DuckDuckGo.description_html : ''
						font {
							pixelSize: Launcher.widgetFontSize
						}

						TapHandler {
							gesturePolicy: TapHandler.DragThreshold
							onTapped: expand = !expand
						}
					}
				}
			}
		}
	}

	Behavior on implicitHeight {
		ISpringAnimation {}
	}
}