RoomHeader: add message selection info and actions

When messages are selected in the timeline, change the chat header's
mode to show how many messages are selected and offer copy, remove and
deselect buttons.
This commit is contained in:
miruka 2021-01-17 13:46:44 -04:00
parent 426faa2673
commit 4070b75544
6 changed files with 118 additions and 41 deletions

View File

@ -190,7 +190,6 @@
- Option to export-logout-login-import to fix one-time key problems - Option to export-logout-login-import to fix one-time key problems
- Cross-signing - Cross-signing
- Display read receipts on events (who/how many people have read an event)
- Fully read markers - Fully read markers
- Methods of signing in that aren't handled yet: - Methods of signing in that aren't handled yet:

View File

@ -6,15 +6,16 @@ import QtQuick.Layouts 1.12
import "../../Base" import "../../Base"
Rectangle { Rectangle {
readonly property bool showLeftButton: id: root
mainUI.mainPane.collapse || mainUI.mainPane.forceCollapse
readonly property bool showRightButton:
chat.roomPane &&
(chat.roomPane.collapse || chat.roomPane.forceCollapse)
readonly property bool center: 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 implicitHeight: theme.baseElementsHeight
color: theme.chat.roomHeader.background color: theme.chat.roomHeader.background
@ -23,24 +24,20 @@ Rectangle {
id: row id: row
anchors.fill: parent anchors.fill: parent
HButton { RoomHeaderButton {
id: goToMainPaneButton id: goToMainPaneButton
show: mainUI.mainPane.collapse || mainUI.mainPane.forceCollapse
padded: false padded: false
visible: Layout.preferredWidth > 0
backgroundColor: "transparent" backgroundColor: "transparent"
icon.name: "go-back-to-main-pane" icon.name: "go-back-to-main-pane"
toolTip.text: qsTr("Go back to main pane") toolTip.text: qsTr("Go back to main pane")
onClicked: mainUI.mainPane.toggleFocus() onClicked: mainUI.mainPane.toggleFocus()
Layout.preferredWidth: showLeftButton ? avatar.width : 0 Layout.preferredWidth: show ? avatar.width : 0
Layout.fillHeight: true
Behavior on Layout.preferredWidth { HNumberAnimation {} }
} }
HSpacer { HSpacer {
visible: center visible: root.center
} }
HRoomAvatar { HRoomAvatar {
@ -55,26 +52,34 @@ Rectangle {
} }
HLabel { HLabel {
id: nameLabel id: mainLabel
text: chat.roomInfo.display_name || qsTr("Empty room")
color: theme.chat.roomHeader.name
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 elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
leftPadding: theme.spacing leftPadding: theme.spacing
rightPadding: leftPadding rightPadding: leftPadding
// FIXME: these dirty manual calculations
Layout.preferredWidth: Math.min( Layout.preferredWidth: Math.min(
implicitWidth, implicitWidth,
row.width - row.width -
row.spacing -
(showLeftButton ? row.spacing : 0) -
(showRightButton ? row.spacing : 0) -
goToMainPaneButton.width - goToMainPaneButton.width -
avatar.width - avatar.width -
encryptionStatusButton.width - encryptionStatusButton.width -
copyButton.width -
removeButton.width -
deselectButton.width -
goToRoomPaneButton.width goToRoomPaneButton.width
) )
Layout.fillWidth: ! topicLabel.text
Layout.fillHeight: true Layout.fillHeight: true
HoverHandler { id: nameHover } HoverHandler { id: nameHover }
@ -82,28 +87,29 @@ Rectangle {
HLabel { HLabel {
id: topicLabel id: topicLabel
text: chat.roomInfo.topic text: root.selected ? "" : chat.roomInfo.topic
textFormat: Text.StyledText textFormat: Text.StyledText
font.pixelSize: theme.fontSize.small font.pixelSize: theme.fontSize.small
color: theme.chat.roomHeader.topic color: theme.chat.roomHeader.topic
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
rightPadding: nameLabel.rightPadding rightPadding: mainLabel.rightPadding
Layout.preferredWidth: Math.min( Layout.preferredWidth: ! text ? 0 : Math.min(
implicitWidth, implicitWidth,
row.width - row.width -
row.spacing -
(showLeftButton ? row.spacing : 0) -
(showRightButton ? row.spacing : 0) -
goToMainPaneButton.width - goToMainPaneButton.width -
avatar.width - avatar.width -
nameLabel.width - mainLabel.width -
encryptionStatusButton.width - encryptionStatusButton.width -
copyButton.width -
removeButton.width -
deselectButton.width -
goToRoomPaneButton.width goToRoomPaneButton.width
) )
Layout.fillWidth: ! center
Layout.fillWidth: text && ! root.center
Layout.fillHeight: true Layout.fillHeight: true
HoverHandler { id: topicHover } HoverHandler { id: topicHover }
@ -118,7 +124,7 @@ Rectangle {
HToolTip { HToolTip {
readonly property string name: readonly property string name:
nameLabel.truncated ? mainLabel.truncated ?
(`<b>${chat.roomInfo.display_name}</b>`) : "" (`<b>${chat.roomInfo.display_name}</b>`) : ""
readonly property string topic: readonly property string topic:
@ -129,10 +135,10 @@ Rectangle {
text: name && topic ? (`${name}<br>${topic}`) : (name || topic) text: name && topic ? (`${name}<br>${topic}`) : (name || topic)
} }
HButton { RoomHeaderButton {
id: encryptionStatusButton id: encryptionStatusButton
show: chat.roomInfo.encrypted && ! root.selected
padded: false padded: false
visible: Layout.preferredWidth > 0
backgroundColor: "transparent" backgroundColor: "transparent"
icon.name: icon.name:
@ -153,28 +159,74 @@ Rectangle {
onClicked: toolTip.instantToggle() onClicked: toolTip.instantToggle()
Layout.preferredWidth: chat.roomInfo.encrypted ? avatar.width : 0 Layout.preferredWidth: show ? avatar.width : 0
Layout.fillHeight: true 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 { HSpacer {
visible: center visible: root.center
} }
HButton { RoomHeaderButton {
id: goToRoomPaneButton id: goToRoomPaneButton
show:
chat.roomPane &&
(chat.roomPane.collapse || chat.roomPane.forceCollapse)
padded: false padded: false
visible: Layout.preferredWidth > 0
backgroundColor: "transparent" backgroundColor: "transparent"
icon.name: "go-to-room-pane" icon.name: "go-to-room-pane"
toolTip.text: qsTr("Go to room pane") toolTip.text: qsTr("Go to room pane")
onClicked: chat.roomPane.toggleFocus() onClicked: chat.roomPane.toggleFocus()
Layout.preferredWidth: showRightButton ? avatar.width : 0 Layout.preferredWidth: show ? avatar.width : 0
Layout.fillHeight: true
} }
} }
} }

View File

@ -0,0 +1,17 @@
// Copyright Mirage authors & contributors <https://github.com/mirukana/mirage>
// 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 {} }
}

View File

@ -0,0 +1,3 @@
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="m7 16h10v1h-10zm0-1h10v-1h-10zm15-13v22h-20v-22h3c1.229 0 2.18-1.084 3-2h8c.82.916 1.771 2 3 2zm-11 1c0 .552.448 1 1 1s1-.448 1-1-.448-1-1-1-1 .448-1 1zm9 1h-4l-2 2h-3.898l-2.102-2h-4v18h16zm-13 9h10v-1h-10zm0-2h10v-1h-10z"/>
</svg>

After

Width:  |  Height:  |  Size: 330 B

View File

@ -0,0 +1,3 @@
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="m23 20.168-8.185-8.187 8.185-8.174-2.832-2.807-8.182 8.179-8.176-8.179-2.81 2.81 8.186 8.196-8.186 8.184 2.81 2.81 8.203-8.192 8.18 8.192z"/>
</svg>

After

Width:  |  Height:  |  Size: 246 B

View File

@ -0,0 +1,3 @@
<svg clip-rule="evenodd" fill-rule="evenodd" height="24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="m5.662 23-5.369-5.365c-.195-.195-.293-.45-.293-.707 0-.256.098-.512.293-.707l14.929-14.928c.195-.194.451-.293.707-.293.255 0 .512.099.707.293l7.071 7.073c.196.195.293.451.293.708 0 .256-.097.511-.293.707l-11.216 11.219h5.514v2zm3.657-2-5.486-5.486-1.419 1.414 4.076 4.072zm6.605-17.581-10.677 10.68 5.658 5.659 10.676-10.682z"/>
</svg>

After

Width:  |  Height:  |  Size: 453 B