DEV: Follow-up small fixes to AI composer helper (#1361)

**This update includes a variety of small fixes to the AI composer helper:**
- ensures there is no flash of no text when diff modal is triggered
- escapes selected text prior to diff streaming
- uses monospace font in diff modal since text rendered is raw markdown
This commit is contained in:
Keegan George 2025-05-22 12:37:42 -07:00 committed by GitHub
parent 11e90f5f3f
commit 61ef1932fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 26 additions and 12 deletions

View File

@ -12,6 +12,7 @@ import concatClass from "discourse/helpers/concat-class";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { bind } from "discourse/lib/decorators"; import { bind } from "discourse/lib/decorators";
import { escapeExpression } from "discourse/lib/utilities";
import { i18n } from "discourse-i18n"; import { i18n } from "discourse-i18n";
import DiffStreamer from "../../lib/diff-streamer"; import DiffStreamer from "../../lib/diff-streamer";
import SmoothStreamer from "../../lib/smooth-streamer"; import SmoothStreamer from "../../lib/smooth-streamer";
@ -23,7 +24,8 @@ export default class ModalDiffModal extends Component {
@tracked loading = false; @tracked loading = false;
@tracked finalResult = ""; @tracked finalResult = "";
@tracked diffStreamer = new DiffStreamer(this.args.model.selectedText); @tracked selectedText = escapeExpression(this.args.model.selectedText);
@tracked diffStreamer = new DiffStreamer(this.selectedText);
@tracked suggestion = ""; @tracked suggestion = "";
@tracked @tracked
smoothStreamer = new SmoothStreamer( smoothStreamer = new SmoothStreamer(
@ -36,6 +38,16 @@ export default class ModalDiffModal extends Component {
this.suggestChanges(); this.suggestChanges();
} }
get diffResult() {
if (this.diffStreamer.diff?.length > 0) {
return this.diffStreamer.diff;
}
// Prevents flash by showing the
// original text when the diff is empty
return this.selectedText;
}
get isStreaming() { get isStreaming() {
return this.diffStreamer.isStreaming || this.smoothStreamer.isStreaming; return this.diffStreamer.isStreaming || this.smoothStreamer.isStreaming;
} }
@ -93,7 +105,7 @@ export default class ModalDiffModal extends Component {
data: { data: {
location: "composer", location: "composer",
mode: this.args.model.mode, mode: this.args.model.mode,
text: this.args.model.selectedText, text: this.selectedText,
custom_prompt: this.args.model.customPromptValue, custom_prompt: this.args.model.customPromptValue,
force_default_locale: true, force_default_locale: true,
}, },
@ -109,7 +121,7 @@ export default class ModalDiffModal extends Component {
if (this.suggestion) { if (this.suggestion) {
this.args.model.toolbarEvent.replaceText( this.args.model.toolbarEvent.replaceText(
this.args.model.selectedText, this.selectedText,
this.suggestion this.suggestion
); );
} }
@ -119,10 +131,7 @@ export default class ModalDiffModal extends Component {
? this.finalResult ? this.finalResult
: this.diffStreamer.suggestion; : this.diffStreamer.suggestion;
if (this.args.model.showResultAsDiff && finalResult) { if (this.args.model.showResultAsDiff && finalResult) {
this.args.model.toolbarEvent.replaceText( this.args.model.toolbarEvent.replaceText(this.selectedText, finalResult);
this.args.model.selectedText,
finalResult
);
} }
} }
@ -133,7 +142,11 @@ export default class ModalDiffModal extends Component {
@closeModal={{@closeModal}} @closeModal={{@closeModal}}
> >
<:body> <:body>
<div {{didInsert this.subscribe}} {{willDestroy this.unsubscribe}}> <div
{{didInsert this.subscribe}}
{{willDestroy this.unsubscribe}}
class="text-preview"
>
{{#if this.loading}} {{#if this.loading}}
<div class="composer-ai-helper-modal__loading"> <div class="composer-ai-helper-modal__loading">
{{~@model.selectedText~}} {{~@model.selectedText~}}
@ -149,9 +162,7 @@ export default class ModalDiffModal extends Component {
}} }}
> >
{{~#if @model.showResultAsDiff~}} {{~#if @model.showResultAsDiff~}}
<span class="diff-inner">{{htmlSafe <span class="diff-inner">{{htmlSafe this.diffResult}}</span>
this.diffStreamer.diff
}}</span>
{{else}} {{else}}
{{#if this.smoothStreamer.isStreaming}} {{#if this.smoothStreamer.isStreaming}}
<CookText <CookText

View File

@ -11,7 +11,7 @@ export default class DiffStreamer {
@tracked isStreaming = false; @tracked isStreaming = false;
@tracked words = []; @tracked words = [];
@tracked lastResultText = ""; @tracked lastResultText = "";
@tracked diff = ""; @tracked diff = this.selectedText;
@tracked suggestion = ""; @tracked suggestion = "";
@tracked isDone = false; @tracked isDone = false;
@tracked isThinking = false; @tracked isThinking = false;

View File

@ -1,6 +1,9 @@
.composer-ai-helper-modal { .composer-ai-helper-modal {
.text-preview, .text-preview,
.inline-diff { .inline-diff {
font-family: var(--d-font-family--monospace);
font-variant-ligatures: none;
ins { ins {
background-color: var(--success-low); background-color: var(--success-low);
text-decoration: none; text-decoration: none;