aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
diff options
context:
space:
mode:
authorA.J. Shulman <Shulman.aj@gmail.com>2025-05-12 15:46:30 -0400
committerA.J. Shulman <Shulman.aj@gmail.com>2025-05-12 15:46:30 -0400
commitb3aa238043d01cbc58293b45867706fa9b36cefe (patch)
tree770f07542f97e4bda2c56e00ef8118688e32fce9 /src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
parent0a6f3fc649b37e273a501302c1dd645a5e9a18ac (diff)
workign better
Diffstat (limited to 'src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx')
-rw-r--r--src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx143
1 files changed, 138 insertions, 5 deletions
diff --git a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
index 00077d68d..af689f243 100644
--- a/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
+++ b/src/client/views/nodes/chatbot/chatboxcomponents/ChatBox.tsx
@@ -15,7 +15,7 @@ import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';
import { ClientUtils, OmitKeys } from '../../../../../ClientUtils';
import { Doc, DocListCast, Opt } from '../../../../../fields/Doc';
-import { DocData, DocViews } from '../../../../../fields/DocSymbols';
+import { DocData, DocLayout, DocViews } from '../../../../../fields/DocSymbols';
import { RichTextField } from '../../../../../fields/RichTextField';
import { ScriptField } from '../../../../../fields/ScriptField';
import { CsvCast, DocCast, NumCast, PDFCast, RTFCast, StrCast, VideoCast, AudioCast } from '../../../../../fields/Types';
@@ -644,6 +644,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// Get the simplified chunk using the document manager
const { foundChunk, doc } = this.docManager.getSimplifiedChunkById(chunkId);
+ console.log('doc: ', doc);
if (!foundChunk) {
if (doc) {
console.warn(`Chunk not found in document, ${doc.id}, for chunk ID: ${chunkId}`);
@@ -665,12 +666,14 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
console.error('No direct matching segment found for the citation.');
}
} else if (foundChunk.chunkType === CHUNK_TYPE.TABLE || foundChunk.chunkType === CHUNK_TYPE.IMAGE) {
- this.handleOtherChunkTypes(foundChunk, citation, doc);
+ console.log('here: ', foundChunk);
+ this.handleOtherChunkTypes(foundChunk as SimplifiedChunk, citation, doc);
} else {
if (doc.type === 'web') {
DocumentManager.Instance.showDocument(doc, { openLocation: OpenWhere.addRight }, () => {});
return;
}
+ this.handleOtherChunkTypes(foundChunk, citation, doc);
// Show the chunk text in citation popup
let chunkText = citation.direct_text || 'Text content not available';
this.showCitationPopup(chunkText);
@@ -834,10 +837,45 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._citationPopup = { text: citation.direct_text ?? 'No text available', visible: true };
this.startCitationPopupTimer();
+ // Check if the document is a PDF (has a PDF viewer component)
+ const isPDF = PDFCast(doc.data) !== null || doc.type === DocumentType.PDF;
+
DocumentManager.Instance.showDocument(doc, { willZoomCentered: true }, () => {
- const firstView = Array.from(doc[DocViews])[0] as DocumentView;
- (firstView.ComponentView as PDFBox)?.gotoPage?.(foundChunk.startPage ?? 0);
- (firstView.ComponentView as PDFBox)?.search?.(citation.direct_text ?? '');
+ // Add a delay to ensure document is fully loaded and rendered
+ setTimeout(() => {
+ try {
+ // Safety check: ensure the document has views
+ if (!doc[DocViews] || doc[DocViews].size === 0) {
+ console.warn('Document views not available yet, retrying...');
+ this.retryPdfSearch(doc, citation, foundChunk, isPDF, 1);
+ return;
+ }
+
+ const views = Array.from(doc[DocViews]);
+ if (!views.length) {
+ console.warn('No document views found, retrying...');
+ this.retryPdfSearch(doc, citation, foundChunk, isPDF, 1);
+ return;
+ }
+
+ const firstView = views[0] as DocumentView;
+ if (!firstView || !firstView.ComponentView) {
+ console.warn('Component view not available yet, retrying...');
+ this.retryPdfSearch(doc, citation, foundChunk, isPDF, 1);
+ return;
+ }
+
+ const pdfComponent = firstView.ComponentView as PDFBox;
+ if (isPDF && pdfComponent && citation.direct_text) {
+ // Use our helper to ensure fuzzy search is enabled and execute the search
+ this.ensureFuzzySearchAndExecute(pdfComponent, citation.direct_text.trim(), foundChunk.startPage);
+ }
+ } catch (error) {
+ console.error('Error accessing PDF component:', error);
+ // Retry with exponential backoff
+ this.retryPdfSearch(doc, citation, foundChunk, isPDF, 1);
+ }
+ }, 500); // Initial delay before first attempt
});
break;
case CHUNK_TYPE.CSV:
@@ -851,6 +889,7 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
break;
}
};
+
/**
* Creates an annotation highlight on a PDF document for image citations.
* @param x1 X-coordinate of the top-left corner of the highlight.
@@ -1092,6 +1131,100 @@ export class ChatBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
/**
+ * Retry PDF search with exponential backoff
+ */
+ retryPdfSearch = (doc: Doc, citation: Citation, foundChunk: SimplifiedChunk, isPDF: boolean, attempt: number) => {
+ if (attempt > 5) {
+ console.error('Maximum retry attempts reached for PDF search');
+ return;
+ }
+
+ const delay = Math.min(2000, 500 * Math.pow(1.5, attempt)); // Exponential backoff with max delay of 2 seconds
+
+ setTimeout(() => {
+ try {
+ if (!doc[DocViews] || doc[DocViews].size === 0) {
+ this.retryPdfSearch(doc, citation, foundChunk, isPDF, attempt + 1);
+ return;
+ }
+
+ const views = Array.from(doc[DocViews]);
+ if (!views.length) {
+ this.retryPdfSearch(doc, citation, foundChunk, isPDF, attempt + 1);
+ return;
+ }
+
+ const firstView = views[0] as DocumentView;
+ if (!firstView || !firstView.ComponentView) {
+ this.retryPdfSearch(doc, citation, foundChunk, isPDF, attempt + 1);
+ return;
+ }
+
+ const pdfComponent = firstView.ComponentView as PDFBox;
+ if (isPDF && pdfComponent && citation.direct_text) {
+ console.log(`PDF component found on attempt ${attempt}, executing search...`);
+ this.ensureFuzzySearchAndExecute(pdfComponent, citation.direct_text.trim(), foundChunk.startPage);
+ }
+ } catch (error) {
+ console.error(`Error on retry attempt ${attempt}:`, error);
+ this.retryPdfSearch(doc, citation, foundChunk, isPDF, attempt + 1);
+ }
+ }, delay);
+ };
+
+ /**
+ * Ensures fuzzy search is enabled in PDFBox and performs a search
+ * @param pdfComponent The PDFBox component
+ * @param searchText The text to search for
+ * @param startPage Optional page to navigate to before searching
+ */
+ private ensureFuzzySearchAndExecute = (pdfComponent: PDFBox, searchText: string, startPage?: number) => {
+ if (!pdfComponent) {
+ console.warn('PDF component is undefined, cannot perform search');
+ return;
+ }
+
+ if (!searchText?.trim()) {
+ console.warn('Search text is empty, skipping search');
+ return;
+ }
+
+ try {
+ // Check if the component has required methods
+ if (typeof pdfComponent.gotoPage !== 'function' || typeof pdfComponent.toggleFuzzySearch !== 'function' || typeof pdfComponent.search !== 'function') {
+ console.warn('PDF component missing required methods');
+ return;
+ }
+
+ // Navigate to the page if specified
+ if (typeof startPage === 'number') {
+ pdfComponent.gotoPage(startPage + 1);
+ }
+
+ // Always try to enable fuzzy search
+ try {
+ // PDFBox.tsx toggles fuzzy search state internally
+ // We'll call it once to make sure it's enabled
+ pdfComponent.toggleFuzzySearch();
+ } catch (toggleError) {
+ console.warn('Error toggling fuzzy search:', toggleError);
+ }
+
+ // Add a sufficient delay to ensure PDF is fully loaded before searching
+ setTimeout(() => {
+ try {
+ console.log('Performing fuzzy search for text:', searchText);
+ pdfComponent.search(searchText);
+ } catch (searchError) {
+ console.error('Error performing search:', searchError);
+ }
+ }, 1000); // Increased delay for better reliability
+ } catch (error) {
+ console.error('Error in fuzzy search setup:', error);
+ }
+ };
+
+ /**
* Main render method for the ChatBox
*/
render() {