diff --git a/imports/Spectral/Component/Avatar.qml b/imports/Spectral/Component/Avatar.qml index 399f465..fe546eb 100644 --- a/imports/Spectral/Component/Avatar.qml +++ b/imports/Spectral/Component/Avatar.qml @@ -36,8 +36,8 @@ Item { visible: !realSource || image.status != Image.Ready radius: height / 2 - color: stringToColor(hint) + antialiasing: true Label { anchors.centerIn: parent diff --git a/imports/Spectral/Component/FullScreenImage.qml b/imports/Spectral/Component/FullScreenImage.qml new file mode 100644 index 0000000..694ac86 --- /dev/null +++ b/imports/Spectral/Component/FullScreenImage.qml @@ -0,0 +1,41 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.12 + +ApplicationWindow { + property url imageUrl + property int sourceWidth + property int sourceHeight + + id: root + + flags: Qt.FramelessWindowHint | Qt.WA_TranslucentBackground + visible: true + visibility: Qt.WindowFullScreen + + title: "Image View - " + imageUrl + + color: "#BB000000" + + Image { + anchors.centerIn: parent + + sourceSize.width: root.sourceWidth + sourceSize.height: root.sourceHeight + source: imageUrl + } + + ItemDelegate { + anchors.top: parent.top + anchors.right: parent.right + + width: 64 + height: 64 + + contentItem: MaterialIcon { + icon: "\ue5cd" + color: "white" + } + + onClicked: root.close() + } +} diff --git a/imports/Spectral/Component/Timeline/ImageDelegate.qml b/imports/Spectral/Component/Timeline/ImageDelegate.qml index 9bb170f..b92881c 100644 --- a/imports/Spectral/Component/Timeline/ImageDelegate.qml +++ b/imports/Spectral/Component/Timeline/ImageDelegate.qml @@ -83,10 +83,13 @@ ColumnLayout { id: img source: "image://mxc/" + - (content.info && content.info.thumbnail_info ? - content.thumbnailMediaId : content.mediaId) - sourceSize.width: messageListView.width * 0.6 - sourceSize.height: messageListView.height + (content.info && content.info.thumbnail_info ? + content.thumbnailMediaId : content.mediaId) + + sourceSize.width: 720 + sourceSize.height: 720 + + fillMode: Image.PreserveAspectCrop layer.enabled: true layer.effect: OpacityMask { @@ -97,6 +100,16 @@ ColumnLayout { } } + Component { + id: fullScreenImage + + FullScreenImage { + imageUrl: "image://mxc/" + content.mediaId + sourceWidth: content.info.w + sourceHeight: content.info.h + } + } + Rectangle { anchors.fill: parent @@ -113,6 +126,11 @@ ColumnLayout { id: messageMouseArea + onPrimaryClicked: { + var window = fullScreenImage.createObject() + window.show() + } + onSecondaryClicked: messageContextMenu.popup() Menu { @@ -126,16 +144,19 @@ ColumnLayout { sourceDialog.open() } } + MenuItem { text: "Open Externally" onTriggered: downloadAndOpen() } + MenuItem { text: "Save As" onTriggered: saveFileAs() } + MenuItem { text: "Reply" @@ -147,6 +168,7 @@ ColumnLayout { roomPanelInput.focus() } } + MenuItem { text: "Redact" diff --git a/imports/Spectral/Component/qmldir b/imports/Spectral/Component/qmldir index be035c4..d929c81 100644 --- a/imports/Spectral/Component/qmldir +++ b/imports/Spectral/Component/qmldir @@ -7,3 +7,4 @@ AutoListView 2.0 AutoListView.qml AutoTextField 2.0 AutoTextField.qml SplitView 2.0 SplitView.qml Avatar 2.0 Avatar.qml +FullScreenImage 2.0 FullScreenImage.qml diff --git a/imports/Spectral/Panel/RoomDrawer.qml b/imports/Spectral/Panel/RoomDrawer.qml index 6817a91..72a1e8d 100644 --- a/imports/Spectral/Panel/RoomDrawer.qml +++ b/imports/Spectral/Panel/RoomDrawer.qml @@ -271,6 +271,102 @@ Drawer { } } + Control { + Layout.fillWidth: true + + visible: room ? room.predecessorId : false + + padding: 8 + + contentItem: RowLayout { + MaterialIcon { + Layout.preferredWidth: 48 + Layout.preferredHeight: 48 + + icon: "\ue8d4" + } + + ColumnLayout { + Layout.fillWidth: true + + spacing: 0 + + Label { + Layout.fillWidth: true + + font.bold: true + color: MPalette.foreground + text: "This room is a continuation of another conversation." + } + + Label { + Layout.fillWidth: true + + color: MPalette.lighter + text: "Click here to see older messages." + } + } + } + + background: Rectangle { + color: MPalette.banner + + RippleEffect { + anchors.fill: parent + + onClicked: roomListForm.enteredRoom = spectralController.connection.room(room.predecessorId) + } + } + } + + Control { + Layout.fillWidth: true + + visible: room ? room.successorId : false + + padding: 8 + + contentItem: RowLayout { + MaterialIcon { + Layout.preferredWidth: 48 + Layout.preferredHeight: 48 + + icon: "\ue8d4" + } + + ColumnLayout { + Layout.fillWidth: true + + spacing: 0 + + Label { + Layout.fillWidth: true + + font.bold: true + color: MPalette.foreground + text: "This room has been replaced and is no longer active." + } + + Label { + Layout.fillWidth: true + + color: MPalette.lighter + text: "The conversation continues here." + } + } + } + + background: Rectangle { + color: MPalette.banner + + RippleEffect { + anchors.fill: parent + + onClicked: roomListForm.enteredRoom = spectralController.connection.room(room.successorId) + } + } + } + MenuSeparator { Layout.fillWidth: true } diff --git a/imports/Spectral/Panel/RoomListPanel.qml b/imports/Spectral/Panel/RoomListPanel.qml index e2d0700..b6f701f 100644 --- a/imports/Spectral/Panel/RoomListPanel.qml +++ b/imports/Spectral/Panel/RoomListPanel.qml @@ -60,6 +60,9 @@ Item { ] filters: [ + ExpressionFilter { + expression: joinState != "upgraded" + }, RegExpFilter { roleName: "name" pattern: searchField.text @@ -272,7 +275,7 @@ Item { } Rectangle { - width: unreadCount > 0 ? 4 : 0 + width: unreadCount >= 0 ? 4 : 0 height: parent.height color: Material.accent diff --git a/res.qrc b/res.qrc index d5d29dd..63748cb 100644 --- a/res.qrc +++ b/res.qrc @@ -43,5 +43,6 @@ imports/Spectral/Component/Avatar.qml imports/Spectral/Setting/Palette.qml imports/Spectral/Component/Timeline/FileDelegate.qml + imports/Spectral/Component/FullScreenImage.qml diff --git a/src/roomlistmodel.cpp b/src/roomlistmodel.cpp index 2c574de..425aefd 100644 --- a/src/roomlistmodel.cpp +++ b/src/roomlistmodel.cpp @@ -195,6 +195,11 @@ QVariant RoomListModel::data(const QModelIndex& index, int role) const { return room->lastEvent(); if (role == LastActiveTimeRole) return room->lastActiveTime(); + if (role == JoinStateRole) { + if (!room->successorId().isEmpty()) + return QStringLiteral("upgraded"); + return toCString(room->joinState()); + } if (role == CurrentRoomRole) return QVariant::fromValue(room); return QVariant(); @@ -231,6 +236,7 @@ QHash RoomListModel::roleNames() const { roles[HighlightCountRole] = "highlightCount"; roles[LastEventRole] = "lastEvent"; roles[LastActiveTimeRole] = "lastActiveTime"; + roles[JoinStateRole] = "joinState"; roles[CurrentRoomRole] = "currentRoom"; return roles; } diff --git a/src/roomlistmodel.h b/src/roomlistmodel.h index 23ea92b..238b372 100644 --- a/src/roomlistmodel.h +++ b/src/roomlistmodel.h @@ -39,6 +39,7 @@ class RoomListModel : public QAbstractListModel { HighlightCountRole, LastEventRole, LastActiveTimeRole, + JoinStateRole, CurrentRoomRole, };