forked from Shinonome/dots-hyprland
refractor
This commit is contained in:
@@ -241,241 +241,12 @@ Rectangle {
|
|||||||
delegate: Loader {
|
delegate: Loader {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
property var segment: modelData
|
property var segment: modelData
|
||||||
sourceComponent: modelData.type === "code" ? codeBlockComponent : textBlockComponent
|
property var messageData: root.messageData
|
||||||
}
|
property var editing: root.editing
|
||||||
}
|
property var renderMarkdown: root.renderMarkdown
|
||||||
}
|
property var enableMouseSelection: root.enableMouseSelection
|
||||||
|
|
||||||
Component { // Text block
|
source: modelData.type === "code" ? "MessageCodeBlock.qml" : "MessageTextBlock.qml"
|
||||||
id: textBlockComponent
|
|
||||||
TextArea {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
readOnly: !root.editing
|
|
||||||
selectByMouse: root.enableMouseSelection || root.editing
|
|
||||||
renderType: Text.NativeRendering
|
|
||||||
font.family: Appearance.font.family.reading
|
|
||||||
font.hintingPreference: Font.PreferNoHinting // Prevent weird bold text
|
|
||||||
font.pixelSize: Appearance.font.pixelSize.small
|
|
||||||
selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
|
|
||||||
selectionColor: Appearance.m3colors.m3secondaryContainer
|
|
||||||
wrapMode: TextEdit.Wrap
|
|
||||||
color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1
|
|
||||||
textFormat: root.renderMarkdown ? TextEdit.MarkdownText : TextEdit.PlainText
|
|
||||||
text: messageData.thinking ? qsTr("Waiting for response...") : segment.content
|
|
||||||
|
|
||||||
onTextChanged: {
|
|
||||||
segment.content = text
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: (event) => {
|
|
||||||
if ((event.key === Qt.Key_C) && event.modifiers == Qt.ControlModifier) {
|
|
||||||
messageText.copy()
|
|
||||||
event.accepted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLinkActivated: (link) => {
|
|
||||||
Qt.openUrlExternally(link)
|
|
||||||
Hyprland.dispatch("global quickshell:sidebarLeftClose")
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea { // Pointing hand for links
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: Qt.NoButton // Only for hover
|
|
||||||
hoverEnabled: true
|
|
||||||
cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor :
|
|
||||||
(root.enableMouseSelection || root.editing) ? Qt.IBeamCursor : Qt.ArrowCursor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component { // Code block
|
|
||||||
id: codeBlockComponent
|
|
||||||
ColumnLayout {
|
|
||||||
spacing: codeBlockComponentSpacing
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
Rectangle { // Code background
|
|
||||||
Layout.fillWidth: true
|
|
||||||
topLeftRadius: codeBlockBackgroundRounding
|
|
||||||
topRightRadius: codeBlockBackgroundRounding
|
|
||||||
bottomLeftRadius: Appearance.rounding.unsharpen
|
|
||||||
bottomRightRadius: Appearance.rounding.unsharpen
|
|
||||||
color: Appearance.m3colors.m3surfaceContainerHighest
|
|
||||||
implicitHeight: codeBlockTitleBarRowLayout.implicitHeight + codeBlockHeaderPadding * 2
|
|
||||||
|
|
||||||
RowLayout { // Language and buttons
|
|
||||||
id: codeBlockTitleBarRowLayout
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.leftMargin: codeBlockHeaderPadding
|
|
||||||
anchors.rightMargin: codeBlockHeaderPadding
|
|
||||||
spacing: 5
|
|
||||||
|
|
||||||
StyledText {
|
|
||||||
id: codeBlockLanguage
|
|
||||||
Layout.alignment: Qt.AlignLeft
|
|
||||||
Layout.fillWidth: false
|
|
||||||
Layout.topMargin: 7
|
|
||||||
Layout.bottomMargin: 7
|
|
||||||
Layout.leftMargin: 10
|
|
||||||
font.pixelSize: Appearance.font.pixelSize.small
|
|
||||||
font.weight: Font.DemiBold
|
|
||||||
color: Appearance.colors.colOnLayer2
|
|
||||||
text: segment.lang ? Repository.definitionForName(segment.lang).name : "plain"
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
|
|
||||||
AiMessageControlButton {
|
|
||||||
id: copyCodeButton
|
|
||||||
buttonIcon: "content_copy"
|
|
||||||
onClicked: {
|
|
||||||
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(segment.content)}'`)
|
|
||||||
}
|
|
||||||
StyledToolTip {
|
|
||||||
content: qsTr("Copy code")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout { // Line numbers and code
|
|
||||||
spacing: codeBlockComponentSpacing
|
|
||||||
|
|
||||||
Rectangle { // Line numbers
|
|
||||||
implicitWidth: 40
|
|
||||||
Layout.fillHeight: true
|
|
||||||
Layout.fillWidth: false
|
|
||||||
topLeftRadius: Appearance.rounding.unsharpen
|
|
||||||
bottomLeftRadius: codeBlockBackgroundRounding
|
|
||||||
topRightRadius: Appearance.rounding.unsharpen
|
|
||||||
bottomRightRadius: Appearance.rounding.unsharpen
|
|
||||||
color: Appearance.colors.colLayer2
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: lineNumberColumnLayout
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 5
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
Repeater {
|
|
||||||
model: codeTextArea.text.split("\n").length
|
|
||||||
Text {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.alignment: Qt.AlignRight
|
|
||||||
font.family: Appearance.font.family.monospace
|
|
||||||
font.pixelSize: Appearance.font.pixelSize.small
|
|
||||||
color: Appearance.colors.colSubtext
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
text: index + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle { // Code background
|
|
||||||
Layout.fillWidth: true
|
|
||||||
topLeftRadius: Appearance.rounding.unsharpen
|
|
||||||
bottomLeftRadius: Appearance.rounding.unsharpen
|
|
||||||
topRightRadius: Appearance.rounding.unsharpen
|
|
||||||
bottomRightRadius: codeBlockBackgroundRounding
|
|
||||||
color: Appearance.colors.colLayer2
|
|
||||||
implicitHeight: codeTextArea.implicitHeight
|
|
||||||
|
|
||||||
ScrollView {
|
|
||||||
id: codeScrollView
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
implicitWidth: parent.width
|
|
||||||
implicitHeight: codeTextArea.implicitHeight + 1
|
|
||||||
contentWidth: codeTextArea.width - 1
|
|
||||||
// contentHeight: codeTextArea.contentHeight
|
|
||||||
clip: true
|
|
||||||
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
|
||||||
|
|
||||||
ScrollBar.horizontal: ScrollBar {
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
padding: 5
|
|
||||||
policy: ScrollBar.AsNeeded
|
|
||||||
opacity: visualSize == 1 ? 0 : 1
|
|
||||||
visible: opacity > 0
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
NumberAnimation {
|
|
||||||
duration: Appearance.animation.elementMoveFast.duration
|
|
||||||
easing.type: Appearance.animation.elementMoveFast.type
|
|
||||||
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
contentItem: Rectangle {
|
|
||||||
implicitHeight: 6
|
|
||||||
radius: Appearance.rounding.small
|
|
||||||
color: Appearance.colors.colLayer2Active
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextArea { // Code
|
|
||||||
id: codeTextArea
|
|
||||||
Layout.fillWidth: true
|
|
||||||
readOnly: !root.editing
|
|
||||||
selectByMouse: root.enableMouseSelection || root.editing
|
|
||||||
renderType: Text.NativeRendering
|
|
||||||
font.family: Appearance.font.family.monospace
|
|
||||||
font.hintingPreference: Font.PreferNoHinting // Prevent weird bold text
|
|
||||||
font.pixelSize: Appearance.font.pixelSize.small
|
|
||||||
selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
|
|
||||||
selectionColor: Appearance.m3colors.m3secondaryContainer
|
|
||||||
// wrapMode: TextEdit.Wrap
|
|
||||||
color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1
|
|
||||||
|
|
||||||
text: segment.content
|
|
||||||
onTextChanged: {
|
|
||||||
segment.content = text
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onPressed: (event) => {
|
|
||||||
if (event.key === Qt.Key_Tab) {
|
|
||||||
// Insert 4 spaces at cursor
|
|
||||||
const cursor = codeTextArea.cursorPosition;
|
|
||||||
codeTextArea.insert(cursor, " ");
|
|
||||||
codeTextArea.cursorPosition = cursor + 4;
|
|
||||||
event.accepted = true;
|
|
||||||
} else if ((event.key === Qt.Key_C) && event.modifiers == Qt.ControlModifier) {
|
|
||||||
messageText.copy();
|
|
||||||
event.accepted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SyntaxHighlighter {
|
|
||||||
id: highlighter
|
|
||||||
textEdit: codeTextArea
|
|
||||||
repository: Repository
|
|
||||||
definition: Repository.definitionForName(segment.lang || "plaintext")
|
|
||||||
// definition: Repository.definitionForName("cpp")
|
|
||||||
theme: Appearance.syntaxHighlightingTheme
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MouseArea to block scrolling
|
|
||||||
MouseArea {
|
|
||||||
id: codeBlockMouseArea
|
|
||||||
anchors.fill: parent
|
|
||||||
acceptedButtons: root.editing ? Qt.NoButton : Qt.LeftButton
|
|
||||||
cursorShape: (root.enableMouseSelection || root.editing) ? Qt.IBeamCursor : Qt.ArrowCursor
|
|
||||||
onWheel: (event) => {
|
|
||||||
event.accepted = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import "root:/"
|
||||||
|
import "root:/services"
|
||||||
|
import "root:/modules/common/"
|
||||||
|
import "root:/modules/common/widgets"
|
||||||
|
import "../"
|
||||||
|
import "root:/modules/common/functions/string_utils.js" as StringUtils
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
import Qt5Compat.GraphicalEffects
|
||||||
|
import org.kde.syntaxhighlighting
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
// These are needed on the parent loader
|
||||||
|
property bool editing: parent.editing ?? false
|
||||||
|
property bool renderMarkdown: parent.renderMarkdown ?? true
|
||||||
|
property bool enableMouseSelection: parent.enableMouseSelection ?? false
|
||||||
|
property var segment: parent.segment ?? {}
|
||||||
|
property var messageData: parent.messageData ?? {}
|
||||||
|
|
||||||
|
spacing: codeBlockComponentSpacing
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
Rectangle { // Code background
|
||||||
|
Layout.fillWidth: true
|
||||||
|
topLeftRadius: codeBlockBackgroundRounding
|
||||||
|
topRightRadius: codeBlockBackgroundRounding
|
||||||
|
bottomLeftRadius: Appearance.rounding.unsharpen
|
||||||
|
bottomRightRadius: Appearance.rounding.unsharpen
|
||||||
|
color: Appearance.m3colors.m3surfaceContainerHighest
|
||||||
|
implicitHeight: codeBlockTitleBarRowLayout.implicitHeight + codeBlockHeaderPadding * 2
|
||||||
|
|
||||||
|
RowLayout { // Language and buttons
|
||||||
|
id: codeBlockTitleBarRowLayout
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: codeBlockHeaderPadding
|
||||||
|
anchors.rightMargin: codeBlockHeaderPadding
|
||||||
|
spacing: 5
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: codeBlockLanguage
|
||||||
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
Layout.fillWidth: false
|
||||||
|
Layout.topMargin: 7
|
||||||
|
Layout.bottomMargin: 7
|
||||||
|
Layout.leftMargin: 10
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.small
|
||||||
|
font.weight: Font.DemiBold
|
||||||
|
color: Appearance.colors.colOnLayer2
|
||||||
|
text: segment.lang ? Repository.definitionForName(segment.lang).name : "plain"
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
|
||||||
|
AiMessageControlButton {
|
||||||
|
id: copyCodeButton
|
||||||
|
buttonIcon: "content_copy"
|
||||||
|
onClicked: {
|
||||||
|
Hyprland.dispatch(`exec wl-copy '${StringUtils.shellSingleQuoteEscape(segment.content)}'`)
|
||||||
|
}
|
||||||
|
StyledToolTip {
|
||||||
|
content: qsTr("Copy code")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout { // Line numbers and code
|
||||||
|
spacing: codeBlockComponentSpacing
|
||||||
|
|
||||||
|
Rectangle { // Line numbers
|
||||||
|
implicitWidth: 40
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: false
|
||||||
|
topLeftRadius: Appearance.rounding.unsharpen
|
||||||
|
bottomLeftRadius: codeBlockBackgroundRounding
|
||||||
|
topRightRadius: Appearance.rounding.unsharpen
|
||||||
|
bottomRightRadius: Appearance.rounding.unsharpen
|
||||||
|
color: Appearance.colors.colLayer2
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: lineNumberColumnLayout
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 5
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
spacing: 0
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: codeTextArea.text.split("\n").length
|
||||||
|
Text {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.alignment: Qt.AlignRight
|
||||||
|
font.family: Appearance.font.family.monospace
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.small
|
||||||
|
color: Appearance.colors.colSubtext
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
text: index + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle { // Code background
|
||||||
|
Layout.fillWidth: true
|
||||||
|
topLeftRadius: Appearance.rounding.unsharpen
|
||||||
|
bottomLeftRadius: Appearance.rounding.unsharpen
|
||||||
|
topRightRadius: Appearance.rounding.unsharpen
|
||||||
|
bottomRightRadius: codeBlockBackgroundRounding
|
||||||
|
color: Appearance.colors.colLayer2
|
||||||
|
implicitHeight: codeTextArea.implicitHeight
|
||||||
|
|
||||||
|
ScrollView {
|
||||||
|
id: codeScrollView
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
implicitWidth: parent.width
|
||||||
|
implicitHeight: codeTextArea.implicitHeight + 1
|
||||||
|
contentWidth: codeTextArea.width - 1
|
||||||
|
// contentHeight: codeTextArea.contentHeight
|
||||||
|
clip: true
|
||||||
|
ScrollBar.vertical.policy: ScrollBar.AlwaysOff
|
||||||
|
|
||||||
|
ScrollBar.horizontal: ScrollBar {
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
padding: 5
|
||||||
|
policy: ScrollBar.AsNeeded
|
||||||
|
opacity: visualSize == 1 ? 0 : 1
|
||||||
|
visible: opacity > 0
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation {
|
||||||
|
duration: Appearance.animation.elementMoveFast.duration
|
||||||
|
easing.type: Appearance.animation.elementMoveFast.type
|
||||||
|
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Rectangle {
|
||||||
|
implicitHeight: 6
|
||||||
|
radius: Appearance.rounding.small
|
||||||
|
color: Appearance.colors.colLayer2Active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea { // Code
|
||||||
|
id: codeTextArea
|
||||||
|
Layout.fillWidth: true
|
||||||
|
readOnly: !editing
|
||||||
|
selectByMouse: enableMouseSelection || editing
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
font.family: Appearance.font.family.monospace
|
||||||
|
font.hintingPreference: Font.PreferNoHinting // Prevent weird bold text
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.small
|
||||||
|
selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
|
||||||
|
selectionColor: Appearance.m3colors.m3secondaryContainer
|
||||||
|
// wrapMode: TextEdit.Wrap
|
||||||
|
color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1
|
||||||
|
|
||||||
|
text: segment.content
|
||||||
|
onTextChanged: {
|
||||||
|
segment.content = text
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: (event) => {
|
||||||
|
if (event.key === Qt.Key_Tab) {
|
||||||
|
// Insert 4 spaces at cursor
|
||||||
|
const cursor = codeTextArea.cursorPosition;
|
||||||
|
codeTextArea.insert(cursor, " ");
|
||||||
|
codeTextArea.cursorPosition = cursor + 4;
|
||||||
|
event.accepted = true;
|
||||||
|
} else if ((event.key === Qt.Key_C) && event.modifiers == Qt.ControlModifier) {
|
||||||
|
messageText.copy();
|
||||||
|
event.accepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SyntaxHighlighter {
|
||||||
|
id: highlighter
|
||||||
|
textEdit: codeTextArea
|
||||||
|
repository: Repository
|
||||||
|
definition: Repository.definitionForName(segment.lang || "plaintext")
|
||||||
|
// definition: Repository.definitionForName("cpp")
|
||||||
|
theme: Appearance.syntaxHighlightingTheme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MouseArea to block scrolling
|
||||||
|
MouseArea {
|
||||||
|
id: codeBlockMouseArea
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: editing ? Qt.NoButton : Qt.LeftButton
|
||||||
|
cursorShape: (enableMouseSelection || editing) ? Qt.IBeamCursor : Qt.ArrowCursor
|
||||||
|
onWheel: (event) => {
|
||||||
|
event.accepted = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import "root:/"
|
||||||
|
import "root:/services"
|
||||||
|
import "root:/modules/common/"
|
||||||
|
import "root:/modules/common/widgets"
|
||||||
|
import "../"
|
||||||
|
import "root:/modules/common/functions/string_utils.js" as StringUtils
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell.Io
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Widgets
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import Quickshell.Hyprland
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
// These are needed on the parent loader
|
||||||
|
property bool editing: parent.editing ?? false
|
||||||
|
property bool renderMarkdown: parent.renderMarkdown ?? true
|
||||||
|
property bool enableMouseSelection: parent.enableMouseSelection ?? false
|
||||||
|
property var segment: parent.segment ?? {}
|
||||||
|
property var messageData: parent.messageData ?? {}
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
readOnly: !editing
|
||||||
|
selectByMouse: enableMouseSelection || editing
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
font.family: Appearance.font.family.reading
|
||||||
|
font.hintingPreference: Font.PreferNoHinting // Prevent weird bold text
|
||||||
|
font.pixelSize: Appearance.font.pixelSize.small
|
||||||
|
selectedTextColor: Appearance.m3colors.m3onSecondaryContainer
|
||||||
|
selectionColor: Appearance.m3colors.m3secondaryContainer
|
||||||
|
wrapMode: TextEdit.Wrap
|
||||||
|
color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1
|
||||||
|
textFormat: renderMarkdown ? TextEdit.MarkdownText : TextEdit.PlainText
|
||||||
|
text: messageData.thinking ? qsTr("Waiting for response...") : segment.content
|
||||||
|
|
||||||
|
onTextChanged: {
|
||||||
|
segment.content = text
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onPressed: (event) => {
|
||||||
|
if ((event.key === Qt.Key_C) && event.modifiers == Qt.ControlModifier) {
|
||||||
|
messageText.copy()
|
||||||
|
event.accepted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLinkActivated: (link) => {
|
||||||
|
Qt.openUrlExternally(link)
|
||||||
|
Hyprland.dispatch("global quickshell:sidebarLeftClose")
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea { // Pointing hand for links
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.NoButton // Only for hover
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: parent.hoveredLink !== "" ? Qt.PointingHandCursor :
|
||||||
|
(enableMouseSelection || editing) ? Qt.IBeamCursor : Qt.ArrowCursor
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user