aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2023-10-19 02:14:16 -0400
committerSophie Zhang <sophie_zhang@brown.edu>2023-10-19 02:14:16 -0400
commit414abda35b79c2d670451df8938740bd891881e1 (patch)
tree17e7e56bbc8ad0baf17a78d718f161a10ad28f16 /src
parent1efba5a6a80cba09633426fc8cb42be4bf9b2e74 (diff)
fixed key events (chatbox)
Diffstat (limited to 'src')
-rw-r--r--src/client/apis/gpt/GPT.ts9
-rw-r--r--src/client/views/nodes/trails/PresBox.scss3
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx81
3 files changed, 74 insertions, 19 deletions
diff --git a/src/client/apis/gpt/GPT.ts b/src/client/apis/gpt/GPT.ts
index 66689f2f6..6806802f3 100644
--- a/src/client/apis/gpt/GPT.ts
+++ b/src/client/apis/gpt/GPT.ts
@@ -25,8 +25,13 @@ const configuration = new Configuration({
const openai = new OpenAIApi(configuration);
const gptTrailSlideCustomization = async (inputText: string) => {
- const prompt =
- 'We are adding customization to a slide in a presentation. Given a natural language input, translate it into a json with the required fields: [title, presentation_transition, presentation_effect, and config_zoom]. title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition to a slide. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. config zoom is a number from 0 to 1.0 indicating the percentage we should be zooming into the slide. If the input does not contain info a specific key, please set their value to null. Please only return the json with these keys and their values.';
+ let prompt =
+ 'We are adding customization to a slide in a presentation. Given a natural language input, translate it into a json with the required fields: [title, presentation_transition, presentation_movement, presentation_effect, config_zoom, presentation_effectDirection].';
+
+ prompt +=
+ 'title is the title/name of the slide. presentation_transition is a number in milliseconds for how long it should take to transition to a slide. presentation_movement is how the slide is moved onscreen. Its only possible values are: [none, center, zoom, pan, jump]. If the input contains zoom, make sure to set presentation_movement to zoom. presentation_effect is an effect applied to the slide when we transition to it. Its only possible values are: [None, Fade in, Flip, Rotate, Bounce, Roll]. presentation_effectDirection is what direction the slide comes in from. Its only possible values are: [Enter from left, Enter from right, Enter from bottom, Enter from Top, Enter from center]. config_zoom is a number from 0 to 1.0 indicating the percentage we should be zooming into the slide.';
+
+ prompt += 'If the input does not contain info a specific key, please set their value to null. Please only return the json with these keys and their values.';
try {
const response = await openai.createChatCompletion({
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
index 370b155fd..1b76a39ad 100644
--- a/src/client/views/nodes/trails/PresBox.scss
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -34,9 +34,6 @@
.pres-chatbox {
outline: none;
border: none;
- font-size: 16px;
- letter-spacing: 1px;
- color: #404040;
}
}
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 051a1fbfd..0d5edcd83 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -36,6 +36,7 @@ import { DocFocusOptions, DocumentView, OpenWhere, OpenWhereMod } from '../Docum
import { FieldView, FieldViewProps } from '../FieldView';
import { ScriptingBox } from '../ScriptingBox';
import './PresBox.scss';
+import ReactLoading from 'react-loading';
import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './PresEnums';
import { IconButton, Type } from 'browndash-components';
import { AiOutlineSend } from 'react-icons/ai';
@@ -112,10 +113,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable _forceKeyEvents: boolean = false;
// GPT
+ private _inputref: HTMLTextAreaElement | null = null;
@observable chatActive: boolean = false;
@observable chatInput: string = '';
public slideToModify: Doc | null = null;
@observable isRecording: boolean = false;
+ @observable isLoading: boolean = false;
@action
setChatInput = (input: string) => {
@@ -123,6 +126,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
};
@action
+ setIsLoading = (isLoading: boolean) => {
+ this.isLoading = isLoading;
+ };
+
+ @action
public setChatActive = (active: boolean) => {
this.chatActive = active;
};
@@ -272,6 +280,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
// GPT
recordDictation = () => {
+ this.setIsRecording(true);
+ this.setChatInput('');
DictationManager.Controls.listen({
interimHandler: this.setDictationContent,
continuous: { indefinite: false },
@@ -281,17 +291,38 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
});
};
- stopDictation = (abort: boolean) => DictationManager.Controls.stop(!abort);
+ stopDictation = (abort: boolean) => {
+ this.setIsRecording(false);
+ DictationManager.Controls.stop(!abort);
+ };
setDictationContent = (value: string) => {
this.setChatInput(value);
+ // // Get the current cursor position
+ // if (!this._inputref) return;
+ // const cursorPosition = this._inputref.selectionStart;
+ // const currentValue = this.chatInput;
+
+ // // split before and after
+ // const textBeforeCursor = currentValue.slice(0, cursorPosition);
+ // const textAfterCursor = currentValue.slice(cursorPosition);
+
+ // // insertion
+ // const updatedText = textBeforeCursor + value + textAfterCursor;
+
+ // // Update the textarea value
+ // this.setChatInput(updatedText);
+
+ // // set new cursor pos
+ // const newCursorPosition = cursorPosition + value.length;
+ // this._inputref.setSelectionRange(newCursorPosition, newCursorPosition);
};
@action
customizeWithGPT = async (input: string) => {
// const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect';
if (!this.slideToModify) return;
-
+ this.setIsLoading(true);
try {
const res = await gptTrailSlideCustomization(input);
if (typeof res === 'string') {
@@ -307,6 +338,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
} catch (err) {
console.error(err);
}
+ this.setIsLoading(false);
};
//TODO: al: it seems currently that tempMedia doesn't stop onslidechange after clicking the button; the time the tempmedia stop depends on the start & end time
@@ -1280,6 +1312,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@action
keyEvents = (e: KeyboardEvent) => {
if (e.target instanceof HTMLInputElement) return;
+ if (e.target instanceof HTMLTextAreaElement) return;
let handled = false;
const anchorNode = document.activeElement as HTMLDivElement;
if (anchorNode && anchorNode.className?.includes('lm_title')) return;
@@ -2742,17 +2775,31 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
{this.chatActive && (
<div className="presBox-chatbox">
<div style={{ alignSelf: 'flex-end' }}>
- <IconButton
- type={Type.PRIM}
- color={StrCast(Doc.UserDoc().userVariantColor)}
- tooltip="Close"
- icon={<BiX size={'16px'} />}
- onClick={() => {
- this.setChatActive(false);
- }}
- />
+ {this.isLoading ? (
+ <ReactLoading type="spin" color={StrCast(Doc.UserDoc().userVariantColor)} width={14} height={14} />
+ ) : (
+ <IconButton
+ type={Type.PRIM}
+ color={StrCast(Doc.UserDoc().userVariantColor)}
+ tooltip="Close"
+ icon={<BiX size={'16px'} />}
+ onClick={() => {
+ this.setChatActive(false);
+ }}
+ />
+ )}
</div>
+ {/* <div
+ contentEditable={true}
+ onInput={e => {
+ const newContent = e.currentTarget.innerHTML;
+ console.log('content', newContent);
+ this.setChatInput(newContent);
+ }}>
+ {this.chatInput}
+ </div> */}
<TextareaAutosize
+ ref={r => (this._inputref = r)}
minRows={3}
placeholder="Customize..."
className="pres-chatbox"
@@ -2761,10 +2808,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
onChange={e => {
this.setChatInput(e.target.value);
}}
- onSelect={e => {
+ // onSelect={e => {
+ // this.stopDictation(true);
+ // }}
+ onKeyDown={e => {
+ // if (e.key === 'Enter') {
+ // this.customizeWithGPT(this.chatInput);
+ // }
this.stopDictation(true);
+ e.stopPropagation();
}}
- onKeyDown={e => e.stopPropagation()}
onKeyPress={e => e.stopPropagation()}
onPointerDown={e => e.stopPropagation()}
onClick={e => e.stopPropagation()}
@@ -2787,7 +2840,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
/>
<IconButton
type={Type.TERT}
- color={StrCast(Doc.UserDoc().userVariantColor)}
+ color={!this.isLoading ? StrCast(Doc.UserDoc().userVariantColor) : '#7c7c7c'}
tooltip="Send"
icon={<AiOutlineSend size={'16px'} />}
onClick={() => {