feat: Add a floating "copy" button

This commit is contained in:
Petr Mironychev 2025-04-28 09:25:39 +02:00
parent ee672f2cda
commit 43adc95857
3 changed files with 42 additions and 14 deletions

View File

@ -29,6 +29,7 @@ Rectangle {
property alias messageAttachments: attachmentsModel.model property alias messageAttachments: attachmentsModel.model
property bool isUserMessage: false property bool isUserMessage: false
property int messageIndex: -1 property int messageIndex: -1
property real listViewContentY: 0
signal resetChatToMessage(int index) signal resetChatToMessage(int index)
@ -84,6 +85,8 @@ Rectangle {
id: codeBlockComponent id: codeBlockComponent
CodeBlockComponent { CodeBlockComponent {
itemData: msgCreatorDelegate.modelData itemData: msgCreatorDelegate.modelData
blockStart: root.y + msgCreatorDelegate.y
currentContentY: root.listViewContentY
} }
} }
} }
@ -160,6 +163,8 @@ Rectangle {
component CodeBlockComponent : CodeBlock { component CodeBlockComponent : CodeBlock {
id: codeblock
required property var itemData required property var itemData
anchors { anchors {
left: parent.left left: parent.left

View File

@ -99,6 +99,7 @@ ChatRootView {
messageAttachments: model.attachments messageAttachments: model.attachments
isUserMessage: model.roleType === ChatModel.User isUserMessage: model.roleType === ChatModel.User
messageIndex: index messageIndex: index
listViewContentY: chatListView.contentY
onResetChatToMessage: function(index) { onResetChatToMessage: function(index) {
messageInput.text = model.content messageInput.text = model.content

View File

@ -27,16 +27,34 @@ Rectangle {
property string code: "" property string code: ""
property string language: "" property string language: ""
property real currentContentY: 0
property real blockStart: 0
readonly property real buttonTopMargin: 5
readonly property real blockEnd: blockStart + root.height
readonly property real maxButtonOffset: Math.max(0, root.height - copyButton.height - buttonTopMargin)
readonly property real buttonPosition: {
if (currentContentY > blockEnd) {
return buttonTopMargin;
}
else if (currentContentY > blockStart) {
let offset = currentContentY - blockStart;
return Math.min(offset, maxButtonOffset);
}
return buttonTopMargin;
}
readonly property string monospaceFont: { readonly property string monospaceFont: {
switch (Qt.platform.os) { switch (Qt.platform.os) {
case "windows": case "windows":
return "Consolas"; return "Consolas";
case "osx": case "osx":
return "Menlo"; return "Menlo";
case "linux": case "linux":
return "DejaVu Sans Mono"; return "DejaVu Sans Mono";
default: default:
return "monospace"; return "monospace";
} }
} }
@ -45,7 +63,6 @@ Rectangle {
: Qt.lighter(root.color, 1.3) : Qt.lighter(root.color, 1.3)
border.width: 2 border.width: 2
radius: 4 radius: 4
implicitWidth: parent.width implicitWidth: parent.width
implicitHeight: codeText.implicitHeight + 20 implicitHeight: codeText.implicitHeight + 20
@ -55,7 +72,6 @@ Rectangle {
TextEdit { TextEdit {
id: codeText id: codeText
anchors.fill: parent anchors.fill: parent
anchors.margins: 10 anchors.margins: 10
text: root.code text: root.code
@ -81,10 +97,16 @@ Rectangle {
} }
QoAButton { QoAButton {
anchors.top: parent.top id: copyButton
anchors.right: parent.right
anchors.margins: 5 anchors {
text: "Copy" top: parent.top
topMargin: root.buttonPosition
right: parent.right
rightMargin: root.buttonTopMargin
}
text: qsTr("Copy")
onClicked: { onClicked: {
utils.copyToClipboard(root.code) utils.copyToClipboard(root.code)
text = qsTr("Copied") text = qsTr("Copied")