matrixion/qml/Completer.qml

271 lines
10 KiB
QML
Raw Normal View History

2021-03-05 02:35:15 +03:00
// SPDX-FileCopyrightText: 2021 Nheko Contributors
// SPDX-FileCopyrightText: 2022 Nheko Contributors
2021-03-05 02:35:15 +03:00
// SPDX-License-Identifier: GPL-3.0-or-later
2022-04-14 16:28:17 +03:00
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import im.nheko
import im.nheko
2022-04-16 03:13:01 +03:00
import "ui"
2020-11-20 03:22:36 +03:00
2022-02-21 06:06:49 +03:00
Control {
2020-11-20 03:22:36 +03:00
id: popup
2021-02-23 19:06:21 +03:00
property int avatarHeight: 24
property int avatarWidth: 24
2022-04-16 03:13:01 +03:00
property bool bottomToTop: true
property bool centerRowContent: true
property var completer
property string completerName
property alias count: listView.count
property alias currentIndex: listView.currentIndex
property bool fullWidth: false
property int rowMargin: 0
property int rowSpacing: 5
2020-11-20 03:22:36 +03:00
2020-11-24 19:32:45 +03:00
signal completionClicked(string completion)
signal completionSelected(string id)
2020-11-24 19:32:45 +03:00
2022-04-16 03:13:01 +03:00
function currentCompletion() {
if (currentIndex > -1 && currentIndex < listView.count)
return completer.completionAt(currentIndex);
2020-11-24 04:35:38 +03:00
else
2022-04-16 03:13:01 +03:00
return null;
2020-11-24 04:35:38 +03:00
}
function down() {
if (bottomToTop)
up_();
else
down_();
}
function down_() {
2020-11-20 03:22:36 +03:00
currentIndex = currentIndex + 1;
2020-11-24 04:35:38 +03:00
if (currentIndex >= listView.count)
2020-11-20 03:22:36 +03:00
currentIndex = -1;
}
function finishCompletion() {
if (popup.completerName == "room")
popup.completionSelected(listView.itemAtIndex(currentIndex).modelData.roomid);
}
2022-04-16 03:13:01 +03:00
function up() {
if (bottomToTop)
down_();
else
up_();
}
function up_() {
currentIndex = currentIndex - 1;
if (currentIndex == -2)
currentIndex = listView.count - 1;
2020-11-20 03:22:36 +03:00
}
2022-03-01 03:59:06 +03:00
bottomPadding: 1
leftPadding: 1
rightPadding: 1
2022-04-16 03:13:01 +03:00
topPadding: 1
2022-02-21 06:06:49 +03:00
2022-04-16 03:13:01 +03:00
background: Rectangle {
border.color: timelineRoot.palette.mid
color: timelineRoot.palette.base
}
2022-02-21 06:06:49 +03:00
contentItem: ListView {
2020-11-24 04:35:38 +03:00
id: listView
2022-04-16 03:13:01 +03:00
clip: true
highlightFollowsCurrentItem: true
2020-11-20 03:22:36 +03:00
2022-04-16 03:13:01 +03:00
// If we have fewer than 7 items, just use the list view's content height.
2022-02-21 06:06:49 +03:00
// Otherwise, we want to show 7 items. Each item consists of row spacing between rows, row margins
// on each side of a row, 1px of padding above the first item and below the last item, and nominally
// some kind of content height. avatarHeight is used for just about every delegate, so we're using
// that until we find something better. Put is all together and you have the formula below!
2022-04-16 03:13:01 +03:00
implicitHeight: Math.min(contentHeight, 6 * rowSpacing + 7 * (popup.avatarHeight + 2 * rowMargin))
2022-02-21 06:06:49 +03:00
implicitWidth: listView.contentItem.childrenRect.width
2020-11-24 04:35:38 +03:00
model: completer
pixelAligned: true
2022-04-16 03:13:01 +03:00
reuseItems: true
spacing: rowSpacing
verticalLayoutDirection: popup.bottomToTop ? ListView.BottomToTop : ListView.TopToBottom
2020-11-20 03:22:36 +03:00
2020-11-24 04:35:38 +03:00
delegate: Rectangle {
property variant modelData: model
2022-04-11 05:18:16 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlight : timelineRoot.palette.base
height: chooser.child.implicitHeight + 2 * popup.rowMargin
2022-03-01 03:59:06 +03:00
implicitWidth: fullWidth ? ListView.view.width : chooser.child.implicitWidth + 4
2020-11-20 03:22:36 +03:00
2020-11-24 19:32:45 +03:00
MouseArea {
2021-01-12 04:22:40 +03:00
id: mouseArea
2020-11-24 19:32:45 +03:00
anchors.fill: parent
hoverEnabled: true
2022-04-16 03:13:01 +03:00
onClicked: {
2022-04-16 03:13:01 +03:00
popup.completionClicked(completer.completionAt(model.index));
if (popup.completerName == "room")
popup.completionSelected(model.roomid);
}
2022-04-16 03:13:01 +03:00
onPositionChanged: if (!listView.moving && !deadTimer.running)
popup.currentIndex = model.index
}
Ripple {
2022-04-11 05:18:16 +03:00
color: Qt.rgba(timelineRoot.palette.base.r, timelineRoot.palette.base.g, timelineRoot.palette.base.b, 0.5)
2020-11-24 19:32:45 +03:00
}
2020-11-24 04:35:38 +03:00
DelegateChooser {
id: chooser
anchors.fill: parent
anchors.margins: popup.rowMargin
enabled: false
2022-04-16 03:13:01 +03:00
roleValue: popup.completerName
2020-11-20 06:33:11 +03:00
2020-11-24 04:35:38 +03:00
DelegateChoice {
roleValue: "user"
2020-11-20 06:33:11 +03:00
2020-11-24 04:35:38 +03:00
RowLayout {
id: del
anchors.centerIn: parent
spacing: rowSpacing
2020-11-20 06:33:11 +03:00
2020-11-24 04:35:38 +03:00
Avatar {
displayName: model.displayName
2022-04-16 03:13:01 +03:00
height: popup.avatarHeight
2020-11-24 04:35:38 +03:00
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
2022-04-16 03:13:01 +03:00
userid: model.userid
width: popup.avatarWidth
2021-01-12 04:02:39 +03:00
onClicked: popup.completionClicked(completer.completionAt(model.index))
2020-11-24 04:35:38 +03:00
}
Label {
2022-04-11 05:18:16 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text
2022-04-16 03:13:01 +03:00
text: model.displayName
2020-11-20 06:33:11 +03:00
}
2020-11-24 21:06:31 +03:00
Label {
2022-04-15 06:53:41 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.placeholderText
2022-04-16 03:13:01 +03:00
text: "(" + model.userid + ")"
2020-11-24 21:06:31 +03:00
}
2020-11-20 03:22:36 +03:00
}
2020-11-24 04:35:38 +03:00
}
DelegateChoice {
roleValue: "emoji"
2020-11-20 06:33:11 +03:00
2020-11-24 04:35:38 +03:00
RowLayout {
id: del
anchors.centerIn: parent
spacing: rowSpacing
2020-11-20 06:33:11 +03:00
2020-11-24 04:35:38 +03:00
Label {
2022-04-11 05:18:16 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text
2020-11-24 04:35:38 +03:00
font: Settings.emojiFont
2022-04-16 03:13:01 +03:00
text: model.unicode
2020-11-24 04:35:38 +03:00
}
Label {
2022-04-11 05:18:16 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text
2022-04-16 03:13:01 +03:00
text: model.shortName
2020-11-20 06:33:11 +03:00
}
2020-11-20 03:22:36 +03:00
}
}
DelegateChoice {
roleValue: "customEmoji"
RowLayout {
id: del
anchors.centerIn: parent
spacing: rowSpacing
Avatar {
2022-04-16 03:13:01 +03:00
crop: false
displayName: model.shortcode
2022-04-16 03:13:01 +03:00
height: popup.avatarHeight
//userid: model.shortcode
url: model.url.replace("mxc://", "image://MxcImage/")
2022-04-16 03:13:01 +03:00
width: popup.avatarWidth
onClicked: popup.completionClicked(completer.completionAt(model.index))
}
Label {
2022-04-11 05:18:16 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text
2022-04-16 03:13:01 +03:00
text: model.shortcode
}
Label {
2022-04-15 06:53:41 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.placeholderText
2022-04-16 03:13:01 +03:00
text: "(" + model.packname + ")"
}
}
}
DelegateChoice {
roleValue: "room"
RowLayout {
id: del
anchors.centerIn: centerRowContent ? parent : undefined
spacing: rowSpacing
Avatar {
displayName: model.roomName
2022-04-16 03:13:01 +03:00
height: popup.avatarHeight
roomid: model.roomid
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
2022-04-16 03:13:01 +03:00
width: popup.avatarWidth
onClicked: {
popup.completionClicked(completer.completionAt(model.index));
popup.completionSelected(model.roomid);
}
}
Label {
2022-04-11 05:18:16 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text
2022-04-16 03:13:01 +03:00
font.pixelSize: popup.avatarHeight * 0.5
text: model.roomName
2021-06-06 00:20:23 +03:00
textFormat: Text.RichText
}
}
}
DelegateChoice {
roleValue: "roomAliases"
RowLayout {
id: del
anchors.centerIn: parent
spacing: rowSpacing
Avatar {
displayName: model.roomName
2022-04-16 03:13:01 +03:00
height: popup.avatarHeight
roomid: model.roomid
url: model.avatarUrl.replace("mxc://", "image://MxcImage/")
2022-04-16 03:13:01 +03:00
width: popup.avatarWidth
onClicked: popup.completionClicked(completer.completionAt(model.index))
}
Label {
2022-04-11 05:18:16 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text
2022-04-16 03:13:01 +03:00
text: model.roomName
2021-06-06 00:20:23 +03:00
textFormat: Text.RichText
}
Label {
2022-04-15 06:53:41 +03:00
color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.placeholderText
2022-04-16 03:13:01 +03:00
text: "(" + model.roomAlias + ")"
2021-06-06 00:20:23 +03:00
textFormat: Text.RichText
}
}
}
2020-11-20 03:22:36 +03:00
}
}
2022-04-16 03:13:01 +03:00
onContentYChanged: deadTimer.restart()
2020-11-20 03:22:36 +03:00
2022-04-16 03:13:01 +03:00
Timer {
id: deadTimer
interval: 50
}
2020-11-20 03:22:36 +03:00
}
2022-04-16 03:13:01 +03:00
onCompleterNameChanged: {
if (completerName) {
completer = TimelineManager.completerFor(completerName, completerName == "room" ? "" : room.roomId);
completer.setSearchString("");
} else {
completer = undefined;
}
currentIndex = -1;
}
2020-11-20 03:22:36 +03:00
}