207 lines
4.3 KiB
QML
207 lines
4.3 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import Quickshell
|
|
import QtQuick
|
|
import QtQuick.Layouts
|
|
import ZShell.Llm
|
|
import ZShell.Config
|
|
import qs.Services
|
|
import qs.Components
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property alias list: list
|
|
property alias model: list.model
|
|
|
|
signal deleteChatRequest(content: ChatSession)
|
|
signal loadChatRequest(content: ChatSession, index: int)
|
|
signal newChatRequest
|
|
|
|
CustomText {
|
|
id: header
|
|
|
|
anchors.left: parent.left
|
|
anchors.margins: Tokens.padding.extraSmall
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
color: Colors.palette.m3outline
|
|
font.family: "CaskaydiaCove NF"
|
|
font.pointSize: 13
|
|
font.weight: 500
|
|
text: qsTr("%1 Chat%2").arg(list.count).arg(list.count > 1 ? "s" : "")
|
|
}
|
|
|
|
CustomListView {
|
|
id: list
|
|
|
|
anchors.bottom: parent.bottom
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: header.bottom
|
|
anchors.topMargin: Tokens.spacing.medium
|
|
cacheBuffer: height * 2
|
|
clip: true
|
|
spacing: Tokens.spacing.medium
|
|
|
|
delegate: Component {
|
|
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
|
|
|
|
anchors.fill: undefined
|
|
implicitHeight: chat.layout.implicitHeight + chat.layout.anchors.topMargin + chat.layout.anchors.bottomMargin
|
|
implicitWidth: ListView.view.width
|
|
|
|
onEditVisibleChanged: if (!editVisible)
|
|
chat.x = 0
|
|
|
|
ParallelAnimation {
|
|
id: removeAnim
|
|
|
|
onFinished: root.deleteChatRequest(chatItem.modelData)
|
|
onStarted: chatItem.closing = true
|
|
|
|
Anim {
|
|
property: "implicitHeight"
|
|
target: chatItem
|
|
to: 0
|
|
}
|
|
|
|
Anim {
|
|
property: "x"
|
|
target: chat
|
|
to: -chat.implicitWidth
|
|
}
|
|
|
|
Anim {
|
|
property: "opacity"
|
|
target: chatItem
|
|
to: 0
|
|
}
|
|
}
|
|
|
|
ChatDelegate {
|
|
id: chat
|
|
|
|
chatItem: chatItem
|
|
implicitWidth: chatItem.implicitWidth
|
|
modelData: chatItem.modelData
|
|
radius: Tokens.rounding.medium
|
|
|
|
Behavior on x {
|
|
Anim {
|
|
}
|
|
}
|
|
Behavior on y {
|
|
Anim {
|
|
}
|
|
}
|
|
|
|
StateLayer {
|
|
cursorShape: drag.active ? Qt.ClosedHandCursor : Qt.PointingHandCursor
|
|
drag.axis: Drag.XAxis
|
|
drag.target: chat
|
|
hoverEnabled: true
|
|
preventStealing: true
|
|
|
|
onClicked: {
|
|
if (chatItem.editVisible)
|
|
chatItem.editVisible = false;
|
|
else
|
|
root.loadChatRequest(chatItem.modelData, chatItem.index);
|
|
}
|
|
onPressed: event => {
|
|
chatItem.startY = event.y;
|
|
}
|
|
onReleased: event => {
|
|
if (chat.x > -(editTools.implicitWidth + Tokens.padding.extraSmall)) {
|
|
chat.x = 0;
|
|
} else {
|
|
chatItem.editVisible = true;
|
|
chat.x = -(editTools.implicitWidth + Tokens.spacing.medium + Tokens.padding.extraSmall);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CustomClippingRect {
|
|
anchors.left: chat.right
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: Tokens.padding.extraSmall
|
|
anchors.verticalCenter: chat.verticalCenter
|
|
implicitHeight: editTools.implicitHeight
|
|
|
|
RowLayout {
|
|
id: editTools
|
|
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
IconButton {
|
|
id: deleteChatBtn
|
|
|
|
font.pointSize: Tokens.font.size.large
|
|
icon: "close"
|
|
radius: Tokens.rounding.full
|
|
|
|
transform: [
|
|
Scale {
|
|
property bool shouldBeActive: (chat.x < -deleteChatBtn.implicitWidth) && !chatItem.closing
|
|
|
|
origin.x: deleteChatBtn.implicitWidth / 2
|
|
origin.y: deleteChatBtn.implicitWidth / 2
|
|
xScale: shouldBeActive ? 1 : 0
|
|
yScale: shouldBeActive ? 1 : 0
|
|
|
|
Behavior on xScale {
|
|
Anim {
|
|
}
|
|
}
|
|
Behavior on yScale {
|
|
Anim {
|
|
}
|
|
}
|
|
}
|
|
]
|
|
|
|
onClicked: {
|
|
removeAnim.start();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
IconButton {
|
|
id: newChatBtn
|
|
|
|
anchors.bottom: parent.bottom
|
|
anchors.margins: Tokens.padding.small
|
|
anchors.right: parent.right
|
|
font.pointSize: Math.round(18 * 1.2)
|
|
icon: "add"
|
|
padding: 8
|
|
radius: Tokens.rounding.full
|
|
|
|
onClicked: {
|
|
root.newChatRequest();
|
|
}
|
|
|
|
Elevation {
|
|
anchors.fill: parent
|
|
level: newChatBtn.stateLayer.containsMouse ? 4 : 3
|
|
radius: parent.radius
|
|
z: -1
|
|
}
|
|
}
|
|
}
|