@@ -7,26 +7,29 @@ import didUpdate from "@ember/render-modifiers/modifiers/did-update";
77import willDestroy from " @ember/render-modifiers/modifiers/will-destroy" ;
88import { cancel , later } from " @ember/runloop" ;
99import { service } from " @ember/service" ;
10+ import { not } from " truth-helpers" ;
1011import CookText from " discourse/components/cook-text" ;
1112import DButton from " discourse/components/d-button" ;
13+ import DModal from " discourse/components/d-modal" ;
1214import concatClass from " discourse/helpers/concat-class" ;
15+ import htmlClass from " discourse/helpers/html-class" ;
1316import { ajax } from " discourse/lib/ajax" ;
1417import { shortDateNoYear } from " discourse/lib/formatter" ;
1518import dIcon from " discourse-common/helpers/d-icon" ;
1619import i18n from " discourse-common/helpers/i18n" ;
1720import { bind } from " discourse-common/utils/decorators" ;
1821import I18n from " discourse-i18n" ;
19- import DMenu from " float-kit/components/d-menu" ;
2022import DTooltip from " float-kit/components/d-tooltip" ;
2123import AiSummarySkeleton from " ../../components/ai-summary-skeleton" ;
2224
2325const STREAMED_TEXT_SPEED = 15 ;
2426
25- export default class AiSummaryBox extends Component {
27+ export default class AiSummaryModal extends Component {
2628 @service siteSettings;
2729 @service messageBus;
2830 @service currentUser;
2931 @service site;
32+ @service modal;
3033
3134 @tracked text = " " ;
3235 @tracked summarizedOn = null ;
@@ -68,25 +71,20 @@ export default class AiSummaryBox extends Component {
6871 }
6972
7073 get topRepliesSummaryEnabled () {
71- return this .args .outletArgs .postStream .summary ;
74+ return this .args .model .postStream .summary ;
7275 }
7376
7477 get topicId () {
75- return this .args .outletArgs .topic .id ;
78+ return this .args .model .topic .id ;
7679 }
7780
7881 get baseSummarizationURL () {
7982 return ` /discourse-ai/summarization/t/${ this .topicId } ` ;
8083 }
8184
8285 @bind
83- subscribe (unsubscribe , [topicId ]) {
84- const sameTopicId = this .args .outletArgs .topic .id === topicId;
85-
86- if (unsubscribe && this ._channel && ! sameTopicId) {
87- this .unsubscribe ();
88- }
89- const channel = ` /discourse-ai/summaries/topic/${ this .args .outletArgs .topic .id } ` ;
86+ subscribe () {
87+ const channel = ` /discourse-ai/summaries/topic/${ this .args .model .topic .id } ` ;
9088 this ._channel = channel;
9189 this .messageBus .subscribe (channel, this ._updateSummary );
9290 }
@@ -206,100 +204,66 @@ export default class AiSummaryBox extends Component {
206204 }
207205
208206 @action
209- async onClose () {
210- await this .dMenu . close ();
211- this .unsubscribe ();
207+ handleClose () {
208+ this .modal . triggerElement = null ; // prevent refocus of trigger, which changes scroll position
209+ this .args . closeModal ();
212210 }
213211
214212 <template >
215- {{#if @ outletArgs.topic.summarizable }}
216- <div
217- class =" ai-summarization-button"
218- {{didInsert this . subscribe}}
219- {{didUpdate this . subscribe @ outletArgs.topic.id}}
220- {{willDestroy this . unsubscribe}}
221- >
222- <DMenu
223- @ onShow ={{this .generateSummary }}
224- @ arrow ={{ false }}
225- @ identifier =" topic-map__ai-summary"
226- @ onRegisterApi ={{this .onRegisterApi }}
227- @ interactive ={{ true }}
228- @ triggers =" click"
229- @ placement =" left"
230- @ modalForMobile ={{ true }}
231- @ groupIdentifier =" topic-map"
232- @ inline ={{ true }}
233- @ label ={{i18n " summary.buttons.generate" }}
234- @ title ={{i18n " summary.buttons.generate" }}
235- @ icon =" discourse-sparkles"
236- @ triggerClass =" ai-topic-summarization"
237- @ closeOnClickOutside ={{ false }}
238- >
239- <: content >
240- <div class =" ai-summary-container" >
241- <header class =" ai-summary__header" >
242- <h3 >{{i18n " discourse_ai.summarization.topic.title" }} </h3 >
243- {{#if this . site.desktopView }}
244- <DButton
245- @ title =" discourse_ai.summarization.topic.close"
246- @ action ={{this .onClose }}
247- @ icon =" times"
248- class =" btn-transparent ai-summary__close"
249- />
250- {{/if }}
251- </header >
252-
253- <article
254- class ={{concatClass
255- " ai-summary-box"
256- " streamable-content"
257- ( if this . isStreaming " streaming" )
258- }}
259- >
260- {{#if this . loading }}
261- <AiSummarySkeleton />
262- {{else }}
263- <div class =" generated-summary cooked" >
264- <CookText @ rawText ={{this .streamedText }} />
265- </div >
266- {{#if this . summarizedOn }}
267- <div class =" summarized-on" >
268- <p >
269- {{i18n " summary.summarized_on" date =this . summarizedOn}}
270- <DTooltip @ placements ={{array " top-end" }} >
271- <: trigger >
272- {{dIcon " info-circle" }}
273- </: trigger >
274- <: content >
275- {{i18n
276- " summary.model_used"
277- model =this . summarizedBy
278- }}
279- </: content >
280- </DTooltip >
281- </p >
282- <div class =" outdated-summary" >
283- {{#if this . outdated }}
284- <p >{{this .outdatedSummaryWarningText }} </p >
285- {{/if }}
286- {{#if this . canRegenerate }}
287- <DButton
288- @ label =" summary.buttons.regenerate"
289- @ title =" summary.buttons.regenerate"
290- @ action ={{this .regenerateSummary }}
291- @ icon =" sync"
292- />
293- {{/if }}
294- </div >
295- </div >
296- {{/if }}
297- {{/if }}
298- </article >
299- </div >
300- </: content >
301- </DMenu >
302- </div >
303- {{/if }}
213+ <DModal
214+ @ title ={{i18n " discourse_ai.summarization.topic.title" }}
215+ @ closeModal ={{this .handleClose }}
216+ @ bodyClass =" ai-summary-modal__body"
217+ class =" ai-summary-modal"
218+ {{didInsert this . subscribe @ model.topic.id}}
219+ {{didUpdate this . subscribe @ model.topic.id}}
220+ {{willDestroy this . unsubscribe}}
221+ @ hideFooter ={{not this . summarizedOn}}
222+ >
223+ <: body >
224+ {{htmlClass " scrollable-modal" }}
225+ <div class =" ai-summary-container" {{didInsert this . generateSummary}} >
226+ <article
227+ class ={{concatClass
228+ " ai-summary-box"
229+ " streamable-content"
230+ ( if this . isStreaming " streaming" )
231+ }}
232+ >
233+ {{#if this . loading }}
234+ <AiSummarySkeleton />
235+ {{else }}
236+ <div class =" generated-summary cooked" >
237+ <CookText @ rawText ={{this .streamedText }} />
238+ </div >
239+ {{/if }}
240+ </article >
241+ </div >
242+ </: body >
243+ <: footer >
244+ <p class =" summarized-on" >
245+ {{i18n " summary.summarized_on" date =this . summarizedOn}}
246+ <DTooltip @ placements ={{array " top-end" }} >
247+ <: trigger >
248+ {{dIcon " circle-info" }}
249+ </: trigger >
250+ <: content >
251+ {{i18n " summary.model_used" model =this . summarizedBy}}
252+ </: content >
253+ </DTooltip >
254+ </p >
255+ {{#if this . outdated }}
256+ <p class =" summary-outdated" >{{this .outdatedSummaryWarningText }} </p >
257+ {{/if }}
258+ {{#if this . canRegenerate }}
259+ <DButton
260+ @ label =" summary.buttons.regenerate"
261+ @ title =" summary.buttons.regenerate"
262+ @ action ={{this .regenerateSummary }}
263+ @ icon =" sync"
264+ />
265+ {{/if }}
266+ </: footer >
267+ </DModal >
304268 </template >
305269}
0 commit comments