Organize banners, add LeftBanner
Previously there was InviteOffer, now there's a base Banner component, InviteBanner and LeftBanner.
This commit is contained in:
parent
909e1c3363
commit
ea8f75c729
2
TODO.md
2
TODO.md
|
@ -13,6 +13,7 @@
|
||||||
- Graphic bug when resizing window vertically for side pane?
|
- Graphic bug when resizing window vertically for side pane?
|
||||||
- Fix tooltip hide()
|
- Fix tooltip hide()
|
||||||
- ![A picture](https://picsum.photos/256/256) not clickable?
|
- ![A picture](https://picsum.photos/256/256) not clickable?
|
||||||
|
- Icons aren't reloaded
|
||||||
|
|
||||||
- UI
|
- UI
|
||||||
- Use HRowLayout and its totalSpacing wherever possible
|
- Use HRowLayout and its totalSpacing wherever possible
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
it should be the peer's display name instead.
|
it should be the peer's display name instead.
|
||||||
|
|
||||||
- Missing nio support
|
- Missing nio support
|
||||||
|
- Left room events
|
||||||
- `org.matrix.room.preview_urls` event
|
- `org.matrix.room.preview_urls` event
|
||||||
- `m.room.aliases` event
|
- `m.room.aliases` event
|
||||||
- Avatars
|
- Avatars
|
||||||
|
|
|
@ -22,15 +22,16 @@ _POOLS: DefaultDict[str, ThreadPoolExecutor] = \
|
||||||
|
|
||||||
|
|
||||||
class Client(QObject):
|
class Client(QObject):
|
||||||
roomInvited = pyqtSignal(str)
|
roomInvited = pyqtSignal([str, dict], [str])
|
||||||
roomInvited = pyqtSignal(str, dict)
|
roomJoined = pyqtSignal(str)
|
||||||
roomJoined = pyqtSignal(str)
|
roomLeft = pyqtSignal([str, dict], [str])
|
||||||
roomLeft = pyqtSignal(str)
|
|
||||||
roomSyncPrevBatchTokenReceived = pyqtSignal(str, str)
|
roomSyncPrevBatchTokenReceived = pyqtSignal(str, str)
|
||||||
roomPastPrevBatchTokenReceived = pyqtSignal(str, str)
|
roomPastPrevBatchTokenReceived = pyqtSignal(str, str)
|
||||||
roomEventReceived = pyqtSignal(str, str, dict)
|
roomEventReceived = pyqtSignal(str, str, dict)
|
||||||
roomTypingUsersUpdated = pyqtSignal(str, list)
|
roomTypingUsersUpdated = pyqtSignal(str, list)
|
||||||
messageAboutToBeSent = pyqtSignal(str, dict)
|
|
||||||
|
messageAboutToBeSent = pyqtSignal(str, dict)
|
||||||
|
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
|
@ -120,13 +121,13 @@ class Client(QObject):
|
||||||
|
|
||||||
for room_id, room_info in response.rooms.invite.items():
|
for room_id, room_info in response.rooms.invite.items():
|
||||||
for ev in room_info.invite_state:
|
for ev in room_info.invite_state:
|
||||||
member_event = isinstance(ev, ne.InviteMemberEvent)
|
member_ev = isinstance(ev, ne.InviteMemberEvent)
|
||||||
|
|
||||||
if member_event and ev.content["membership"] == "join":
|
if member_ev and ev.content["membership"] == "join":
|
||||||
self.roomInvited.emit(room_id, ev.content)
|
self.roomInvited.emit(room_id, ev.content)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.roomInvited.emit(room_id)
|
self.roomInvited[str].emit(room_id)
|
||||||
|
|
||||||
for room_id, room_info in response.rooms.join.items():
|
for room_id, room_info in response.rooms.join.items():
|
||||||
self.roomJoined.emit(room_id)
|
self.roomJoined.emit(room_id)
|
||||||
|
@ -146,8 +147,15 @@ class Client(QObject):
|
||||||
else:
|
else:
|
||||||
print("ephemeral event: ", ev)
|
print("ephemeral event: ", ev)
|
||||||
|
|
||||||
for room_id in response.rooms.leave:
|
for room_id, room_info in response.rooms.leave.items():
|
||||||
self.roomLeft.emit(room_id)
|
for ev in room_info.timeline.events:
|
||||||
|
member_ev = isinstance(ev, ne.RoomMemberEvent)
|
||||||
|
|
||||||
|
if member_ev and ev.content["membership"] in ("leave", "ban"):
|
||||||
|
self.roomLeft.emit(room_id, ev.__dict__)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.roomLeft[str].emit(room_id)
|
||||||
|
|
||||||
|
|
||||||
@futurize()
|
@futurize()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from typing import Any, Callable, Optional, Tuple, Union
|
from typing import Any, Callable, Optional, Sequence, Tuple, Union
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
|
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
|
||||||
|
|
||||||
|
@ -6,8 +6,9 @@ from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal
|
||||||
class ListItem(QObject):
|
class ListItem(QObject):
|
||||||
roles: Tuple[str, ...] = ()
|
roles: Tuple[str, ...] = ()
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, no_update: Sequence[str] = (), **kwargs):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
self.no_update = no_update
|
||||||
|
|
||||||
for role, value in zip(self.roles, args):
|
for role, value in zip(self.roles, args):
|
||||||
setattr(self, role, value)
|
setattr(self, role, value)
|
||||||
|
@ -17,8 +18,9 @@ class ListItem(QObject):
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return "%s(%s)" % (
|
return "%s(no_update=%s, %s)" % (
|
||||||
type(self).__name__,
|
type(self).__name__,
|
||||||
|
self.no_update,
|
||||||
", ".join((f"{r}={getattr(self, r)!r}" for r in self.roles)),
|
", ".join((f"{r}={getattr(self, r)!r}" for r in self.roles)),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -63,7 +65,7 @@ class User(ListItem):
|
||||||
|
|
||||||
class Room(ListItem):
|
class Room(ListItem):
|
||||||
roles = ("roomId", "category", "displayName", "topic", "typingUsers",
|
roles = ("roomId", "category", "displayName", "topic", "typingUsers",
|
||||||
"inviter")
|
"inviter", "leftEvent")
|
||||||
|
|
||||||
categoryChanged = pyqtSignal(str)
|
categoryChanged = pyqtSignal(str)
|
||||||
displayNameChanged = pyqtSignal("QVariant")
|
displayNameChanged = pyqtSignal("QVariant")
|
||||||
|
@ -75,7 +77,8 @@ class Room(ListItem):
|
||||||
displayName = prop(str, "displayName", displayNameChanged)
|
displayName = prop(str, "displayName", displayNameChanged)
|
||||||
topic = prop(str, "topic", topicChanged, "")
|
topic = prop(str, "topic", topicChanged, "")
|
||||||
typingUsers = prop(list, "typingUsers", typingUsersChanged, [])
|
typingUsers = prop(list, "typingUsers", typingUsersChanged, [])
|
||||||
inviter = prop("QVariantMap", "inviter")
|
inviter = prop("QVariant", "inviter")
|
||||||
|
leftEvent = prop("QVariant", "leftEvent")
|
||||||
|
|
||||||
|
|
||||||
class RoomEvent(ListItem):
|
class RoomEvent(ListItem):
|
||||||
|
|
|
@ -148,6 +148,9 @@ class ListModel(QAbstractListModel):
|
||||||
value = self._convert_new_value(value)
|
value = self._convert_new_value(value)
|
||||||
|
|
||||||
for role in self.roles:
|
for role in self.roles:
|
||||||
|
if role in value.no_update:
|
||||||
|
continue
|
||||||
|
|
||||||
setattr(self._data[index], role, getattr(value, role))
|
setattr(self._data[index], role, getattr(value, role))
|
||||||
|
|
||||||
qidx = QAbstractListModel.index(self, index, 0)
|
qidx = QAbstractListModel.index(self, index, 0)
|
||||||
|
|
|
@ -13,7 +13,8 @@ from .backend import Backend
|
||||||
from .client import Client
|
from .client import Client
|
||||||
from .model.items import Room, RoomEvent, User
|
from .model.items import Room, RoomEvent, User
|
||||||
|
|
||||||
Inviter = Optional[Dict[str, str]]
|
Inviter = Optional[Dict[str, str]]
|
||||||
|
LeftEvent = Optional[Dict[str, str]]
|
||||||
|
|
||||||
|
|
||||||
class SignalManager(QObject):
|
class SignalManager(QObject):
|
||||||
|
@ -23,8 +24,8 @@ class SignalManager(QObject):
|
||||||
super().__init__(parent=backend)
|
super().__init__(parent=backend)
|
||||||
self.backend = backend
|
self.backend = backend
|
||||||
|
|
||||||
self.last_room_events: Deque[str] = Deque(maxlen=1000)
|
self.last_room_events: Deque[str] = Deque(maxlen=1000)
|
||||||
self._events_in_transfer: int = 0
|
self._events_in_transfer: int = 0
|
||||||
|
|
||||||
cm = self.backend.clientManager
|
cm = self.backend.clientManager
|
||||||
cm.clientAdded.connect(self.onClientAdded)
|
cm.clientAdded.connect(self.onClientAdded)
|
||||||
|
@ -60,45 +61,60 @@ class SignalManager(QObject):
|
||||||
client: Client,
|
client: Client,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
inviter: Inviter = None) -> None:
|
inviter: Inviter = None) -> None:
|
||||||
self._add_room(
|
|
||||||
client, client.nio.invited_rooms[room_id], "Invites", inviter
|
self._add_room(client, room_id, client.nio.invited_rooms[room_id],
|
||||||
)
|
"Invites", inviter=inviter)
|
||||||
|
|
||||||
|
|
||||||
def onRoomJoined(self, client: Client, room_id: str) -> None:
|
def onRoomJoined(self, client: Client, room_id: str) -> None:
|
||||||
self._add_room(client, client.nio.rooms[room_id], "Rooms")
|
self._add_room(client, room_id, client.nio.rooms[room_id], "Rooms")
|
||||||
|
|
||||||
|
|
||||||
|
def onRoomLeft(self,
|
||||||
|
client: Client,
|
||||||
|
room_id: str,
|
||||||
|
left_event: LeftEvent = None) -> None:
|
||||||
|
|
||||||
|
self._add_room(client, room_id, client.nio.rooms.get(room_id), "Left",
|
||||||
|
left_event=left_event)
|
||||||
|
|
||||||
|
|
||||||
def _add_room(self,
|
def _add_room(self,
|
||||||
client: Client,
|
client: Client,
|
||||||
room: MatrixRoom,
|
room_id: str,
|
||||||
category: str,
|
room: MatrixRoom,
|
||||||
inviter: Inviter = None) -> None:
|
category: str,
|
||||||
model = self.backend.models.rooms[client.userId]
|
inviter: Inviter = None,
|
||||||
|
left_event: LeftEvent = None) -> None:
|
||||||
|
|
||||||
|
assert not (inviter and left_event)
|
||||||
|
|
||||||
|
model = self.backend.models.rooms[client.userId]
|
||||||
|
no_update = []
|
||||||
|
|
||||||
|
def get_displayname() -> Optional[str]:
|
||||||
|
if not room:
|
||||||
|
no_update.append("displayName")
|
||||||
|
return room_id
|
||||||
|
|
||||||
|
name = room.name or room.canonical_alias
|
||||||
|
if name:
|
||||||
|
return name
|
||||||
|
|
||||||
def group_name() -> Optional[str]:
|
|
||||||
name = room.group_name()
|
name = room.group_name()
|
||||||
return None if name == "Empty room?" else name
|
return None if name == "Empty room?" else name
|
||||||
|
|
||||||
item = Room(
|
item = Room(
|
||||||
roomId = room.room_id,
|
roomId = room_id,
|
||||||
category = category,
|
category = category,
|
||||||
displayName = room.name or room.canonical_alias or group_name(),
|
displayName = get_displayname(),
|
||||||
topic = room.topic,
|
topic = room.topic if room else "",
|
||||||
inviter = inviter,
|
inviter = inviter,
|
||||||
|
leftEvent = left_event,
|
||||||
|
no_update = no_update,
|
||||||
)
|
)
|
||||||
|
|
||||||
model.updateOrAppendWhere("roomId", room.room_id, item)
|
model.updateOrAppendWhere("roomId", room_id, item)
|
||||||
|
|
||||||
|
|
||||||
def onRoomLeft(self, client: Client, room_id: str) -> None:
|
|
||||||
rooms = self.backend.models.rooms[client.userId]
|
|
||||||
try:
|
|
||||||
index = rooms.indexWhere("roomId", room_id)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
del rooms[index]
|
|
||||||
|
|
||||||
|
|
||||||
def onRoomSyncPrevBatchTokenReceived(
|
def onRoomSyncPrevBatchTokenReceived(
|
||||||
|
|
|
@ -15,7 +15,7 @@ Controls1.SplitView {
|
||||||
}
|
}
|
||||||
|
|
||||||
StackView {
|
StackView {
|
||||||
function showRoom(userId, roomId, isInvite) {
|
function showRoom(userId, roomId) {
|
||||||
pageStack.replace(
|
pageStack.replace(
|
||||||
"chat/Root.qml", { userId: userId, roomId: roomId }
|
"chat/Root.qml", { userId: userId, roomId: roomId }
|
||||||
)
|
)
|
||||||
|
@ -29,6 +29,7 @@ Controls1.SplitView {
|
||||||
initialItem: Item { // TODO: (test, remove)
|
initialItem: Item { // TODO: (test, remove)
|
||||||
Keys.onPressed: pageStack.showRoom(
|
Keys.onPressed: pageStack.showRoom(
|
||||||
"@test_mary:matrix.org", "!TSXGsbBbdwsdylIOJZ:matrix.org"
|
"@test_mary:matrix.org", "!TSXGsbBbdwsdylIOJZ:matrix.org"
|
||||||
|
//"@test_mary:matrix.org", "!TEXkdeErtVCMqClNfb:matrix.org"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
89
harmonyqml/components/chat/Banner.qml
Normal file
89
harmonyqml/components/chat/Banner.qml
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.4
|
||||||
|
import "../base" as Base
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: banner
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 32
|
||||||
|
color: "#BBB"
|
||||||
|
|
||||||
|
property alias avatarName: bannerAvatar.name
|
||||||
|
property alias avatarSource: bannerAvatar.imageSource
|
||||||
|
property alias labelText: bannerLabel.text
|
||||||
|
property alias buttonModel: bannerRepeater.model
|
||||||
|
|
||||||
|
Base.HRowLayout {
|
||||||
|
id: bannerRow
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Base.Avatar {
|
||||||
|
id: bannerAvatar
|
||||||
|
dimmension: banner.Layout.preferredHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
Base.HLabel {
|
||||||
|
id: bannerLabel
|
||||||
|
textFormat: Text.StyledText
|
||||||
|
maximumLineCount: 1
|
||||||
|
elide: Text.ElideRight
|
||||||
|
|
||||||
|
visible:
|
||||||
|
bannerRow.width - bannerAvatar.width - bannerButtons.width > 30
|
||||||
|
|
||||||
|
Layout.maximumWidth:
|
||||||
|
bannerRow.width -
|
||||||
|
bannerAvatar.width - bannerButtons.width -
|
||||||
|
Layout.leftMargin - Layout.rightMargin
|
||||||
|
|
||||||
|
Layout.leftMargin: 10
|
||||||
|
Layout.rightMargin: Layout.leftMargin
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
|
||||||
|
Base.HRowLayout {
|
||||||
|
id: bannerButtons
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
function getButtonsWidth() {
|
||||||
|
var total = 0
|
||||||
|
|
||||||
|
for (var i = 0; i < bannerRepeater.count; i++) {
|
||||||
|
total += bannerRepeater.itemAt(i).implicitWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
return total
|
||||||
|
}
|
||||||
|
|
||||||
|
property bool compact:
|
||||||
|
bannerRow.width <
|
||||||
|
bannerAvatar.width +
|
||||||
|
bannerLabel.implicitWidth +
|
||||||
|
bannerLabel.Layout.leftMargin +
|
||||||
|
bannerLabel.Layout.rightMargin +
|
||||||
|
getButtonsWidth()
|
||||||
|
|
||||||
|
property int displayMode:
|
||||||
|
compact ? Button.IconOnly : Button.TextBesideIcon
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: bannerRepeater
|
||||||
|
model: []
|
||||||
|
|
||||||
|
Base.HButton {
|
||||||
|
id: declineButton
|
||||||
|
text: modelData.text
|
||||||
|
iconName: modelData.iconName
|
||||||
|
icon.color: modelData.iconColor
|
||||||
|
icon.width: 32
|
||||||
|
display: bannerButtons.displayMode
|
||||||
|
|
||||||
|
Layout.maximumWidth: bannerButtons.compact ? height : -1
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
harmonyqml/components/chat/InviteBanner.qml
Normal file
29
harmonyqml/components/chat/InviteBanner.qml
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.4
|
||||||
|
import "../base" as Base
|
||||||
|
|
||||||
|
Banner {
|
||||||
|
property var inviter: null
|
||||||
|
|
||||||
|
avatarName: inviter ? inviter.displayname : ""
|
||||||
|
//avatarSource: inviter ? inviter.avatar_url : ""
|
||||||
|
|
||||||
|
labelText:
|
||||||
|
(inviter ?
|
||||||
|
("<b>" + inviter.displayname + "</b>") : qsTr("Someone")) +
|
||||||
|
" " + qsTr("invited you to join the room.")
|
||||||
|
|
||||||
|
buttonModel: [
|
||||||
|
{
|
||||||
|
text: "Accept",
|
||||||
|
iconName: "accept",
|
||||||
|
iconColor: Qt.hsla(0.45, 0.9, 0.3, 1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Decline",
|
||||||
|
iconName: "decline",
|
||||||
|
iconColor: Qt.hsla(0.95, 0.9, 0.35, 1),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,84 +0,0 @@
|
||||||
import QtQuick 2.7
|
|
||||||
import QtQuick.Controls 2.2
|
|
||||||
import QtQuick.Layouts 1.4
|
|
||||||
import "../base" as Base
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: inviteOffer
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.preferredHeight: 32
|
|
||||||
color: "#BBB"
|
|
||||||
|
|
||||||
property var inviter: null
|
|
||||||
|
|
||||||
Base.HRowLayout {
|
|
||||||
id: inviteRow
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Base.Avatar {
|
|
||||||
id: inviteAvatar
|
|
||||||
name: inviter ? inviter.displayname : ""
|
|
||||||
dimmension: inviteOffer.Layout.preferredHeight
|
|
||||||
//imageSource: inviter ? inviter.avatar_url : ""
|
|
||||||
}
|
|
||||||
|
|
||||||
Base.HLabel {
|
|
||||||
id: inviteLabel
|
|
||||||
text: (inviter ?
|
|
||||||
("<b>" + inviter.displayname + "</b>") : qsTr("Someone")) +
|
|
||||||
" " + qsTr("invited you to join the room.")
|
|
||||||
textFormat: Text.StyledText
|
|
||||||
maximumLineCount: 1
|
|
||||||
elide: Text.ElideRight
|
|
||||||
|
|
||||||
visible:
|
|
||||||
inviteRow.width - inviteAvatar.width - inviteButtons.width > 30
|
|
||||||
|
|
||||||
Layout.maximumWidth:
|
|
||||||
inviteRow.width -
|
|
||||||
inviteAvatar.width - inviteButtons.width -
|
|
||||||
Layout.leftMargin - Layout.rightMargin
|
|
||||||
|
|
||||||
Layout.leftMargin: 10
|
|
||||||
Layout.rightMargin: Layout.leftMargin
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
|
|
||||||
Base.HRowLayout {
|
|
||||||
id: inviteButtons
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
property bool compact:
|
|
||||||
inviteRow.width <
|
|
||||||
inviteAvatar.width + inviteLabel.implicitWidth +
|
|
||||||
acceptButton.implicitWidth + declineButton.implicitWidth
|
|
||||||
|
|
||||||
property int displayMode:
|
|
||||||
compact ? Button.IconOnly : Button.TextBesideIcon
|
|
||||||
|
|
||||||
Base.HButton {
|
|
||||||
id: acceptButton
|
|
||||||
text: qsTr("Accept")
|
|
||||||
iconName: "accept"
|
|
||||||
icon.color: Qt.hsla(0.45, 0.9, 0.3, 1)
|
|
||||||
display: inviteButtons.displayMode
|
|
||||||
|
|
||||||
Layout.maximumWidth: inviteButtons.compact ? height : -1
|
|
||||||
Layout.fillHeight: true
|
|
||||||
}
|
|
||||||
|
|
||||||
Base.HButton {
|
|
||||||
id: declineButton
|
|
||||||
text: qsTr("Decline")
|
|
||||||
iconName: "decline"
|
|
||||||
icon.color: Qt.hsla(0.95, 0.9, 0.35, 1)
|
|
||||||
icon.width: 32
|
|
||||||
display: inviteButtons.displayMode
|
|
||||||
|
|
||||||
Layout.maximumWidth: inviteButtons.compact ? height : -1
|
|
||||||
Layout.fillHeight: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
25
harmonyqml/components/chat/LeftBanner.qml
Normal file
25
harmonyqml/components/chat/LeftBanner.qml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.4
|
||||||
|
import "../base" as Base
|
||||||
|
import "utils.js" as ChatJS
|
||||||
|
|
||||||
|
Banner {
|
||||||
|
property var leftEvent: null
|
||||||
|
|
||||||
|
avatarName: ChatJS.getLeftBannerAvatarName(leftEvent, chatPage.userId)
|
||||||
|
labelText: ChatJS.getLeftBannerText(leftEvent)
|
||||||
|
|
||||||
|
buttonModel: [
|
||||||
|
{
|
||||||
|
text: "Rejoin",
|
||||||
|
iconName: "join",
|
||||||
|
iconColor: Qt.hsla(0.13, 0.9, 0.35, 1),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Forget",
|
||||||
|
iconName: "trash_can",
|
||||||
|
iconColor: Qt.hsla(0.95, 0.9, 0.35, 1),
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -9,8 +9,6 @@ ColumnLayout {
|
||||||
readonly property var roomInfo:
|
readonly property var roomInfo:
|
||||||
Backend.models.rooms.get(userId).getWhere("roomId", roomId)
|
Backend.models.rooms.get(userId).getWhere("roomId", roomId)
|
||||||
|
|
||||||
property bool isInvite: roomInfo.category === "Invites"
|
|
||||||
|
|
||||||
id: chatPage
|
id: chatPage
|
||||||
spacing: 0
|
spacing: 0
|
||||||
onFocusChanged: sendBox.setFocus()
|
onFocusChanged: sendBox.setFocus()
|
||||||
|
@ -20,19 +18,22 @@ ColumnLayout {
|
||||||
topic: roomInfo.topic
|
topic: roomInfo.topic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MessageList {}
|
MessageList {}
|
||||||
|
|
||||||
|
|
||||||
TypingUsersBar {}
|
TypingUsersBar {}
|
||||||
|
|
||||||
InviteOffer {
|
InviteBanner {
|
||||||
visible: isInvite
|
visible: roomInfo.category === "Invites"
|
||||||
inviter: roomInfo.inviter
|
inviter: roomInfo.inviter
|
||||||
}
|
}
|
||||||
|
|
||||||
SendBox {
|
SendBox {
|
||||||
id: sendBox
|
id: sendBox
|
||||||
visible: ! isInvite
|
visible: roomInfo.category === "Rooms"
|
||||||
|
}
|
||||||
|
|
||||||
|
LeftBanner {
|
||||||
|
visible: roomInfo.category === "Left"
|
||||||
|
leftEvent: roomInfo.leftEvent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,6 +151,51 @@ function getMemberEventText(dict) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getLeftBannerText(leftEvent) {
|
||||||
|
if (! leftEvent) {
|
||||||
|
return "You are not member of this room."
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(JSON.stringify(leftEvent, null, 4))
|
||||||
|
|
||||||
|
var info = leftEvent.content
|
||||||
|
var prev = leftEvent.prev_content
|
||||||
|
var reason = info.reason ? (" Reason: " + info.reason) : ""
|
||||||
|
|
||||||
|
if (leftEvent.state_key === leftEvent.sender) {
|
||||||
|
return (prev && prev.membership === "invite" ?
|
||||||
|
"You declined to join this room." : "You left the room.") +
|
||||||
|
reason
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.membership)
|
||||||
|
|
||||||
|
var name = Backend.getUserDisplayName(leftEvent.sender, false).result()
|
||||||
|
|
||||||
|
return "<b>" + name + "</b> " +
|
||||||
|
(info.membership == "ban" ?
|
||||||
|
"banned you from the room." :
|
||||||
|
|
||||||
|
prev && prev.membership === "invite" ?
|
||||||
|
"canceled your invitation." :
|
||||||
|
|
||||||
|
prev && prev.membership == "ban" ?
|
||||||
|
"unbanned you from the room." :
|
||||||
|
|
||||||
|
"kicked you out of the room.") +
|
||||||
|
reason
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getLeftBannerAvatarName(leftEvent, accountId) {
|
||||||
|
if (! leftEvent || leftEvent.state_key == leftEvent.sender) {
|
||||||
|
return Backend.getUserDisplayName(accountId, false).result()
|
||||||
|
}
|
||||||
|
|
||||||
|
return Backend.getUserDisplayName(leftEvent.sender, false).result()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function getTypingUsersText(users, ourAccountId) {
|
function getTypingUsersText(users, ourAccountId) {
|
||||||
var names = []
|
var names = []
|
||||||
|
|
||||||
|
|
1
harmonyqml/icons/join.svg
Normal file
1
harmonyqml/icons/join.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M16 9v-4l8 7-8 7v-4h-8v-6h8zm-2 10v-.083c-1.178.685-2.542 1.083-4 1.083-4.411 0-8-3.589-8-8s3.589-8 8-8c1.458 0 2.822.398 4 1.083v-2.245c-1.226-.536-2.577-.838-4-.838-5.522 0-10 4.477-10 10s4.478 10 10 10c1.423 0 2.774-.302 4-.838v-2.162z"/></svg>
|
After Width: | Height: | Size: 339 B |
1
harmonyqml/icons/trash_can.svg
Normal file
1
harmonyqml/icons/trash_can.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M3 6v18h18v-18h-18zm5 14c0 .552-.448 1-1 1s-1-.448-1-1v-10c0-.552.448-1 1-1s1 .448 1 1v10zm5 0c0 .552-.448 1-1 1s-1-.448-1-1v-10c0-.552.448-1 1-1s1 .448 1 1v10zm5 0c0 .552-.448 1-1 1s-1-.448-1-1v-10c0-.552.448-1 1-1s1 .448 1 1v10zm4-18v2h-20v-2h5.711c.9 0 1.631-1.099 1.631-2h5.315c0 .901.73 2 1.631 2h5.712z"/></svg>
|
After Width: | Height: | Size: 409 B |
Loading…
Reference in New Issue
Block a user