Loading icon for accounts until synced
This commit is contained in:
parent
b457f46247
commit
6cb7589cca
5
TODO.md
5
TODO.md
|
@ -34,7 +34,7 @@
|
||||||
- Terrible performance using `QT_QPA_PLATFORM=wayland-egl`, must use `xcb`
|
- Terrible performance using `QT_QPA_PLATFORM=wayland-egl`, must use `xcb`
|
||||||
|
|
||||||
- UI
|
- UI
|
||||||
- Disable buttons when loading, disable edit profile when account loading
|
- Disable edit profile when account loading
|
||||||
- Make invite icon blink if there's no one but ourself in the room,
|
- Make invite icon blink if there's no one but ourself in the room,
|
||||||
but never do it again once the user hovered it long enough to show tooltip
|
but never do it again once the user hovered it long enough to show tooltip
|
||||||
or clicked on it once
|
or clicked on it once
|
||||||
|
@ -95,8 +95,7 @@
|
||||||
- Logout & leave/forget room warning popup
|
- Logout & leave/forget room warning popup
|
||||||
- Prevent using the SendBox if no permission (power levels)
|
- Prevent using the SendBox if no permission (power levels)
|
||||||
- Prevent using an alias if that user is not in the room or no permission
|
- Prevent using an alias if that user is not in the room or no permission
|
||||||
- Spinner when loading account, past room events, images or clicking buttons
|
- Spinner when loading past room events or images
|
||||||
- Show account page as loading until profile initially retrieved
|
|
||||||
|
|
||||||
- Theming
|
- Theming
|
||||||
- Distribute fonts
|
- Distribute fonts
|
||||||
|
|
|
@ -53,9 +53,9 @@ class MatrixClient(nio.AsyncClient):
|
||||||
self.backend: Backend = backend
|
self.backend: Backend = backend
|
||||||
self.models: ModelStore = self.backend.models
|
self.models: ModelStore = self.backend.models
|
||||||
|
|
||||||
self.sync_task: Optional[asyncio.Future] = None
|
self.sync_task: Optional[asyncio.Future] = None
|
||||||
self.first_sync_happened: asyncio.Event = asyncio.Event()
|
self.first_sync_done: asyncio.Event = asyncio.Event()
|
||||||
self.first_sync_date: Optional[datetime] = None
|
self.first_sync_date: Optional[datetime] = None
|
||||||
|
|
||||||
self.send_locks: DefaultDict[str, asyncio.Lock] = \
|
self.send_locks: DefaultDict[str, asyncio.Lock] = \
|
||||||
DefaultDict(asyncio.Lock) # {room_id: lock}
|
DefaultDict(asyncio.Lock) # {room_id: lock}
|
||||||
|
@ -224,7 +224,7 @@ class MatrixClient(nio.AsyncClient):
|
||||||
if room_id in self.fully_loaded_rooms or room_id in self.invited_rooms:
|
if room_id in self.fully_loaded_rooms or room_id in self.invited_rooms:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
await self.first_sync_happened.wait()
|
await self.first_sync_done.wait()
|
||||||
|
|
||||||
response = await self.room_messages(
|
response = await self.room_messages(
|
||||||
room_id = room_id,
|
room_id = room_id,
|
||||||
|
@ -484,11 +484,12 @@ class MatrixClient(nio.AsyncClient):
|
||||||
|
|
||||||
await self.register_nio_room(self.all_rooms[room_id], left=True)
|
await self.register_nio_room(self.all_rooms[room_id], left=True)
|
||||||
|
|
||||||
if not self.first_sync_happened.is_set():
|
if not self.first_sync_done.is_set():
|
||||||
asyncio.ensure_future(self.load_rooms_without_visible_events())
|
asyncio.ensure_future(self.load_rooms_without_visible_events())
|
||||||
|
|
||||||
self.first_sync_happened.set()
|
self.first_sync_done.set()
|
||||||
self.first_sync_date = datetime.now()
|
self.first_sync_date = datetime.now()
|
||||||
|
self.models[Account][self.user_id].first_sync_done = True
|
||||||
|
|
||||||
|
|
||||||
async def onErrorResponse(self, resp: nio.ErrorResponse) -> None:
|
async def onErrorResponse(self, resp: nio.ErrorResponse) -> None:
|
||||||
|
@ -628,8 +629,9 @@ class MatrixClient(nio.AsyncClient):
|
||||||
# Update our account profile if the event is newer than last update
|
# Update our account profile if the event is newer than last update
|
||||||
if ev.state_key == self.user_id:
|
if ev.state_key == self.user_id:
|
||||||
account = self.models[Account][self.user_id]
|
account = self.models[Account][self.user_id]
|
||||||
|
updated = account.profile_updated
|
||||||
|
|
||||||
if account.profile_updated < ev_date:
|
if not updated or updated < ev_date:
|
||||||
account.profile_updated = ev_date
|
account.profile_updated = ev_date
|
||||||
account.display_name = now["displayname"] or ""
|
account.display_name = now["displayname"] or ""
|
||||||
account.avatar_url = now["avatar_url"] or ""
|
account.avatar_url = now["avatar_url"] or ""
|
||||||
|
@ -712,7 +714,7 @@ class MatrixClient(nio.AsyncClient):
|
||||||
async def onTypingNoticeEvent(self, room, ev) -> None:
|
async def onTypingNoticeEvent(self, room, ev) -> None:
|
||||||
# Prevent recent past typing notices from being shown for a split
|
# Prevent recent past typing notices from being shown for a split
|
||||||
# second on client startup:
|
# second on client startup:
|
||||||
if not self.first_sync_happened.is_set():
|
if not self.first_sync_done.is_set():
|
||||||
return
|
return
|
||||||
|
|
||||||
self.models[Room, self.user_id][room.room_id].typing_members = sorted(
|
self.models[Room, self.user_id][room.room_id].typing_members = sorted(
|
||||||
|
|
|
@ -10,10 +10,11 @@ from .model_item import ModelItem
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Account(ModelItem):
|
class Account(ModelItem):
|
||||||
user_id: str = field()
|
user_id: str = field()
|
||||||
display_name: str = ""
|
display_name: str = ""
|
||||||
avatar_url: str = ""
|
avatar_url: str = ""
|
||||||
profile_updated: datetime = field(default_factory=datetime.now)
|
first_sync_done: bool = False
|
||||||
|
profile_updated: Optional[datetime] = None
|
||||||
|
|
||||||
def __lt__(self, other: "Account") -> bool:
|
def __lt__(self, other: "Account") -> bool:
|
||||||
name = self.display_name or self.user_id[1:]
|
name = self.display_name or self.user_id[1:]
|
||||||
|
|
|
@ -3,6 +3,7 @@ import QtQuick.Controls 2.12
|
||||||
import QtQuick.Layouts 1.12
|
import QtQuick.Layouts 1.12
|
||||||
|
|
||||||
HRowLayout {
|
HRowLayout {
|
||||||
|
id: buttonContent
|
||||||
spacing: button.spacing
|
spacing: button.spacing
|
||||||
opacity: loading ? theme.loadingElementsOpacity :
|
opacity: loading ? theme.loadingElementsOpacity :
|
||||||
enabled ? 1 : theme.disabledElementsOpacity
|
enabled ? 1 : theme.disabledElementsOpacity
|
||||||
|
@ -32,25 +33,14 @@ HRowLayout {
|
||||||
target: icon
|
target: icon
|
||||||
property: "opacity"
|
property: "opacity"
|
||||||
from: 1
|
from: 1
|
||||||
to: 0.3
|
to: 0.5
|
||||||
factor: 2
|
factor: 2
|
||||||
running: button.loading || false
|
running: button.loading || false
|
||||||
onStopped: { [from, to] = [to, from]; start() }
|
onFinished: { [from, to] = [to, from]; start() }
|
||||||
}
|
}
|
||||||
|
|
||||||
HNumberAnimation {
|
|
||||||
target: icon
|
|
||||||
property: "scale"
|
|
||||||
from: 1
|
|
||||||
to: 0.92
|
|
||||||
factor: blink.factor
|
|
||||||
running: blink.running
|
|
||||||
onStopped: { [from, to] = [to, from]; start() }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SequentialAnimation {
|
SequentialAnimation {
|
||||||
running: blink.running
|
running: button.loading || false
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
|
|
||||||
HPauseAnimation { factor: blink.factor * 8 }
|
HPauseAnimation { factor: blink.factor * 8 }
|
||||||
|
|
|
@ -56,6 +56,7 @@ HTileDelegate {
|
||||||
|
|
||||||
HButton {
|
HButton {
|
||||||
id: expand
|
id: expand
|
||||||
|
loading: ! model.data.first_sync_done || ! model.data.profile_updated
|
||||||
icon.name: "expand"
|
icon.name: "expand"
|
||||||
backgroundColor: "transparent"
|
backgroundColor: "transparent"
|
||||||
padding: sidePane.currentSpacing / 1.5
|
padding: sidePane.currentSpacing / 1.5
|
||||||
|
@ -64,13 +65,13 @@ HTileDelegate {
|
||||||
onClicked: accountDelegate.toggleCollapse()
|
onClicked: accountDelegate.toggleCollapse()
|
||||||
|
|
||||||
visible: opacity > 0
|
visible: opacity > 0
|
||||||
opacity: accountDelegate.forceExpand ? 0 : 1
|
opacity: ! loading && accountDelegate.forceExpand ? 0 : 1
|
||||||
|
|
||||||
iconItem.transform: Rotation {
|
iconItem.transform: Rotation {
|
||||||
origin.x: expand.iconItem.dimension / 2
|
origin.x: expand.iconItem.dimension / 2
|
||||||
origin.y: expand.iconItem.dimension / 2
|
origin.y: expand.iconItem.dimension / 2
|
||||||
|
angle: expand.loading ? 0 : collapsed ? 180 : 90
|
||||||
|
|
||||||
angle: collapsed ? 180 : 90
|
|
||||||
Behavior on angle { HNumberAnimation {} }
|
Behavior on angle { HNumberAnimation {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user