moment/harmonyqml/backend/base.py
miruka cccc43a9ae Reorganize sidePane, accounts and rooms
- Accordion design for accounts and rooms (not finished)
- Toolbar and account/room lists reduce correctly, buttons become
  hamburger menu if not enough width
- Can set status using the "Set status message" account fields
- Uniformized avatar sizes for sidePane, roomHeader and SendBox
2019-03-26 03:19:55 -04:00

110 lines
3.4 KiB
Python

# Copyright 2019 miruka
# This file is part of harmonyqml, licensed under GPLv3.
import hashlib
from typing import Any, DefaultDict, Dict, NamedTuple, Optional
from PyQt5.QtCore import QDateTime, QObject, pyqtProperty, pyqtSlot
from .enums import Activity, MessageKind, Presence
from .list_model import ListModel, _QtListModel
class User(NamedTuple):
user_id: str
display_name: str
avatar_url: Optional[str] = None
status_message: Optional[str] = None
class Room(NamedTuple):
room_id: str
display_name: str
subtitle: str = ""
unread_messages: int = 0
presence: Presence = Presence.none
activity: Activity = Activity.none
last_activity_timestamp_ms: Optional[int] = None
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 Backend(QObject):
def __init__(self) -> None:
super().__init__()
self._known_users: Dict[str, User] = {}
self.accounts: ListModel = ListModel()
self.rooms: DefaultDict[str, ListModel] = DefaultDict(ListModel)
self.messages: DefaultDict[str, ListModel] = DefaultDict(ListModel)
@pyqtProperty(_QtListModel, constant=True)
def accountsModel(self) -> _QtListModel:
return self.accounts.qt_model
@pyqtProperty("QVariantMap", constant=True)
def roomsModel(self) -> Dict[str, _QtListModel]:
return {account_id: l.qt_model for account_id, l in self.rooms.items()}
@pyqtProperty("QVariantMap", constant=True)
def messagesModel(self) -> Dict[str, _QtListModel]:
return {room_id: l.qt_model for room_id, l in self.messages.items()}
@pyqtSlot(str, str, str)
def sendMessage(self, sender_id: str, room_id: str, markdown: str) -> None:
self.localEcho(sender_id, room_id, markdown)
self.sendToServer(sender_id, room_id, markdown)
def localEcho(self, sender_id: str, room_id: str, html: str) -> None:
self.messages[room_id].append(Message(
sender_id, QDateTime.currentDateTime(), html,
))
def sendToServer(self, sender_id: str, room_id: str, html: str) -> None:
pass
@pyqtSlot(str, result="QVariantMap")
def getUser(self, user_id: str) -> Dict[str, Any]:
for user in self.accounts:
if user.user_id == user_id:
return user._asdict()
try:
return self._known_users[user_id]._asdict()
except KeyError:
name = user_id.lstrip("@").split(":")[0].capitalize()
user = User(user_id, name)
self._known_users[user_id] = user
return user._asdict()
@pyqtSlot(str, result=float)
def hueFromString(self, string: str) -> float:
# pylint: disable=no-self-use
md5 = hashlib.md5(bytes(string, "utf-8")).hexdigest()
return float("0.%s" % int(md5[-10:], 16))
@pyqtSlot(str, str)
def setStatusMessage(self, user_id: str, to: str) -> None:
for user in self.accounts:
if user.user_id == user_id:
user.status_message = to
break
else:
raise ValueError(f"{user_id} not found in Backend.accounts")