summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2023-08-13 11:30:41 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2023-08-25 19:03:16 +0200
commit2360dfd80ae8991c557c9c7d9474c528c00fdaa6 (patch)
tree70a357307798038525871a5e12e422babc342ccd
parent718a58d388abd228c6a08f9fa3365588c06923ba (diff)
Remaining events apart from verification
-rw-r--r--resources/qml/MessageView.qml184
-rw-r--r--resources/qml/delegates/Encrypted.qml33
-rw-r--r--resources/qml/delegates/EncryptionEnabled.qml47
-rw-r--r--resources/qml/delegates/FileMessage.qml36
-rw-r--r--resources/qml/delegates/Redacted.qml1
-rw-r--r--src/timeline/EventDelegateChooser.cpp27
-rw-r--r--src/timeline/TimelineModel.cpp42
-rw-r--r--src/timeline/TimelineModel.h3
-rw-r--r--src/voip/CallManager.cpp3
9 files changed, 287 insertions, 89 deletions
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index 417a4f5a..2f50789f 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -203,7 +203,7 @@ Item {
color: type == MtxEvent.NoticeMessage ? palette.buttonText : palette.text
font.italic: type == MtxEvent.NoticeMessage
- formatted: formattedBody + "a"
+ formatted: formattedBody
Layout.fillWidth: true
//Layout.maximumWidth: implicitWidth
@@ -262,6 +262,7 @@ Item {
text: formattedStateEvent
formatted: ''
body: ''
+ horizontalAlignment: Text.AlignHCenter
color: palette.buttonText
font.italic: true
@@ -274,6 +275,79 @@ Item {
EventDelegateChoice {
roleValues: [
+ MtxEvent.CallInvite,
+ ]
+ TextMessage {
+ keepFullText: true
+
+ required property string userId
+ required property string userName
+ required property string callType
+
+ isOnlyEmoji: false
+ body: formatted
+ formatted: {
+ switch (callType) {
+ case "voice":
+ return qsTr("%1 placed a voice call.").arg(TimelineManager.escapeEmoji(userName));
+ case "video":
+ return qsTr("%1 placed a video call.").arg(TimelineManager.escapeEmoji(userName));
+ default:
+ return qsTr("%1 placed a call.").arg(TimelineManager.escapeEmoji(userName));
+ }
+ }
+
+ color: palette.buttonText
+ font.italic: true
+
+ Layout.fillWidth: true
+ }
+ }
+
+ EventDelegateChoice {
+ roleValues: [
+ MtxEvent.CallAnswer,
+ MtxEvent.CallReject,
+ MtxEvent.CallSelectAnswer,
+ MtxEvent.CallHangUp,
+ MtxEvent.CallCandidates,
+ MtxEvent.CallNegotiate,
+ ]
+ TextMessage {
+ keepFullText: true
+
+ required property string userId
+ required property string userName
+ required property int type
+
+ isOnlyEmoji: false
+ body: formatted
+ formatted: {
+ switch (type) {
+ case MtxEvent.CallAnswer:
+ return qsTr("%1 answered the call.").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallReject:
+ return qsTr("%1 rejected the call.").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallSelectAnswer:
+ return qsTr("%1 selected answer.").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallHangUp:
+ return qsTr("%1 ended the call.").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallCandidates:
+ return qsTr("%1 is negotiating the call...").arg(TimelineManager.escapeEmoji(userName));
+ case MtxEvent.CallNegotiate:
+ return qsTr("%1 is negotiating the call...").arg(TimelineManager.escapeEmoji(userName));
+ }
+ }
+
+ color: palette.buttonText
+ font.italic: true
+
+ Layout.fillWidth: true
+ }
+ }
+
+ EventDelegateChoice {
+ roleValues: [
MtxEvent.ImageMessage,
MtxEvent.Sticker,
]
@@ -287,6 +361,44 @@ Item {
EventDelegateChoice {
roleValues: [
+ MtxEvent.FileMessage,
+ ]
+ FileMessage {
+ Layout.fillWidth: true
+ }
+ }
+
+ EventDelegateChoice {
+ roleValues: [
+ MtxEvent.VideoMessage,
+ MtxEvent.AudioMessage,
+ ]
+ PlayableMediaMessage {
+ Layout.fillWidth: true
+ }
+ }
+
+ EventDelegateChoice {
+ roleValues: [
+ MtxEvent.Encrypted,
+ ]
+ Encrypted {
+ Layout.fillWidth: true
+ }
+ }
+
+ EventDelegateChoice {
+ roleValues: [
+ MtxEvent.Encryption,
+ ]
+ EncryptionEnabled {
+ Layout.fillWidth: true
+ }
+ }
+
+
+ EventDelegateChoice {
+ roleValues: [
MtxEvent.Redacted
]
@@ -300,6 +412,76 @@ Item {
EventDelegateChoice {
roleValues: [
+ MtxEvent.Member
+ ]
+
+ ColumnLayout {
+ id: member
+
+ required property string userId
+ required property string userName
+
+ required property bool isReply
+ required property Room room
+ required property string formattedStateEvent
+
+ NoticeMessage {
+ body: formatted
+ isOnlyEmoji: false
+ isReply: tombstone.isReply
+ keepFullText: true
+ isStateEvent: true
+ Layout.fillWidth: true
+ formatted: member.formattedStateEvent
+ }
+
+ Button {
+ visible: room.showAcceptKnockButton(eventId)
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("Allow them in")
+ onClicked: room.acceptKnock(member.eventId)
+ }
+
+ }
+ }
+
+ EventDelegateChoice {
+ roleValues: [
+ MtxEvent.Tombstone
+ ]
+
+ ColumnLayout {
+ id: tombstone
+
+ required property string userId
+ required property string userName
+
+ required property string body
+ required property bool isReply
+ required property Room room
+ required property string eventId
+
+ NoticeMessage {
+ body: formatted
+ isOnlyEmoji: false
+ isReply: tombstone.isReply
+ keepFullText: true
+ isStateEvent: true
+ Layout.fillWidth: true
+ formatted: qsTr("This room was replaced for the following reason: %1").arg(tombstone.body)
+ }
+
+ Button {
+ Layout.alignment: Qt.AlignHCenter
+ text: qsTr("Go to replacement room")
+ onClicked: tombstone.room.joinReplacementRoom(tombstone.eventId)
+ }
+
+ }
+ }
+
+ EventDelegateChoice {
+ roleValues: [
]
MatrixText {
Layout.fillWidth: true
diff --git a/resources/qml/delegates/Encrypted.qml b/resources/qml/delegates/Encrypted.qml
index fdfe958e..7aeeb28a 100644
--- a/resources/qml/delegates/Encrypted.qml
+++ b/resources/qml/delegates/Encrypted.qml
@@ -8,37 +8,34 @@ import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import im.nheko 1.0
-Rectangle {
+Control {
id: r
required property int encryptionError
required property string eventId
- radius: fontMetrics.lineSpacing / 2 + Nheko.paddingMedium
- width: parent.width? parent.width : 0
- implicitWidth: encryptedText.implicitWidth+24+Nheko.paddingMedium*3 // Column doesn't provide a useful implicitWidth, should be replaced by ColumnLayout
- height: contents.implicitHeight + Nheko.paddingMedium * 2
- color: palette.alternateBase
+ padding: Nheko.paddingMedium
+ implicitHeight: contents.implicitHeight + Nheko.paddingMedium * 2
+ Layout.maximumWidth: contents.Layout.maximumWidth + padding * 2
+ Layout.fillWidth: true
- RowLayout {
+ contentItem: RowLayout {
id: contents
- anchors.fill: parent
- anchors.margins: Nheko.paddingMedium
spacing: Nheko.paddingMedium
Image {
source: "image://colorimage/:/icons/icons/ui/shield-filled-cross.svg?" + Nheko.theme.error
Layout.alignment: Qt.AlignVCenter
- width: 24
- height: width
+ Layout.preferredWidth: 24
+ Layout.preferredHeight: 24
}
- Column {
+ ColumnLayout {
spacing: Nheko.paddingSmall
Layout.fillWidth: true
- MatrixText {
+ Label {
id: encryptedText
text: {
switch (encryptionError) {
@@ -58,8 +55,11 @@ Rectangle {
return qsTr("Unknown decryption error");
}
}
+ textFormat: Text.PlainText
+ wrapMode: Label.WordWrap
color: palette.text
- width: parent.width
+ Layout.fillWidth: true
+ Layout.maximumWidth: implicitWidth + 1
}
Button {
@@ -72,4 +72,9 @@ Rectangle {
}
+ background: Rectangle {
+ color: palette.alternateBase
+ radius: fontMetrics.lineSpacing / 2 + 2 * Nheko.paddingMedium
+ visible: !Settings.bubbles // the bubble in a bubble looks odd
+ }
}
diff --git a/resources/qml/delegates/EncryptionEnabled.qml b/resources/qml/delegates/EncryptionEnabled.qml
index 0e2b7fc0..40894543 100644
--- a/resources/qml/delegates/EncryptionEnabled.qml
+++ b/resources/qml/delegates/EncryptionEnabled.qml
@@ -3,27 +3,24 @@
// SPDX-License-Identifier: GPL-3.0-or-later
import ".."
-import QtQuick 2.15
-import QtQuick.Layouts 1.15
-import im.nheko 1.0
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import im.nheko
-Rectangle {
+Control {
id: r
- required property string username
+ required property string userName
- radius: fontMetrics.lineSpacing / 2 + Nheko.paddingMedium
- width: parent.width ? Math.min(parent.width, 700) : 0
- height: contents.implicitHeight + Nheko.paddingMedium * 2
- color: palette.alternateBase
- border.color: Nheko.theme.green
- border.width: 2
+ padding: Nheko.paddingMedium
+ //implicitHeight: contents.implicitHeight + padd * 2
+ Layout.maximumWidth: contents.Layout.maximumWidth + padding * 2
+ Layout.fillWidth: true
- RowLayout {
+ contentItem: RowLayout {
id: contents
- anchors.fill: parent
- anchors.margins: Nheko.paddingMedium
spacing: Nheko.paddingMedium
Image {
@@ -33,26 +30,36 @@ Rectangle {
Layout.preferredHeight: 24
}
- Column {
+ ColumnLayout {
spacing: Nheko.paddingSmall
Layout.fillWidth: true
MatrixText {
- text: qsTr("%1 enabled end-to-end encryption").arg(r.username)
+ text: qsTr("%1 enabled end-to-end encryption").arg(r.userName)
font.bold: true
font.pointSize: 14
color: palette.text
- width: parent.width
+ Layout.fillWidth: true
+ Layout.maximumWidth: implicitWidth + 1
}
- MatrixText {
+ Label {
text: qsTr("Encryption keeps your messages safe by only allowing the people you sent the message to to read it. For extra security, if you want to make sure you are talking to the right people, you can verify them in real life.")
- color: palette.text
- width: parent.width
+ textFormat: Text.PlainText
+ wrapMode: Label.WordWrap
+ Layout.fillWidth: true
+ Layout.maximumWidth: implicitWidth + 1
}
}
}
+ background: Rectangle {
+ radius: fontMetrics.lineSpacing / 2 + Nheko.paddingMedium
+ height: contents.implicitHeight + Nheko.paddingMedium * 2
+ color: palette.alternateBase
+ border.color: Nheko.theme.green
+ border.width: 2
+ }
}
diff --git a/resources/qml/delegates/FileMessage.qml b/resources/qml/delegates/FileMessage.qml
index 82b82c1b..9f350123 100644
--- a/resources/qml/delegates/FileMessage.qml
+++ b/resources/qml/delegates/FileMessage.qml
@@ -2,26 +2,30 @@
//
// SPDX-License-Identifier: GPL-3.0-or-later
-import QtQuick 2.12
-import QtQuick.Layouts 1.2
-import im.nheko 1.0
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+import im.nheko
+
+Control {
+ id: evRoot
-Item {
required property string eventId
required property string filename
required property string filesize
- height: rowa.height + (Settings.bubbles? 16: 24)
- implicitWidth: rowa.implicitWidth + metadataWidth
- property int metadataWidth
- property bool fitsMetadata: true
+ padding: Settings.bubbles? 8 : 12
+ //Layout.preferredHeight: rowa.implicitHeight + padding
+ //Layout.maximumWidth: rowa.Layout.maximumWidth + metadataWidth + padding
+ property int metadataWidth: 0
+ property bool fitsMetadata: false
+
+ Layout.maximumWidth: rowa.Layout.maximumWidth + padding * 2
- RowLayout {
+ contentItem: RowLayout {
id: rowa
- anchors.centerIn: parent
- width: parent.width - (Settings.bubbles? 16 : 24)
- spacing: 15
+ spacing: 16
Rectangle {
id: button
@@ -63,6 +67,7 @@ Item {
id: filename_
Layout.fillWidth: true
+ Layout.maximumWidth: implicitWidth + 1
text: filename
textFormat: Text.PlainText
elide: Text.ElideRight
@@ -73,6 +78,7 @@ Item {
id: filesize_
Layout.fillWidth: true
+ Layout.maximumWidth: implicitWidth + 1
text: filesize
textFormat: Text.PlainText
elide: Text.ElideRight
@@ -83,11 +89,9 @@ Item {
}
- Rectangle {
+ background: Rectangle {
color: palette.alternateBase
- z: -1
- radius: 10
- anchors.fill: parent
+ radius: fontMetrics.lineSpacing / 2 + 2 * Nheko.paddingSmall
visible: !Settings.bubbles // the bubble in a bubble looks odd
}
diff --git a/resources/qml/delegates/Redacted.qml b/resources/qml/delegates/Redacted.qml
index 1bb3209f..3c496f08 100644
--- a/resources/qml/delegates/Redacted.qml
+++ b/resources/qml/delegates/Redacted.qml
@@ -36,7 +36,6 @@ Control {
property var redactedPair: room.formatRedactedEvent(msgRoot.eventId)
text: redactedPair["first"]
wrapMode: Label.WordWrap
- color: palette.text
ToolTip.text: redactedPair["second"]
ToolTip.visible: hh.hovered
diff --git a/src/timeline/EventDelegateChooser.cpp b/src/timeline/EventDelegateChooser.cpp
index 7fec38dd..2218d9ee 100644
--- a/src/timeline/EventDelegateChooser.cpp
+++ b/src/timeline/EventDelegateChooser.cpp
@@ -195,17 +195,22 @@ EventDelegateChooser::DelegateIncubator::setInitialState(QObject *obj)
if (!forReply) {
auto row = chooser.room_->idToIndex(currentId);
- connect(chooser.room_,
- &QAbstractItemModel::dataChanged,
- obj,
- [row, update](const QModelIndex &topLeft,
- const QModelIndex &bottomRight,
- const QList<int> &changedRoles) {
- if (row < topLeft.row() || row > bottomRight.row())
- return;
-
- update(changedRoles);
- });
+ auto connection = connect(
+ chooser.room_,
+ &QAbstractItemModel::dataChanged,
+ obj,
+ [row, update](const QModelIndex &topLeft,
+ const QModelIndex &bottomRight,
+ const QList<int> &changedRoles) {
+ if (row < topLeft.row() || row > bottomRight.row())
+ return;
+
+ update(changedRoles);
+ },
+ Qt::QueuedConnection);
+ connect(&this->chooser, &EventDelegateChooser::destroyed, obj, [connection]() {
+ QObject::disconnect(connection);
+ });
}
}
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 66f7d5b8..3e0c6688 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -757,6 +757,8 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
return formatHistoryVisibilityEvent(e);
else if constexpr (t == mtx::events::EventType::RoomGuestAccess)
return formatGuestAccessEvent(e);
+ else if constexpr (t == mtx::events::EventType::RoomMember)
+ return formatMemberEvent(e);
return tr("%1 changed unknown state event %2.")
.arg(displayName(QString::fromStdString(e.sender)))
@@ -2958,34 +2960,27 @@ TimelineModel::joinReplacementRoom(const QString &id)
}
QString
-TimelineModel::formatMemberEvent(const QString &id)
+TimelineModel::formatMemberEvent(
+ const mtx::events::StateEvent<mtx::events::state::Member> &event) const
{
- auto e = events.get(id.toStdString(), "");
- if (!e)
- return {};
-
- auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
- if (!event)
- return {};
-
mtx::events::StateEvent<mtx::events::state::Member> const *prevEvent = nullptr;
- if (!event->unsigned_data.replaces_state.empty()) {
- auto tempPrevEvent = events.get(event->unsigned_data.replaces_state, event->event_id);
+ if (!event.unsigned_data.replaces_state.empty()) {
+ auto tempPrevEvent = events.get(event.unsigned_data.replaces_state, event.event_id);
if (tempPrevEvent) {
prevEvent =
std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(tempPrevEvent);
}
}
- QString user = QString::fromStdString(event->state_key);
+ QString user = QString::fromStdString(event.state_key);
QString name = utils::replaceEmoji(displayName(user));
QString rendered;
- QString sender = QString::fromStdString(event->sender);
+ QString sender = QString::fromStdString(event.sender);
QString senderName = utils::replaceEmoji(displayName(sender));
// see table https://matrix.org/docs/spec/client_server/latest#m-room-member
using namespace mtx::events::state;
- switch (event->content.membership) {
+ switch (event.content.membership) {
case Membership::Invite:
rendered = tr("%1 invited %2.").arg(senderName, name);
break;
@@ -2994,9 +2989,8 @@ TimelineModel::formatMemberEvent(const QString &id)
QString oldName = utils::replaceEmoji(
QString::fromStdString(prevEvent->content.display_name).toHtmlEscaped());
- bool displayNameChanged =
- prevEvent->content.display_name != event->content.display_name;
- bool avatarChanged = prevEvent->content.avatar_url != event->content.avatar_url;
+ bool displayNameChanged = prevEvent->content.display_name != event.content.display_name;
+ bool avatarChanged = prevEvent->content.avatar_url != event.content.avatar_url;
if (displayNameChanged && avatarChanged)
rendered = tr("%1 has changed their avatar and changed their "
@@ -3011,30 +3005,30 @@ TimelineModel::formatMemberEvent(const QString &id)
// the case of nothing changed but join follows join shouldn't happen, so
// just show it as join
} else {
- if (event->content.join_authorised_via_users_server.empty())
+ if (event.content.join_authorised_via_users_server.empty())
rendered = tr("%1 joined.").arg(name);
else
rendered =
tr("%1 joined via authorisation from %2's server.")
.arg(name,
- QString::fromStdString(event->content.join_authorised_via_users_server));
+ QString::fromStdString(event.content.join_authorised_via_users_server));
}
break;
case Membership::Leave:
if (!prevEvent || prevEvent->content.membership == Membership::Join) {
- if (event->state_key == event->sender)
+ if (event.state_key == event.sender)
rendered = tr("%1 left the room.").arg(name);
else
rendered = tr("%2 kicked %1.").arg(name, senderName);
} else if (prevEvent->content.membership == Membership::Invite) {
- if (event->state_key == event->sender)
+ if (event.state_key == event.sender)
rendered = tr("%1 rejected their invite.").arg(name);
else
rendered = tr("%2 revoked the invite to %1.").arg(name, senderName);
} else if (prevEvent->content.membership == Membership::Ban) {
rendered = tr("%2 unbanned %1.").arg(name, senderName);
} else if (prevEvent->content.membership == Membership::Knock) {
- if (event->state_key == event->sender)
+ if (event.state_key == event.sender)
rendered = tr("%1 redacted their knock.").arg(name);
else
rendered = tr("%2 rejected the knock from %1.").arg(name, senderName);
@@ -3053,8 +3047,8 @@ TimelineModel::formatMemberEvent(const QString &id)
break;
}
- if (event->content.reason != "") {
- rendered += " " + tr("Reason: %1").arg(QString::fromStdString(event->content.reason));
+ if (event.content.reason != "") {
+ rendered += " " + tr("Reason: %1").arg(QString::fromStdString(event.content.reason));
}
return rendered;
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 2b22ad61..8f787f21 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -310,7 +310,8 @@ public:
Q_INVOKABLE bool showAcceptKnockButton(const QString &id);
Q_INVOKABLE void acceptKnock(const QString &id);
Q_INVOKABLE void joinReplacementRoom(const QString &id);
- Q_INVOKABLE QString formatMemberEvent(const QString &id);
+ Q_INVOKABLE QString
+ formatMemberEvent(const mtx::events::StateEvent<mtx::events::state::Member> &event) const;
Q_INVOKABLE QString formatJoinRuleEvent(const QString &id);
QString formatHistoryVisibilityEvent(
const mtx::events::StateEvent<mtx::events::state::HistoryVisibility> &event) const;
diff --git a/src/voip/CallManager.cpp b/src/voip/CallManager.cpp
index 5479ba31..46679e71 100644
--- a/src/voip/CallManager.cpp
+++ b/src/voip/CallManager.cpp
@@ -92,7 +92,8 @@ CallManager::CallManager(QObject *parent)
if (QGuiApplication::platformName() != QStringLiteral("wayland")) {
// Selected by default
screenShareType_ = ScreenShareType::X11;
- std::swap(screenShareTypes_[0], screenShareTypes_[1]);
+ if (screenShareTypes_.size() >= 2)
+ std::swap(screenShareTypes_[0], screenShareTypes_[1]);
}
}
#endif