Python filter for AccountsBar

This commit is contained in:
miruka 2020-05-10 14:26:26 -04:00
parent 0e49b5f972
commit 200f25d23e
5 changed files with 81 additions and 49 deletions

View File

@ -24,6 +24,8 @@
- rooms without messages on first sync - rooms without messages on first sync
- avatar loading performance problem? - avatar loading performance problem?
- docstrings
## Refactoring ## Refactoring
- Rewrite account settings using `HTabbedContainer` - Rewrite account settings using `HTabbedContainer`

View File

@ -20,7 +20,7 @@ from .models.filters import FieldSubstringFilter
from .models.items import Account from .models.items import Account
from .models.model import Model from .models.model import Model
from .models.model_store import ModelStore from .models.model_store import ModelStore
from .models.special_models import AllRooms from .models.special_models import AllRooms, MatchingAccounts
from .user_files import Accounts, History, Theme, UISettings, UIState from .user_files import Accounts, History, Theme, UISettings, UIState
# Logging configuration # Logging configuration
@ -81,9 +81,11 @@ class Backend:
self.ui_state: UIState = UIState(self) self.ui_state: UIState = UIState(self)
self.history: History = History(self) self.history: History = History(self)
self.all_rooms: AllRooms = AllRooms() self.all_rooms = AllRooms()
self.models: ModelStore = ModelStore() self.matching_accounts = MatchingAccounts(self.all_rooms)
self.clients: Dict[str, MatrixClient] = {} self.models = ModelStore()
self.clients: Dict[str, MatrixClient] = {}
self.profile_cache: Dict[str, nio.ProfileGetResponse] = {} self.profile_cache: Dict[str, nio.ProfileGetResponse] = {}
self.get_profile_locks: DefaultDict[str, asyncio.Lock] = \ self.get_profile_locks: DefaultDict[str, asyncio.Lock] = \

View File

@ -1,6 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
from typing import TYPE_CHECKING, Any, Collection, Dict, Optional, Tuple from typing import (
TYPE_CHECKING, Any, Callable, Collection, Dict, List, Optional, Tuple,
)
from . import SyncId from . import SyncId
from .model import Model from .model import Model
@ -13,6 +15,7 @@ if TYPE_CHECKING:
class ModelFilter(ModelProxy): class ModelFilter(ModelProxy):
def __init__(self, sync_id: SyncId) -> None: def __init__(self, sync_id: SyncId) -> None:
self.filtered_out: Dict[Tuple[Optional[SyncId], str], "ModelItem"] = {} self.filtered_out: Dict[Tuple[Optional[SyncId], str], "ModelItem"] = {}
self.items_changed_callbacks: List[Callable[[], None]] = []
super().__init__(sync_id) super().__init__(sync_id)
@ -35,6 +38,9 @@ class ModelFilter(ModelProxy):
self.filtered_out[source.sync_id, key] = value self.filtered_out[source.sync_id, key] = value
self.pop((source.sync_id, key), None) self.pop((source.sync_id, key), None)
for callback in self.items_changed_callbacks:
callback()
def source_item_deleted(self, source: Model, key) -> None: def source_item_deleted(self, source: Model, key) -> None:
if self.accept_source(source): if self.accept_source(source):
@ -43,6 +49,9 @@ class ModelFilter(ModelProxy):
except KeyError: except KeyError:
del self.filtered_out[source.sync_id, key] del self.filtered_out[source.sync_id, key]
for callback in self.items_changed_callbacks:
callback()
def source_cleared(self, source: Model) -> None: def source_cleared(self, source: Model) -> None:
if self.accept_source(source): if self.accept_source(source):
@ -53,6 +62,9 @@ class ModelFilter(ModelProxy):
except KeyError: except KeyError:
del self.filtered_out[source.sync_id, key] del self.filtered_out[source.sync_id, key]
for callback in self.items_changed_callbacks:
callback()
def refilter(self) -> None: def refilter(self) -> None:
with self._write_lock: with self._write_lock:
@ -74,6 +86,9 @@ class ModelFilter(ModelProxy):
for key in bring_back: for key in bring_back:
self[key] = self.filtered_out.pop(key) self[key] = self.filtered_out.pop(key)
for callback in self.items_changed_callbacks:
callback()
class FieldSubstringFilter(ModelFilter): class FieldSubstringFilter(ModelFilter):
def __init__(self, sync_id: SyncId, fields: Collection[str]) -> None: def __init__(self, sync_id: SyncId, fields: Collection[str]) -> None:

View File

@ -1,7 +1,8 @@
# SPDX-License-Identifier: LGPL-3.0-or-later # SPDX-License-Identifier: LGPL-3.0-or-later
from .filters import FieldSubstringFilter from .filters import FieldSubstringFilter, ModelFilter
from .model import Model from .model import Model
from .model_item import ModelItem
class AllRooms(FieldSubstringFilter): class AllRooms(FieldSubstringFilter):
@ -15,3 +16,24 @@ class AllRooms(FieldSubstringFilter):
len(source.sync_id) == 2 and len(source.sync_id) == 2 and
source.sync_id[1] == "rooms" # type: ignore source.sync_id[1] == "rooms" # type: ignore
) )
class MatchingAccounts(ModelFilter):
def __init__(self, all_rooms: AllRooms) -> None:
super().__init__(sync_id="matching_accounts")
self.all_rooms = all_rooms
self.all_rooms.items_changed_callbacks.append(self.refilter)
def accept_source(self, source: Model) -> bool:
return source.sync_id == "accounts"
def accept_item(self, item: ModelItem) -> bool:
if not self.all_rooms.filter:
return True
return next(
(r for r in self.all_rooms.values() if r.for_account == item.id),
False,
)

View File

@ -39,61 +39,52 @@ HColumnLayout {
-1, -1,
) )
model: HFilterModel { model: ModelStore.get("matching_accounts")
model: ModelStore.get("accounts")
acceptItem: item =>
! roomFilter || item.id in roomList.sectionIndice
delegate: HTileDelegate { delegate: HTileDelegate {
id: tile id: tile
width: accountList.width width: accountList.width
backgroundColor: backgroundColor:
theme.accountsBar.accountList.account.background theme.accountsBar.accountList.account.background
topPadding: (accountList.width - avatar.width) / 4 topPadding: (accountList.width - avatar.width) / 4
bottomPadding: topPadding bottomPadding: topPadding
leftPadding: 0 leftPadding: 0
rightPadding: leftPadding rightPadding: leftPadding
contentItem: Item { contentItem: Item {
implicitHeight: avatar.height implicitHeight: avatar.height
HUserAvatar { HUserAvatar {
id: avatar id: avatar
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
userId: model.id userId: model.id
displayName: model.display_name displayName: model.display_name
mxc: model.avatar_url mxc: model.avatar_url
// compact: tile.compact // compact: tile.compact
radius: radius:
theme.accountsBar.accountList.account.avatarRadius theme.accountsBar.accountList.account.avatarRadius
}
MessageIndicator {
anchors.right: parent.right
anchors.bottom: parent.bottom
indicatorTheme:
theme.accountView.account.unreadIndicator
unreads: model.total_unread
mentions: model.total_mentions
}
} }
contextMenu: AccountContextMenu { userId: model.id } MessageIndicator {
anchors.right: parent.right
anchors.bottom: parent.bottom
onLeftClicked: { indicatorTheme:
model.id in roomList.sectionIndice ? theme.accountView.account.unreadIndicator
roomList.goToAccount(model.id) : unreads: model.total_unread
pageLoader.showPage("AddChat/AddChat", {userId: model.id}) mentions: model.total_mentions
} }
} }
contextMenu: AccountContextMenu { userId: model.id }
onRoomFilterChanged: refilterAll() onLeftClicked: {
model.id in roomList.sectionIndice ?
readonly property string roomFilter: roomList.filter roomList.goToAccount(model.id) :
pageLoader.showPage("AddChat/AddChat", {userId: model.id})
}
} }
highlight: Item { highlight: Item {