From 6ab4acdc84eebf9f8733716132f2a8d3c706fcbf Mon Sep 17 00:00:00 2001 From: miruka Date: Wed, 17 Apr 2019 22:34:22 -0400 Subject: [PATCH] Improve room past events loading - Trigger when room is shown if there's not enough messages to fill the list height - Trigger whenever user is scrolling before a certain point, instead of when dragging is released/scrolling stopped and the top edge is hit - Prevent multiple load requests at same time - Keep a set of fully loaded rooms, don't request anymore history if a room is fully loaded --- TODO.md | 4 ++++ harmonyqml/backend/backend.py | 17 ++++++++++++----- harmonyqml/backend/client.py | 14 ++++++++++++-- harmonyqml/backend/signal_manager.py | 3 +++ harmonyqml/components/chat/MessageList.qml | 10 ++++++++-- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/TODO.md b/TODO.md index 6428bfa2..5542e75b 100644 --- a/TODO.md +++ b/TODO.md @@ -30,3 +30,7 @@ - Push instead of replacing in stack view - QQuickImageProvider, matrix preview API + +- Spinner when loading past room events or images + +- nio: org.matrix.room.preview\_urls, m.room.aliases diff --git a/harmonyqml/backend/backend.py b/harmonyqml/backend/backend.py index 3398f7be..6ff370b0 100644 --- a/harmonyqml/backend/backend.py +++ b/harmonyqml/backend/backend.py @@ -2,20 +2,21 @@ # This file is part of harmonyqml, licensed under GPLv3. import hashlib -from typing import Dict +from typing import Dict, Set from PyQt5.QtCore import QObject, pyqtProperty, pyqtSlot from .client_manager import ClientManager +from .html_filter import HtmlFilter from .model.items import User from .model.qml_models import QMLModels -from .html_filter import HtmlFilter class Backend(QObject): def __init__(self) -> None: super().__init__() - self.past_tokens: Dict[str, str] = {} + self.past_tokens: Dict[str, str] = {} + self.fully_loaded_rooms: Set[str] = set() self._client_manager: ClientManager = ClientManager() self._models: QMLModels = QMLModels() @@ -61,13 +62,19 @@ class Backend(QObject): @pyqtSlot(str) - def loadPastEvents(self, room_id: str) -> None: + @pyqtSlot(str, int) + def loadPastEvents(self, room_id: str, limit: int = 100) -> None: if not room_id in self.past_tokens: return # Initial sync not done yet + if room_id in self.fully_loaded_rooms: + return + for client in self.clientManager.clients.values(): if room_id in client.nio.rooms: - client.loadPastEvents(room_id, self.past_tokens[room_id]) + client.loadPastEvents( + room_id, self.past_tokens[room_id], limit + ) break else: raise ValueError(f"Room not found in any client: {room_id}") diff --git a/harmonyqml/backend/client.py b/harmonyqml/backend/client.py index 6ae81db5..6c71fbb2 100644 --- a/harmonyqml/backend/client.py +++ b/harmonyqml/backend/client.py @@ -69,6 +69,8 @@ class Client(QObject): self.net = NetworkManager(self.host, self.port, self.nio) self.net_sync = NetworkManager(self.host, self.port, self.nio_sync) + self._loading: bool = False + self._stop_sync: Event = Event() @@ -157,14 +159,22 @@ class Client(QObject): @futurize - def loadPastEvents(self, room_id: str, start_token: str) -> None: + def loadPastEvents(self, room_id: str, start_token: str, limit: int = 100 + ) -> None: # From QML, use Backend.loastPastEvents instead + + if self._loading: + return + self._loading = True + + print("load", limit) self._on_past_events( room_id, self.net.talk( - self.nio.room_messages, room_id, start=start_token, limit=100 + self.nio.room_messages, room_id, start=start_token, limit=limit ) ) + self._loading = False def _on_past_events(self, room_id: str, response: nr.RoomMessagesResponse diff --git a/harmonyqml/backend/signal_manager.py b/harmonyqml/backend/signal_manager.py index c79b7b89..54c44ab6 100644 --- a/harmonyqml/backend/signal_manager.py +++ b/harmonyqml/backend/signal_manager.py @@ -93,6 +93,9 @@ class SignalManager(QObject): self, _: Client, room_id: str, token: str ) -> None: + if self.backend.past_tokens[room_id] == token: + self.backend.fully_loaded_rooms.add(room_id) + self.backend.past_tokens[room_id] = token diff --git a/harmonyqml/components/chat/MessageList.qml b/harmonyqml/components/chat/MessageList.qml index 29081f63..3228da07 100644 --- a/harmonyqml/components/chat/MessageList.qml +++ b/harmonyqml/components/chat/MessageList.qml @@ -26,8 +26,14 @@ Rectangle { // reloaded from network. cacheBuffer: height * 6 - onMovementEnded: if (atYBeginning) { - Backend.loadPastEvents(chatPage.room.room_id) + // Declaring this "alias" provides the on... signal + property real yPos: visibleArea.yPosition + + onYPosChanged: { + console.log(yPos) + if (yPos <= 0.1) { + Backend.loadPastEvents(chatPage.room.room_id) + } } } }