From 31d435e6f4865a72e6c9c6b36a4326fd89201208 Mon Sep 17 00:00:00 2001 From: Black Hat Date: Tue, 10 Jul 2018 12:18:21 +0800 Subject: [PATCH] Separate different message delegates. --- matrix/controller.cpp | 4 + matrix/controller.h | 2 + qml/component/ImageBubble.qml | 52 ++++++++++++ qml/component/MessageBubble.qml | 59 ++++++++++++++ qml/component/MessageDelegate.qml | 126 +++++------------------------- qml/component/SideNavButton.qml | 2 +- qml/component/StateBubble.qml | 24 ++++++ qml/form/ListForm.qml | 2 +- qml/form/RoomForm.qml | 11 ++- qml/main.qml | 2 +- res.qrc | 3 + 11 files changed, 170 insertions(+), 117 deletions(-) create mode 100644 qml/component/ImageBubble.qml create mode 100644 qml/component/MessageBubble.qml create mode 100644 qml/component/StateBubble.qml diff --git a/matrix/controller.cpp b/matrix/controller.cpp index d882ef5..0e940c8 100644 --- a/matrix/controller.cpp +++ b/matrix/controller.cpp @@ -51,6 +51,10 @@ void Controller::logout() { setIsLogin(false); } +void Controller::uploadFile(QString filename) { + m_connection->uploadFile(filename); +} + void Controller::connected() { qDebug() << "Logged in."; setHomeserver(m_connection->homeserver().toString()); diff --git a/matrix/controller.h b/matrix/controller.h index 0cf5f14..896a346 100644 --- a/matrix/controller.h +++ b/matrix/controller.h @@ -32,6 +32,8 @@ class Controller : public QObject { Q_INVOKABLE void loginWithCredentials(QString, QString, QString); Q_INVOKABLE void logout(); + Q_INVOKABLE void uploadFile(QString); + // All the non-Q_INVOKABLE functions. // All the Q_PROPERTYs. diff --git a/qml/component/ImageBubble.qml b/qml/component/ImageBubble.qml new file mode 100644 index 0000000..14e67ae --- /dev/null +++ b/qml/component/ImageBubble.qml @@ -0,0 +1,52 @@ +import QtQuick 2.11 +import QtQuick.Controls 2.4 +import QtQuick.Controls.Material 2.4 + +Row { + id: messageRow + + spacing: 6 + + ImageStatus { + id: avatar + + width: height + height: 40 + round: false + visible: !sentByMe + source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null + displayText: author.displayName + + MouseArea { + anchors.fill: parent + + hoverEnabled: true + ToolTip.visible: containsMouse + ToolTip.text: author.displayName + } + } + + Rectangle { + id: messageRect + + width: messageImage.implicitWidth + 24 + height: messageImage.implicitHeight + 24 + + color: sentByMe ? "lightgrey" : Material.accent + + Image { + id: messageImage + anchors.centerIn: parent + source: "image://mxc/" + content.url + + MouseArea { + anchors.fill: parent + + hoverEnabled: true + propagateComposedEvents: true + ToolTip.visible: containsMouse + ToolTip.text: content.body + } + } + } +} diff --git a/qml/component/MessageBubble.qml b/qml/component/MessageBubble.qml new file mode 100644 index 0000000..f8c0806 --- /dev/null +++ b/qml/component/MessageBubble.qml @@ -0,0 +1,59 @@ +import QtQuick 2.11 +import QtQuick.Controls 2.4 +import QtQuick.Controls.Material 2.4 + +Row { + readonly property bool isNotice: eventType === "notice" + + id: messageRow + + spacing: 6 + + ImageStatus { + id: avatar + + width: height + height: 40 + round: false + visible: !sentByMe && aboveAuthor !== author + source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null + displayText: author.displayName + + MouseArea { + anchors.fill: parent + + hoverEnabled: true + ToolTip.visible: containsMouse + ToolTip.text: author.displayName + } + } + + Rectangle { + width: height + height: 40 + color: "transparent" + visible: !sentByMe && aboveAuthor === author + } + + Rectangle { + id: messageRect + + width: Math.min(messageText.implicitWidth + 24, messageListView.width - (!sentByMe ? avatar.width + messageRow.spacing : 0)) + height: messageText.implicitHeight + 24 + + color: isNotice ? "transparent" : sentByMe ? "lightgrey" : Material.accent + border.color: Material.accent + border.width: isNotice ? 2 : 0 + + Label { + id: messageText + text: display + color: isNotice ? "black" : sentByMe ? "black" : "white" + anchors.fill: parent + anchors.margins: 12 + wrapMode: Label.Wrap + linkColor: isNotice ? Material.accent : sentByMe ? Material.accent : "white" + textFormat: Text.StyledText + } + } +} diff --git a/qml/component/MessageDelegate.qml b/qml/component/MessageDelegate.qml index b03cecd..aa1a106 100644 --- a/qml/component/MessageDelegate.qml +++ b/qml/component/MessageDelegate.qml @@ -3,22 +3,17 @@ import QtQuick.Controls 2.4 import QtQuick.Controls.Material 2.4 Item { + id: messageDelegate + readonly property bool sentByMe: author === currentRoom.localUser - anchors.right: messageRow.visible && sentByMe ? parent.right : undefined - anchors.horizontalCenter: stateText.visible ? parent.horizontalCenter : undefined + width: delegateLoader.width + height: delegateLoader.height - width: { - if (messageRow.visible) return messageRow.width - if (stateText.visible) return stateText.width - } - height: { - if (messageRow.visible) return messageRow.height - if (stateText.visible) return stateText.height - } + anchors.right: (eventType === "message" || eventType === "image") && sentByMe ? parent.right : undefined + anchors.horizontalCenter: (eventType === "state" || eventType === "emote") ? parent.horizontalCenter : undefined MouseArea { - id: baseMouseArea anchors.fill: parent ToolTip.visible: pressed @@ -26,105 +21,20 @@ Item { ToolTip.text: time } - Row { - id: messageRow - visible: eventType === "message" || eventType === "image" || eventType === "notice" + Loader { + id: delegateLoader - spacing: 6 - - ImageStatus { - id: avatar - - width: height - height: 40 - round: false - visible: !sentByMe - source: author.avatarUrl != "" ? "image://mxc/" + author.avatarUrl : null - displayText: author.displayName - - MouseArea { - anchors.fill: parent - - hoverEnabled: true - ToolTip.visible: containsMouse - ToolTip.text: author.displayName + source: { + switch (eventType) { + case "notice": + case "message": + return "MessageBubble.qml" + case "image": + return "ImageBubble.qml" + case "emote": + case "state": + return "StateBubble.qml" } } - - Rectangle { - id: messageRect - - width: { - if (eventType === "image") return messageImage.width + 24 - if (eventType === "message") - return Math.min(messageText.implicitWidth + 24, messageListView.width - (!sentByMe ? avatar.width + messageRow.spacing : 0)) - if (eventType === "notice") - return Math.min(noticeText.implicitWidth + 24, messageListView.width - (!sentByMe ? avatar.width + messageRow.spacing : 0)) - } - height: { - if (eventType === "image") return messageImage.height + 24 - if (eventType === "message") return messageText.implicitHeight + 24 - if (eventType === "notice") return noticeText.implicitHeight + 24 - } - - color: noticeText.visible ? "transparent" : sentByMe ? "lightgrey" : Material.accent - border.color: Material.accent - border.width: noticeText.visible ? 2 : 0 - - Label { - id: messageText - visible: eventType === "message" - text: display - color: sentByMe ? "black" : "white" - anchors.fill: parent - anchors.margins: 12 - wrapMode: Label.Wrap - textFormat: Text.RichText - } - - Label { - id: noticeText - visible: eventType === "notice" - text: display - color: "black" - anchors.fill: parent - anchors.margins: 12 - wrapMode: Label.Wrap - textFormat: Text.RichText - } - - Image { - id: messageImage - anchors.centerIn: parent - visible: eventType === "image" - source: visible? "image://mxc/" + content.url : "" - - MouseArea { - anchors.fill: parent - - hoverEnabled: true - propagateComposedEvents: true - ToolTip.visible: containsMouse - ToolTip.text: visible ? content.body : "" - } - } - } - } - - Label { - id: stateText - visible: eventType === "state" || eventType === "emote" - width: Math.min(implicitWidth, messageListView.width) - height: implicitHeight - padding: 12 - text: author.displayName + " " + display - color: eventType === "state" ? "black" : "white" - wrapMode: Label.Wrap - textFormat: Text.StyledText - - background: Rectangle { - anchors.fill: parent - color: eventType === "state" ? "lightgrey" : Material.accent - } } } diff --git a/qml/component/SideNavButton.qml b/qml/component/SideNavButton.qml index 43cd3c9..7e04fa0 100644 --- a/qml/component/SideNavButton.qml +++ b/qml/component/SideNavButton.qml @@ -29,7 +29,7 @@ Item { anchors.fill: parent onClicked: { - if(!page && stackView.currentItem !== page) { + if(page && stackView.currentItem !== page) { if(stackView.depth === 1) { stackView.replace(page) } else { diff --git a/qml/component/StateBubble.qml b/qml/component/StateBubble.qml new file mode 100644 index 0000000..59d585b --- /dev/null +++ b/qml/component/StateBubble.qml @@ -0,0 +1,24 @@ +import QtQuick 2.11 +import QtQuick.Controls 2.4 +import QtQuick.Controls.Material 2.4 + +Rectangle { + readonly property bool isEmote: eventType === "emote" + + id: stateRect + + width: Math.min(stateText.implicitWidth + 24, messageListView.width) + height: stateText.implicitHeight + 24 + + color: isEmote ? Material.accent : "lightgrey" + + Label { + id: stateText + text: "" + author.displayName + " " + display + color: isEmote ? "white" : "black" + anchors.fill: parent + anchors.margins: 12 + wrapMode: Label.Wrap + textFormat: Text.StyledText + } +} diff --git a/qml/form/ListForm.qml b/qml/form/ListForm.qml index 14492e3..dc8daee 100644 --- a/qml/form/ListForm.qml +++ b/qml/form/ListForm.qml @@ -125,7 +125,7 @@ Item { height: parent.height } - Text { + Label { height: parent.height visible: !mini text: "Search" diff --git a/qml/form/RoomForm.qml b/qml/form/RoomForm.qml index 9d7873d..c106305 100644 --- a/qml/form/RoomForm.qml +++ b/qml/form/RoomForm.qml @@ -89,6 +89,7 @@ Item { displayMarginBeginning: 40 displayMarginEnd: 40 verticalLayoutDirection: ListView.BottomToTop + maximumFlickVelocity: 1024 spacing: 12 model: MessageEventModel{ @@ -98,13 +99,11 @@ Item { onRoomChanged: if (room.timelineSize === 0) room.getPreviousContent(50) } - delegate: MessageDelegate { - - } + delegate: MessageDelegate {} onAtYBeginningChanged: if (atYBeginning && currentRoom) currentRoom.getPreviousContent(50) - ScrollBar.vertical: ScrollBar { /*anchors.left: messageListView.right*/ } + ScrollBar.vertical: ScrollBar {} Behavior on contentY { PropertyAnimation { easing.type: Easing.InOutCubic; duration: 200 } @@ -125,7 +124,7 @@ Item { color: "white" } - opacity: hovered ? 0.7 : 0.4 + opacity: pressed ? 1 : hovered ? 0.7 : 0.4 Material.background: Qt.lighter(Material.accent) onClicked: parent.positionViewAtBeginning() @@ -188,7 +187,7 @@ Item { type = "m.emote" } -// var parsedText = Markdown.markdown_parser(text) + // var parsedText = Markdown.markdown_parser(text) currentRoom.postMessage(type, text) } } diff --git a/qml/main.qml b/qml/main.qml index 5e45dc1..d14de15 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -118,7 +118,7 @@ ApplicationWindow { anchors.fill: parent anchors.margins: 15 - source: matriqueController.connection.localUser && matriqueController.connection.localUser.avatarUrl ? "image://mxc/" + matriqueController.connection.localUser.avatarUrl : "" + source: matriqueController.isLogin ? matriqueController.connection.localUser && matriqueController.connection.localUser.avatarUrl ? "image://mxc/" + matriqueController.connection.localUser.avatarUrl : "" : "qrc:/asset/img/avatar.png" displayText: matriqueController.connection.localUser && matriqueController.connection.localUser.displayText ? matriqueController.connection.localUser.displayText : "N" opaqueBackground: false } diff --git a/res.qrc b/res.qrc index 1c2d3ab..6ecdb60 100644 --- a/res.qrc +++ b/res.qrc @@ -18,5 +18,8 @@ asset/img/icon.png js/md.js qml/component/MessageDelegate.qml + qml/component/MessageBubble.qml + qml/component/ImageBubble.qml + qml/component/StateBubble.qml