aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/pdf/PDFViewer.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/pdf/PDFViewer.tsx')
-rw-r--r--src/client/views/pdf/PDFViewer.tsx169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index dee0edfae..02d310f7d 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -28,6 +28,12 @@ import { AnchorMenu } from './AnchorMenu';
import { Annotation } from './Annotation';
import { GPTPopup } from './GPTPopup/GPTPopup';
import './PDFViewer.scss';
+import { GPTCallType, gptAPICall } from '../../apis/gpt/GPT';
+import ReactLoading from 'react-loading';
+// import html2canvas from 'html2canvas';
+// import SpeechRecognition, { useSpeechRecognition } from 'react-speech-recognition';
+
+// pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`;
// The workerSrc property shall be specified.
// Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.4.168/build/pdf.worker.mjs';
@@ -58,12 +64,50 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
super(props);
makeObservable(this);
}
+ // @observable transcriptRef = React.createRef();
+ // @observable startBtnRef = React.createRef();
+ // @observable stopBtnRef = React.createRef();
+ // @observable transcriptElement = '';
+
+ // handleResult = (e: SpeechRecognitionEvent) => {
+ // let interimTranscript = '';
+ // let finalTranscript = '';
+ // console.log('H');
+ // for (let i = e.resultIndex; i < e.results.length; i++) {
+ // const transcript = e.results[i][0].transcript;
+ // if (e.results[i].isFinal) {
+ // finalTranscript += transcript;
+ // } else {
+ // interimTranscript += transcript;
+ // }
+ // }
+ // console.log(interimTranscript);
+ // this.transcriptElement = finalTranscript || interimTranscript;
+ // };
+
+ // startListening = () => {
+ // const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
+ // if (SpeechRecognition) {
+ // console.log('here');
+ // const recognition = new SpeechRecognition();
+ // recognition.continuous = true; // Continue listening even if the user pauses
+ // recognition.interimResults = true; // Show interim results
+ // recognition.lang = 'en-US'; // Set language (optional)
+ // recognition.onresult = this.handleResult.bind(this);
+ // // recognition.onend = this.handleEnd.bind(this);
+
+ // recognition.start();
+ // // this.handleResult;
+ // // recognition.stop();
+ // }
+ // };
@observable _pageSizes: { width: number; height: number }[] = [];
@observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>();
@observable _textSelecting = true;
@observable _showWaiting = true;
@observable Index: number = -1;
+ @observable private _loading = false;
private _pdfViewer!: PDFJSViewer.PDFViewer;
private _styleRule: number | undefined; // stylesheet rule for making hyperlinks clickable
@@ -394,6 +438,122 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
}
};
+ gptPDFFlashcards = async () => {
+ // const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
+ // if (SpeechRecognition) {
+ // this.recognition = new SpeechRecognition();
+ // this.recognition.continuous = true; // Continue listening even if the user pauses
+ // this.recognition.interimResults = true; // Show interim results
+ // this.recognition.lang = 'en-US'; // Set language (optional)
+
+ // this.recognition.onresult = this.handleResult;
+ // this.recognition.onerror = this.handleError;
+ // this.recognition.onend = this.handleEnd;
+ // } else {
+ // console.error("Browser doesn't support Speech Recognition API");
+ // }
+ // const Dictaphone = () => {
+ // const { transcript, resetTranscript } = useSpeechRecognition();
+
+ // if (!SpeechRecognition.browserSupportsSpeechRecognition()) {
+ // return null;
+ // }
+
+ // return (
+ // <div>
+ // <button onClick={e => SpeechRecognition.startListening}>Start</button>
+ // <button onClick={e => SpeechRecognition.stopListening}>Stop</button>
+ // <button onClick={resetTranscript}>Reset</button>
+ // <p>{transcript}</p>
+ // </div>
+ // );
+ // };
+ // const grammar =
+ // '#JSGF V1.0; grammar colors; public <color> = aqua | azure | beige | bisque | black | blue | brown | chocolate | coral | crimson | cyan | fuchsia | ghostwhite | gold | goldenrod | gray | green | indigo | ivory | khaki | lavender | lime | linen | magenta | maroon | moccasin | navy | olive | orange | orchid | peru | pink | plum | purple | red | salmon | sienna | silver | snow | tan | teal | thistle | tomato | turquoise | violet | white | yellow ;';
+ // const recognition = new SpeechRecognition();
+ // const speechRecognitionList = new SpeechGrammarList();
+ // speechRecognitionList.addFromString(grammar, 1);
+ // recognition.grammars = speechRecognitionList;
+ // recognition.continuous = false;
+ // recognition.lang = 'en-US';
+ // recognition.interimResults = false;
+ // recognition.maxAlternatives = 1;
+
+ // const diagnostic = document.querySelector('.output');
+ // const bg = document.querySelector('html');
+
+ // document.body.onclick = () => {
+ // recognition.start();
+ // console.log('Ready to receive a color command.');
+ // };
+
+ // recognition.onresult = event => {
+ // const color = event.results[0][0].transcript;
+ // diagnostic!.textContent = `Result received: ${color}`;
+ // bg!.style.backgroundColor = color;
+ // };
+
+ //const SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
+
+ // recognition.continous = true;
+ // recognition.interimResults = true;
+ // recognition.lang = 'en-US';
+
+ const queryText = this._selectionText;
+
+ // const canvas = await html2canvas();
+ // const image = canvas.toDataURL("image/png", 1.0);
+ // (window as any)
+ // .html2canvas(this._marqueeref, {
+ // x: 100,
+ // y: 100,
+ // width: 100,
+ // height: 100,
+ // })
+ // .then((canvas: HTMLCanvasElement) => {
+ // const img = canvas.toDataURL('image/png');
+
+ // const link = document.createElement('a');
+ // link.href = img;
+ // link.download = 'screenshot.png';
+
+ // document.body.appendChild(link);
+ // link.click();
+ // link.remove();
+ // });
+
+ // var range = window.getSelection()?.getRangeAt(0);
+ // var selectionContents = range?.extractContents();
+ // var div = document.createElement("div");
+ // div.style.color = "yellow";
+ // div.appendChild(selectionContents!);
+ // range!.insertNode(div);
+
+ // const canvas = document.createElement('canvas');
+ // const scaling = 1 / (this._props.NativeDimScaling?.() || 1);
+ // const w = AnchorMenu.Instance.marqueeWidth * scaling;
+ // const h = AnchorMenu.Instance.marqueeHeight * scaling;
+ // canvas.width = w;
+ // canvas.height = h;
+ // const ctx = canvas.getContext('2d'); // draw image to canvas. scale to target dimensions
+ // if (ctx) {
+ // this._marqueeref && ctx.drawImage(div, NumCast(this._marqueeref.current?.left) * scaling, NumCast(this._marqueeref.current?.top) * scaling, w, h, 0, 0, w, h);
+ // }
+ this._loading = true;
+ try {
+ if (this._selectionText === '') {
+ }
+ const res = await gptAPICall(queryText, GPTCallType.FLASHCARD);
+
+ console.log(res);
+ AnchorMenu.Instance.transferToFlashcard(res || 'Something went wrong', NumCast(this._props.layoutDoc['x']), NumCast(this._props.layoutDoc['y']));
+ this._selectionText = '';
+ } catch (err) {
+ console.error(err);
+ }
+ this._loading = false;
+ };
+
@action
finishMarquee = (/* x?: number, y?: number */) => {
this._getAnchor = AnchorMenu.Instance?.GetAnchor;
@@ -411,8 +571,10 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
document.removeEventListener('pointerup', this.onSelectEnd);
const sel = window.getSelection();
+
if (sel) {
AnchorMenu.Instance.setSelectedText(sel.toString());
+ AnchorMenu.Instance.setLocation(NumCast(this._props.layoutDoc['x']), NumCast(this._props.layoutDoc['y']));
}
if (sel?.type === 'Range') {
@@ -424,6 +586,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
GPTPopup.Instance.addDoc = this._props.sidebarAddDoc;
// allows for creating collection
AnchorMenu.Instance.addToCollection = this._props.DocumentView?.()._props.addDocument;
+ AnchorMenu.Instance.gptFlashcards = this.gptPDFFlashcards;
};
@action
@@ -451,6 +614,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
this._mainCont.current!.style.transform = '';
}
this._selectionContent = selRange.cloneContents();
+
this._selectionText = this._selectionContent?.textContent || '';
// clear selection
@@ -612,6 +776,11 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
/>
)}
</div>
+ {this._loading ? (
+ <div className="loading-spinner" style={{ position: 'absolute' }}>
+ <ReactLoading type="spin" height={80} width={80} color={'blue'} />
+ </div>
+ ) : null}
</div>
);
}