diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml
index ff342be5..27322172 100644
--- a/resources/qml/Completer.qml
+++ b/resources/qml/Completer.qml
@@ -11,6 +11,7 @@ Popup {
property string completerName
property var completer
property bool bottomToTop: true
+ property alias count: listView.count
signal completionClicked(string completion)
@@ -57,9 +58,9 @@ Popup {
completer = undefined;
}
}
- padding: 0
+ padding: 1
onAboutToShow: currentIndex = -1
- height: listView.contentHeight
+ height: listView.contentHeight + 2 // + 2 for the padding on top and bottom
Connections {
onTimelineChanged: completer = null
@@ -84,7 +85,7 @@ Popup {
anchors.fill: parent
hoverEnabled: true
- onEntered: popup.currentIndex = model.index
+ onPositionChanged: popup.currentIndex = model.index
onClicked: popup.completionClicked(completer.completionAt(model.index))
Ripple {
@@ -183,6 +184,7 @@ Popup {
color: colors.base
implicitHeight: popup.contentHeight
implicitWidth: popup.contentWidth
+ border.color: colors.mid
}
}
diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index fc50ea32..cb7d383f 100644
--- a/resources/qml/MessageInput.qml
+++ b/resources/qml/MessageInput.qml
@@ -98,29 +98,28 @@ Rectangle {
clip: true
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.VerticalFlick
- implicitWidth: textArea.width
- implicitHeight: textArea.height
- contentWidth: textArea.width
- contentHeight: textArea.height
+ implicitWidth: messageInput.width
+ implicitHeight: messageInput.height
+ contentWidth: messageInput.width
+ contentHeight: messageInput.height
TextArea {
- id: textArea
+ id: messageInput
property int completerTriggeredAt: -1
function insertCompletion(completion) {
- textArea.remove(completerTriggeredAt, cursorPosition);
- textArea.insert(cursorPosition, completion);
+ messageInput.remove(completerTriggeredAt, cursorPosition);
+ messageInput.insert(cursorPosition, completion);
}
function openCompleter(pos, type) {
completerTriggeredAt = pos;
popup.completerName = type;
popup.open();
- popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition));
+ popup.completer.setSearchString(messageInput.getText(completerTriggeredAt, cursorPosition));
}
- text: "asfkajsdf"
selectByMouse: true
placeholderText: qsTr("Write a message...")
//placeholderTextColor: colors.buttonText
@@ -152,7 +151,7 @@ Rectangle {
popup.close();
}
if (popup.opened)
- popup.completer.setSearchString(textArea.getText(completerTriggeredAt, cursorPosition));
+ popup.completer.setSearchString(messageInput.getText(completerTriggeredAt, cursorPosition));
}
onSelectionStartChanged: TimelineManager.timeline.input.updateState(selectionStart, selectionEnd, cursorPosition, text)
@@ -163,17 +162,21 @@ Rectangle {
if (event.matches(StandardKey.Paste)) {
TimelineManager.timeline.input.paste(false);
event.accepted = true;
+ } else if (event.key == Qt.Key_Space) {
+ if (popup.opened && popup.count <= 0)
+ popup.close();
+
} else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_U) {
- textArea.clear();
+ messageInput.clear();
} else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_P) {
- textArea.text = TimelineManager.timeline.input.previousText();
+ messageInput.text = TimelineManager.timeline.input.previousText();
} else if (event.modifiers == Qt.ControlModifier && event.key == Qt.Key_N) {
- textArea.text = TimelineManager.timeline.input.nextText();
+ messageInput.text = TimelineManager.timeline.input.nextText();
} else if (event.key == Qt.Key_At) {
- textArea.openCompleter(cursorPosition, "user");
+ messageInput.openCompleter(cursorPosition, "user");
popup.open();
} else if (event.key == Qt.Key_Colon) {
- textArea.openCompleter(cursorPosition, "emoji");
+ messageInput.openCompleter(cursorPosition, "emoji");
popup.open();
} else if (event.key == Qt.Key_Escape && popup.opened) {
completerTriggeredAt = -1;
@@ -186,13 +189,13 @@ Rectangle {
popup.completerName = "";
popup.close();
if (currentCompletion) {
- textArea.insertCompletion(currentCompletion);
+ messageInput.insertCompletion(currentCompletion);
event.accepted = true;
return ;
}
}
TimelineManager.timeline.input.send();
- textArea.clear();
+ messageInput.clear();
event.accepted = true;
} else if (event.key == Qt.Key_Tab) {
event.accepted = true;
@@ -201,19 +204,22 @@ Rectangle {
} else {
var pos = cursorPosition - 1;
while (pos > -1) {
- var t = textArea.getText(pos, pos + 1);
+ var t = messageInput.getText(pos, pos + 1);
console.log('"' + t + '"');
- if (t == '@' || t == ' ' || t == '\t') {
- textArea.openCompleter(pos, "user");
+ if (t == '@') {
+ messageInput.openCompleter(pos, "user");
+ return ;
+ } else if (t == ' ' || t == '\t') {
+ messageInput.openCompleter(pos + 1, "user");
return ;
} else if (t == ':') {
- textArea.openCompleter(pos, "emoji");
+ messageInput.openCompleter(pos, "emoji");
return ;
}
pos = pos - 1;
}
// At start of input
- textArea.openCompleter(0, "user");
+ messageInput.openCompleter(0, "user");
}
} else if (event.key == Qt.Key_Up && popup.opened) {
event.accepted = true;
@@ -226,33 +232,40 @@ Rectangle {
background: null
Connections {
- onTimelineChanged: {
- textArea.clear();
- textArea.append(TimelineManager.timeline.input.text());
- textArea.completerTriggeredAt = -1;
+ onActiveTimelineChanged: {
+ messageInput.clear();
+ messageInput.append(TimelineManager.timeline.input.text());
+ messageInput.completerTriggeredAt = -1;
popup.completerName = "";
+ messageInput.forceActiveFocus();
}
target: TimelineManager
}
Connections {
- onCompletionClicked: textArea.insertCompletion(completion)
+ onCompletionClicked: messageInput.insertCompletion(completion)
target: popup
}
Completer {
id: popup
- x: textArea.completerTriggeredAt >= 0 ? textArea.positionToRectangle(textArea.completerTriggeredAt).x : 0
- y: textArea.completerTriggeredAt >= 0 ? textArea.positionToRectangle(textArea.completerTriggeredAt).y - height : 0
+ x: messageInput.completerTriggeredAt >= 0 ? messageInput.positionToRectangle(messageInput.completerTriggeredAt).x : 0
+ y: messageInput.completerTriggeredAt >= 0 ? messageInput.positionToRectangle(messageInput.completerTriggeredAt).y - height : 0
}
Connections {
ignoreUnknownSignals: true
- onInsertText: textArea.insert(textArea.cursorPosition, text)
+ onInsertText: messageInput.insert(messageInput.cursorPosition, text)
target: TimelineManager.timeline ? TimelineManager.timeline.input : null
}
+ Connections {
+ ignoreUnknownSignals: true
+ onReplyChanged: messageInput.forceActiveFocus()
+ target: TimelineManager.timeline
+ }
+
MouseArea {
// workaround for wrong cursor shape on some platforms
anchors.fill: parent
@@ -284,7 +297,7 @@ Rectangle {
ToolTip.visible: hovered
ToolTip.text: qsTr("Emoji")
onClicked: emojiPopup.visible ? emojiPopup.close() : emojiPopup.show(emojiButton, function(emoji) {
- textArea.insert(textArea.cursorPosition, emoji);
+ messageInput.insert(messageInput.cursorPosition, emoji);
})
}
@@ -299,7 +312,7 @@ Rectangle {
ToolTip.text: qsTr("Send")
onClicked: {
TimelineManager.timeline.input.send();
- textArea.clear();
+ messageInput.clear();
}
}
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index 379b19fb..14d55b23 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -35,7 +35,7 @@ Page {
colors: palette
model: EmojiProxyModel {
- category: EmojiCategory.People
+ category: Emoji.Category.People
sourceModel: EmojiModel {
}
@@ -125,6 +125,13 @@ Page {
onTriggered: TimelineManager.timeline.saveMedia(messageContextMenu.eventId)
}
+ MenuItem {
+ visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker
+ height: visible ? implicitHeight : 0
+ text: qsTr("Open in external program")
+ onTriggered: TimelineManager.timeline.openMedia(messageContextMenu.eventId)
+ }
+
}
Rectangle {
diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml
index 17e698d6..4cb9eb10 100644
--- a/resources/qml/UserProfile.qml
+++ b/resources/qml/UserProfile.qml
@@ -10,10 +10,19 @@ ApplicationWindow {
property var profile
+ x: MainWindow.x + (MainWindow.width / 2) - (width / 2)
+ y: MainWindow.y + (MainWindow.height / 2) - (height / 2)
height: 650
width: 420
minimumHeight: 420
palette: colors
+ color: colors.window
+ title: profile.isGlobalUserProfile ? "Global User Profile" : "Room User Profile"
+
+ Shortcut {
+ sequence: StandardKey.Cancel
+ onActivated: userProfileDialog.close()
+ }
ColumnLayout {
id: contentL
@@ -32,13 +41,42 @@ ApplicationWindow {
onClicked: TimelineManager.openImageOverlay(TimelineManager.timeline.avatarUrl(userid), TimelineManager.timeline.data.id)
}
- Label {
+ TextInput {
+ id: displayUsername
+
+ property bool isUsernameEditingAllowed
+
+ readOnly: !isUsernameEditingAllowed
text: profile.displayName
- fontSizeMode: Text.HorizontalFit
font.pixelSize: 20
color: TimelineManager.userColor(profile.userid, colors.window)
font.bold: true
Layout.alignment: Qt.AlignHCenter
+ selectByMouse: true
+
+ onAccepted: {
+ profile.changeUsername(displayUsername.text)
+ displayUsername.isUsernameEditingAllowed = false
+ }
+
+ ImageButton {
+ visible: profile.isSelf
+ anchors.leftMargin: 5
+ anchors.left: displayUsername.right
+ anchors.verticalCenter: displayUsername.verticalCenter
+ image: displayUsername.isUsernameEditingAllowed ? ":/icons/icons/ui/checkmark.png" : ":/icons/icons/ui/edit.png"
+
+ onClicked: {
+ if (displayUsername.isUsernameEditingAllowed) {
+ profile.changeUsername(displayUsername.text)
+ displayUsername.isUsernameEditingAllowed = false
+ } else {
+ displayUsername.isUsernameEditingAllowed = true
+ displayUsername.focus = true
+ displayUsername.selectAll()
+ }
+ }
+ }
}
MatrixText {
diff --git a/resources/qml/delegates/PlayableMediaMessage.qml b/resources/qml/delegates/PlayableMediaMessage.qml
index be22687f..1534da2e 100644
--- a/resources/qml/delegates/PlayableMediaMessage.qml
+++ b/resources/qml/delegates/PlayableMediaMessage.qml
@@ -194,7 +194,6 @@ Rectangle {
Text {
Layout.fillWidth: true
text: model.data.body
- textFormat: Text.PlainText
elide: Text.ElideRight
color: colors.text
}
diff --git a/resources/qml/emoji/EmojiPicker.qml b/resources/qml/emoji/EmojiPicker.qml
index e0e1ceaf..7c75e010 100644
--- a/resources/qml/emoji/EmojiPicker.qml
+++ b/resources/qml/emoji/EmojiPicker.qml
@@ -126,7 +126,7 @@ Popup {
interval: 350 // tweak as needed?
onTriggered: {
emojiPopup.model.filter = emojiSearch.text;
- emojiPopup.model.category = EmojiCategory.Search;
+ emojiPopup.model.category = Emoji.Category.Search;
}
}
@@ -178,42 +178,42 @@ Popup {
// TODO: Would like to get 'simple' icons for the categories
ListElement {
image: ":/icons/icons/emoji-categories/people.png"
- category: EmojiCategory.People
+ category: Emoji.Category.People
}
ListElement {
image: ":/icons/icons/emoji-categories/nature.png"
- category: EmojiCategory.Nature
+ category: Emoji.Category.Nature
}
ListElement {
image: ":/icons/icons/emoji-categories/foods.png"
- category: EmojiCategory.Food
+ category: Emoji.Category.Food
}
ListElement {
image: ":/icons/icons/emoji-categories/activity.png"
- category: EmojiCategory.Activity
+ category: Emoji.Category.Activity
}
ListElement {
image: ":/icons/icons/emoji-categories/travel.png"
- category: EmojiCategory.Travel
+ category: Emoji.Category.Travel
}
ListElement {
image: ":/icons/icons/emoji-categories/objects.png"
- category: EmojiCategory.Objects
+ category: Emoji.Category.Objects
}
ListElement {
image: ":/icons/icons/emoji-categories/symbols.png"
- category: EmojiCategory.Symbols
+ category: Emoji.Category.Symbols
}
ListElement {
image: ":/icons/icons/emoji-categories/flags.png"
- category: EmojiCategory.Flags
+ category: Emoji.Category.Flags
}
}
@@ -224,21 +224,21 @@ Popup {
hoverEnabled: true
ToolTip.text: {
switch (model.category) {
- case EmojiCategory.People:
+ case Emoji.Category.People:
return qsTr('People');
- case EmojiCategory.Nature:
+ case Emoji.Category.Nature:
return qsTr('Nature');
- case EmojiCategory.Food:
+ case Emoji.Category.Food:
return qsTr('Food');
- case EmojiCategory.Activity:
+ case Emoji.Category.Activity:
return qsTr('Activity');
- case EmojiCategory.Travel:
+ case Emoji.Category.Travel:
return qsTr('Travel');
- case EmojiCategory.Objects:
+ case Emoji.Category.Objects:
return qsTr('Objects');
- case EmojiCategory.Symbols:
+ case Emoji.Category.Symbols:
return qsTr('Symbols');
- case EmojiCategory.Flags:
+ case Emoji.Category.Flags:
return qsTr('Flags');
}
}
@@ -295,7 +295,7 @@ Popup {
ToolTip.visible: hovered
onClicked: {
// clear any filters
- emojiPopup.model.category = EmojiCategory.Search;
+ emojiPopup.model.category = Emoji.Category.Search;
gridView.positionViewAtBeginning();
emojiSearch.forceActiveFocus();
}
|