diff --git a/imports/Spectral/Component/Timeline/MessageDelegate.qml b/imports/Spectral/Component/Timeline/MessageDelegate.qml index 40d04bf..601a18e 100644 --- a/imports/Spectral/Component/Timeline/MessageDelegate.qml +++ b/imports/Spectral/Component/Timeline/MessageDelegate.qml @@ -9,7 +9,7 @@ import Spectral.Setting 0.1 import Spectral.Component 2.0 import Spectral.Font 0.1 -RowLayout { +ColumnLayout { readonly property bool avatarVisible: !sentByMe && (aboveAuthor !== author || aboveSection !== section || aboveEventType === "state" || aboveEventType === "emote" || aboveEventType === "other") readonly property bool highlighted: !(sentByMe || eventType === "notice" ) readonly property bool sentByMe: author === currentRoom.localUser @@ -18,191 +18,223 @@ RowLayout { signal saveFileAs() signal openExternally() - z: -5 - - id: messageRow - Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft - spacing: 4 + id: root - ImageItem { - Layout.preferredWidth: 32 - Layout.preferredHeight: 32 - Layout.alignment: Qt.AlignTop + spacing: 0 + + Label { + Layout.leftMargin: 48 + + text: author.displayName visible: avatarVisible - hint: author.displayName - source: author.paintable + + font.pixelSize: 13 + font.weight: Font.Medium + verticalAlignment: Text.AlignVCenter } - Rectangle { - Layout.preferredWidth: 32 - Layout.preferredHeight: 32 - Layout.alignment: Qt.AlignTop + RowLayout { + Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft - color: "transparent" - visible: !(sentByMe || avatarVisible) - } + z: -5 - Control { - Layout.maximumWidth: messageListView.width - (!sentByMe ? 40 + messageRow.spacing : 0) - 48 + id: messageRow - topPadding: 8 - bottomPadding: 8 - leftPadding: 16 - rightPadding: 16 + spacing: 4 - background: Rectangle { - color: sentByMe ? "#009DC2" : (highlighted || eventType) === "notice" ? "#4285F4" : "#673AB7" - radius: 18 + ImageItem { + Layout.preferredWidth: 32 + Layout.preferredHeight: 32 + Layout.alignment: Qt.AlignTop - AutoMouseArea { - anchors.fill: parent - - onSecondaryClicked: { - messageContextMenu.row = messageRow - messageContextMenu.model = model - messageContextMenu.selectedText = contentLabel.selectedText - messageContextMenu.popup() - } - } + visible: avatarVisible + hint: author.displayName + source: author.paintable } - contentItem: ColumnLayout { - id: messageColumn + Rectangle { + Layout.preferredWidth: 32 + Layout.preferredHeight: 32 + Layout.alignment: Qt.AlignTop - spacing: 0 + color: "transparent" + visible: !(sentByMe || avatarVisible) + } - TextEdit { - Layout.fillWidth: true + Control { + Layout.maximumWidth: messageListView.width - (!sentByMe ? 32 + messageRow.spacing : 0) - 48 - id: contentLabel + topPadding: 8 + bottomPadding: 8 + leftPadding: 16 + rightPadding: 16 - text: "" + display + background: Rectangle { + color: sentByMe ? "#009DC2" : eventType === "notice" ? "#4285F4" : "#673AB7" + radius: 18 - visible: isText - color: "white" - - font.family: CommonFont.font.family - font.pixelSize: 14 - selectByMouse: true - readOnly: true - wrapMode: Label.Wrap - selectedTextColor: highlighted ? Material.accent : "white" - selectionColor: highlighted ? "white" : Material.accent - textFormat: Text.RichText - - onLinkActivated: Qt.openUrlExternally(link) - - MouseArea { + AutoMouseArea { anchors.fill: parent - acceptedButtons: Qt.NoButton - cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + + onSecondaryClicked: { + index === messageListView.currentIndex ? messageListView.currentIndex = -1 : messageListView.currentIndex = index + messageContextMenu.root = root + messageContextMenu.model = model + messageContextMenu.selectedText = contentLabel.selectedText + messageContextMenu.popup() + } } } - Loader { - sourceComponent: { - switch (eventType) { - case "image": - return imageComponent - case "file": - return fileComponent - case "audio": - return audioComponent + contentItem: ColumnLayout { + id: messageColumn + + spacing: 0 + + TextEdit { + Layout.fillWidth: true + + id: contentLabel + + text: "" + display + + visible: isText + color: "white" + + font.family: CommonFont.font.family + font.pixelSize: 14 + selectByMouse: true + readOnly: true + wrapMode: Label.Wrap + selectedTextColor: highlighted ? Material.accent : "white" + selectionColor: highlighted ? "white" : Material.accent + textFormat: Text.RichText + + onLinkActivated: Qt.openUrlExternally(link) + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton + cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor } } - active: eventType === "image" || eventType === "file" || eventType === "audio" - } - } + Loader { + sourceComponent: { + switch (eventType) { + case "image": + return imageComponent + case "file": + return fileComponent + case "audio": + return audioComponent + } + } - Component { - id: imageComponent - - DownloadableContent { - width: messageImage.width - height: messageImage.height - - id: downloadable - - TimelineImage { - z: -4 - - id: messageImage - - sourceSize: 128 - source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url) - - onClicked: downloadAndOpen() - } - - Component.onCompleted: { - messageRow.saveFileAs.connect(saveFileAs) - messageRow.openExternally.connect(downloadAndOpen) + active: eventType === "image" || eventType === "file" || eventType === "audio" } } - } - Component { - id: fileComponent + Component { + id: imageComponent - TimelineLabel { - Layout.fillWidth: true + DownloadableContent { + width: messageImage.width + height: messageImage.height - id: downloadDelegate - - text: "File: " + content.body - coloredBackground: highlighted - - background: DownloadableContent { id: downloadable + TimelineImage { + z: -4 + + id: messageImage + + sourceSize: 128 + source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url) + + onClicked: downloadAndOpen() + } + Component.onCompleted: { - messageRow.saveFileAs.connect(saveFileAs) - messageRow.openExternally.connect(downloadAndOpen) + root.saveFileAs.connect(saveFileAs) + root.openExternally.connect(downloadAndOpen) } } } - } - Component { - id: audioComponent + Component { + id: fileComponent - TimelineLabel { - id: downloadDelegate + TimelineLabel { + Layout.fillWidth: true - text: content.info.duration / 1000 + '"' - coloredBackground: highlighted + id: downloadDelegate - MouseArea { - anchors.fill: parent + text: "File: " + content.body + coloredBackground: highlighted - propagateComposedEvents: true + background: DownloadableContent { + id: downloadable - onClicked: { - if (downloadable.downloaded) - spectralController.playAudio(progressInfo.localPath) - else - { - playOnFinished = true - currentRoom.downloadFile(eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_") + ".tmp") + Component.onCompleted: { + root.saveFileAs.connect(saveFileAs) + root.openExternally.connect(downloadAndOpen) } } } + } - background: DownloadableContent { - id: downloadable + Component { + id: audioComponent - onDownloadedChanged: downloaded && playOnFinished ? spectralController.playAudio(progressInfo.localPath) : {} + TimelineLabel { + id: downloadDelegate - Component.onCompleted: { - messageRow.saveFileAs.connect(saveFileAs) - messageRow.openExternally.connect(downloadAndOpen) + text: content.info.duration / 1000 + '"' + coloredBackground: highlighted + + MouseArea { + anchors.fill: parent + + propagateComposedEvents: true + + onClicked: { + if (downloadable.downloaded) + spectralController.playAudio(progressInfo.localPath) + else + { + playOnFinished = true + currentRoom.downloadFile(eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_") + ".tmp") + } + } + } + + background: DownloadableContent { + id: downloadable + + onDownloadedChanged: downloaded && playOnFinished ? spectralController.playAudio(progressInfo.localPath) : {} + + Component.onCompleted: { + root.saveFileAs.connect(saveFileAs) + root.openExternally.connect(downloadAndOpen) + } } } } } } + + Label { + Layout.leftMargin: sentByMe ? 12 : 48 + + text: Qt.formatDateTime(time, "dd/MM/yyyy '-' hh:mm") + + visible: index === messageListView.currentIndex + + font.pixelSize: 13 + verticalAlignment: Text.AlignVCenter + } } diff --git a/imports/Spectral/Menu/MessageContextMenu.qml b/imports/Spectral/Menu/MessageContextMenu.qml index 973e428..a843067 100644 --- a/imports/Spectral/Menu/MessageContextMenu.qml +++ b/imports/Spectral/Menu/MessageContextMenu.qml @@ -2,7 +2,7 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 Menu { - property var row: null + property var root: null property var model: null property string selectedText @@ -23,14 +23,14 @@ Menu { height: visible ? undefined : 0 text: "Open Externally" - onTriggered: row.openExternally() + onTriggered: root.openExternally() } MenuItem { visible: isFile height: visible ? undefined : 0 text: "Save As" - onTriggered: row.saveFileAs() + onTriggered: root.saveFileAs() } MenuItem { height: visible ? undefined : 0 diff --git a/imports/Spectral/Panel/RoomPanel.qml b/imports/Spectral/Panel/RoomPanel.qml index 430d6dd..38c8f9d 100644 --- a/imports/Spectral/Panel/RoomPanel.qml +++ b/imports/Spectral/Panel/RoomPanel.qml @@ -80,10 +80,12 @@ Item { id: messageListView + spacing: 4 + displayMarginBeginning: 100 displayMarginEnd: 100 verticalLayoutDirection: ListView.BottomToTop - spacing: 4 + highlightMoveDuration: 500 boundsBehavior: Flickable.DragOverBounds diff --git a/include/libqmatrixclient b/include/libqmatrixclient index 6f18091..e1fdb33 160000 --- a/include/libqmatrixclient +++ b/include/libqmatrixclient @@ -1 +1 @@ -Subproject commit 6f18091a48530399908fbc6ebcb0697bae970abb +Subproject commit e1fdb33a4161b29d6df590ccea339d361d9fc4e8 diff --git a/qtquickcontrols2.conf b/qtquickcontrols2.conf index cbed40a..ef76765 100644 --- a/qtquickcontrols2.conf +++ b/qtquickcontrols2.conf @@ -11,3 +11,4 @@ Primary=#344955 Accent=#673AB7 ;Foreground=#1D333E ;Background=#161616 +Font/Family=Roboto diff --git a/src/controller.cpp b/src/controller.cpp index 040854d..9ca954c 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -75,11 +75,11 @@ void Controller::loginWithCredentials(QString serverAddr, QString user, setConnection(conn); }); connect(conn, &Connection::networkError, - [=](QString error, QByteArray detail) { + [=](QString error, QString, int, int) { emit errorOccured("Network Error", error); }); connect(conn, &Connection::loginError, - [=](QString error, QByteArray detail) { + [=](QString error, QString) { emit errorOccured("Login Failed", error); }); } @@ -150,11 +150,11 @@ void Controller::invokeLogin() { addConnection(c); }); connect(c, &Connection::loginError, - [=](QString error, QByteArray detail) { + [=](QString error, QString) { emit errorOccured("Login Failed", error); }); connect(c, &Connection::networkError, - [=](QString error, QByteArray detail) { + [=](QString error, QString, int, int) { emit errorOccured("Network Error", error); }); c->connectWithToken(account.userId(), accessToken, account.deviceId());