ai: fade in response

This commit is contained in:
end-4
2025-10-12 12:58:03 +02:00
parent 79b49bd57e
commit a6e360c1db
2 changed files with 84 additions and 32 deletions
@@ -348,6 +348,9 @@ Singleton {
property JsonObject translator: JsonObject {
property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag.
}
property JsonObject ai: JsonObject {
property bool textFadeIn: true
}
property JsonObject booru: JsonObject {
property bool allowNsfw: false
property string defaultProvider: "yandere"
@@ -8,6 +8,7 @@ import qs.modules.common.functions
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Hyprland
ColumnLayout {
@@ -22,6 +23,8 @@ ColumnLayout {
property list<string> renderedLatexHashes: []
property string renderedSegmentContent: ""
property string shownText: ""
property bool fadeChunkSplitting: !editing && !/\n\|/.test(shownText) && Config.options.sidebar.ai.textFadeIn
Layout.fillWidth: true
@@ -73,7 +76,7 @@ ColumnLayout {
renderLatex()
} else {
// console.log("Editing mode enabled", segmentContent)
textArea.text = segmentContent
root.shownText = segmentContent
}
}
@@ -88,7 +91,7 @@ ColumnLayout {
onRenderedSegmentContentChanged: {
// console.log("Rendered segment content changed: " + renderedSegmentContent);
if (renderedSegmentContent) {
textArea.text = renderedSegmentContent;
root.shownText = renderedSegmentContent;
}
}
@@ -104,39 +107,85 @@ ColumnLayout {
}
}
TextArea {
id: textArea
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.colors.colSecondaryContainer
wrapMode: TextEdit.Wrap
color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1
textFormat: renderMarkdown ? TextEdit.MarkdownText : TextEdit.PlainText
text: Translation.tr("Waiting for response...")
onTextChanged: {
if (!root.editing) return
segmentContent = text
spacing: 0
Repeater {
id: textLinesRepeater
property list<real> textLineOpacities: []
model: ScriptModel {
// Split by either double newlines or single newlines in a list
values: root.fadeChunkSplitting ? root.shownText.split(/\n\n|\n(?= {0,2}[-\*])/g).filter(line => line.trim() !== "") : [root.shownText]
onValuesChanged: {
while (textLinesRepeater.textLineOpacities.length < values.length) {
textLinesRepeater.textLineOpacities.push(root.messageData.done ? 1 : 0);
}
}
}
delegate: TextArea {
id: textArea
required property int index
required property string modelData
onLinkActivated: (link) => {
Qt.openUrlExternally(link)
GlobalStates.sidebarLeftOpen = false
}
// Fade in animation
visible: opacity > 0
opacity: fadeChunkSplitting ? (textLinesRepeater.textLineOpacities[index] ?? (root.messageData.done ? 1 : 0)) : 1
Connections {
target: root.messageData
function onDoneChanged() {
if (root.messageData.done) {
textLinesRepeater.textLineOpacities[textArea.index] = 1
}
}
}
Connections {
target: textLinesRepeater.model
function onValuesChanged() {
if (textLinesRepeater.model.values.length > textArea.index + 1) {
textLinesRepeater.textLineOpacities[textArea.index] = 1
}
}
}
Behavior on opacity {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
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
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.colors.colSecondaryContainer
wrapMode: TextEdit.Wrap
color: messageData.thinking ? Appearance.colors.colSubtext : Appearance.colors.colOnLayer1
textFormat: renderMarkdown ? TextEdit.MarkdownText : TextEdit.PlainText
text: modelData
onTextChanged: {
if (!root.editing) return
segmentContent = text
}
onLinkActivated: (link) => {
Qt.openUrlExternally(link)
GlobalStates.sidebarLeftOpen = false
}
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
}
// Rectangle {
// anchors.fill: parent
// color: "#22786378"
// border.width: 1
// border.color: "#7E7E7E"
// }
}
}
}