Add users currently typing in room bar
This commit is contained in:
parent
14a76b710b
commit
8a3189df15
2
TODO.md
2
TODO.md
|
@ -20,3 +20,5 @@
|
||||||
- Load previous events on scroll up
|
- Load previous events on scroll up
|
||||||
|
|
||||||
- Migrate more JS functions to their own files
|
- Migrate more JS functions to their own files
|
||||||
|
|
||||||
|
- Accept room\_id arg for getUser
|
||||||
|
|
|
@ -41,6 +41,7 @@ class Client(QObject):
|
||||||
roomJoined = pyqtSignal(str)
|
roomJoined = pyqtSignal(str)
|
||||||
roomLeft = pyqtSignal(str)
|
roomLeft = pyqtSignal(str)
|
||||||
roomEventReceived = pyqtSignal(str, str, dict)
|
roomEventReceived = pyqtSignal(str, str, dict)
|
||||||
|
roomTypingUsersUpdated = pyqtSignal(str, list)
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, hostname: str, username: str, device_id: str = ""
|
def __init__(self, hostname: str, username: str, device_id: str = ""
|
||||||
|
@ -121,5 +122,11 @@ class Client(QObject):
|
||||||
room_id, type(ev).__name__, ev.__dict__
|
room_id, type(ev).__name__, ev.__dict__
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for ev in room_info.ephemeral:
|
||||||
|
if isinstance(ev, nr.TypingNoticeEvent):
|
||||||
|
self.roomTypingUsersUpdated.emit(room_id, ev.users)
|
||||||
|
else:
|
||||||
|
print("ephemeral event: ", ev)
|
||||||
|
|
||||||
for room_id in response.rooms.leave:
|
for room_id in response.rooms.leave:
|
||||||
self.roomLeft.emit(room_id)
|
self.roomLeft.emit(room_id)
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
# Copyright 2019 miruka
|
# Copyright 2019 miruka
|
||||||
# This file is part of harmonyqml, licensed under GPLv3.
|
# This file is part of harmonyqml, licensed under GPLv3.
|
||||||
|
|
||||||
from typing import Dict, NamedTuple, Optional
|
from typing import Dict, List, NamedTuple, Optional
|
||||||
|
|
||||||
from PyQt5.QtCore import QDateTime
|
from PyQt5.QtCore import QDateTime
|
||||||
|
|
||||||
from .enums import Activity, Presence
|
|
||||||
|
|
||||||
|
|
||||||
class User(NamedTuple):
|
class User(NamedTuple):
|
||||||
user_id: str
|
user_id: str
|
||||||
|
@ -19,11 +17,7 @@ class Room(NamedTuple):
|
||||||
room_id: str
|
room_id: str
|
||||||
display_name: Optional[str]
|
display_name: Optional[str]
|
||||||
description: str = ""
|
description: str = ""
|
||||||
unread_messages: int = 0
|
typing_users: List[str] = []
|
||||||
presence: Presence = Presence.none
|
|
||||||
activity: Activity = Activity.none
|
|
||||||
last_activity_timestamp_ms: Optional[int] = None
|
|
||||||
avatar_url: Optional[str] = None
|
|
||||||
|
|
||||||
|
|
||||||
class RoomEvent(NamedTuple):
|
class RoomEvent(NamedTuple):
|
||||||
|
|
|
@ -10,6 +10,7 @@ from PyQt5.QtCore import (
|
||||||
)
|
)
|
||||||
|
|
||||||
NewValue = Union[Mapping[str, Any], Sequence]
|
NewValue = Union[Mapping[str, Any], Sequence]
|
||||||
|
ReturnItem = Dict[str, Any]
|
||||||
|
|
||||||
|
|
||||||
class ListModel(QAbstractListModel):
|
class ListModel(QAbstractListModel):
|
||||||
|
@ -96,7 +97,7 @@ class ListModel(QAbstractListModel):
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(int, result="QVariantMap")
|
@pyqtSlot(int, result="QVariantMap")
|
||||||
def get(self, index: int) -> Dict[str, Any]:
|
def get(self, index: int) -> ReturnItem:
|
||||||
return self._list[index]._asdict()
|
return self._list[index]._asdict()
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,6 +111,11 @@ class ListModel(QAbstractListModel):
|
||||||
f"property {prop!r} set to {is_value!r}.")
|
f"property {prop!r} set to {is_value!r}.")
|
||||||
|
|
||||||
|
|
||||||
|
@pyqtSlot(str, "QVariant", result="QVariantMap")
|
||||||
|
def getWhere(self, prop: str, is_value: Any) -> ReturnItem:
|
||||||
|
return self.get(self.indexWhere(prop, is_value))
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(int, list)
|
@pyqtSlot(int, list)
|
||||||
def insert(self, index: int, value: NewValue) -> None:
|
def insert(self, index: int, value: NewValue) -> None:
|
||||||
value = self._convert_new_value(value)
|
value = self._convert_new_value(value)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# This file is part of harmonyqml, licensed under GPLv3.
|
# This file is part of harmonyqml, licensed under GPLv3.
|
||||||
|
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from typing import Any, Deque, Dict, Optional
|
from typing import Any, Deque, Dict, List, Optional
|
||||||
|
|
||||||
from PyQt5.QtCore import QDateTime, QObject, pyqtBoundSignal
|
from PyQt5.QtCore import QDateTime, QObject, pyqtBoundSignal
|
||||||
|
|
||||||
|
@ -109,3 +109,11 @@ class SignalManager(QObject):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
model.insert(0, new_event)
|
model.insert(0, new_event)
|
||||||
|
|
||||||
|
|
||||||
|
def onRoomTypingUsersUpdated(
|
||||||
|
self, client: Client, room_id: str, users: List[str]
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
rooms = self.backend.models.rooms[client.userID]
|
||||||
|
rooms[rooms.indexWhere("room_id", room_id)].typing_users = users
|
||||||
|
|
|
@ -24,10 +24,6 @@ Controls1.SplitView {
|
||||||
}
|
}
|
||||||
|
|
||||||
id: "pageStack"
|
id: "pageStack"
|
||||||
// initialItem: Chat.Root {
|
|
||||||
//user: Backend.accountsModel.get(0)
|
|
||||||
//room: Backend.roomsModel[Backend.accountsModel.get(0).user_id].get(0)
|
|
||||||
//}
|
|
||||||
|
|
||||||
onCurrentItemChanged: currentItem.forceActiveFocus()
|
onCurrentItemChanged: currentItem.forceActiveFocus()
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,13 @@ ColumnLayout {
|
||||||
property var user_id: null
|
property var user_id: null
|
||||||
property var room: null
|
property var room: null
|
||||||
|
|
||||||
|
|
||||||
id: chatPage
|
id: chatPage
|
||||||
spacing: 0
|
spacing: 0
|
||||||
onFocusChanged: sendBox.setFocus()
|
onFocusChanged: sendBox.setFocus()
|
||||||
|
|
||||||
RoomHeader {}
|
RoomHeader {}
|
||||||
MessageList {}
|
MessageList {}
|
||||||
|
TypingUsersBar {}
|
||||||
SendBox { id: sendBox }
|
SendBox { id: sendBox }
|
||||||
}
|
}
|
||||||
|
|
31
harmonyqml/components/chat/TypingUsersBar.qml
Normal file
31
harmonyqml/components/chat/TypingUsersBar.qml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import QtQuick.Layouts 1.4
|
||||||
|
import "../base" as Base
|
||||||
|
import "utils.js" as ChatJS
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.minimumHeight: usersLabel.text ? usersLabel.implicitHeight : 0
|
||||||
|
Layout.maximumHeight: Layout.minimumHeight
|
||||||
|
color: "#BBB"
|
||||||
|
|
||||||
|
Base.HLabel {
|
||||||
|
id: "usersLabel"
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 500
|
||||||
|
repeat: true
|
||||||
|
running: true
|
||||||
|
triggeredOnStart: true
|
||||||
|
onTriggered: usersLabel.text = ChatJS.get_typing_users_text(
|
||||||
|
chatPage.user_id, chatPage.room.room_id
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
maximumLineCount: 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -124,3 +124,21 @@ function get_member_event_text(dict) {
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function get_typing_users_text(account_id, room_id) {
|
||||||
|
var names = []
|
||||||
|
var room = Backend.models.rooms.get(account_id)
|
||||||
|
.getWhere("room_id", room_id)
|
||||||
|
|
||||||
|
for (var i = 0; i < room.typing_users.length; i++) {
|
||||||
|
names.push(Backend.getUser(room.typing_users[i]).display_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (names.length < 1) { return "" }
|
||||||
|
|
||||||
|
return "🖋 " +
|
||||||
|
[names.slice(0, -1).join(", "), names.slice(-1)[0]]
|
||||||
|
.join(names.length < 2 ? "" : " and ") +
|
||||||
|
(names.length > 1 ? " are" : " is") + " typing…"
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user