Make Chat show spinner until ready
Like EditAccount, instead of crashing if the room isn't loaded yet.
This commit is contained in:
		@@ -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
 | 
			
		||||
 | 
			
		||||
    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:
 | 
			
		||||
        if not self.clients:
 | 
			
		||||
            return
 | 
			
		||||
            await self.wait_until_client_exists()
 | 
			
		||||
 | 
			
		||||
        client = self.clients.get(
 | 
			
		||||
            user_id,
 | 
			
		||||
 
 | 
			
		||||
@@ -4,13 +4,11 @@
 | 
			
		||||
import QtQuick 2.12
 | 
			
		||||
import QtQuick.Layouts 1.12
 | 
			
		||||
import "../Base"
 | 
			
		||||
import "Banners"
 | 
			
		||||
import "Timeline"
 | 
			
		||||
import "RoomSidePane"
 | 
			
		||||
 | 
			
		||||
HPage {
 | 
			
		||||
    id: chatPage
 | 
			
		||||
    onFocusChanged: sendBox.setFocus()
 | 
			
		||||
 | 
			
		||||
    property bool ready: roomInfo && ! roomInfo.loading
 | 
			
		||||
 | 
			
		||||
    property var roomInfo: null
 | 
			
		||||
    onRoomInfoChanged: if (! roomInfo) { pageStack.showPage("Default") }
 | 
			
		||||
@@ -27,120 +25,34 @@ HPage {
 | 
			
		||||
 | 
			
		||||
    header: RoomHeader {
 | 
			
		||||
        id: roomHeader
 | 
			
		||||
        width: parent.width
 | 
			
		||||
        displayName: roomInfo.displayName
 | 
			
		||||
        topic: roomInfo.topic
 | 
			
		||||
 | 
			
		||||
        clip: height < implicitHeight
 | 
			
		||||
        width: parent.width
 | 
			
		||||
        height: ready ? implicitHeight : 0
 | 
			
		||||
        Behavior on height { HNumberAnimation {} }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    page.leftPadding: 0
 | 
			
		||||
    page.rightPadding: 0
 | 
			
		||||
 | 
			
		||||
    HSplitView {
 | 
			
		||||
        id: chatSplitView
 | 
			
		||||
        Layout.fillWidth: true
 | 
			
		||||
        Layout.fillHeight: true
 | 
			
		||||
 | 
			
		||||
        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
 | 
			
		||||
    Loader {
 | 
			
		||||
        Timer {
 | 
			
		||||
            interval: 200
 | 
			
		||||
            repeat: true
 | 
			
		||||
            running: ! ready
 | 
			
		||||
            onTriggered: {
 | 
			
		||||
                let info = rooms.find(userId, category, roomId)
 | 
			
		||||
                if (! info.loading) { roomInfo = Qt.binding(() => info) }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        RoomSidePane {
 | 
			
		||||
            id: roomSidePane
 | 
			
		||||
        source: ready ? "ChatSplitView.qml" : "../Base/HBusyIndicator.qml"
 | 
			
		||||
 | 
			
		||||
            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
 | 
			
		||||
        }
 | 
			
		||||
        Layout.fillWidth: ready
 | 
			
		||||
        Layout.fillHeight: ready
 | 
			
		||||
        Layout.alignment: Qt.AlignCenter
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										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")}
 | 
			
		||||
 | 
			
		||||
    let item = {
 | 
			
		||||
        loading:    false,
 | 
			
		||||
        typingText: typingTextFor(typingMembers, userId),
 | 
			
		||||
 | 
			
		||||
        userId, category, roomId, displayName, avatarUrl, topic, members,
 | 
			
		||||
 
 | 
			
		||||
@@ -9,4 +9,24 @@ HListModel {
 | 
			
		||||
    sorters: StringSorter {
 | 
			
		||||
        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
 | 
			
		||||
        if (! userId) { return }
 | 
			
		||||
 | 
			
		||||
        let found = getWhere({userId}, 1)
 | 
			
		||||
        if (found.length > 0) { return found[0] }
 | 
			
		||||
        let found = getWhere({userId}, 1)[0]
 | 
			
		||||
        if (found) { return found }
 | 
			
		||||
 | 
			
		||||
        py.callCoro("request_user_update_event", [userId])
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,10 +27,12 @@ Python {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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() {}
 | 
			
		||||
        call("APP.call_client_coro", [accountId, name, uuid, args])
 | 
			
		||||
            pendingCoroutines[uuid] = callback || function() {}
 | 
			
		||||
            call("APP.call_client_coro", [accountId, name, uuid, args])
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function saveConfig(backend_attribute, data, callback=null) {
 | 
			
		||||
 
 | 
			
		||||
@@ -69,8 +69,8 @@ Item {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function showRoom(userId, category, roomId) {
 | 
			
		||||
                let info = rooms.getWhere({userId, roomId, category}, 1)[0]
 | 
			
		||||
                show("Chat/Chat.qml", {"roomInfo": info})
 | 
			
		||||
                let roomInfo = rooms.find(userId, category, roomId)
 | 
			
		||||
                show("Chat/Chat.qml", {roomInfo})
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            onCurrentItemChanged: if (currentItem) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user