@@ -13,37 +13,32 @@ import { ajax } from "discourse/lib/ajax";
13
13
import { popupAjaxError } from " discourse/lib/ajax-error" ;
14
14
import { bind } from " discourse/lib/decorators" ;
15
15
import { i18n } from " discourse-i18n" ;
16
+ import DiffStreamer from " ../../lib/diff-streamer" ;
16
17
import SmoothStreamer from " ../../lib/smooth-streamer" ;
17
18
import AiIndicatorWave from " ../ai-indicator-wave" ;
18
- import { cancel , later } from " @ember/runloop" ;
19
-
20
- const WORD_TYPING_DELAY = 200 ;
21
19
22
20
export default class ModalDiffModal extends Component {
23
21
@service currentUser;
24
22
@service messageBus;
25
23
26
24
@tracked loading = false ;
27
- @tracked diff ;
25
+ @tracked diffStreamer = new DiffStreamer ( this . args . model . selectedText ) ;
28
26
@tracked suggestion = " " ;
29
- @tracked isStreaming = false ;
30
- @tracked lastResultText = " " ;
31
- // @tracked
32
- // smoothStreamer = new SmoothStreamer(
33
- // () => this.suggestion,
34
- // (newValue) => (this.suggestion = newValue)
35
- // );
36
- @tracked finalDiff = " " ;
37
- @tracked words = [];
38
- originalWords = [];
39
- typingTimer = null ;
40
- currentWordIndex = 0 ;
27
+ @tracked
28
+ smoothStreamer = new SmoothStreamer (
29
+ () => this .suggestion ,
30
+ (newValue ) => (this .suggestion = newValue)
31
+ );
41
32
42
33
constructor () {
43
34
super (... arguments );
44
35
this .suggestChanges ();
45
36
}
46
37
38
+ get isStreaming () {
39
+ return this .diffStreamer .isStreaming || this .smoothStreamer .isStreaming ;
40
+ }
41
+
47
42
@bind
48
43
subscribe () {
49
44
const channel = " /discourse-ai/ai-helper/stream_composer_suggestion" ;
@@ -56,93 +51,21 @@ export default class ModalDiffModal extends Component {
56
51
this .messageBus .subscribe (channel, this .updateResult );
57
52
}
58
53
59
- compareText (oldText = " " , newText = " " , opts = {}) {
60
- const oldWords = oldText .trim ().split (/ \s + / );
61
- const newWords = newText .trim ().split (/ \s + / );
62
-
63
- const diff = [];
64
- let i = 0 ;
65
-
66
- while (i < newWords .length ) {
67
- const oldWord = oldWords[i];
68
- const newWord = newWords[i];
69
-
70
- let wordHTML;
71
- if (oldWord === undefined ) {
72
- wordHTML = ` <ins>${ newWord} </ins>` ;
73
- } else if (oldWord !== newWord) {
74
- wordHTML = ` <del>${ oldWord} </del> <ins>${ newWord} </ins>` ;
75
- } else {
76
- wordHTML = newWord;
77
- }
78
-
79
- if (i === newWords .length - 1 && opts .markLastWord ) {
80
- wordHTML = ` <mark class="highlight">${ wordHTML} </mark>` ;
81
- }
82
-
83
- diff .push (wordHTML);
84
- i++ ;
85
- }
86
-
87
- return diff .join (" " );
88
- }
89
-
90
54
@action
91
55
async updateResult (result ) {
92
56
this .loading = false ;
93
57
94
- const newText = result .result ;
95
- const diffText = newText .slice (this .lastResultText .length ).trim ();
96
- const newWords = diffText .split (/ \s + / ).filter (Boolean );
97
-
98
- if (newWords .length > 0 ) {
99
- this .words .push (... newWords);
100
- if (! this .typingTimer ) {
101
- this .streamNextWord ();
102
- }
103
- }
104
-
105
- if (result .done ) {
106
- // this.finalDiff = result.diff;
107
- }
108
-
109
- this .lastResultText = newText;
110
- this .isStreaming = ! result .done ;
111
- }
112
-
113
- streamNextWord () {
114
- if (this .currentWordIndex === this .words .length ) {
115
- this .diff = this .compareText (
116
- this .args .model .selectedText ,
117
- this .suggestion ,
118
- { markLastWord: false }
119
- );
120
- }
121
-
122
- if (this .currentWordIndex < this .words .length ) {
123
- this .suggestion += this .words [this .currentWordIndex ] + " " ;
124
- this .diff = this .compareText (
125
- this .args .model .selectedText ,
126
- this .suggestion ,
127
- { markLastWord: true }
128
- );
129
-
130
- this .currentWordIndex ++ ;
131
- this .typingTimer = later (this , this .streamNextWord , WORD_TYPING_DELAY );
58
+ if (this .args .model .showResultAsDiff ) {
59
+ this .diffStreamer .updateResult (result, " result" );
132
60
} else {
133
- this .typingTimer = null ;
61
+ this .smoothStreamer . updateResult (result, " result " ) ;
134
62
}
135
63
}
136
64
137
65
@action
138
66
async suggestChanges () {
139
- // this.smoothStreamer.resetStreaming();
140
- this .diff = null ;
141
- this .suggestion = " " ;
142
- this .loading = true ;
143
- this .lastResultText = " " ;
144
- this .words = [];
145
- this .currentWordIndex = 0 ;
67
+ this .smoothStreamer .resetStreaming ();
68
+ this .diffStreamer .reset ();
146
69
147
70
try {
148
71
return await ajax (" /discourse-ai/ai-helper/stream_suggestion" , {
@@ -170,6 +93,13 @@ export default class ModalDiffModal extends Component {
170
93
this .suggestion
171
94
);
172
95
}
96
+
97
+ if (this .args .model .showResultAsDiff && this .diffStreamer .suggestion ) {
98
+ this .args .model .toolbarEvent .replaceText (
99
+ this .args .model .selectedText ,
100
+ this .diffStreamer .suggestion
101
+ );
102
+ }
173
103
}
174
104
175
105
<template >
@@ -189,20 +119,18 @@ export default class ModalDiffModal extends Component {
189
119
class ={{concatClass
190
120
" composer-ai-helper-modal__suggestion"
191
121
" streamable-content"
122
+ ( if this . isStreaming " streaming" )
123
+ ( if @ model.showResultAsDiff " inline-diff" )
192
124
}}
193
125
>
194
- {{!-- <CookText @rawText={{this.diff}} class="cooked" /> --}}
195
- {{htmlSafe this . diff}}
196
- {{!-- <div class="composer-ai-helper-modal__old-value">
197
- {{@model.selectedText}}
198
- {{!-- {{#if this.smoothStreamer.isStreaming}}
199
- <CookText
200
- @rawText={{this.smoothStreamer.renderedText}}
201
- class="cooked"
202
- />
126
+ {{#if @ model.showResultAsDiff }}
127
+ {{htmlSafe this . diffStreamer.diff}}
203
128
{{else }}
204
- {{#if this.diff}}
205
- {{htmlSafe this.diff}}
129
+ {{#if this . smoothStreamer.isStreaming }}
130
+ <CookText
131
+ @ rawText ={{this .smoothStreamer.renderedText }}
132
+ class =" cooked"
133
+ />
206
134
{{else }}
207
135
<div class =" composer-ai-helper-modal__old-value" >
208
136
{{@ model.selectedText }}
@@ -214,7 +142,7 @@ export default class ModalDiffModal extends Component {
214
142
/>
215
143
</div >
216
144
{{/if }}
217
- {{/if}} --}}
145
+ {{/if }}
218
146
</div >
219
147
{{/if }}
220
148
</div >
@@ -232,6 +160,7 @@ export default class ModalDiffModal extends Component {
232
160
{{else }}
233
161
<DButton
234
162
class =" btn-primary confirm"
163
+ @ disabled ={{this .isStreaming }}
235
164
@ action ={{this .triggerConfirmChanges }}
236
165
@ label =" discourse_ai.ai_helper.context_menu.confirm"
237
166
/>
0 commit comments