From 4c4603691f96bd2924feca658528ffd493142017 Mon Sep 17 00:00:00 2001 From: miruka Date: Fri, 5 Jul 2019 19:54:16 -0400 Subject: [PATCH] Working typing users bar --- harmonyqml.pro | 2 ++ src/python/events/rooms.py | 13 +++++---- src/python/matrix_client.py | 20 +++++++++----- src/qml/Chat/Chat.qml | 2 +- src/qml/Chat/TypingMembersBar.qml | 8 ++---- src/qml/Chat/utils.js | 18 ------------ src/qml/EventHandlers/rooms.js | 46 ++++++++++++++++++++++++------- src/qml/utils.js | 14 ++++++++++ 8 files changed, 75 insertions(+), 48 deletions(-) diff --git a/harmonyqml.pro b/harmonyqml.pro index da92b789..8331a070 100644 --- a/harmonyqml.pro +++ b/harmonyqml.pro @@ -3,7 +3,9 @@ QT = quick DEFINES += QT_DEPRECATED_WARNINGS CONFIG += warn_off c++11 release dev { + CONFIG -= warn_off release CONFIG += debug + message($$CONFIG) } BUILD_DIR = build diff --git a/src/python/events/rooms.py b/src/python/events/rooms.py index 25e34566..b78d3c42 100644 --- a/src/python/events/rooms.py +++ b/src/python/events/rooms.py @@ -11,12 +11,13 @@ from .event import AutoStrEnum, Event @dataclass class RoomUpdated(Event): - user_id: str = field() - category: str = field() - room_id: str = field() - display_name: str = "" - avatar_url: str = "" - topic: str = "" + user_id: str = field() + category: str = field() + room_id: str = field() + display_name: str = "" + avatar_url: str = "" + topic: str = "" + typing_members: Sequence[str] = () inviter_id: str = "" left_event: Dict[str, str] = field(default_factory=dict) diff --git a/src/python/matrix_client.py b/src/python/matrix_client.py index 9479fb20..ea4aed80 100644 --- a/src/python/matrix_client.py +++ b/src/python/matrix_client.py @@ -7,7 +7,7 @@ import platform from contextlib import suppress from datetime import datetime from types import ModuleType -from typing import DefaultDict, Dict, Optional, Type +from typing import DefaultDict, Dict, List, Optional, Type from uuid import uuid4 import nio @@ -216,13 +216,19 @@ class MatrixClient(nio.AsyncClient): if room_id not in self.backend.past_tokens: self.backend.past_tokens[room_id] = info.timeline.prev_batch + typing: List[str] = [] + for ev in info.ephemeral: + if isinstance(ev, nio.TypingNoticeEvent): + typing = ev.users + rooms.RoomUpdated( - user_id = self.user_id, - category = "Rooms", - room_id = room_id, - display_name = self._get_room_name(room) or "", - avatar_url = room.gen_avatar_url or "", - topic = room.topic or "", + user_id = self.user_id, + category = "Rooms", + room_id = room_id, + display_name = self._get_room_name(room) or "", + avatar_url = room.gen_avatar_url or "", + topic = room.topic or "", + typing_members = typing, ) for room_id, _ in resp.rooms.leave.items(): diff --git a/src/qml/Chat/Chat.qml b/src/qml/Chat/Chat.qml index 70182704..b91ce81e 100644 --- a/src/qml/Chat/Chat.qml +++ b/src/qml/Chat/Chat.qml @@ -55,7 +55,7 @@ HColumnLayout { Layout.fillHeight: true } - //TypingMembersBar {} + TypingMembersBar {} InviteBanner { visible: category === "Invites" diff --git a/src/qml/Chat/TypingMembersBar.qml b/src/qml/Chat/TypingMembersBar.qml index 0283d4e4..5046dd30 100644 --- a/src/qml/Chat/TypingMembersBar.qml +++ b/src/qml/Chat/TypingMembersBar.qml @@ -1,22 +1,18 @@ import QtQuick 2.7 import QtQuick.Layouts 1.3 import "../Base" -import "utils.js" as ChatJS HRectangle { - property var typingMembers: chatPage.roomInfo.typingMembers - color: HStyle.chat.typingMembers.background Layout.fillWidth: true - Layout.minimumHeight: usersLabel.text ? usersLabel.implicitHeight : 0 - Layout.maximumHeight: Layout.minimumHeight + Layout.preferredHeight: usersLabel.text ? usersLabel.implicitHeight : 0 HLabel { id: usersLabel anchors.fill: parent - text: ChatJS.getTypingMembersText(typingMembers, chatPage.userId) + text: chatPage.roomInfo.typingText elide: Text.ElideMiddle maximumLineCount: 1 } diff --git a/src/qml/Chat/utils.js b/src/qml/Chat/utils.js index 8999f83c..17059c3d 100644 --- a/src/qml/Chat/utils.js +++ b/src/qml/Chat/utils.js @@ -39,21 +39,3 @@ function getLeftBannerAvatarName(leftEvent, accountId) { return Backend.users.get(leftEvent.sender).displayName.value } - - -function getTypingMembersText(users, ourAccountId) { - var names = [] - - for (var i = 0; i < users.length; i++) { - if (users[i] !== ourAccountId) { - names.push(Backend.users.get(users[i]).displayName.value) - } - } - - 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…" -} diff --git a/src/qml/EventHandlers/rooms.js b/src/qml/EventHandlers/rooms.js index 913fc569..258744c8 100644 --- a/src/qml/EventHandlers/rooms.js +++ b/src/qml/EventHandlers/rooms.js @@ -1,6 +1,27 @@ -function onRoomUpdated(user_id, category, room_id, display_name, avatar_url, - topic, inviter_id, left_event) { +function typingTextFor(members, our_user_id) { + var names = [] + for (var i = 0; i < members.length; i++) { + if (members[i] != our_user_id) { + names.push(users.getUser(members[i]).displayName) + } + } + + if (names.length == 0) { return "" } + if (names.length == 1) { return qsTr("%1 is typing...").arg(names[0]) } + + var text = qsTr("%1 and %2 are typing...") + + if (names.length == 2) { return text.arg(names[0]).arg(names[1]) } + + return text.arg(names.slice(0, -1).join(", ")).arg(names.slice(-1)[0]) +} + + +function onRoomUpdated( + user_id, category, room_id, display_name, avatar_url, topic, + typing_members, inviter_id, left_event +) { roomCategories.upsert({"userId": user_id, "name": category}, { "userId": user_id, "name": category @@ -31,14 +52,15 @@ function onRoomUpdated(user_id, category, room_id, display_name, avatar_url, } rooms.upsert(roles(category), { - "userId": user_id, - "category": category, - "roomId": room_id, - "displayName": display_name, - "avatarUrl": avatar_url, - "topic": topic, - "inviterId": inviter_id, - "leftEvent": left_event + "userId": user_id, + "category": category, + "roomId": room_id, + "displayName": display_name, + "avatarUrl": avatar_url, + "topic": topic, + "typingText": typingTextFor(typing_members, user_id), + "inviterId": inviter_id, + "leftEvent": left_event, }) } @@ -98,3 +120,7 @@ function onTimelineEventReceived( var onTimelineMessageReceived = onTimelineEventReceived + + +function onTypingNoticeEvent(room_id, members) { +} diff --git a/src/qml/utils.js b/src/qml/utils.js index c9a8156c..8f4b4240 100644 --- a/src/qml/utils.js +++ b/src/qml/utils.js @@ -1,3 +1,17 @@ +function arrayToModelItem(keys_name, array) { + // Convert an array to an object suitable to be in a model, example: + // [1, 2, 3] → [{keys_name: 1}, {keys_name: 2}, {keys_name: 3}] + var items = [] + + for (var i = 0; i < array.length; i++) { + var obj = {} + obj[keys_name] = array[i] + items.push(obj) + } + return items +} + + function stripUserId(user_id) { // Remove leading @ return user_id.substring(1)