Rework models hierarchy, room categories models
This commit is contained in:
parent
ada44cf6f7
commit
047225fded
4
TODO.md
4
TODO.md
@ -3,16 +3,18 @@
|
|||||||
- Don't bake in size properties for components
|
- Don't bake in size properties for components
|
||||||
|
|
||||||
- Bug fixes
|
- Bug fixes
|
||||||
|
- Sendbox
|
||||||
- 100% CPU usage when hitting top edge to trigger messages loading
|
- 100% CPU usage when hitting top edge to trigger messages loading
|
||||||
- Sending `` → not clickable?
|
- Sending `` → not clickable?
|
||||||
- Icons and images aren't reloaded
|
- Icons and images aren't reloaded
|
||||||
- HStyle singleton isn't reloaded
|
- HStyle singleton isn't reloaded
|
||||||
- `MessageDelegate.qml:63: TypeError: 'reloadPreviousItem' not a function`
|
- `MessageDelegate.qml:63: TypeError: 'reloadPreviousItem' not a function`
|
||||||
- Bug when resizing window being tiled (i3), can't figure it out
|
- Bug when resizing window being tiled (i3), can't figure it out
|
||||||
|
- Can scroll the SidePane rooms too far
|
||||||
|
|
||||||
- UI
|
- UI
|
||||||
- Use nested listview for categories instead of section property
|
|
||||||
- Improve SidePane appearance when at min width
|
- Improve SidePane appearance when at min width
|
||||||
|
- Accounts delegates background
|
||||||
- Server selection
|
- Server selection
|
||||||
- Register/Forgot? for SignIn dialog
|
- Register/Forgot? for SignIn dialog
|
||||||
- Scaling
|
- Scaling
|
||||||
|
@ -110,22 +110,3 @@ 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")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
@ -89,7 +89,6 @@ class ClientManager(QObject):
|
|||||||
def deleteAll(self) -> None:
|
def deleteAll(self) -> None:
|
||||||
for user_id in self.clients.copy():
|
for user_id in self.clients.copy():
|
||||||
self.delete(user_id)
|
self.delete(user_id)
|
||||||
print("deleted", user_id, self.clients)
|
|
||||||
|
|
||||||
|
|
||||||
@pyqtProperty(str, constant=True)
|
@pyqtProperty(str, constant=True)
|
||||||
|
@ -3,29 +3,7 @@ from typing import Any, Dict, List, Optional
|
|||||||
from PyQt5.QtCore import QDateTime
|
from PyQt5.QtCore import QDateTime
|
||||||
|
|
||||||
from .list_item import ListItem
|
from .list_item import ListItem
|
||||||
|
from .list_model import ListModel
|
||||||
|
|
||||||
class User(ListItem):
|
|
||||||
_required_init_values = {"userId"}
|
|
||||||
_constant = {"userId"}
|
|
||||||
|
|
||||||
userId: str = ""
|
|
||||||
displayName: Optional[str] = None
|
|
||||||
avatarUrl: Optional[str] = None
|
|
||||||
statusMessage: Optional[str] = None
|
|
||||||
|
|
||||||
|
|
||||||
class Room(ListItem):
|
|
||||||
_required_init_values = {"roomId", "displayName"}
|
|
||||||
_constant = {"roomId"}
|
|
||||||
|
|
||||||
roomId: str = ""
|
|
||||||
displayName: str = ""
|
|
||||||
category: str = "Rooms"
|
|
||||||
topic: Optional[str] = None
|
|
||||||
typingUsers: List[str] = []
|
|
||||||
inviter: Optional[Dict[str, str]] = None
|
|
||||||
leftEvent: Optional[Dict[str, str]] = None
|
|
||||||
|
|
||||||
|
|
||||||
class RoomEvent(ListItem):
|
class RoomEvent(ListItem):
|
||||||
@ -36,3 +14,38 @@ class RoomEvent(ListItem):
|
|||||||
dict: Dict[str, Any] = {}
|
dict: Dict[str, Any] = {}
|
||||||
dateTime: QDateTime = QDateTime.currentDateTime()
|
dateTime: QDateTime = QDateTime.currentDateTime()
|
||||||
isLocalEcho: bool = False
|
isLocalEcho: bool = False
|
||||||
|
|
||||||
|
|
||||||
|
class Room(ListItem):
|
||||||
|
_required_init_values = {"roomId", "displayName"}
|
||||||
|
_constant = {"roomId"}
|
||||||
|
|
||||||
|
roomId: str = ""
|
||||||
|
displayName: str = ""
|
||||||
|
topic: Optional[str] = None
|
||||||
|
typingUsers: List[str] = []
|
||||||
|
|
||||||
|
inviter: Optional[Dict[str, str]] = None
|
||||||
|
leftEvent: Optional[Dict[str, str]] = None
|
||||||
|
|
||||||
|
|
||||||
|
class RoomCategory(ListItem):
|
||||||
|
_required_init_values = {"name", "rooms"}
|
||||||
|
_constant = {"rooms"}
|
||||||
|
|
||||||
|
name: str = ""
|
||||||
|
|
||||||
|
# Must be provided at init, else it will be the same object
|
||||||
|
# for every RoomCategory
|
||||||
|
rooms: ListModel = ListModel()
|
||||||
|
|
||||||
|
|
||||||
|
class Account(ListItem):
|
||||||
|
_required_init_values = {"userId", "roomCategories"}
|
||||||
|
_constant = {"userId", "roomCategories"}
|
||||||
|
|
||||||
|
userId: str = ""
|
||||||
|
roomCategories: ListModel = ListModel() # same as RoomCategory.rooms
|
||||||
|
displayName: Optional[str] = None
|
||||||
|
avatarUrl: Optional[str] = None
|
||||||
|
statusMessage: Optional[str] = None
|
||||||
|
@ -15,15 +15,23 @@ Index = Union[int, str]
|
|||||||
NewItem = Union[ListItem, Mapping[str, Any], Sequence]
|
NewItem = Union[ListItem, Mapping[str, Any], Sequence]
|
||||||
|
|
||||||
|
|
||||||
|
class _GetFail:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class _PopFail:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ListModel(QAbstractListModel):
|
class ListModel(QAbstractListModel):
|
||||||
rolesSet = pyqtSignal()
|
rolesSet = pyqtSignal()
|
||||||
changed = pyqtSignal()
|
changed = pyqtSignal()
|
||||||
countChanged = pyqtSignal(int)
|
countChanged = pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
parent: QObject,
|
|
||||||
initial_data: Optional[List[NewItem]] = None,
|
initial_data: Optional[List[NewItem]] = None,
|
||||||
container: Callable[..., MutableSequence] = list) -> None:
|
container: Callable[..., MutableSequence] = list,
|
||||||
|
parent: QObject = None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._data: MutableSequence[ListItem] = container()
|
self._data: MutableSequence[ListItem] = container()
|
||||||
|
|
||||||
@ -135,11 +143,19 @@ class ListModel(QAbstractListModel):
|
|||||||
|
|
||||||
@pyqtSlot(int, result="QVariant")
|
@pyqtSlot(int, result="QVariant")
|
||||||
@pyqtSlot(str, result="QVariant")
|
@pyqtSlot(str, result="QVariant")
|
||||||
def get(self, index: Index) -> ListItem:
|
@pyqtSlot(int, "QVariant", result="QVariant")
|
||||||
if isinstance(index, str):
|
@pyqtSlot(str, "QVariant", result="QVariant")
|
||||||
index = self.indexWhere(self.mainKey, index)
|
def get(self, index: Index, default: Any = _GetFail()) -> ListItem:
|
||||||
|
try:
|
||||||
|
i_index: int = self.indexWhere(self.mainKey, index) \
|
||||||
|
if isinstance(index, str) else index
|
||||||
|
|
||||||
return self._data[index] # type: ignore
|
return self._data[i_index]
|
||||||
|
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
if isinstance(default, _GetFail):
|
||||||
|
raise
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(int, "QVariantMap")
|
@pyqtSlot(int, "QVariantMap")
|
||||||
@ -170,20 +186,20 @@ class ListModel(QAbstractListModel):
|
|||||||
self.append(val)
|
self.append(val)
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(int, "QVariantMap")
|
@pyqtSlot(int, "QVariantMap", result=int)
|
||||||
@pyqtSlot(int, "QVariantMap", "QStringList")
|
@pyqtSlot(int, "QVariantMap", "QStringList", result=int)
|
||||||
@pyqtSlot(str, "QVariantMap")
|
@pyqtSlot(str, "QVariantMap", result=int)
|
||||||
@pyqtSlot(str, "QVariantMap", "QStringList")
|
@pyqtSlot(str, "QVariantMap", "QStringList", result=int)
|
||||||
def update(self,
|
def update(self,
|
||||||
index: Index,
|
index: Index,
|
||||||
value: NewItem,
|
value: NewItem,
|
||||||
ignore_roles: Sequence[str] = ()) -> None:
|
ignore_roles: Sequence[str] = ()) -> int:
|
||||||
value = self._convert_new_value(value)
|
value = self._convert_new_value(value)
|
||||||
|
|
||||||
if isinstance(index, str):
|
i_index: int = self.indexWhere(self.mainKey, index) \
|
||||||
index = self.indexWhere(self.mainKey or value.mainKey, index)
|
if isinstance(index, str) else index
|
||||||
|
|
||||||
to_update = self._data[index] # type: ignore
|
to_update = self[i_index]
|
||||||
|
|
||||||
for role in self.roles:
|
for role in self.roles:
|
||||||
if role not in ignore_roles:
|
if role not in ignore_roles:
|
||||||
@ -192,35 +208,40 @@ class ListModel(QAbstractListModel):
|
|||||||
except AttributeError: # constant/not settable
|
except AttributeError: # constant/not settable
|
||||||
pass
|
pass
|
||||||
|
|
||||||
qidx = QAbstractListModel.index(self, index, 0)
|
qidx = QAbstractListModel.index(self, i_index, 0)
|
||||||
self.dataChanged.emit(qidx, qidx, self.roleNames())
|
self.dataChanged.emit(qidx, qidx, self.roleNames())
|
||||||
self.changed.emit()
|
self.changed.emit()
|
||||||
|
return i_index
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(str, "QVariantMap")
|
@pyqtSlot(str, "QVariantMap")
|
||||||
@pyqtSlot(str, "QVariantMap", int)
|
@pyqtSlot(str, "QVariantMap", int)
|
||||||
@pyqtSlot(str, "QVariantMap", int, "QStringList")
|
@pyqtSlot(str, "QVariantMap", int, int)
|
||||||
|
@pyqtSlot(str, "QVariantMap", int, int, "QStringList")
|
||||||
def upsert(self,
|
def upsert(self,
|
||||||
where_main_key_is_value: Any,
|
where_main_key_is: Any,
|
||||||
update_with: NewItem,
|
update_with: NewItem,
|
||||||
index_if_insert: Optional[int] = None,
|
new_index_if_insert: Optional[int] = None,
|
||||||
ignore_roles: Sequence[str] = ()) -> None:
|
new_index_if_update: Optional[int] = None,
|
||||||
|
ignore_roles: Sequence[str] = ()) -> None:
|
||||||
try:
|
try:
|
||||||
self.update(where_main_key_is_value, update_with, ignore_roles)
|
index = self.update(where_main_key_is, update_with, ignore_roles)
|
||||||
except (IndexError, ValueError):
|
except (IndexError, ValueError):
|
||||||
self.insert(index_if_insert or len(self), update_with)
|
self.insert(new_index_if_insert or len(self), update_with)
|
||||||
|
else:
|
||||||
|
if new_index_if_update:
|
||||||
|
self.move(index, new_index_if_update)
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(int, list)
|
@pyqtSlot(int, list)
|
||||||
@pyqtSlot(str, list)
|
@pyqtSlot(str, list)
|
||||||
def set(self, index: Index, value: NewItem) -> None:
|
def set(self, index: Index, value: NewItem) -> None:
|
||||||
if isinstance(index, str):
|
i_index: int = self.indexWhere(self.mainKey, index) \
|
||||||
index = self.indexWhere(self.mainKey, index)
|
if isinstance(index, str) else index
|
||||||
|
|
||||||
qidx = QAbstractListModel.index(self, index, 0)
|
qidx = QAbstractListModel.index(self, i_index, 0)
|
||||||
value = self._convert_new_value(value)
|
value = self._convert_new_value(value)
|
||||||
self._data[index] = value # type: ignore
|
self._data[i_index] = value
|
||||||
self.dataChanged.emit(qidx, qidx, self.roleNames())
|
self.dataChanged.emit(qidx, qidx, self.roleNames())
|
||||||
self.changed.emit()
|
self.changed.emit()
|
||||||
|
|
||||||
@ -228,11 +249,11 @@ class ListModel(QAbstractListModel):
|
|||||||
@pyqtSlot(int, str, "QVariant")
|
@pyqtSlot(int, str, "QVariant")
|
||||||
@pyqtSlot(str, str, "QVariant")
|
@pyqtSlot(str, str, "QVariant")
|
||||||
def setProperty(self, index: Index, prop: str, value: Any) -> None:
|
def setProperty(self, index: Index, prop: str, value: Any) -> None:
|
||||||
if isinstance(index, str):
|
i_index: int = self.indexWhere(self.mainKey, index) \
|
||||||
index = self.indexWhere(self.mainKey, index)
|
if isinstance(index, str) else index
|
||||||
|
|
||||||
setattr(self._data[index], prop, value) # type: ignore
|
setattr(self[i_index], prop, value)
|
||||||
qidx = QAbstractListModel.index(self, index, 0)
|
qidx = QAbstractListModel.index(self, i_index, 0)
|
||||||
self.dataChanged.emit(qidx, qidx, self.roleNames())
|
self.dataChanged.emit(qidx, qidx, self.roleNames())
|
||||||
self.changed.emit()
|
self.changed.emit()
|
||||||
|
|
||||||
@ -269,17 +290,39 @@ class ListModel(QAbstractListModel):
|
|||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def remove(self, index: Index) -> None:
|
def remove(self, index: Index) -> None:
|
||||||
if isinstance(index, str):
|
i_index: int = self.indexWhere(self.mainKey, index) \
|
||||||
index = self.indexWhere(self.mainKey, index)
|
if isinstance(index, str) else index
|
||||||
|
|
||||||
self.beginRemoveRows(QModelIndex(), index, index)
|
self.beginRemoveRows(QModelIndex(), i_index, i_index)
|
||||||
del self._data[index] # type: ignore
|
del self._data[i_index]
|
||||||
self.endRemoveRows()
|
self.endRemoveRows()
|
||||||
|
|
||||||
self.countChanged.emit(len(self))
|
self.countChanged.emit(len(self))
|
||||||
self.changed.emit()
|
self.changed.emit()
|
||||||
|
|
||||||
|
|
||||||
|
@pyqtSlot(int, result="QVariant")
|
||||||
|
@pyqtSlot(str, result="QVariant")
|
||||||
|
def pop(self, index: Index, default: Any = _PopFail()) -> ListItem:
|
||||||
|
try:
|
||||||
|
i_index: int = self.indexWhere(self.mainKey, index) \
|
||||||
|
if isinstance(index, str) else index
|
||||||
|
item = self[i_index]
|
||||||
|
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
if isinstance(default, _PopFail):
|
||||||
|
raise
|
||||||
|
return default
|
||||||
|
|
||||||
|
self.beginRemoveRows(QModelIndex(), i_index, i_index)
|
||||||
|
del self._data[i_index]
|
||||||
|
self.endRemoveRows()
|
||||||
|
|
||||||
|
self.countChanged.emit(len(self))
|
||||||
|
self.changed.emit()
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def clear(self) -> None:
|
def clear(self) -> None:
|
||||||
# Reimplemented for performance reasons (begin/endRemoveRows)
|
# Reimplemented for performance reasons (begin/endRemoveRows)
|
||||||
|
@ -7,15 +7,15 @@ from .list_model import ListModel
|
|||||||
|
|
||||||
class ListModelMap(QObject):
|
class ListModelMap(QObject):
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
parent: QObject,
|
models_container: Callable[..., MutableSequence] = list,
|
||||||
models_container: Callable[..., MutableSequence] = list
|
parent: QObject = None) -> None:
|
||||||
) -> None:
|
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
# Set the parent to prevent item garbage-collection on the C++ side
|
# Set the parent to prevent item garbage-collection on the C++ side
|
||||||
self.dict: DefaultDict[Any, ListModel] = \
|
self.dict: DefaultDict[Any, ListModel] = \
|
||||||
DefaultDict(lambda: ListModel(parent = self,
|
DefaultDict(
|
||||||
container = models_container))
|
lambda: ListModel(container=models_container, parent=self)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pyqtSlot(str, result="QVariant")
|
@pyqtSlot(str, result="QVariant")
|
||||||
|
@ -12,10 +12,8 @@ from .list_model_map import ListModelMap
|
|||||||
class QMLModels(QObject):
|
class QMLModels(QObject):
|
||||||
def __init__(self, parent: QObject) -> None:
|
def __init__(self, parent: QObject) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self._accounts: ListModel = ListModel(parent)
|
self._accounts: ListModel = ListModel(parent=parent)
|
||||||
self._rooms: ListModelMap = ListModelMap(parent)
|
self._room_events: ListModelMap = ListModelMap(Deque, parent)
|
||||||
self._room_events: ListModelMap = ListModelMap(parent,
|
|
||||||
models_container=Deque)
|
|
||||||
|
|
||||||
|
|
||||||
@pyqtProperty(ListModel, constant=True)
|
@pyqtProperty(ListModel, constant=True)
|
||||||
@ -23,11 +21,6 @@ class QMLModels(QObject):
|
|||||||
return self._accounts
|
return self._accounts
|
||||||
|
|
||||||
|
|
||||||
@pyqtProperty("QVariant", constant=True)
|
|
||||||
def rooms(self):
|
|
||||||
return self._rooms
|
|
||||||
|
|
||||||
|
|
||||||
@pyqtProperty("QVariant", constant=True)
|
@pyqtProperty("QVariant", constant=True)
|
||||||
def roomEvents(self):
|
def roomEvents(self):
|
||||||
return self._room_events
|
return self._room_events
|
||||||
|
@ -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, Sequence
|
from typing import Any, Deque, Dict, List, Optional
|
||||||
|
|
||||||
from PyQt5.QtCore import QDateTime, QObject, pyqtBoundSignal
|
from PyQt5.QtCore import QDateTime, QObject, pyqtBoundSignal
|
||||||
|
|
||||||
@ -11,7 +11,8 @@ from nio.rooms import MatrixRoom
|
|||||||
|
|
||||||
from .backend import Backend
|
from .backend import Backend
|
||||||
from .client import Client
|
from .client import Client
|
||||||
from .model.items import Room, RoomEvent, User
|
from .model.items import Account, Room, RoomCategory, RoomEvent
|
||||||
|
from .model.list_model import ListModel
|
||||||
|
|
||||||
Inviter = Optional[Dict[str, str]]
|
Inviter = Optional[Dict[str, str]]
|
||||||
LeftEvent = Optional[Dict[str, str]]
|
LeftEvent = Optional[Dict[str, str]]
|
||||||
@ -34,8 +35,14 @@ class SignalManager(QObject):
|
|||||||
|
|
||||||
def onClientAdded(self, client: Client) -> None:
|
def onClientAdded(self, client: Client) -> None:
|
||||||
self.connectClient(client)
|
self.connectClient(client)
|
||||||
self.backend.models.accounts.append(User(
|
|
||||||
userId = client.userId,
|
self.backend.models.accounts.append(Account(
|
||||||
|
userId = client.userId,
|
||||||
|
roomCategories = ListModel([
|
||||||
|
RoomCategory("Invites", ListModel()),
|
||||||
|
RoomCategory("Rooms", ListModel()),
|
||||||
|
RoomCategory("Left", ListModel()),
|
||||||
|
]),
|
||||||
displayName = self.backend.getUserDisplayName(client.userId),
|
displayName = self.backend.getUserDisplayName(client.userId),
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -56,104 +63,65 @@ class SignalManager(QObject):
|
|||||||
attr.connect(onSignal)
|
attr.connect(onSignal)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_room_displayname(nio_room: MatrixRoom) -> Optional[str]:
|
||||||
|
name = nio_room.name or nio_room.canonical_alias
|
||||||
|
if name:
|
||||||
|
return name
|
||||||
|
|
||||||
|
name = nio_room.group_name()
|
||||||
|
return None if name == "Empty room?" else name
|
||||||
|
|
||||||
|
|
||||||
def onRoomInvited(self,
|
def onRoomInvited(self,
|
||||||
client: Client,
|
client: Client,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
inviter: Inviter = None) -> None:
|
inviter: Inviter = None) -> None:
|
||||||
|
|
||||||
self._add_room(client, room_id, client.nio.invited_rooms[room_id],
|
nio_room = client.nio.invited_rooms[room_id]
|
||||||
"Invites", inviter=inviter)
|
categories = self.backend.models.accounts[client.userId].roomCategories
|
||||||
|
|
||||||
|
categories["Rooms"].rooms.pop(room_id, None)
|
||||||
|
categories["Left"].rooms.pop(room_id, None)
|
||||||
|
|
||||||
|
categories["Invites"].rooms.upsert(room_id, Room(
|
||||||
|
roomId = room_id,
|
||||||
|
displayName = self._get_room_displayname(nio_room),
|
||||||
|
topic = nio_room.topic,
|
||||||
|
inviter = inviter,
|
||||||
|
), 0, 0)
|
||||||
|
|
||||||
|
|
||||||
def onRoomJoined(self, client: Client, room_id: str) -> None:
|
def onRoomJoined(self, client: Client, room_id: str) -> None:
|
||||||
self._add_room(client, room_id, client.nio.rooms[room_id], "Rooms")
|
nio_room = client.nio.rooms[room_id]
|
||||||
|
categories = self.backend.models.accounts[client.userId].roomCategories
|
||||||
|
|
||||||
|
categories["Invites"].rooms.pop(room_id, None)
|
||||||
|
categories["Left"].rooms.pop(room_id, None)
|
||||||
|
|
||||||
|
categories["Rooms"].rooms.upsert(room_id, Room(
|
||||||
|
roomId = room_id,
|
||||||
|
displayName = self._get_room_displayname(nio_room),
|
||||||
|
topic = nio_room.topic,
|
||||||
|
), 0, 0)
|
||||||
|
|
||||||
|
|
||||||
def onRoomLeft(self,
|
def onRoomLeft(self,
|
||||||
client: Client,
|
client: Client,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
left_event: LeftEvent = None) -> None:
|
left_event: LeftEvent = None) -> None:
|
||||||
|
categories = self.backend.models.accounts[client.userId].roomCategories
|
||||||
|
|
||||||
self._add_room(client, room_id, client.nio.rooms.get(room_id), "Left",
|
previous = categories["Rooms"].rooms.pop(room_id, None)
|
||||||
left_event=left_event)
|
previous = previous or categories["Invites"].rooms.pop(room_id, None)
|
||||||
|
previous = previous or categories["Left"].rooms.get(room_id, None)
|
||||||
|
|
||||||
|
categories["Left"].rooms.upsert(0, Room(
|
||||||
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,
|
|
||||||
client: Client,
|
|
||||||
room_id: str,
|
|
||||||
room: MatrixRoom,
|
|
||||||
category: str = "Rooms",
|
|
||||||
inviter: Inviter = None,
|
|
||||||
left_event: LeftEvent = None) -> None:
|
|
||||||
|
|
||||||
if (inviter and left_event):
|
|
||||||
raise ValueError()
|
|
||||||
|
|
||||||
model = self.backend.models.rooms[client.userId]
|
|
||||||
no_update = []
|
|
||||||
|
|
||||||
def get_displayname() -> Optional[str]:
|
|
||||||
if not room:
|
|
||||||
no_update.append("displayName")
|
|
||||||
return room_id
|
|
||||||
|
|
||||||
name = room.name or room.canonical_alias
|
|
||||||
if name:
|
|
||||||
return name
|
|
||||||
|
|
||||||
name = room.group_name()
|
|
||||||
return None if name == "Empty room?" else name
|
|
||||||
|
|
||||||
item = Room(
|
|
||||||
roomId = room_id,
|
roomId = room_id,
|
||||||
displayName = get_displayname(),
|
displayName = previous.displayName if previous else None,
|
||||||
category = category,
|
topic = previous.topic if previous else None,
|
||||||
topic = room.topic if room else None,
|
|
||||||
inviter = inviter,
|
|
||||||
leftEvent = left_event,
|
leftEvent = left_event,
|
||||||
)
|
), 0, 0)
|
||||||
|
|
||||||
model.upsert(room_id, item, ignore_roles=no_update)
|
|
||||||
with self._lock:
|
|
||||||
self._move_room(client.userId, room_id)
|
|
||||||
|
|
||||||
|
|
||||||
def onRoomSyncPrevBatchTokenReceived(self,
|
def onRoomSyncPrevBatchTokenReceived(self,
|
||||||
_: Client,
|
_: Client,
|
||||||
@ -176,7 +144,7 @@ class SignalManager(QObject):
|
|||||||
|
|
||||||
|
|
||||||
def onRoomEventReceived(self,
|
def onRoomEventReceived(self,
|
||||||
client: Client,
|
_: Client,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
etype: str,
|
etype: str,
|
||||||
edict: Dict[str, Any]) -> None:
|
edict: Dict[str, Any]) -> None:
|
||||||
@ -192,6 +160,16 @@ class SignalManager(QObject):
|
|||||||
.fromMSecsSinceEpoch(edict["server_timestamp"])
|
.fromMSecsSinceEpoch(edict["server_timestamp"])
|
||||||
new_event = RoomEvent(type=etype, dateTime=date_time, dict=edict)
|
new_event = RoomEvent(type=etype, dateTime=date_time, dict=edict)
|
||||||
|
|
||||||
|
event_is_our_profile_changed = (
|
||||||
|
etype == "RoomMemberEvent" and
|
||||||
|
edict.get("sender") in self.backend.clientManager.clients and
|
||||||
|
((edict.get("content") or {}).get("membership") ==
|
||||||
|
(edict.get("prev_content") or {}).get("membership"))
|
||||||
|
)
|
||||||
|
|
||||||
|
if event_is_our_profile_changed:
|
||||||
|
return
|
||||||
|
|
||||||
if etype == "RoomCreateEvent":
|
if etype == "RoomCreateEvent":
|
||||||
self.backend.fully_loaded_rooms.add(room_id)
|
self.backend.fully_loaded_rooms.add(room_id)
|
||||||
|
|
||||||
@ -233,14 +211,20 @@ class SignalManager(QObject):
|
|||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
process()
|
process()
|
||||||
self._move_room(client.userId, room_id)
|
# self._move_room(client.userId, room_id)
|
||||||
|
|
||||||
|
|
||||||
def onRoomTypingUsersUpdated(self,
|
def onRoomTypingUsersUpdated(self,
|
||||||
client: Client,
|
client: Client,
|
||||||
room_id: str,
|
room_id: str,
|
||||||
users: List[str]) -> None:
|
users: List[str]) -> None:
|
||||||
self.backend.models.rooms[client.userId][room_id].typingUsers = users
|
categories = self.backend.models.accounts[client.userId].roomCategories
|
||||||
|
for categ in categories:
|
||||||
|
try:
|
||||||
|
categ.rooms[room_id].typingUsers = users
|
||||||
|
break
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def onMessageAboutToBeSent(self,
|
def onMessageAboutToBeSent(self,
|
||||||
@ -264,10 +248,13 @@ 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)
|
# self._move_room(client.userId, room_id)
|
||||||
|
|
||||||
|
|
||||||
def onRoomAboutToBeForgotten(self, client: Client, room_id: str) -> None:
|
def onRoomAboutToBeForgotten(self, client: Client, room_id: str) -> None:
|
||||||
with self._lock:
|
categories = self.backend.models.accounts[client.userId].roomCategories
|
||||||
del self.backend.models.rooms[client.userId][room_id]
|
|
||||||
self.backend.models.roomEvents[room_id].clear()
|
for categ in categories:
|
||||||
|
categ.rooms.pop(room_id, None)
|
||||||
|
|
||||||
|
self.backend.models.roomEvents[room_id].clear()
|
||||||
|
@ -5,7 +5,7 @@ Rectangle {
|
|||||||
property bool hidden: false
|
property bool hidden: false
|
||||||
property var name: null // null, string or PyQtFuture
|
property var name: null // null, string or PyQtFuture
|
||||||
property var imageSource: null
|
property var imageSource: null
|
||||||
property int dimension: 48
|
property int dimension: 36
|
||||||
|
|
||||||
|
|
||||||
readonly property string resolvedName:
|
readonly property string resolvedName:
|
||||||
|
@ -3,6 +3,7 @@ import QtQuick.Layouts 1.3
|
|||||||
import "../Base"
|
import "../Base"
|
||||||
|
|
||||||
HRowLayout {
|
HRowLayout {
|
||||||
|
property alias label: noticeLabel
|
||||||
property alias text: noticeLabel.text
|
property alias text: noticeLabel.text
|
||||||
property alias color: noticeLabel.color
|
property alias color: noticeLabel.color
|
||||||
property alias font: noticeLabel.font
|
property alias font: noticeLabel.font
|
||||||
@ -19,7 +20,10 @@ HRowLayout {
|
|||||||
|
|
||||||
Layout.margins: 10
|
Layout.margins: 10
|
||||||
Layout.alignment: Qt.AlignCenter
|
Layout.alignment: Qt.AlignCenter
|
||||||
Layout.maximumWidth: parent.width - Layout.margins * 2
|
Layout.maximumWidth:
|
||||||
|
parent.width - Layout.leftMargin - Layout.rightMargin
|
||||||
|
|
||||||
|
opacity: width > Layout.leftMargin + Layout.rightMargin ? 1 : 0
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
id: noticeLabelBackground
|
id: noticeLabelBackground
|
@ -1,14 +1,17 @@
|
|||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
import "../Base"
|
import "../Base"
|
||||||
import "Banners"
|
import "Banners"
|
||||||
import "RoomEventList"
|
import "RoomEventList"
|
||||||
|
|
||||||
HColumnLayout {
|
HColumnLayout {
|
||||||
property string userId: ""
|
property string userId: ""
|
||||||
|
property string category: ""
|
||||||
property string roomId: ""
|
property string roomId: ""
|
||||||
|
|
||||||
readonly property var roomInfo:
|
readonly property var roomInfo:
|
||||||
Backend.models.rooms.get(userId).get(roomId)
|
Backend.models.accounts.get(userId)
|
||||||
|
.roomCategories.get(category).rooms.get(roomId)
|
||||||
|
|
||||||
property bool canLoadPastEvents: true
|
property bool canLoadPastEvents: true
|
||||||
|
|
||||||
@ -20,22 +23,25 @@ HColumnLayout {
|
|||||||
topic: roomInfo.topic || ""
|
topic: roomInfo.topic || ""
|
||||||
}
|
}
|
||||||
|
|
||||||
RoomEventList {}
|
RoomEventList {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
|
||||||
TypingUsersBar {}
|
TypingUsersBar {}
|
||||||
|
|
||||||
InviteBanner {
|
InviteBanner {
|
||||||
visible: roomInfo.category === "Invites"
|
visible: category === "Invites"
|
||||||
inviter: roomInfo.inviter
|
inviter: roomInfo.inviter
|
||||||
}
|
}
|
||||||
|
|
||||||
SendBox {
|
SendBox {
|
||||||
id: sendBox
|
id: sendBox
|
||||||
visible: roomInfo.category === "Rooms"
|
visible: category === "Rooms"
|
||||||
}
|
}
|
||||||
|
|
||||||
LeftBanner {
|
LeftBanner {
|
||||||
visible: roomInfo.category === "Left"
|
visible: category === "Left"
|
||||||
leftEvent: roomInfo.leftEvent
|
leftEvent: roomInfo.leftEvent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
import "../../Base"
|
import "../../Base"
|
||||||
|
|
||||||
HNoticeLabel {
|
HNoticePage {
|
||||||
text: dateTime.toLocaleDateString()
|
text: dateTime.toLocaleDateString()
|
||||||
color: HStyle.chat.daybreak.foreground
|
color: HStyle.chat.daybreak.foreground
|
||||||
backgroundColor: HStyle.chat.daybreak.background
|
backgroundColor: HStyle.chat.daybreak.background
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
import QtQuick.Layouts 1.3
|
|
||||||
import "../../Base"
|
import "../../Base"
|
||||||
|
|
||||||
HGlassRectangle {
|
HGlassRectangle {
|
||||||
@ -8,9 +7,6 @@ HGlassRectangle {
|
|||||||
|
|
||||||
color: HStyle.chat.roomEventList.background
|
color: HStyle.chat.roomEventList.background
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: roomEventListView
|
id: roomEventListView
|
||||||
delegate: RoomEventDelegate {}
|
delegate: RoomEventDelegate {}
|
||||||
@ -20,7 +16,6 @@ HGlassRectangle {
|
|||||||
anchors.leftMargin: space
|
anchors.leftMargin: space
|
||||||
anchors.rightMargin: space
|
anchors.rightMargin: space
|
||||||
|
|
||||||
clip: true
|
|
||||||
topMargin: space
|
topMargin: space
|
||||||
bottomMargin: space
|
bottomMargin: space
|
||||||
verticalLayoutDirection: ListView.BottomToTop
|
verticalLayoutDirection: ListView.BottomToTop
|
||||||
@ -39,10 +34,10 @@ HGlassRectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HNoticeLabel {
|
HNoticePage {
|
||||||
text: qsTr("Nothing to show here yet...")
|
text: qsTr("Nothing to show here yet...")
|
||||||
|
|
||||||
visible: roomEventListView.model.count < 1
|
visible: roomEventListView.model.count < 1
|
||||||
anchors.centerIn: parent
|
anchors.fill: parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import "../Base"
|
import "../Base"
|
||||||
|
|
||||||
HNoticeLabel {
|
HNoticePage {
|
||||||
text: "Select or add a room to start."
|
text: "Select or add a room to start."
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
|
import QtQuick 2.7
|
||||||
import QtQuick.Layouts 1.3
|
import QtQuick.Layouts 1.3
|
||||||
import "../Base"
|
import "../Base"
|
||||||
|
|
||||||
HColumnLayout {
|
Column {
|
||||||
id: accountDelegate
|
id: accountDelegate
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
property string roomListUserId: userId
|
property string roomCategoriesListUserId: userId
|
||||||
|
property bool expanded: true
|
||||||
|
|
||||||
HRowLayout {
|
HRowLayout {
|
||||||
|
width: parent.width
|
||||||
|
height: childrenRect.height
|
||||||
id: row
|
id: row
|
||||||
|
|
||||||
HAvatar { id: avatar; name: displayName; dimension: 36 }
|
HAvatar {
|
||||||
|
id: avatar
|
||||||
|
name: displayName
|
||||||
|
}
|
||||||
|
|
||||||
HColumnLayout {
|
HColumnLayout {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@ -47,30 +54,27 @@ HColumnLayout {
|
|||||||
|
|
||||||
HButton {
|
HButton {
|
||||||
id: toggleExpand
|
id: toggleExpand
|
||||||
iconName: roomList.visible ? "up" : "down"
|
iconName: roomCategoriesList.visible ? "up" : "down"
|
||||||
iconDimension: 16
|
iconDimension: 16
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
onClicked: roomList.visible = ! roomList.visible
|
onClicked: accountDelegate.expanded = ! accountDelegate.expanded
|
||||||
|
|
||||||
Layout.preferredHeight: row.height
|
Layout.preferredHeight: row.height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RoomList {
|
RoomCategoriesList {
|
||||||
id: roomList
|
id: roomCategoriesList
|
||||||
visible: true
|
|
||||||
interactive: false // no scrolling
|
interactive: false // no scrolling
|
||||||
userId: roomListUserId
|
visible: height > 0
|
||||||
|
width: parent.width
|
||||||
|
height: childrenRect.height * (accountDelegate.expanded ? 1 : 0)
|
||||||
|
clip: heightAnimation.running
|
||||||
|
|
||||||
Layout.preferredHeight: roomList.visible ? roomList.contentHeight : 0
|
userId: roomCategoriesListUserId
|
||||||
|
|
||||||
Layout.preferredWidth:
|
Behavior on height {
|
||||||
parent.width - Layout.leftMargin - Layout.rightMargin
|
NumberAnimation { id: heightAnimation; duration: 100 }
|
||||||
|
}
|
||||||
Layout.margins: accountList.spacing
|
|
||||||
Layout.rightMargin: 0
|
|
||||||
Layout.leftMargin:
|
|
||||||
sidePane.width <= (sidePane.Layout.minimumWidth + Layout.margins) ?
|
|
||||||
0 : Layout.margins
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,6 @@ ListView {
|
|||||||
spacing: 8
|
spacing: 8
|
||||||
topMargin: spacing
|
topMargin: spacing
|
||||||
bottomMargin: topMargin
|
bottomMargin: topMargin
|
||||||
Layout.leftMargin:
|
|
||||||
sidePane.width <= (sidePane.Layout.minimumWidth + spacing) ?
|
|
||||||
0 : spacing
|
|
||||||
|
|
||||||
model: Backend.models.accounts
|
model: Backend.models.accounts
|
||||||
delegate: AccountDelegate {}
|
delegate: AccountDelegate {}
|
||||||
|
11
harmonyqml/components/SidePane/RoomCategoriesList.qml
Normal file
11
harmonyqml/components/SidePane/RoomCategoriesList.qml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import "../Base"
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
property string userId: ""
|
||||||
|
|
||||||
|
id: roomCategoriesList
|
||||||
|
model: Backend.models.accounts.get(userId).roomCategories
|
||||||
|
delegate: RoomCategoryDelegate {}
|
||||||
|
}
|
@ -1,15 +1,52 @@
|
|||||||
import QtQuick 2.7
|
import QtQuick 2.7
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
import "../Base"
|
import "../Base"
|
||||||
|
|
||||||
HLabel {
|
Column {
|
||||||
width: roomList.width
|
id: roomCategoryDelegate
|
||||||
|
width: roomCategoriesList.width
|
||||||
|
height: childrenRect.height
|
||||||
|
visible: roomList.contentHeight > 0
|
||||||
|
|
||||||
// topPadding is provided by the roomList spacing
|
property string roomListUserId: userId
|
||||||
bottomPadding: roomList.spacing
|
property bool expanded: true
|
||||||
|
|
||||||
text: section
|
HRowLayout {
|
||||||
elide: Text.ElideRight
|
width: parent.width
|
||||||
maximumLineCount: 1
|
|
||||||
|
|
||||||
font.weight: Font.DemiBold
|
HLabel {
|
||||||
|
id: roomCategoryLabel
|
||||||
|
text: name
|
||||||
|
font.weight: Font.DemiBold
|
||||||
|
elide: Text.ElideRight
|
||||||
|
maximumLineCount: 1
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
HButton {
|
||||||
|
id: roomCategoryToggleExpand
|
||||||
|
iconName: roomList.visible ? "up" : "down"
|
||||||
|
iconDimension: 16
|
||||||
|
backgroundColor: "transparent"
|
||||||
|
onClicked:
|
||||||
|
roomCategoryDelegate.expanded = !roomCategoryDelegate.expanded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomList {
|
||||||
|
id: roomList
|
||||||
|
interactive: false // no scrolling
|
||||||
|
visible: height > 0
|
||||||
|
width: roomCategoriesList.width - accountList.Layout.leftMargin
|
||||||
|
height: childrenRect.height * (roomCategoryDelegate.expanded ? 1 : 0)
|
||||||
|
clip: heightAnimation.running
|
||||||
|
|
||||||
|
userId: roomListUserId
|
||||||
|
category: name
|
||||||
|
|
||||||
|
Behavior on height {
|
||||||
|
NumberAnimation { id: heightAnimation; duration: 100 }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,36 +6,33 @@ import "utils.js" as SidePaneJS
|
|||||||
MouseArea {
|
MouseArea {
|
||||||
id: roomDelegate
|
id: roomDelegate
|
||||||
width: roomList.width
|
width: roomList.width
|
||||||
height: roomList.childrenHeight
|
height: childrenRect.height
|
||||||
|
|
||||||
onClicked: pageStack.showRoom(roomList.userId, roomId)
|
onClicked: pageStack.showRoom(roomList.userId, roomList.category, roomId)
|
||||||
|
|
||||||
HRowLayout {
|
HRowLayout {
|
||||||
anchors.fill: parent
|
width: parent.width
|
||||||
id: row
|
spacing: roomList.spacing
|
||||||
spacing: 1
|
|
||||||
|
|
||||||
HAvatar {
|
HAvatar {
|
||||||
id: roomAvatar
|
id: roomAvatar
|
||||||
name: displayName
|
name: displayName
|
||||||
dimension: roomDelegate.height
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HColumnLayout {
|
HColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.maximumWidth:
|
||||||
|
parent.width - parent.totalSpacing - roomAvatar.width
|
||||||
|
|
||||||
HLabel {
|
HLabel {
|
||||||
id: roomLabel
|
id: roomLabel
|
||||||
text: displayName ? displayName : "<i>Empty room</i>"
|
text: displayName ? displayName : "<i>Empty room</i>"
|
||||||
textFormat: Text.StyledText
|
textFormat: Text.StyledText
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
Layout.maximumWidth:
|
|
||||||
row.width - row.totalSpacing - roomAvatar.width
|
|
||||||
verticalAlignment: Qt.AlignVCenter
|
verticalAlignment: Qt.AlignVCenter
|
||||||
|
|
||||||
topPadding: -2
|
Layout.maximumWidth: parent.width
|
||||||
bottomPadding: subtitleLabel.visible ? 0 : topPadding
|
|
||||||
leftPadding: 5
|
|
||||||
rightPadding: leftPadding
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HLabel {
|
HLabel {
|
||||||
@ -58,15 +55,9 @@ MouseArea {
|
|||||||
font.pixelSize: HStyle.fontSize.small
|
font.pixelSize: HStyle.fontSize.small
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
maximumLineCount: 1
|
maximumLineCount: 1
|
||||||
Layout.maximumWidth: roomLabel.Layout.maximumWidth
|
|
||||||
|
|
||||||
topPadding: -2
|
Layout.maximumWidth: parent.width
|
||||||
bottomPadding: topPadding
|
|
||||||
leftPadding: 5
|
|
||||||
rightPadding: leftPadding
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HSpacer {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,36 +3,11 @@ import QtQuick.Layouts 1.3
|
|||||||
import "../Base"
|
import "../Base"
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
property var userId: null
|
property string userId: ""
|
||||||
|
property string category: ""
|
||||||
property int childrenHeight: 36
|
|
||||||
property int sectionHeight: 16 + spacing
|
|
||||||
property int contentHeight: getContentHeight()
|
|
||||||
|
|
||||||
function getContentHeight() {
|
|
||||||
var sections = []
|
|
||||||
|
|
||||||
for (var i = 0; i < model.count; i++) {
|
|
||||||
var categ = model.get(i).category
|
|
||||||
if (sections.indexOf(categ) == -1) { sections.push(categ) }
|
|
||||||
}
|
|
||||||
|
|
||||||
contentHeight =
|
|
||||||
childrenHeight * model.count +
|
|
||||||
spacing * Math.max(0, (model.count - 1)) +
|
|
||||||
sectionHeight * sections.length
|
|
||||||
}
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: model
|
|
||||||
onChanged: getContentHeight()
|
|
||||||
}
|
|
||||||
|
|
||||||
id: roomList
|
id: roomList
|
||||||
spacing: 8
|
spacing: accountList.spacing
|
||||||
model: Backend.models.rooms.get(userId)
|
model: Backend.models.accounts.get(userId).roomCategories.get(category).rooms
|
||||||
delegate: RoomDelegate {}
|
delegate: RoomDelegate {}
|
||||||
|
|
||||||
section.property: "category"
|
|
||||||
section.delegate: RoomCategoryDelegate { height: sectionHeight }
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,6 @@ import "../Base"
|
|||||||
|
|
||||||
HGlassRectangle {
|
HGlassRectangle {
|
||||||
id: sidePane
|
id: sidePane
|
||||||
clip: true // Avoid artifacts when resizing pane width to minimum
|
|
||||||
|
|
||||||
isPageStackDescendant: false
|
isPageStackDescendant: false
|
||||||
|
|
||||||
HColumnLayout {
|
HColumnLayout {
|
||||||
@ -14,6 +12,10 @@ HGlassRectangle {
|
|||||||
AccountList {
|
AccountList {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
Layout.leftMargin:
|
||||||
|
sidePane.width <= (sidePane.Layout.minimumWidth + spacing) ?
|
||||||
|
0 : spacing
|
||||||
}
|
}
|
||||||
|
|
||||||
PaneToolBar {}
|
PaneToolBar {}
|
||||||
|
@ -3,17 +3,8 @@
|
|||||||
|
|
||||||
function getLastRoomEventText(roomId, accountId) {
|
function getLastRoomEventText(roomId, accountId) {
|
||||||
var eventsModel = Backend.models.roomEvents.get(roomId)
|
var eventsModel = Backend.models.roomEvents.get(roomId)
|
||||||
|
if (eventsModel.count < 1) { return "" }
|
||||||
for (var i = 0; i < eventsModel.count; i++) {
|
var ev = eventsModel.get(0)
|
||||||
var ev = eventsModel.get(i)
|
|
||||||
|
|
||||||
if (! Backend.EventIsOurProfileChanged(ev, accountId)) {
|
|
||||||
var found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! found) { return "" }
|
|
||||||
|
|
||||||
var name = Backend.getUserDisplayName(ev.dict.sender, false).result()
|
var name = Backend.getUserDisplayName(ev.dict.sender, false).result()
|
||||||
var undecryptable = ev.type === "OlmEvent" || ev.type === "MegolmEvent"
|
var undecryptable = ev.type === "OlmEvent" || ev.type === "MegolmEvent"
|
||||||
|
@ -40,9 +40,10 @@ Item {
|
|||||||
pageStack.replace("Pages/" + name + ".qml", properties || {})
|
pageStack.replace("Pages/" + name + ".qml", properties || {})
|
||||||
}
|
}
|
||||||
|
|
||||||
function showRoom(userId, roomId) {
|
function showRoom(userId, category, roomId) {
|
||||||
pageStack.replace(
|
pageStack.replace(
|
||||||
"Chat/Chat.qml", { userId: userId, roomId: roomId }
|
"Chat/Chat.qml",
|
||||||
|
{ userId: userId, category: category, roomId: roomId }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user