diff --git a/docs/TODO.md b/docs/TODO.md
index 3ba8285e..7a674112 100644
--- a/docs/TODO.md
+++ b/docs/TODO.md
@@ -190,7 +190,6 @@
- Option to export-logout-login-import to fix one-time key problems
- Cross-signing
-- Display read receipts on events (who/how many people have read an event)
- Fully read markers
- Methods of signing in that aren't handled yet:
diff --git a/src/gui/Pages/Chat/RoomHeader.qml b/src/gui/Pages/Chat/RoomHeader.qml
index 09e7ae1b..0a493ac4 100644
--- a/src/gui/Pages/Chat/RoomHeader.qml
+++ b/src/gui/Pages/Chat/RoomHeader.qml
@@ -6,15 +6,16 @@ import QtQuick.Layouts 1.12
import "../../Base"
Rectangle {
- readonly property bool showLeftButton:
- mainUI.mainPane.collapse || mainUI.mainPane.forceCollapse
-
- readonly property bool showRightButton:
- chat.roomPane &&
- (chat.roomPane.collapse || chat.roomPane.forceCollapse)
+ id: root
readonly property bool center:
- showLeftButton || window.settings.Chat.always_center_header
+ goToMainPaneButton.show || window.settings.Chat.always_center_header
+
+ readonly property HListView eventList: chatPage.eventList.eventList
+ readonly property int selected:
+ eventList.selectedCount === 1 && eventList.selectedText ?
+ 0 :
+ eventList.selectedCount
implicitHeight: theme.baseElementsHeight
color: theme.chat.roomHeader.background
@@ -23,24 +24,20 @@ Rectangle {
id: row
anchors.fill: parent
- HButton {
+ RoomHeaderButton {
id: goToMainPaneButton
+ show: mainUI.mainPane.collapse || mainUI.mainPane.forceCollapse
padded: false
- visible: Layout.preferredWidth > 0
backgroundColor: "transparent"
icon.name: "go-back-to-main-pane"
toolTip.text: qsTr("Go back to main pane")
-
onClicked: mainUI.mainPane.toggleFocus()
- Layout.preferredWidth: showLeftButton ? avatar.width : 0
- Layout.fillHeight: true
-
- Behavior on Layout.preferredWidth { HNumberAnimation {} }
+ Layout.preferredWidth: show ? avatar.width : 0
}
HSpacer {
- visible: center
+ visible: root.center
}
HRoomAvatar {
@@ -55,26 +52,34 @@ Rectangle {
}
HLabel {
- id: nameLabel
- text: chat.roomInfo.display_name || qsTr("Empty room")
- color: theme.chat.roomHeader.name
+ id: mainLabel
+ text:
+ root.selected === 0 ?
+ chat.roomInfo.display_name || qsTr("Empty room") :
+ root.selected === 1 ?
+ qsTr("%1 selected message").arg(root.selected) :
+ qsTr("%1 selected messages").arg(root.selected)
+
+ color: theme.chat.roomHeader.name
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
leftPadding: theme.spacing
rightPadding: leftPadding
+ // FIXME: these dirty manual calculations
Layout.preferredWidth: Math.min(
implicitWidth,
row.width -
- row.spacing -
- (showLeftButton ? row.spacing : 0) -
- (showRightButton ? row.spacing : 0) -
goToMainPaneButton.width -
avatar.width -
encryptionStatusButton.width -
+ copyButton.width -
+ removeButton.width -
+ deselectButton.width -
goToRoomPaneButton.width
)
+ Layout.fillWidth: ! topicLabel.text
Layout.fillHeight: true
HoverHandler { id: nameHover }
@@ -82,28 +87,29 @@ Rectangle {
HLabel {
id: topicLabel
- text: chat.roomInfo.topic
+ text: root.selected ? "" : chat.roomInfo.topic
textFormat: Text.StyledText
font.pixelSize: theme.fontSize.small
color: theme.chat.roomHeader.topic
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
- rightPadding: nameLabel.rightPadding
+ rightPadding: mainLabel.rightPadding
- Layout.preferredWidth: Math.min(
+ Layout.preferredWidth: ! text ? 0 : Math.min(
implicitWidth,
row.width -
- row.spacing -
- (showLeftButton ? row.spacing : 0) -
- (showRightButton ? row.spacing : 0) -
goToMainPaneButton.width -
avatar.width -
- nameLabel.width -
+ mainLabel.width -
encryptionStatusButton.width -
+ copyButton.width -
+ removeButton.width -
+ deselectButton.width -
goToRoomPaneButton.width
)
- Layout.fillWidth: ! center
+
+ Layout.fillWidth: text && ! root.center
Layout.fillHeight: true
HoverHandler { id: topicHover }
@@ -118,7 +124,7 @@ Rectangle {
HToolTip {
readonly property string name:
- nameLabel.truncated ?
+ mainLabel.truncated ?
(`${chat.roomInfo.display_name}`) : ""
readonly property string topic:
@@ -129,10 +135,10 @@ Rectangle {
text: name && topic ? (`${name}
${topic}`) : (name || topic)
}
- HButton {
+ RoomHeaderButton {
id: encryptionStatusButton
+ show: chat.roomInfo.encrypted && ! root.selected
padded: false
- visible: Layout.preferredWidth > 0
backgroundColor: "transparent"
icon.name:
@@ -153,28 +159,74 @@ Rectangle {
onClicked: toolTip.instantToggle()
- Layout.preferredWidth: chat.roomInfo.encrypted ? avatar.width : 0
+ Layout.preferredWidth: show ? avatar.width : 0
Layout.fillHeight: true
+ }
- Behavior on Layout.preferredWidth { HNumberAnimation {} }
+ RoomHeaderButton {
+ id: copyButton
+ show: root.selected
+ icon.name: "room-header-copy"
+ toolTip.text: qsTr("Copy messages")
+ toolTip.onClosed: toolTip.text = qsTr("Copy messages")
+
+ onClicked: {
+ root.eventList.copySelectedDelegates()
+ toolTip.text = qsTr("Copied messages")
+ toolTip.instantShow(2000)
+ }
+ }
+
+ RoomHeaderButton {
+ id: removeButton
+
+ readonly property var events:
+ root.eventList.redactableCheckedEvents
+
+ show: root.selected
+ enabled: events.length > 0
+ icon.name: "room-header-remove"
+ toolTip.text: qsTr("Remove messages")
+
+ onClicked: utils.makePopup(
+ "Popups/RedactPopup.qml",
+ window,
+ {
+ preferUserId: chat.userId,
+ roomId: chat.roomId,
+ eventSenderAndIds: events.map(ev => [ev.sender_id, ev.id]),
+ onlyOwnMessageWarning:
+ ! chat.roomInfo.can_redact_all &&
+ events.length < root.selected
+ },
+ )
+ }
+
+ RoomHeaderButton {
+ id: deselectButton
+ show: root.selected
+ icon.name: "room-header-deselect"
+ toolTip.text: qsTr("Deselect messages")
+ onClicked: root.eventList.checked = []
}
HSpacer {
- visible: center
+ visible: root.center
}
- HButton {
+ RoomHeaderButton {
id: goToRoomPaneButton
+ show:
+ chat.roomPane &&
+ (chat.roomPane.collapse || chat.roomPane.forceCollapse)
+
padded: false
- visible: Layout.preferredWidth > 0
backgroundColor: "transparent"
icon.name: "go-to-room-pane"
toolTip.text: qsTr("Go to room pane")
-
onClicked: chat.roomPane.toggleFocus()
- Layout.preferredWidth: showRightButton ? avatar.width : 0
- Layout.fillHeight: true
+ Layout.preferredWidth: show ? avatar.width : 0
}
}
}
diff --git a/src/gui/Pages/Chat/RoomHeaderButton.qml b/src/gui/Pages/Chat/RoomHeaderButton.qml
new file mode 100644
index 00000000..11dce3b6
--- /dev/null
+++ b/src/gui/Pages/Chat/RoomHeaderButton.qml
@@ -0,0 +1,17 @@
+// Copyright Mirage authors & contributors
+// SPDX-License-Identifier: LGPL-3.0-or-later
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import "../../Base"
+
+HButton {
+ property bool show: true
+
+ visible: Layout.preferredWidth > 0
+
+ Layout.preferredWidth: show ? implicitWidth : 0
+ Layout.fillHeight: true
+
+ Behavior on Layout.preferredWidth { HNumberAnimation {} }
+}
diff --git a/src/icons/thin/room-header-copy.svg b/src/icons/thin/room-header-copy.svg
new file mode 100644
index 00000000..fc3a9c39
--- /dev/null
+++ b/src/icons/thin/room-header-copy.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/icons/thin/room-header-deselect.svg b/src/icons/thin/room-header-deselect.svg
new file mode 100644
index 00000000..e4728028
--- /dev/null
+++ b/src/icons/thin/room-header-deselect.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/icons/thin/room-header-remove.svg b/src/icons/thin/room-header-remove.svg
new file mode 100644
index 00000000..d8b94628
--- /dev/null
+++ b/src/icons/thin/room-header-remove.svg
@@ -0,0 +1,3 @@
+