From 0b678d06ff5cdc9eefc21c28da68ceef4be3d22b Mon Sep 17 00:00:00 2001 From: niv Date: Wed, 13 May 2026 14:41:25 +0200 Subject: [PATCH 1/4] fix(assistant): render markdown in TextInput output Wrap the output field in NcRichText when isOutput is true, falling back to NcRichContenteditable for the input case. Headings, lists, bold, italic, code blocks and links are now rendered. Tables are not rendered due to the markdown-it configuration of NcRichText in @nextcloud/vue, which does not enable the table plugin by default. The copy still functions and keeps the markdown as expected. Signed-off-by: niv --- src/components/fields/TextInput.vue | 63 ++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/components/fields/TextInput.vue b/src/components/fields/TextInput.vue index c9b9e243..8933e113 100644 --- a/src/components/fields/TextInput.vue +++ b/src/components/fields/TextInput.vue @@ -9,7 +9,16 @@
{{ limitLabel ?? '' }} + + @update:model-value="$emit('update:value', $event)" + @blur="onEditableBlur" />
{ + const ref = this.$refs.input + if (!ref) { + return + } + if (typeof ref.focus === 'function') { + ref.focus() + return + } + const el = ref.$el + if (!el) { + return + } + if (typeof el.focus === 'function') { + el.focus() + return + } + const editable = el.querySelector?.('[contenteditable]') + if (editable && typeof editable.focus === 'function') { + editable.focus() + } + }) + }, + onEditableBlur() { + if (this.isOutput && this.isEditing) { + this.isEditing = false + } + }, }, } @@ -272,6 +318,20 @@ body[dir="rtl"] .output-buttons { bottom: 2px; } + .output-wrapper { + display: block !important; + box-sizing: border-box !important; + border: 2px solid var(--color-primary-element) !important; + border-radius: var(--border-radius-large) !important; + padding: 8px !important; + padding-bottom: 42px !important; + max-height: 35vh !important; + overflow-y: auto !important; + .rendered-output, .rendered-output * { + cursor: text; + } + } + .rich-contenteditable__input { min-height: calc(var(--default-clickable-area) * 3 + 4px); padding-top: 5px !important; @@ -280,6 +340,7 @@ body[dir="rtl"] .output-buttons { .shadowed .rich-contenteditable__input { border: 2px solid var(--color-primary-element); padding-bottom: 38px !important; + max-height: 35vh !important; } .shadowed.streaming .rich-contenteditable__input { animation: pulse 2s infinite; From b3a161ed3188a3c2ae235ed04bedb6accc852dc5 Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Fri, 10 Jul 2026 10:33:28 +0200 Subject: [PATCH 2/4] fix: change the min height of NcRichText in Signed-off-by: Julien Veyssier --- src/components/fields/TextInput.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/fields/TextInput.vue b/src/components/fields/TextInput.vue index 8933e113..c5b2a012 100644 --- a/src/components/fields/TextInput.vue +++ b/src/components/fields/TextInput.vue @@ -325,6 +325,7 @@ body[dir="rtl"] .output-buttons { border-radius: var(--border-radius-large) !important; padding: 8px !important; padding-bottom: 42px !important; + min-height: calc(var(--default-clickable-area) * 3 + 4px); max-height: 35vh !important; overflow-y: auto !important; .rendered-output, .rendered-output * { From 67e3d8ffe6725c22373d7724671d296d92621516 Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Fri, 10 Jul 2026 10:39:41 +0200 Subject: [PATCH 3/4] fix: make NcRichText scroll while streaming in Signed-off-by: Julien Veyssier --- src/components/fields/TextInput.vue | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/fields/TextInput.vue b/src/components/fields/TextInput.vue index c5b2a012..0df983e1 100644 --- a/src/components/fields/TextInput.vue +++ b/src/components/fields/TextInput.vue @@ -11,6 +11,7 @@ { + const scrollableArea = this.$refs.input?.$el?.querySelector('#' + this.id) + if (scrollableArea) { + scrollableArea.scrollTo(0, scrollableArea.scrollHeight) + } + const richText = this.$refs.richText?.$el + if (richText) { + richText.scrollTo(0, richText.scrollHeight) + } + }) }, }, From 05afc7c39e5ac6523b703c29bd6219121a3e188a Mon Sep 17 00:00:00 2001 From: Julien Veyssier Date: Wed, 22 Jul 2026 16:10:01 +0200 Subject: [PATCH 4/4] fix: add pulse animation to NcRichText Signed-off-by: Julien Veyssier --- src/components/fields/TextInput.vue | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/fields/TextInput.vue b/src/components/fields/TextInput.vue index 0df983e1..80630b03 100644 --- a/src/components/fields/TextInput.vue +++ b/src/components/fields/TextInput.vue @@ -13,6 +13,7 @@ v-if="isOutput && hasValue && !isEditing" ref="richText" class="rendered-output output-wrapper" + :class="{ streaming: isOutput && streaming() }" :title="t('assistant', 'Double-click to edit')" :text="value ?? ''" :use-markdown="true" @@ -353,10 +354,16 @@ body[dir="rtl"] .output-buttons { .shadowed.streaming .rich-contenteditable__input { animation: pulse 2s infinite; } + .output-wrapper.streaming { + animation: pulse 2s infinite; + } @media (prefers-reduced-motion: reduce) { .shadowed.streaming .rich-contenteditable__input { animation: none; } + .output-wrapper.streaming { + animation: none; + } } }