Make Chat show spinner until ready
Like EditAccount, instead of crashing if the room isn't loaded yet.
This commit is contained in:
parent
5b421f02d8
commit
246058e647
|
@ -91,6 +91,17 @@ class Backend:
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
async def wait_until_client_exists(self, user_id: str = "") -> None:
|
||||||
|
while True:
|
||||||
|
if user_id and user_id in self.clients:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not user_id and self.clients:
|
||||||
|
return
|
||||||
|
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
|
||||||
|
|
||||||
# General functions
|
# General functions
|
||||||
|
|
||||||
async def load_settings(self) -> Tuple[Dict[str, Any], ...]:
|
async def load_settings(self) -> Tuple[Dict[str, Any], ...]:
|
||||||
|
@ -99,7 +110,7 @@ class Backend:
|
||||||
|
|
||||||
async def request_user_update_event(self, user_id: str) -> None:
|
async def request_user_update_event(self, user_id: str) -> None:
|
||||||
if not self.clients:
|
if not self.clients:
|
||||||
return
|
await self.wait_until_client_exists()
|
||||||
|
|
||||||
client = self.clients.get(
|
client = self.clients.get(
|
||||||
user_id,
|
user_id,
|
||||||
|
|
|
@ -4,13 +4,11 @@
|
||||||
import QtQuick 2.12
|
import QtQuick 2.12
|
||||||
import QtQuick.Layouts 1.12
|
import QtQuick.Layouts 1.12
|
||||||
import "../Base"
|
import "../Base"
|
||||||
import "Banners"
|
|
||||||
import "Timeline"
|
|
||||||
import "RoomSidePane"
|
|
||||||
|
|
||||||
HPage {
|
HPage {
|
||||||
id: chatPage
|
id: chatPage
|
||||||
onFocusChanged: sendBox.setFocus()
|
|
||||||
|
property bool ready: roomInfo && ! roomInfo.loading
|
||||||
|
|
||||||
property var roomInfo: null
|
property var roomInfo: null
|
||||||
onRoomInfoChanged: if (! roomInfo) { pageStack.showPage("Default") }
|
onRoomInfoChanged: if (! roomInfo) { pageStack.showPage("Default") }
|
||||||
|
@ -27,120 +25,34 @@ HPage {
|
||||||
|
|
||||||
header: RoomHeader {
|
header: RoomHeader {
|
||||||
id: roomHeader
|
id: roomHeader
|
||||||
width: parent.width
|
|
||||||
displayName: roomInfo.displayName
|
displayName: roomInfo.displayName
|
||||||
topic: roomInfo.topic
|
topic: roomInfo.topic
|
||||||
|
|
||||||
|
clip: height < implicitHeight
|
||||||
|
width: parent.width
|
||||||
|
height: ready ? implicitHeight : 0
|
||||||
|
Behavior on height { HNumberAnimation {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
page.leftPadding: 0
|
page.leftPadding: 0
|
||||||
page.rightPadding: 0
|
page.rightPadding: 0
|
||||||
|
|
||||||
HSplitView {
|
|
||||||
id: chatSplitView
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
|
|
||||||
HColumnLayout {
|
Loader {
|
||||||
Layout.fillWidth: true
|
Timer {
|
||||||
|
interval: 200
|
||||||
EventList {
|
repeat: true
|
||||||
Layout.fillWidth: true
|
running: ! ready
|
||||||
Layout.fillHeight: true
|
onTriggered: {
|
||||||
}
|
let info = rooms.find(userId, category, roomId)
|
||||||
|
if (! info.loading) { roomInfo = Qt.binding(() => info) }
|
||||||
TypingMembersBar {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
InviteBanner {
|
|
||||||
visible: category == "Invites"
|
|
||||||
inviterId: roomInfo.inviterId
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
|
||||||
|
|
||||||
//UnknownDevicesBanner {
|
|
||||||
//visible: category == "Rooms" && hasUnknownDevices
|
|
||||||
//
|
|
||||||
//Layout.fillWidth: true
|
|
||||||
//}
|
|
||||||
|
|
||||||
SendBox {
|
|
||||||
id: sendBox
|
|
||||||
visible: category == "Rooms" && ! hasUnknownDevices
|
|
||||||
}
|
|
||||||
|
|
||||||
LeftBanner {
|
|
||||||
visible: category == "Left"
|
|
||||||
userId: chatPage.userId
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RoomSidePane {
|
source: ready ? "ChatSplitView.qml" : "../Base/HBusyIndicator.qml"
|
||||||
id: roomSidePane
|
|
||||||
|
|
||||||
activeView: roomHeader.activeButton
|
Layout.fillWidth: ready
|
||||||
property int oldWidth: width
|
Layout.fillHeight: ready
|
||||||
onActiveViewChanged:
|
Layout.alignment: Qt.AlignCenter
|
||||||
activeView ? restoreAnimation.start() : hideAnimation.start()
|
|
||||||
|
|
||||||
HNumberAnimation {
|
|
||||||
id: hideAnimation
|
|
||||||
target: roomSidePane
|
|
||||||
properties: "width"
|
|
||||||
from: target.width
|
|
||||||
to: 0
|
|
||||||
|
|
||||||
onStarted: {
|
|
||||||
target.oldWidth = target.width
|
|
||||||
target.Layout.minimumWidth = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HNumberAnimation {
|
|
||||||
id: restoreAnimation
|
|
||||||
target: roomSidePane
|
|
||||||
properties: "width"
|
|
||||||
from: 0
|
|
||||||
to: target.oldWidth
|
|
||||||
|
|
||||||
onStopped: target.Layout.minimumWidth = Qt.binding(
|
|
||||||
() => theme.avatar.size
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
collapsed: width < theme.avatar.size + theme.spacing
|
|
||||||
|
|
||||||
property bool wasSnapped: false
|
|
||||||
property int referenceWidth: roomHeader.buttonsWidth
|
|
||||||
onReferenceWidthChanged: {
|
|
||||||
if (! chatSplitView.manuallyResized || wasSnapped) {
|
|
||||||
if (wasSnapped) { chatSplitView.manuallyResized = false }
|
|
||||||
width = referenceWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property int currentWidth: width
|
|
||||||
onCurrentWidthChanged: {
|
|
||||||
if (referenceWidth != width &&
|
|
||||||
referenceWidth - 15 < width &&
|
|
||||||
width < referenceWidth + 15)
|
|
||||||
{
|
|
||||||
currentWidth = referenceWidth
|
|
||||||
width = referenceWidth
|
|
||||||
wasSnapped = true
|
|
||||||
currentWidth = Qt.binding(() => roomSidePane.width)
|
|
||||||
} else {
|
|
||||||
wasSnapped = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width: referenceWidth // Initial width
|
|
||||||
Layout.minimumWidth: theme.avatar.size
|
|
||||||
Layout.maximumWidth:
|
|
||||||
parent.width - theme.minimumSupportedWidthPlusSpacing
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
117
src/qml/Chat/ChatSplitView.qml
Normal file
117
src/qml/Chat/ChatSplitView.qml
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
// Copyright 2019 miruka
|
||||||
|
// This file is part of harmonyqml, licensed under LGPLv3.
|
||||||
|
|
||||||
|
import QtQuick 2.12
|
||||||
|
import QtQuick.Layouts 1.12
|
||||||
|
import "../Base"
|
||||||
|
import "Banners"
|
||||||
|
import "Timeline"
|
||||||
|
import "RoomSidePane"
|
||||||
|
|
||||||
|
HSplitView {
|
||||||
|
id: chatSplitView
|
||||||
|
Component.onCompleted: sendBox.setFocus()
|
||||||
|
|
||||||
|
HColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
EventList {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
}
|
||||||
|
|
||||||
|
TypingMembersBar {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
InviteBanner {
|
||||||
|
visible: category == "Invites"
|
||||||
|
inviterId: roomInfo.inviterId
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
|
||||||
|
//UnknownDevicesBanner {
|
||||||
|
//visible: category == "Rooms" && hasUnknownDevices
|
||||||
|
//
|
||||||
|
//Layout.fillWidth: true
|
||||||
|
//}
|
||||||
|
|
||||||
|
SendBox {
|
||||||
|
id: sendBox
|
||||||
|
visible: category == "Rooms" && ! hasUnknownDevices
|
||||||
|
}
|
||||||
|
|
||||||
|
LeftBanner {
|
||||||
|
visible: category == "Left"
|
||||||
|
userId: chatPage.userId
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomSidePane {
|
||||||
|
id: roomSidePane
|
||||||
|
|
||||||
|
activeView: roomHeader.activeButton
|
||||||
|
property int oldWidth: width
|
||||||
|
onActiveViewChanged:
|
||||||
|
activeView ? restoreAnimation.start() : hideAnimation.start()
|
||||||
|
|
||||||
|
HNumberAnimation {
|
||||||
|
id: hideAnimation
|
||||||
|
target: roomSidePane
|
||||||
|
properties: "width"
|
||||||
|
from: target.width
|
||||||
|
to: 0
|
||||||
|
|
||||||
|
onStarted: {
|
||||||
|
target.oldWidth = target.width
|
||||||
|
target.Layout.minimumWidth = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HNumberAnimation {
|
||||||
|
id: restoreAnimation
|
||||||
|
target: roomSidePane
|
||||||
|
properties: "width"
|
||||||
|
from: 0
|
||||||
|
to: target.oldWidth
|
||||||
|
|
||||||
|
onStopped: target.Layout.minimumWidth = Qt.binding(
|
||||||
|
() => theme.avatar.size
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
collapsed: width < theme.avatar.size + theme.spacing
|
||||||
|
|
||||||
|
property bool wasSnapped: false
|
||||||
|
property int referenceWidth: roomHeader.buttonsWidth
|
||||||
|
onReferenceWidthChanged: {
|
||||||
|
if (! chatSplitView.manuallyResized || wasSnapped) {
|
||||||
|
if (wasSnapped) { chatSplitView.manuallyResized = false }
|
||||||
|
width = referenceWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
property int currentWidth: width
|
||||||
|
onCurrentWidthChanged: {
|
||||||
|
if (referenceWidth != width &&
|
||||||
|
referenceWidth - 15 < width &&
|
||||||
|
width < referenceWidth + 15)
|
||||||
|
{
|
||||||
|
currentWidth = referenceWidth
|
||||||
|
width = referenceWidth
|
||||||
|
wasSnapped = true
|
||||||
|
currentWidth = Qt.binding(() => roomSidePane.width)
|
||||||
|
} else {
|
||||||
|
wasSnapped = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
width: referenceWidth // Initial width
|
||||||
|
Layout.minimumWidth: theme.avatar.size
|
||||||
|
Layout.maximumWidth:
|
||||||
|
parent.width - theme.minimumSupportedWidthPlusSpacing
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,6 +56,7 @@ function onRoomUpdated(
|
||||||
else if (category == "Left") { replace = find("Invites") || find("Rooms")}
|
else if (category == "Left") { replace = find("Invites") || find("Rooms")}
|
||||||
|
|
||||||
let item = {
|
let item = {
|
||||||
|
loading: false,
|
||||||
typingText: typingTextFor(typingMembers, userId),
|
typingText: typingTextFor(typingMembers, userId),
|
||||||
|
|
||||||
userId, category, roomId, displayName, avatarUrl, topic, members,
|
userId, category, roomId, displayName, avatarUrl, topic, members,
|
||||||
|
|
|
@ -9,4 +9,24 @@ HListModel {
|
||||||
sorters: StringSorter {
|
sorters: StringSorter {
|
||||||
roleName: "displayName"
|
roleName: "displayName"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
readonly property ListModel _emptyModel: ListModel {}
|
||||||
|
|
||||||
|
function find(userId, category, roomId) {
|
||||||
|
if (! userId) { return }
|
||||||
|
|
||||||
|
let found = rooms.getWhere({userId, roomId, category}, 1)[0]
|
||||||
|
if (found) { return found }
|
||||||
|
|
||||||
|
return {
|
||||||
|
userId, category, roomId,
|
||||||
|
displayName: "",
|
||||||
|
avatarUrl: "",
|
||||||
|
topic: "",
|
||||||
|
members: _emptyModel,
|
||||||
|
typingText: "",
|
||||||
|
inviterId: "",
|
||||||
|
loading: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,8 @@ HListModel {
|
||||||
// the expression with invalid data to establish property bindings
|
// the expression with invalid data to establish property bindings
|
||||||
if (! userId) { return }
|
if (! userId) { return }
|
||||||
|
|
||||||
let found = getWhere({userId}, 1)
|
let found = getWhere({userId}, 1)[0]
|
||||||
if (found.length > 0) { return found[0] }
|
if (found) { return found }
|
||||||
|
|
||||||
py.callCoro("request_user_update_event", [userId])
|
py.callCoro("request_user_update_event", [userId])
|
||||||
|
|
||||||
|
|
|
@ -27,10 +27,12 @@ Python {
|
||||||
}
|
}
|
||||||
|
|
||||||
function callClientCoro(accountId, name, args=[], callback=null) {
|
function callClientCoro(accountId, name, args=[], callback=null) {
|
||||||
let uuid = Math.random() + "." + name
|
callCoro("wait_until_client_exists", [accountId], () => {
|
||||||
|
let uuid = Math.random() + "." + name
|
||||||
|
|
||||||
pendingCoroutines[uuid] = callback || function() {}
|
pendingCoroutines[uuid] = callback || function() {}
|
||||||
call("APP.call_client_coro", [accountId, name, uuid, args])
|
call("APP.call_client_coro", [accountId, name, uuid, args])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveConfig(backend_attribute, data, callback=null) {
|
function saveConfig(backend_attribute, data, callback=null) {
|
||||||
|
|
|
@ -69,8 +69,8 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
function showRoom(userId, category, roomId) {
|
function showRoom(userId, category, roomId) {
|
||||||
let info = rooms.getWhere({userId, roomId, category}, 1)[0]
|
let roomInfo = rooms.find(userId, category, roomId)
|
||||||
show("Chat/Chat.qml", {"roomInfo": info})
|
show("Chat/Chat.qml", {roomInfo})
|
||||||
}
|
}
|
||||||
|
|
||||||
onCurrentItemChanged: if (currentItem) {
|
onCurrentItemChanged: if (currentItem) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user