Display room messages and other events
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
# This file is part of harmonyqml, licensed under GPLv3.
|
||||
|
||||
import hashlib
|
||||
from typing import Dict
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSlot
|
||||
|
||||
from .client_manager import ClientManager
|
||||
from .model.items import User
|
||||
from .model.qml_models import QMLModels
|
||||
|
||||
|
||||
@@ -35,6 +37,18 @@ class Backend(QObject):
|
||||
return self._models
|
||||
|
||||
|
||||
@pyqtSlot(str, result="QVariantMap")
|
||||
def getUser(self, user_id: str) -> Dict[str, str]:
|
||||
for client in self.clientManager.clients.values():
|
||||
for room in client.nio.rooms.values():
|
||||
|
||||
name = room.user_name(user_id)
|
||||
if name:
|
||||
return User(user_id=user_id, display_name=name)._asdict()
|
||||
|
||||
return User(user_id=user_id, display_name=user_id)._asdict()
|
||||
|
||||
|
||||
@pyqtSlot(str, result=float)
|
||||
def hueFromString(self, string: str) -> float:
|
||||
# pylint:disable=no-self-use
|
||||
|
@@ -7,15 +7,13 @@ import sys
|
||||
import traceback
|
||||
from concurrent.futures import Future, ThreadPoolExecutor
|
||||
from threading import Event, currentThread
|
||||
from typing import Callable, DefaultDict, Dict
|
||||
from typing import Callable, DefaultDict
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot
|
||||
|
||||
import nio
|
||||
import nio.responses as nr
|
||||
|
||||
from .model.items import User
|
||||
|
||||
# One pool per hostname/remote server;
|
||||
# multiple Client for different accounts on the same server can exist.
|
||||
_POOLS: DefaultDict[str, ThreadPoolExecutor] = \
|
||||
@@ -39,9 +37,10 @@ def futurize(func: Callable) -> Callable:
|
||||
|
||||
|
||||
class Client(QObject):
|
||||
roomInvited = pyqtSignal(str)
|
||||
roomJoined = pyqtSignal(str)
|
||||
roomLeft = pyqtSignal(str)
|
||||
roomInvited = pyqtSignal(str)
|
||||
roomJoined = pyqtSignal(str)
|
||||
roomLeft = pyqtSignal(str)
|
||||
roomEventReceived = pyqtSignal(str, str, dict)
|
||||
|
||||
|
||||
def __init__(self, hostname: str, username: str, device_id: str = ""
|
||||
@@ -114,21 +113,13 @@ class Client(QObject):
|
||||
for room_id in response.rooms.invite:
|
||||
self.roomInvited.emit(room_id)
|
||||
|
||||
for room_id in response.rooms.join:
|
||||
for room_id, room_info in response.rooms.join.items():
|
||||
self.roomJoined.emit(room_id)
|
||||
|
||||
for ev in room_info.timeline.events:
|
||||
self.roomEventReceived.emit(
|
||||
room_id, type(ev).__name__, ev.__dict__
|
||||
)
|
||||
|
||||
for room_id in response.rooms.leave:
|
||||
self.roomLeft.emit(room_id)
|
||||
|
||||
|
||||
@pyqtSlot(str, str, result="QVariantMap")
|
||||
def getUser(self, room_id: str, user_id: str) -> Dict[str, str]:
|
||||
try:
|
||||
name = self.nio.rooms[room_id].user_name(user_id)
|
||||
except KeyError:
|
||||
name = None
|
||||
|
||||
return User(
|
||||
user_id = user_id,
|
||||
display_name = name or user_id,
|
||||
)._asdict()
|
||||
|
@@ -1,11 +1,11 @@
|
||||
# Copyright 2019 miruka
|
||||
# This file is part of harmonyqml, licensed under GPLv3.
|
||||
|
||||
from typing import NamedTuple, Optional
|
||||
from typing import Dict, NamedTuple, Optional
|
||||
|
||||
from PyQt5.QtCore import QDateTime
|
||||
|
||||
from .enums import Activity, MessageKind, Presence
|
||||
from .enums import Activity, Presence
|
||||
|
||||
|
||||
class User(NamedTuple):
|
||||
@@ -26,9 +26,7 @@ class Room(NamedTuple):
|
||||
avatar_url: Optional[str] = None
|
||||
|
||||
|
||||
class Message(NamedTuple):
|
||||
sender_id: str
|
||||
date_time: QDateTime
|
||||
content: str
|
||||
kind: MessageKind = MessageKind.text
|
||||
sender_avatar: Optional[str] = None
|
||||
class RoomEvent(NamedTuple):
|
||||
type: str
|
||||
date_time: QDateTime
|
||||
dict: Dict[str, str]
|
||||
|
@@ -13,9 +13,9 @@ class QMLModels(QObject):
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._accounts: ListModel = ListModel()
|
||||
self._rooms: ListModelMap = ListModelMap()
|
||||
self._messages: ListModelMap = ListModelMap()
|
||||
self._accounts: ListModel = ListModel()
|
||||
self._rooms: ListModelMap = ListModelMap()
|
||||
self._room_events: ListModelMap = ListModelMap()
|
||||
|
||||
|
||||
@pyqtProperty(ListModel, constant=True)
|
||||
@@ -29,5 +29,5 @@ class QMLModels(QObject):
|
||||
|
||||
|
||||
@pyqtProperty("QVariant", constant=True)
|
||||
def messages(self):
|
||||
return self._messages
|
||||
def roomEvents(self):
|
||||
return self._room_events
|
||||
|
@@ -1,18 +1,18 @@
|
||||
# Copyright 2019 miruka
|
||||
# This file is part of harmonyqml, licensed under GPLv3.
|
||||
|
||||
from typing import Optional
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from PyQt5.QtCore import QObject
|
||||
from PyQt5.QtCore import QDateTime, QObject, pyqtBoundSignal
|
||||
|
||||
from .backend import Backend
|
||||
from .client import Client
|
||||
from .model.items import Room, User
|
||||
from .model.items import Room, RoomEvent, User
|
||||
|
||||
|
||||
class SignalManager(QObject):
|
||||
def __init__(self, backend: Backend) -> None:
|
||||
super().__init__()
|
||||
super().__init__(parent=backend)
|
||||
self.backend = backend
|
||||
|
||||
cm = self.backend.clientManager
|
||||
@@ -34,10 +34,15 @@ class SignalManager(QObject):
|
||||
|
||||
|
||||
def connectClient(self, client: Client) -> None:
|
||||
for sig_name in ("roomInvited", "roomJoined", "roomLeft"):
|
||||
sig = getattr(client, sig_name)
|
||||
on_sig = getattr(self, f"on{sig_name[0].upper()}{sig_name[1:]}")
|
||||
sig.connect(lambda room_id, o=on_sig, c=client: o(c, room_id))
|
||||
for name in dir(client):
|
||||
attr = getattr(client, name)
|
||||
|
||||
if isinstance(attr, pyqtBoundSignal):
|
||||
def onSignal(*args, name=name) -> None:
|
||||
func = getattr(self, f"on{name[0].upper()}{name[1:]}")
|
||||
func(client, *args)
|
||||
|
||||
attr.connect(onSignal)
|
||||
|
||||
|
||||
def onRoomInvited(self, client: Client, room_id: str) -> None:
|
||||
@@ -69,3 +74,25 @@ class SignalManager(QObject):
|
||||
def onRoomLeft(self, client: Client, room_id: str) -> None:
|
||||
rooms = self.backend.models.rooms[client.userID]
|
||||
del rooms[rooms.indexWhere("room_id", room_id)]
|
||||
|
||||
|
||||
def onRoomEventReceived(
|
||||
self, _: Client, room_id: str, etype: str, edict: Dict[str, Any]
|
||||
) -> None:
|
||||
model = self.backend.models.roomEvents[room_id]
|
||||
date_time = QDateTime.fromMSecsSinceEpoch(edict["server_timestamp"])
|
||||
new_event = RoomEvent(type=etype, date_time=date_time, dict=edict)
|
||||
|
||||
# Insert event in model at the right position, based on timestamps
|
||||
# to keep them sorted by date of arrival.
|
||||
# Iterate in reverse, since a new event is more likely to be appended,
|
||||
# but events can arrive out of order.
|
||||
if not model or model[-1].date_time < new_event.date_time:
|
||||
model.append(new_event)
|
||||
else:
|
||||
for i, event in enumerate(reversed(model)):
|
||||
if event.date_time < new_event.date_time:
|
||||
model.insert(-i, new_event)
|
||||
break
|
||||
else:
|
||||
model.insert(0, new_event)
|
||||
|
Reference in New Issue
Block a user