From 3f6a168b2916ccac707cf5ea1e4ef898a470d7d1 Mon Sep 17 00:00:00 2001 From: bobzel Date: Thu, 13 Feb 2025 23:27:42 -0500 Subject: lots of cleanup in GPTpopup. --- src/client/views/pdf/GPTPopup/GPTPopup.scss | 45 +++++++++-------------------- 1 file changed, 13 insertions(+), 32 deletions(-) (limited to 'src/client/views/pdf/GPTPopup/GPTPopup.scss') diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 0247dc10c..9cf318dc0 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -5,7 +5,7 @@ $lightgrey: #ececec; $button: #5b97ff; $highlightedText: #82e0ff; -.summary-box { +.gptPopup-summary-box { position: fixed; top: 115px; left: 75px; @@ -35,7 +35,7 @@ $highlightedText: #82e0ff; right: 0; bottom: 0; cursor: se-resize; - } + } .summary-heading { display: flex; @@ -63,12 +63,12 @@ $highlightedText: #82e0ff; cursor: pointer; } - .content-wrapper { + .gptPopup-content-wrapper { padding-top: 10px; min-height: 50px; // max-height: 150px; overflow-y: auto; - height: 100% + height: 100%; } .btns-wrapper-gpt { @@ -78,7 +78,7 @@ $highlightedText: #82e0ff; align-items: center; flex-direction: column; - .inputWrapper{ + .inputWrapper { display: flex; justify-content: center; align-items: center; @@ -87,17 +87,15 @@ $highlightedText: #82e0ff; bottom: 0; width: 100%; background-color: white; - - } - .searchBox-input{ + .searchBox-input { height: 40px; border-radius: 10px; position: absolute; bottom: 10px; border-color: #5b97ff; - width: 90% + width: 90%; } .chat-wrapper { @@ -106,52 +104,41 @@ $highlightedText: #82e0ff; width: 100%; max-height: calc(100vh - 80px); overflow-y: auto; - padding-bottom: 60px; + padding-bottom: 60px; } - + .chat-bubbles { margin-top: 20px; display: flex; flex-direction: column; flex-grow: 1; } - + .chat-bubble { padding: 10px; margin-bottom: 10px; border-radius: 10px; max-width: 60%; } - + .user-message { background-color: #283d53; align-self: flex-end; color: whitesmoke; } - + .chat-message { background-color: #367ae7; align-self: flex-start; - color:whitesmoke; + color: whitesmoke; } - - - .summarizing { display: flex; align-items: center; } - - - - - - } - - .text-btn { &:hover { background-color: $button; @@ -198,18 +185,12 @@ $highlightedText: #82e0ff; color: #666; } - - - - @keyframes spin { to { transform: rotate(360deg); } } - - .image-content-wrapper { display: flex; flex-direction: column; -- cgit v1.2.3-70-g09d2 From cf791104c0b1608e37c3cf2d25dac7f6f58a1b66 Mon Sep 17 00:00:00 2001 From: bobzel Date: Tue, 18 Feb 2025 09:01:44 -0500 Subject: css fixes for gptPopup + close button --- src/client/util/SnappingManager.ts | 3 + src/client/views/MainView.tsx | 3 +- src/client/views/OverlayView.scss | 13 ++-- src/client/views/OverlayView.tsx | 18 ++++-- src/client/views/ScriptBox.tsx | 1 - src/client/views/global/globalScripts.ts | 8 +-- .../views/nodes/formattedText/FormattedTextBox.tsx | 4 +- src/client/views/pdf/GPTPopup/GPTPopup.scss | 69 ++++++++++------------ src/client/views/pdf/GPTPopup/GPTPopup.tsx | 62 ++++++++++--------- 9 files changed, 98 insertions(+), 83 deletions(-) (limited to 'src/client/views/pdf/GPTPopup/GPTPopup.scss') diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts index 2a150dc5a..9d8a41844 100644 --- a/src/client/util/SnappingManager.ts +++ b/src/client/util/SnappingManager.ts @@ -32,6 +32,7 @@ export class SnappingManager { @observable _hideDecorations: boolean = false; @observable _keepGestureMode: boolean = false; // for whether primitive selection enters a one-shot or persistent mode @observable _inkShape: Gestures | undefined = undefined; + @observable _chatVisible: boolean = false; private constructor() { SnappingManager._manager = this; @@ -66,6 +67,7 @@ export class SnappingManager { public static get HideDecorations(){ return this.Instance._hideDecorations; } // prettier-ignore public static get KeepGestureMode(){ return this.Instance._keepGestureMode; } // prettier-ignore public static get InkShape() { return this.Instance._inkShape; } // prettier-ignore + public static get ChatVisible() { return this.Instance._chatVisible; } // prettier-ignore public static SetLongPress = (press: boolean) => runInAction(() => {this.Instance._longPress = press}); // prettier-ignore public static SetShiftKey = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore @@ -85,6 +87,7 @@ export class SnappingManager { public static SetHideDecorations= (state:boolean) =>runInAction(() => {this.Instance._hideDecorations = state}); // prettier-ignore public static SetKeepGestureMode= (state:boolean) =>runInAction(() => {this.Instance._keepGestureMode = state}); // prettier-ignore public static SetInkShape = (shape?:Gestures)=>runInAction(() => {this.Instance._inkShape = shape}); // prettier-ignore + public static SetChatVisible = (vis:boolean) =>runInAction(() => {this.Instance._chatVisible = vis}); // prettier-ignore public static userColor: string | undefined; public static userVariantColor: string | undefined; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index d748b70ae..195b1c572 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -78,6 +78,7 @@ import { AnchorMenu } from './pdf/AnchorMenu'; import { GPTPopup } from './pdf/GPTPopup/GPTPopup'; import { SmartDrawHandler } from './smartdraw/SmartDrawHandler'; import { TopBar } from './topbar/TopBar'; +import { OverlayView } from './OverlayView'; // eslint-disable-next-line @typescript-eslint/no-require-imports const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore @@ -168,6 +169,7 @@ export class MainView extends ObservableReactComponent { mainDocViewHeight = () => this._dashUIHeight - this.headerBarDocHeight(); componentDidMount() { + OverlayView.Instance.addWindow(, { x: 400, y: 200, width: 500, height: 400, title: 'GPT', backgroundColor: 'transparent', isHidden: () => !SnappingManager.ChatVisible, onClick: () => SnappingManager.SetChatVisible(false) }); // Utils.TraceConsoleLog(); reaction( // when a multi-selection occurs, remove focus from all active elements to allow keyboad input to go only to global key manager to act upon selection @@ -1154,7 +1156,6 @@ export class MainView extends ObservableReactComponent { {this.snapLines} - diff --git a/src/client/views/OverlayView.scss b/src/client/views/OverlayView.scss index 33a297fd4..f4998efa1 100644 --- a/src/client/views/OverlayView.scss +++ b/src/client/views/OverlayView.scss @@ -4,7 +4,7 @@ top: 0; width: 100vw; height: 100vh; - z-index: 1001; // shouold be greater than LightboxView's z-index so that link lines and the presentation mini player appear + z-index: 2002; // shouold be greater than LightboxView's z-index so that link lines and the presentation mini player appear /* background-color: pink; */ user-select: none; } @@ -26,27 +26,30 @@ } .overlayWindow-titleBar { - flex: 0 1 30px; + flex: 0 1 20px; background: darkslategray; color: whitesmoke; text-align: center; cursor: move; + z-index: 1; } .overlayWindow-content { flex: 1 1 auto; display: flex; flex-direction: column; + z-index: 0; } .overlayWindow-closeButton { float: right; - height: 30px; - width: 30px; + height: 20px; + width: 20px; + padding: 0; + background-color: inherit; } .overlayWindow-resizeDragger { - background-color: rgb(0, 0, 0); position: absolute; right: 0px; bottom: 0px; diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx index 5e9677b45..20931fc3d 100644 --- a/src/client/views/OverlayView.tsx +++ b/src/client/views/OverlayView.tsx @@ -18,6 +18,7 @@ import { ObservableReactComponent } from './ObservableReactComponent'; import './OverlayView.scss'; import { DefaultStyleProvider, returnEmptyDocViewList } from './StyleProvider'; import { DocumentView, DocumentViewInternal } from './nodes/DocumentView'; +import { SnappingManager } from '../util/SnappingManager'; export type OverlayDisposer = () => void; @@ -27,12 +28,17 @@ export type OverlayElementOptions = { width?: number; height?: number; title?: string; + onClick?: (e: React.MouseEvent) => void; + isHidden?: () => boolean; + backgroundColor?: string; }; export interface OverlayWindowProps { children: JSX.Element; overlayOptions: OverlayElementOptions; - onClick: () => void; + onClick: (e: React.MouseEvent) => void; + isHidden?: () => boolean; + backgroundColor?: string; } @observer @@ -93,15 +99,17 @@ export class OverlayWindow extends ObservableReactComponent render() { return ( -
-
+
+
{this._props.overlayOptions.title || 'Untitled'}
{this.props.children}
-
+
); } @@ -166,7 +174,7 @@ export class OverlayView extends ObservableReactComponent { if (index !== -1) this._elements.splice(index, 1); }); const wincontents = ( - remove(wincontents)} key={Utils.GenerateGuid()} overlayOptions={options}> + remove(wincontents))} key={Utils.GenerateGuid()} overlayOptions={options}> {contents} ); diff --git a/src/client/views/ScriptBox.tsx b/src/client/views/ScriptBox.tsx index 9c36e6d26..d05b0a6b6 100644 --- a/src/client/views/ScriptBox.tsx +++ b/src/client/views/ScriptBox.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/require-default-props */ import { action, makeObservable, observable } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts index 790ebeabe..2bc0e3338 100644 --- a/src/client/views/global/globalScripts.ts +++ b/src/client/views/global/globalScripts.ts @@ -223,13 +223,13 @@ ScriptingGlobals.add(function showFreeform( setDoc: (doc: Doc, dv: DocumentView) => { doc[Doc.LayoutFieldKey(doc)+"_sort_desc"] = true; }, }], ['toggle-chat', { - checkResult: (doc: Doc) => GPTPopup.Instance.Visible, + checkResult: (doc: Doc) => SnappingManager.ChatVisible, setDoc: (doc: Doc, dv: DocumentView) => { - if (GPTPopup.Instance.Visible){ + if (SnappingManager.ChatVisible){ doc[Doc.LayoutFieldKey(doc)+"_sort"] = ''; - GPTPopup.Instance.setVisible(false); + SnappingManager.SetChatVisible(false); } else { - GPTPopup.Instance.setVisible(true); + SnappingManager.SetChatVisible(true); GPTPopup.Instance.setMode(GPTPopupMode.GPT_MENU); } }, diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 6960247e9..3abb39ff2 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -977,7 +977,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent this.generateImage(), icon: 'star' }); + optionItems.push({ description: `Generate Dall-E Image`, event: this.generateImage, icon: 'star' }); // optionItems.push({ description: `Make AI Flashcards`, event: () => this.makeAIFlashcards(), icon: 'lightbulb' }); optionItems.push({ description: `Ask GPT-3`, event: this.askGPT, icon: 'lightbulb' }); this._props.renderDepth && @@ -1061,7 +1061,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent { + generateImage = () => { GPTPopup.Instance?.setTextAnchor(this.getAnchor(false)); GPTPopup.Instance.generateImage((this.dataDoc.text as RichTextField)?.Text, this.Document, this._props.addDocument); }; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 9cf318dc0..0b832f64c 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -4,19 +4,23 @@ $greyborder: #d3d3d3; $lightgrey: #ececec; $button: #5b97ff; $highlightedText: #82e0ff; +$inputHeight: 60px; +$headingHeight: 32px; .gptPopup-summary-box { position: fixed; top: 115px; left: 75px; - width: 250px; - height: 200px; - min-height: 200px; - min-width: 180px; - + width: 100%; + height: 100%; + top: 0; + left: 0; + pointer-events: none; + border-top: solid gray 20px; border-radius: 16px; padding: 16px; padding-bottom: 0; + padding-top: 0px; z-index: 999; display: flex; flex-direction: column; @@ -24,17 +28,12 @@ $highlightedText: #82e0ff; background-color: #ffffff; box-shadow: 0 2px 5px #7474748d; color: $textgrey; - resize: both; /* Allows resizing */ - overflow: auto; - - .resize-handle { - width: 10px; - height: 10px; - background: #ccc; - position: absolute; - right: 0; - bottom: 0; - cursor: se-resize; + + .gptPopup-sortBox { + display: flex; + flex-direction: column; + height: calc(100% - $inputHeight - $headingHeight); + pointer-events: all; } .summary-heading { @@ -42,7 +41,7 @@ $highlightedText: #82e0ff; justify-content: space-between; align-items: center; border-bottom: 1px solid $greyborder; - padding-bottom: 5px; + height: $headingHeight; .summary-text { font-size: 12px; @@ -66,28 +65,17 @@ $highlightedText: #82e0ff; .gptPopup-content-wrapper { padding-top: 10px; min-height: 50px; - // max-height: 150px; - overflow-y: auto; - height: 100%; + height: calc(100% - 32px); } - .btns-wrapper-gpt { - height: 100%; + .inputWrapper { display: flex; justify-content: center; align-items: center; - flex-direction: column; - - .inputWrapper { - display: flex; - justify-content: center; - align-items: center; - height: 60px; - position: absolute; - bottom: 0; - width: 100%; - background-color: white; - } + height: $inputHeight; + background-color: white; + width: 100%; + pointer-events: all; .searchBox-input { height: 40px; @@ -97,14 +85,21 @@ $highlightedText: #82e0ff; border-color: #5b97ff; width: 90%; } + } + .btns-wrapper-gpt { + height: 100%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; .chat-wrapper { display: flex; flex-direction: column; width: 100%; - max-height: calc(100vh - 80px); + height: 100%; overflow-y: auto; - padding-bottom: 60px; + padding-right: 5px; } .chat-bubbles { @@ -194,7 +189,7 @@ $highlightedText: #82e0ff; .image-content-wrapper { display: flex; flex-direction: column; - align-items: flex-start; + align-items: center; gap: 8px; padding-bottom: 16px; diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index f09d786d0..72381cfad 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -3,7 +3,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, makeObservable, observable, reaction } from 'mobx'; import { observer } from 'mobx-react'; import * as React from 'react'; -import { CgClose, CgCornerUpLeft } from 'react-icons/cg'; +import { CgCornerUpLeft } from 'react-icons/cg'; import ReactLoading from 'react-loading'; import { TypeAnimation } from 'react-type-animation'; import { ClientUtils } from '../../../../ClientUtils'; @@ -108,8 +108,6 @@ export class GPTPopup extends ObservableReactComponent { @observable private _mode: GPTPopupMode = GPTPopupMode.SUMMARY; @action public setMode = (mode: GPTPopupMode) => (this._mode = mode); - @observable public Visible: boolean = false; - @action public setVisible = (vis: boolean) => (this.Visible = vis); onQuizRandom?: () => void; onGptResponse?: (sortResult: string, questionType: GPTTypeStyle, tag?: string) => void; @@ -233,10 +231,10 @@ export class GPTPopup extends ObservableReactComponent { */ generateImage = (imgDesc: string, imgTarget: Doc, addToCollection?: (doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) => { this._imgTargetDoc = imgTarget; + SnappingManager.SetChatVisible(true); this.addDoc = addToCollection; this.setImgUrls([]); this.setMode(GPTPopupMode.IMAGE); - this.setVisible(true); this.setGptProcessing(true); this._imageDescription = imgDesc; @@ -259,8 +257,8 @@ export class GPTPopup extends ObservableReactComponent { * @param text the text to summarizz */ generateSummary = (text: string) => { + SnappingManager.SetChatVisible(true); this._textToSummarize = text; - this.setVisible(true); this.setMode(GPTPopupMode.SUMMARY); this.setGptProcessing(true); return gptAPICall(text, GPTCallType.SUMMARY) @@ -274,7 +272,6 @@ export class GPTPopup extends ObservableReactComponent { * this.dataJson in the popup. */ generateDataAnalysis = () => { - this.setVisible(true); this.setGptProcessing(true); return gptAPICall(this._dataJson, GPTCallType.DATA, this._dataChatPrompt) .then(res => { @@ -398,7 +395,7 @@ export class GPTPopup extends ObservableReactComponent { } }; - gptUserInput = (isUserPrompt: boolean) => ( + gptUserInput = () => (
@@ -412,6 +409,15 @@ export class GPTPopup extends ObservableReactComponent {
+ + ); + + promptBox = (isUserPrompt: boolean) => ( + <> +
+ {this.heading(isUserPrompt ? 'ASK' : 'QUIZ')} + {this.gptUserInput()} +
{ placeholder={`${isUserPrompt ? 'Have ChatGPT sort, tag, define, or filter your documents for you!' : 'Describe/answer the selected document!'}`} />
- + ); - promptBox = (isUserPrompt: boolean) => ( -
- {this.heading(isUserPrompt ? 'SORTING' : 'QUIZ')} - {this._mode === GPTPopupMode.GPT_MENU ? this.gptMenu() : this.gptUserInput(isUserPrompt)} + menuBox = () => ( +
+ {this.heading('CHOOSE')} + {this.gptMenu()}
); imageBox = () => ( -
+
{this.heading('GENERATED IMAGE')}
{this._imgUrls.map((rawSrc, i) => ( -
-
- dalle generation + <> +
+
+ dalle generation +
-
+ ))}
{this._gptProcessing ? null : ( @@ -461,7 +469,7 @@ export class GPTPopup extends ObservableReactComponent { summaryBox = () => ( <> -
+
{this.heading('SUMMARY')}
{!this._gptProcessing && @@ -481,7 +489,7 @@ export class GPTPopup extends ObservableReactComponent { {!this._gptProcessing && ( -
+
{this._stopAnimatingResponse ? ( <> this.generateSummary(this._textToSummarize + ' ')} icon={} color={StrCast(SettingsManager.userVariantColor)} /> @@ -571,19 +579,18 @@ export class GPTPopup extends ObservableReactComponent { ) : ( <> - {(this._mode === GPTPopupMode.USER_PROMPT || this._mode === GPTPopupMode.QUIZ_RESPONSE) && ( - } onClick={() => (this._mode = GPTPopupMode.GPT_MENU)} style={{ right: '50px', position: 'absolute' }} /> - )} this._collectionContext && Doc.setDocFilter(this._collectionContext, 'tags', '#chat', 'remove')} /> - } onClick={() => this.setVisible(false)} /> + {(this._mode === GPTPopupMode.USER_PROMPT || this._mode === GPTPopupMode.QUIZ_RESPONSE) && ( + } onClick={() => (this._mode = GPTPopupMode.GPT_MENU)} /> + )} )} @@ -591,20 +598,19 @@ export class GPTPopup extends ObservableReactComponent { render() { return ( -
+
{(() => { //prettier-ignore switch (this._mode) { - case GPTPopupMode.GPT_MENU: - case GPTPopupMode.USER_PROMPT: + case GPTPopupMode.USER_PROMPT: case GPTPopupMode.QUIZ_RESPONSE: return this.promptBox(this._mode === GPTPopupMode.USER_PROMPT); + case GPTPopupMode.GPT_MENU: return this.menuBox(); case GPTPopupMode.SUMMARY: return this.summaryBox(); case GPTPopupMode.DATA: return this.dataAnalysisBox(); case GPTPopupMode.IMAGE: return this.imageBox(); default: return null; } })()} -
); } -- cgit v1.2.3-70-g09d2 From 23db3e08831c9083bee9b95a0156bb5bb5124312 Mon Sep 17 00:00:00 2001 From: bobzel Date: Wed, 19 Feb 2025 16:29:22 -0500 Subject: added drop shadow to overlay windows. --- src/client/views/OverlayView.scss | 1 + src/client/views/pdf/GPTPopup/GPTPopup.scss | 3 +- src/client/views/pdf/GPTPopup/GPTPopup.tsx | 44 ++++++++++++++++++++--------- 3 files changed, 32 insertions(+), 16 deletions(-) (limited to 'src/client/views/pdf/GPTPopup/GPTPopup.scss') diff --git a/src/client/views/OverlayView.scss b/src/client/views/OverlayView.scss index f4998efa1..2e8621b5b 100644 --- a/src/client/views/OverlayView.scss +++ b/src/client/views/OverlayView.scss @@ -17,6 +17,7 @@ top: 0; left: 0; pointer-events: all; + box-shadow: black 5px 5px 5px; } .overlayWindow-outerDiv, diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.scss b/src/client/views/pdf/GPTPopup/GPTPopup.scss index 0b832f64c..c8903e09f 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.scss +++ b/src/client/views/pdf/GPTPopup/GPTPopup.scss @@ -80,8 +80,7 @@ $headingHeight: 32px; .searchBox-input { height: 40px; border-radius: 10px; - position: absolute; - bottom: 10px; + position: relative; border-color: #5b97ff; width: 90%; } diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx index cb3e9b2d7..b7eaf2674 100644 --- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx +++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx @@ -22,6 +22,8 @@ import { ChatSortField, docSortings } from '../../collections/CollectionSubView' import { DocumentView } from '../../nodes/DocumentView'; import { AnchorMenu } from '../AnchorMenu'; import './GPTPopup.scss'; +import { DictationButton } from '../../DictationButton'; +import { AiOutlineSend } from 'react-icons/ai'; export enum GPTPopupMode { SUMMARY, // summary of seleted document text @@ -37,6 +39,7 @@ export class GPTPopup extends ObservableReactComponent { // eslint-disable-next-line no-use-before-define static Instance: GPTPopup; static ChatTag = '#chat'; // tag used by GPT popup to filter docs + private _askDictation: DictationButton | null = null; private _messagesEndRef: React.RefObject; private _correlatedColumns: string[] = []; private _dataChatPrompt: string | undefined = undefined; @@ -101,9 +104,9 @@ export class GPTPopup extends ObservableReactComponent { @observable private _collectionContext: Doc | undefined = undefined; @action setCollectionContext = (doc: Doc | undefined) => (this._collectionContext = doc); @observable private _userPrompt: string = ''; - @action setUserPrompt = (e: React.ChangeEvent) => (this._userPrompt = e.target.value); + @action setUserPrompt = (e: string) => (this._userPrompt = e); @observable private _quizAnswer: string = ''; - @action setQuizAnswer = (e: React.ChangeEvent) => (this._quizAnswer = e.target.value); + @action setQuizAnswer = (e: string) => (this._quizAnswer = e); @observable private _stopAnimatingResponse: boolean = false; @action private setStopAnimatingResponse = (done: boolean) => (this._stopAnimatingResponse = done); @@ -371,22 +374,26 @@ export class GPTPopup extends ObservableReactComponent { ); + callGpt = (isUserPrompt: boolean) => { + this.setGptProcessing(true); + if (isUserPrompt) { + this._conversationArray.push(this._userPrompt); + return this.generateUserPromptResponse(this._userPrompt).then(action(() => (this._userPrompt = ''))); + } + this._conversationArray.push(this._quizAnswer); + return this.generateQuizAnswerAnalysis(DocumentView.SelectedDocs().lastElement(), this._quizAnswer).then(action(() => (this._quizAnswer = ''))); + }; + @action handleKeyPress = async (e: React.KeyboardEvent, isUserPrompt: boolean) => { + this._askDictation?.stopDictation(); if (e.key === 'Enter') { e.stopPropagation(); - this.setGptProcessing(true); - if (isUserPrompt) { - this._conversationArray.push(this._userPrompt); - await this.generateUserPromptResponse(this._userPrompt).then(action(() => (this._userPrompt = ''))); - } else { - this._conversationArray.push(this._quizAnswer); - await this.generateQuizAnswerAnalysis(DocumentView.SelectedDocs().lastElement(), this._quizAnswer).then(action(() => (this._quizAnswer = ''))); - } - this.setGptProcessing(false); - - this.scrollToBottom(); + this.callGpt(isUserPrompt).then(() => { + this.setGptProcessing(false); + this.scrollToBottom(); + }); } }; @@ -418,11 +425,20 @@ export class GPTPopup extends ObservableReactComponent { className="searchBox-input" value={isUserPrompt ? this._userPrompt : this._quizAnswer} // Controlled input autoComplete="off" - onChange={isUserPrompt ? this.setUserPrompt : this.setQuizAnswer} + onChange={e => (isUserPrompt ? this.setUserPrompt : this.setQuizAnswer)(e.target.value)} onKeyDown={e => this.handleKeyPress(e, isUserPrompt)} type="text" placeholder={`${isUserPrompt ? 'Have ChatGPT sort, tag, define, or filter your documents for you!' : 'Describe/answer the selected document!'}`} /> +