aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/PDFBox.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes/PDFBox.tsx')
-rw-r--r--src/client/views/nodes/PDFBox.tsx88
1 files changed, 64 insertions, 24 deletions
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 4ecbd65b6..34211fa07 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -10,7 +10,7 @@ import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { ComputedField } from '../../../fields/ScriptField';
-import { Cast, FieldValue, NumCast, StrCast, toList } from '../../../fields/Types';
+import { Cast, DocCast, FieldValue, NumCast, StrCast, toList } from '../../../fields/Types';
import { ImageField, PdfField } from '../../../fields/URLField';
import { TraceMobx } from '../../../fields/util';
import { emptyFunction } from '../../../Utils';
@@ -27,13 +27,15 @@ import { Colors } from '../global/globalEnums';
import { PDFViewer } from '../pdf/PDFViewer';
import { PinDocView, PinProps } from '../PinFuncs';
import { SidebarAnnos } from '../SidebarAnnos';
-import { DocumentView } from './DocumentView';
import { FieldView, FieldViewProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
import { ImageBox } from './ImageBox';
import { OpenWhere } from './OpenWhere';
import './PDFBox.scss';
import { CreateImage } from './WebBoxRenderer';
+import { gptAPICall } from '../../apis/gpt/GPT';
+import { List } from '../../../fields/List';
+import { GPTCallType } from '../../apis/gpt/GPT';
@observer
export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@@ -57,6 +59,9 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@observable private _pdf: Opt<Pdfjs.PDFDocumentProxy> = undefined;
@observable private _pageControls = false;
+ @computed get sidebarKey() {
+ return this.fieldKey + '_sidebar';
+ }
@computed get pdfUrl() {
return Cast(this.dataDoc[this._props.fieldKey], PdfField);
}
@@ -77,6 +82,36 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
}
+ autoTag = async () => {
+ if (!this.Document.$tags_chat && this._pdf) {
+ if (!this.dataDoc.text) {
+ // 1) Extract text from the first few pages (e.g., first 2 pages)
+ const maxPages = Math.min(2, this._pdf.numPages);
+ const promises: Promise<string>[] = [];
+ for (let pageNum = 1; pageNum <= maxPages; pageNum++) {
+ promises.push(
+ this._pdf
+ .getPage(pageNum)
+ .then(page => page.getTextContent())
+ .then(content => content.items.map(item => ('str' in item ? item.str : '')).join(' '))
+ );
+ }
+ this.dataDoc.text = (await Promise.all(promises)).join(' ');
+ }
+
+ const text = StrCast(this.dataDoc.text).trim().slice(0, 2000);
+ if (text) {
+ // 2) Ask GPT to classify and provide descriptive tags, then normalize the results
+ const label = await gptAPICall(`"${text}"`, GPTCallType.CLASSIFYTEXTFULL).then(raw => raw.trim().toUpperCase());
+
+ this.Document.$tags_chat = new List<string>(label.split(/\s+/));
+
+ // 4) Show tags in layout
+ this.Document._layout_showTags = true;
+ }
+ }
+ };
+
replaceCanvases = (oldDiv: HTMLElement, newDiv: HTMLElement) => {
if (oldDiv.childNodes) {
for (let i = 0; i < oldDiv.childNodes.length; i++) {
@@ -233,14 +268,11 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return this._pdfViewer?.scrollFocus(anchor, NumCast(anchor.y, NumCast(anchor.config_scrollTop)), options);
};
- getView = (doc: Doc, options: FocusViewOptions) => {
- if (this._sidebarRef?.current?.makeDocUnfiltered(doc) && !this.SidebarShown) {
- options.didMove = true;
- this.toggleSidebar(false);
+ getView = async (doc: Doc, options: FocusViewOptions) => {
+ if (DocListCast(this.dataDoc[this.sidebarKey]).find(anno => Doc.AreProtosEqual(doc.layout_unrendered ? DocCast(doc.annotationOn) : doc, anno))) {
+ SidebarAnnos.getView(this._sidebarRef.current, this.SidebarShown, () => this.toggleSidebar(false), doc, options);
}
- return new Promise<Opt<DocumentView>>(res => {
- DocumentView.addViewRenderedCb(doc, dv => res(dv));
- });
+ return undefined;
};
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
@@ -406,7 +438,15 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
onKeyDown={e => ([KeyCodes.BACKSPACE, KeyCodes.DELETE].includes(e.keyCode) ? e.stopPropagation() : true)}
onPointerDown={e => e.stopPropagation()}
style={{ display: this._props.isContentActive() ? 'flex' : 'none' }}>
- <div className="pdfBox-overlayCont" onPointerDown={e => e.stopPropagation()} style={{ left: `${this._searching ? 0 : 100}%` }}>
+ <div
+ className="pdfBox-overlayCont"
+ onPointerDown={e => e.stopPropagation()}
+ style={{
+ transformOrigin: 'bottom left',
+ transform: `scale(${this._props.DocumentView?.().UIBtnScaling || 1})`,
+ width: `${100 / (this._props.DocumentView?.().UIBtnScaling || 1)}%`,
+ left: `${this._searching ? 0 : 100}%`,
+ }}>
<button type="button" className="pdfBox-overlayButton" title={searchTitle} />
<input
className="pdfBox-searchBar"
@@ -435,17 +475,25 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
type="button"
className="pdfBox-overlayButton"
title={searchTitle}
+ style={{
+ transformOrigin: 'bottom right',
+ transform: `scale(${this._props.DocumentView?.().UIBtnScaling || 1})`,
+ }}
onClick={action(() => {
this._searching = !this._searching;
this.search('', true, true);
})}>
- <div className="pdfBox-overlayButton-arrow" onPointerDown={e => e.stopPropagation()} />
<div className="pdfBox-overlayButton-iconCont" onPointerDown={e => e.stopPropagation()}>
<FontAwesomeIcon icon={this._searching ? 'times' : 'search'} size="lg" />
</div>
</button>
- <div className="pdfBox-pageNums">
+ <div
+ className="pdfBox-pageNums"
+ style={{
+ transformOrigin: 'top left',
+ transform: `scale(${this._props.DocumentView?.().UIBtnScaling || 1})`,
+ }}>
<input
value={curPage}
style={{ width: `${curPage > 99 ? 4 : 3}ch`, pointerEvents: 'all' }}
@@ -649,19 +697,11 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const pdfView = !this._pdf ? null : this.renderPdfView;
const href = this.pdfUrl?.url.href;
if (!pdfView && href) {
- if (PDFBox.pdfcache.get(href))
- setTimeout(
- action(() => {
- this._pdf = PDFBox.pdfcache.get(href);
- })
- );
+ if (PDFBox.pdfcache.get(href)) setTimeout(action(() => (this._pdf = PDFBox.pdfcache.get(href))));
else {
- if (!PDFBox.pdfpromise.get(href)) PDFBox.pdfpromise.set(href, Pdfjs.getDocument(href).promise);
- PDFBox.pdfpromise.get(href)?.then(
- action(pdf => {
- PDFBox.pdfcache.set(href, (this._pdf = pdf));
- })
- );
+ const pdfPromise = PDFBox.pdfpromise.get(href) ?? Pdfjs.getDocument(href).promise;
+ PDFBox.pdfpromise.set(href, pdfPromise);
+ pdfPromise.then(action(pdf => PDFBox.pdfcache.set(href, (this._pdf = pdf))));
}
}
return pdfView ?? this.renderTitleBox;