diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index af3a3371..a0ff0ff1 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -100,6 +100,7 @@ Item {
required property string url
required property string userId
required property string userName
+ required property int userPowerlevel
ListView.delayRemove: true
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
@@ -119,6 +120,7 @@ Item {
property date timestamp: wrapper.timestamp
property string userId: wrapper.userId
property string userName: wrapper.userName
+ property int userPowerlevel: wrapper.userPowerlevel
active: previousMessageUserId !== userId || previousMessageDay !== day || previousMessageIsStateEvent !== isStateEvent
//asynchronous: true
@@ -562,14 +564,25 @@ Item {
target: room
}
+
AbstractButton {
id: userNameButton
+ PowerlevelIndicator {
+ id: powerlevelIndicator
+ anchors.left: parent.left
+ //anchors.horizontalCenter: parent.horizontalCenter
+
+ powerlevel: userPowerlevel
+ permissions: room ? room.permissions : null
+ visible: isAdmin || isModerator
+ }
+
ToolTip.delay: Nheko.tooltipDelay
ToolTip.text: userId
ToolTip.visible: hovered
+ leftPadding: powerlevelIndicator.visible ? 16 : 0
leftInset: 0
- leftPadding: 0
rightInset: 0
rightPadding: 0
diff --git a/resources/qml/Reactions.qml b/resources/qml/Reactions.qml
index 5ab58beb..eff62fc1 100644
--- a/resources/qml/Reactions.qml
+++ b/resources/qml/Reactions.qml
@@ -77,6 +77,7 @@ Flow {
source: modelData.key.startsWith("mxc://") ? (modelData.key.replace("mxc://", "image://MxcImage/") + "?scale") : ""
visible: modelData.key.startsWith("mxc://")
width: textMetrics.height
+ mipmap: true
}
Rectangle {
id: divider
diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml
index 92e7ef6d..20e5b95b 100644
--- a/resources/qml/RoomList.qml
+++ b/resources/qml/RoomList.qml
@@ -727,6 +727,11 @@ Page {
}
}
Platform.MenuItem {
+ text: qsTr("Mark as read")
+ onTriggered: Rooms.getRoomById(roomContextMenu.roomid).markRoomAsRead()
+ }
+
+ Platform.MenuItem {
text: qsTr("Room settings")
onTriggered: TimelineManager.openRoomSettings(roomContextMenu.roomid)
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index fb0c6036..1e8a6a27 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -385,6 +385,18 @@ Pane {
console.error("Failed to create component: " + component.errorString());
}
}
+ function onFallbackAuth(fallback) {
+ var component = Qt.createComponent("qrc:/resources/qml/dialogs/FallbackAuthDialog.qml");
+ if (component.status == Component.Ready) {
+ var dialog = component.createObject(timelineRoot, {
+ "fallback": fallback
+ });
+ dialog.show();
+ destroyOnClose(dialog);
+ } else {
+ console.error("Failed to create component: " + component.errorString());
+ }
+ }
target: UIA
}
diff --git a/resources/qml/components/PowerlevelIndicator.qml b/resources/qml/components/PowerlevelIndicator.qml
new file mode 100644
index 00000000..4b826284
--- /dev/null
+++ b/resources/qml/components/PowerlevelIndicator.qml
@@ -0,0 +1,42 @@
+// SPDX-FileCopyrightText: Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import QtQuick
+import QtQuick.Controls
+import im.nheko
+
+Image {
+ required property int powerlevel
+ required property var permissions
+
+ readonly property bool isAdmin: permissions ? permissions.changeLevel(MtxEvent.PowerLevels) <= powerlevel : false
+ readonly property bool isModerator: permissions ? permissions.redactLevel() <= powerlevel : false
+ readonly property bool isDefault: permissions ? permissions.defaultLevel() <= powerlevel : false
+
+ readonly property string sourceUrl: {
+ if (isAdmin)
+ return "image://colorimage/:/icons/icons/ui/ribbon_star.svg?";
+ else if (isModerator)
+ return "image://colorimage/:/icons/icons/ui/ribbon.svg?";
+ else
+ return "image://colorimage/:/icons/icons/ui/person.svg?";
+ }
+
+ sourceSize.width: 16
+ sourceSize.height: 16
+ source: sourceUrl + (ma.hovered ? palette.highlight : palette.buttonText)
+ ToolTip.visible: ma.hovered
+ ToolTip.text: {
+ if (isAdmin)
+ return qsTr("Administrator: %1").arg(powerlevel);
+ else if (isModerator)
+ return qsTr("Moderator: %1").arg(powerlevel);
+ else
+ return qsTr("User: %1").arg(powerlevel);
+ }
+
+ HoverHandler {
+ id: ma
+ }
+}
diff --git a/resources/qml/dialogs/FallbackAuthDialog.qml b/resources/qml/dialogs/FallbackAuthDialog.qml
new file mode 100644
index 00000000..d9a7ac8f
--- /dev/null
+++ b/resources/qml/dialogs/FallbackAuthDialog.qml
@@ -0,0 +1,63 @@
+// SPDX-FileCopyrightText: Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+import QtQuick
+import QtQuick.Controls
+import im.nheko
+
+ApplicationWindow {
+ id: fallbackRoot
+
+ required property FallbackAuth fallback
+
+ function accept() {
+ fallback.confirm();
+ fallbackRoot.close();
+ }
+
+ function reject() {
+ fallback.cancel();
+ fallbackRoot.close();
+ }
+
+ color: palette.window
+ title: qsTr("Fallback authentication")
+ flags: Qt.Tool | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
+ height: msg.implicitHeight + footer.implicitHeight
+ width: Math.max(msg.implicitWidth, footer.implicitWidth)
+
+ Shortcut {
+ sequence: StandardKey.Cancel
+ onActivated: fallbackRoot.reject()
+ }
+
+ Label {
+ id: msg
+
+ anchors.fill: parent
+ padding: 8
+ text: qsTr("Open the fallback, follow the steps, and confirm after completing them.")
+ }
+
+ footer: DialogButtonBox {
+ onAccepted: fallbackRoot.accept()
+ onRejected: fallbackRoot.reject()
+
+ Button {
+ text: qsTr("Open Fallback in Browser")
+ onClicked: fallback.openFallbackAuth()
+ }
+
+ Button {
+ text: qsTr("Cancel")
+ DialogButtonBox.buttonRole: DialogButtonBox.RejectRole
+ }
+
+ Button {
+ text: qsTr("Confirm")
+ DialogButtonBox.buttonRole: DialogButtonBox.AcceptRole
+ }
+ }
+
+}
diff --git a/resources/qml/dialogs/RoomMembers.qml b/resources/qml/dialogs/RoomMembers.qml
index bbf1605d..64f21381 100644
--- a/resources/qml/dialogs/RoomMembers.qml
+++ b/resources/qml/dialogs/RoomMembers.qml
@@ -4,6 +4,7 @@
import ".."
import "../ui"
+import "../components"
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
@@ -159,39 +160,9 @@ ApplicationWindow {
}
- Image {
- property bool isAdmin: room.permissions.changeLevel(MtxEvent.PowerLevels) <= model.powerlevel
- property bool isModerator: room.permissions.redactLevel() <= model.powerlevel
- //property bool isDefault: room.permissions.defaultLevel() <= model.powerlevel
-
- property string sourceUrl: {
- if (isAdmin)
- return "image://colorimage/:/icons/icons/ui/ribbon_star.svg?";
- else if (isModerator)
- return "image://colorimage/:/icons/icons/ui/ribbon.svg?";
- else
- return "image://colorimage/:/icons/icons/ui/person.svg?";
- }
-
- Layout.preferredWidth: 16
- Layout.preferredHeight: 16
- sourceSize.width: width
- sourceSize.height: height
- source: sourceUrl + (ma.hovered ? palette.highlight : palette.buttonText)
- ToolTip.visible: ma.hovered
- ToolTip.text: {
- if (isAdmin)
- return qsTr("Administrator: %1").arg(model.powerlevel);
- else if (isModerator)
- return qsTr("Moderator: %1").arg(model.powerlevel);
- else
- return qsTr("User: %1").arg(model.powerlevel);
- }
-
- HoverHandler {
- id: ma
- }
-
+ PowerlevelIndicator {
+ powerlevel: model.powerlevel
+ permissions: room.permissions
}
EncryptionIndicator {
|