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
This commit is contained in:
miruka 2019-04-17 22:34:22 -04:00
parent a0f9acddaa
commit 6ab4acdc84
5 changed files with 39 additions and 9 deletions

View File

@ -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

View File

@ -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.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}")

View File

@ -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

View File

@ -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

View File

@ -26,8 +26,14 @@ Rectangle {
// reloaded from network.
cacheBuffer: height * 6
onMovementEnded: if (atYBeginning) {
// 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)
}
}
}
}