aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/trails/PresBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/trails/PresBox.tsx')
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx71
1 files changed, 70 insertions, 1 deletions
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index ebf9c211c..051a1fbfd 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -40,6 +40,9 @@ import { PresEffect, PresEffectDirection, PresMovement, PresStatus } from './Pre
import { IconButton, Type } from 'browndash-components';
import { AiOutlineSend } from 'react-icons/ai';
import { gptTrailSlideCustomization } from '../../../apis/gpt/GPT';
+import { DictationManager } from '../../../util/DictationManager';
+import { BiMicrophone, BiX } from 'react-icons/bi';
+import TextareaAutosize from 'react-textarea-autosize';
export interface pinDataTypes {
scrollable?: boolean;
@@ -112,6 +115,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
@observable chatActive: boolean = false;
@observable chatInput: string = '';
public slideToModify: Doc | null = null;
+ @observable isRecording: boolean = false;
@action
setChatInput = (input: string) => {
@@ -123,6 +127,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
this.chatActive = active;
};
+ @action
+ public setIsRecording = (isRecording: boolean) => {
+ this.isRecording = isRecording;
+ };
+
@computed
get isTreeOrStack() {
return [CollectionViewType.Tree, CollectionViewType.Stacking].includes(StrCast(this.layoutDoc._type_collection) as any);
@@ -260,6 +269,24 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
};
+ // GPT
+
+ recordDictation = () => {
+ DictationManager.Controls.listen({
+ interimHandler: this.setDictationContent,
+ continuous: { indefinite: false },
+ }).then(results => {
+ if (results && [DictationManager.Controls.Infringed].includes(results)) {
+ DictationManager.Controls.stop();
+ }
+ });
+ };
+ stopDictation = (abort: boolean) => DictationManager.Controls.stop(!abort);
+
+ setDictationContent = (value: string) => {
+ this.setChatInput(value);
+ };
+
@action
customizeWithGPT = async (input: string) => {
// const testInput = 'change title to Customized Slide, transition for 2.3s with fade in effect';
@@ -2714,9 +2741,51 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
{/* presbox chatbox */}
{this.chatActive && (
<div className="presBox-chatbox">
- <input placeholder="Customize..." value={this.chatInput} onChange={e => this.setChatInput(e.target.value)} />
<div style={{ alignSelf: 'flex-end' }}>
<IconButton
+ type={Type.PRIM}
+ color={StrCast(Doc.UserDoc().userVariantColor)}
+ tooltip="Close"
+ icon={<BiX size={'16px'} />}
+ onClick={() => {
+ this.setChatActive(false);
+ }}
+ />
+ </div>
+ <TextareaAutosize
+ minRows={3}
+ placeholder="Customize..."
+ className="pres-chatbox"
+ autoFocus={true}
+ value={this.chatInput}
+ onChange={e => {
+ this.setChatInput(e.target.value);
+ }}
+ onSelect={e => {
+ this.stopDictation(true);
+ }}
+ onKeyDown={e => e.stopPropagation()}
+ onKeyPress={e => e.stopPropagation()}
+ onPointerDown={e => e.stopPropagation()}
+ onClick={e => e.stopPropagation()}
+ onPointerUp={e => e.stopPropagation()}
+ />
+ {/* <input className="chatbox" placeholder="Customize..." value={this.chatInput} onChange={e => this.setChatInput(e.target.value)} /> */}
+ <div style={{ alignSelf: 'flex-end', display: 'flex', gap: '8px' }}>
+ <IconButton
+ type={Type.TERT}
+ color={this.isRecording ? 'red' : StrCast(Doc.UserDoc().userVariantColor)}
+ tooltip="Record"
+ icon={<BiMicrophone size={'16px'} />}
+ onClick={() => {
+ if (!this.isRecording) {
+ this.recordDictation();
+ } else {
+ this.stopDictation(true);
+ }
+ }}
+ />
+ <IconButton
type={Type.TERT}
color={StrCast(Doc.UserDoc().userVariantColor)}
tooltip="Send"