diff --git a/TODO.md b/TODO.md index 6cfbfbf1..d2fc735d 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,6 @@ - Refactoring + - filter string serialize thing + - set client max timeout to 10s - Make all icon SVG files white/black, since we can now use ColorOverlay - Make the icon blue in EditAccount when hovering and no avatar set diff --git a/src/python/app.py b/src/python/app.py index 0770a928..e0726776 100644 --- a/src/python/app.py +++ b/src/python/app.py @@ -84,7 +84,6 @@ class App: rl = self.run_in_loop # noqa ba = self.backend # noqa mo = self.backend.models # noqa - smo = self.backend.sidepane_model # noqa cl = self.backend.clients tcl = lambda user: cl[f"@test_{user}:matrix.org"] # noqa diff --git a/src/python/models/items.py b/src/python/models/items.py index e659426b..fa8a0b3a 100644 --- a/src/python/models/items.py +++ b/src/python/models/items.py @@ -13,12 +13,17 @@ class Account(ModelItem): display_name: str = "" avatar_url: str = "" profile_updated: datetime = field(default_factory=datetime.now) + filter_string: str = "" def __lt__(self, other: "Account") -> bool: name = self.display_name or self.user_id[1:] other_name = other.display_name or other.user_id[1:] return name < other_name + # @property + # def filter_string(self) -> str: # TODO: support serializing properties + # return " ".join((self.user_id, self.display_name)) + @dataclass class Room(ModelItem): diff --git a/src/qml/SidePane/AccountRoomList.qml b/src/qml/SidePane/AccountRoomList.qml index 4dbc386a..af2e74d0 100644 --- a/src/qml/SidePane/AccountRoomList.qml +++ b/src/qml/SidePane/AccountRoomList.qml @@ -1,16 +1,54 @@ import QtQuick 2.12 import QtQuick.Layouts 1.12 import "../Base" +import "../utils.js" as Utils HListView { id: accountRoomList - // property bool forceExpand: paneToolBar.roomFilter && roomList.model.count - property bool forceExpand: false + + readonly property var originSource: window.sidePaneModelSource + readonly property var collapseAccounts: window.uiState.collapseAccounts + readonly property string filter: paneToolBar.roomFilter + + onOriginSourceChanged: Qt.callLater(filterSource) + onFilterChanged: Qt.callLater(filterSource) + onCollapseAccountsChanged: Qt.callLater(filterSource) + + + function filterSource() { + let show = [] + + for (let i = 0; i < window.sidePaneModelSource.length; i++) { + let item = window.sidePaneModelSource[i] + + if (item.type == "Account" || + (filter ? + Utils.filterMatches(filter, item.data.filter_string) : + ! window.uiState.collapseAccounts[item.user_id])) + { + if (filter && show.length && item.type == "Account" && + show[show.length - 1].type == "Account" && + ! Utils.filterMatches(filter, item.data.filter_string)) { + // If current and previous items are both accounts, + // that means the previous account had no matching rooms. + show.pop() + } + + show.push(item) + } + } + + // If last item is an account, that account had no matching rooms. + if (show.length && show[show.length - 1].type == "Account") show.pop() + + model.source = show + } + model: HListModel { keyField: "id" - source: window.sidePaneModelSource + source: originSource } delegate: Loader { diff --git a/src/qml/SidePane/DelegateAccount.qml b/src/qml/SidePane/DelegateAccount.qml index 18cdd92e..85d4a3e9 100644 --- a/src/qml/SidePane/DelegateAccount.qml +++ b/src/qml/SidePane/DelegateAccount.qml @@ -4,17 +4,22 @@ import "../Base" HInteractiveRectangle { id: accountDelegate - height: row.height color: theme.sidePane.account.background + checked: isCurrent + height: row.height + - checked: accountDelegate.isCurrent readonly property bool isCurrent: window.uiState.page == "Pages/EditAccount/EditAccount.qml" && window.uiState.pageProperties.userId == model.data.user_id + readonly property bool forceExpand: + Boolean(accountRoomList.filter) + readonly property bool collapsed: - ! accountRoomList.forceExpand && - window.uiState.collapseAccounts[model.data.user_id] || false + ! forceExpand && + accountRoomList.collapseAccounts[model.data.user_id] || false + function toggleCollapse() { window.uiState.collapseAccounts[model.data.user_id] = ! collapsed @@ -27,6 +32,7 @@ HInteractiveRectangle { ) } + TapHandler { onTapped: accountDelegate.activate() } HRowLayout { @@ -74,7 +80,7 @@ HInteractiveRectangle { visible: opacity > 0 opacity: - accountRoomList.forceExpand ? 0 : + accountDelegate.forceExpand ? 0 : collapsed ? theme.sidePane.account.collapsedOpacity + 0.2 : 1 Behavior on opacity { HNumberAnimation {} } diff --git a/src/qml/SidePane/DelegateRoom.qml b/src/qml/SidePane/DelegateRoom.qml index d1e2bb2c..6af77714 100644 --- a/src/qml/SidePane/DelegateRoom.qml +++ b/src/qml/SidePane/DelegateRoom.qml @@ -6,29 +6,30 @@ import "../utils.js" as Utils HInteractiveRectangle { id: roomDelegate color: theme.sidePane.room.background - - readonly property bool collapsed: - ! accountRoomList.forceExpand && - window.uiState.collapseAccounts[model.user_id] || false - visible: height > 0 - height: collapsed ? 0 : rowLayout.height - Behavior on height { HNumberAnimation {} } - + height: rowLayout.height opacity: model.data.left ? theme.sidePane.room.leftRoomOpacity : 1 + checked: isCurrent + + Behavior on opacity { HNumberAnimation {} } - checked: isCurrent + + readonly property bool forceExpand: + Boolean(accountRoomList.filter) + readonly property bool isCurrent: window.uiState.page == "Chat/Chat.qml" && window.uiState.pageProperties.userId == model.user_id && window.uiState.pageProperties.roomId == model.data.room_id + function activate() { pageStack.showRoom(model.user_id, model.data.room_id) print(model.user_id, model.data.room_id) } + TapHandler { onTapped: activate() } HRowLayout { diff --git a/src/qml/utils.js b/src/qml/utils.js index fe7a57ed..35a2a7a4 100644 --- a/src/qml/utils.js +++ b/src/qml/utils.js @@ -89,11 +89,13 @@ function filterMatches(filter, text) { function filterModelSource(source, filter_text, property="filter_string") { - if (! filter_text) { return source } - + if (! filter_text) return source let results = [] - for (let item of source) { - if (filterMatches(filter_text, item[property])) { results.push(item) } + + for (let i = 0; i < source.length; i++) { + if (filterMatches(filter_text, source[i][property])) { + results.push(item) + } } return results }