-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtxtEditor.jsx
428 lines (388 loc) · 15.4 KB
/
txtEditor.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
//DESC: This is the rich text editor and the chatbot
import ExampleTheme from "./themes/themeEditor";
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import React, {useEffect, useState} from "react";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
import TreeViewPlugin from "./plugins/TreeViewPlugin";
import ToolbarPlugin from "./plugins/ToolbarPlugin";
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { TableCellNode, TableNode, TableRowNode } from "@lexical/table";
import { ListItemNode, ListNode } from "@lexical/list";
import { CodeHighlightNode, CodeNode } from "@lexical/code";
import { AutoLinkNode, LinkNode } from "@lexical/link";
import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
import { ListPlugin } from "@lexical/react/LexicalListPlugin";
import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
import { TRANSFORMERS } from "@lexical/markdown";
import { useRef } from "react";
import ListMaxIndentLevelPlugin from "./plugins/ListMaxIndentLevelPlugin";
import CodeHighlightPlugin from "./plugins/CodeHighlightPlugin";
import AutoLinkPlugin from "./plugins/AutoLinkPlugin";
import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
import StateUpdater from "./plugins/htmlPlugin"
import { getFunctions, httpsCallable } from "firebase/functions";
import {app,storage} from "../../../firebase"
import { getDownloadURL, ref} from 'firebase/storage';
import 'firebase/functions';
//GPT
import ChatMessage from "../chatMessage"
export default function Editor({setData,setContent,audioUrl,passTranscription,isSubscribed}) {
const [initialEditorState, setInitialEditorState] = useState(null)
const loadContent = async () => {
// 'empty' editor
const value = '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}';
return value;
}
useEffect(() => {
const initialEditorState = loadContent();
setInitialEditorState(initialEditorState)
},[])
const editorConfig = {
// The editor theme
theme: ExampleTheme,
editorState: initialEditorState,
// Handling of errors during update
onError(error) {
throw error;
},
// Any custom nodes go here
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
CodeHighlightNode,
TableNode,
TableCellNode,
TableRowNode,
AutoLinkNode,
LinkNode
]
};
const functions = getFunctions(app);
//GPT
const [aiTxt,setAiTxt] = useState("")//INPUT
const [chatLog,setChatLog] = useState([])
const [questionLoading, setQuestionLoading] = useState(false)
const [isFirstQuestion,setIsFirstQuestion] = useState(true)
const [isAiActive,setIsAiActive] = useState(false)
//ANALYZE SCIPT
const [isScriptLoading, setIsScriptLoading] = useState(false)
const [isScriptLoaded, setIsScriptLoaded] = useState(false)
const [transcriptScript,setTranscriptScript] = useState("")
const [summerisingIsLoading,setSummerisingIsLoading] = useState(false)
const handleInputChange = (e) => {
const userInput = e.target.value;
setAiTxt(userInput);
};
const handleEnterPress = (e) => {
if (e.key === 'Enter') {
if(questionLoading == false){
// Do something when Enter is pressed, e.g., trigger a function or submit a form
e.preventDefault();
setQuestionLoading(true)
setIsScriptLoaded(false)
const generateTextFromPrompt = async (request) => {
const generateTextFunction = httpsCallable(functions, 'openAIHttpFunctionSec');
if(transcriptScript != "" && isSubscribed == true){
const userQuestionShow = "[ SCRIPT ANALISYS ] " + aiTxt
let chatLogNew = [...chatLog, {user: "me", message: `${userQuestionShow}`} ]
try {
console.log(request)
const result = await generateTextFunction({name: request});
//SETT LOADING FALSE
setQuestionLoading(false)
setChatLog([...chatLogNew, {user: "gpt", message: `${result.data.data.choices[0].message.content}`}])
} catch (error) {
console.error('Firebase function invocation failed:', error);
}
}else if(transcriptScript == "" && isSubscribed == false){
const userQuestionShow = aiTxt
let chatLogNew = [...chatLog, {user: "me", message: `${userQuestionShow}`} ]
try {
console.log(request)
const result = await generateTextFunction({name: request});
//SETT LOADING FALSE
setQuestionLoading(false)
setChatLog([...chatLogNew, {user: "gpt", message: `${result.data.data.choices[0].message.content}`}])
} catch (error) {
console.error('Firebase function invocation failed:', error);
}
}else{
alert("Something went wrong. Please Refresh the page !")
}
};
if(transcriptScript != "" && isSubscribed == true){
//QUESTION WITH TRANSCRIPT
const question = "( " + transcriptScript + " )" + "this is a video script," + " " + aiTxt;
//SETT CHATLOG WITH THE MESSAGE
const userQuestionShow = "[ SCRIPT ANALISYS ] " + aiTxt
let chatLogNew = [...chatLog, {user: "me", message: `${userQuestionShow}`} ];
//SETT GPT LOADING
setChatLog([...chatLogNew, {user: "gpt", message: "Answering..."}]);
//FINSIH QUESTION
console.log('question:', question);
//FUNCTION EVENT
generateTextFromPrompt(question)
}else if (transcriptScript == "") {
const question = aiTxt;
let chatLogNew = [...chatLog, {user: "me", message: `${question}`} ];
//Loading GPT
setChatLog([...chatLogNew, {user: "gpt", message: "Answering..."}]);
//FINSIH QUESTION
console.log('question:', question);
//FUNCTION EVENT
generateTextFromPrompt(question);
} else if (transcriptScript != "" && isSubscribed == false){
alert("Please Upgrade to Premium to use this feature")
}
//FIRST QUESTION LOGIC
setIsFirstQuestion(false)
//BACK TO DEFAULTS
setAiTxt("")
setTranscriptScript("")
} else{
alert("Wait for the answer !")
}
}
};
const handleScriptLoading = async () =>{
setIsScriptLoading(true)
try{
const audioMetaName = `${audioUrl + ".wav_transcription.txt"}`
const transRef = ref(storage,audioMetaName)
const transcription = await getDownloadURL(transRef)
console.log(transcription)
fetch(transcription)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json(); // Parse the response as JSON
})
.then(data => {
const querySnaphot = data.results // This will log the JSON data
const userFolders = [];
querySnaphot.forEach((doc) => {
// Extract folder data and add it to the userFolders array
userFolders.push(doc.alternatives[0].transcript);
});
console.log(userFolders)
const concatenatedText = userFolders.map(doc => doc).join(' ');
console.log(concatenatedText)
passTranscription(concatenatedText);
setTranscriptScript(concatenatedText)
// You can now work with the JSON data as needed
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
setIsScriptLoading(false)
setIsScriptLoaded(true)
} catch (error) {
console.log('Firebase Storage error code:', error.code); // Add this line for debugging
if ('storage/object-not-found' === error.code) {
alert('Sorry, The Added Video is too Fresh, Try Again in 3 minutes ');
} else {
console.error('Firebase function invocation failed:', error);
}
setIsScriptLoading(false);
}
}
const editorStateRef = useRef();
const handleScriptLoaded = async () => {
setTranscriptScript("")
setIsScriptLoaded(false)
console.log("undo")
};
const handleSummerising = async () =>{
if(isSubscribed == true){
setSummerisingIsLoading(true)
setQuestionLoading(true)
const audioMetaName = `${audioUrl + ".wav_transcription.txt"}`
const transRef = ref(storage,audioMetaName)
const transcription = await getDownloadURL(transRef)
try{
fetch(transcription)
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json(); // Parse the response as JSON
})
.then(data => {
const querySnaphot = data.results // This will log the JSON data
const userFolders = [];
querySnaphot.forEach((doc) => {
// Extract folder data and add it to the userFolders array
userFolders.push(doc.alternatives[0].transcript);
});
console.log(userFolders)
const concatenatedText = userFolders.map(doc => doc).join(' ');
console.log(concatenatedText)
passTranscription(concatenatedText);
const question = "( " + concatenatedText + " )" + " summerise this video script";
const userQuestionShow = "[ SUMMERY IN PROCESS ] "
//SETT CHATLOG WITH THE MESSAGE
let chatLogNew = [...chatLog, {user: "me", message: `${userQuestionShow}`} ];
setChatLog([...chatLogNew, {user: "gpt", message: "Answering..."}]);
const generateTextFromPrompt = async (request) => {
const generateTextFunction = httpsCallable(functions, 'openAIHttpFunctionSec');
const userQuestionShow = "[ SUMMERY IN PROCESS ] "
let chatLogNew = [...chatLog, {user: "me", message: `${userQuestionShow}`} ]
try {
console.log(request)
const result = await generateTextFunction({name: request});
//SETT LOADING FALSE
setChatLog([...chatLogNew, {user: "gpt", message: `${result.data.data.choices[0].message.content}`}])
setSummerisingIsLoading(false)
setQuestionLoading(false)
} catch (error) {
console.error('Firebase function invocation failed:', error);
}
};
generateTextFromPrompt(question);
setIsFirstQuestion(false)
setTranscriptScript("")
// You can now work with the JSON data as needed
})
.catch(error => {
console.error('There was a problem with the fetch operation:', error);
});
} catch (error) {
console.error('Firebase function invocation failed:', error);
}
}else if (isSubscribed == false){
alert("Please Upgrade to Premium to use this feature")
}
}
return (
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
<ToolbarPlugin isActive={setIsAiActive} />
{!isAiActive ? (
<div className={`editor-inner ${!isFirstQuestion ? 'active' : ''}`}>
<RichTextPlugin
contentEditable={
<ContentEditable className="editor-input" />
}
ErrorBoundary={LexicalErrorBoundary}
/>
<OnChangePlugin onChange={editorState => editorStateRef.current = editorState} />
<OnChangePlugin onChange={() => {
if (editorStateRef.current) {
setContent(JSON.stringify(editorStateRef.current))
}
}}/>
<StateUpdater initialHtml={`${setData}`} />
<HistoryPlugin />
<TreeViewPlugin />
<AutoFocusPlugin />
<CodeHighlightPlugin />
<ListPlugin />
<LinkPlugin />
<AutoLinkPlugin />
<ListMaxIndentLevelPlugin maxDepth={7} />
<MarkdownShortcutPlugin transformers={TRANSFORMERS} />
</div>
) :
<div className={`editor-inner ${!isFirstQuestion ? 'active' : ''}`}>
{isFirstQuestion ? (
<div className="ai-input-cont">
<h1 className="ai_title">Use Clippify Ai</h1>
<div className="feature-boxes">
{ !isScriptLoaded?(
!isScriptLoading? (
<div className="feature_1" onClick={handleScriptLoading}>
<h2>Analyze the Script</h2>
<h5>Ask your question if it's highlighted</h5>
</div>):(
<div className="feature_1">
<h2>Scipt Loading</h2>
<h5>It may take some times...</h5>
</div>
)
):(
<div className="feature_1" style={{borderColor:"aquamarine"}} onClick={handleScriptLoaded}>
<h2>Scipt is Ready</h2>
<h5>Ask Anyithing I Click to Undo</h5>
</div>
)}
{!summerisingIsLoading?(
<div className="feature_2" onClick={handleSummerising}>
<h2>Summarise the video</h2>
<h5>However you want</h5>
</div>):(
<div className="feature_2" style={{borderColor:"aquamarine"}} onClick={handleSummerising}>
<h2>Processing</h2>
<h5>It may take some times</h5>
</div>
)}
</div>
{!isScriptLoaded ? (
<input type="text" value={aiTxt} className="ai-input" placeholder="Ask me anything" onChange={handleInputChange} onKeyPress={handleEnterPress}/>
):(
<input type="text" value={aiTxt} className="ai-input" placeholder="The Video Script is Loaded" onChange={handleInputChange} onKeyPress={handleEnterPress}/>
)
}
</div>
) : (
<>
<div className="editor-inner2">
<div className="chat-cont">
<h1 className="chat-log-title">Chat Log</h1>
<hr className="chat-log-hr"/>
{chatLog.map((message,index) => (
<ChatMessage key={index} message={message}/>
))}
</div>
</div>
<div className="input_bar_2_stage">
<div className="feature-boxes">
{ !isScriptLoaded?(
!isScriptLoading? (
<div className="feature_1" onClick={handleScriptLoading}>
<h2>Analyze the Script</h2>
<h5>If it's green you can ask your question</h5>
</div>):(
<div className="feature_1">
<h2>Scipt Loading</h2>
<h5>It may take some times...</h5>
</div>
)
):(
<div className="feature_1" style={{borderColor:"aquamarine"}} onClick={handleScriptLoaded}>
<h2>Scipt is Ready</h2>
<h5>Click to Undo</h5>
</div>
)}
{!summerisingIsLoading?(
<div className="feature_2" onClick={handleSummerising}>
<h2>Summarise the video</h2>
<h5>However you want</h5>
</div>):(
<div className="feature_2" style={{borderColor:"aquamarine"}} onClick={handleSummerising}>
<h2>Processing</h2>
<h5>It may take some times</h5>
</div>
)}
</div>
{!isScriptLoaded ? (
<input type="text" value={aiTxt} className="ai-input" placeholder="Ask me anything" onChange={handleInputChange} onKeyPress={handleEnterPress}/>
):(
<input type="text" value={aiTxt} className="ai-input" placeholder="The Video Script is Loaded" onChange={handleInputChange} onKeyPress={handleEnterPress}/>
)
}
</div>
</>
)}
</div>}
</div>
</LexicalComposer>
);
}