Overhaul room list sorting

This commit is contained in:
miruka 2019-04-21 20:55:24 -04:00
parent 424405e3e8
commit 237d750d47
8 changed files with 112 additions and 36 deletions

View File

@ -1,6 +1,6 @@
- Current focus - Current focus
- Separate categories for invited, group and direct rooms - When clicking on invited room but no multiaccount broadcasting events
- Invited → Accept/Deny dialog - Sort accounts
- Merge login page - Merge login page
- Refactoring - Refactoring

View File

@ -8,6 +8,7 @@ from typing import Dict, Sequence, Set
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSlot from PyQt5.QtCore import QObject, pyqtProperty, pyqtSlot
from .html_filter import HtmlFilter from .html_filter import HtmlFilter
from .model.items import RoomEvent
from .model.qml_models import QMLModels from .model.qml_models import QMLModels
from .pyqt_future import futurize from .pyqt_future import futurize
@ -113,3 +114,22 @@ class Backend(QObject):
from PyQt5.QtCore import pyqtRemoveInputHook from PyQt5.QtCore import pyqtRemoveInputHook
pyqtRemoveInputHook() pyqtRemoveInputHook()
pdb.set_trace() pdb.set_trace()
@pyqtSlot("QVariant", str, result=bool)
def EventIsOurProfileChanged(self, event: RoomEvent, account_id) -> bool:
# pylint: disable=unused-self
info = event.dict.get("content")
previous = event.dict.get("prev_content")
return (
event.type == "RoomMemberEvent" and
event.dict["sender"] == account_id and
bool(info) and
bool(previous) and
info["membership"] == previous["membership"] and
(
info.get("displayname") != previous.get("displayname") or
info.get("avatar_url") != previous.get("avatar_url")
)
)

View File

@ -48,6 +48,10 @@ class ListModel(QAbstractListModel):
return self.rowCount() return self.rowCount()
def __iter__(self):
return iter(self._data)
@pyqtProperty(list) @pyqtProperty(list)
def roles(self) -> Tuple[str, ...]: def roles(self) -> Tuple[str, ...]:
return self._data[0].roles if self._data else () # type: ignore return self._data[0].roles if self._data else () # type: ignore
@ -205,7 +209,7 @@ class ListModel(QAbstractListModel):
valid = self.beginMoveRows(qidx, from_, qlast, qidx, qto) valid = self.beginMoveRows(qidx, from_, qlast, qidx, qto)
if not valid: if not valid:
logging.warning("Invalid move operation") logging.warning("Invalid move operation - %r", locals())
return return
last = from_ + n last = from_ + n

View File

@ -2,7 +2,7 @@
# This file is part of harmonyqml, licensed under GPLv3. # This file is part of harmonyqml, licensed under GPLv3.
from threading import Lock from threading import Lock
from typing import Any, Deque, Dict, List, Optional from typing import Any, Deque, Dict, List, Optional, Sequence
from PyQt5.QtCore import QDateTime, QObject, pyqtBoundSignal from PyQt5.QtCore import QDateTime, QObject, pyqtBoundSignal
@ -18,7 +18,7 @@ LeftEvent = Optional[Dict[str, str]]
class SignalManager(QObject): class SignalManager(QObject):
_event_handling_lock: Lock = Lock() _lock: Lock = Lock()
def __init__(self, backend: Backend) -> None: def __init__(self, backend: Backend) -> None:
super().__init__(parent=backend) super().__init__(parent=backend)
@ -79,6 +79,43 @@ class SignalManager(QObject):
left_event=left_event) left_event=left_event)
def _move_room(self, account_id: str, room_id: str) -> None:
def get_newest_event_date_time(room_id: str) -> QDateTime:
for ev in self.backend.models.roomEvents[room_id]:
if not self.backend.EventIsOurProfileChanged(ev, account_id):
return ev.dateTime
return QDateTime.fromMSecsSinceEpoch(0)
rooms_model = self.backend.models.rooms[account_id]
room_index = rooms_model.indexWhere("roomId", room_id)
category = rooms_model[room_index].category
timestamp = get_newest_event_date_time(room_id)
def get_index(put_before_categories: Sequence[str],
put_after_categories: Sequence[str]) -> int:
for i, room in enumerate(rooms_model):
if room.category not in put_after_categories and \
(room.category in put_before_categories or
timestamp >= get_newest_event_date_time(room.roomId)):
return i
return len(rooms_model) - 1
to = 0
if category == "Invites":
to = get_index(["Rooms", "Left"], [])
if category == "Rooms":
to = get_index(["Left"], ["Invites"])
elif category == "Left":
to = get_index([], ["Invites", "Rooms", "Left"])
rooms_model.move(room_index, to)
def _add_room(self, def _add_room(self,
client: Client, client: Client,
room_id: str, room_id: str,
@ -115,27 +152,23 @@ class SignalManager(QObject):
) )
model.updateOrAppendWhere("roomId", room_id, item) model.updateOrAppendWhere("roomId", room_id, item)
index = model.indexWhere("roomId", room_id) with self._lock:
self._move_room(client.userId, room_id)
if category == "Invites":
model.move(index, 0)
elif category == "Left":
model.move(index, len(model))
def onRoomSyncPrevBatchTokenReceived(self,
def onRoomSyncPrevBatchTokenReceived( _: Client,
self, _: Client, room_id: str, token: str room_id: str,
) -> None: token: str) -> None:
if room_id not in self.backend.past_tokens: if room_id not in self.backend.past_tokens:
self.backend.past_tokens[room_id] = token self.backend.past_tokens[room_id] = token
def onRoomPastPrevBatchTokenReceived( def onRoomPastPrevBatchTokenReceived(self,
self, _: Client, room_id: str, token: str _: Client,
) -> None: room_id: str,
token: str) -> None:
if self.backend.past_tokens[room_id] == token: if self.backend.past_tokens[room_id] == token:
self.backend.fully_loaded_rooms.add(room_id) self.backend.fully_loaded_rooms.add(room_id)
@ -143,11 +176,12 @@ class SignalManager(QObject):
self.backend.past_tokens[room_id] = token self.backend.past_tokens[room_id] = token
def onRoomEventReceived( def onRoomEventReceived(self,
self, _: Client, room_id: str, etype: str, edict: Dict[str, Any] client: Client,
) -> None: room_id: str,
etype: str,
with self._event_handling_lock: edict: Dict[str, Any]) -> None:
def process() -> None:
# Prevent duplicate events in models due to multiple accounts # Prevent duplicate events in models due to multiple accounts
if edict["event_id"] in self.last_room_events: if edict["event_id"] in self.last_room_events:
return return
@ -195,19 +229,26 @@ class SignalManager(QObject):
model.append(new_event) model.append(new_event)
with self._lock:
process()
self._move_room(client.userId, room_id)
def onRoomTypingUsersUpdated(
self, client: Client, room_id: str, users: List[str] def onRoomTypingUsersUpdated(self,
) -> None: client: Client,
room_id: str,
users: List[str]) -> None:
rooms = self.backend.models.rooms[client.userId] rooms = self.backend.models.rooms[client.userId]
rooms[rooms.indexWhere("roomId", room_id)].typingUsers = users rooms[rooms.indexWhere("roomId", room_id)].typingUsers = users
def onMessageAboutToBeSent( def onMessageAboutToBeSent(self,
self, client: Client, room_id: str, content: Dict[str, str] client: Client,
) -> None: room_id: str,
with self._event_handling_lock: content: Dict[str, str]) -> None:
with self._lock:
timestamp = QDateTime.currentMSecsSinceEpoch() timestamp = QDateTime.currentMSecsSinceEpoch()
model = self.backend.models.roomEvents[room_id] model = self.backend.models.roomEvents[room_id]
nio_event = nio.events.RoomMessage.parse_event({ nio_event = nio.events.RoomMessage.parse_event({
@ -224,3 +265,5 @@ class SignalManager(QObject):
) )
model.insert(0, event) model.insert(0, event)
self._events_in_transfer += 1 self._events_in_transfer += 1
self._move_room(client.userId, room_id)

View File

@ -2,12 +2,19 @@ import QtQuick 2.7
import "../base" as Base import "../base" as Base
Base.HLabel { Base.HLabel {
property bool isToday: {
const today = new Date()
return dateTime.getDate() == today.getDate() &&
dateTime.getMonth() == today.getMonth() &&
dateTime.getFullYear() == today.getFullYear()
}
width: messageDelegate.width width: messageDelegate.width
topPadding: messageDelegate.isFirstMessage ? topPadding: messageDelegate.isFirstMessage ?
0 : messageDelegate.standardSpacing 0 : messageDelegate.standardSpacing
bottomPadding: messageDelegate.standardSpacing bottomPadding: messageDelegate.standardSpacing
text: dateTime.toLocaleDateString() text: dateTime.toLocaleDateString() + (isToday ? qsTr(" (Today)") : "")
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
font.pixelSize: normalSize * 1.1 font.pixelSize: normalSize * 1.1
color: "darkolivegreen" color: "darkolivegreen"

View File

@ -46,7 +46,7 @@ Column {
readonly property bool dayBreak: readonly property bool dayBreak:
isFirstEvent || isFirstEvent ||
previousItem && previousItem &&
dateTime.getDay() != previousItem.dateTime.getDay() dateTime.getDate() != previousItem.dateTime.getDate()
readonly property bool talkBreak: readonly property bool talkBreak:
previousItem && previousItem &&

View File

@ -37,7 +37,9 @@ MouseArea {
} }
Base.HLabel { Base.HLabel {
function getText() { function getText() {
return SidePaneJS.getLastRoomEventText(roomId) return SidePaneJS.getLastRoomEventText(
roomId, roomList.forUserId
)
} }
Connections { Connections {

View File

@ -1,13 +1,13 @@
.import "../chat/utils.js" as ChatJS .import "../chat/utils.js" as ChatJS
function getLastRoomEventText(roomId) { function getLastRoomEventText(roomId, accountId) {
var eventsModel = Backend.models.roomEvents.get(roomId) var eventsModel = Backend.models.roomEvents.get(roomId)
for (var i = 0; i < eventsModel.count; i++) { for (var i = 0; i < eventsModel.count; i++) {
var ev = eventsModel.get(i) var ev = eventsModel.get(i)
if (ev.type !== "RoomMemberEvent") { if (! Backend.EventIsOurProfileChanged(ev, accountId)) {
var found = true var found = true
break break
} }