start initial work on detaching chat to floating window
This commit is contained in:
@@ -11,7 +11,7 @@ import qs.Services
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property ChatSession chatData
|
||||
property ChatSession chatData
|
||||
property bool following: true
|
||||
readonly property int messageCount: chatData.messages.length
|
||||
|
||||
@@ -257,7 +257,7 @@ Item {
|
||||
|
||||
anchors.fill: parent
|
||||
spacing: Tokens.spacing.small
|
||||
visible: root.messageCount === 0 && !Chat.busy
|
||||
visible: (root.messageCount === 0 && !Chat.busy) || !root.chatData
|
||||
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
@@ -273,7 +273,7 @@ Item {
|
||||
CustomText {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
color: Colors.tPalette.m3onSurfaceVariant
|
||||
text: qsTr("No messages yet")
|
||||
text: !root.chatData ? qsTr("Open a previous chat or start a new one") : qsTr("No messages yet")
|
||||
}
|
||||
|
||||
Item {
|
||||
|
||||
@@ -8,6 +8,7 @@ import qs.Services
|
||||
CustomRect {
|
||||
id: root
|
||||
|
||||
required property Item chatItem
|
||||
property alias layout: layout
|
||||
required property ChatSession modelData
|
||||
|
||||
@@ -20,6 +21,7 @@ CustomRect {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Tokens.padding.large
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: root.chatItem.ListView.isCurrentItem ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||
font.pointSize: Tokens.font.size.extraLarge
|
||||
text: root.modelData.icon || "check"
|
||||
}
|
||||
@@ -48,6 +50,7 @@ CustomRect {
|
||||
CustomText {
|
||||
id: title
|
||||
|
||||
color: root.chatItem.ListView.isCurrentItem ? Colors.palette.m3onPrimary : Colors.palette.m3onSurface
|
||||
text: root.modelData.title
|
||||
}
|
||||
|
||||
@@ -57,7 +60,7 @@ CustomRect {
|
||||
anchors.left: title.right
|
||||
anchors.leftMargin: Tokens.spacing.small
|
||||
anchors.verticalCenter: title.verticalCenter
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
color: root.chatItem.ListView.isCurrentItem ? Qt.alpha(Colors.palette.m3onPrimary, 0.9) : Colors.palette.m3onSurfaceVariant
|
||||
text: "•"
|
||||
visible: titleContainer.enoughSpace
|
||||
}
|
||||
@@ -70,7 +73,7 @@ CustomRect {
|
||||
anchors.top: titleContainer.enoughSpace ? undefined : title.bottom
|
||||
anchors.topMargin: Tokens.spacing.extraSmall
|
||||
anchors.verticalCenter: titleContainer.enoughSpace ? title.verticalCenter : undefined
|
||||
color: Colors.palette.m3onSurfaceVariant
|
||||
color: root.chatItem.ListView.isCurrentItem ? Qt.alpha(Colors.palette.m3onPrimary, 0.9) : Colors.palette.m3onSurfaceVariant
|
||||
font.pointSize: Tokens.font.size.small
|
||||
text: root.modelData.updatedAt.toLocaleString(Qt.locale("en_US"), "MMM d, yyyy - h:mm AP")
|
||||
}
|
||||
@@ -78,7 +81,7 @@ CustomRect {
|
||||
|
||||
CustomText {
|
||||
Layout.fillWidth: true
|
||||
color: Colors.palette.m3outline
|
||||
color: root.chatItem.ListView.isCurrentItem ? Qt.alpha(Colors.palette.m3onPrimary, 0.9) : Colors.palette.m3onSurfaceVariant
|
||||
elide: Text.ElideRight
|
||||
font.pointSize: Tokens.font.size.small
|
||||
maximumLineCount: 1
|
||||
|
||||
@@ -11,10 +11,11 @@ import qs.Components
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property alias list: list
|
||||
property alias model: list.model
|
||||
|
||||
signal deleteChatRequest(content: ChatSession)
|
||||
signal loadChatRequest(content: ChatSession)
|
||||
signal loadChatRequest(content: ChatSession, index: int)
|
||||
signal newChatRequest
|
||||
|
||||
CustomText {
|
||||
@@ -47,8 +48,10 @@ Item {
|
||||
Item {
|
||||
id: chatItem
|
||||
|
||||
property alias chat: chat
|
||||
property bool closing: false
|
||||
property bool editVisible: false
|
||||
required property int index
|
||||
required property var modelData
|
||||
property real startY: 0.0
|
||||
|
||||
@@ -87,6 +90,7 @@ Item {
|
||||
ChatDelegate {
|
||||
id: chat
|
||||
|
||||
chatItem: chatItem
|
||||
implicitWidth: chatItem.implicitWidth
|
||||
modelData: chatItem.modelData
|
||||
radius: Tokens.rounding.medium
|
||||
@@ -111,7 +115,7 @@ Item {
|
||||
if (chatItem.editVisible)
|
||||
chatItem.editVisible = false;
|
||||
else
|
||||
root.loadChatRequest(chatItem.modelData);
|
||||
root.loadChatRequest(chatItem.modelData, chatItem.index);
|
||||
}
|
||||
onPressed: event => {
|
||||
chatItem.startY = event.y;
|
||||
|
||||
@@ -5,6 +5,7 @@ import ZShell.Llm
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import Quickshell
|
||||
import qs.Helpers
|
||||
import qs.Modules.Notifications.Sidebar
|
||||
import qs.Components
|
||||
import qs.Services
|
||||
@@ -12,26 +13,49 @@ import qs.Services
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property bool chatOpen: false
|
||||
required property Props props
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: Tokens.padding.small
|
||||
|
||||
Component.onCompleted: {
|
||||
if (root.props.inChat) {
|
||||
stack.push(chatList);
|
||||
stack.push(chatContent, {
|
||||
"chatData": root.props.chatSession
|
||||
if (ChatState.inChat) {
|
||||
stackLoader.item?.push(chatList);
|
||||
stackLoader.item?.push(chatContent, {
|
||||
"chatData": ChatState.chatSession
|
||||
});
|
||||
} else
|
||||
stack.push(chatList);
|
||||
stackLoader.item?.push(chatList);
|
||||
}
|
||||
|
||||
StackView {
|
||||
id: stack
|
||||
Loader {
|
||||
id: stackLoader
|
||||
|
||||
active: !ChatState.isWindow || root.width <= (ChatState.screen.width / 4)
|
||||
anchors.fill: parent
|
||||
|
||||
sourceComponent: StackView {
|
||||
id: stack
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: sidebarViewLoader
|
||||
|
||||
active: ChatState.isWindow && root.width > (ChatState.screen.width / 4)
|
||||
anchors.fill: parent
|
||||
|
||||
sourceComponent: SidebarView {
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
anchors.right: parent.right
|
||||
icon: "close"
|
||||
visible: !ChatState.isWindow
|
||||
|
||||
onClicked: {
|
||||
Detach.create();
|
||||
Visibilities.getForActive().sidebar = false;
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
@@ -46,19 +70,19 @@ Item {
|
||||
Chat.chats.remove(chat);
|
||||
}
|
||||
onLoadChatRequest: chat => {
|
||||
stack.push(chatContent, {
|
||||
stackLoader.item?.push(chatContent, {
|
||||
"chatData": chat
|
||||
});
|
||||
root.props.inChat = true;
|
||||
root.props.chatSession = chat;
|
||||
ChatState.inChat = true;
|
||||
ChatState.chatSession = chat;
|
||||
}
|
||||
onNewChatRequest: {
|
||||
const data = Chat.chats.insert();
|
||||
stack.push(chatContent, {
|
||||
stackLoader.item?.push(chatContent, {
|
||||
"chatData": data
|
||||
});
|
||||
root.props.inChat = true;
|
||||
root.props.chatSession = data;
|
||||
ChatState.inChat = true;
|
||||
ChatState.chatSession = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,8 +92,8 @@ Item {
|
||||
|
||||
ChatContent {
|
||||
onRequestClose: {
|
||||
stack.pop();
|
||||
root.props.inChat = false;
|
||||
stackLoader.item?.pop();
|
||||
ChatState.inChat = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import ZShell.Llm
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property ChatSession chatSession
|
||||
property bool inChat: false
|
||||
property bool isWindow: false
|
||||
property ShellScreen screen
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
pragma Singleton
|
||||
|
||||
import Quickshell
|
||||
import QtQuick
|
||||
import ZShell.Config
|
||||
import qs.Services
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
function create(parent: Item, props: var): void {
|
||||
chatComp.createObject(parent ?? dummy, props);
|
||||
ChatState.isWindow = true;
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: dummy
|
||||
}
|
||||
|
||||
Component {
|
||||
id: chatComp
|
||||
|
||||
FloatingWindow {
|
||||
id: win
|
||||
|
||||
property var props
|
||||
|
||||
color: Colors.tPalette.m3surface
|
||||
implicitHeight: chat.implicitHeight
|
||||
implicitWidth: chat.implicitWidth
|
||||
minimumSize.height: Config.sidebar.sizes.width
|
||||
minimumSize.width: Config.sidebar.sizes.width
|
||||
surfaceFormat.opaque: false
|
||||
title: qsTr("ZShell - Chat")
|
||||
|
||||
Component.onCompleted: ChatState.screen = screen
|
||||
onVisibleChanged: {
|
||||
if (!visible) {
|
||||
destroy();
|
||||
ChatState.isWindow = false;
|
||||
}
|
||||
}
|
||||
|
||||
ChatPanel {
|
||||
id: chat
|
||||
|
||||
anchors.fill: parent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Quickshell
|
||||
import ZShell.Config
|
||||
import ZShell.Llm
|
||||
import qs.Components
|
||||
import qs.Services
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
ChatList {
|
||||
id: chatList
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: Config.sidebar.sizes.width
|
||||
Layout.minimumWidth: Config.sidebar.sizes.width / 2
|
||||
list.currentIndex: -1
|
||||
list.highlightFollowsCurrentItem: false
|
||||
|
||||
list.highlight: CustomRect {
|
||||
color: Colors.palette.m3primary
|
||||
implicitHeight: chatList.list.currentItem?.implicitHeight ?? 0
|
||||
implicitWidth: chatList.list.width
|
||||
radius: Tokens.rounding.medium
|
||||
x: chatList.list.currentItem?.chat.x ?? 0
|
||||
y: chatList.list.currentItem?.y ?? 0
|
||||
|
||||
Behavior on y {
|
||||
Anim {
|
||||
duration: Tokens.anim.durations.small
|
||||
easing: Tokens.anim.expressiveDefaultEffects
|
||||
}
|
||||
}
|
||||
}
|
||||
model: ScriptModel {
|
||||
values: Chat.chats.values
|
||||
}
|
||||
|
||||
onLoadChatRequest: (chat, index) => {
|
||||
chatList.list.currentIndex = index;
|
||||
chatContent.chatData = chat;
|
||||
}
|
||||
}
|
||||
|
||||
ChatContent {
|
||||
id: chatContent
|
||||
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: Config.sidebar.sizes.width
|
||||
Layout.preferredWidth: Math.round(Config.sidebar.sizes.width * 1.5)
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,15 @@ Item {
|
||||
required property Props props
|
||||
required property var visibilities
|
||||
|
||||
Connections {
|
||||
function onIsWindowChanged(): void {
|
||||
if (ChatState.isWindow)
|
||||
root.props.currentTab = 0;
|
||||
}
|
||||
|
||||
target: ChatState
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: layout
|
||||
|
||||
@@ -22,8 +31,10 @@ Item {
|
||||
|
||||
Tabs {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: ChatState.isWindow ? 0 : implicitHeight
|
||||
dashState: root.props
|
||||
nonAnimWidth: layout.width
|
||||
visible: height > 0
|
||||
}
|
||||
|
||||
CustomClippingRect {
|
||||
@@ -75,7 +86,6 @@ Item {
|
||||
|
||||
ChatPanel {
|
||||
anchors.fill: parent
|
||||
props: root.props
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,8 @@ import Quickshell
|
||||
import ZShell.Llm
|
||||
|
||||
PersistentProperties {
|
||||
property ChatSession chatSession
|
||||
property int currentTab: 0
|
||||
property list<string> expandedNotifs: []
|
||||
property bool inChat: false
|
||||
|
||||
reloadableId: "sidebar"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user