mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-26 04:58:49 +03:00
parent
2e0d0dad96
commit
75b112f0c8
11 changed files with 298 additions and 14 deletions
1
resources/icons/ui/pin-off.svg
Normal file
1
resources/icons/ui/pin-off.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg width="32" height="32" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3.28 2.22a.75.75 0 0 0-1.06 1.06l5.905 5.905L4.81 10.33a1.25 1.25 0 0 0-.476 2.065L7.439 15.5 3 19.94V21h1.06l4.44-4.44 3.105 3.105a1.25 1.25 0 0 0 2.065-.476l1.145-3.313 5.905 5.904a.75.75 0 0 0 1.06-1.06L3.28 2.22Zm10.355 12.476-1.252 3.626-6.705-6.705 3.626-1.252 4.331 4.331Zm6.048-3.876-3.787 1.894 1.118 1.118 3.34-1.67a2.75 2.75 0 0 0 .714-4.404l-4.825-4.826a2.75 2.75 0 0 0-4.405.715l-1.67 3.34 1.118 1.117 1.894-3.787a1.25 1.25 0 0 1 2.002-.325l4.826 4.826a1.25 1.25 0 0 1-.325 2.002Z" fill="#212121"/></svg>
|
After Width: | Height: | Size: 623 B |
1
resources/icons/ui/pin.svg
Normal file
1
resources/icons/ui/pin.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg width="32" height="32" fill="none" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m16.242 2.932 4.826 4.826a2.75 2.75 0 0 1-.715 4.404l-4.87 2.435a.75.75 0 0 0-.374.426l-1.44 4.166a1.25 1.25 0 0 1-2.065.476L8.5 16.561 4.06 21H3v-1.06l4.44-4.44-3.105-3.104a1.25 1.25 0 0 1 .476-2.066l4.166-1.44a.75.75 0 0 0 .426-.373l2.435-4.87a2.75 2.75 0 0 1 4.405-.715Zm3.766 5.886-4.826-4.826a1.25 1.25 0 0 0-2.002.325l-2.435 4.871a2.25 2.25 0 0 1-1.278 1.12l-3.789 1.31 6.705 6.704 1.308-3.789a2.25 2.25 0 0 1 1.12-1.277l4.872-2.436a1.25 1.25 0 0 0 .325-2.002Z" fill="#212121"/></svg>
|
After Width: | Height: | Size: 595 B |
|
@ -582,6 +582,13 @@ ScrollView {
|
||||||
onTriggered: room.editAction(messageContextMenu.eventId)
|
onTriggered: room.editAction(messageContextMenu.eventId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Platform.MenuItem {
|
||||||
|
visible: (room ? room.permissions.canChange(MtxEvent.PinnedEvents) : false)
|
||||||
|
enabled: visible
|
||||||
|
text: visible && room.pinnedMessages.includes(messageContextMenu.eventId) ? qsTr("Un&pin") : qsTr("&Pin")
|
||||||
|
onTriggered: visible && room.pinnedMessages.includes(messageContextMenu.eventId) ? room.unpin(messageContextMenu.eventId) : room.pin(messageContextMenu.eventId)
|
||||||
|
}
|
||||||
|
|
||||||
Platform.MenuItem {
|
Platform.MenuItem {
|
||||||
text: qsTr("Read receip&ts")
|
text: qsTr("Read receip&ts")
|
||||||
onTriggered: room.showReadReceipts(messageContextMenu.eventId)
|
onTriggered: room.showReadReceipts(messageContextMenu.eventId)
|
||||||
|
|
|
@ -8,6 +8,8 @@ import QtQuick.Controls 2.15
|
||||||
import QtQuick.Layouts 1.2
|
import QtQuick.Layouts 1.2
|
||||||
import im.nheko 1.0
|
import im.nheko 1.0
|
||||||
|
|
||||||
|
import "./delegates"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: topBar
|
id: topBar
|
||||||
|
|
||||||
|
@ -28,6 +30,19 @@ Rectangle {
|
||||||
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
onSingleTapped: {
|
onSingleTapped: {
|
||||||
|
if (eventPoint.position.y > topBar.height - pinnedMessages.height) {
|
||||||
|
eventPoint.accepted = true
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (showBackButton && eventPoint.position.x < Nheko.paddingMedium + backToRoomsButton.width) {
|
||||||
|
eventPoint.accepted = true
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (eventPoint.position.x > topBar.width - Nheko.paddingMedium - roomOptionsButton.width) {
|
||||||
|
eventPoint.accepted = true
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (room) {
|
if (room) {
|
||||||
let p = topBar.mapToItem(roomTopicC, eventPoint.position.x, eventPoint.position.y);
|
let p = topBar.mapToItem(roomTopicC, eventPoint.position.x, eventPoint.position.y);
|
||||||
let link = roomTopicC.linkAt(p.x, p.y);
|
let link = roomTopicC.linkAt(p.x, p.y);
|
||||||
|
@ -46,11 +61,11 @@ Rectangle {
|
||||||
|
|
||||||
HoverHandler {
|
HoverHandler {
|
||||||
grabPermissions: PointerHandler.TakeOverForbidden | PointerHandler.CanTakeOverFromAnything
|
grabPermissions: PointerHandler.TakeOverForbidden | PointerHandler.CanTakeOverFromAnything
|
||||||
//cursorShape: Qt.PointingHandCursor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CursorShape {
|
CursorShape {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
anchors.bottomMargin: pinnedMessages.height
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +76,8 @@ Rectangle {
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.margins: Nheko.paddingMedium
|
anchors.margins: Nheko.paddingMedium
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
columnSpacing: Nheko.paddingSmall
|
||||||
|
rowSpacing: Nheko.paddingSmall
|
||||||
|
|
||||||
ImageButton {
|
ImageButton {
|
||||||
id: backToRoomsButton
|
id: backToRoomsButton
|
||||||
|
@ -142,11 +159,41 @@ Rectangle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
id: pinButton
|
||||||
|
|
||||||
|
property bool pinsShown: !Settings.hiddenPins.includes(roomId)
|
||||||
|
|
||||||
|
visible: !!room && room.pinnedMessages.length > 0
|
||||||
|
Layout.column: 4
|
||||||
|
Layout.row: 0
|
||||||
|
Layout.rowSpan: 2
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
Layout.preferredHeight: Nheko.avatarSize - Nheko.paddingMedium
|
||||||
|
Layout.preferredWidth: Nheko.avatarSize - Nheko.paddingMedium
|
||||||
|
image: pinsShown ? ":/icons/icons/ui/pin.svg" : ":/icons/icons/ui/pin-off.svg"
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: qsTr("Show or hide pinned messages")
|
||||||
|
onClicked: {
|
||||||
|
var ps = Settings.hiddenPins;
|
||||||
|
if (pinsShown) {
|
||||||
|
ps.push(roomId);
|
||||||
|
} else {
|
||||||
|
const index = ps.indexOf(roomId);
|
||||||
|
if (index > -1) {
|
||||||
|
ps.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Settings.hiddenPins = ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
ImageButton {
|
ImageButton {
|
||||||
id: roomOptionsButton
|
id: roomOptionsButton
|
||||||
|
|
||||||
visible: !!room
|
visible: !!room
|
||||||
Layout.column: 4
|
Layout.column: 5
|
||||||
Layout.row: 0
|
Layout.row: 0
|
||||||
Layout.rowSpan: 2
|
Layout.rowSpan: 2
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
@ -185,11 +232,79 @@ Rectangle {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScrollView {
|
||||||
|
id: pinnedMessages
|
||||||
|
|
||||||
|
Layout.row: 2
|
||||||
|
Layout.column: 2
|
||||||
|
Layout.columnSpan: 1
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: Math.min(contentHeight, Nheko.avatarSize * 4)
|
||||||
|
|
||||||
|
visible: !!room && room.pinnedMessages.length > 0 && !Settings.hiddenPins.includes(roomId)
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
palette: Nheko.colors
|
||||||
|
ScrollBar.horizontal.visible: false
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
|
||||||
|
spacing: Nheko.paddingSmall
|
||||||
|
model: room ? room.pinnedMessages : undefined
|
||||||
|
delegate: RowLayout {
|
||||||
|
required property string modelData
|
||||||
|
|
||||||
|
width: ListView.view.width
|
||||||
|
height: implicitHeight
|
||||||
|
|
||||||
|
Reply {
|
||||||
|
property var e: room ? room.getDump(modelData, "") : {}
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: height
|
||||||
|
|
||||||
|
userColor: TimelineManager.userColor(e.userId, Nheko.colors.window)
|
||||||
|
blurhash: e.blurhash ?? ""
|
||||||
|
body: e.body ?? ""
|
||||||
|
formattedBody: e.formattedBody ?? ""
|
||||||
|
eventId: e.eventId ?? ""
|
||||||
|
filename: e.filename ?? ""
|
||||||
|
filesize: e.filesize ?? ""
|
||||||
|
proportionalHeight: e.proportionalHeight ?? 1
|
||||||
|
type: e.type ?? MtxEvent.UnknownMessage
|
||||||
|
typeString: e.typeString ?? ""
|
||||||
|
url: e.url ?? ""
|
||||||
|
originalWidth: e.originalWidth ?? 0
|
||||||
|
isOnlyEmoji: e.isOnlyEmoji ?? false
|
||||||
|
userId: e.userId ?? ""
|
||||||
|
userName: e.userName ?? ""
|
||||||
|
encryptionError: e.encryptionError ?? ""
|
||||||
}
|
}
|
||||||
|
|
||||||
CursorShape {
|
ImageButton {
|
||||||
|
id: deletePinButton
|
||||||
|
|
||||||
|
Layout.preferredHeight: 16
|
||||||
|
Layout.preferredWidth: 16
|
||||||
|
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||||
|
visible: room.permissions.canChange(MtxEvent.PinnedEvents)
|
||||||
|
|
||||||
|
hoverEnabled: true
|
||||||
|
image: ":/icons/icons/ui/dismiss.svg"
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: qsTr("Unpin")
|
||||||
|
|
||||||
|
onClicked: room.unpin(modelData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ScrollHelper {
|
||||||
|
flickable: parent
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
cursorShape: Qt.PointingHandCursor
|
enabled: !Settings.mobileMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,6 +239,54 @@ Item {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: MtxEvent.PinnedEvents
|
||||||
|
|
||||||
|
NoticeMessage {
|
||||||
|
body: formatted
|
||||||
|
isOnlyEmoji: false
|
||||||
|
isReply: d.isReply
|
||||||
|
formatted: qsTr("%1 changed the pinned messages.").arg(d.userName)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: MtxEvent.ImagePackInRoom
|
||||||
|
|
||||||
|
NoticeMessage {
|
||||||
|
body: formatted
|
||||||
|
isOnlyEmoji: false
|
||||||
|
isReply: d.isReply
|
||||||
|
formatted: qsTr("%1 changed the stickers and emotes in this room.").arg(d.userName)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: MtxEvent.CanonicalAlias
|
||||||
|
|
||||||
|
NoticeMessage {
|
||||||
|
body: formatted
|
||||||
|
isOnlyEmoji: false
|
||||||
|
isReply: d.isReply
|
||||||
|
formatted: qsTr("%1 changed the addresses for this room.").arg(d.userName)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DelegateChoice {
|
||||||
|
roleValue: MtxEvent.SpaceParent
|
||||||
|
|
||||||
|
NoticeMessage {
|
||||||
|
body: formatted
|
||||||
|
isOnlyEmoji: false
|
||||||
|
isReply: d.isReply
|
||||||
|
formatted: qsTr("%1 changed the parent spaces for this room.").arg(d.userName)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: MtxEvent.RoomCreate
|
roleValue: MtxEvent.RoomCreate
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ Item {
|
||||||
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
onSingleTapped: chat.model.showEvent(r.eventId)
|
onSingleTapped: room.showEvent(r.eventId)
|
||||||
gesturePolicy: TapHandler.ReleaseWithinBounds
|
gesturePolicy: TapHandler.ReleaseWithinBounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ Item {
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
onSingleTapped: chat.model.openUserProfile(userId)
|
onSingleTapped: room.openUserProfile(userId)
|
||||||
gesturePolicy: TapHandler.ReleaseWithinBounds
|
gesturePolicy: TapHandler.ReleaseWithinBounds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
<file>icons/ui/pause-symbol.svg</file>
|
<file>icons/ui/pause-symbol.svg</file>
|
||||||
<file>icons/ui/people.svg</file>
|
<file>icons/ui/people.svg</file>
|
||||||
<file>icons/ui/picture-in-picture.svg</file>
|
<file>icons/ui/picture-in-picture.svg</file>
|
||||||
|
<file>icons/ui/pin-off.svg</file>
|
||||||
|
<file>icons/ui/pin.svg</file>
|
||||||
<file>icons/ui/place-call.svg</file>
|
<file>icons/ui/place-call.svg</file>
|
||||||
<file>icons/ui/play-sign.svg</file>
|
<file>icons/ui/play-sign.svg</file>
|
||||||
<file>icons/ui/power-off.svg</file>
|
<file>icons/ui/power-off.svg</file>
|
||||||
|
|
|
@ -117,6 +117,7 @@ UserSettings::load(std::optional<QString> profile)
|
||||||
userId_ = settings.value(prefix + "auth/user_id", "").toString();
|
userId_ = settings.value(prefix + "auth/user_id", "").toString();
|
||||||
deviceId_ = settings.value(prefix + "auth/device_id", "").toString();
|
deviceId_ = settings.value(prefix + "auth/device_id", "").toString();
|
||||||
hiddenTags_ = settings.value(prefix + "user/hidden_tags", QStringList{}).toStringList();
|
hiddenTags_ = settings.value(prefix + "user/hidden_tags", QStringList{}).toStringList();
|
||||||
|
hiddenPins_ = settings.value(prefix + "user/hidden_pins", QStringList{}).toStringList();
|
||||||
|
|
||||||
collapsedSpaces_.clear();
|
collapsedSpaces_.clear();
|
||||||
for (const auto &e :
|
for (const auto &e :
|
||||||
|
@ -200,6 +201,14 @@ UserSettings::setHiddenTags(QStringList hiddenTags)
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UserSettings::setHiddenPins(QStringList hiddenTags)
|
||||||
|
{
|
||||||
|
hiddenPins_ = hiddenTags;
|
||||||
|
save();
|
||||||
|
emit hiddenPinsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
UserSettings::setCollapsedSpaces(QList<QStringList> spaces)
|
UserSettings::setCollapsedSpaces(QList<QStringList> spaces)
|
||||||
{
|
{
|
||||||
|
@ -707,6 +716,7 @@ UserSettings::save()
|
||||||
onlyShareKeysWithVerifiedUsers_);
|
onlyShareKeysWithVerifiedUsers_);
|
||||||
settings.setValue(prefix + "user/online_key_backup", useOnlineKeyBackup_);
|
settings.setValue(prefix + "user/online_key_backup", useOnlineKeyBackup_);
|
||||||
settings.setValue(prefix + "user/hidden_tags", hiddenTags_);
|
settings.setValue(prefix + "user/hidden_tags", hiddenTags_);
|
||||||
|
settings.setValue(prefix + "user/hidden_pins", hiddenPins_);
|
||||||
|
|
||||||
QVariantList v;
|
QVariantList v;
|
||||||
for (const auto &e : collapsedSpaces_)
|
for (const auto &e : collapsedSpaces_)
|
||||||
|
|
|
@ -105,6 +105,8 @@ class UserSettings : public QObject
|
||||||
setDisableCertificateValidation NOTIFY disableCertificateValidationChanged)
|
setDisableCertificateValidation NOTIFY disableCertificateValidationChanged)
|
||||||
Q_PROPERTY(bool useIdenticon READ useIdenticon WRITE setUseIdenticon NOTIFY useIdenticonChanged)
|
Q_PROPERTY(bool useIdenticon READ useIdenticon WRITE setUseIdenticon NOTIFY useIdenticonChanged)
|
||||||
|
|
||||||
|
Q_PROPERTY(QStringList hiddenPins READ hiddenPins WRITE setHiddenPins NOTIFY hiddenPinsChanged)
|
||||||
|
|
||||||
UserSettings();
|
UserSettings();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -171,6 +173,7 @@ public:
|
||||||
void setHomeserver(QString homeserver);
|
void setHomeserver(QString homeserver);
|
||||||
void setDisableCertificateValidation(bool disabled);
|
void setDisableCertificateValidation(bool disabled);
|
||||||
void setHiddenTags(QStringList hiddenTags);
|
void setHiddenTags(QStringList hiddenTags);
|
||||||
|
void setHiddenPins(QStringList hiddenTags);
|
||||||
void setUseIdenticon(bool state);
|
void setUseIdenticon(bool state);
|
||||||
void setCollapsedSpaces(QList<QStringList> spaces);
|
void setCollapsedSpaces(QList<QStringList> spaces);
|
||||||
|
|
||||||
|
@ -228,6 +231,7 @@ public:
|
||||||
QString homeserver() const { return homeserver_; }
|
QString homeserver() const { return homeserver_; }
|
||||||
bool disableCertificateValidation() const { return disableCertificateValidation_; }
|
bool disableCertificateValidation() const { return disableCertificateValidation_; }
|
||||||
QStringList hiddenTags() const { return hiddenTags_; }
|
QStringList hiddenTags() const { return hiddenTags_; }
|
||||||
|
QStringList hiddenPins() const { return hiddenPins_; }
|
||||||
bool useIdenticon() const { return useIdenticon_ && JdenticonProvider::isAvailable(); }
|
bool useIdenticon() const { return useIdenticon_ && JdenticonProvider::isAvailable(); }
|
||||||
QList<QStringList> collapsedSpaces() const { return collapsedSpaces_; }
|
QList<QStringList> collapsedSpaces() const { return collapsedSpaces_; }
|
||||||
|
|
||||||
|
@ -278,6 +282,7 @@ signals:
|
||||||
void homeserverChanged(QString homeserver);
|
void homeserverChanged(QString homeserver);
|
||||||
void disableCertificateValidationChanged(bool disabled);
|
void disableCertificateValidationChanged(bool disabled);
|
||||||
void useIdenticonChanged(bool state);
|
void useIdenticonChanged(bool state);
|
||||||
|
void hiddenPinsChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Default to system theme if QT_QPA_PLATFORMTHEME var is set.
|
// Default to system theme if QT_QPA_PLATFORMTHEME var is set.
|
||||||
|
@ -331,6 +336,7 @@ private:
|
||||||
QString deviceId_;
|
QString deviceId_;
|
||||||
QString homeserver_;
|
QString homeserver_;
|
||||||
QStringList hiddenTags_;
|
QStringList hiddenTags_;
|
||||||
|
QStringList hiddenPins_;
|
||||||
QList<QStringList> collapsedSpaces_;
|
QList<QStringList> collapsedSpaces_;
|
||||||
bool useIdenticon_;
|
bool useIdenticon_;
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,10 @@ struct RoomEventType
|
||||||
return qml_mtx_events::EventType::Sticker;
|
return qml_mtx_events::EventType::Sticker;
|
||||||
case EventType::Tag:
|
case EventType::Tag:
|
||||||
return qml_mtx_events::EventType::Tag;
|
return qml_mtx_events::EventType::Tag;
|
||||||
|
case EventType::SpaceParent:
|
||||||
|
return qml_mtx_events::EventType::SpaceParent;
|
||||||
|
case EventType::SpaceChild:
|
||||||
|
return qml_mtx_events::EventType::SpaceChild;
|
||||||
case EventType::Unsupported:
|
case EventType::Unsupported:
|
||||||
return qml_mtx_events::EventType::Unsupported;
|
return qml_mtx_events::EventType::Unsupported;
|
||||||
default:
|
default:
|
||||||
|
@ -286,6 +290,12 @@ qml_mtx_events::fromRoomEventType(qml_mtx_events::EventType t)
|
||||||
// m.tag
|
// m.tag
|
||||||
case qml_mtx_events::Tag:
|
case qml_mtx_events::Tag:
|
||||||
return mtx::events::EventType::Tag;
|
return mtx::events::EventType::Tag;
|
||||||
|
// m.space.parent
|
||||||
|
case qml_mtx_events::SpaceParent:
|
||||||
|
return mtx::events::EventType::SpaceParent;
|
||||||
|
// m.space.child
|
||||||
|
case qml_mtx_events::SpaceChild:
|
||||||
|
return mtx::events::EventType::SpaceChild;
|
||||||
/// m.room.message
|
/// m.room.message
|
||||||
case qml_mtx_events::AudioMessage:
|
case qml_mtx_events::AudioMessage:
|
||||||
case qml_mtx_events::EmoteMessage:
|
case qml_mtx_events::EmoteMessage:
|
||||||
|
@ -808,7 +818,9 @@ TimelineModel::syncState(const mtx::responses::State &s)
|
||||||
emit roomNameChanged();
|
emit roomNameChanged();
|
||||||
else if (std::holds_alternative<StateEvent<state::Topic>>(e))
|
else if (std::holds_alternative<StateEvent<state::Topic>>(e))
|
||||||
emit roomTopicChanged();
|
emit roomTopicChanged();
|
||||||
else if (std::holds_alternative<StateEvent<state::Topic>>(e)) {
|
else if (std::holds_alternative<StateEvent<state::PinnedEvents>>(e))
|
||||||
|
emit pinnedMessagesChanged();
|
||||||
|
else if (std::holds_alternative<StateEvent<state::PowerLevels>>(e)) {
|
||||||
permissions_.invalidate();
|
permissions_.invalidate();
|
||||||
emit permissionsChanged();
|
emit permissionsChanged();
|
||||||
} else if (std::holds_alternative<StateEvent<state::Member>>(e)) {
|
} else if (std::holds_alternative<StateEvent<state::Member>>(e)) {
|
||||||
|
@ -870,6 +882,8 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
|
||||||
emit roomNameChanged();
|
emit roomNameChanged();
|
||||||
else if (std::holds_alternative<StateEvent<state::Topic>>(e))
|
else if (std::holds_alternative<StateEvent<state::Topic>>(e))
|
||||||
emit roomTopicChanged();
|
emit roomTopicChanged();
|
||||||
|
else if (std::holds_alternative<StateEvent<state::PinnedEvents>>(e))
|
||||||
|
emit pinnedMessagesChanged();
|
||||||
else if (std::holds_alternative<StateEvent<state::PowerLevels>>(e)) {
|
else if (std::holds_alternative<StateEvent<state::PowerLevels>>(e)) {
|
||||||
permissions_.invalidate();
|
permissions_.invalidate();
|
||||||
emit permissionsChanged();
|
emit permissionsChanged();
|
||||||
|
@ -1084,6 +1098,60 @@ TimelineModel::replyAction(QString id)
|
||||||
setReply(id);
|
setReply(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineModel::unpin(QString id)
|
||||||
|
{
|
||||||
|
auto pinned =
|
||||||
|
cache::client()->getStateEvent<mtx::events::state::PinnedEvents>(room_id_.toStdString());
|
||||||
|
|
||||||
|
mtx::events::state::PinnedEvents content{};
|
||||||
|
if (pinned)
|
||||||
|
content = pinned->content;
|
||||||
|
|
||||||
|
auto idStr = id.toStdString();
|
||||||
|
|
||||||
|
for (auto it = content.pinned.begin(); it != content.pinned.end(); ++it) {
|
||||||
|
if (*it == idStr) {
|
||||||
|
content.pinned.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http::client()->send_state_event(
|
||||||
|
room_id_.toStdString(),
|
||||||
|
content,
|
||||||
|
[idStr](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
||||||
|
if (err)
|
||||||
|
nhlog::net()->error("Failed to unpin {}: {}", idStr, *err);
|
||||||
|
else
|
||||||
|
nhlog::net()->debug("Unpinned {}", idStr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineModel::pin(QString id)
|
||||||
|
{
|
||||||
|
auto pinned =
|
||||||
|
cache::client()->getStateEvent<mtx::events::state::PinnedEvents>(room_id_.toStdString());
|
||||||
|
|
||||||
|
mtx::events::state::PinnedEvents content{};
|
||||||
|
if (pinned)
|
||||||
|
content = pinned->content;
|
||||||
|
|
||||||
|
auto idStr = id.toStdString();
|
||||||
|
content.pinned.push_back(idStr);
|
||||||
|
|
||||||
|
http::client()->send_state_event(
|
||||||
|
room_id_.toStdString(),
|
||||||
|
content,
|
||||||
|
[idStr](const mtx::responses::EventId &, mtx::http::RequestErr err) {
|
||||||
|
if (err)
|
||||||
|
nhlog::net()->error("Failed to pin {}: {}", idStr, *err);
|
||||||
|
else
|
||||||
|
nhlog::net()->debug("Pinned {}", idStr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineModel::editAction(QString id)
|
TimelineModel::editAction(QString id)
|
||||||
{
|
{
|
||||||
|
@ -2108,6 +2176,23 @@ TimelineModel::roomTopic() const
|
||||||
utils::linkifyMessage(QString::fromStdString(info[room_id_].topic).toHtmlEscaped()));
|
utils::linkifyMessage(QString::fromStdString(info[room_id_].topic).toHtmlEscaped()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList
|
||||||
|
TimelineModel::pinnedMessages() const
|
||||||
|
{
|
||||||
|
auto pinned =
|
||||||
|
cache::client()->getStateEvent<mtx::events::state::PinnedEvents>(room_id_.toStdString());
|
||||||
|
|
||||||
|
if (!pinned || pinned->content.pinned.empty())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
QStringList list;
|
||||||
|
list.reserve(pinned->content.pinned.size());
|
||||||
|
for (const auto &p : pinned->content.pinned)
|
||||||
|
list.push_back(QString::fromStdString(p));
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
crypto::Trust
|
crypto::Trust
|
||||||
TimelineModel::trustlevel() const
|
TimelineModel::trustlevel() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -115,6 +115,10 @@ enum EventType
|
||||||
ImagePackInAccountData,
|
ImagePackInAccountData,
|
||||||
//! m.image_pack.rooms, currently im.ponies.emote_rooms
|
//! m.image_pack.rooms, currently im.ponies.emote_rooms
|
||||||
ImagePackRooms,
|
ImagePackRooms,
|
||||||
|
// m.space.parent
|
||||||
|
SpaceParent,
|
||||||
|
// m.space.child
|
||||||
|
SpaceChild,
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(EventType)
|
Q_ENUM_NS(EventType)
|
||||||
mtx::events::EventType fromRoomEventType(qml_mtx_events::EventType);
|
mtx::events::EventType fromRoomEventType(qml_mtx_events::EventType);
|
||||||
|
@ -172,6 +176,7 @@ class TimelineModel : public QAbstractListModel
|
||||||
Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY plainRoomNameChanged)
|
Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY plainRoomNameChanged)
|
||||||
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged)
|
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged)
|
||||||
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
|
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
|
||||||
|
Q_PROPERTY(QStringList pinnedMessages READ pinnedMessages NOTIFY pinnedMessagesChanged)
|
||||||
Q_PROPERTY(int roomMemberCount READ roomMemberCount NOTIFY roomMemberCountChanged)
|
Q_PROPERTY(int roomMemberCount READ roomMemberCount NOTIFY roomMemberCountChanged)
|
||||||
Q_PROPERTY(bool isEncrypted READ isEncrypted NOTIFY encryptionChanged)
|
Q_PROPERTY(bool isEncrypted READ isEncrypted NOTIFY encryptionChanged)
|
||||||
Q_PROPERTY(bool isSpace READ isSpace CONSTANT)
|
Q_PROPERTY(bool isSpace READ isSpace CONSTANT)
|
||||||
|
@ -256,6 +261,8 @@ public:
|
||||||
Q_INVOKABLE void openUserProfile(QString userid);
|
Q_INVOKABLE void openUserProfile(QString userid);
|
||||||
Q_INVOKABLE void editAction(QString id);
|
Q_INVOKABLE void editAction(QString id);
|
||||||
Q_INVOKABLE void replyAction(QString id);
|
Q_INVOKABLE void replyAction(QString id);
|
||||||
|
Q_INVOKABLE void unpin(QString id);
|
||||||
|
Q_INVOKABLE void pin(QString id);
|
||||||
Q_INVOKABLE void showReadReceipts(QString id);
|
Q_INVOKABLE void showReadReceipts(QString id);
|
||||||
Q_INVOKABLE void redactEvent(QString id);
|
Q_INVOKABLE void redactEvent(QString id);
|
||||||
Q_INVOKABLE int idToIndex(QString id) const;
|
Q_INVOKABLE int idToIndex(QString id) const;
|
||||||
|
@ -354,6 +361,7 @@ public slots:
|
||||||
QString roomName() const;
|
QString roomName() const;
|
||||||
QString plainRoomName() const;
|
QString plainRoomName() const;
|
||||||
QString roomTopic() const;
|
QString roomTopic() const;
|
||||||
|
QStringList pinnedMessages() const;
|
||||||
InputBar *input() { return &input_; }
|
InputBar *input() { return &input_; }
|
||||||
Permissions *permissions() { return &permissions_; }
|
Permissions *permissions() { return &permissions_; }
|
||||||
QString roomAvatarUrl() const;
|
QString roomAvatarUrl() const;
|
||||||
|
@ -395,6 +403,7 @@ signals:
|
||||||
void roomNameChanged();
|
void roomNameChanged();
|
||||||
void plainRoomNameChanged();
|
void plainRoomNameChanged();
|
||||||
void roomTopicChanged();
|
void roomTopicChanged();
|
||||||
|
void pinnedMessagesChanged();
|
||||||
void roomAvatarUrlChanged();
|
void roomAvatarUrlChanged();
|
||||||
void roomMemberCountChanged();
|
void roomMemberCountChanged();
|
||||||
void isDirectChanged();
|
void isDirectChanged();
|
||||||
|
|
Loading…
Reference in a new issue