Loading icon for accounts until synced

This commit is contained in:
miruka 2019-08-27 15:00:50 -04:00
parent b457f46247
commit 6cb7589cca
5 changed files with 24 additions and 31 deletions

View File

@ -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

View File

@ -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(

View File

@ -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:]

View File

@ -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 }

View File

@ -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 {} }
} }