import Component from "@glimmer/component"; import { tracked } from "@glimmer/tracking"; import { array } from "@ember/helper"; import { action } from "@ember/object"; import didInsert from "@ember/render-modifiers/modifiers/did-insert"; import willDestroy from "@ember/render-modifiers/modifiers/will-destroy"; import { service } from "@ember/service"; import DButton from "discourse/components/d-button"; import { ajax } from "discourse/lib/ajax"; import { shortDateNoYear } from "discourse/lib/formatter"; import { cook } from "discourse/lib/text"; import dIcon from "discourse-common/helpers/d-icon"; import i18n from "discourse-common/helpers/i18n"; import { bind } from "discourse-common/utils/decorators"; import I18n from "discourse-i18n"; import DMenu from "float-kit/components/d-menu"; import DTooltip from "float-kit/components/d-tooltip"; import AiSummarySkeleton from "../../components/ai-summary-skeleton"; export default class AiSummaryBox extends Component { @service siteSettings; @service messageBus; @service currentUser; @service site; @tracked text = ""; @tracked summarizedOn = null; @tracked summarizedBy = null; @tracked newPostsSinceSummary = null; @tracked outdated = false; @tracked canRegenerate = false; @tracked loading = false; get outdatedSummaryWarningText() { let outdatedText = I18n.t("summary.outdated"); if (!this.topRepliesSummaryEnabled && this.newPostsSinceSummary > 0) { outdatedText += " "; outdatedText += I18n.t("summary.outdated_posts", { count: this.newPostsSinceSummary, }); } return outdatedText; } get topRepliesSummaryEnabled() { return this.args.outletArgs.postStream.summary; } get topicId() { return this.args.outletArgs.topic.id; } get baseSummarizationURL() { return `/discourse-ai/summarization/t/${this.topicId}`; } @bind subscribe() { const channel = `/discourse-ai/summaries/topic/${this.args.outletArgs.topic.id}`; this.messageBus.subscribe(channel, this._updateSummary); } @bind unsubscribe() { this.messageBus.unsubscribe( "/discourse-ai/summaries/topic/*", this._updateSummary ); } @action generateSummary() { let fetchURL = this.baseSummarizationURL; if (this.currentUser) { fetchURL += `?stream=true`; } return this._requestSummary(fetchURL); } @action regenerateSummary() { let fetchURL = this.baseSummarizationURL; if (this.currentUser) { fetchURL += `?stream=true`; if (this.canRegenerate) { fetchURL += "&skip_age_check=true"; } } return this._requestSummary(fetchURL); } @action _requestSummary(url) { if (this.loading || (this.text && !this.canRegenerate)) { return; } this.loading = true; this.summarizedOn = null; return ajax(url).then((data) => { if (!this.currentUser) { data.done = true; this._updateSummary(data); } }); } @bind _updateSummary(update) { const topicSummary = update.ai_topic_summary; return cook(topicSummary.summarized_text) .then((cooked) => { this.text = cooked; this.loading = false; }) .then(() => { if (update.done) { this.summarizedOn = shortDateNoYear( moment(topicSummary.updated_at, "YYYY-MM-DD HH:mm:ss Z") ); this.summarizedBy = topicSummary.algorithm; this.newPostsSinceSummary = topicSummary.new_posts_since_summary; this.outdated = topicSummary.outdated; this.newPostsSinceSummary = topicSummary.new_posts_since_summary; this.canRegenerate = topicSummary.outdated && topicSummary.can_regenerate; } }); } @action onRegisterApi(api) { this.dMenu = api; } @action async onClose() { await this.dMenu.close(); this.unsubscribe(); } }