import React = require('react'); import './GPTPopup.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, observable } from 'mobx'; import { observer } from 'mobx-react'; import ReactLoading from 'react-loading'; import Typist from 'react-typist'; import { Doc } from '../../../../fields/Doc'; import { DocUtils, Docs } from '../../../documents/Documents'; import { Button, IconButton, Type } from 'browndash-components'; import { NumCast, StrCast } from '../../../../fields/Types'; import { CgClose } from 'react-icons/cg'; export enum GPTPopupMode { SUMMARY, EDIT, IMAGE, } interface GPTPopupProps {} @observer export class GPTPopup extends React.Component { static Instance: GPTPopup; @observable public visible: boolean = false; @action public setVisible = (vis: boolean) => { this.visible = vis; }; @observable public loading: boolean = false; @action public setLoading = (loading: boolean) => { this.loading = loading; }; @observable public text: string = ''; @action public setText = (text: string) => { this.text = text; }; @observable public imageUrls: string[] = []; @action public setImgUrls = (imgs: string[]) => { this.imageUrls = imgs; }; @observable public mode: GPTPopupMode = GPTPopupMode.SUMMARY; @action public setMode = (mode: GPTPopupMode) => { this.mode = mode; }; @observable public highlightRange: number[] = []; @action callSummaryApi = () => {}; @action callEditApi = () => {}; @action replaceText = (replacement: string) => {}; @observable private done: boolean = false; @action public setDone = (done: boolean) => { this.done = done; }; // change what can be a ref into a ref @observable private sidebarId: string = ''; @action public setSidebarId = (id: string) => { this.sidebarId = id; }; // pdfs and webpages @observable private targetAnchor: Doc | undefined; @action public setTargetAnchor = (anchor: Doc) => { this.targetAnchor = anchor; }; @observable private imgTargetDoc: Doc | undefined; @action public setImgTargetDoc = (anchor: Doc) => { this.imgTargetDoc = anchor; }; @observable private textAnchor: Doc | undefined; @action public setTextAnchor = (anchor: Doc) => { this.textAnchor = anchor; }; public addDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean = () => false; public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined; /** * Transfers the summarization text to a sidebar annotation text document. */ private transferToText = () => { const newDoc = Docs.Create.TextDocument(this.text.trim(), { _width: 200, _height: 50, _layout_fitWidth: true, _layout_autoHeight: true, }); this.addDoc(newDoc, this.sidebarId); if (this.targetAnchor) { DocUtils.MakeLink(newDoc, this.targetAnchor, { link_relationship: 'GPT Summary', }); } }; /** * Transfers the image urls to actual image docs */ private transferToImage = (source: string) => { console.log('Text Anchor', this.textAnchor); console.log('Whole doc anchor', this.imgTargetDoc); const textAnchor = this.textAnchor ?? this.imgTargetDoc; if (!textAnchor) return; const newDoc = Docs.Create.ImageDocument(source, { x: NumCast(textAnchor.x) + NumCast(textAnchor._width) + 10, y: NumCast(textAnchor.y), _height: 200, _width: 200, data_nativeWidth: 1024, data_nativeHeight: 1024, }); if (Doc.IsInMyOverlay(textAnchor)) { newDoc.overlayX = textAnchor.x; newDoc.overlayY = NumCast(textAnchor.y) + NumCast(textAnchor._height); Doc.AddToMyOverlay(newDoc); } else { this.addToCollection?.(newDoc); } // Create link between prompt and image DocUtils.MakeLink(textAnchor, newDoc, { link_relationship: 'Image Prompt' }); }; private getPreviewUrl = (source: string) => source.split('.').join('_m.'); constructor(props: GPTPopupProps) { super(props); GPTPopup.Instance = this; } componentDidUpdate = () => { if (this.loading) { this.setDone(false); } }; imageBox = () => { return (
{this.heading('GENERATED IMAGE')}
{this.imageUrls.map(rawSrc => (
dalle generation
))}
); }; summaryBox = () => ( <>
{this.heading('SUMMARY')}
{!this.loading && (!this.done ? ( { setTimeout(() => { this.setDone(true); }, 500); }}> {this.text} ) : ( this.text ))}
{!this.loading && (
{this.done ? ( <> } color={StrCast(Doc.UserDoc().userVariantColor)} />
)} )} ); editBox = () => { const hr = this.highlightRange; return ( <>
{this.heading('TEXT EDIT SUGGESTIONS')}
{hr && (
{this.text.slice(0, hr[0])} {this.text.slice(hr[0], hr[1])} {this.text.slice(hr[1])}
)}
{hr && !this.loading && ( <>
<>
{this.aiWarning()} )} ); }; aiWarning = () => this.done ? (
AI generated responses can contain inaccurate or misleading content.
) : ( <> ); heading = (headingText: string) => (
{this.loading ? : } onClick={() => this.setVisible(false)} />}
); render() { return (
{this.mode === GPTPopupMode.SUMMARY ? this.summaryBox() : this.mode === GPTPopupMode.IMAGE ? this.imageBox() : this.editBox()}
); } }