import QtQuick import ZShell.Llm import ZShell.Config import qs.Components import qs.Services import qs.Modules.Notifications.Sidebar.Chat Item { id: root property int animOff property Item currentItem property bool noAnim: false property bool loading: false property int lastIdx: -1 readonly property Component conversationComp: ChatContent {} signal requestClose function loadConversation(chat): void { if (currentItem) { currentItem.destroy(); currentItem = null; } if (!chat) return; root.loading = true; const incubator = root.conversationComp.incubateObject(container, { chatData: chat }); const attach = () => { incubator.object.anchors.fill = container; incubator.object.requestClose.connect(root.requestClose); currentItem = incubator.object; root.loading = false; if (!noAnim) enterAnim.start(); }; if (incubator.status === Component.Ready) attach(); else incubator.onStatusChanged = status => { if (status === Component.Ready) attach(); }; } Item { id: container anchors.fill: parent layer.enabled: opacity < 1 objectName: "ConversationContainer" Component.onCompleted: { if (ChatState.chatSession) root.loadConversation(ChatState.chatSession); } } LoadingIndicator { anchors.centerIn: parent implicitSize: Tokens.font.size.extraLarge * 4 opacity: root.loading ? 1 : 0 visible: opacity > 0 Behavior on opacity { Anim {} } } Connections { function onChatSessionChanged(): void { exitAnim.complete(); enterAnim.complete(); if (root.noAnim) { root.loadConversation(ChatState.chatSession); return; } root.animOff = Tokens.padding.small * (ChatState.currentIdx > root.lastIdx ? 1 : -1); root.lastIdx = ChatState.currentIdx; exitAnim.start(); } target: ChatState } SequentialAnimation { id: exitAnim Anim { property: "opacity" target: container to: 0 type: Anim.DefaultEffects } ScriptAction { script: root.loadConversation(ChatState.chatSession) } } SequentialAnimation { id: enterAnim PropertyAction { property: "topMargin" target: container.anchors value: root.animOff } PropertyAction { property: "bottomMargin" target: container.anchors value: -root.animOff } ParallelAnimation { Anim { from: 0 property: "opacity" target: container to: 1 type: Anim.SlowEffects } Anim { properties: "topMargin,bottomMargin" target: container.anchors to: 0 type: Anim.SlowEffects } } } }