@@ -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,72 @@ export default class AiSummaryBox extends Component {
206204 }
207205
208206 @action
209- async onClose () {
210- await this .dMenu .close ();
211- this .unsubscribe ();
207+ handleDidInsert () {
208+ this .subscribe ();
209+ this .generateSummary ();
210+ }
211+
212+ @action
213+ handleClose () {
214+ this .modal .triggerElement = null ; // prevent refocus of trigger, which changes scroll position
215+ this .args .closeModal ();
212216 }
213217
214218 <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 }}
219+ <DModal
220+ @ title ={{i18n " discourse_ai.summarization.topic.title" }}
221+ @ closeModal ={{this .handleClose }}
222+ @ bodyClass =" ai-summary-modal__body"
223+ class =" ai-summary-modal"
224+ {{didInsert this . handleDidInsert}}
225+ {{didUpdate this . subscribe @ model.topic.id}}
226+ {{willDestroy this . unsubscribe}}
227+ @ hideFooter ={{not this . summarizedOn}}
228+ >
229+ <: body >
230+ {{htmlClass " scrollable-modal" }}
231+ <div class =" ai-summary-container" >
232+ <article
233+ class ={{concatClass
234+ " ai-summary-box"
235+ " streamable-content"
236+ ( if this . isStreaming " streaming" )
237+ }}
238+ >
239+ {{#if this . loading }}
240+ <AiSummarySkeleton />
241+ {{else }}
242+ <div class =" generated-summary cooked" >
243+ <CookText @ rawText ={{this .streamedText }} />
244+ </div >
245+ {{/if }}
246+ </article >
247+ </div >
248+ </: body >
249+ <: footer >
250+ <p class =" summarized-on" >
251+ {{i18n " summary.summarized_on" date =this . summarizedOn}}
252+ <DTooltip @ placements ={{array " top-end" }} >
253+ <: trigger >
254+ {{dIcon " info-circle" }}
255+ </: trigger >
256+ <: content >
257+ {{i18n " summary.model_used" model =this . summarizedBy}}
258+ </: content >
259+ </DTooltip >
260+ </p >
261+ {{#if this . outdated }}
262+ <p class =" summary-outdated" >{{this .outdatedSummaryWarningText }} </p >
263+ {{/if }}
264+ {{#if this . canRegenerate }}
265+ <DButton
266+ @ label =" summary.buttons.regenerate"
267+ @ title =" summary.buttons.regenerate"
268+ @ action ={{this .regenerateSummary }}
269+ @ icon =" sync"
270+ />
271+ {{/if }}
272+ </: footer >
273+ </DModal >
304274 </template >
305275}
0 commit comments